diff options
| author | Jason Miller <[email protected]> | 2017-01-14 21:48:51 -0500 |
|---|---|---|
| committer | Jason Miller <[email protected]> | 2017-01-14 21:48:51 -0500 |
| commit | e77a42cdeca3f4c484f82a335a8a2bb8382d4fcc (patch) | |
| tree | 612f883228b2db7343df71151427480f82b35206 | |
Initial commit! 🚀
| -rw-r--r-- | .gitignore | 5 | ||||
| -rw-r--r-- | README.md | 54 | ||||
| -rw-r--r-- | package.json | 76 | ||||
| -rw-r--r-- | rollup.config.js | 8 | ||||
| -rw-r--r-- | src/index.js | 47 | ||||
| -rw-r--r-- | test/index.js | 145 |
6 files changed, 335 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f8275b5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/dist +/test-reports +/node_modules +/npm-debug.log +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..2b6974e --- /dev/null +++ b/README.md @@ -0,0 +1,54 @@ +# `mitt` + +[](https://www.npmjs.org/package/mitt) +[](https://travis-ci.org/developit/mitt) + +**Tiny (~200b) functional event emitter / pubsub.** + +**It's tiny:** no dependencies and only **190 bytes** when gzipped _(250b without)_. + +* * * + +## Installation + +```sh +npm install --save mitt +``` + +* * * + +## API + +### mitt + +Mitt: Tiny (~200b) functional event emitter / pubsub. + +Returns **Mitt** + +#### on + +Register an event handler for the given type. + +**Parameters** + +- `type` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Type of event to listen for, or `"*"` for all events +- `handler` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** Function to call in response to the given event + +#### off + +Remove an event handler for the given type. + +**Parameters** + +- `type` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** Type of event to unregister `handler` from, or `"*"` +- `handler` **[Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)** Handler function to remove + +#### emit + +Invoke all handlers for the given type. +If present, `"*"` handlers are invoked prior to type-matched handlers. + +**Parameters** + +- `type` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** The event type to invoke +- `event` **\[Any]** An event object, passed to each handler diff --git a/package.json b/package.json new file mode 100644 index 0000000..a94a3c2 --- /dev/null +++ b/package.json @@ -0,0 +1,76 @@ +{ + "name": "mitt", + "amdName": "mitt", + "version": "0.2.1", + "description": "Tiny ~200b functional event emitter / pubsub.", + "jsnext:main": "src/index.js", + "main": "dist/mitt.js", + "umd:main": "dist/mitt.umd.js", + "scripts": { + "test": "eslint src test && mocha --compilers js:babel-register test/**/*.js", + "build": "npm-run-all clean -p rollup:* -p minify:* -s docs size", + "clean": "rimraf dist && mkdirp dist", + "rollup:cjs": "rollup -c rollup.config.js -m -f cjs -n $npm_package_amdName $npm_package_jsnext_main -o $npm_package_main", + "rollup:umd": "rollup -c rollup.config.js -m -f umd -n $npm_package_amdName $npm_package_jsnext_main -o $npm_package_umd_main", + "minify:cjs": "uglifyjs $npm_package_main -cm toplevel -o $npm_package_main -p relative --in-source-map ${npm_package_main}.map --source-map ${npm_package_main}.map", + "minify:umd": "uglifyjs $npm_package_umd_main -cm -o $npm_package_umd_main -p relative --in-source-map ${npm_package_umd_main}.map --source-map ${npm_package_umd_main}.map", + "docs": "documentation readme src/index.js --section API -q", + "size": "echo \"Gzipped Size: $(strip-json-comments --no-whitespace $npm_package_main | gzip-size | pretty-bytes)\"", + "release": "npm run build -s && git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish" + }, + "repository": "developit/mitt", + "keywords": [ + "events", + "eventemitter", + "pubsub" + ], + "homepage": "httsp://github.com/developit/mitt", + "authors": [ + "Jason Miller <[email protected]>" + ], + "license": "MIT", + "files": [ + "src", + "dist" + ], + "babel": { + "presets": [ + "es2015", + "stage-0" + ] + }, + "eslintConfig": { + "parser": "babel-eslint", + "extends": "eslint:recommended", + "env": { + "browser": true, + "mocha": true, + "es6": true + }, + "globals": { + "expect": true + } + }, + "devDependencies": { + "babel-core": "^6.9.1", + "babel-eslint": "^7.1.1", + "babel-preset-es2015": "^6.9.0", + "babel-preset-stage-0": "^6.5.0", + "babel-register": "^6.9.0", + "chai": "^3.5.0", + "documentation": "^4.0.0-beta4", + "eslint": "^3.13.1", + "gzip-size-cli": "^1.0.0", + "mkdirp": "^0.5.1", + "mocha": "^3.2.0", + "npm-run-all": "^2.1.1", + "pretty-bytes": "^4.0.2", + "rimraf": "^2.5.2", + "rollup": "^0.41.4", + "rollup-plugin-buble": "^0.15.0", + "sinon": "^1.17.4", + "sinon-chai": "^2.8.0", + "strip-json-comments-cli": "^1.0.1", + "uglify-js": "^2.6.2" + } +} diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 0000000..277d99e --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,8 @@ +import buble from 'rollup-plugin-buble'; + +export default { + useStrict: false, + plugins: [ + buble() + ] +}; diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..36b25f1 --- /dev/null +++ b/src/index.js @@ -0,0 +1,47 @@ +/** Mitt: Tiny (~200b) functional event emitter / pubsub. + * @name mitt + * @returns {Mitt} + */ +export default function mitt(all) { + // Arrays of event handlers, keyed by type + all = all || {}; + + // Get or create a named handler list + function list(type) { + let t = type.toLowerCase(); + return all[t] || (all[t] = []); + } + + return { + + /** Register an event handler for the given type. + * @param {String} type Type of event to listen for, or `"*"` for all events + * @param {Function} handler Function to call in response to the given event + * @memberof mitt + */ + on(type, handler) { + list(type).push(handler); + }, + + /** Remove an event handler for the given type. + * @param {String} type Type of event to unregister `handler` from, or `"*"` + * @param {Function} handler Handler function to remove + * @memberof mitt + */ + off(type, handler) { + let e = list(type), + i = e.indexOf(handler); + if (~i) e.splice(i, 1); + }, + + /** Invoke all handlers for the given type. + * If present, `"*"` handlers are invoked prior to type-matched handlers. + * @param {String} type The event type to invoke + * @param {Any} [event] An event object, passed to each handler + * @memberof mitt + */ + emit(type, event) { + list('*').concat(list(type)).forEach( f => { f(event); }); + } + }; +} diff --git a/test/index.js b/test/index.js new file mode 100644 index 0000000..8055544 --- /dev/null +++ b/test/index.js @@ -0,0 +1,145 @@ +import mitt from '../src'; +import chai, { expect } from 'chai'; +import { spy } from 'sinon'; +import sinonChai from 'sinon-chai'; +chai.use(sinonChai); + + +describe('mitt', () => { + it('should be a function', () => { + expect(mitt).to.be.a('function'); + }); + + describe('mitt#', () => { + let events, inst; + + beforeEach( () => { + events = {}; + inst = mitt(events); + }); + + describe('on()', () => { + it('should be a function', () => { + expect(inst) + .to.have.property('on') + .that.is.a('function'); + }); + + it('should register handler for new type', () => { + let foo = () => {}; + inst.on('foo', foo); + + expect(events).to.have.property('foo').that.deep.equals([foo]); + }); + + it('should append handler for existing type', () => { + let foo = () => {}; + let bar = () => {}; + inst.on('foo', foo); + inst.on('foo', foo); + inst.on('foo', bar); + + expect(events).to.have.property('foo').that.deep.equals([foo, foo, bar]); + }); + + it('should normalize case', () => { + let foo = () => {}; + inst.on('FOO', foo); + inst.on('Bar', foo); + inst.on('baz:baT!', foo); + + expect(events).to.have.property('foo').that.deep.equals([foo]); + expect(events).to.have.property('bar').that.deep.equals([foo]); + expect(events).to.have.property('baz:bat!').that.deep.equals([foo]); + }); + }); + + describe('off()', () => { + it('should be a function', () => { + expect(inst) + .to.have.property('off') + .that.is.a('function'); + }); + + it('should remove handler for type', () => { + let foo = () => {}; + events.foo = [foo]; + inst.off('foo', foo); + + expect(events).to.have.property('foo').that.is.empty; + }); + + it('should remove only one handler for dupes', () => { + let foo = () => {}; + events.foo = [foo, foo]; + + inst.off('foo', foo); + expect(events).to.have.property('foo').that.deep.equals([foo]); + + inst.off('foo', foo); + expect(events).to.have.property('foo').that.is.empty; + }); + + it('should normalize case', () => { + let foo = () => {}; + events.foo = [foo]; + events.bar = [foo]; + events['baz:bat!'] = [foo]; + + inst.off('FOO', foo); + inst.off('Bar', foo); + inst.off('baz:baT!', foo); + + expect(events).to.have.property('foo').that.is.empty; + expect(events).to.have.property('bar').that.is.empty; + expect(events).to.have.property('baz:bat!').that.is.empty; + }); + }); + + describe('emit()', () => { + it('should be a function', () => { + expect(inst) + .to.have.property('emit') + .that.is.a('function'); + }); + + it('should invoke handler for type', () => { + let foo = spy(), + event = {}; + events.foo = [foo]; + + inst.emit('foo', event); + + expect(foo) + .to.have.been.calledOnce + .and.calledWithExactly(event); + }); + + it('should ignore case', () => { + let foo = spy(), + event = {}; + events.foo = [foo]; + + inst.emit('FOO', event); + inst.emit('Foo', event); + + expect(foo) + .to.have.been.calledTwice + .and.always.calledWithExactly(event); + }); + + it('should invoke * handlers', () => { + let star = spy(), + event = {}; + events['*'] = [star]; + + inst.emit('foo', event); + inst.emit('bar', event); + + expect(star) + .to.have.been.calledTwice + .and.always.calledWithExactly(event); + }); + }); + }); +}); |
