├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── example ├── dinosaurs │ └── index.js ├── robots │ ├── index.js │ ├── problem.txt │ └── solution.txt ├── runner.js └── wowsers │ ├── index.js │ ├── problem.txt │ └── solution.txt ├── index.js ├── lib ├── help.js ├── menu.js └── usage.txt ├── package-lock.json ├── package.json ├── readme.markdown └── test ├── adventure.js └── menu.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 12 4 | - 11 5 | - 10 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This software is released under the MIT license: 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /example/dinosaurs/index.js: -------------------------------------------------------------------------------- 1 | exports.problem = 'Make a dinosaur sound.\n' 2 | + 'Use `$ADVENTURE_COMMAND verify YOUR_TEXT...` to make your sound.' 3 | ; 4 | 5 | exports.verify = function (args, cb) { 6 | if (/RAWR/.test(args)) { 7 | console.log('Wow that is a convincing dinosaur.\n'); 8 | cb(true); 9 | } 10 | else if (/rawr/i.test(args)) { 11 | console.log('Close, but too quiet. Try louder.\n'); 12 | cb(false); 13 | } 14 | else { 15 | console.log("That doesn't sound like a dinosaur at all.\n"); 16 | cb(false); 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /example/robots/index.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | 4 | exports.problem = fs.createReadStream(__dirname + '/problem.txt'); 5 | exports.solution = fs.createReadStream(__dirname + '/solution.txt'); 6 | 7 | exports.verify = function (args, cb) { 8 | var res = require(path.resolve(args[0])); 9 | if (/beep/.test(res) && /boop/.test(res)) { 10 | console.log('That sounds about right!\n'); 11 | cb(true); 12 | } 13 | else if (/beep/.test(res) || /boop/.test(res)) { 14 | console.log('Hmm that sounds partly convincing but try harder.\n'); 15 | cb(false); 16 | } 17 | else { 18 | console.log("That doesn't sound like a robot at all.\n"); 19 | cb(false); 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /example/robots/problem.txt: -------------------------------------------------------------------------------- 1 | Write a program that exports a string containing a sound a robot would be likely 2 | to make. Here's some boilerplate code you can use to get started: 3 | 4 | module.exports = 'your sound goes here...' 5 | 6 | Save that code into a file, YOUR_PROGRAM.js (you can name it whatever you like) 7 | and then: 8 | 9 | Use `$ADVENTURE_COMMAND verify YOUR_PROGRAM.js` to verify your program. 10 | Use `$ADVENTURE_COMMAND run YOUR_PROGRAM.js` to run your program. 11 | 12 | -------------------------------------------------------------------------------- /example/robots/solution.txt: -------------------------------------------------------------------------------- 1 | Here's the reference solution, if you're interested: 2 | 3 | module.exports = 'beep boop' 4 | 5 | But your solution is probably good too. 6 | -------------------------------------------------------------------------------- /example/runner.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var adventure = require('../'); 4 | var shop = adventure('example-adventure'); 5 | 6 | shop.add('dinosaurs', function () { return require('./dinosaurs') }); 7 | shop.add('robots', function () { return require('./robots') }); 8 | shop.add('wowsers', function () { return require('./wowsers') }); 9 | 10 | shop.execute(process.argv.slice(2)); 11 | -------------------------------------------------------------------------------- /example/wowsers/index.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | var verify = require('adventure-verify'); 4 | 5 | exports.problem = fs.createReadStream(__dirname + '/problem.txt'); 6 | exports.solution = fs.createReadStream(__dirname + '/solution.txt'); 7 | 8 | exports.verify = verify({ modeReset: true }, function (args, t) { 9 | var f = require(path.resolve(args[0])); 10 | t.equal(typeof f, 'function', 'you exported a function'); 11 | t.equal(f(2,3), 6, '2 * 3 = 6'); 12 | t.equal(f(1,1), 1, '1 * 1 = 1'); 13 | t.equal(f(0.5,0.5), 0.25, '0.5 * 0.5 = 0.25'); 14 | t.end(); 15 | }); 16 | -------------------------------------------------------------------------------- /example/wowsers/problem.txt: -------------------------------------------------------------------------------- 1 | Write a program that exports a single function to multiple 2 arguments. 2 | 3 | Here is some boilerplate code to get you started: 4 | 5 | module.exports = function (a, b) { 6 | // ... 7 | } 8 | 9 | Use `$ADVENTURE_COMMAND verify PROGRAM.js` to verify your program. 10 | -------------------------------------------------------------------------------- /example/wowsers/solution.txt: -------------------------------------------------------------------------------- 1 | Here is the reference solution, if you're curious: 2 | 3 | module.exports = function (a, b) { 4 | return a * b 5 | } 6 | 7 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var inherits = require('inherits'); 2 | var EventEmitter = require('events').EventEmitter; 3 | var mkdirp = require('mkdirp'); 4 | var fs = require('fs'); 5 | var path = require('path'); 6 | var x256 = require('x256'); 7 | var through = require('through2'); 8 | var split = require('split'); 9 | var minimist = require('minimist'); 10 | 11 | var showMenu = require('./lib/menu.js'); 12 | var showHelp = require('./lib/help.js'); 13 | 14 | module.exports = Shop; 15 | inherits(Shop, EventEmitter); 16 | 17 | function Shop (opts) { 18 | if (!(this instanceof Shop)) return new Shop(opts); 19 | if (!opts) opts = {}; 20 | if (typeof opts === 'string') opts = { name: opts }; 21 | 22 | this.name = opts.name; 23 | this.options = opts; 24 | 25 | if (!this.name) return this._error( 26 | 'Your adventure must have a name! ' 27 | + 'Supply an `opts.name` to adventure().' 28 | ); 29 | this.command = opts.command || commandify(this.name); 30 | 31 | this.datadir = opts.datadir || path.resolve( 32 | process.env.HOME || process.env.USERPROFILE, 33 | '.config/' + this.name 34 | ); 35 | mkdirp.sync(this.datadir); 36 | 37 | this.files = { 38 | completed: path.join(this.datadir, 'completed.json'), 39 | current: path.join(this.datadir, 'current.json') 40 | }; 41 | this.state = { 42 | completed: [], 43 | current: null 44 | }; 45 | 46 | try { this.state.completed = require(this.files.completed) } 47 | catch (err) {} 48 | 49 | try { this.state.current = require(this.files.current) } 50 | catch (err) {} 51 | 52 | this.colors = opts.colors || {}; 53 | var c = { 54 | pass: [0,255,0], 55 | fail: [255,0,0], 56 | info: [0,255,255] 57 | }; 58 | var colors = Object.keys(c).reduce(function (acc, key) { 59 | acc[key] = '\x1b[38;5;' + x256(c[key]) + 'm'; 60 | return acc; 61 | }, {}); 62 | 63 | if (!this.colors.pass) this.colors.pass = colors.pass; 64 | if (!this.colors.fail) this.colors.fail = colors.fail; 65 | if (!this.colors.info) this.colors.info = colors.info; 66 | this.colors.reset = '\x1b[00m'; 67 | 68 | this._adventures = []; 69 | } 70 | 71 | Shop.prototype.execute = function (args) { 72 | var cmd = args[0]; 73 | var argv = minimist(args, { alias: { h: 'help' } }); 74 | 75 | if (cmd === 'verify') { 76 | this.verify(args.slice(1), this.state.current); 77 | } 78 | else if (cmd === 'run') { 79 | this.run(args.slice(1), this.state.current); 80 | } 81 | else if (cmd === 'help' || argv.help) { 82 | showHelp({ command: this.command }); 83 | } 84 | else if (cmd === 'selected') { 85 | console.log(this.state.current); 86 | } 87 | else if (cmd === 'list') { 88 | console.log(this._adventures 89 | .map(function (adv) { return adv.name }) 90 | .join('\n') 91 | ); 92 | } 93 | else if (cmd === 'completed') { 94 | console.log(this.state.completed.join('\n')); 95 | } 96 | else if (cmd === 'select') { 97 | this.select(args[1]); 98 | } 99 | else if (cmd === 'print') { 100 | this.select(this.state.current); 101 | } 102 | else if (cmd === 'next' || cmd === 'prev') { 103 | var names = this._adventures 104 | .map(function (adv) { return adv.name }) 105 | ; 106 | var ix = names.indexOf(this.state.current); 107 | if (cmd === 'next') ix ++ 108 | else if (cmd === 'prev') ix -- 109 | if (names[ix]) this.select(names[ix]) 110 | } 111 | else if (cmd === 'solution') { 112 | var adv = this.find(this.state.current); 113 | if (!adv) { 114 | return console.log( 115 | 'No adventure is currently selected. ' 116 | + 'Select an adventure from the menu.' 117 | ); 118 | process.exit(1); 119 | } 120 | var p = adv.fn(); 121 | if (p.solution) this._show(p.solution); 122 | else console.log('No reference solution available for this adventure.') 123 | } 124 | else if (cmd === 'reset') { 125 | this.state.completed = []; 126 | this.save('completed'); 127 | this.state.current = null; 128 | this.save('current'); 129 | } 130 | else if (!cmd || cmd === 'menu') { 131 | this.showMenu(this.options); 132 | } 133 | else { 134 | console.log('unrecognized command: ' + cmd); 135 | } 136 | }; 137 | 138 | Shop.prototype.add = function (name, fn) { 139 | this._adventures.push({ name: name, fn: fn }); 140 | }; 141 | 142 | Shop.prototype.find = function (name) { 143 | for (var i = 0; i < this._adventures.length; i++) { 144 | var adv = this._adventures[i]; 145 | if (norm(adv.name) === norm(name)) return adv; 146 | } 147 | function norm (s) { return String(s).replace(/\W/g, '').toLowerCase() } 148 | }; 149 | 150 | Shop.prototype.verify = function (args, name) { 151 | var self = this; 152 | var adv = this.find(name); 153 | if (!adv) return this._error( 154 | 'No adventure is currently selected. ' 155 | + 'Select an adventure from the menu.' 156 | ); 157 | var p = adv.fn(); 158 | if (!p.verify) return this._error( 159 | "This problem doesn't have a .verify function yet!" 160 | ); 161 | if (typeof p.verify !== 'function') return this._error( 162 | 'This p.verify is a ' + typeof p.verify 163 | + '. It should be a function instead.' 164 | ); 165 | 166 | var s = p.verify(args, function (ok) { 167 | if (ok) self.pass(name, p) 168 | else self.fail(name, p) 169 | }); 170 | if (s) this._show(s); 171 | }; 172 | 173 | Shop.prototype.run = function (args, name) { 174 | var self = this; 175 | var adv = this.find(name); 176 | if (!adv) return this._error( 177 | 'No adventure is currently selected. ' 178 | + 'Select an adventure from the menu.' 179 | ); 180 | var p = adv.fn(); 181 | if (!p.run) return this._error( 182 | "This problem doesn't have a .run function." 183 | ); 184 | if (typeof p.run !== 'function') return this._error( 185 | 'This p.run is a ' + typeof p.run 186 | + '. It should be a function instead.' 187 | ); 188 | var s = p.run(args); 189 | if (s) this._show(s); 190 | }; 191 | 192 | Shop.prototype.pass = function (name, p) { 193 | var ix = this.state.completed.indexOf(name); 194 | if (ix < 0) this.state.completed.push(name); 195 | this.save('completed'); 196 | 197 | if (p.pass) { 198 | this._show(p.pass); 199 | console.log(); 200 | } 201 | else { 202 | console.log( 203 | '\n' + this.colors.pass 204 | + '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@' 205 | ); 206 | console.log( 207 | '@@@' + this.colors.reset 208 | + ' YOUR SOLUTION IS CORRECT' 209 | + this.colors.pass + '! @@@' 210 | ); 211 | console.log('@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'); 212 | console.log(this.colors.reset + '\n'); 213 | } 214 | if (p.solution) this._show(p.solution); 215 | 216 | this.emit('pass', name); 217 | if (this.state.completed.length === this._adventures.length) { 218 | this.emit('finished'); 219 | } 220 | }; 221 | 222 | Shop.prototype.fail = function (name, p) { 223 | if (p.fail) { 224 | this._show(p.fail); 225 | console.log(); 226 | } 227 | else { 228 | console.log( 229 | this.colors.fail 230 | + '#########################################' 231 | ); 232 | console.log( 233 | '###' + this.colors.reset 234 | + ' YOUR SOLUTION IS NOT CORRECT!' 235 | + this.colors.fail + ' ###' 236 | ); 237 | console.log('#########################################'); 238 | console.log(this.colors.reset + '\n'); 239 | } 240 | this.emit('fail', name); 241 | }; 242 | 243 | Shop.prototype.select = function (name) { 244 | var adv = this.find(name); 245 | this.state.current = name; 246 | this.save('current'); 247 | 248 | var p = adv.fn(); 249 | if (!p.problem) { 250 | p.problem = this.colors.info + Array(67).join('!') + '\n' 251 | + '!!!' + this.colors.reset 252 | + ' This adventure does not have a .problem description yet! ' 253 | + this.colors.info + ' !!!\n!!!' + this.colors.reset 254 | + ' Set .problem to a string, buffer, stream or function that' 255 | + this.colors.info + ' !!!\n!!!' + this.colors.reset 256 | + ' returns a string, buffer, or stream. ' 257 | + this.colors.info + ' !!!\n' + Array(67).join('!') + '\n' 258 | ; 259 | } 260 | if (p.problem) this._show(p.problem); 261 | }; 262 | 263 | Shop.prototype.showMenu = function (opts) { 264 | var self = this; 265 | if (!opts) opts = {}; 266 | 267 | var menu = showMenu({ 268 | fg: opts.fg, 269 | bg: opts.bg, 270 | autoclose: typeof opts.autoclose === 'boolean' ? opts.autoclose : true, 271 | command: this.command, 272 | title: opts.title || this.name.toUpperCase(), 273 | names: this._adventures.map(function (x) { return x.name }), 274 | completed: this.state.completed 275 | }); 276 | menu.on('select', function (name) { 277 | console.log(); 278 | self.select(name); 279 | }); 280 | menu.on('exit', function () { 281 | menu.close(); 282 | console.log(); 283 | }); 284 | return menu; 285 | }; 286 | 287 | Shop.prototype.save = function (key) { 288 | fs.writeFile( 289 | this.files[key], 290 | JSON.stringify(this.state[key]), 291 | function(){} 292 | ); 293 | }; 294 | 295 | Shop.prototype._error = function (msg) { 296 | console.error('ERROR: ' + msg); 297 | process.exit(1); 298 | }; 299 | 300 | Shop.prototype._show = function (m) { 301 | var self = this; 302 | if (typeof m === 'object' && m.pipe) { 303 | m.pipe(split()).pipe(through(write)).pipe(process.stdout); 304 | } 305 | else if (typeof m === 'function') { 306 | this._show(m()); 307 | } 308 | else console.log(replace(m)); 309 | 310 | function write (buf, enc, next) { 311 | this.push(replace(buf) + '\n'); 312 | next(); 313 | } 314 | function replace (s) { 315 | if (typeof s !== 'string') s = String(s); 316 | return s 317 | .replace(/\$ADVENTURE_COMMAND/g, self.command) 318 | .replace(/\$ADVENTURE_NAME/g, self.name) 319 | ; 320 | } 321 | } 322 | 323 | function commandify (s) { 324 | return String(s).toLowerCase().replace(/\s+/g, '-'); 325 | } 326 | -------------------------------------------------------------------------------- /lib/help.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var split = require('split'); 3 | var through = require('through2'); 4 | 5 | module.exports = function (opts) { 6 | fs.createReadStream(__dirname + '/usage.txt') 7 | .pipe(through(function (buf, enc, next) { 8 | var line = buf.toString('utf8') 9 | .replace(/\$COMMAND/g, opts.command) 10 | ; 11 | this.push(line + '\n'); 12 | next(); 13 | })) 14 | .pipe(process.stdout) 15 | ; 16 | }; 17 | -------------------------------------------------------------------------------- /lib/menu.js: -------------------------------------------------------------------------------- 1 | var tmenu = require('terminal-menu'); 2 | var path = require('path'); 3 | var EventEmitter = require('events').EventEmitter; 4 | var showHelp = require('./help.js'); 5 | 6 | module.exports = function (opts) { 7 | var emitter = new EventEmitter; 8 | 9 | var menu = tmenu({ 10 | width: 65, 11 | x: 3, y: 2, 12 | bg: opts.bg || 'blue', 13 | fg: opts.fg || 'white' 14 | }); 15 | 16 | menu.reset(); 17 | 18 | var title = opts.title || 'UNTITLED\n'; 19 | menu.write(title + '\n'); 20 | menu.write(Array(title.length+1).join('-') + '\n'); 21 | 22 | (opts.names || []).forEach(function (name) { 23 | var isDone = (opts.completed || []).indexOf(name) >= 0; 24 | if (isDone) { 25 | var m = '[COMPLETED]'; 26 | menu.add( 27 | name 28 | + Array(65 - m.length - name.length + 1).join(' ') 29 | + m 30 | ); 31 | } 32 | else menu.add(name); 33 | }); 34 | menu.write('-----------------\n'); 35 | menu.add('HELP'); 36 | menu.add('EXIT'); 37 | 38 | menu.on('select', function (label) { 39 | var name = label.replace(/\s{2}.*/, ''); 40 | 41 | menu.close(); 42 | if (name === 'EXIT') { 43 | return emitter.emit('exit'); 44 | } 45 | else if (name === 'HELP') { 46 | console.log(); 47 | showHelp(opts); 48 | } 49 | else emitter.emit('select', name); 50 | }); 51 | 52 | if (!process.env.TEST) { 53 | process.stdin.setRawMode(true); 54 | process.stdin.pipe(menu.createStream()).pipe(process.stdout); 55 | } 56 | 57 | menu.once('close', function () { 58 | process.stdin.setRawMode(false); 59 | if (opts.autoclose) { 60 | process.stdin.destroy(); 61 | } 62 | }); 63 | emitter.menu = menu; 64 | emitter.close = function () { menu.close() }; 65 | 66 | return emitter; 67 | }; 68 | -------------------------------------------------------------------------------- /lib/usage.txt: -------------------------------------------------------------------------------- 1 | $COMMAND 2 | $COMMAND menu 3 | 4 | Show the menu. 5 | 6 | $COMMAND verify [ARGS...] 7 | 8 | Verify the currently selected problem with ARGS. 9 | 10 | $COMMAND run [ARGS...] 11 | 12 | Run the currently selected problem with ARGS. 13 | Not all problems support `run`. 14 | 15 | $COMMAND solution 16 | 17 | Show the solution for the currently selected problem. 18 | 19 | $COMMAND print 20 | 21 | Print the text of the currently selected level. 22 | 23 | $COMMAND selected 24 | 25 | Print the name of the currently selected level. 26 | 27 | $COMMAND select LEVEL 28 | 29 | Set the currently selected LEVEL. 30 | 31 | $COMMAND list 32 | 33 | List the available levels. 34 | 35 | $COMMAND next 36 | 37 | Select the next adventure. 38 | 39 | $COMMAND prev 40 | 41 | Select the previous adventure. 42 | 43 | $COMMAND completed 44 | 45 | List the completed levels. 46 | 47 | $COMMAND reset 48 | 49 | Reset the list of completed levels. 50 | 51 | $COMMAND help 52 | 53 | Show this message. 54 | 55 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "adventure", 3 | "version": "2.11.2", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@sinonjs/commons": { 8 | "version": "1.4.0", 9 | "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.4.0.tgz", 10 | "integrity": "sha512-9jHK3YF/8HtJ9wCAbG+j8cD0i0+ATS9A7gXFqS36TblLPNy6rEEc+SB0imo91eCboGaBYGV/MT1/br/J+EE7Tw==", 11 | "dev": true, 12 | "requires": { 13 | "type-detect": "4.0.8" 14 | } 15 | }, 16 | "@sinonjs/formatio": { 17 | "version": "3.2.1", 18 | "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.1.tgz", 19 | "integrity": "sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==", 20 | "dev": true, 21 | "requires": { 22 | "@sinonjs/commons": "^1", 23 | "@sinonjs/samsam": "^3.1.0" 24 | } 25 | }, 26 | "@sinonjs/samsam": { 27 | "version": "3.3.2", 28 | "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.2.tgz", 29 | "integrity": "sha512-ILO/rR8LfAb60Y1Yfp9vxfYAASK43NFC2mLzpvLUbCQY/Qu8YwReboseu8aheCEkyElZF2L2T9mHcR2bgdvZyA==", 30 | "dev": true, 31 | "requires": { 32 | "@sinonjs/commons": "^1.0.2", 33 | "array-from": "^2.1.1", 34 | "lodash": "^4.17.11" 35 | } 36 | }, 37 | "@sinonjs/text-encoding": { 38 | "version": "0.7.1", 39 | "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", 40 | "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", 41 | "dev": true 42 | }, 43 | "adventure-verify": { 44 | "version": "2.2.0", 45 | "resolved": "https://registry.npmjs.org/adventure-verify/-/adventure-verify-2.2.0.tgz", 46 | "integrity": "sha1-AxHUSEZJobFPoOBVR81pZnNGKvs=", 47 | "dev": true, 48 | "requires": { 49 | "tap-colorize": "^1.1.0", 50 | "tap-parser": "~0.5.0", 51 | "tape": "^2.13.2" 52 | } 53 | }, 54 | "ansi-colors": { 55 | "version": "3.2.3", 56 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", 57 | "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", 58 | "dev": true 59 | }, 60 | "ansi-regex": { 61 | "version": "3.0.0", 62 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 63 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 64 | "dev": true 65 | }, 66 | "ansi-styles": { 67 | "version": "3.2.1", 68 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 69 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 70 | "dev": true, 71 | "requires": { 72 | "color-convert": "^1.9.0" 73 | } 74 | }, 75 | "argparse": { 76 | "version": "1.0.10", 77 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 78 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 79 | "dev": true, 80 | "requires": { 81 | "sprintf-js": "~1.0.2" 82 | } 83 | }, 84 | "array-from": { 85 | "version": "2.1.1", 86 | "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", 87 | "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", 88 | "dev": true 89 | }, 90 | "balanced-match": { 91 | "version": "1.0.0", 92 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 93 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 94 | "dev": true 95 | }, 96 | "brace-expansion": { 97 | "version": "1.1.11", 98 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 99 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 100 | "dev": true, 101 | "requires": { 102 | "balanced-match": "^1.0.0", 103 | "concat-map": "0.0.1" 104 | } 105 | }, 106 | "browser-stdout": { 107 | "version": "1.3.1", 108 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 109 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 110 | "dev": true 111 | }, 112 | "camelcase": { 113 | "version": "5.3.1", 114 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 115 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 116 | "dev": true 117 | }, 118 | "chalk": { 119 | "version": "2.4.2", 120 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 121 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 122 | "dev": true, 123 | "requires": { 124 | "ansi-styles": "^3.2.1", 125 | "escape-string-regexp": "^1.0.5", 126 | "supports-color": "^5.3.0" 127 | }, 128 | "dependencies": { 129 | "supports-color": { 130 | "version": "5.5.0", 131 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 132 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 133 | "dev": true, 134 | "requires": { 135 | "has-flag": "^3.0.0" 136 | } 137 | } 138 | } 139 | }, 140 | "charm": { 141 | "version": "0.1.2", 142 | "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", 143 | "integrity": "sha1-BsIe7RobBq62dVPNxT4jJ0usIpY=" 144 | }, 145 | "cliui": { 146 | "version": "4.1.0", 147 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", 148 | "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", 149 | "dev": true, 150 | "requires": { 151 | "string-width": "^2.1.1", 152 | "strip-ansi": "^4.0.0", 153 | "wrap-ansi": "^2.0.0" 154 | } 155 | }, 156 | "code-point-at": { 157 | "version": "1.1.0", 158 | "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", 159 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", 160 | "dev": true 161 | }, 162 | "color-convert": { 163 | "version": "1.9.3", 164 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 165 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 166 | "dev": true, 167 | "requires": { 168 | "color-name": "1.1.3" 169 | } 170 | }, 171 | "color-name": { 172 | "version": "1.1.3", 173 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 174 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 175 | "dev": true 176 | }, 177 | "colornames": { 178 | "version": "0.0.2", 179 | "resolved": "https://registry.npmjs.org/colornames/-/colornames-0.0.2.tgz", 180 | "integrity": "sha1-2BH9bIT1kClJmorEQ2ICk1uSvjE=", 181 | "dev": true 182 | }, 183 | "concat-map": { 184 | "version": "0.0.1", 185 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 186 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 187 | "dev": true 188 | }, 189 | "core-util-is": { 190 | "version": "1.0.2", 191 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 192 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 193 | }, 194 | "cross-spawn": { 195 | "version": "6.0.5", 196 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", 197 | "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", 198 | "dev": true, 199 | "requires": { 200 | "nice-try": "^1.0.4", 201 | "path-key": "^2.0.1", 202 | "semver": "^5.5.0", 203 | "shebang-command": "^1.2.0", 204 | "which": "^1.2.9" 205 | } 206 | }, 207 | "debug": { 208 | "version": "3.2.6", 209 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 210 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 211 | "dev": true, 212 | "requires": { 213 | "ms": "^2.1.1" 214 | } 215 | }, 216 | "decamelize": { 217 | "version": "1.2.0", 218 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 219 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 220 | "dev": true 221 | }, 222 | "deep-equal": { 223 | "version": "0.2.2", 224 | "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-0.2.2.tgz", 225 | "integrity": "sha1-hLdFiW80xoTpjyzg5Cq69Du6AX0=", 226 | "dev": true 227 | }, 228 | "define-properties": { 229 | "version": "1.1.3", 230 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 231 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 232 | "dev": true, 233 | "requires": { 234 | "object-keys": "^1.0.12" 235 | }, 236 | "dependencies": { 237 | "object-keys": { 238 | "version": "1.1.1", 239 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 240 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 241 | "dev": true 242 | } 243 | } 244 | }, 245 | "defined": { 246 | "version": "0.0.0", 247 | "resolved": "https://registry.npmjs.org/defined/-/defined-0.0.0.tgz", 248 | "integrity": "sha1-817qfXBekzuvE7LwOz+D2SFAOz4=", 249 | "dev": true 250 | }, 251 | "diff": { 252 | "version": "3.5.0", 253 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", 254 | "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", 255 | "dev": true 256 | }, 257 | "duplexer": { 258 | "version": "0.1.1", 259 | "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", 260 | "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", 261 | "dev": true 262 | }, 263 | "duplexer2": { 264 | "version": "0.0.2", 265 | "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", 266 | "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", 267 | "requires": { 268 | "readable-stream": "~1.1.9" 269 | } 270 | }, 271 | "emoji-regex": { 272 | "version": "7.0.3", 273 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 274 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", 275 | "dev": true 276 | }, 277 | "end-of-stream": { 278 | "version": "1.4.1", 279 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", 280 | "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", 281 | "dev": true, 282 | "requires": { 283 | "once": "^1.4.0" 284 | } 285 | }, 286 | "es-abstract": { 287 | "version": "1.13.0", 288 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", 289 | "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", 290 | "dev": true, 291 | "requires": { 292 | "es-to-primitive": "^1.2.0", 293 | "function-bind": "^1.1.1", 294 | "has": "^1.0.3", 295 | "is-callable": "^1.1.4", 296 | "is-regex": "^1.0.4", 297 | "object-keys": "^1.0.12" 298 | }, 299 | "dependencies": { 300 | "has": { 301 | "version": "1.0.3", 302 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 303 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 304 | "dev": true, 305 | "requires": { 306 | "function-bind": "^1.1.1" 307 | } 308 | }, 309 | "object-keys": { 310 | "version": "1.1.1", 311 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 312 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 313 | "dev": true 314 | } 315 | } 316 | }, 317 | "es-to-primitive": { 318 | "version": "1.2.0", 319 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", 320 | "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", 321 | "dev": true, 322 | "requires": { 323 | "is-callable": "^1.1.4", 324 | "is-date-object": "^1.0.1", 325 | "is-symbol": "^1.0.2" 326 | } 327 | }, 328 | "escape-string-regexp": { 329 | "version": "1.0.5", 330 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 331 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 332 | "dev": true 333 | }, 334 | "esprima": { 335 | "version": "4.0.1", 336 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 337 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 338 | "dev": true 339 | }, 340 | "execa": { 341 | "version": "1.0.0", 342 | "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", 343 | "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", 344 | "dev": true, 345 | "requires": { 346 | "cross-spawn": "^6.0.0", 347 | "get-stream": "^4.0.0", 348 | "is-stream": "^1.1.0", 349 | "npm-run-path": "^2.0.0", 350 | "p-finally": "^1.0.0", 351 | "signal-exit": "^3.0.0", 352 | "strip-eof": "^1.0.0" 353 | } 354 | }, 355 | "find-up": { 356 | "version": "3.0.0", 357 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 358 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 359 | "dev": true, 360 | "requires": { 361 | "locate-path": "^3.0.0" 362 | } 363 | }, 364 | "flat": { 365 | "version": "4.1.0", 366 | "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", 367 | "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", 368 | "dev": true, 369 | "requires": { 370 | "is-buffer": "~2.0.3" 371 | } 372 | }, 373 | "fs.realpath": { 374 | "version": "1.0.0", 375 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 376 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 377 | "dev": true 378 | }, 379 | "function-bind": { 380 | "version": "1.1.1", 381 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 382 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 383 | "dev": true 384 | }, 385 | "get-caller-file": { 386 | "version": "2.0.5", 387 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 388 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 389 | "dev": true 390 | }, 391 | "get-stream": { 392 | "version": "4.1.0", 393 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", 394 | "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", 395 | "dev": true, 396 | "requires": { 397 | "pump": "^3.0.0" 398 | } 399 | }, 400 | "glob": { 401 | "version": "3.2.11", 402 | "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", 403 | "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", 404 | "dev": true, 405 | "requires": { 406 | "inherits": "2", 407 | "minimatch": "0.3" 408 | } 409 | }, 410 | "growl": { 411 | "version": "1.10.5", 412 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 413 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 414 | "dev": true 415 | }, 416 | "has": { 417 | "version": "0.0.1", 418 | "resolved": "https://registry.npmjs.org/has/-/has-0.0.1.tgz", 419 | "integrity": "sha1-ZmOcFOr1WfE52ivg5DiRDvP9Wxs=", 420 | "dev": true 421 | }, 422 | "has-flag": { 423 | "version": "3.0.0", 424 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 425 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 426 | "dev": true 427 | }, 428 | "has-symbols": { 429 | "version": "1.0.0", 430 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", 431 | "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", 432 | "dev": true 433 | }, 434 | "he": { 435 | "version": "1.2.0", 436 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 437 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 438 | "dev": true 439 | }, 440 | "inflight": { 441 | "version": "1.0.6", 442 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 443 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 444 | "dev": true, 445 | "requires": { 446 | "once": "^1.3.0", 447 | "wrappy": "1" 448 | } 449 | }, 450 | "inherits": { 451 | "version": "2.0.4", 452 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 453 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 454 | }, 455 | "invert-kv": { 456 | "version": "2.0.0", 457 | "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", 458 | "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", 459 | "dev": true 460 | }, 461 | "is-buffer": { 462 | "version": "2.0.3", 463 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", 464 | "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", 465 | "dev": true 466 | }, 467 | "is-callable": { 468 | "version": "1.1.4", 469 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", 470 | "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", 471 | "dev": true 472 | }, 473 | "is-date-object": { 474 | "version": "1.0.1", 475 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", 476 | "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", 477 | "dev": true 478 | }, 479 | "is-fullwidth-code-point": { 480 | "version": "2.0.0", 481 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 482 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 483 | "dev": true 484 | }, 485 | "is-regex": { 486 | "version": "1.0.4", 487 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", 488 | "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", 489 | "dev": true, 490 | "requires": { 491 | "has": "^1.0.1" 492 | }, 493 | "dependencies": { 494 | "has": { 495 | "version": "1.0.3", 496 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 497 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 498 | "dev": true, 499 | "requires": { 500 | "function-bind": "^1.1.1" 501 | } 502 | } 503 | } 504 | }, 505 | "is-stream": { 506 | "version": "1.1.0", 507 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 508 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", 509 | "dev": true 510 | }, 511 | "is-symbol": { 512 | "version": "1.0.2", 513 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", 514 | "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", 515 | "dev": true, 516 | "requires": { 517 | "has-symbols": "^1.0.0" 518 | } 519 | }, 520 | "isarray": { 521 | "version": "0.0.1", 522 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 523 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" 524 | }, 525 | "isexe": { 526 | "version": "2.0.0", 527 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 528 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 529 | "dev": true 530 | }, 531 | "js-yaml": { 532 | "version": "3.13.1", 533 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", 534 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", 535 | "dev": true, 536 | "requires": { 537 | "argparse": "^1.0.7", 538 | "esprima": "^4.0.0" 539 | } 540 | }, 541 | "just-extend": { 542 | "version": "4.0.2", 543 | "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", 544 | "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", 545 | "dev": true 546 | }, 547 | "lcid": { 548 | "version": "2.0.0", 549 | "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", 550 | "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", 551 | "dev": true, 552 | "requires": { 553 | "invert-kv": "^2.0.0" 554 | } 555 | }, 556 | "locate-path": { 557 | "version": "3.0.0", 558 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 559 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 560 | "dev": true, 561 | "requires": { 562 | "p-locate": "^3.0.0", 563 | "path-exists": "^3.0.0" 564 | } 565 | }, 566 | "lodash": { 567 | "version": "4.17.15", 568 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 569 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", 570 | "dev": true 571 | }, 572 | "log-symbols": { 573 | "version": "2.2.0", 574 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", 575 | "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", 576 | "dev": true, 577 | "requires": { 578 | "chalk": "^2.0.1" 579 | } 580 | }, 581 | "lolex": { 582 | "version": "4.1.0", 583 | "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.1.0.tgz", 584 | "integrity": "sha512-BYxIEXiVq5lGIXeVHnsFzqa1TxN5acnKnPCdlZSpzm8viNEOhiigupA4vTQ9HEFQ6nLTQ9wQOgBknJgzUYQ9Aw==", 585 | "dev": true 586 | }, 587 | "lru-cache": { 588 | "version": "2.7.3", 589 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", 590 | "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", 591 | "dev": true 592 | }, 593 | "map-age-cleaner": { 594 | "version": "0.1.3", 595 | "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", 596 | "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", 597 | "dev": true, 598 | "requires": { 599 | "p-defer": "^1.0.0" 600 | } 601 | }, 602 | "mem": { 603 | "version": "4.3.0", 604 | "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", 605 | "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", 606 | "dev": true, 607 | "requires": { 608 | "map-age-cleaner": "^0.1.1", 609 | "mimic-fn": "^2.0.0", 610 | "p-is-promise": "^2.0.0" 611 | } 612 | }, 613 | "mimic-fn": { 614 | "version": "2.1.0", 615 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", 616 | "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", 617 | "dev": true 618 | }, 619 | "minimatch": { 620 | "version": "0.3.0", 621 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", 622 | "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", 623 | "dev": true, 624 | "requires": { 625 | "lru-cache": "2", 626 | "sigmund": "~1.0.0" 627 | } 628 | }, 629 | "minimist": { 630 | "version": "1.2.3", 631 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.3.tgz", 632 | "integrity": "sha512-+bMdgqjMN/Z77a6NlY/I3U5LlRDbnmaAk6lDveAPKwSpcPM4tKAuYsvYF8xjhOPXhOYGe/73vVLVez5PW+jqhw==" 633 | }, 634 | "mkdirp": { 635 | "version": "0.5.1", 636 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 637 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 638 | "requires": { 639 | "minimist": "0.0.8" 640 | }, 641 | "dependencies": { 642 | "minimist": { 643 | "version": "0.0.8", 644 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 645 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" 646 | } 647 | } 648 | }, 649 | "mocha": { 650 | "version": "6.2.0", 651 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz", 652 | "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==", 653 | "dev": true, 654 | "requires": { 655 | "ansi-colors": "3.2.3", 656 | "browser-stdout": "1.3.1", 657 | "debug": "3.2.6", 658 | "diff": "3.5.0", 659 | "escape-string-regexp": "1.0.5", 660 | "find-up": "3.0.0", 661 | "glob": "7.1.3", 662 | "growl": "1.10.5", 663 | "he": "1.2.0", 664 | "js-yaml": "3.13.1", 665 | "log-symbols": "2.2.0", 666 | "minimatch": "3.0.4", 667 | "mkdirp": "0.5.1", 668 | "ms": "2.1.1", 669 | "node-environment-flags": "1.0.5", 670 | "object.assign": "4.1.0", 671 | "strip-json-comments": "2.0.1", 672 | "supports-color": "6.0.0", 673 | "which": "1.3.1", 674 | "wide-align": "1.1.3", 675 | "yargs": "13.2.2", 676 | "yargs-parser": "13.0.0", 677 | "yargs-unparser": "1.5.0" 678 | }, 679 | "dependencies": { 680 | "glob": { 681 | "version": "7.1.3", 682 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", 683 | "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", 684 | "dev": true, 685 | "requires": { 686 | "fs.realpath": "^1.0.0", 687 | "inflight": "^1.0.4", 688 | "inherits": "2", 689 | "minimatch": "^3.0.4", 690 | "once": "^1.3.0", 691 | "path-is-absolute": "^1.0.0" 692 | } 693 | }, 694 | "minimatch": { 695 | "version": "3.0.4", 696 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 697 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 698 | "dev": true, 699 | "requires": { 700 | "brace-expansion": "^1.1.7" 701 | } 702 | } 703 | } 704 | }, 705 | "ms": { 706 | "version": "2.1.1", 707 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 708 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", 709 | "dev": true 710 | }, 711 | "nice-try": { 712 | "version": "1.0.5", 713 | "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", 714 | "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", 715 | "dev": true 716 | }, 717 | "nise": { 718 | "version": "1.5.0", 719 | "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.0.tgz", 720 | "integrity": "sha512-Z3sfYEkLFzFmL8KY6xnSJLRxwQwYBjOXi/24lb62ZnZiGA0JUzGGTI6TBIgfCSMIDl9Jlu8SRmHNACLTemDHww==", 721 | "dev": true, 722 | "requires": { 723 | "@sinonjs/formatio": "^3.1.0", 724 | "@sinonjs/text-encoding": "^0.7.1", 725 | "just-extend": "^4.0.2", 726 | "lolex": "^4.1.0", 727 | "path-to-regexp": "^1.7.0" 728 | } 729 | }, 730 | "node-environment-flags": { 731 | "version": "1.0.5", 732 | "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", 733 | "integrity": "sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ==", 734 | "dev": true, 735 | "requires": { 736 | "object.getownpropertydescriptors": "^2.0.3", 737 | "semver": "^5.7.0" 738 | } 739 | }, 740 | "npm-run-path": { 741 | "version": "2.0.2", 742 | "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", 743 | "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", 744 | "dev": true, 745 | "requires": { 746 | "path-key": "^2.0.0" 747 | } 748 | }, 749 | "number-is-nan": { 750 | "version": "1.0.1", 751 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", 752 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", 753 | "dev": true 754 | }, 755 | "object-inspect": { 756 | "version": "1.6.0", 757 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", 758 | "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==", 759 | "dev": true 760 | }, 761 | "object-keys": { 762 | "version": "0.4.0", 763 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", 764 | "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", 765 | "dev": true 766 | }, 767 | "object.assign": { 768 | "version": "4.1.0", 769 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", 770 | "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", 771 | "dev": true, 772 | "requires": { 773 | "define-properties": "^1.1.2", 774 | "function-bind": "^1.1.1", 775 | "has-symbols": "^1.0.0", 776 | "object-keys": "^1.0.11" 777 | }, 778 | "dependencies": { 779 | "object-keys": { 780 | "version": "1.1.1", 781 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 782 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 783 | "dev": true 784 | } 785 | } 786 | }, 787 | "object.getownpropertydescriptors": { 788 | "version": "2.0.3", 789 | "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", 790 | "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", 791 | "dev": true, 792 | "requires": { 793 | "define-properties": "^1.1.2", 794 | "es-abstract": "^1.5.1" 795 | } 796 | }, 797 | "once": { 798 | "version": "1.4.0", 799 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 800 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 801 | "dev": true, 802 | "requires": { 803 | "wrappy": "1" 804 | } 805 | }, 806 | "os-locale": { 807 | "version": "3.1.0", 808 | "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", 809 | "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", 810 | "dev": true, 811 | "requires": { 812 | "execa": "^1.0.0", 813 | "lcid": "^2.0.0", 814 | "mem": "^4.0.0" 815 | } 816 | }, 817 | "p-defer": { 818 | "version": "1.0.0", 819 | "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", 820 | "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", 821 | "dev": true 822 | }, 823 | "p-finally": { 824 | "version": "1.0.0", 825 | "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", 826 | "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", 827 | "dev": true 828 | }, 829 | "p-is-promise": { 830 | "version": "2.1.0", 831 | "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", 832 | "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", 833 | "dev": true 834 | }, 835 | "p-limit": { 836 | "version": "2.2.0", 837 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", 838 | "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", 839 | "dev": true, 840 | "requires": { 841 | "p-try": "^2.0.0" 842 | } 843 | }, 844 | "p-locate": { 845 | "version": "3.0.0", 846 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 847 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 848 | "dev": true, 849 | "requires": { 850 | "p-limit": "^2.0.0" 851 | } 852 | }, 853 | "p-try": { 854 | "version": "2.2.0", 855 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 856 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 857 | "dev": true 858 | }, 859 | "path-exists": { 860 | "version": "3.0.0", 861 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 862 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 863 | "dev": true 864 | }, 865 | "path-is-absolute": { 866 | "version": "1.0.1", 867 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 868 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 869 | "dev": true 870 | }, 871 | "path-key": { 872 | "version": "2.0.1", 873 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", 874 | "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", 875 | "dev": true 876 | }, 877 | "path-to-regexp": { 878 | "version": "1.7.0", 879 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", 880 | "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", 881 | "dev": true, 882 | "requires": { 883 | "isarray": "0.0.1" 884 | } 885 | }, 886 | "pump": { 887 | "version": "3.0.0", 888 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 889 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 890 | "dev": true, 891 | "requires": { 892 | "end-of-stream": "^1.1.0", 893 | "once": "^1.3.1" 894 | } 895 | }, 896 | "quotemeta": { 897 | "version": "0.0.0", 898 | "resolved": "https://registry.npmjs.org/quotemeta/-/quotemeta-0.0.0.tgz", 899 | "integrity": "sha1-UdOgbuD81uO1AdvSiQQ1Gtelo4w=", 900 | "dev": true 901 | }, 902 | "readable-stream": { 903 | "version": "1.1.14", 904 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", 905 | "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", 906 | "requires": { 907 | "core-util-is": "~1.0.0", 908 | "inherits": "~2.0.1", 909 | "isarray": "0.0.1", 910 | "string_decoder": "~0.10.x" 911 | } 912 | }, 913 | "require-directory": { 914 | "version": "2.1.1", 915 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 916 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 917 | "dev": true 918 | }, 919 | "require-main-filename": { 920 | "version": "2.0.0", 921 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 922 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", 923 | "dev": true 924 | }, 925 | "resumer": { 926 | "version": "0.0.0", 927 | "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", 928 | "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", 929 | "requires": { 930 | "through": "~2.3.4" 931 | } 932 | }, 933 | "semver": { 934 | "version": "5.7.0", 935 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", 936 | "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", 937 | "dev": true 938 | }, 939 | "set-blocking": { 940 | "version": "2.0.0", 941 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 942 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", 943 | "dev": true 944 | }, 945 | "shebang-command": { 946 | "version": "1.2.0", 947 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 948 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", 949 | "dev": true, 950 | "requires": { 951 | "shebang-regex": "^1.0.0" 952 | } 953 | }, 954 | "shebang-regex": { 955 | "version": "1.0.0", 956 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 957 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", 958 | "dev": true 959 | }, 960 | "sigmund": { 961 | "version": "1.0.1", 962 | "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", 963 | "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", 964 | "dev": true 965 | }, 966 | "signal-exit": { 967 | "version": "3.0.2", 968 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 969 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", 970 | "dev": true 971 | }, 972 | "sinon": { 973 | "version": "7.3.2", 974 | "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.3.2.tgz", 975 | "integrity": "sha512-thErC1z64BeyGiPvF8aoSg0LEnptSaWE7YhdWWbWXgelOyThent7uKOnnEh9zBxDbKixtr5dEko+ws1sZMuFMA==", 976 | "dev": true, 977 | "requires": { 978 | "@sinonjs/commons": "^1.4.0", 979 | "@sinonjs/formatio": "^3.2.1", 980 | "@sinonjs/samsam": "^3.3.1", 981 | "diff": "^3.5.0", 982 | "lolex": "^4.0.1", 983 | "nise": "^1.4.10", 984 | "supports-color": "^5.5.0" 985 | }, 986 | "dependencies": { 987 | "supports-color": { 988 | "version": "5.5.0", 989 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 990 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 991 | "dev": true, 992 | "requires": { 993 | "has-flag": "^3.0.0" 994 | } 995 | } 996 | } 997 | }, 998 | "split": { 999 | "version": "0.3.3", 1000 | "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", 1001 | "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", 1002 | "requires": { 1003 | "through": "2" 1004 | } 1005 | }, 1006 | "sprintf-js": { 1007 | "version": "1.0.3", 1008 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1009 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 1010 | "dev": true 1011 | }, 1012 | "stream-combiner": { 1013 | "version": "0.2.2", 1014 | "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", 1015 | "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", 1016 | "dev": true, 1017 | "requires": { 1018 | "duplexer": "~0.1.1", 1019 | "through": "~2.3.4" 1020 | } 1021 | }, 1022 | "string-width": { 1023 | "version": "2.1.1", 1024 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 1025 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 1026 | "dev": true, 1027 | "requires": { 1028 | "is-fullwidth-code-point": "^2.0.0", 1029 | "strip-ansi": "^4.0.0" 1030 | } 1031 | }, 1032 | "string_decoder": { 1033 | "version": "0.10.31", 1034 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 1035 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" 1036 | }, 1037 | "strip-ansi": { 1038 | "version": "4.0.0", 1039 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 1040 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 1041 | "dev": true, 1042 | "requires": { 1043 | "ansi-regex": "^3.0.0" 1044 | } 1045 | }, 1046 | "strip-eof": { 1047 | "version": "1.0.0", 1048 | "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", 1049 | "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", 1050 | "dev": true 1051 | }, 1052 | "strip-json-comments": { 1053 | "version": "2.0.1", 1054 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 1055 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 1056 | "dev": true 1057 | }, 1058 | "supports-color": { 1059 | "version": "6.0.0", 1060 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", 1061 | "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", 1062 | "dev": true, 1063 | "requires": { 1064 | "has-flag": "^3.0.0" 1065 | } 1066 | }, 1067 | "tap-colorize": { 1068 | "version": "1.2.0", 1069 | "resolved": "https://registry.npmjs.org/tap-colorize/-/tap-colorize-1.2.0.tgz", 1070 | "integrity": "sha1-zf+kQ8c9iNWks5TBKfhzTiwyuqs=", 1071 | "dev": true, 1072 | "requires": { 1073 | "colornames": "~0.0.2", 1074 | "minimist": "~0.2.0", 1075 | "quotemeta": "0.0.0", 1076 | "split": "~0.3.0", 1077 | "stream-combiner": "~0.2.1", 1078 | "through2": "~1.0.0", 1079 | "x256": "~0.0.2" 1080 | }, 1081 | "dependencies": { 1082 | "minimist": { 1083 | "version": "0.2.1", 1084 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.1.tgz", 1085 | "integrity": "sha512-GY8fANSrTMfBVfInqJAY41QkOM+upUTytK1jZ0c8+3HdHrJxBJ3rF5i9moClXTE8uUSnUo8cAsCoxDXvSY4DHg==", 1086 | "dev": true 1087 | }, 1088 | "through2": { 1089 | "version": "1.0.0", 1090 | "resolved": "https://registry.npmjs.org/through2/-/through2-1.0.0.tgz", 1091 | "integrity": "sha1-JEXNjf50KF3uXa2gVeBXHQH/F6w=", 1092 | "dev": true, 1093 | "requires": { 1094 | "readable-stream": "~1.1.10", 1095 | "xtend": "~2.1.1" 1096 | } 1097 | }, 1098 | "xtend": { 1099 | "version": "2.1.2", 1100 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", 1101 | "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", 1102 | "dev": true, 1103 | "requires": { 1104 | "object-keys": "~0.4.0" 1105 | } 1106 | } 1107 | } 1108 | }, 1109 | "tap-parser": { 1110 | "version": "0.5.0", 1111 | "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-0.5.0.tgz", 1112 | "integrity": "sha1-pD4k0DUKmv8eRohtYPCypRR2SeM=", 1113 | "dev": true, 1114 | "requires": { 1115 | "inherits": "~2.0.1", 1116 | "readable-stream": "~1.1.11" 1117 | } 1118 | }, 1119 | "tape": { 1120 | "version": "2.14.1", 1121 | "resolved": "https://registry.npmjs.org/tape/-/tape-2.14.1.tgz", 1122 | "integrity": "sha1-j26y3QO3UKoFao3gGlRF5Z98nM4=", 1123 | "dev": true, 1124 | "requires": { 1125 | "deep-equal": "~0.2.0", 1126 | "defined": "~0.0.0", 1127 | "glob": "^3.2.9", 1128 | "has": "~0.0.1", 1129 | "inherits": "^2.0.1", 1130 | "object-inspect": "^1.0.0", 1131 | "resumer": "~0.0.0", 1132 | "through": "^2.3.4" 1133 | } 1134 | }, 1135 | "terminal-menu": { 1136 | "version": "2.1.1", 1137 | "resolved": "https://registry.npmjs.org/terminal-menu/-/terminal-menu-2.1.1.tgz", 1138 | "integrity": "sha1-uQhiCAAARHtFYBFOLSqBEf7MOnk=", 1139 | "requires": { 1140 | "charm": "~0.1.2", 1141 | "duplexer2": "0.0.2", 1142 | "inherits": "~2.0.0", 1143 | "resumer": "~0.0.0", 1144 | "through2": "^0.6.3", 1145 | "visualwidth": "~0.0.1" 1146 | }, 1147 | "dependencies": { 1148 | "readable-stream": { 1149 | "version": "1.0.34", 1150 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", 1151 | "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", 1152 | "requires": { 1153 | "core-util-is": "~1.0.0", 1154 | "inherits": "~2.0.1", 1155 | "isarray": "0.0.1", 1156 | "string_decoder": "~0.10.x" 1157 | } 1158 | }, 1159 | "through2": { 1160 | "version": "0.6.5", 1161 | "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", 1162 | "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", 1163 | "requires": { 1164 | "readable-stream": ">=1.0.33-1 <1.1.0-0", 1165 | "xtend": ">=4.0.0 <4.1.0-0" 1166 | } 1167 | } 1168 | } 1169 | }, 1170 | "through": { 1171 | "version": "2.3.8", 1172 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 1173 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" 1174 | }, 1175 | "through2": { 1176 | "version": "0.5.1", 1177 | "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", 1178 | "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", 1179 | "requires": { 1180 | "readable-stream": "~1.0.17", 1181 | "xtend": "~3.0.0" 1182 | }, 1183 | "dependencies": { 1184 | "readable-stream": { 1185 | "version": "1.0.34", 1186 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", 1187 | "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", 1188 | "requires": { 1189 | "core-util-is": "~1.0.0", 1190 | "inherits": "~2.0.1", 1191 | "isarray": "0.0.1", 1192 | "string_decoder": "~0.10.x" 1193 | } 1194 | }, 1195 | "xtend": { 1196 | "version": "3.0.0", 1197 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", 1198 | "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=" 1199 | } 1200 | } 1201 | }, 1202 | "type-detect": { 1203 | "version": "4.0.8", 1204 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 1205 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", 1206 | "dev": true 1207 | }, 1208 | "visualwidth": { 1209 | "version": "0.0.1", 1210 | "resolved": "https://registry.npmjs.org/visualwidth/-/visualwidth-0.0.1.tgz", 1211 | "integrity": "sha1-I3Z1q5pyEVY5JrpjMJRYx9qRWrc=" 1212 | }, 1213 | "which": { 1214 | "version": "1.3.1", 1215 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 1216 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 1217 | "dev": true, 1218 | "requires": { 1219 | "isexe": "^2.0.0" 1220 | } 1221 | }, 1222 | "which-module": { 1223 | "version": "2.0.0", 1224 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 1225 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", 1226 | "dev": true 1227 | }, 1228 | "wide-align": { 1229 | "version": "1.1.3", 1230 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", 1231 | "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", 1232 | "dev": true, 1233 | "requires": { 1234 | "string-width": "^1.0.2 || 2" 1235 | } 1236 | }, 1237 | "wrap-ansi": { 1238 | "version": "2.1.0", 1239 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", 1240 | "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", 1241 | "dev": true, 1242 | "requires": { 1243 | "string-width": "^1.0.1", 1244 | "strip-ansi": "^3.0.1" 1245 | }, 1246 | "dependencies": { 1247 | "ansi-regex": { 1248 | "version": "2.1.1", 1249 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 1250 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", 1251 | "dev": true 1252 | }, 1253 | "is-fullwidth-code-point": { 1254 | "version": "1.0.0", 1255 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", 1256 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 1257 | "dev": true, 1258 | "requires": { 1259 | "number-is-nan": "^1.0.0" 1260 | } 1261 | }, 1262 | "string-width": { 1263 | "version": "1.0.2", 1264 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", 1265 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 1266 | "dev": true, 1267 | "requires": { 1268 | "code-point-at": "^1.0.0", 1269 | "is-fullwidth-code-point": "^1.0.0", 1270 | "strip-ansi": "^3.0.0" 1271 | } 1272 | }, 1273 | "strip-ansi": { 1274 | "version": "3.0.1", 1275 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 1276 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 1277 | "dev": true, 1278 | "requires": { 1279 | "ansi-regex": "^2.0.0" 1280 | } 1281 | } 1282 | } 1283 | }, 1284 | "wrappy": { 1285 | "version": "1.0.2", 1286 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1287 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1288 | "dev": true 1289 | }, 1290 | "x256": { 1291 | "version": "0.0.2", 1292 | "resolved": "https://registry.npmjs.org/x256/-/x256-0.0.2.tgz", 1293 | "integrity": "sha1-ya8Yh296F1gB1WT+cK2egxd4STQ=" 1294 | }, 1295 | "xtend": { 1296 | "version": "4.0.2", 1297 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 1298 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" 1299 | }, 1300 | "y18n": { 1301 | "version": "4.0.0", 1302 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", 1303 | "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", 1304 | "dev": true 1305 | }, 1306 | "yargs": { 1307 | "version": "13.2.2", 1308 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", 1309 | "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", 1310 | "dev": true, 1311 | "requires": { 1312 | "cliui": "^4.0.0", 1313 | "find-up": "^3.0.0", 1314 | "get-caller-file": "^2.0.1", 1315 | "os-locale": "^3.1.0", 1316 | "require-directory": "^2.1.1", 1317 | "require-main-filename": "^2.0.0", 1318 | "set-blocking": "^2.0.0", 1319 | "string-width": "^3.0.0", 1320 | "which-module": "^2.0.0", 1321 | "y18n": "^4.0.0", 1322 | "yargs-parser": "^13.0.0" 1323 | }, 1324 | "dependencies": { 1325 | "ansi-regex": { 1326 | "version": "4.1.0", 1327 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 1328 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 1329 | "dev": true 1330 | }, 1331 | "string-width": { 1332 | "version": "3.1.0", 1333 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 1334 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 1335 | "dev": true, 1336 | "requires": { 1337 | "emoji-regex": "^7.0.1", 1338 | "is-fullwidth-code-point": "^2.0.0", 1339 | "strip-ansi": "^5.1.0" 1340 | } 1341 | }, 1342 | "strip-ansi": { 1343 | "version": "5.2.0", 1344 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 1345 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 1346 | "dev": true, 1347 | "requires": { 1348 | "ansi-regex": "^4.1.0" 1349 | } 1350 | } 1351 | } 1352 | }, 1353 | "yargs-parser": { 1354 | "version": "13.0.0", 1355 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", 1356 | "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", 1357 | "dev": true, 1358 | "requires": { 1359 | "camelcase": "^5.0.0", 1360 | "decamelize": "^1.2.0" 1361 | } 1362 | }, 1363 | "yargs-unparser": { 1364 | "version": "1.5.0", 1365 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", 1366 | "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", 1367 | "dev": true, 1368 | "requires": { 1369 | "flat": "^4.1.0", 1370 | "lodash": "^4.17.11", 1371 | "yargs": "^12.0.5" 1372 | }, 1373 | "dependencies": { 1374 | "get-caller-file": { 1375 | "version": "1.0.3", 1376 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", 1377 | "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", 1378 | "dev": true 1379 | }, 1380 | "require-main-filename": { 1381 | "version": "1.0.1", 1382 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", 1383 | "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", 1384 | "dev": true 1385 | }, 1386 | "yargs": { 1387 | "version": "12.0.5", 1388 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", 1389 | "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", 1390 | "dev": true, 1391 | "requires": { 1392 | "cliui": "^4.0.0", 1393 | "decamelize": "^1.2.0", 1394 | "find-up": "^3.0.0", 1395 | "get-caller-file": "^1.0.1", 1396 | "os-locale": "^3.0.0", 1397 | "require-directory": "^2.1.1", 1398 | "require-main-filename": "^1.0.1", 1399 | "set-blocking": "^2.0.0", 1400 | "string-width": "^2.0.0", 1401 | "which-module": "^2.0.0", 1402 | "y18n": "^3.2.1 || ^4.0.0", 1403 | "yargs-parser": "^11.1.1" 1404 | } 1405 | }, 1406 | "yargs-parser": { 1407 | "version": "11.1.1", 1408 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", 1409 | "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", 1410 | "dev": true, 1411 | "requires": { 1412 | "camelcase": "^5.0.0", 1413 | "decamelize": "^1.2.0" 1414 | } 1415 | } 1416 | } 1417 | } 1418 | } 1419 | } 1420 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "adventure", 3 | "version": "2.11.2", 4 | "description": "quickly hack together a nodeschool adventure", 5 | "main": "index.js", 6 | "dependencies": { 7 | "inherits": "~2.0.1", 8 | "minimist": "~1.2.3", 9 | "mkdirp": "~0.5.0", 10 | "split": "~0.3.0", 11 | "terminal-menu": "^2.1.1", 12 | "through2": "~0.5.1", 13 | "x256": "~0.0.1" 14 | }, 15 | "devDependencies": { 16 | "adventure-verify": "^2.0.0", 17 | "mocha": "^6.1.4", 18 | "sinon": "^7.3.2" 19 | }, 20 | "scripts": { 21 | "test": "TEST=1 mocha" 22 | }, 23 | "repository": { 24 | "type": "git", 25 | "url": "git://github.com/substack/adventure.git" 26 | }, 27 | "homepage": "https://github.com/substack/adventure", 28 | "keywords": [ 29 | "nodeschool", 30 | "adventure", 31 | "workshop", 32 | "education", 33 | "edutainment" 34 | ], 35 | "author": { 36 | "name": "James Halliday", 37 | "email": "mail@substack.net", 38 | "url": "http://substack.net" 39 | }, 40 | "license": "MIT" 41 | } 42 | -------------------------------------------------------------------------------- /readme.markdown: -------------------------------------------------------------------------------- 1 | # adventure 2 | 3 | quickly hack together a [nodeschool](http://nodeschool.io) adventure 4 | 5 | This is an alternative to the 6 | [workshopper](https://www.npmjs.org/package/workshopper) 7 | module, which you should also look at. 8 | 9 | `workshopper` is more convention-driven and fully-featured, but expects a 10 | particular (configurable) filesystem organization for problems. 11 | 12 | `adventure` is entirely api-driven and has fewer configuration options. 13 | 14 | # tutorial 15 | 16 | You can fork this tutorial from the 17 | [example-adventure](https://github.com/substack/example-adventure) repo. 18 | 19 | First make a `runner.js`. This is the file you can wire up to the `package.json` 20 | `"bin"` field. 21 | 22 | ``` js 23 | #!/usr/bin/env node 24 | 25 | var adventure = require('adventure'); 26 | var shop = adventure('example-adventure'); 27 | 28 | shop.add('dinosaurs', function () { return require('./dinosaurs') }); 29 | shop.add('robots', function () { return require('./robots') }); 30 | shop.add('wowsers', function () { return require('./wowsers') }); 31 | 32 | shop.execute(process.argv.slice(2)); 33 | ``` 34 | 35 | You simply `.add(name, fn)` each of the adventures in your problem set and then 36 | `.execute()` the adventure with the command-line arguments. 37 | 38 | The interface to problem files is very simple. The simplest version of a problem 39 | is just an object with a `.problem` string and `.verify` function. 40 | 41 | Here's what we can put in `dinosaurs/index.js`: 42 | 43 | ``` js 44 | exports.problem = 'Make a dinosaur sound.\n' 45 | + 'Use `$ADVENTURE_COMMAND verify YOUR_TEXT...` to make your sound.' 46 | ; 47 | 48 | exports.verify = function (args, cb) { 49 | if (/RAWR/.test(args)) { 50 | console.log('Wow that is a convincing dinosaur.\n'); 51 | cb(true); 52 | } 53 | else if (/rawr/i.test(args)) { 54 | console.log('Close, but too quiet. Try louder.\n'); 55 | cb(false); 56 | } 57 | else { 58 | console.log("That doesn't sound like a dinosaur at all.\n"); 59 | cb(false); 60 | } 61 | }; 62 | ``` 63 | 64 | You don't need to put this in a file necessarily even, you just need to return 65 | an object with these properties from the function you pass to `.add()`. 66 | 67 | Your `verify(args, cb)` function will get the arguments passed to it on the 68 | command-line and a callback that you can use to indicate whether the solution 69 | was successful or not. 70 | 71 | You can return many different kinds of objects in your `.problem` or `.solution` 72 | functions: a string, a buffer, a stream, or a function that returns a string, a 73 | buffer, or a stream. 74 | 75 | Now in `robots/index.js` we can use streams for the problem and solution: 76 | 77 | ``` js 78 | var fs = require('fs'); 79 | var path = require('path'); 80 | 81 | exports.problem = fs.createReadStream(__dirname + '/problem.txt'); 82 | exports.solution = fs.createReadStream(__dirname + '/solution.txt'); 83 | 84 | exports.verify = function (args, cb) { 85 | var res = require(path.resolve(args[0])); 86 | if (/beep/.test(res) && /boop/.test(res)) { 87 | console.log('That sounds about right!\n'); 88 | cb(true); 89 | } 90 | else if (/beep/.test(res) || /boop/.test(res)) { 91 | console.log('Hmm that sounds partly convincing but try harder.\n'); 92 | cb(false); 93 | } 94 | else { 95 | console.log("That doesn't sound like a robot at all.\n"); 96 | cb(false); 97 | } 98 | }; 99 | ``` 100 | 101 | Finally, we can use 102 | [adventure-verify](https://npmjs.org/package/adventure-verify) 103 | to verify solutions using [tape](https://npmjs.org/package/tape) with 104 | friendly [colorized tap output](https://npmjs.org/package/tap-colorize). 105 | 106 | In `wowsers/index.js` we can use 107 | [adventure-verify](https://npmjs.org/package/adventure-verify) to do: 108 | 109 | ``` js 110 | var fs = require('fs'); 111 | var path = require('path'); 112 | var verify = require('adventure-verify'); 113 | 114 | exports.problem = fs.createReadStream(__dirname + '/problem.txt'); 115 | exports.solution = fs.createReadStream(__dirname + '/solution.txt'); 116 | 117 | exports.verify = verify({ modeReset: true }, function (args, t) { 118 | var f = require(path.resolve(args[0])); 119 | t.equal(typeof f, 'function', 'you exported a function'); 120 | t.equal(f(2,3), 6, '2 * 3 = 6'); 121 | t.equal(f(1,1), 1, '1 * 1 = 1'); 122 | t.equal(f(0.5,0.5), 0.25, '0.5 * 0.5 = 0.25'); 123 | t.end(); 124 | }); 125 | ``` 126 | 127 | Here we use `modeReset` so that when a user does `console.log()` or 128 | `console.error()` in their solution, their text shows up as the terminal default 129 | instead of getting mixed up with the TAP colors. 130 | 131 | Now just fill in the `problem.txt` and `solution.txt` files and you will have a 132 | working nodeschool-style adventure! Yay! 133 | 134 | # methods 135 | 136 | ``` js 137 | var adventure = require('adventure') 138 | ``` 139 | 140 | ## var shop = adventure(opts) 141 | 142 | Create a new nodeschool workshop adventure. 143 | 144 | options are: 145 | 146 | * `opts.name` - name of your adventure (required) 147 | * `opts.command` - the name of the adventure command (inferred from `opts.name`) 148 | * `opts.title` - title to use for your adventure 149 | (default: `opts.name.toUpperCase()`) 150 | * `opts.datadir` - directory used to store the current level and the list of 151 | completed levels. default: `'~/.config/' + opts.name` 152 | 153 | * `opts.colors` - object mapping color types to `[r,g,b]` arrays 154 | * `opts.colors.pass` - show passing solution messages with this color 155 | * `opts.colors.fail` - show failing solution messages with this color 156 | * `opts.colors.info` - show extra info with this color 157 | 158 | * `opts.fg` - menu foreground color 159 | * `opts.bg` - menu background color 160 | 161 | * `opts.autoclose` - whether to close stdin automatically after the menu is 162 | shown 163 | 164 | If `opts` is a string, it will be treated as the `opts.name`. 165 | 166 | ## shop.add(name, fn) 167 | 168 | Your `fn()` should return a problem object in the format described below. 169 | 170 | ## shop.execute(args) 171 | 172 | Run whatever commands are specified in the command-line `args`. 173 | 174 | ## shop.showMenu(opts) 175 | 176 | If you don't want to let `.execute()` show the menu, you can show the menu 177 | yourself explicitly with `.showMenu()`. 178 | 179 | The options are: 180 | 181 | * `opts.fg` - foreground color 182 | * `opts.bg` - background color 183 | * `opts.title` - menu title text 184 | * `opts.autoclose` - whether to close stdin automatically after the menu is 185 | shown 186 | 187 | ## shop.select(name) 188 | 189 | You can explicitly select a level with this method if you don't want to rely on 190 | the user to select a menu for themselves from the graphical menu. 191 | 192 | # problem object format 193 | 194 | Problems must have a `verify()` function. All other fields are optional. 195 | 196 | ## problem.verify(args, cb) 197 | 198 | This function will be called when a user attempts to verify a problem with the 199 | `verify` command on the command-line. 200 | 201 | You will get an array of the arguments given after the `verify` command in 202 | `args`. 203 | 204 | You must call `cb(ok)` with `ok`, a boolean containing whether the solution was 205 | acceptible. 206 | 207 | Check out [adventure-verify](https://npmjs.org/package/adventure-verify) 208 | for a higher-level way of verifying solutions with 209 | [tape](https://npmjs.org/package/tape). 210 | 211 | ## problem.run(args) 212 | 213 | This function will be called when the user uses the `run` command from the 214 | command-line. You can implement this if you want to but it doesn't make sense 215 | for all problems. 216 | 217 | ## problem.problem 218 | 219 | This message will be displayed when a user selects the problem from the menu. 220 | 221 | `problem.problem` can be a string, a buffer, a stream, or a function that 222 | returns a string, a buffer, or a stream. 223 | 224 | ## problem.solution 225 | 226 | This message will be displayed when a user successfully completes a problem, 227 | after the success notification. 228 | 229 | `problem.solution` can be a string, a buffer, a stream, or a function that 230 | returns a string, a buffer, or a stream. 231 | 232 | ## problem.pass 233 | 234 | This message will be displayed when a user successfully completes a level. The 235 | default `problem.pass` is says `YOUR SOLUTION IS CORRECT` in a box of made of 236 | `@`s. 237 | 238 | `problem.pass` can be a string, a buffer, a stream, or a function that 239 | returns a string, a buffer, or a stream. 240 | 241 | ## problem.fail 242 | 243 | This message will be displayed when a user's solution fails to pass all the 244 | tests. The default `problem.fail` is says `YOUR SOLUTION IS NOT CORRECT` in a 245 | box of made of `#`s. 246 | 247 | `problem.fail` can be a string, a buffer, a stream, or a function that 248 | returns a string, a buffer, or a stream. 249 | 250 | # events 251 | 252 | ## shop.on('pass', function (name) {}) 253 | 254 | This event fires when a solution passed. 255 | 256 | ## shop.on('fail', function (name) {}) 257 | 258 | This event fires when a solution failed. 259 | 260 | ## shop.on('finished', function () {}) 261 | 262 | This event fires when all the levels are completed. 263 | 264 | # problem variables 265 | 266 | These variables will be automatically replaced any time you use them in any of 267 | the problem messages, whether in a string, a buffer, a stream, or a function 268 | that returns a string, a buffer, or a stream. 269 | 270 | * `$ADVENTURE_NAME` - the name of the adventure 271 | * `$ADVENTURE_COMMAND` - the name of the adventure command 272 | 273 | # usage 274 | 275 | The `.execute(args)` function accepts these commands: 276 | 277 | ``` 278 | $COMMAND 279 | $COMMAND menu 280 | 281 | Show the menu. 282 | 283 | $COMMAND verify [ARGS...] 284 | 285 | Verify the currently selected problem with ARGS. 286 | 287 | $COMMAND run [ARGS...] 288 | 289 | Run the currently selected problem with ARGS. 290 | Not all problems support `run`. 291 | 292 | $COMMAND solution 293 | 294 | Show the solution for the currently selected problem. 295 | 296 | $COMMAND print 297 | 298 | Print the text of the currently selected level. 299 | 300 | $COMMAND selected 301 | 302 | Print the name of the currently selected level. 303 | 304 | $COMMAND select LEVEL 305 | 306 | Set the currently selected LEVEL. 307 | 308 | $COMMAND list 309 | 310 | List the available levels. 311 | 312 | $COMMAND completed 313 | 314 | List the completed levels. 315 | 316 | $COMMAND reset 317 | 318 | Reset the list of completed levels. 319 | 320 | $COMMAND help 321 | 322 | Show this message. 323 | 324 | ``` 325 | 326 | # install 327 | 328 | With [npm](https://npmjs.org) do: 329 | 330 | ``` 331 | npm install adventure 332 | ``` 333 | 334 | # license 335 | 336 | MIT 337 | -------------------------------------------------------------------------------- /test/adventure.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var sinon = require('sinon'); 3 | var adventure = require('../'); 4 | 5 | describe('adventure', () => { 6 | before(() => { 7 | this.shop = adventure('test-adventure'); 8 | this.shop.add('test', () => { return {}}); 9 | }); 10 | 11 | describe('#add', () => { 12 | it('add new adventure', () => { 13 | assert.equal(this.shop._adventures.length, 1); 14 | }); 15 | }); 16 | 17 | describe('#find', () => { 18 | it('return adventure selected', () => { 19 | this.shop.add('other-test', () => {}); 20 | assert.equal(this.shop._adventures.length, 2); 21 | assert.equal(this.shop.find('test'), this.shop._adventures[0]); 22 | }); 23 | }); 24 | 25 | describe('#select', () => { 26 | it('show adventure problem', () => { 27 | var dinosaurs = require('./../example/dinosaurs'); 28 | this.shop.add('dinosaurs', () => dinosaurs); 29 | var stub = sinon.stub(this.shop, '_show'); 30 | this.shop.select('dinosaurs'); 31 | assert(stub.calledOnce); 32 | assert(stub.calledWith(dinosaurs.problem)); 33 | this.shop._show.restore(); 34 | }); 35 | }); 36 | 37 | describe('with verify stubed', () => { 38 | before(() => { 39 | this.dinosaurs = require('./../example/dinosaurs'); 40 | this.stub = sinon.stub(this.dinosaurs, 'verify'); 41 | this.shop.add('dinosaurs', () => this.dinosaurs); 42 | this.shop.select('dinosaurs'); 43 | }); 44 | after(() => { 45 | this.dinosaurs.verify.restore(); 46 | }); 47 | describe('#verify', () => { 48 | it('run adventure verify', () => { 49 | this.shop.verify('rawr', 'dinosaurs'); 50 | assert(this.stub.calledOnce); 51 | }); 52 | }); 53 | 54 | describe('#execute', () => { 55 | it('command', () => { 56 | this.shop.execute(['verify']); 57 | assert(this.stub.called); 58 | }); 59 | }); 60 | }); 61 | }); 62 | -------------------------------------------------------------------------------- /test/menu.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var sinon = require('sinon'); 3 | var menu = require('../lib/menu'); 4 | 5 | describe('menu', () => { 6 | before(() => { 7 | this.menuInstance = menu({ names: ['foo'], title: 'FOO' }); 8 | }); 9 | 10 | it('is not broken', () => { 11 | assert(this.menuInstance); 12 | }); 13 | 14 | it('add new exercise to menu', () => { 15 | var tmenu = this.menuInstance.menu; 16 | assert.equal(tmenu.items.length, 3); 17 | }); 18 | }); 19 | --------------------------------------------------------------------------------