aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Miller <[email protected]>2017-01-14 21:48:51 -0500
committerJason Miller <[email protected]>2017-01-14 21:48:51 -0500
commite77a42cdeca3f4c484f82a335a8a2bb8382d4fcc (patch)
tree612f883228b2db7343df71151427480f82b35206
Initial commit! 🚀
-rw-r--r--.gitignore5
-rw-r--r--README.md54
-rw-r--r--package.json76
-rw-r--r--rollup.config.js8
-rw-r--r--src/index.js47
-rw-r--r--test/index.js145
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`
+
+[![NPM](https://img.shields.io/npm/v/mitt.svg?style=flat)](https://www.npmjs.org/package/mitt)
+[![travis-ci](https://travis-ci.org/developit/mitt.svg?branch=master)](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);
+ });
+ });
+ });
+});