From c576269d9770f78294f01074d0ac4fa778ae01f5 Mon Sep 17 00:00:00 2001 From: kleinfreund Date: Thu, 3 Jan 2019 11:03:16 +0100 Subject: [PATCH 1/8] Export KeyEvent as module to enable require in tests --- tests/libs/key-event.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/libs/key-event.js b/tests/libs/key-event.js index 44cee7ca..d71748bf 100644 --- a/tests/libs/key-event.js +++ b/tests/libs/key-event.js @@ -1,4 +1,4 @@ -(function() { +(function(window, document) { var KeyEvent = function(data, type) { this.keyCode = 'keyCode' in data ? data.keyCode : 0; this.charCode = 'charCode' in data ? data.charCode : 0; @@ -126,4 +126,16 @@ }; window.KeyEvent = KeyEvent; -}) (); + + // expose as a common js module + if (typeof module !== 'undefined' && module.exports) { + module.exports = KeyEvent; + } + + // expose KeyEvent as an AMD module + if (typeof define === 'function' && define.amd) { + define(function() { + return KeyEvent; + }); + } +}) (typeof window !== 'undefined' ? window : null, typeof window !== 'undefined' ? document : null); From a0a38c2df43f2b2786cf962ec39feba84a94c4ef Mon Sep 17 00:00:00 2001 From: kleinfreund Date: Thu, 3 Jan 2019 15:58:48 +0100 Subject: [PATCH 2/8] Rework tests to use npm-managed packages --- Gruntfile.js | 15 +- README.md | 30 +- package.json | 8 +- tests/libs/chai-1.6.0.js | 4251 ------------------------------- tests/libs/sinon-1.7.1.js | 4299 -------------------------------- tests/libs/sinon-chai-2.4.0.js | 109 - tests/libs/sinon-ie-1.7.1.js | 82 - tests/mousetrap.html | 28 +- tests/test.mousetrap.js | 1168 ++++----- 9 files changed, 624 insertions(+), 9366 deletions(-) delete mode 100644 tests/libs/chai-1.6.0.js delete mode 100644 tests/libs/sinon-1.7.1.js delete mode 100644 tests/libs/sinon-chai-2.4.0.js delete mode 100644 tests/libs/sinon-ie-1.7.1.js diff --git a/Gruntfile.js b/Gruntfile.js index 7db5a9b1..7e431fdb 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -5,17 +5,6 @@ module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), - mocha: { - options: { - reporter: 'Nyan', - run: true, - growlOnSuccess: false - }, - mousetrap: { - src: ['tests/mousetrap.html'] - } - }, - complexity: { options: { errorsOnly: false, @@ -39,10 +28,8 @@ module.exports = function(grunt) { }); grunt.loadNpmTasks('grunt-complexity'); - grunt.loadNpmTasks('grunt-mocha'); grunt.registerTask('default', [ - 'complexity', - 'mocha' + 'complexity' ]); }; diff --git a/README.md b/README.md index 749fdd14..54328702 100644 --- a/README.md +++ b/README.md @@ -12,11 +12,11 @@ It is around **2kb** minified and gzipped and **4.5kb** minified, has no externa - Firefox - Chrome -It has support for ``keypress``, ``keydown``, and ``keyup`` events on specific keys, keyboard combinations, or key sequences. +It has support for `keypress`, `keydown`, and `keyup` events on specific keys, keyboard combinations, or key sequences. ## Getting started -1. Include mousetrap on your page before the closing ```` tag +1. Include mousetrap on your page before the closing `` tag ```html @@ -28,7 +28,7 @@ It has support for ``keypress``, ``keydown``, and ``keyup`` events on specific k var Mousetrap = require('mousetrap'); ``` -2. Add some keyboard events to listen for +2. Add some keyboard events to listen for ```html + + - - - - - - + + diff --git a/tests/test.mousetrap.js b/tests/test.mousetrap.js index 98310da0..fa3ce747 100644 --- a/tests/test.mousetrap.js +++ b/tests/test.mousetrap.js @@ -1,714 +1,738 @@ -/* jshint es5: true, browser: true, expr: true */ -/* globals describe, afterEach, chai, it, sinon, Mousetrap, KeyEvent, Event */ +/** + * The following strategy of importing modules allows the tests to be run in a browser environment. + * Test libraries like `mocha`, `sinon`, etc. are expected to be loaded before this file. + */ +var sinon = sinon || require('sinon'); +var chai = chai || require('chai'); var expect = chai.expect; -afterEach(function() { - Mousetrap.reset(); + +if (typeof window === 'undefined') { + require('mocha'); + require('jsdom-global')(); +} + +// Load libraries that require access to the DOM after `jsdom-global` +var Mousetrap = Mousetrap || require('./../mousetrap'); +var KeyEvent = KeyEvent || require('./libs/key-event'); + + + +// Reset Mousetrap after each test +afterEach(function () { + Mousetrap.reset(); }); -describe('Mousetrap.bind', function() { - describe('basic', function() { - it('z key fires when pressing z', function() { - var spy = sinon.spy(); +describe('Mousetrap.bind', function () { + describe('basic', function () { + it('z key fires when pressing z', function () { + var spy = sinon.spy(); - Mousetrap.bind('z', spy); + Mousetrap.bind('z', spy); - KeyEvent.simulate('Z'.charCodeAt(0), 90); + KeyEvent.simulate('Z'.charCodeAt(0), 90); - // really slow for some reason - // expect(spy).to.have.been.calledOnce; - expect(spy.callCount).to.equal(1, 'callback should fire once'); - expect(spy.args[0][0]).to.be.an.instanceOf(Event, 'first argument should be Event'); - expect(spy.args[0][1]).to.equal('z', 'second argument should be key combo'); - }); + // really slow for some reason + // expect(spy).to.have.been.calledOnce; + expect(spy.callCount).to.equal(1, 'callback should fire once'); + expect(spy.args[0][0]).to.be.an.instanceOf(Event, 'first argument should be Event'); + expect(spy.args[0][1]).to.equal('z', 'second argument should be key combo'); + }); - it('z key fires from keydown', function() { - var spy = sinon.spy(); + it('z key fires from keydown', function () { + var spy = sinon.spy(); - Mousetrap.bind('z', spy, 'keydown'); + Mousetrap.bind('z', spy, 'keydown'); - KeyEvent.simulate('Z'.charCodeAt(0), 90); + KeyEvent.simulate('Z'.charCodeAt(0), 90); - // really slow for some reason - // expect(spy).to.have.been.calledOnce; - expect(spy.callCount).to.equal(1, 'callback should fire once'); - expect(spy.args[0][0]).to.be.an.instanceOf(Event, 'first argument should be Event'); - expect(spy.args[0][1]).to.equal('z', 'second argument should be key combo'); - }); + // really slow for some reason + // expect(spy).to.have.been.calledOnce; + expect(spy.callCount).to.equal(1, 'callback should fire once'); + expect(spy.args[0][0]).to.be.an.instanceOf(Event, 'first argument should be Event'); + expect(spy.args[0][1]).to.equal('z', 'second argument should be key combo'); + }); - it('z key does not fire when pressing b', function() { - var spy = sinon.spy(); + it('z key does not fire when pressing b', function () { + var spy = sinon.spy(); - Mousetrap.bind('z', spy); + Mousetrap.bind('z', spy); - KeyEvent.simulate('B'.charCodeAt(0), 66); + KeyEvent.simulate('B'.charCodeAt(0), 66); - expect(spy.callCount).to.equal(0); - }); + expect(spy.callCount).to.equal(0); + }); - it('z key does not fire when holding a modifier key', function() { - var spy = sinon.spy(); - var modifiers = ['ctrl', 'alt', 'meta', 'shift']; - var charCode; - var modifier; + it('z key does not fire when holding a modifier key', function () { + var spy = sinon.spy(); + var modifiers = ['ctrl', 'alt', 'meta', 'shift']; + var charCode; + var modifier; - Mousetrap.bind('z', spy); + Mousetrap.bind('z', spy); - for (var i = 0; i < 4; i++) { - modifier = modifiers[i]; - charCode = 'Z'.charCodeAt(0); + for (var i = 0; i < 4; i++) { + modifier = modifiers[i]; + charCode = 'Z'.charCodeAt(0); - // character code is different when alt is pressed - if (modifier == 'alt') { - charCode = 'Ω'.charCodeAt(0); - } + // character code is different when alt is pressed + if (modifier == 'alt') { + charCode = 'Ω'.charCodeAt(0); + } - spy.reset(); + spy.resetHistory(); - KeyEvent.simulate(charCode, 90, [modifier]); + KeyEvent.simulate(charCode, 90, [modifier]); - expect(spy.callCount).to.equal(0); - } - }); + expect(spy.callCount).to.equal(0); + } + }); - it('keyup events should fire', function() { - var spy = sinon.spy(); + it('keyup events should fire', function () { + var spy = sinon.spy(); - Mousetrap.bind('z', spy, 'keyup'); + Mousetrap.bind('z', spy, 'keyup'); - KeyEvent.simulate('Z'.charCodeAt(0), 90); + KeyEvent.simulate('Z'.charCodeAt(0), 90); - expect(spy.callCount).to.equal(1, 'keyup event for "z" should fire'); + expect(spy.callCount).to.equal(1, 'keyup event for "z" should fire'); - // for key held down we should only get one key up - KeyEvent.simulate('Z'.charCodeAt(0), 90, [], document, 10); - expect(spy.callCount).to.equal(2, 'keyup event for "z" should fire once for held down key'); - }); + // for key held down we should only get one key up + KeyEvent.simulate('Z'.charCodeAt(0), 90, [], document, 10); + expect(spy.callCount).to.equal(2, 'keyup event for "z" should fire once for held down key'); + }); - it('keyup event for 0 should fire', function() { - var spy = sinon.spy(); + it('keyup event for 0 should fire', function () { + var spy = sinon.spy(); - Mousetrap.bind('0', spy, 'keyup'); + Mousetrap.bind('0', spy, 'keyup'); - KeyEvent.simulate(0, 48); + KeyEvent.simulate(0, 48); - expect(spy.callCount).to.equal(1, 'keyup event for "0" should fire'); - }); + expect(spy.callCount).to.equal(1, 'keyup event for "0" should fire'); + }); - it('rebinding a key overwrites the callback for that key', function() { - var spy1 = sinon.spy(); - var spy2 = sinon.spy(); - Mousetrap.bind('x', spy1); - Mousetrap.bind('x', spy2); + it('rebinding a key overwrites the callback for that key', function () { + var spy1 = sinon.spy(); + var spy2 = sinon.spy(); + Mousetrap.bind('x', spy1); + Mousetrap.bind('x', spy2); - KeyEvent.simulate('X'.charCodeAt(0), 88); + KeyEvent.simulate('X'.charCodeAt(0), 88); - expect(spy1.callCount).to.equal(0, 'original callback should not fire'); - expect(spy2.callCount).to.equal(1, 'new callback should fire'); - }); + expect(spy1.callCount).to.equal(0, 'original callback should not fire'); + expect(spy2.callCount).to.equal(1, 'new callback should fire'); + }); - it('binding an array of keys', function() { - var spy = sinon.spy(); - Mousetrap.bind(['a', 'b', 'c'], spy); + it('binding an array of keys', function () { + var spy = sinon.spy(); + Mousetrap.bind(['a', 'b', 'c'], spy); - KeyEvent.simulate('A'.charCodeAt(0), 65); - expect(spy.callCount).to.equal(1, 'new callback was called'); - expect(spy.args[0][1]).to.equal('a', 'callback should match "a"'); + KeyEvent.simulate('A'.charCodeAt(0), 65); + expect(spy.callCount).to.equal(1, 'new callback was called'); + expect(spy.args[0][1]).to.equal('a', 'callback should match "a"'); - KeyEvent.simulate('B'.charCodeAt(0), 66); - expect(spy.callCount).to.equal(2, 'new callback was called twice'); - expect(spy.args[1][1]).to.equal('b', 'callback should match "b"'); + KeyEvent.simulate('B'.charCodeAt(0), 66); + expect(spy.callCount).to.equal(2, 'new callback was called twice'); + expect(spy.args[1][1]).to.equal('b', 'callback should match "b"'); - KeyEvent.simulate('C'.charCodeAt(0), 67); - expect(spy.callCount).to.equal(3, 'new callback was called three times'); - expect(spy.args[2][1]).to.equal('c', 'callback should match "c"'); - }); + KeyEvent.simulate('C'.charCodeAt(0), 67); + expect(spy.callCount).to.equal(3, 'new callback was called three times'); + expect(spy.args[2][1]).to.equal('c', 'callback should match "c"'); + }); - it('return false should prevent default and stop propagation', function() { - var spy = sinon.spy(function() { - return false; - }); + it('return false should prevent default and stop propagation', function () { + var spy = sinon.spy(function () { + return false; + }); - Mousetrap.bind('command+s', spy); + Mousetrap.bind('command+s', spy); - KeyEvent.simulate('S'.charCodeAt(0), 83, ['meta']); + KeyEvent.simulate('S'.charCodeAt(0), 83, ['meta']); - expect(spy.callCount).to.equal(1, 'callback should fire'); - expect(spy.args[0][0]).to.be.an.instanceOf(Event, 'first argument should be Event'); + expect(spy.callCount).to.equal(1, 'callback should fire'); + expect(spy.args[0][0]).to.be.an.instanceOf(Event, 'first argument should be Event'); - expect(spy.args[0][0].defaultPrevented).to.be.true; + expect(spy.args[0][0].defaultPrevented).to.be.true; - // cancelBubble is not correctly set to true in webkit/blink - // - // @see https://code.google.com/p/chromium/issues/detail?id=162270 - // expect(spy.args[0][0].cancelBubble).to.be.true; + // cancelBubble is not correctly set to true in webkit/blink + // + // @see https://code.google.com/p/chromium/issues/detail?id=162270 + // expect(spy.args[0][0].cancelBubble).to.be.true; - // try without return false - spy = sinon.spy(); - Mousetrap.bind('command+s', spy); - KeyEvent.simulate('S'.charCodeAt(0), 83, ['meta']); + // try without return false + spy = sinon.spy(); + Mousetrap.bind('command+s', spy); + KeyEvent.simulate('S'.charCodeAt(0), 83, ['meta']); - expect(spy.callCount).to.equal(1, 'callback should fire'); - expect(spy.args[0][0]).to.be.an.instanceOf(Event, 'first argument should be Event'); - expect(spy.args[0][0].cancelBubble).to.be.falsey; - expect(spy.args[0][0].defaultPrevented).to.be.falsey; - }); + expect(spy.callCount).to.equal(1, 'callback should fire'); + expect(spy.args[0][0]).to.be.an.instanceOf(Event, 'first argument should be Event'); + expect(spy.args[0][0].cancelBubble).to.be.false; + expect(spy.args[0][0].defaultPrevented).to.be.false; + }); - it('capslock key is ignored', function() { - var spy = sinon.spy(); - Mousetrap.bind('a', spy); + it('capslock key is ignored', function () { + var spy = sinon.spy(); + Mousetrap.bind('a', spy); - KeyEvent.simulate('a'.charCodeAt(0), 65); - expect(spy.callCount).to.equal(1, 'callback should fire for lowercase a'); + KeyEvent.simulate('a'.charCodeAt(0), 65); + expect(spy.callCount).to.equal(1, 'callback should fire for lowercase a'); - spy.reset(); - KeyEvent.simulate('A'.charCodeAt(0), 65); - expect(spy.callCount).to.equal(1, 'callback should fire for capslock A'); + spy.resetHistory(); + KeyEvent.simulate('A'.charCodeAt(0), 65); + expect(spy.callCount).to.equal(1, 'callback should fire for capslock A'); - spy.reset(); - KeyEvent.simulate('A'.charCodeAt(0), 65, ['shift']); - expect(spy.callCount).to.equal(0, 'callback should not fire fort shift+a'); - }); + spy.resetHistory(); + KeyEvent.simulate('A'.charCodeAt(0), 65, ['shift']); + expect(spy.callCount).to.equal(0, 'callback should not fire fort shift+a'); }); + }); - describe('special characters', function() { - it('binding special characters', function() { - var spy = sinon.spy(); - Mousetrap.bind('*', spy); + describe('special characters', function () { + it('binding special characters', function () { + var spy = sinon.spy(); + Mousetrap.bind('*', spy); - KeyEvent.simulate('*'.charCodeAt(0), 56, ['shift']); + KeyEvent.simulate('*'.charCodeAt(0), 56, ['shift']); - expect(spy.callCount).to.equal(1, 'callback should fire'); - expect(spy.args[0][1]).to.equal('*', 'callback should match *'); - }); + expect(spy.callCount).to.equal(1, 'callback should fire'); + expect(spy.args[0][1]).to.equal('*', 'callback should match *'); + }); - it('binding special characters keyup', function() { - var spy = sinon.spy(); - Mousetrap.bind('*', spy, 'keyup'); + it('binding special characters keyup', function () { + var spy = sinon.spy(); + Mousetrap.bind('*', spy, 'keyup'); - KeyEvent.simulate('*'.charCodeAt(0), 56, ['shift']); + KeyEvent.simulate('*'.charCodeAt(0), 56, ['shift']); - expect(spy.callCount).to.equal(1, 'callback should fire'); - expect(spy.args[0][1]).to.equal('*', 'callback should match "*"'); - }); + expect(spy.callCount).to.equal(1, 'callback should fire'); + expect(spy.args[0][1]).to.equal('*', 'callback should match "*"'); + }); - it('binding keys with no associated charCode', function() { - var spy = sinon.spy(); - Mousetrap.bind('left', spy); + it('binding keys with no associated charCode', function () { + var spy = sinon.spy(); + Mousetrap.bind('left', spy); - KeyEvent.simulate(0, 37); + KeyEvent.simulate(0, 37); - expect(spy.callCount).to.equal(1, 'callback should fire'); - expect(spy.args[0][1]).to.equal('left', 'callback should match "left"'); - }); + expect(spy.callCount).to.equal(1, 'callback should fire'); + expect(spy.args[0][1]).to.equal('left', 'callback should match "left"'); + }); - it('binding plus key alone should work', function() { - var spy = sinon.spy(); - Mousetrap.bind('+', spy); + it('binding plus key alone should work', function () { + var spy = sinon.spy(); + Mousetrap.bind('+', spy); - // fires for regular + character - KeyEvent.simulate('+'.charCodeAt(0), 43); + // fires for regular + character + KeyEvent.simulate('+'.charCodeAt(0), 43); - // and for shift+= - KeyEvent.simulate(43, 187, ['shift']); + // and for shift+= + KeyEvent.simulate(43, 187, ['shift']); - expect(spy.callCount).to.equal(2, 'callback should fire'); - expect(spy.args[0][1]).to.equal('+', 'callback should match "+"'); - }); + expect(spy.callCount).to.equal(2, 'callback should fire'); + expect(spy.args[0][1]).to.equal('+', 'callback should match "+"'); + }); - it('binding plus key as "plus" should work', function() { - var spy = sinon.spy(); - Mousetrap.bind('plus', spy); + it('binding plus key as "plus" should work', function () { + var spy = sinon.spy(); + Mousetrap.bind('plus', spy); - // fires for regular + character - KeyEvent.simulate('+'.charCodeAt(0), 43); + // fires for regular + character + KeyEvent.simulate('+'.charCodeAt(0), 43); - // and for shift+= - KeyEvent.simulate(43, 187, ['shift']); + // and for shift+= + KeyEvent.simulate(43, 187, ['shift']); - expect(spy.callCount).to.equal(2, 'callback should fire'); - expect(spy.args[0][1]).to.equal('plus', 'callback should match "plus"'); - }); + expect(spy.callCount).to.equal(2, 'callback should fire'); + expect(spy.args[0][1]).to.equal('plus', 'callback should match "plus"'); + }); - it('binding to alt++ should work', function() { - var spy = sinon.spy(); - Mousetrap.bind('alt++', spy); + it('binding to alt++ should work', function () { + var spy = sinon.spy(); + Mousetrap.bind('alt++', spy); - KeyEvent.simulate('+'.charCodeAt(0), 43, ['alt']); - expect(spy.callCount).to.equal(1, 'callback should fire'); - expect(spy.args[0][1]).to.equal('alt++', 'callback should match "alt++"'); - }); + KeyEvent.simulate('+'.charCodeAt(0), 43, ['alt']); + expect(spy.callCount).to.equal(1, 'callback should fire'); + expect(spy.args[0][1]).to.equal('alt++', 'callback should match "alt++"'); + }); - it('binding to alt+shift++ should work as well', function() { - var spy = sinon.spy(); - Mousetrap.bind('alt+shift++', spy); + it('binding to alt+shift++ should work as well', function () { + var spy = sinon.spy(); + Mousetrap.bind('alt+shift++', spy); - KeyEvent.simulate('+'.charCodeAt(0), 43, ['shift', 'alt']); - expect(spy.callCount).to.equal(1, 'callback should fire'); - expect(spy.args[0][1]).to.equal('alt+shift++', 'callback should match "alt++"'); + KeyEvent.simulate('+'.charCodeAt(0), 43, ['shift', 'alt']); + expect(spy.callCount).to.equal(1, 'callback should fire'); + expect(spy.args[0][1]).to.equal('alt+shift++', 'callback should match "alt++"'); - }) }); + }); - describe('combos with modifiers', function() { - it('binding key combinations', function() { - var spy = sinon.spy(); - Mousetrap.bind('command+o', spy); + describe('combos with modifiers', function () { + it('binding key combinations', function () { + var spy = sinon.spy(); + Mousetrap.bind('command+o', spy); - KeyEvent.simulate('O'.charCodeAt(0), 79, ['meta']); + KeyEvent.simulate('O'.charCodeAt(0), 79, ['meta']); - expect(spy.callCount).to.equal(1, 'command+o callback should fire'); - expect(spy.args[0][1]).to.equal('command+o', 'keyboard string returned is correct'); - }); + expect(spy.callCount).to.equal(1, 'command+o callback should fire'); + expect(spy.args[0][1]).to.equal('command+o', 'keyboard string returned is correct'); + }); - it('binding key combos with multiple modifiers', function() { - var spy = sinon.spy(); - Mousetrap.bind('command+shift+o', spy); - KeyEvent.simulate('O'.charCodeAt(0), 79, ['meta']); - expect(spy.callCount).to.equal(0, 'command+o callback should not fire'); + it('binding key combos with multiple modifiers', function () { + var spy = sinon.spy(); + Mousetrap.bind('command+shift+o', spy); + KeyEvent.simulate('O'.charCodeAt(0), 79, ['meta']); + expect(spy.callCount).to.equal(0, 'command+o callback should not fire'); - KeyEvent.simulate('O'.charCodeAt(0), 79, ['meta', 'shift']); - expect(spy.callCount).to.equal(1, 'command+o callback should fire'); - }); + KeyEvent.simulate('O'.charCodeAt(0), 79, ['meta', 'shift']); + expect(spy.callCount).to.equal(1, 'command+o callback should fire'); + }); - it('should fire callback when ctrl+numpad 0 is pressed', function() { - var spy = sinon.spy(); + it('should fire callback when ctrl+numpad 0 is pressed', function () { + var spy = sinon.spy(); - Mousetrap.bind('ctrl+0', spy); + Mousetrap.bind('ctrl+0', spy); - // numpad 0 keycode - KeyEvent.simulate(96, 96, ['ctrl']); + // numpad 0 keycode + KeyEvent.simulate(96, 96, ['ctrl']); - expect(spy.callCount).to.equal(1, 'callback should fire once'); - expect(spy.args[0][0]).to.be.an.instanceOf(Event, 'first argument should be Event'); - expect(spy.args[0][1]).to.equal('ctrl+0', 'second argument should be key combo'); - }); + expect(spy.callCount).to.equal(1, 'callback should fire once'); + expect(spy.args[0][0]).to.be.an.instanceOf(Event, 'first argument should be Event'); + expect(spy.args[0][1]).to.equal('ctrl+0', 'second argument should be key combo'); }); + }); - describe('sequences', function() { - it('binding sequences', function() { - var spy = sinon.spy(); - Mousetrap.bind('g i', spy); + describe('sequences', function () { + it('binding sequences', function () { + var spy = sinon.spy(); + Mousetrap.bind('g i', spy); - KeyEvent.simulate('G'.charCodeAt(0), 71); - expect(spy.callCount).to.equal(0, 'callback should not fire'); + KeyEvent.simulate('G'.charCodeAt(0), 71); + expect(spy.callCount).to.equal(0, 'callback should not fire'); - KeyEvent.simulate('I'.charCodeAt(0), 73); - expect(spy.callCount).to.equal(1, 'callback should fire'); - }); + KeyEvent.simulate('I'.charCodeAt(0), 73); + expect(spy.callCount).to.equal(1, 'callback should fire'); + }); - it('binding sequences with mixed types', function() { - var spy = sinon.spy(); - Mousetrap.bind('g o enter', spy); + it('binding sequences with mixed types', function () { + var spy = sinon.spy(); + Mousetrap.bind('g o enter', spy); - KeyEvent.simulate('G'.charCodeAt(0), 71); - expect(spy.callCount).to.equal(0, 'callback should not fire'); + KeyEvent.simulate('G'.charCodeAt(0), 71); + expect(spy.callCount).to.equal(0, 'callback should not fire'); - KeyEvent.simulate('O'.charCodeAt(0), 79); - expect(spy.callCount).to.equal(0, 'callback should not fire'); + KeyEvent.simulate('O'.charCodeAt(0), 79); + expect(spy.callCount).to.equal(0, 'callback should not fire'); - KeyEvent.simulate(0, 13); - expect(spy.callCount).to.equal(1, 'callback should fire'); - }); + KeyEvent.simulate(0, 13); + expect(spy.callCount).to.equal(1, 'callback should fire'); + }); - it('binding sequences starting with modifier keys', function() { - var spy = sinon.spy(); - Mousetrap.bind('option enter', spy); - KeyEvent.simulate(0, 18, ['alt']); - KeyEvent.simulate(0, 13); - expect(spy.callCount).to.equal(1, 'callback should fire'); + it('binding sequences starting with modifier keys', function () { + var spy = sinon.spy(); + Mousetrap.bind('option enter', spy); + KeyEvent.simulate(0, 18, ['alt']); + KeyEvent.simulate(0, 13); + expect(spy.callCount).to.equal(1, 'callback should fire'); + + spy = sinon.spy(); + Mousetrap.bind('command enter', spy); + KeyEvent.simulate(0, 91, ['meta']); + KeyEvent.simulate(0, 13); + expect(spy.callCount).to.equal(1, 'callback should fire'); + + spy = sinon.spy(); + Mousetrap.bind('escape enter', spy); + KeyEvent.simulate(0, 27); + KeyEvent.simulate(0, 13); + expect(spy.callCount).to.equal(1, 'callback should fire'); + }); - spy = sinon.spy(); - Mousetrap.bind('command enter', spy); - KeyEvent.simulate(0, 91, ['meta']); - KeyEvent.simulate(0, 13); - expect(spy.callCount).to.equal(1, 'callback should fire'); + it('key within sequence should not fire', function () { + var spy1 = sinon.spy(); + var spy2 = sinon.spy(); + Mousetrap.bind('a', spy1); + Mousetrap.bind('c a t', spy2); + + KeyEvent.simulate('A'.charCodeAt(0), 65); + expect(spy1.callCount).to.equal(1, 'callback 1 should fire'); + spy1.resetHistory(); + + KeyEvent.simulate('C'.charCodeAt(0), 67); + KeyEvent.simulate('A'.charCodeAt(0), 65); + KeyEvent.simulate('T'.charCodeAt(0), 84); + expect(spy1.callCount).to.equal(0, 'callback for "a" key should not fire'); + expect(spy2.callCount).to.equal(1, 'callback for "c a t" sequence should fire'); + }); - spy = sinon.spy(); - Mousetrap.bind('escape enter', spy); - KeyEvent.simulate(0, 27); - KeyEvent.simulate(0, 13); - expect(spy.callCount).to.equal(1, 'callback should fire'); - }); + it('keyup at end of sequence should not fire', function () { + var spy1 = sinon.spy(); + var spy2 = sinon.spy(); - it('key within sequence should not fire', function() { - var spy1 = sinon.spy(); - var spy2 = sinon.spy(); - Mousetrap.bind('a', spy1); - Mousetrap.bind('c a t', spy2); + Mousetrap.bind('t', spy1, 'keyup'); + Mousetrap.bind('b a t', spy2); - KeyEvent.simulate('A'.charCodeAt(0), 65); - expect(spy1.callCount).to.equal(1, 'callback 1 should fire'); - spy1.reset(); + KeyEvent.simulate('B'.charCodeAt(0), 66); + KeyEvent.simulate('A'.charCodeAt(0), 65); + KeyEvent.simulate('T'.charCodeAt(0), 84); - KeyEvent.simulate('C'.charCodeAt(0), 67); - KeyEvent.simulate('A'.charCodeAt(0), 65); - KeyEvent.simulate('T'.charCodeAt(0), 84); - expect(spy1.callCount).to.equal(0, 'callback for "a" key should not fire'); - expect(spy2.callCount).to.equal(1, 'callback for "c a t" sequence should fire'); - }); + expect(spy1.callCount).to.equal(0, 'callback for "t" keyup should not fire'); + expect(spy2.callCount).to.equal(1, 'callback for "b a t" sequence should fire'); + }); - it('keyup at end of sequence should not fire', function() { - var spy1 = sinon.spy(); - var spy2 = sinon.spy(); - - Mousetrap.bind('t', spy1, 'keyup'); - Mousetrap.bind('b a t', spy2); - - KeyEvent.simulate('B'.charCodeAt(0), 66); - KeyEvent.simulate('A'.charCodeAt(0), 65); - KeyEvent.simulate('T'.charCodeAt(0), 84); - - expect(spy1.callCount).to.equal(0, 'callback for "t" keyup should not fire'); - expect(spy2.callCount).to.equal(1, 'callback for "b a t" sequence should fire'); - }); - - it('keyup sequences should work', function() { - var spy = sinon.spy(); - Mousetrap.bind('b a t', spy, 'keyup'); - - KeyEvent.simulate('b'.charCodeAt(0), 66); - KeyEvent.simulate('a'.charCodeAt(0), 65); - - // hold the last key down for a while - KeyEvent.simulate('t'.charCodeAt(0), 84, [], document, 10); - - expect(spy.callCount).to.equal(1, 'callback for "b a t" sequence should fire on keyup'); - }); - - it('extra spaces in sequences should be ignored', function() { - var spy = sinon.spy(); - Mousetrap.bind('b a t', spy); - - KeyEvent.simulate('b'.charCodeAt(0), 66); - KeyEvent.simulate('a'.charCodeAt(0), 65); - KeyEvent.simulate('t'.charCodeAt(0), 84); - - expect(spy.callCount).to.equal(1, 'callback for "b a t" sequence should fire'); - }); - - it('modifiers and sequences play nicely', function() { - var spy1 = sinon.spy(); - var spy2 = sinon.spy(); - - Mousetrap.bind('ctrl a', spy1); - Mousetrap.bind('ctrl+b', spy2); - - KeyEvent.simulate(0, 17, ['ctrl']); - KeyEvent.simulate('A'.charCodeAt(0), 65); - expect(spy1.callCount).to.equal(1, '"ctrl a" should fire'); - - KeyEvent.simulate('B'.charCodeAt(0), 66, ['ctrl']); - expect(spy2.callCount).to.equal(1, '"ctrl+b" should fire'); - }); - - it('sequences that start the same work', function() { - var spy1 = sinon.spy(); - var spy2 = sinon.spy(); - - Mousetrap.bind('g g l', spy2); - Mousetrap.bind('g g o', spy1); - - KeyEvent.simulate('g'.charCodeAt(0), 71); - KeyEvent.simulate('g'.charCodeAt(0), 71); - KeyEvent.simulate('o'.charCodeAt(0), 79); - expect(spy1.callCount).to.equal(1, '"g g o" should fire'); - expect(spy2.callCount).to.equal(0, '"g g l" should not fire'); - - spy1.reset(); - spy2.reset(); - KeyEvent.simulate('g'.charCodeAt(0), 71); - KeyEvent.simulate('g'.charCodeAt(0), 71); - KeyEvent.simulate('l'.charCodeAt(0), 76); - expect(spy1.callCount).to.equal(0, '"g g o" should not fire'); - expect(spy2.callCount).to.equal(1, '"g g l" should fire'); - }); - - it('sequences should not fire subsequences', function() { - var spy1 = sinon.spy(); - var spy2 = sinon.spy(); - - Mousetrap.bind('a b c', spy1); - Mousetrap.bind('b c', spy2); - - KeyEvent.simulate('A'.charCodeAt(0), 65); - KeyEvent.simulate('B'.charCodeAt(0), 66); - KeyEvent.simulate('C'.charCodeAt(0), 67); + it('keyup sequences should work', function () { + var spy = sinon.spy(); + Mousetrap.bind('b a t', spy, 'keyup'); - expect(spy1.callCount).to.equal(1, '"a b c" should fire'); - expect(spy2.callCount).to.equal(0, '"b c" should not fire'); - - spy1.reset(); - spy2.reset(); - Mousetrap.bind('option b', spy1); - Mousetrap.bind('a option b', spy2); - - KeyEvent.simulate('A'.charCodeAt(0), 65); - KeyEvent.simulate(0, 18, ['alt']); - KeyEvent.simulate('B'.charCodeAt(0), 66); + KeyEvent.simulate('b'.charCodeAt(0), 66); + KeyEvent.simulate('a'.charCodeAt(0), 65); - expect(spy1.callCount).to.equal(0, '"option b" should not fire'); - expect(spy2.callCount).to.equal(1, '"a option b" should fire'); - }); + // hold the last key down for a while + KeyEvent.simulate('t'.charCodeAt(0), 84, [], document, 10); - it('rebinding same sequence should override previous', function() { - var spy1 = sinon.spy(); - var spy2 = sinon.spy(); - Mousetrap.bind('a b c', spy1); - Mousetrap.bind('a b c', spy2); - - KeyEvent.simulate('a'.charCodeAt(0), 65); - KeyEvent.simulate('b'.charCodeAt(0), 66); - KeyEvent.simulate('c'.charCodeAt(0), 67); + expect(spy.callCount).to.equal(1, 'callback for "b a t" sequence should fire on keyup'); + }); - expect(spy1.callCount).to.equal(0, 'first callback should not fire'); - expect(spy2.callCount).to.equal(1, 'second callback should fire'); - }); - - it('broken sequences', function() { - var spy = sinon.spy(); - Mousetrap.bind('h a t', spy); - - KeyEvent.simulate('h'.charCodeAt(0), 72); - KeyEvent.simulate('e'.charCodeAt(0), 69); - KeyEvent.simulate('a'.charCodeAt(0), 65); - KeyEvent.simulate('r'.charCodeAt(0), 82); - KeyEvent.simulate('t'.charCodeAt(0), 84); - - expect(spy.callCount).to.equal(0, 'sequence for "h a t" should not fire for "h e a r t"'); - }); - - it('sequences containing combos should work', function() { - var spy = sinon.spy(); - Mousetrap.bind('a ctrl+b', spy); - - KeyEvent.simulate('a'.charCodeAt(0), 65); - KeyEvent.simulate('B'.charCodeAt(0), 66, ['ctrl']); - - expect(spy.callCount).to.equal(1, '"a ctrl+b" should fire'); - - Mousetrap.unbind('a ctrl+b'); - - spy = sinon.spy(); - Mousetrap.bind('ctrl+b a', spy); - - KeyEvent.simulate('b'.charCodeAt(0), 66, ['ctrl']); - KeyEvent.simulate('a'.charCodeAt(0), 65); - - expect(spy.callCount).to.equal(1, '"ctrl+b a" should fire'); - }); - - it('sequences starting with spacebar should work', function() { - var spy = sinon.spy(); - Mousetrap.bind('a space b c', spy); - - KeyEvent.simulate('a'.charCodeAt(0), 65); - KeyEvent.simulate(32, 32); - KeyEvent.simulate('b'.charCodeAt(0), 66); - KeyEvent.simulate('c'.charCodeAt(0), 67); - - expect(spy.callCount).to.equal(1, '"a space b c" should fire'); - }); - - it('konami code', function() { - var spy = sinon.spy(); - Mousetrap.bind('up up down down left right left right b a enter', spy); - - KeyEvent.simulate(0, 38); - KeyEvent.simulate(0, 38); - KeyEvent.simulate(0, 40); - KeyEvent.simulate(0, 40); - KeyEvent.simulate(0, 37); - KeyEvent.simulate(0, 39); - KeyEvent.simulate(0, 37); - KeyEvent.simulate(0, 39); - KeyEvent.simulate('b'.charCodeAt(0), 66); - KeyEvent.simulate('a'.charCodeAt(0), 65); - KeyEvent.simulate(0, 13); - - expect(spy.callCount).to.equal(1, 'konami code should fire'); - }); - - it('sequence timer resets', function() { - var spy = sinon.spy(); - var clock = sinon.useFakeTimers(); - - Mousetrap.bind('h a t', spy); - - KeyEvent.simulate('h'.charCodeAt(0), 72); - clock.tick(600); - KeyEvent.simulate('a'.charCodeAt(0), 65); - clock.tick(900); - KeyEvent.simulate('t'.charCodeAt(0), 84); - - expect(spy.callCount).to.equal(1, 'sequence should fire after waiting'); - clock.restore(); - }); - - it('sequences timeout', function() { - var spy = sinon.spy(); - var clock = sinon.useFakeTimers(); - - Mousetrap.bind('g t', spy); - KeyEvent.simulate('g'.charCodeAt(0), 71); - clock.tick(1000); - KeyEvent.simulate('t'.charCodeAt(0), 84); - - expect(spy.callCount).to.equal(0, 'sequence callback should not fire'); - clock.restore(); - }); - }); - - describe('default actions', function() { - var keys = { - keypress: [ - ['a', 65], - ['A', 65, ['shift']], - ['7', 55], - ['?', 191], - ['*', 56], - ['+', 187], - ['$', 52], - ['[', 219], - ['.', 190] - ], - keydown: [ - ['shift+\'', 222, ['shift']], - ['shift+a', 65, ['shift']], - ['shift+5', 53, ['shift']], - ['command+shift+p', 80, ['meta', 'shift']], - ['space', 32], - ['left', 37] - ] - }; - - function getCallback(key, keyCode, type, modifiers) { - return function() { - var spy = sinon.spy(); - Mousetrap.bind(key, spy); - - KeyEvent.simulate(key.charCodeAt(0), keyCode, modifiers); - expect(spy.callCount).to.equal(1); - expect(spy.args[0][0].type).to.equal(type); - }; - } + it('extra spaces in sequences should be ignored', function () { + var spy = sinon.spy(); + Mousetrap.bind('b a t', spy); - for (var type in keys) { - for (var i = 0; i < keys[type].length; i++) { - var key = keys[type][i][0]; - var keyCode = keys[type][i][1]; - var modifiers = keys[type][i][2] || []; - it('"' + key + '" uses "' + type + '"', getCallback(key, keyCode, type, modifiers)); - } - } + KeyEvent.simulate('b'.charCodeAt(0), 66); + KeyEvent.simulate('a'.charCodeAt(0), 65); + KeyEvent.simulate('t'.charCodeAt(0), 84); + + expect(spy.callCount).to.equal(1, 'callback for "b a t" sequence should fire'); }); -}); -describe('Mousetrap.unbind', function() { - it('unbind works', function() { - var spy = sinon.spy(); - Mousetrap.bind('a', spy); - KeyEvent.simulate('a'.charCodeAt(0), 65); - expect(spy.callCount).to.equal(1, 'callback for a should fire'); + it('modifiers and sequences play nicely', function () { + var spy1 = sinon.spy(); + var spy2 = sinon.spy(); + + Mousetrap.bind('ctrl a', spy1); + Mousetrap.bind('ctrl+b', spy2); - Mousetrap.unbind('a'); - KeyEvent.simulate('a'.charCodeAt(0), 65); - expect(spy.callCount).to.equal(1, 'callback for a should not fire after unbind'); + KeyEvent.simulate(0, 17, ['ctrl']); + KeyEvent.simulate('A'.charCodeAt(0), 65); + expect(spy1.callCount).to.equal(1, '"ctrl a" should fire'); + + KeyEvent.simulate('B'.charCodeAt(0), 66, ['ctrl']); + expect(spy2.callCount).to.equal(1, '"ctrl+b" should fire'); }); - it('unbind accepts an array', function() { - var spy = sinon.spy(); - Mousetrap.bind(['a', 'b', 'c'], spy); - KeyEvent.simulate('a'.charCodeAt(0), 65); - KeyEvent.simulate('b'.charCodeAt(0), 66); - KeyEvent.simulate('c'.charCodeAt(0), 67); - expect(spy.callCount).to.equal(3, 'callback should have fired 3 times'); - - Mousetrap.unbind(['a', 'b', 'c']); - KeyEvent.simulate('a'.charCodeAt(0), 65); - KeyEvent.simulate('b'.charCodeAt(0), 66); - KeyEvent.simulate('c'.charCodeAt(0), 67); - expect(spy.callCount).to.equal(3, 'callback should not fire after unbind'); + it('sequences that start the same work', function () { + var spy1 = sinon.spy(); + var spy2 = sinon.spy(); + + Mousetrap.bind('g g l', spy2); + Mousetrap.bind('g g o', spy1); + + KeyEvent.simulate('g'.charCodeAt(0), 71); + KeyEvent.simulate('g'.charCodeAt(0), 71); + KeyEvent.simulate('o'.charCodeAt(0), 79); + expect(spy1.callCount).to.equal(1, '"g g o" should fire'); + expect(spy2.callCount).to.equal(0, '"g g l" should not fire'); + + spy1.resetHistory(); + spy2.resetHistory(); + KeyEvent.simulate('g'.charCodeAt(0), 71); + KeyEvent.simulate('g'.charCodeAt(0), 71); + KeyEvent.simulate('l'.charCodeAt(0), 76); + expect(spy1.callCount).to.equal(0, '"g g o" should not fire'); + expect(spy2.callCount).to.equal(1, '"g g l" should fire'); }); -}); -describe('wrapping a specific element', function() { - var form = document.querySelector('form'); - var textarea = form.querySelector('textarea'); + it('sequences should not fire subsequences', function () { + var spy1 = sinon.spy(); + var spy2 = sinon.spy(); - it('z key fires when pressing z in the target element', function() { - var spy = sinon.spy(); + Mousetrap.bind('a b c', spy1); + Mousetrap.bind('b c', spy2); + + KeyEvent.simulate('A'.charCodeAt(0), 65); + KeyEvent.simulate('B'.charCodeAt(0), 66); + KeyEvent.simulate('C'.charCodeAt(0), 67); - Mousetrap(form).bind('z', spy); + expect(spy1.callCount).to.equal(1, '"a b c" should fire'); + expect(spy2.callCount).to.equal(0, '"b c" should not fire'); - KeyEvent.simulate('Z'.charCodeAt(0), 90, [], form); + spy1.resetHistory(); + spy2.resetHistory(); + Mousetrap.bind('option b', spy1); + Mousetrap.bind('a option b', spy2); - expect(spy.callCount).to.equal(1, 'callback should fire once'); - expect(spy.args[0][0]).to.be.an.instanceOf(Event, 'first argument should be Event'); - expect(spy.args[0][1]).to.equal('z', 'second argument should be key combo'); + KeyEvent.simulate('A'.charCodeAt(0), 65); + KeyEvent.simulate(0, 18, ['alt']); + KeyEvent.simulate('B'.charCodeAt(0), 66); + + expect(spy1.callCount).to.equal(0, '"option b" should not fire'); + expect(spy2.callCount).to.equal(1, '"a option b" should fire'); }); - it('z key fires when pressing z in a child of the target element', function() { - var spy = sinon.spy(); + it('rebinding same sequence should override previous', function () { + var spy1 = sinon.spy(); + var spy2 = sinon.spy(); + Mousetrap.bind('a b c', spy1); + Mousetrap.bind('a b c', spy2); - Mousetrap(form).bind('z', spy); + KeyEvent.simulate('a'.charCodeAt(0), 65); + KeyEvent.simulate('b'.charCodeAt(0), 66); + KeyEvent.simulate('c'.charCodeAt(0), 67); - KeyEvent.simulate('Z'.charCodeAt(0), 90, [], textarea); + expect(spy1.callCount).to.equal(0, 'first callback should not fire'); + expect(spy2.callCount).to.equal(1, 'second callback should fire'); + }); + + it('broken sequences', function () { + var spy = sinon.spy(); + Mousetrap.bind('h a t', spy); + + KeyEvent.simulate('h'.charCodeAt(0), 72); + KeyEvent.simulate('e'.charCodeAt(0), 69); + KeyEvent.simulate('a'.charCodeAt(0), 65); + KeyEvent.simulate('r'.charCodeAt(0), 82); + KeyEvent.simulate('t'.charCodeAt(0), 84); - expect(spy.callCount).to.equal(1, 'callback should fire once'); - expect(spy.args[0][0]).to.be.an.instanceOf(Event, 'first argument should be Event'); - expect(spy.args[0][1]).to.equal('z', 'second argument should be key combo'); + expect(spy.callCount).to.equal(0, 'sequence for "h a t" should not fire for "h e a r t"'); }); - it('z key does not fire when pressing z outside the target element', function() { - var spy = sinon.spy(); + it('sequences containing combos should work', function () { + var spy = sinon.spy(); + Mousetrap.bind('a ctrl+b', spy); + + KeyEvent.simulate('a'.charCodeAt(0), 65); + KeyEvent.simulate('B'.charCodeAt(0), 66, ['ctrl']); + + expect(spy.callCount).to.equal(1, '"a ctrl+b" should fire'); - Mousetrap(textarea).bind('z', spy); + Mousetrap.unbind('a ctrl+b'); - KeyEvent.simulate('Z'.charCodeAt(0), 90); + spy = sinon.spy(); + Mousetrap.bind('ctrl+b a', spy); - expect(spy.callCount).to.equal(0, 'callback should not have fired'); + KeyEvent.simulate('b'.charCodeAt(0), 66, ['ctrl']); + KeyEvent.simulate('a'.charCodeAt(0), 65); + + expect(spy.callCount).to.equal(1, '"ctrl+b a" should fire'); }); - it('should work when constructing a new mousetrap object', function() { - var spy = sinon.spy(); + it('sequences starting with spacebar should work', function () { + var spy = sinon.spy(); + Mousetrap.bind('a space b c', spy); - var mousetrap = new Mousetrap(form); - mousetrap.bind('a', spy); + KeyEvent.simulate('a'.charCodeAt(0), 65); + KeyEvent.simulate(32, 32); + KeyEvent.simulate('b'.charCodeAt(0), 66); + KeyEvent.simulate('c'.charCodeAt(0), 67); - KeyEvent.simulate('a'.charCodeAt(0), 65, [], textarea); + expect(spy.callCount).to.equal(1, '"a space b c" should fire'); + }); - expect(spy.callCount).to.equal(1, 'callback should fire once'); - expect(spy.args[0][0]).to.be.an.instanceOf(Event, 'first argument should be Event'); - expect(spy.args[0][1]).to.equal('a', 'second argument should be key combo'); + it('konami code', function () { + var spy = sinon.spy(); + Mousetrap.bind('up up down down left right left right b a enter', spy); + + KeyEvent.simulate(0, 38); + KeyEvent.simulate(0, 38); + KeyEvent.simulate(0, 40); + KeyEvent.simulate(0, 40); + KeyEvent.simulate(0, 37); + KeyEvent.simulate(0, 39); + KeyEvent.simulate(0, 37); + KeyEvent.simulate(0, 39); + KeyEvent.simulate('b'.charCodeAt(0), 66); + KeyEvent.simulate('a'.charCodeAt(0), 65); + KeyEvent.simulate(0, 13); + + expect(spy.callCount).to.equal(1, 'konami code should fire'); }); - it('should allow you to create an empty mousetrap constructor', function() { - var spy = sinon.spy(); + it('sequence timer resets', function () { + var spy = sinon.spy(); + var clock = sinon.useFakeTimers(); - var mousetrap = new Mousetrap(); - mousetrap.bind('a', spy); + Mousetrap.bind('h a t', spy); - KeyEvent.simulate('a'.charCodeAt(0), 65); + KeyEvent.simulate('h'.charCodeAt(0), 72); + clock.tick(600); + KeyEvent.simulate('a'.charCodeAt(0), 65); + clock.tick(900); + KeyEvent.simulate('t'.charCodeAt(0), 84); - expect(spy.callCount).to.equal(1, 'callback should fire once'); - expect(spy.args[0][0]).to.be.an.instanceOf(Event, 'first argument should be Event'); - expect(spy.args[0][1]).to.equal('a', 'second argument should be key combo'); + expect(spy.callCount).to.equal(1, 'sequence should fire after waiting'); + clock.restore(); }); -}); -describe('Mouestrap.addKeycodes', function() { - it('should properly recognize non-default mapping', function() { + it('sequences timeout', function () { + var spy = sinon.spy(); + var clock = sinon.useFakeTimers(); + + Mousetrap.bind('g t', spy); + KeyEvent.simulate('g'.charCodeAt(0), 71); + clock.tick(1000); + KeyEvent.simulate('t'.charCodeAt(0), 84); + + expect(spy.callCount).to.equal(0, 'sequence callback should not fire'); + clock.restore(); + }); + }); + + describe('default actions', function () { + var keys = { + keypress: [ + ['a', 65], + ['A', 65, ['shift']], + ['7', 55], + ['?', 191], + ['*', 56], + ['+', 187], + ['$', 52], + ['[', 219], + ['.', 190] + ], + keydown: [ + ['shift+\'', 222, ['shift']], + ['shift+a', 65, ['shift']], + ['shift+5', 53, ['shift']], + ['command+shift+p', 80, ['meta', 'shift']], + ['space', 32], + ['left', 37] + ] + }; + + function getCallback(key, keyCode, type, modifiers) { + return function () { var spy = sinon.spy(); + Mousetrap.bind(key, spy); + + KeyEvent.simulate(key.charCodeAt(0), keyCode, modifiers); + expect(spy.callCount).to.equal(1); + expect(spy.args[0][0].type).to.equal(type); + }; + } + + for (var type in keys) { + for (var i = 0; i < keys[type].length; i++) { + var key = keys[type][i][0]; + var keyCode = keys[type][i][1]; + var modifiers = keys[type][i][2] || []; + it('"' + key + '" uses "' + type + '"', getCallback(key, keyCode, type, modifiers)); + } + } + }); +}); + +describe('Mousetrap.unbind', function () { + it('unbind works', function () { + var spy = sinon.spy(); + Mousetrap.bind('a', spy); + KeyEvent.simulate('a'.charCodeAt(0), 65); + expect(spy.callCount).to.equal(1, 'callback for a should fire'); + + Mousetrap.unbind('a'); + KeyEvent.simulate('a'.charCodeAt(0), 65); + expect(spy.callCount).to.equal(1, 'callback for a should not fire after unbind'); + }); + + it('unbind accepts an array', function () { + var spy = sinon.spy(); + Mousetrap.bind(['a', 'b', 'c'], spy); + KeyEvent.simulate('a'.charCodeAt(0), 65); + KeyEvent.simulate('b'.charCodeAt(0), 66); + KeyEvent.simulate('c'.charCodeAt(0), 67); + expect(spy.callCount).to.equal(3, 'callback should have fired 3 times'); + + Mousetrap.unbind(['a', 'b', 'c']); + KeyEvent.simulate('a'.charCodeAt(0), 65); + KeyEvent.simulate('b'.charCodeAt(0), 66); + KeyEvent.simulate('c'.charCodeAt(0), 67); + expect(spy.callCount).to.equal(3, 'callback should not fire after unbind'); + }); +}); + +describe('wrapping a specific element', function () { + // Prepare the DOM for these tests. + document.body.insertAdjacentHTML('afterbegin', ` +
+ +
+ `); + + var form = document.querySelector('form'); + var textarea = form.querySelector('textarea'); + + it('z key fires when pressing z in the target element', function () { + var spy = sinon.spy(); + + Mousetrap(form).bind('z', spy); - Mousetrap.addKeycodes({ - 144: 'num', - }); + KeyEvent.simulate('Z'.charCodeAt(0), 90, [], form); - Mousetrap.bind('num', spy); + expect(spy.callCount).to.equal(1, 'callback should fire once'); + expect(spy.args[0][0]).to.be.an.instanceOf(Event, 'first argument should be Event'); + expect(spy.args[0][1]).to.equal('z', 'second argument should be key combo'); + }); - KeyEvent.simulate(144, 144); - expect(spy.callCount).to.equal(1, 'callback should fire for num'); + it('z key fires when pressing z in a child of the target element', function () { + var spy = sinon.spy(); - spy.reset(); + Mousetrap(form).bind('z', spy); + + KeyEvent.simulate('Z'.charCodeAt(0), 90, [], textarea); + + expect(spy.callCount).to.equal(1, 'callback should fire once'); + expect(spy.args[0][0]).to.be.an.instanceOf(Event, 'first argument should be Event'); + expect(spy.args[0][1]).to.equal('z', 'second argument should be key combo'); + }); + + it('z key does not fire when pressing z outside the target element', function () { + var spy = sinon.spy(); + + Mousetrap(textarea).bind('z', spy); + + KeyEvent.simulate('Z'.charCodeAt(0), 90); + + expect(spy.callCount).to.equal(0, 'callback should not have fired'); + }); + + it('should work when constructing a new mousetrap object', function () { + var spy = sinon.spy(); + + var mousetrap = new Mousetrap(form); + mousetrap.bind('a', spy); + + KeyEvent.simulate('a'.charCodeAt(0), 65, [], textarea); + + expect(spy.callCount).to.equal(1, 'callback should fire once'); + expect(spy.args[0][0]).to.be.an.instanceOf(Event, 'first argument should be Event'); + expect(spy.args[0][1]).to.equal('a', 'second argument should be key combo'); + }); + + it('should allow you to create an empty mousetrap constructor', function () { + var spy = sinon.spy(); + + var mousetrap = new Mousetrap(); + mousetrap.bind('a', spy); + + KeyEvent.simulate('a'.charCodeAt(0), 65); + + expect(spy.callCount).to.equal(1, 'callback should fire once'); + expect(spy.args[0][0]).to.be.an.instanceOf(Event, 'first argument should be Event'); + expect(spy.args[0][1]).to.equal('a', 'second argument should be key combo'); + }); +}); + +describe('Mouestrap.addKeycodes', function () { + it('should properly recognize non-default mapping', function () { + const spy = sinon.spy(); + + Mousetrap.addKeycodes({ + 144: 'num', }); + + Mousetrap.bind('num', spy); + + KeyEvent.simulate(144, 144); + expect(spy.callCount).to.equal(1, 'callback should fire for num'); + + spy.resetHistory(); + }); }); From e939c112dc797fcd7f9296a984a949c4a0fc3a46 Mon Sep 17 00:00:00 2001 From: Craig Campbell Date: Thu, 31 Jan 2019 13:43:05 -0500 Subject: [PATCH 3/8] Change reporter back to nyan cat --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e6879fa3..fc53a215 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "test": "tests" }, "scripts": { - "test": "mocha tests/test.mousetrap.js" + "test": "mocha --reporter=nyan tests/test.mousetrap.js" }, "repository": { "type": "git", From 30edb2edd188750ad1161ef88c08c7cd1cc00140 Mon Sep 17 00:00:00 2001 From: Craig Campbell Date: Thu, 31 Jan 2019 13:45:32 -0500 Subject: [PATCH 4/8] Add npm package lock file --- package-lock.json | 1979 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1979 insertions(+) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..42369898 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1979 @@ +{ + "name": "mousetrap", + "version": "1.6.2", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@sinonjs/commons": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.3.0.tgz", + "integrity": "sha512-j4ZwhaHmwsCb4DlDOIWnI5YyKDNMoNThsmwEpfHx6a1EpsGZ9qYLxP++LMlmBRjtGptGHFsGItJ768snllFWpA==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/formatio": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.1.0.tgz", + "integrity": "sha512-ZAR2bPHOl4Xg6eklUGpsdiIJ4+J1SNag1DHHrG/73Uz/nVwXqjgUtRPLoS+aVyieN9cSbc0E4LsU984tWcDyNg==", + "dev": true, + "requires": { + "@sinonjs/samsam": "^2 || ^3" + } + }, + "@sinonjs/samsam": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.0.2.tgz", + "integrity": "sha512-m08g4CS3J6lwRQk1pj1EO+KEVWbrbXsmi9Pw0ySmrIbcVxVaedoFgLvFsV8wHLwh01EpROVz3KvVcD1Jmks9FQ==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.0.2", + "array-from": "^2.1.1", + "lodash.get": "^4.4.2" + } + }, + "abab": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz", + "integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w==", + "dev": true + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "acorn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.6.tgz", + "integrity": "sha512-5M3G/A4uBSMIlfJ+h9W125vJvPFH/zirISsW5qfxF5YzEvXJCtolLoQvM5yZft0DvMcUrPGKPOlgEu55I6iUtA==", + "dev": true + }, + "acorn-globals": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.0.tgz", + "integrity": "sha512-hMtHj3s5RnuhvHPowpBYvJVj3rAar82JiDQHvGs1zO0l10ocX/xEdBShNHTJaboucJUsScghp74pH3s7EnHHQw==", + "dev": true, + "requires": { + "acorn": "^6.0.1", + "acorn-walk": "^6.0.1" + } + }, + "acorn-walk": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.1.1.tgz", + "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==", + "dev": true + }, + "ajv": { + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.5.tgz", + "integrity": "sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + }, + "dependencies": { + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + } + } + }, + "array-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.0.tgz", + "integrity": "sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-from": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", + "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "async-limiter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", + "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-process-hrtime": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", + "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", + "dev": true + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "coffeescript": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.10.0.tgz", + "integrity": "sha1-56qDAZF+9iGzXYo580jc3R234z4=", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colors": { + "version": "1.1.2", + "resolved": "http://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cssom": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.4.tgz", + "integrity": "sha512-+7prCSORpXNeR4/fUP3rL+TzqtiFfhMvTd7uEqMdgPvLPt4+uzFUeufx5RHjGTACCargg/DiEt/moMQmvnfkog==", + "dev": true + }, + "cssstyle": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.1.1.tgz", + "integrity": "sha512-364AI1l/M5TYcFH83JnOH/pSqgaNnKmYgKrm0didZMGKWjQB60dymwWy1rKUgL3J1ffdq9xVi2yGLHdSjjSNog==", + "dev": true, + "requires": { + "cssom": "0.3.x" + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-urls": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz", + "integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "whatwg-mimetype": "^2.2.0", + "whatwg-url": "^7.0.0" + } + }, + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1", + "meow": "^3.3.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "domexception": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz", + "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==", + "dev": true, + "requires": { + "webidl-conversions": "^4.0.2" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escodegen": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.11.0.tgz", + "integrity": "sha512-IeMV45ReixHS53K/OmfKAIztN/igDHzTJUhZM3k1jMhIZWjk45SMwAtBsEXiJp3vSPmTcu6CXn7mDvFHRN66fw==", + "dev": true, + "requires": { + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + } + } + }, + "escomplex-plugin-metrics-module": { + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/escomplex-plugin-metrics-module/-/escomplex-plugin-metrics-module-0.0.13.tgz", + "integrity": "sha1-uj/ir5obBi3uDhMJO3HtOJodcWg=", + "dev": true, + "requires": { + "typhonjs-escomplex-commons": "^0.0.16" + } + }, + "escomplex-plugin-metrics-project": { + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/escomplex-plugin-metrics-project/-/escomplex-plugin-metrics-project-0.0.13.tgz", + "integrity": "sha1-cDSXc/DEsZPVjyHqEDLRN1vvD0U=", + "dev": true, + "requires": { + "typhonjs-escomplex-commons": "^0.0.16" + } + }, + "escomplex-plugin-syntax-babylon": { + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/escomplex-plugin-syntax-babylon/-/escomplex-plugin-syntax-babylon-0.0.13.tgz", + "integrity": "sha1-bh8pnyAR1IfdK0rOtxQ4SKC/23I=", + "dev": true, + "requires": { + "escomplex-plugin-syntax-estree": "^0.0.13", + "typhonjs-escomplex-commons": "^0.0.16" + } + }, + "escomplex-plugin-syntax-estree": { + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/escomplex-plugin-syntax-estree/-/escomplex-plugin-syntax-estree-0.0.13.tgz", + "integrity": "sha1-/BKGZxuMpo8fC4Abc2SwNBgvIUU=", + "dev": true, + "requires": { + "typhonjs-escomplex-commons": "^0.0.16" + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "eventemitter2": { + "version": "0.4.14", + "resolved": "http://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", + "dev": true + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "findup-sync": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", + "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", + "dev": true, + "requires": { + "glob": "~5.0.0" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs-extra": { + "version": "0.30.0", + "resolved": "http://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "getobject": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", + "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", + "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "grunt": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.3.tgz", + "integrity": "sha512-/JzmZNPfKorlCrrmxWqQO4JVodO+DVd5XX4DkocL/1WlLlKVLE9+SdEIempOAxDhWPysLle6afvn/hg7Ck2k9g==", + "dev": true, + "requires": { + "coffeescript": "~1.10.0", + "dateformat": "~1.0.12", + "eventemitter2": "~0.4.13", + "exit": "~0.1.1", + "findup-sync": "~0.3.0", + "glob": "~7.0.0", + "grunt-cli": "~1.2.0", + "grunt-known-options": "~1.1.0", + "grunt-legacy-log": "~2.0.0", + "grunt-legacy-util": "~1.1.1", + "iconv-lite": "~0.4.13", + "js-yaml": "~3.5.2", + "minimatch": "~3.0.2", + "mkdirp": "~0.5.1", + "nopt": "~3.0.6", + "path-is-absolute": "~1.0.0", + "rimraf": "~2.6.2" + }, + "dependencies": { + "grunt-cli": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz", + "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=", + "dev": true, + "requires": { + "findup-sync": "~0.3.0", + "grunt-known-options": "~1.1.0", + "nopt": "~3.0.6", + "resolve": "~1.1.0" + } + } + } + }, + "grunt-complexity": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grunt-complexity/-/grunt-complexity-1.1.0.tgz", + "integrity": "sha1-BmciEzyay++kkipHl3M2xrI7DfY=", + "dev": true, + "requires": { + "fs-extra": "~0.30.0", + "grunt": ">=0.4.x", + "lodash": "^4.15.0", + "typhonjs-escomplex": "0.0.12" + } + }, + "grunt-known-options": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.1.tgz", + "integrity": "sha512-cHwsLqoighpu7TuYj5RonnEuxGVFnztcUqTqp5rXFGYL4OuPFofwC4Ycg7n9fYwvK6F5WbYgeVOwph9Crs2fsQ==", + "dev": true + }, + "grunt-legacy-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-2.0.0.tgz", + "integrity": "sha512-1m3+5QvDYfR1ltr8hjiaiNjddxGdQWcH0rw1iKKiQnF0+xtgTazirSTGu68RchPyh1OBng1bBUjLmX8q9NpoCw==", + "dev": true, + "requires": { + "colors": "~1.1.2", + "grunt-legacy-log-utils": "~2.0.0", + "hooker": "~0.2.3", + "lodash": "~4.17.5" + } + }, + "grunt-legacy-log-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.0.1.tgz", + "integrity": "sha512-o7uHyO/J+i2tXG8r2bZNlVk20vlIFJ9IEYyHMCQGfWYru8Jv3wTqKZzvV30YW9rWEjq0eP3cflQ1qWojIe9VFA==", + "dev": true, + "requires": { + "chalk": "~2.4.1", + "lodash": "~4.17.10" + } + }, + "grunt-legacy-util": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.1.1.tgz", + "integrity": "sha512-9zyA29w/fBe6BIfjGENndwoe1Uy31BIXxTH3s8mga0Z5Bz2Sp4UCjkeyv2tI449ymkx3x26B+46FV4fXEddl5A==", + "dev": true, + "requires": { + "async": "~1.5.2", + "exit": "~0.1.1", + "getobject": "~0.1.0", + "hooker": "~0.2.3", + "lodash": "~4.17.10", + "underscore.string": "~3.3.4", + "which": "~1.3.0" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "hooker": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", + "dev": true + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, + "html-encoding-sniffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz", + "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.1" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "js-yaml": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.5.5.tgz", + "integrity": "sha1-A3fDgBfKvHMisNH7zSWkkWQfL74=", + "dev": true, + "requires": { + "argparse": "^1.0.2", + "esprima": "^2.6.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "jsdom": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-13.2.0.tgz", + "integrity": "sha512-cG1NtMWO9hWpqRNRR3dSvEQa8bFI6iLlqU2x4kwX51FQjp0qus8T9aBaAO6iGp3DeBrhdwuKxckknohkmfvsFw==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "acorn": "^6.0.4", + "acorn-globals": "^4.3.0", + "array-equal": "^1.0.0", + "cssom": "^0.3.4", + "cssstyle": "^1.1.1", + "data-urls": "^1.1.0", + "domexception": "^1.0.1", + "escodegen": "^1.11.0", + "html-encoding-sniffer": "^1.0.2", + "nwsapi": "^2.0.9", + "parse5": "5.1.0", + "pn": "^1.1.0", + "request": "^2.88.0", + "request-promise-native": "^1.0.5", + "saxes": "^3.1.5", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.5.0", + "w3c-hr-time": "^1.0.1", + "w3c-xmlserializer": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^7.0.0", + "ws": "^6.1.2", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + } + } + }, + "jsdom-global": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsdom-global/-/jsdom-global-3.0.2.tgz", + "integrity": "sha1-a9KZwTsMRiay2iwDk81DhdYGrLk=", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "just-extend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", + "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", + "dev": true + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, + "lolex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-3.0.0.tgz", + "integrity": "sha512-hcnW80h3j2lbUfFdMArd5UPA/vxZJ+G8vobd+wg3nVEQA0EigStbYcrG030FJxL6xiDDPEkoMatV9xIh5OecQQ==", + "dev": true + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "meow": { + "version": "3.7.0", + "resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" + } + }, + "mime-db": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", + "dev": true + }, + "mime-types": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "dev": true, + "requires": { + "mime-db": "~1.37.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "mocha": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "dev": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + }, + "dependencies": { + "commander": { + "version": "2.15.1", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "nise": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.8.tgz", + "integrity": "sha512-kGASVhuL4tlAV0tvA34yJYZIVihrUt/5bDwpp4tTluigxUr2bBlJeDXmivb6NuEdFkqvdv/Ybb9dm16PSKUhtw==", + "dev": true, + "requires": { + "@sinonjs/formatio": "^3.1.0", + "just-extend": "^4.0.2", + "lolex": "^2.3.2", + "path-to-regexp": "^1.7.0", + "text-encoding": "^0.6.4" + }, + "dependencies": { + "lolex": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", + "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", + "dev": true + } + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "nwsapi": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.0.9.tgz", + "integrity": "sha512-nlWFSCTYQcHk/6A9FFnfhKc14c3aFhfdNBXgo8Qgi9QTBu/qg3Ww+Uiz9wMzXd1T8GFxPc2QIHB6Qtf2XFryFQ==", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse5": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-to-regexp": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "dev": true, + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" + } + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "request-promise-core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", + "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "dev": true, + "requires": { + "lodash": "^4.13.1" + } + }, + "request-promise-native": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz", + "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=", + "dev": true, + "requires": { + "request-promise-core": "1.1.1", + "stealthy-require": "^1.1.0", + "tough-cookie": ">=2.3.3" + } + }, + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "^7.0.5" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "saxes": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-3.1.6.tgz", + "integrity": "sha512-LAYs+lChg1v5uKNzPtsgTxSS5hLo8aIhSMCJt1WMpefAxm3D1RTpMwSpb6ebdL31cubiLTnhokVktBW+cv9Y9w==", + "dev": true, + "requires": { + "xmlchars": "^1.3.1" + } + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "sinon": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.2.3.tgz", + "integrity": "sha512-i6j7sqcLEqTYqUcMV327waI745VASvYuSuQMCjbAwlpAeuCgKZ3LtrjDxAbu+GjNQR0FEDpywtwGCIh8GicNyg==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.3.0", + "@sinonjs/formatio": "^3.1.0", + "@sinonjs/samsam": "^3.0.2", + "diff": "^3.5.0", + "lolex": "^3.0.0", + "nise": "^1.4.8", + "supports-color": "^5.5.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + }, + "spdx-correct": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", + "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz", + "integrity": "sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg==", + "dev": true + }, + "sprintf-js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", + "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=", + "dev": true + }, + "sshpk": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", + "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stealthy-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", + "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", + "dev": true + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "symbol-tree": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz", + "integrity": "sha1-rifbOPZgp64uHDt9G8KQgZuFGeY=", + "dev": true + }, + "text-encoding": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", + "dev": true + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "typhonjs-ast-walker": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/typhonjs-ast-walker/-/typhonjs-ast-walker-0.1.1.tgz", + "integrity": "sha1-gUVUptrSnhyyy2K8io6GwXTBaOM=", + "dev": true + }, + "typhonjs-escomplex": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/typhonjs-escomplex/-/typhonjs-escomplex-0.0.12.tgz", + "integrity": "sha1-wrDlpzOdeG3d03R7FT5/ZDPx/iA=", + "dev": true, + "requires": { + "babylon": "^6.0.0", + "commander": "^2.0.0", + "typhonjs-escomplex-module": "^0.0.12", + "typhonjs-escomplex-project": "^0.0.12" + } + }, + "typhonjs-escomplex-commons": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/typhonjs-escomplex-commons/-/typhonjs-escomplex-commons-0.0.16.tgz", + "integrity": "sha1-5oTo3ITTxsyVmKbb1hS3A/hqfUk=", + "dev": true + }, + "typhonjs-escomplex-module": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/typhonjs-escomplex-module/-/typhonjs-escomplex-module-0.0.12.tgz", + "integrity": "sha1-xZm7PeKzj/LYMmJa7iwgXxUxvmE=", + "dev": true, + "requires": { + "escomplex-plugin-metrics-module": "^0.0.13", + "escomplex-plugin-syntax-babylon": "^0.0.13", + "typhonjs-ast-walker": "^0.1.0", + "typhonjs-escomplex-commons": "^0.0.16", + "typhonjs-plugin-manager": "^0.0.3" + } + }, + "typhonjs-escomplex-project": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/typhonjs-escomplex-project/-/typhonjs-escomplex-project-0.0.12.tgz", + "integrity": "sha1-EKHWvzJ/czOKG9eHFZ/GMka5x5g=", + "dev": true, + "requires": { + "escomplex-plugin-metrics-project": "^0.0.13", + "typhonjs-escomplex-commons": "^0.0.16", + "typhonjs-escomplex-module": "^0.0.12", + "typhonjs-plugin-manager": "^0.0.3" + } + }, + "typhonjs-plugin-manager": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/typhonjs-plugin-manager/-/typhonjs-plugin-manager-0.0.3.tgz", + "integrity": "sha1-hN1eHQG0QRm95JPqZW3O+JJVq4Q=", + "dev": true + }, + "underscore.string": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.5.tgz", + "integrity": "sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg==", + "dev": true, + "requires": { + "sprintf-js": "^1.0.3", + "util-deprecate": "^1.0.2" + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "w3c-hr-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", + "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "dev": true, + "requires": { + "browser-process-hrtime": "^0.1.2" + } + }, + "w3c-xmlserializer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-1.0.1.tgz", + "integrity": "sha512-XZGI1OH/OLQr/NaJhhPmzhngwcAnZDLytsvXnRmlYeRkmbb0I7sqFFA22erq4WQR0sUu17ZSQOAV9mFwCqKRNg==", + "dev": true, + "requires": { + "domexception": "^1.0.1", + "webidl-conversions": "^4.0.2", + "xml-name-validator": "^3.0.0" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.0.0.tgz", + "integrity": "sha512-37GeVSIJ3kn1JgKyjiYNmSLP1yzbpb29jdmwBSgkD9h40/hyrR/OifpVUndji3tmwGgD8qpw7iQu3RSbCrBpsQ==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "ws": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.3.tgz", + "integrity": "sha512-tbSxiT+qJI223AP4iLfQbkbxkwdFcneYinM2+x46Gx2wgvbaOMO36czfdfVUBRTHvzAMRhDd98sA5d/BuWbQdg==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "xmlchars": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-1.3.1.tgz", + "integrity": "sha512-tGkGJkN8XqCod7OT+EvGYK5Z4SfDQGD30zAa58OcnAa0RRWgzUEK72tkXhsX1FZd+rgnhRxFtmO+ihkp8LHSkw==", + "dev": true + } + } +} From 6254001877bec03e120fa2dc7b61f2164fba492f Mon Sep 17 00:00:00 2001 From: Craig Campbell Date: Thu, 31 Jan 2019 13:46:23 -0500 Subject: [PATCH 5/8] Add mousetrap sublime project file --- .gitignore | 1 + mousetrap.sublime-project | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 mousetrap.sublime-project diff --git a/.gitignore b/.gitignore index 3c3629e6..008b790e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +*.sublime-workspace diff --git a/mousetrap.sublime-project b/mousetrap.sublime-project new file mode 100644 index 00000000..6ad21c02 --- /dev/null +++ b/mousetrap.sublime-project @@ -0,0 +1,20 @@ +{ + "settings": + { + "detect_indentation": true, + "ensure_newline_at_eof_on_save": true, + "tab_size": 4, + "translate_tabs_to_spaces": true, + "trim_automatic_white_space": false, + "trim_trailing_white_space_on_save": true, + }, + "folders": + [ + { + "path": "./", + "folder_exclude_patterns": ["bin", "coverage", "node_modules"], + "file_exclude_patterns": ["*.sublime-workspace"] + } + ] +} + From f681459dd996abc4a7072595bc89357e0671832e Mon Sep 17 00:00:00 2001 From: kleinfreund Date: Tue, 27 Nov 2018 11:08:26 +0100 Subject: [PATCH 6/8] Stop callbacks from inside a shadow tree when appropriate --- mousetrap.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/mousetrap.js b/mousetrap.js index eea6f61e..404a5366 100644 --- a/mousetrap.js +++ b/mousetrap.js @@ -982,6 +982,20 @@ return false; } + // Events originating from a shadow DOM are re-targetted and `e.target` is the shadow host, + // not the initial event target in the shadow tree. Note that not all events cross the + // shadow boundary. + // For shadow trees with `mode: 'open'`, the initial event target is the first element in + // the event’s composed path. For shadow trees with `mode: 'closed'`, the initial event + // target cannot be obtained. + if ('composedPath' in e && typeof e.composedPath === 'function') { + // For open shadow trees, update `element` so that the following check works. + var initialEventTarget = e.composedPath()[0]; + if (initialEventTarget !== e.target) { + element = initialEventTarget; + } + } + // stop for input, select, and textarea return element.tagName == 'INPUT' || element.tagName == 'SELECT' || element.tagName == 'TEXTAREA' || element.isContentEditable; }; From 49580b9e461c2440f3a21e754b634542f348bc82 Mon Sep 17 00:00:00 2001 From: kleinfreund Date: Tue, 27 Nov 2018 11:08:38 +0100 Subject: [PATCH 7/8] Add tests for shadow DOM handling --- tests/libs/key-event.js | 19 ++++++++++++++++++- tests/test.mousetrap.js | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/tests/libs/key-event.js b/tests/libs/key-event.js index d71748bf..91030588 100644 --- a/tests/libs/key-event.js +++ b/tests/libs/key-event.js @@ -46,7 +46,7 @@ // simulates complete key event as if the user pressed the key in the browser // triggers a keydown, then a keypress, then a keyup - KeyEvent.simulate = function(charCode, keyCode, modifiers, element, repeat) { + KeyEvent.simulate = function(charCode, keyCode, modifiers, element, repeat, options) { if (modifiers === undefined) { modifiers = []; } @@ -59,6 +59,23 @@ repeat = 1; } + if (options === undefined) { + options = {}; + } + + // Re-target the element so that `event.target` becomes the shadow host. See: + // https://developers.google.com/web/fundamentals/web-components/shadowdom#events + // This is a bit of a lie because true events would re-target the event target both for + // closed and open shadow trees. `KeyEvent` is not a true event and will fire the event + // directly from the shadow host for closed shadow trees. For open trees, this would make + // the tests fail as the actual event that will be eventually dispatched would have an + // incorrect `Event.composedPath()` starting with the shadow host instead of the + // initial event target. + if (options.shadowHost && options.shadowHost.shadowRoot === null) { + // closed shadow dom + element = options.shadowHost; + } + var modifierToKeyCode = { 'shift': 16, 'ctrl': 17, diff --git a/tests/test.mousetrap.js b/tests/test.mousetrap.js index fa3ce747..e2c1d147 100644 --- a/tests/test.mousetrap.js +++ b/tests/test.mousetrap.js @@ -87,7 +87,41 @@ describe('Mousetrap.bind', function () { } }); - it('keyup events should fire', function () { + it('z key does not fire when inside an input element in an open shadow dom', function() { + var spy = sinon.spy(); + + var shadowHost = document.createElement('div'); + var shadowRoot = shadowHost.attachShadow({ mode: 'open' }); + document.body.appendChild(shadowHost); + + var inputElement = document.createElement('input'); + shadowRoot.appendChild(inputElement); + expect(shadowHost.shadowRoot).to.equal(shadowRoot, 'shadow root accessible'); + + Mousetrap.bind('z', spy); + KeyEvent.simulate('Z'.charCodeAt(0), 90, [], inputElement, 1, { shadowHost: shadowHost }); + document.body.removeChild(shadowHost); + expect(spy.callCount).to.equal(0, 'callback should not have fired'); + }); + + it('z key does fire when inside an input element in a closed shadow dom', function() { + var spy = sinon.spy(); + + var shadowHost = document.createElement('div'); + var shadowRoot = shadowHost.attachShadow({ mode: 'closed' }); + document.body.appendChild(shadowHost); + + var inputElement = document.createElement('input'); + shadowRoot.appendChild(inputElement); + expect(shadowHost.shadowRoot).to.equal(null, 'shadow root unaccessible'); + + Mousetrap.bind('z', spy); + KeyEvent.simulate('Z'.charCodeAt(0), 90, [], inputElement, 1, { shadowHost: shadowHost }); + document.body.removeChild(shadowHost); + expect(spy.callCount).to.equal(1, 'callback should have fired once'); + }); + + it('keyup events should fire', function() { var spy = sinon.spy(); Mousetrap.bind('z', spy, 'keyup'); From 6833a231bd2ac7363b6c393cc4b765adad4901ea Mon Sep 17 00:00:00 2001 From: Craig Campbell Date: Mon, 4 Mar 2019 12:09:20 -0500 Subject: [PATCH 8/8] Update version to 1.6.3 --- mousetrap.js | 2 +- mousetrap.min.js | 22 +++++++++++----------- package-lock.json | 2 +- package.json | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/mousetrap.js b/mousetrap.js index 404a5366..66257606 100644 --- a/mousetrap.js +++ b/mousetrap.js @@ -17,7 +17,7 @@ * Mousetrap is a simple keyboard shortcut library for Javascript with * no external dependencies * - * @version 1.6.2 + * @version 1.6.3 * @url craig.is/killing/mice */ (function(window, document, undefined) { diff --git a/mousetrap.min.js b/mousetrap.min.js index 105ae55b..35660c4d 100644 --- a/mousetrap.min.js +++ b/mousetrap.min.js @@ -1,11 +1,11 @@ -/* mousetrap v1.6.2 craig.is/killing/mice */ -(function(p,t,h){function u(a,b,d){a.addEventListener?a.addEventListener(b,d,!1):a.attachEvent("on"+b,d)}function y(a){if("keypress"==a.type){var b=String.fromCharCode(a.which);a.shiftKey||(b=b.toLowerCase());return b}return m[a.which]?m[a.which]:q[a.which]?q[a.which]:String.fromCharCode(a.which).toLowerCase()}function E(a){var b=[];a.shiftKey&&b.push("shift");a.altKey&&b.push("alt");a.ctrlKey&&b.push("ctrl");a.metaKey&&b.push("meta");return b}function v(a){return"shift"==a||"ctrl"==a||"alt"==a|| -"meta"==a}function z(a,b){var d,e=[];var c=a;"+"===c?c=["+"]:(c=c.replace(/\+{2}/g,"+plus"),c=c.split("+"));for(d=0;dh||m.hasOwnProperty(h)&&(n[m[h]]=h)}d=n[c]?"keydown":"keypress"}"keypress"==d&&e.length&&(d="keydown");return{key:k,modifiers:e,action:d}}function C(a,b){return null===a||a===t?!1:a===b?!0:C(a.parentNode,b)}function e(a){function b(a){a= -a||{};var b=!1,l;for(l in n)a[l]?b=!0:n[l]=0;b||(w=!1)}function d(a,b,r,g,F,e){var l,D=[],h=r.type;if(!f._callbacks[a])return[];"keyup"==h&&v(a)&&(b=[a]);for(l=0;l":".","?":"/","|":"\\"},A={option:"alt",command:"meta","return":"enter", -escape:"esc",plus:"+",mod:/Mac|iPod|iPhone|iPad/.test(navigator.platform)?"meta":"ctrl"},n;for(h=1;20>h;++h)m[111+h]="f"+h;for(h=0;9>=h;++h)m[h+96]=h.toString();e.prototype.bind=function(a,b,d){a=a instanceof Array?a:[a];this._bindMultiple.call(this,a,b,d);return this};e.prototype.unbind=function(a,b){return this.bind.call(this,a,function(){},b)};e.prototype.trigger=function(a,b){if(this._directMap[a+":"+b])this._directMap[a+":"+b]({},a);return this};e.prototype.reset=function(){this._callbacks={}; -this._directMap={};return this};e.prototype.stopCallback=function(a,b){return-1<(" "+b.className+" ").indexOf(" mousetrap ")||C(b,this.target)?!1:"INPUT"==b.tagName||"SELECT"==b.tagName||"TEXTAREA"==b.tagName||b.isContentEditable};e.prototype.handleKey=function(){return this._handleKey.apply(this,arguments)};e.addKeycodes=function(a){for(var b in a)a.hasOwnProperty(b)&&(m[b]=a[b]);n=null};e.init=function(){var a=e(t),b;for(b in a)"_"!==b.charAt(0)&&(e[b]=function(b){return function(){return a[b].apply(a, -arguments)}}(b))};e.init();p.Mousetrap=e;"undefined"!==typeof module&&module.exports&&(module.exports=e);"function"===typeof define&&define.amd&&define(function(){return e})}})("undefined"!==typeof window?window:null,"undefined"!==typeof window?document:null); +/* mousetrap v1.6.3 craig.is/killing/mice */ +(function(q,u,c){function v(a,b,g){a.addEventListener?a.addEventListener(b,g,!1):a.attachEvent("on"+b,g)}function z(a){if("keypress"==a.type){var b=String.fromCharCode(a.which);a.shiftKey||(b=b.toLowerCase());return b}return n[a.which]?n[a.which]:r[a.which]?r[a.which]:String.fromCharCode(a.which).toLowerCase()}function F(a){var b=[];a.shiftKey&&b.push("shift");a.altKey&&b.push("alt");a.ctrlKey&&b.push("ctrl");a.metaKey&&b.push("meta");return b}function w(a){return"shift"==a||"ctrl"==a||"alt"==a|| +"meta"==a}function A(a,b){var g,d=[];var e=a;"+"===e?e=["+"]:(e=e.replace(/\+{2}/g,"+plus"),e=e.split("+"));for(g=0;gc||n.hasOwnProperty(c)&&(p[n[c]]=c)}g=p[e]?"keydown":"keypress"}"keypress"==g&&d.length&&(g="keydown");return{key:m,modifiers:d,action:g}}function D(a,b){return null===a||a===u?!1:a===b?!0:D(a.parentNode,b)}function d(a){function b(a){a= +a||{};var b=!1,l;for(l in p)a[l]?b=!0:p[l]=0;b||(x=!1)}function g(a,b,t,f,g,d){var l,E=[],h=t.type;if(!k._callbacks[a])return[];"keyup"==h&&w(a)&&(b=[a]);for(l=0;l":".","?":"/","|":"\\"},B={option:"alt",command:"meta","return":"enter", +escape:"esc",plus:"+",mod:/Mac|iPod|iPhone|iPad/.test(navigator.platform)?"meta":"ctrl"},p;for(c=1;20>c;++c)n[111+c]="f"+c;for(c=0;9>=c;++c)n[c+96]=c.toString();d.prototype.bind=function(a,b,c){a=a instanceof Array?a:[a];this._bindMultiple.call(this,a,b,c);return this};d.prototype.unbind=function(a,b){return this.bind.call(this,a,function(){},b)};d.prototype.trigger=function(a,b){if(this._directMap[a+":"+b])this._directMap[a+":"+b]({},a);return this};d.prototype.reset=function(){this._callbacks={}; +this._directMap={};return this};d.prototype.stopCallback=function(a,b){if(-1<(" "+b.className+" ").indexOf(" mousetrap ")||D(b,this.target))return!1;if("composedPath"in a&&"function"===typeof a.composedPath){var c=a.composedPath()[0];c!==a.target&&(b=c)}return"INPUT"==b.tagName||"SELECT"==b.tagName||"TEXTAREA"==b.tagName||b.isContentEditable};d.prototype.handleKey=function(){return this._handleKey.apply(this,arguments)};d.addKeycodes=function(a){for(var b in a)a.hasOwnProperty(b)&&(n[b]=a[b]);p=null}; +d.init=function(){var a=d(u),b;for(b in a)"_"!==b.charAt(0)&&(d[b]=function(b){return function(){return a[b].apply(a,arguments)}}(b))};d.init();q.Mousetrap=d;"undefined"!==typeof module&&module.exports&&(module.exports=d);"function"===typeof define&&define.amd&&define(function(){return d})}})("undefined"!==typeof window?window:null,"undefined"!==typeof window?document:null); diff --git a/package-lock.json b/package-lock.json index 42369898..6aa58d08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mousetrap", - "version": "1.6.2", + "version": "1.6.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index fc53a215..81c55e6a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mousetrap", - "version": "1.6.2", + "version": "1.6.3", "description": "Simple library for handling keyboard shortcuts", "main": "mousetrap.js", "directories": {