Skip to content

Commit

Permalink
feat: first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
fjc0k committed Oct 9, 2018
0 parents commit 6c5e7c7
Show file tree
Hide file tree
Showing 18 changed files with 9,386 additions and 0 deletions.
22 changes: 22 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# http://editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

# The JSON files contain newlines inconsistently
[*.json]
insert_final_newline = ignore

# Minified JavaScript files shouldn't be changed
[**.min.js]
indent_style = ignore
insert_final_newline = ignore

[*.md]
trim_trailing_whitespace = false
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.log
node_modules
.vscode
*.stackdump
.rpt2_cache
coverage
12 changes: 12 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
language: node_js
node_js:
- 9
cache:
directories:
- node_modules
install:
- yarn
script:
- yarn test
after_success:
- yarn codecov
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# vtils <a href="https://travis-ci.org/fjc0k/vtils"><img src="https://travis-ci.org/fjc0k/vtils.svg?branch=master" alt="Build Status"></a> <a href="https://codecov.io/gh/fjc0k/vtils"><img src="https://codecov.io/gh/fjc0k/vtils/branch/master/graph/badge.svg" alt="Coverage Status"></a>

一些常用的 JavaScript 工具库。
11 changes: 11 additions & 0 deletions bdr.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
entry: {
'vtils': ['src/index.ts', 'vtils']
},
format: 'es,cjs,umd,umd-min',
typescript: require('typescript'),
external: {
vue: 'Vue'
},
clear: false
}
68 changes: 68 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{
"name": "vtils",
"version": "0.0.1",
"description": "一些常用的 JavaScript 工具库。",
"main": "dist/vtils.cjs.js",
"module": "dist/vtils.es.js",
"unpkg": "dist/vtils.min.js",
"jsdelivr": "dist/vtils.min.js",
"types": "dist/index.d.ts",
"homepage": "https://github.com/fjc0k/vtils",
"license": "MIT",
"sideEffects": false,
"repository": {
"type": "git",
"url": "[email protected]:fjc0k/vtils.git"
},
"bugs": {
"url": "https://github.com/fjc0k/vtils/issues"
},
"keywords": [
"utils"
],
"files": [
"dist"
],
"author": {
"name": "Jay Fong",
"email": "[email protected]",
"url": "https://github.com/fjc0k"
},
"scripts": {
"test": "jest --coverage",
"build": "tsc --emitDeclarationOnly & bdr build",
"release": "standard-version -a",
"postrelease": "git push --follow-tags origin master && npm publish"
},
"standard-version": {
"scripts": {
"postbump": "yarn build && git add -A"
}
},
"jest": {
"transform": {
"^.+\\.ts$": "ts-jest"
},
"collectCoverageFrom": [
"<rootDir>/src/**/*.ts"
],
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
"moduleFileExtensions": [
"ts",
"js",
"json"
]
},
"devDependencies": {
"@types/jest": "^23.3.4",
"@types/sinon": "^5.0.5",
"bdr": "^1.6.1",
"codecov": "^3.1.0",
"jest": "^23.6.0",
"sinon": "^6.3.5",
"standard-version": "^4.4.0",
"ts-jest": "^23.10.4",
"tslint": "^5.11.0",
"typescript": "^3.1.1"
}
}
48 changes: 48 additions & 0 deletions src/Disposer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
export type DisposerItemName = string | number

export type Dispose = () => void

/**
* 处置器。
*/
export default class Disposer {
/**
* 待处置项目存放容器。
*
* @private
*/
private jar: { [name: string]: Dispose[] } = Object.create(null)

/**
* 将待处置项目加入容器。
*
* @param name 待处置项目名称
* @param dispose 处置行为
*/
public add(name: DisposerItemName, dispose: Dispose | Dispose[]): void {
dispose = Array.isArray(dispose) ? dispose : [dispose]
this.jar[name] = [
...(this.jar[name] || []),
...dispose
]
}

/**
* 处置项目。
*
* @param name 欲处置项目名称
*/
public dispose(name: DisposerItemName): void {
(this.jar[name] || []).forEach(dispose => dispose())
delete this.jar[name]
}

/**
* 处置所有未处置项目。
*/
public disposeAll(): void {
for (const key in this.jar) {
this.dispose(key)
}
}
}
25 changes: 25 additions & 0 deletions src/bindEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
type UnbindFn = () => void

/**
* 将指定类型的事件绑定在指定的目标上并返回解绑函数。
*
* @param target 事件目标
* @param types 事件类型
* @param listener 事件监听器
* @param [options] 事件选项
*/
export default function bindEvent(
target: EventTarget,
types: string | string[],
listener: EventListenerOrEventListenerObject,
options?: AddEventListenerOptions
): UnbindFn {
const disposes: Array<() => void> = [];
(Array.isArray(types) ? types : types.split(/\s+/)).forEach(eventType => {
target.addEventListener(eventType, listener, options)
disposes.push(
() => target.removeEventListener(eventType, listener, options)
)
})
return () => disposes.forEach(dispose => dispose())
}
9 changes: 9 additions & 0 deletions src/castArray.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* 如果 value 不是数组,那么强制转为数组。
*
* @param value 要处理的值
* @returns 转换后的数组
*/
export default function castArray<T>(value: T | ReadonlyArray<T>): T[] {
return Array.isArray(value) ? value : [value]
}
13 changes: 13 additions & 0 deletions src/clamp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* 返回限制在最小值和最大值之间的值。
*
* @param value 被限制的值
* @param min 最小值
* @param max 最大值
* @returns 结果值
*/
export default function clamp(value: number, min: number, max: number): number {
return value <= min ? min
: value >= max ? max
: value
}
6 changes: 6 additions & 0 deletions src/inBrowser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* 是否在浏览器环境中。
*/
export default typeof window === 'object'
&& typeof document === 'object'
&& document.nodeType === 9
7 changes: 7 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export { default as bindEvent } from './bindEvent'
export { default as castArray } from './castArray'
export { default as clamp } from './clamp'
export { default as Disposer } from './Disposer'
export { default as inBrowser } from './inBrowser'
export { default as noop } from './noop'
export { default as reduce } from './reduce'
4 changes: 4 additions & 0 deletions src/noop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/**
* 无操作函数。
*/
export default function noop() {} // tslint:disable-line
29 changes: 29 additions & 0 deletions src/reduce.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**
* 将一个数组或一个对象归纳为一个值。
*
* @param data 待归纳的数组或对象
* @param fn 归纳函数
* @param initialValue 归纳初始值
* @returns 归纳最终值
*/
function reduce<T, K extends number, R>(
data: ReadonlyArray<T>,
fn: (accumulator: R, currentValue: T, currentKey: K) => R,
accumulator: R
): R
function reduce<T extends object, K extends keyof T, R>(
data: T,
fn: (accumulator: R, currentValue: T[K], currentKey: K) => R,
accumulator: R
): R
function reduce(data: any, fn: any, accumulator: any): any {
if (Array.isArray(data)) {
return data.reduce(fn, accumulator)
} else {
return Object.keys(data).reduce((localAccumulator, key) => {
return fn(localAccumulator, data[key], key)
}, accumulator)
}
}

export default reduce
90 changes: 90 additions & 0 deletions test/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { SinonApi } from 'sinon'
const sinon: SinonApi = require('sinon') // tslint:disable-line
import * as vtils from '../src'

const now = new Date()

describe('bindEvent', () => {
test(`'click'`, () => {
const div = document.createElement('div')
const listener = sinon.fake()
vtils.bindEvent(div, 'click', listener)
expect(listener.called).toBeFalsy()
div.click()
expect(listener.callCount).toBe(1)
div.click()
expect(listener.callCount).toBe(2)
})
test(`'click tap'`, () => {
const div = document.createElement('div')
const listener = sinon.fake()
vtils.bindEvent(div, 'click tap', listener)
expect(listener.called).toBeFalsy()
div.click()
expect(listener.callCount).toBe(1)
div.dispatchEvent(new CustomEvent('tap'))
expect(listener.callCount).toBe(2)
})
test(`['click', 'tap']`, () => {
const div = document.createElement('div')
const listener = sinon.fake()
vtils.bindEvent(div, ['click', 'tap'], listener)
expect(listener.called).toBeFalsy()
div.click()
expect(listener.callCount).toBe(1)
div.dispatchEvent(new CustomEvent('tap'))
expect(listener.callCount).toBe(2)
})
test(`解绑`, () => {
const div = document.createElement('div')
const listener = sinon.fake()
const unbind = vtils.bindEvent(div, 'click', listener)
expect(listener.called).toBeFalsy()
div.click()
expect(listener.callCount).toBe(1)
div.click()
expect(listener.callCount).toBe(2)
unbind()
div.click()
expect(listener.callCount).toBe(2)
})
})

describe('castArray', () => {
test('数组保持不变', () => {
expect(vtils.castArray([1])).toEqual([1])
expect(vtils.castArray([true])).toEqual([true])
expect(vtils.castArray([1, true])).toEqual([1, true])
expect(vtils.castArray([1, true, now])).toEqual([1, true, now])
})
test('非数组强制转为一维数组', () => {
expect(vtils.castArray(1)).toEqual([1])
expect(vtils.castArray(true)).toEqual([true])
expect(vtils.castArray('hello')).toEqual(['hello'])
expect(vtils.castArray(now)).toEqual([now])
})
})

describe('clamp', () => {
test('上下限值之间返回原值', () => {
expect(vtils.clamp(5, 1, 20)).toEqual(5)
expect(vtils.clamp(0, -0.001, 0.11)).toEqual(0)
})
test('边界值处返回边界值', () => {
expect(vtils.clamp(1, 1, 20)).toEqual(1)
expect(vtils.clamp(0.11, -0.001, 0.11)).toEqual(0.11)
})
})

describe('reduce', () => {
test('数组归纳', () => {
expect(vtils.reduce([1, 2, 3], (total, value) => {
return total + value
}, 0)).toBe(6)
})
test('对象归纳', () => {
expect(vtils.reduce({ x: 'x', y: 'y', z: 'z', t: 2 }, (result, value) => {
return result + value
}, '')).toBe('xyz2')
})
})
22 changes: 22 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"compilerOptions": {
"strict": true,
"strictNullChecks": false,
"target": "es5",
"module": "ESNext",
"moduleResolution": "node",
"declaration": true,
"removeComments": true,
"outDir": "./dist",
"lib": [
"esnext",
"dom"
]
},
"include": [
"src"
],
"exclude": [
"node_modules"
]
}
Loading

0 comments on commit 6c5e7c7

Please sign in to comment.