├── .gitignore ├── .jshintrc ├── .npmignore ├── .travis.yml ├── CHANGELOG.md ├── README.md ├── package-lock.json ├── package.json ├── rocambole.jpg ├── rocambole.js └── test ├── files ├── crossroads.js └── jquery.js ├── moonwalk.spec.js ├── parse.spec.js ├── perf.spec.js └── runner.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .DS_Store? 3 | ._* 4 | .Spotlight-V100 5 | .Trashes 6 | Icon? 7 | ehthumbs.db 8 | Thumbs.db 9 | 10 | ### 11 | 12 | node_modules/ 13 | npm-debug.log 14 | coverage/ 15 | 16 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | // Settings 3 | "passfail" : false, // Stop on first error. 4 | "maxerr" : 500, // Maximum error before stopping. 5 | 6 | 7 | // Predefined globals whom JSHint will ignore. 8 | "browser" : false, // Standard browser globals e.g. `window`, `document`. 9 | "node" : true, 10 | 11 | 12 | // Custom globals. 13 | "predef" : [], 14 | 15 | 16 | // Development. 17 | "debug" : false, // Allow debugger statements e.g. browser breakpoints. 18 | "devel" : false, // Allow developments statements e.g. `console.log();`. 19 | 20 | 21 | // EcmaScript 5. 22 | "es5" : false, // Allow EcmaScript 5 syntax. 23 | "globalstrict" : true, // Allow global "use strict" (also enables 'strict'). 24 | "strict" : true, // Require `use strict` pragma in every file. 25 | 26 | 27 | // The Good Parts. 28 | "asi" : false, // Tolerate Automatic Semicolon Insertion (no semicolons). 29 | "bitwise" : false, // Prohibit bitwise operators (&, |, ^, etc.). 30 | "boss" : true, // Tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments. 31 | "curly" : false, // Require {} for every new block or scope. 32 | "eqeqeq" : false, // Require triple equals i.e. `===`. 33 | "eqnull" : true, // Tolerate use of `== null`. 34 | "evil" : false, // Tolerate use of `eval`. 35 | "expr" : false, // Tolerate `ExpressionStatement` as Programs. 36 | "forin" : true, // Tolerate `for in` loops without `hasOwnPrototype`. 37 | "immed" : true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );` 38 | "latedef" : false, // Prohibit variable use before definition. 39 | "laxbreak" : false, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons. 40 | "loopfunc" : false, // Allow functions to be defined within loops. 41 | "noarg" : true, // Prohibit use of `arguments.caller` and `arguments.callee`. 42 | "regexdash" : true, // Tolerate unescaped last dash i.e. `[-...]`. 43 | "regexp" : false, // Prohibit `.` and `[^...]` in regular expressions. 44 | "scripturl" : false, // Tolerate script-targeted URLs. 45 | "shadow" : false, // Allows re-define variables later in code e.g. `var x=1; x=2;`. 46 | "supernew" : false, // Tolerate `new function () { ... };` and `new Object;`. 47 | "undef" : true, // Require all non-global variables be declared before they are used. 48 | "unused" : true, // Check for unused vars 49 | 50 | 51 | // Personal styling prefrences. 52 | "newcap" : true, // Require capitalization of all constructor functions e.g. `new F()`. 53 | "noempty" : true, // Prohipit use of empty blocks. 54 | "nomen" : false, // Prohibit use of initial or trailing underbars in names. 55 | "nonew" : true, // Prohibit use of constructors for side-effects. 56 | "onevar" : false, // Allow only one `var` statement per function. 57 | "plusplus" : false, // Prohibit use of `++` & `--`. 58 | "sub" : false, // Tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`. 59 | "trailing" : true, // Prohibit trailing whitespaces. 60 | "white" : false // Check against strict whitespace and indentation rules. 61 | } 62 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | test/ 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: stable 4 | script: 5 | - "npm test --coverage" 6 | 7 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## v0.8.0 (2019/03/18) 4 | 5 | - update `esprima` to 4.0.1 to handle async/await. 6 | - remote `test/` files from deploy. 7 | 8 | ## v0.7.0 (2015/08/26) 9 | 10 | - Ignore TryStatement's "handlers" property in favor of "handler" 11 | 12 | ## v0.6.0 (2015/03/30) 13 | 14 | - allow custom parser. (#27) 15 | 16 | ## v0.5.1 (2015/03/19) 17 | 18 | - make it compatible with esprima@2.1 (don't loop through the same CatchClause 19 | twice). 20 | 21 | ## v0.5.0 (2015/02/25) 22 | 23 | - updated `esprima` to v2.0 because of ES6 features and to avoid `esprima-fb` 24 | bug related to RegExp. 25 | 26 | ## v0.4.0 (2014/07/14) 27 | 28 | - aliased `rocambole.recursive` as `rocambole.walk` to avoid confusions. 29 | - switched `esprima` dependency to `esprima-fb` because of ES6 features. 30 | 31 | ## v0.3.6 (2014/06/23) 32 | 33 | - really handle sparse arrays (eg. `[,]`), fixes moonwalk. (#15) 34 | 35 | ## v0.3.5 (2014/06/23) 36 | 37 | - handle sparse arrays (eg. `[,]`). (#15) 38 | 39 | ## v0.3.4 (2014/06/23) 40 | 41 | - only add `BlockComment.originalIndent` if `WhiteSpace` is on the start of 42 | a line. 43 | 44 | ## v0.3.3 (2014/04/26) 45 | 46 | - add `toString` to empty programs AST (#16) 47 | 48 | ## v0.3.2 (2014/01/17) 49 | 50 | - exports `BYPASS_RECURSION` (#8) 51 | - fix error if input is empty (#12) 52 | - support anything that implements `toString()` as input (#13) 53 | 54 | ## v0.3.1 (2013/12/15) 55 | 56 | - fix `originalIndent` on `BlockComment` when prev token is not `WhiteSpace`. 57 | 58 | ## v0.3.0 (2013/12/15) 59 | 60 | - add `originalIndent` to `BlockComment` (#11) 61 | 62 | ## v0.2.3 (2013/01/08) 63 | 64 | - improve `rocambole.parse()` performance by 4500%. (#4) 65 | - improve `rocambole.moonwalk()` performance by 11000%. 66 | 67 | ## v0.2.2 (2012/12/19) 68 | 69 | - fix consecutive comments before start of program. (#3) 70 | 71 | ## v0.2.1 (2012/12/13) 72 | 73 | - fix `loc` info on `WhiteSpace` and `LineBreak` tokens. (#2) 74 | 75 | ## v0.2.0 (2012/12/09) 76 | 77 | - Deprecated: 78 | - `token.before()` 79 | - `token.after()` 80 | - `token.remove()` 81 | - `node.getTokens()` 82 | - `ast.nodes` 83 | - avoid recursion over comments. 84 | - fix weird bug on esformatter introduced on v0.1.1 related to `token._ast` 85 | property. 86 | 87 | ## v0.1.1 (2012/12/08) 88 | 89 | - Improve token manipulation methods behavior (`before`, `after`, `remove`) 90 | 91 | ## v0.1.0 (2012/12/06) 92 | 93 | - Initial release 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rocambole [![Build Status](https://secure.travis-ci.org/millermedeiros/rocambole.svg?branch=master)](https://travis-ci.org/millermedeiros/rocambole) 2 | 3 | ![rocambole](https://raw.github.com/millermedeiros/rocambole/master/rocambole.jpg) 4 | 5 | Recursively walk and add extra information/helpers to [Esprima / Mozilla 6 | SpiderMonkey Parser API](http://esprima.org/doc/index.html#ast) compatible AST. 7 | 8 | The main difference between other tools is that it also keeps information about 9 | tokens and white spaces and it is meant to be used to transform the tokens and 10 | not the string values itself. 11 | 12 | This library is specially useful for non-destructive AST manipulation. 13 | 14 | 15 | ## Inspiration 16 | 17 | This module was heavily inspired by 18 | [node-falafel](https://github.com/substack/node-falafel) and 19 | [node-burrito](https://github.com/substack/node-burrito) but I needed more 20 | information than what is currently available on falafel (specially about 21 | tokens, empty lines and white spaces) and also needed to do the node traversing 22 | on the opposite order (start from leaf nodes). The amount of changes required 23 | to introduce the new features and the differences on the concept behind the 24 | tool justified a new project. 25 | 26 | It was created mainly to be used on 27 | [esformatter](https://github.com/millermedeiros/esformatter/). 28 | 29 | 30 | 31 | ## Extra Tokens 32 | 33 | Besides all the regular tokens returned by `esprima` we also add a few more 34 | that are important for non-destructive transformations: 35 | 36 | * `WhiteSpace` 37 | - Can store multiple white spaces (tabs are considered white space, line 38 | breaks not). Important if you want to do non-destructive replacements that 39 | are white-space sensitive. 40 | - Multiple subsequent white spaces are treated as a single token. 41 | * `LineBreak` 42 | * `LineComment` 43 | * `BlockComment` 44 | 45 | It's way easier to rebuild the JS string if the tokens already have line breaks 46 | and comments. It's also easier to identify if previous/next/current token is a 47 | LineBreak or Comment (sometimes needed for non-destructive transformations). 48 | 49 | Rocambole structure might change in the future to keep the extraneous tokens 50 | outside the `tokens` array and also add an option to toggle the behavior. 51 | ([issue #7](https://github.com/millermedeiros/rocambole/issues/7)) 52 | 53 | 54 | ## Extra Properties 55 | 56 | Each Node have the following extra properties/methods: 57 | 58 | - `parent` : Node|undefined 59 | - `toString()` : string 60 | - `next` : Node|undefined 61 | - `prev` : Node|undefined 62 | - `depth` : Number 63 | - `startToken` : Token 64 | - `endToken` : Token 65 | 66 | Each token also have: 67 | 68 | - `prev` : Token|undefined 69 | - `next` : Token|undefined 70 | 71 | BlockComment also have: 72 | 73 | - `originalIndent`: String|undefined 74 | 75 | To get a better idea of the generated AST structure try out 76 | [rocambole-visualize](http://piuccio.github.io/rocambole-visualize/). 77 | 78 | 79 | ## Linked List 80 | 81 | You should **treat the tokens as a linked list instead of reading the 82 | `ast.tokens` array** (inserting/removing items from a linked list is very cheap 83 | and won't break the loop). You should grab a reference to the `node.startToken` 84 | and get `token.next` until you find the desired token or reach the end of the 85 | program. To loop between all tokens inside a node you can do like this: 86 | 87 | ```js 88 | var token = node.startToken; 89 | while (token !== node.endToken.next) { 90 | doStuffWithToken(token); 91 | token = token.next; 92 | } 93 | ``` 94 | 95 | The method `toString` loops through all tokens between `node.startToken` and 96 | `node.endToken` grabbing the `token.raw` (used by comments) or `token.value` 97 | properties. To implement a method similar to falafel `update()` you can do 98 | this: 99 | 100 | ```js 101 | function update(node, str){ 102 | var newToken = { 103 | type : 'Custom', // can be anything (not used internally) 104 | value : str 105 | }; 106 | // update linked list references 107 | if ( node.startToken.prev ) { 108 | node.startToken.prev.next = newToken; 109 | newToken.prev = node.startToken.prev; 110 | } 111 | if ( node.endToken.next ) { 112 | node.endToken.next.prev = newToken; 113 | newToken.next = node.endToken.next; 114 | } 115 | node.startToken = node.endToken = newToken; 116 | } 117 | ``` 118 | 119 | 120 | ## Helpers 121 | 122 | I plan to create helpers as separate projects when possible. 123 | 124 | - [rocambole-token](https://github.com/millermedeiros/rocambole-token): helpers for token manipulation/traversal 125 | - [rocambole-node](https://github.com/millermedeiros/rocambole-node): helpers for node manipulation/traversal 126 | - [rocambole-whitespace](https://github.com/millermedeiros/rocambole-whitespace): helpers for whitespace manipulation 127 | - [rocambole-linebreak](https://github.com/millermedeiros/rocambole-linebreak): helpers for line break manipulation 128 | - [rocambole-indent](https://github.com/millermedeiros/rocambole-indent): helpers for indentation 129 | 130 | 131 | ## API 132 | 133 | 134 | ### rocambole.parse(source, [opts]) 135 | 136 | Parses a string and instrument the AST with extra properties/methods. 137 | 138 | ```js 139 | var rocambole = require('rocambole'); 140 | var ast = rocambole.parse(string); 141 | console.log( ast.startToken ); 142 | // to get a string representation of all tokens call toString() 143 | console.log( ast.toString() ); 144 | ``` 145 | 146 | You can pass custom options as the second argument: 147 | 148 | ```js 149 | rocambole.parse(source, { 150 | loc: true, 151 | // custom options are forwarded to the rocambole.parseFn 152 | ecmaFeatures: { 153 | arrowFunctions: true 154 | } 155 | }); 156 | ``` 157 | 158 | **IMPORTANT:** rocambole needs the `range`, `tokens` and `comment` info to 159 | build the token linked list, so these options will always be set to `true`. 160 | 161 | ### rocambole.parseFn:Function 162 | 163 | Allows you to override the function used to parse the program. Defaults to 164 | `esprima.parse`. 165 | 166 | ```js 167 | // espree is compatible with esprima AST so things should work as expected 168 | var espree = require('espree'); 169 | rocambole.parseFn = espree.parse; 170 | rocambole.parseContext = espree; 171 | ``` 172 | 173 | ### rocambole.parseContext:Object 174 | 175 | Sets the context (`this` value) of the `parseFn`. Defaults to `esprima`. 176 | 177 | ### rocambole.parseOptions:Object 178 | 179 | Sets the default options passed to `parseFn`. 180 | 181 | ```js 182 | // default values 183 | rocambole.parseOptions = { 184 | // we need range/tokens/comment info to build the tokens linked list! 185 | range: true, 186 | tokens: true, 187 | comment: true 188 | }; 189 | ``` 190 | 191 | ### rocambole.moonwalk(ast, callback) 192 | 193 | The `moonwalk()` starts at the leaf nodes and go down the tree until it reaches 194 | the root node (`Program`). Each node will be traversed only once. 195 | 196 | ```js 197 | rocambole.moonwalk(ast, function(node){ 198 | if (node.type == 'ArrayExpression'){ 199 | console.log( node.depth +': '+ node.toString() ); 200 | } 201 | }); 202 | ``` 203 | 204 | Traverse order: 205 | 206 | ``` 207 | Program [#18] 208 | `-FunctionDeclaration [#16] 209 | |-BlockStatement [#14] 210 | | |-IfStatement [#12] 211 | | | |-BynaryExpression [#9] 212 | | | | |-Identifier [#4] 213 | | | | `-Literal [#5] 214 | | | `-BlockStatement [#10] 215 | | | `-ExpressionStatement [#6] 216 | | | `-AssignmentExpression [#3] 217 | | | |-Identifier [#1 walk starts here] 218 | | | `-Literal [#2] 219 | | `-VariableDeclaration [#13] 220 | | `-VariableDeclarator [#11] 221 | | |-Identifier [#7] 222 | | `-Literal [#8] 223 | `-ReturnStatement [#17] 224 | `-Identifier [#15] 225 | ``` 226 | 227 | This behavior is very different from node-falafel and node-burrito. 228 | 229 | 230 | ### rocambole.walk(ast, callback) 231 | 232 | It loops through all nodes on the AST starting from the root node (`Program`), 233 | similar to `node-falafel`. 234 | 235 | ```js 236 | rocambole.walk(ast, function(node){ 237 | console.log(node.type); 238 | }); 239 | ``` 240 | 241 | 242 | ## Popular Alternatives 243 | 244 | - [burrito](https://github.com/substack/node-burrito) 245 | - [falafel](https://github.com/substack/node-falafel) 246 | 247 | 248 | 249 | ## Unit Tests 250 | 251 | Besides the regular unit tests we also use 252 | [istanbul](https://github.com/yahoo/istanbul) to generate code coverage 253 | reports, tests should have at least 95% code coverage for statements, branches 254 | and lines and 100% code coverage for functions or travis build will fail. 255 | 256 | We do not run the coverage test at each call since it slows down the 257 | performnace of the tests and it also makes it harder to see the test results. 258 | To execute tests and generate coverage report call `npm test --coverage`, for 259 | regular tests just do `npm test`. 260 | 261 | Coverage reports are not committed to the repository since they will change at 262 | each `npm test --coverage` call. 263 | 264 | 265 | 266 | ## License 267 | 268 | MIT 269 | 270 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rocambole", 3 | "version": "0.8.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "abbrev": { 8 | "version": "1.0.9", 9 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", 10 | "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", 11 | "dev": true 12 | }, 13 | "amdefine": { 14 | "version": "1.0.1", 15 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", 16 | "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", 17 | "dev": true, 18 | "optional": true 19 | }, 20 | "ansi-colors": { 21 | "version": "3.2.3", 22 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", 23 | "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", 24 | "dev": true 25 | }, 26 | "ansi-regex": { 27 | "version": "3.0.0", 28 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 29 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 30 | "dev": true 31 | }, 32 | "ansi-styles": { 33 | "version": "3.2.1", 34 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 35 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 36 | "dev": true, 37 | "requires": { 38 | "color-convert": "^1.9.0" 39 | } 40 | }, 41 | "argparse": { 42 | "version": "1.0.10", 43 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 44 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 45 | "dev": true, 46 | "requires": { 47 | "sprintf-js": "~1.0.2" 48 | } 49 | }, 50 | "arr-diff": { 51 | "version": "4.0.0", 52 | "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", 53 | "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", 54 | "dev": true 55 | }, 56 | "arr-flatten": { 57 | "version": "1.1.0", 58 | "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", 59 | "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", 60 | "dev": true 61 | }, 62 | "arr-union": { 63 | "version": "3.1.0", 64 | "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", 65 | "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", 66 | "dev": true 67 | }, 68 | "array-unique": { 69 | "version": "0.3.2", 70 | "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", 71 | "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", 72 | "dev": true 73 | }, 74 | "assign-symbols": { 75 | "version": "1.0.0", 76 | "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", 77 | "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", 78 | "dev": true 79 | }, 80 | "async": { 81 | "version": "1.5.2", 82 | "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", 83 | "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", 84 | "dev": true 85 | }, 86 | "atob": { 87 | "version": "2.1.2", 88 | "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", 89 | "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", 90 | "dev": true 91 | }, 92 | "balanced-match": { 93 | "version": "1.0.0", 94 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 95 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 96 | "dev": true 97 | }, 98 | "base": { 99 | "version": "0.11.2", 100 | "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", 101 | "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", 102 | "dev": true, 103 | "requires": { 104 | "cache-base": "^1.0.1", 105 | "class-utils": "^0.3.5", 106 | "component-emitter": "^1.2.1", 107 | "define-property": "^1.0.0", 108 | "isobject": "^3.0.1", 109 | "mixin-deep": "^1.2.0", 110 | "pascalcase": "^0.1.1" 111 | }, 112 | "dependencies": { 113 | "define-property": { 114 | "version": "1.0.0", 115 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", 116 | "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", 117 | "dev": true, 118 | "requires": { 119 | "is-descriptor": "^1.0.0" 120 | } 121 | }, 122 | "is-accessor-descriptor": { 123 | "version": "1.0.0", 124 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", 125 | "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", 126 | "dev": true, 127 | "requires": { 128 | "kind-of": "^6.0.0" 129 | } 130 | }, 131 | "is-data-descriptor": { 132 | "version": "1.0.0", 133 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", 134 | "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", 135 | "dev": true, 136 | "requires": { 137 | "kind-of": "^6.0.0" 138 | } 139 | }, 140 | "is-descriptor": { 141 | "version": "1.0.2", 142 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", 143 | "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", 144 | "dev": true, 145 | "requires": { 146 | "is-accessor-descriptor": "^1.0.0", 147 | "is-data-descriptor": "^1.0.0", 148 | "kind-of": "^6.0.2" 149 | } 150 | } 151 | } 152 | }, 153 | "brace-expansion": { 154 | "version": "1.1.11", 155 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 156 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 157 | "dev": true, 158 | "requires": { 159 | "balanced-match": "^1.0.0", 160 | "concat-map": "0.0.1" 161 | } 162 | }, 163 | "braces": { 164 | "version": "2.3.2", 165 | "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", 166 | "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", 167 | "dev": true, 168 | "requires": { 169 | "arr-flatten": "^1.1.0", 170 | "array-unique": "^0.3.2", 171 | "extend-shallow": "^2.0.1", 172 | "fill-range": "^4.0.0", 173 | "isobject": "^3.0.1", 174 | "repeat-element": "^1.1.2", 175 | "snapdragon": "^0.8.1", 176 | "snapdragon-node": "^2.0.1", 177 | "split-string": "^3.0.2", 178 | "to-regex": "^3.0.1" 179 | }, 180 | "dependencies": { 181 | "extend-shallow": { 182 | "version": "2.0.1", 183 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 184 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 185 | "dev": true, 186 | "requires": { 187 | "is-extendable": "^0.1.0" 188 | } 189 | } 190 | } 191 | }, 192 | "browser-stdout": { 193 | "version": "1.3.1", 194 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 195 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 196 | "dev": true 197 | }, 198 | "cache-base": { 199 | "version": "1.0.1", 200 | "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", 201 | "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", 202 | "dev": true, 203 | "requires": { 204 | "collection-visit": "^1.0.0", 205 | "component-emitter": "^1.2.1", 206 | "get-value": "^2.0.6", 207 | "has-value": "^1.0.0", 208 | "isobject": "^3.0.1", 209 | "set-value": "^2.0.0", 210 | "to-object-path": "^0.3.0", 211 | "union-value": "^1.0.0", 212 | "unset-value": "^1.0.0" 213 | } 214 | }, 215 | "camelcase": { 216 | "version": "5.2.0", 217 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.2.0.tgz", 218 | "integrity": "sha512-IXFsBS2pC+X0j0N/GE7Dm7j3bsEBp+oTpb7F50dwEVX7rf3IgwO9XatnegTsDtniKCUtEJH4fSU6Asw7uoVLfQ==", 219 | "dev": true 220 | }, 221 | "chalk": { 222 | "version": "2.4.2", 223 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 224 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 225 | "dev": true, 226 | "requires": { 227 | "ansi-styles": "^3.2.1", 228 | "escape-string-regexp": "^1.0.5", 229 | "supports-color": "^5.3.0" 230 | }, 231 | "dependencies": { 232 | "supports-color": { 233 | "version": "5.5.0", 234 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 235 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 236 | "dev": true, 237 | "requires": { 238 | "has-flag": "^3.0.0" 239 | } 240 | } 241 | } 242 | }, 243 | "class-utils": { 244 | "version": "0.3.6", 245 | "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", 246 | "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", 247 | "dev": true, 248 | "requires": { 249 | "arr-union": "^3.1.0", 250 | "define-property": "^0.2.5", 251 | "isobject": "^3.0.0", 252 | "static-extend": "^0.1.1" 253 | }, 254 | "dependencies": { 255 | "define-property": { 256 | "version": "0.2.5", 257 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", 258 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", 259 | "dev": true, 260 | "requires": { 261 | "is-descriptor": "^0.1.0" 262 | } 263 | } 264 | } 265 | }, 266 | "cliui": { 267 | "version": "4.1.0", 268 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", 269 | "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", 270 | "dev": true, 271 | "requires": { 272 | "string-width": "^2.1.1", 273 | "strip-ansi": "^4.0.0", 274 | "wrap-ansi": "^2.0.0" 275 | } 276 | }, 277 | "code-point-at": { 278 | "version": "1.1.0", 279 | "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", 280 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", 281 | "dev": true 282 | }, 283 | "collection-visit": { 284 | "version": "1.0.0", 285 | "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", 286 | "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", 287 | "dev": true, 288 | "requires": { 289 | "map-visit": "^1.0.0", 290 | "object-visit": "^1.0.0" 291 | } 292 | }, 293 | "color-convert": { 294 | "version": "1.9.3", 295 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 296 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 297 | "dev": true, 298 | "requires": { 299 | "color-name": "1.1.3" 300 | } 301 | }, 302 | "color-name": { 303 | "version": "1.1.3", 304 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 305 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 306 | "dev": true 307 | }, 308 | "commander": { 309 | "version": "2.19.0", 310 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", 311 | "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", 312 | "dev": true, 313 | "optional": true 314 | }, 315 | "component-emitter": { 316 | "version": "1.2.1", 317 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", 318 | "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", 319 | "dev": true 320 | }, 321 | "concat-map": { 322 | "version": "0.0.1", 323 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 324 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 325 | "dev": true 326 | }, 327 | "copy-descriptor": { 328 | "version": "0.1.1", 329 | "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", 330 | "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", 331 | "dev": true 332 | }, 333 | "cross-spawn": { 334 | "version": "6.0.5", 335 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", 336 | "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", 337 | "dev": true, 338 | "requires": { 339 | "nice-try": "^1.0.4", 340 | "path-key": "^2.0.1", 341 | "semver": "^5.5.0", 342 | "shebang-command": "^1.2.0", 343 | "which": "^1.2.9" 344 | }, 345 | "dependencies": { 346 | "which": { 347 | "version": "1.3.1", 348 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 349 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 350 | "dev": true, 351 | "requires": { 352 | "isexe": "^2.0.0" 353 | } 354 | } 355 | } 356 | }, 357 | "debug": { 358 | "version": "3.2.6", 359 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", 360 | "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", 361 | "dev": true, 362 | "requires": { 363 | "ms": "^2.1.1" 364 | } 365 | }, 366 | "decamelize": { 367 | "version": "1.2.0", 368 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 369 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 370 | "dev": true 371 | }, 372 | "decode-uri-component": { 373 | "version": "0.2.0", 374 | "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", 375 | "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", 376 | "dev": true 377 | }, 378 | "deep-is": { 379 | "version": "0.1.3", 380 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 381 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 382 | "dev": true 383 | }, 384 | "define-properties": { 385 | "version": "1.1.3", 386 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 387 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 388 | "dev": true, 389 | "requires": { 390 | "object-keys": "^1.0.12" 391 | } 392 | }, 393 | "define-property": { 394 | "version": "2.0.2", 395 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", 396 | "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", 397 | "dev": true, 398 | "requires": { 399 | "is-descriptor": "^1.0.2", 400 | "isobject": "^3.0.1" 401 | }, 402 | "dependencies": { 403 | "is-accessor-descriptor": { 404 | "version": "1.0.0", 405 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", 406 | "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", 407 | "dev": true, 408 | "requires": { 409 | "kind-of": "^6.0.0" 410 | } 411 | }, 412 | "is-data-descriptor": { 413 | "version": "1.0.0", 414 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", 415 | "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", 416 | "dev": true, 417 | "requires": { 418 | "kind-of": "^6.0.0" 419 | } 420 | }, 421 | "is-descriptor": { 422 | "version": "1.0.2", 423 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", 424 | "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", 425 | "dev": true, 426 | "requires": { 427 | "is-accessor-descriptor": "^1.0.0", 428 | "is-data-descriptor": "^1.0.0", 429 | "kind-of": "^6.0.2" 430 | } 431 | } 432 | } 433 | }, 434 | "detect-file": { 435 | "version": "1.0.0", 436 | "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", 437 | "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", 438 | "dev": true 439 | }, 440 | "diff": { 441 | "version": "3.5.0", 442 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", 443 | "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", 444 | "dev": true 445 | }, 446 | "end-of-stream": { 447 | "version": "1.4.1", 448 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", 449 | "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", 450 | "dev": true, 451 | "requires": { 452 | "once": "^1.4.0" 453 | } 454 | }, 455 | "es-abstract": { 456 | "version": "1.13.0", 457 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", 458 | "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", 459 | "dev": true, 460 | "requires": { 461 | "es-to-primitive": "^1.2.0", 462 | "function-bind": "^1.1.1", 463 | "has": "^1.0.3", 464 | "is-callable": "^1.1.4", 465 | "is-regex": "^1.0.4", 466 | "object-keys": "^1.0.12" 467 | } 468 | }, 469 | "es-to-primitive": { 470 | "version": "1.2.0", 471 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", 472 | "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", 473 | "dev": true, 474 | "requires": { 475 | "is-callable": "^1.1.4", 476 | "is-date-object": "^1.0.1", 477 | "is-symbol": "^1.0.2" 478 | } 479 | }, 480 | "escape-string-regexp": { 481 | "version": "1.0.5", 482 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 483 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 484 | "dev": true 485 | }, 486 | "escodegen": { 487 | "version": "1.8.1", 488 | "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", 489 | "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", 490 | "dev": true, 491 | "requires": { 492 | "esprima": "^2.7.1", 493 | "estraverse": "^1.9.1", 494 | "esutils": "^2.0.2", 495 | "optionator": "^0.8.1", 496 | "source-map": "~0.2.0" 497 | }, 498 | "dependencies": { 499 | "esprima": { 500 | "version": "2.7.3", 501 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", 502 | "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", 503 | "dev": true 504 | } 505 | } 506 | }, 507 | "esprima": { 508 | "version": "4.0.1", 509 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 510 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" 511 | }, 512 | "estraverse": { 513 | "version": "1.9.3", 514 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", 515 | "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", 516 | "dev": true 517 | }, 518 | "esutils": { 519 | "version": "2.0.2", 520 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", 521 | "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", 522 | "dev": true 523 | }, 524 | "execa": { 525 | "version": "1.0.0", 526 | "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", 527 | "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", 528 | "dev": true, 529 | "requires": { 530 | "cross-spawn": "^6.0.0", 531 | "get-stream": "^4.0.0", 532 | "is-stream": "^1.1.0", 533 | "npm-run-path": "^2.0.0", 534 | "p-finally": "^1.0.0", 535 | "signal-exit": "^3.0.0", 536 | "strip-eof": "^1.0.0" 537 | } 538 | }, 539 | "expand-brackets": { 540 | "version": "2.1.4", 541 | "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", 542 | "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", 543 | "dev": true, 544 | "requires": { 545 | "debug": "^2.3.3", 546 | "define-property": "^0.2.5", 547 | "extend-shallow": "^2.0.1", 548 | "posix-character-classes": "^0.1.0", 549 | "regex-not": "^1.0.0", 550 | "snapdragon": "^0.8.1", 551 | "to-regex": "^3.0.1" 552 | }, 553 | "dependencies": { 554 | "debug": { 555 | "version": "2.6.9", 556 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 557 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 558 | "dev": true, 559 | "requires": { 560 | "ms": "2.0.0" 561 | } 562 | }, 563 | "define-property": { 564 | "version": "0.2.5", 565 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", 566 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", 567 | "dev": true, 568 | "requires": { 569 | "is-descriptor": "^0.1.0" 570 | } 571 | }, 572 | "extend-shallow": { 573 | "version": "2.0.1", 574 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 575 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 576 | "dev": true, 577 | "requires": { 578 | "is-extendable": "^0.1.0" 579 | } 580 | }, 581 | "ms": { 582 | "version": "2.0.0", 583 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 584 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 585 | "dev": true 586 | } 587 | } 588 | }, 589 | "expand-tilde": { 590 | "version": "2.0.2", 591 | "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", 592 | "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", 593 | "dev": true, 594 | "requires": { 595 | "homedir-polyfill": "^1.0.1" 596 | } 597 | }, 598 | "expect.js": { 599 | "version": "0.2.0", 600 | "resolved": "https://registry.npmjs.org/expect.js/-/expect.js-0.2.0.tgz", 601 | "integrity": "sha1-EChTPSwcNj90pnlv9X7AUg3tK+E=", 602 | "dev": true 603 | }, 604 | "extend-shallow": { 605 | "version": "3.0.2", 606 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", 607 | "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", 608 | "dev": true, 609 | "requires": { 610 | "assign-symbols": "^1.0.0", 611 | "is-extendable": "^1.0.1" 612 | }, 613 | "dependencies": { 614 | "is-extendable": { 615 | "version": "1.0.1", 616 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", 617 | "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", 618 | "dev": true, 619 | "requires": { 620 | "is-plain-object": "^2.0.4" 621 | } 622 | } 623 | } 624 | }, 625 | "extglob": { 626 | "version": "2.0.4", 627 | "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", 628 | "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", 629 | "dev": true, 630 | "requires": { 631 | "array-unique": "^0.3.2", 632 | "define-property": "^1.0.0", 633 | "expand-brackets": "^2.1.4", 634 | "extend-shallow": "^2.0.1", 635 | "fragment-cache": "^0.2.1", 636 | "regex-not": "^1.0.0", 637 | "snapdragon": "^0.8.1", 638 | "to-regex": "^3.0.1" 639 | }, 640 | "dependencies": { 641 | "define-property": { 642 | "version": "1.0.0", 643 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", 644 | "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", 645 | "dev": true, 646 | "requires": { 647 | "is-descriptor": "^1.0.0" 648 | } 649 | }, 650 | "extend-shallow": { 651 | "version": "2.0.1", 652 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 653 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 654 | "dev": true, 655 | "requires": { 656 | "is-extendable": "^0.1.0" 657 | } 658 | }, 659 | "is-accessor-descriptor": { 660 | "version": "1.0.0", 661 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", 662 | "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", 663 | "dev": true, 664 | "requires": { 665 | "kind-of": "^6.0.0" 666 | } 667 | }, 668 | "is-data-descriptor": { 669 | "version": "1.0.0", 670 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", 671 | "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", 672 | "dev": true, 673 | "requires": { 674 | "kind-of": "^6.0.0" 675 | } 676 | }, 677 | "is-descriptor": { 678 | "version": "1.0.2", 679 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", 680 | "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", 681 | "dev": true, 682 | "requires": { 683 | "is-accessor-descriptor": "^1.0.0", 684 | "is-data-descriptor": "^1.0.0", 685 | "kind-of": "^6.0.2" 686 | } 687 | } 688 | } 689 | }, 690 | "fast-levenshtein": { 691 | "version": "2.0.6", 692 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 693 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 694 | "dev": true 695 | }, 696 | "fill-range": { 697 | "version": "4.0.0", 698 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", 699 | "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", 700 | "dev": true, 701 | "requires": { 702 | "extend-shallow": "^2.0.1", 703 | "is-number": "^3.0.0", 704 | "repeat-string": "^1.6.1", 705 | "to-regex-range": "^2.1.0" 706 | }, 707 | "dependencies": { 708 | "extend-shallow": { 709 | "version": "2.0.1", 710 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 711 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 712 | "dev": true, 713 | "requires": { 714 | "is-extendable": "^0.1.0" 715 | } 716 | } 717 | } 718 | }, 719 | "find-up": { 720 | "version": "3.0.0", 721 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 722 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 723 | "dev": true, 724 | "requires": { 725 | "locate-path": "^3.0.0" 726 | } 727 | }, 728 | "findup-sync": { 729 | "version": "2.0.0", 730 | "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", 731 | "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", 732 | "dev": true, 733 | "requires": { 734 | "detect-file": "^1.0.0", 735 | "is-glob": "^3.1.0", 736 | "micromatch": "^3.0.4", 737 | "resolve-dir": "^1.0.1" 738 | } 739 | }, 740 | "flat": { 741 | "version": "4.1.0", 742 | "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", 743 | "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", 744 | "dev": true, 745 | "requires": { 746 | "is-buffer": "~2.0.3" 747 | }, 748 | "dependencies": { 749 | "is-buffer": { 750 | "version": "2.0.3", 751 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", 752 | "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", 753 | "dev": true 754 | } 755 | } 756 | }, 757 | "for-in": { 758 | "version": "1.0.2", 759 | "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", 760 | "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", 761 | "dev": true 762 | }, 763 | "fragment-cache": { 764 | "version": "0.2.1", 765 | "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", 766 | "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", 767 | "dev": true, 768 | "requires": { 769 | "map-cache": "^0.2.2" 770 | } 771 | }, 772 | "fs.realpath": { 773 | "version": "1.0.0", 774 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 775 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 776 | "dev": true 777 | }, 778 | "function-bind": { 779 | "version": "1.1.1", 780 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 781 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 782 | "dev": true 783 | }, 784 | "get-caller-file": { 785 | "version": "1.0.3", 786 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", 787 | "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", 788 | "dev": true 789 | }, 790 | "get-stream": { 791 | "version": "4.1.0", 792 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", 793 | "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", 794 | "dev": true, 795 | "requires": { 796 | "pump": "^3.0.0" 797 | } 798 | }, 799 | "get-value": { 800 | "version": "2.0.6", 801 | "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", 802 | "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", 803 | "dev": true 804 | }, 805 | "glob": { 806 | "version": "5.0.15", 807 | "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", 808 | "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", 809 | "dev": true, 810 | "requires": { 811 | "inflight": "^1.0.4", 812 | "inherits": "2", 813 | "minimatch": "2 || 3", 814 | "once": "^1.3.0", 815 | "path-is-absolute": "^1.0.0" 816 | } 817 | }, 818 | "global-modules": { 819 | "version": "1.0.0", 820 | "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", 821 | "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", 822 | "dev": true, 823 | "requires": { 824 | "global-prefix": "^1.0.1", 825 | "is-windows": "^1.0.1", 826 | "resolve-dir": "^1.0.0" 827 | } 828 | }, 829 | "global-prefix": { 830 | "version": "1.0.2", 831 | "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", 832 | "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", 833 | "dev": true, 834 | "requires": { 835 | "expand-tilde": "^2.0.2", 836 | "homedir-polyfill": "^1.0.1", 837 | "ini": "^1.3.4", 838 | "is-windows": "^1.0.1", 839 | "which": "^1.2.14" 840 | }, 841 | "dependencies": { 842 | "which": { 843 | "version": "1.3.1", 844 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 845 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 846 | "dev": true, 847 | "requires": { 848 | "isexe": "^2.0.0" 849 | } 850 | } 851 | } 852 | }, 853 | "growl": { 854 | "version": "1.10.5", 855 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 856 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 857 | "dev": true 858 | }, 859 | "handlebars": { 860 | "version": "4.1.1", 861 | "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.1.tgz", 862 | "integrity": "sha512-3Zhi6C0euYZL5sM0Zcy7lInLXKQ+YLcF/olbN010mzGQ4XVm50JeyBnMqofHh696GrciGruC7kCcApPDJvVgwA==", 863 | "dev": true, 864 | "requires": { 865 | "neo-async": "^2.6.0", 866 | "optimist": "^0.6.1", 867 | "source-map": "^0.6.1", 868 | "uglify-js": "^3.1.4" 869 | }, 870 | "dependencies": { 871 | "source-map": { 872 | "version": "0.6.1", 873 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 874 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 875 | "dev": true 876 | } 877 | } 878 | }, 879 | "has": { 880 | "version": "1.0.3", 881 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 882 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 883 | "dev": true, 884 | "requires": { 885 | "function-bind": "^1.1.1" 886 | } 887 | }, 888 | "has-flag": { 889 | "version": "3.0.0", 890 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 891 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 892 | "dev": true 893 | }, 894 | "has-symbols": { 895 | "version": "1.0.0", 896 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", 897 | "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", 898 | "dev": true 899 | }, 900 | "has-value": { 901 | "version": "1.0.0", 902 | "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", 903 | "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", 904 | "dev": true, 905 | "requires": { 906 | "get-value": "^2.0.6", 907 | "has-values": "^1.0.0", 908 | "isobject": "^3.0.0" 909 | } 910 | }, 911 | "has-values": { 912 | "version": "1.0.0", 913 | "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", 914 | "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", 915 | "dev": true, 916 | "requires": { 917 | "is-number": "^3.0.0", 918 | "kind-of": "^4.0.0" 919 | }, 920 | "dependencies": { 921 | "kind-of": { 922 | "version": "4.0.0", 923 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", 924 | "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", 925 | "dev": true, 926 | "requires": { 927 | "is-buffer": "^1.1.5" 928 | } 929 | } 930 | } 931 | }, 932 | "he": { 933 | "version": "1.2.0", 934 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 935 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 936 | "dev": true 937 | }, 938 | "homedir-polyfill": { 939 | "version": "1.0.3", 940 | "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", 941 | "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", 942 | "dev": true, 943 | "requires": { 944 | "parse-passwd": "^1.0.0" 945 | } 946 | }, 947 | "inflight": { 948 | "version": "1.0.6", 949 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 950 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 951 | "dev": true, 952 | "requires": { 953 | "once": "^1.3.0", 954 | "wrappy": "1" 955 | } 956 | }, 957 | "inherits": { 958 | "version": "2.0.3", 959 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 960 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 961 | "dev": true 962 | }, 963 | "ini": { 964 | "version": "1.3.5", 965 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", 966 | "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", 967 | "dev": true 968 | }, 969 | "invert-kv": { 970 | "version": "2.0.0", 971 | "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", 972 | "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", 973 | "dev": true 974 | }, 975 | "is-accessor-descriptor": { 976 | "version": "0.1.6", 977 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", 978 | "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", 979 | "dev": true, 980 | "requires": { 981 | "kind-of": "^3.0.2" 982 | }, 983 | "dependencies": { 984 | "kind-of": { 985 | "version": "3.2.2", 986 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 987 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 988 | "dev": true, 989 | "requires": { 990 | "is-buffer": "^1.1.5" 991 | } 992 | } 993 | } 994 | }, 995 | "is-buffer": { 996 | "version": "1.1.6", 997 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 998 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", 999 | "dev": true 1000 | }, 1001 | "is-callable": { 1002 | "version": "1.1.4", 1003 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", 1004 | "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", 1005 | "dev": true 1006 | }, 1007 | "is-data-descriptor": { 1008 | "version": "0.1.4", 1009 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", 1010 | "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", 1011 | "dev": true, 1012 | "requires": { 1013 | "kind-of": "^3.0.2" 1014 | }, 1015 | "dependencies": { 1016 | "kind-of": { 1017 | "version": "3.2.2", 1018 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 1019 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 1020 | "dev": true, 1021 | "requires": { 1022 | "is-buffer": "^1.1.5" 1023 | } 1024 | } 1025 | } 1026 | }, 1027 | "is-date-object": { 1028 | "version": "1.0.1", 1029 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", 1030 | "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", 1031 | "dev": true 1032 | }, 1033 | "is-descriptor": { 1034 | "version": "0.1.6", 1035 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", 1036 | "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", 1037 | "dev": true, 1038 | "requires": { 1039 | "is-accessor-descriptor": "^0.1.6", 1040 | "is-data-descriptor": "^0.1.4", 1041 | "kind-of": "^5.0.0" 1042 | }, 1043 | "dependencies": { 1044 | "kind-of": { 1045 | "version": "5.1.0", 1046 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", 1047 | "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", 1048 | "dev": true 1049 | } 1050 | } 1051 | }, 1052 | "is-extendable": { 1053 | "version": "0.1.1", 1054 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", 1055 | "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", 1056 | "dev": true 1057 | }, 1058 | "is-extglob": { 1059 | "version": "2.1.1", 1060 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1061 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 1062 | "dev": true 1063 | }, 1064 | "is-fullwidth-code-point": { 1065 | "version": "2.0.0", 1066 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 1067 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 1068 | "dev": true 1069 | }, 1070 | "is-glob": { 1071 | "version": "3.1.0", 1072 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", 1073 | "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", 1074 | "dev": true, 1075 | "requires": { 1076 | "is-extglob": "^2.1.0" 1077 | } 1078 | }, 1079 | "is-number": { 1080 | "version": "3.0.0", 1081 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", 1082 | "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", 1083 | "dev": true, 1084 | "requires": { 1085 | "kind-of": "^3.0.2" 1086 | }, 1087 | "dependencies": { 1088 | "kind-of": { 1089 | "version": "3.2.2", 1090 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 1091 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 1092 | "dev": true, 1093 | "requires": { 1094 | "is-buffer": "^1.1.5" 1095 | } 1096 | } 1097 | } 1098 | }, 1099 | "is-plain-object": { 1100 | "version": "2.0.4", 1101 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", 1102 | "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", 1103 | "dev": true, 1104 | "requires": { 1105 | "isobject": "^3.0.1" 1106 | } 1107 | }, 1108 | "is-regex": { 1109 | "version": "1.0.4", 1110 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", 1111 | "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", 1112 | "dev": true, 1113 | "requires": { 1114 | "has": "^1.0.1" 1115 | } 1116 | }, 1117 | "is-stream": { 1118 | "version": "1.1.0", 1119 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 1120 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", 1121 | "dev": true 1122 | }, 1123 | "is-symbol": { 1124 | "version": "1.0.2", 1125 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", 1126 | "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", 1127 | "dev": true, 1128 | "requires": { 1129 | "has-symbols": "^1.0.0" 1130 | } 1131 | }, 1132 | "is-windows": { 1133 | "version": "1.0.2", 1134 | "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", 1135 | "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", 1136 | "dev": true 1137 | }, 1138 | "isarray": { 1139 | "version": "1.0.0", 1140 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 1141 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 1142 | "dev": true 1143 | }, 1144 | "isexe": { 1145 | "version": "2.0.0", 1146 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1147 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 1148 | "dev": true 1149 | }, 1150 | "isobject": { 1151 | "version": "3.0.1", 1152 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", 1153 | "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", 1154 | "dev": true 1155 | }, 1156 | "istanbul": { 1157 | "version": "0.4.5", 1158 | "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", 1159 | "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", 1160 | "dev": true, 1161 | "requires": { 1162 | "abbrev": "1.0.x", 1163 | "async": "1.x", 1164 | "escodegen": "1.8.x", 1165 | "esprima": "2.7.x", 1166 | "glob": "^5.0.15", 1167 | "handlebars": "^4.0.1", 1168 | "js-yaml": "3.x", 1169 | "mkdirp": "0.5.x", 1170 | "nopt": "3.x", 1171 | "once": "1.x", 1172 | "resolve": "1.1.x", 1173 | "supports-color": "^3.1.0", 1174 | "which": "^1.1.1", 1175 | "wordwrap": "^1.0.0" 1176 | }, 1177 | "dependencies": { 1178 | "esprima": { 1179 | "version": "2.7.3", 1180 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", 1181 | "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", 1182 | "dev": true 1183 | }, 1184 | "has-flag": { 1185 | "version": "1.0.0", 1186 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", 1187 | "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", 1188 | "dev": true 1189 | }, 1190 | "supports-color": { 1191 | "version": "3.2.3", 1192 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", 1193 | "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", 1194 | "dev": true, 1195 | "requires": { 1196 | "has-flag": "^1.0.0" 1197 | } 1198 | } 1199 | } 1200 | }, 1201 | "js-yaml": { 1202 | "version": "3.12.0", 1203 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", 1204 | "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", 1205 | "dev": true, 1206 | "requires": { 1207 | "argparse": "^1.0.7", 1208 | "esprima": "^4.0.0" 1209 | }, 1210 | "dependencies": { 1211 | "esprima": { 1212 | "version": "4.0.1", 1213 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 1214 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 1215 | "dev": true 1216 | } 1217 | } 1218 | }, 1219 | "kind-of": { 1220 | "version": "6.0.2", 1221 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", 1222 | "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", 1223 | "dev": true 1224 | }, 1225 | "lcid": { 1226 | "version": "2.0.0", 1227 | "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", 1228 | "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", 1229 | "dev": true, 1230 | "requires": { 1231 | "invert-kv": "^2.0.0" 1232 | } 1233 | }, 1234 | "levn": { 1235 | "version": "0.3.0", 1236 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 1237 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 1238 | "dev": true, 1239 | "requires": { 1240 | "prelude-ls": "~1.1.2", 1241 | "type-check": "~0.3.2" 1242 | } 1243 | }, 1244 | "locate-path": { 1245 | "version": "3.0.0", 1246 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 1247 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 1248 | "dev": true, 1249 | "requires": { 1250 | "p-locate": "^3.0.0", 1251 | "path-exists": "^3.0.0" 1252 | } 1253 | }, 1254 | "lodash": { 1255 | "version": "4.17.11", 1256 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", 1257 | "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", 1258 | "dev": true 1259 | }, 1260 | "log-symbols": { 1261 | "version": "2.2.0", 1262 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", 1263 | "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", 1264 | "dev": true, 1265 | "requires": { 1266 | "chalk": "^2.0.1" 1267 | } 1268 | }, 1269 | "map-age-cleaner": { 1270 | "version": "0.1.3", 1271 | "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", 1272 | "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", 1273 | "dev": true, 1274 | "requires": { 1275 | "p-defer": "^1.0.0" 1276 | } 1277 | }, 1278 | "map-cache": { 1279 | "version": "0.2.2", 1280 | "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", 1281 | "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", 1282 | "dev": true 1283 | }, 1284 | "map-visit": { 1285 | "version": "1.0.0", 1286 | "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", 1287 | "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", 1288 | "dev": true, 1289 | "requires": { 1290 | "object-visit": "^1.0.0" 1291 | } 1292 | }, 1293 | "mem": { 1294 | "version": "4.2.0", 1295 | "resolved": "https://registry.npmjs.org/mem/-/mem-4.2.0.tgz", 1296 | "integrity": "sha512-5fJxa68urlY0Ir8ijatKa3eRz5lwXnRCTvo9+TbTGAuTFJOwpGcY0X05moBd0nW45965Njt4CDI2GFQoG8DvqA==", 1297 | "dev": true, 1298 | "requires": { 1299 | "map-age-cleaner": "^0.1.1", 1300 | "mimic-fn": "^2.0.0", 1301 | "p-is-promise": "^2.0.0" 1302 | } 1303 | }, 1304 | "micromatch": { 1305 | "version": "3.1.10", 1306 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", 1307 | "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", 1308 | "dev": true, 1309 | "requires": { 1310 | "arr-diff": "^4.0.0", 1311 | "array-unique": "^0.3.2", 1312 | "braces": "^2.3.1", 1313 | "define-property": "^2.0.2", 1314 | "extend-shallow": "^3.0.2", 1315 | "extglob": "^2.0.4", 1316 | "fragment-cache": "^0.2.1", 1317 | "kind-of": "^6.0.2", 1318 | "nanomatch": "^1.2.9", 1319 | "object.pick": "^1.3.0", 1320 | "regex-not": "^1.0.0", 1321 | "snapdragon": "^0.8.1", 1322 | "to-regex": "^3.0.2" 1323 | } 1324 | }, 1325 | "mimic-fn": { 1326 | "version": "2.0.0", 1327 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.0.0.tgz", 1328 | "integrity": "sha512-jbex9Yd/3lmICXwYT6gA/j2mNQGU48wCh/VzRd+/Y/PjYQtlg1gLMdZqvu9s/xH7qKvngxRObl56XZR609IMbA==", 1329 | "dev": true 1330 | }, 1331 | "minimatch": { 1332 | "version": "3.0.4", 1333 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1334 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1335 | "dev": true, 1336 | "requires": { 1337 | "brace-expansion": "^1.1.7" 1338 | } 1339 | }, 1340 | "minimist": { 1341 | "version": "0.0.8", 1342 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 1343 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 1344 | "dev": true 1345 | }, 1346 | "mixin-deep": { 1347 | "version": "1.3.1", 1348 | "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", 1349 | "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", 1350 | "dev": true, 1351 | "requires": { 1352 | "for-in": "^1.0.2", 1353 | "is-extendable": "^1.0.1" 1354 | }, 1355 | "dependencies": { 1356 | "is-extendable": { 1357 | "version": "1.0.1", 1358 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", 1359 | "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", 1360 | "dev": true, 1361 | "requires": { 1362 | "is-plain-object": "^2.0.4" 1363 | } 1364 | } 1365 | } 1366 | }, 1367 | "mkdirp": { 1368 | "version": "0.5.1", 1369 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 1370 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 1371 | "dev": true, 1372 | "requires": { 1373 | "minimist": "0.0.8" 1374 | } 1375 | }, 1376 | "mocha": { 1377 | "version": "6.0.2", 1378 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.0.2.tgz", 1379 | "integrity": "sha512-RtTJsmmToGyeTznSOMoM6TPEk1A84FQaHIciKrRqARZx+B5ccJ5tXlmJzEKGBxZdqk9UjpRsesZTUkZmR5YnuQ==", 1380 | "dev": true, 1381 | "requires": { 1382 | "ansi-colors": "3.2.3", 1383 | "browser-stdout": "1.3.1", 1384 | "debug": "3.2.6", 1385 | "diff": "3.5.0", 1386 | "escape-string-regexp": "1.0.5", 1387 | "findup-sync": "2.0.0", 1388 | "glob": "7.1.3", 1389 | "growl": "1.10.5", 1390 | "he": "1.2.0", 1391 | "js-yaml": "3.12.0", 1392 | "log-symbols": "2.2.0", 1393 | "minimatch": "3.0.4", 1394 | "mkdirp": "0.5.1", 1395 | "ms": "2.1.1", 1396 | "node-environment-flags": "1.0.4", 1397 | "object.assign": "4.1.0", 1398 | "strip-json-comments": "2.0.1", 1399 | "supports-color": "6.0.0", 1400 | "which": "1.3.1", 1401 | "wide-align": "1.1.3", 1402 | "yargs": "12.0.5", 1403 | "yargs-parser": "11.1.1", 1404 | "yargs-unparser": "1.5.0" 1405 | }, 1406 | "dependencies": { 1407 | "glob": { 1408 | "version": "7.1.3", 1409 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", 1410 | "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", 1411 | "dev": true, 1412 | "requires": { 1413 | "fs.realpath": "^1.0.0", 1414 | "inflight": "^1.0.4", 1415 | "inherits": "2", 1416 | "minimatch": "^3.0.4", 1417 | "once": "^1.3.0", 1418 | "path-is-absolute": "^1.0.0" 1419 | } 1420 | }, 1421 | "minimatch": { 1422 | "version": "3.0.4", 1423 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1424 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1425 | "dev": true, 1426 | "requires": { 1427 | "brace-expansion": "^1.1.7" 1428 | } 1429 | }, 1430 | "mkdirp": { 1431 | "version": "0.5.1", 1432 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 1433 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 1434 | "dev": true, 1435 | "requires": { 1436 | "minimist": "0.0.8" 1437 | } 1438 | }, 1439 | "which": { 1440 | "version": "1.3.1", 1441 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 1442 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 1443 | "dev": true, 1444 | "requires": { 1445 | "isexe": "^2.0.0" 1446 | } 1447 | } 1448 | } 1449 | }, 1450 | "ms": { 1451 | "version": "2.1.1", 1452 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 1453 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", 1454 | "dev": true 1455 | }, 1456 | "nanomatch": { 1457 | "version": "1.2.13", 1458 | "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", 1459 | "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", 1460 | "dev": true, 1461 | "requires": { 1462 | "arr-diff": "^4.0.0", 1463 | "array-unique": "^0.3.2", 1464 | "define-property": "^2.0.2", 1465 | "extend-shallow": "^3.0.2", 1466 | "fragment-cache": "^0.2.1", 1467 | "is-windows": "^1.0.2", 1468 | "kind-of": "^6.0.2", 1469 | "object.pick": "^1.3.0", 1470 | "regex-not": "^1.0.0", 1471 | "snapdragon": "^0.8.1", 1472 | "to-regex": "^3.0.1" 1473 | } 1474 | }, 1475 | "neo-async": { 1476 | "version": "2.6.0", 1477 | "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.0.tgz", 1478 | "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", 1479 | "dev": true 1480 | }, 1481 | "nice-try": { 1482 | "version": "1.0.5", 1483 | "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", 1484 | "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", 1485 | "dev": true 1486 | }, 1487 | "node-environment-flags": { 1488 | "version": "1.0.4", 1489 | "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.4.tgz", 1490 | "integrity": "sha512-M9rwCnWVLW7PX+NUWe3ejEdiLYinRpsEre9hMkU/6NS4h+EEulYaDH1gCEZ2gyXsmw+RXYDaV2JkkTNcsPDJ0Q==", 1491 | "dev": true, 1492 | "requires": { 1493 | "object.getownpropertydescriptors": "^2.0.3" 1494 | } 1495 | }, 1496 | "nopt": { 1497 | "version": "3.0.6", 1498 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", 1499 | "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", 1500 | "dev": true, 1501 | "requires": { 1502 | "abbrev": "1" 1503 | } 1504 | }, 1505 | "npm-run-path": { 1506 | "version": "2.0.2", 1507 | "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", 1508 | "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", 1509 | "dev": true, 1510 | "requires": { 1511 | "path-key": "^2.0.0" 1512 | } 1513 | }, 1514 | "number-is-nan": { 1515 | "version": "1.0.1", 1516 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", 1517 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", 1518 | "dev": true 1519 | }, 1520 | "object-copy": { 1521 | "version": "0.1.0", 1522 | "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", 1523 | "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", 1524 | "dev": true, 1525 | "requires": { 1526 | "copy-descriptor": "^0.1.0", 1527 | "define-property": "^0.2.5", 1528 | "kind-of": "^3.0.3" 1529 | }, 1530 | "dependencies": { 1531 | "define-property": { 1532 | "version": "0.2.5", 1533 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", 1534 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", 1535 | "dev": true, 1536 | "requires": { 1537 | "is-descriptor": "^0.1.0" 1538 | } 1539 | }, 1540 | "kind-of": { 1541 | "version": "3.2.2", 1542 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 1543 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 1544 | "dev": true, 1545 | "requires": { 1546 | "is-buffer": "^1.1.5" 1547 | } 1548 | } 1549 | } 1550 | }, 1551 | "object-keys": { 1552 | "version": "1.1.0", 1553 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz", 1554 | "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==", 1555 | "dev": true 1556 | }, 1557 | "object-visit": { 1558 | "version": "1.0.1", 1559 | "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", 1560 | "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", 1561 | "dev": true, 1562 | "requires": { 1563 | "isobject": "^3.0.0" 1564 | } 1565 | }, 1566 | "object.assign": { 1567 | "version": "4.1.0", 1568 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", 1569 | "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", 1570 | "dev": true, 1571 | "requires": { 1572 | "define-properties": "^1.1.2", 1573 | "function-bind": "^1.1.1", 1574 | "has-symbols": "^1.0.0", 1575 | "object-keys": "^1.0.11" 1576 | } 1577 | }, 1578 | "object.getownpropertydescriptors": { 1579 | "version": "2.0.3", 1580 | "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", 1581 | "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", 1582 | "dev": true, 1583 | "requires": { 1584 | "define-properties": "^1.1.2", 1585 | "es-abstract": "^1.5.1" 1586 | } 1587 | }, 1588 | "object.pick": { 1589 | "version": "1.3.0", 1590 | "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", 1591 | "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", 1592 | "dev": true, 1593 | "requires": { 1594 | "isobject": "^3.0.1" 1595 | } 1596 | }, 1597 | "once": { 1598 | "version": "1.4.0", 1599 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1600 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1601 | "dev": true, 1602 | "requires": { 1603 | "wrappy": "1" 1604 | } 1605 | }, 1606 | "optimist": { 1607 | "version": "0.6.1", 1608 | "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", 1609 | "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", 1610 | "dev": true, 1611 | "requires": { 1612 | "minimist": "~0.0.1", 1613 | "wordwrap": "~0.0.2" 1614 | }, 1615 | "dependencies": { 1616 | "wordwrap": { 1617 | "version": "0.0.3", 1618 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", 1619 | "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", 1620 | "dev": true 1621 | } 1622 | } 1623 | }, 1624 | "optionator": { 1625 | "version": "0.8.2", 1626 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", 1627 | "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", 1628 | "dev": true, 1629 | "requires": { 1630 | "deep-is": "~0.1.3", 1631 | "fast-levenshtein": "~2.0.4", 1632 | "levn": "~0.3.0", 1633 | "prelude-ls": "~1.1.2", 1634 | "type-check": "~0.3.2", 1635 | "wordwrap": "~1.0.0" 1636 | } 1637 | }, 1638 | "os-locale": { 1639 | "version": "3.1.0", 1640 | "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", 1641 | "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", 1642 | "dev": true, 1643 | "requires": { 1644 | "execa": "^1.0.0", 1645 | "lcid": "^2.0.0", 1646 | "mem": "^4.0.0" 1647 | } 1648 | }, 1649 | "p-defer": { 1650 | "version": "1.0.0", 1651 | "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", 1652 | "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", 1653 | "dev": true 1654 | }, 1655 | "p-finally": { 1656 | "version": "1.0.0", 1657 | "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", 1658 | "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", 1659 | "dev": true 1660 | }, 1661 | "p-is-promise": { 1662 | "version": "2.0.0", 1663 | "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.0.0.tgz", 1664 | "integrity": "sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg==", 1665 | "dev": true 1666 | }, 1667 | "p-limit": { 1668 | "version": "2.2.0", 1669 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz", 1670 | "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", 1671 | "dev": true, 1672 | "requires": { 1673 | "p-try": "^2.0.0" 1674 | } 1675 | }, 1676 | "p-locate": { 1677 | "version": "3.0.0", 1678 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 1679 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 1680 | "dev": true, 1681 | "requires": { 1682 | "p-limit": "^2.0.0" 1683 | } 1684 | }, 1685 | "p-try": { 1686 | "version": "2.1.0", 1687 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.1.0.tgz", 1688 | "integrity": "sha512-H2RyIJ7+A3rjkwKC2l5GGtU4H1vkxKCAGsWasNVd0Set+6i4znxbWy6/j16YDPJDWxhsgZiKAstMEP8wCdSpjA==", 1689 | "dev": true 1690 | }, 1691 | "parse-passwd": { 1692 | "version": "1.0.0", 1693 | "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", 1694 | "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", 1695 | "dev": true 1696 | }, 1697 | "pascalcase": { 1698 | "version": "0.1.1", 1699 | "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", 1700 | "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", 1701 | "dev": true 1702 | }, 1703 | "path-exists": { 1704 | "version": "3.0.0", 1705 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 1706 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 1707 | "dev": true 1708 | }, 1709 | "path-is-absolute": { 1710 | "version": "1.0.1", 1711 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1712 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1713 | "dev": true 1714 | }, 1715 | "path-key": { 1716 | "version": "2.0.1", 1717 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", 1718 | "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", 1719 | "dev": true 1720 | }, 1721 | "posix-character-classes": { 1722 | "version": "0.1.1", 1723 | "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", 1724 | "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", 1725 | "dev": true 1726 | }, 1727 | "prelude-ls": { 1728 | "version": "1.1.2", 1729 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 1730 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", 1731 | "dev": true 1732 | }, 1733 | "pump": { 1734 | "version": "3.0.0", 1735 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 1736 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 1737 | "dev": true, 1738 | "requires": { 1739 | "end-of-stream": "^1.1.0", 1740 | "once": "^1.3.1" 1741 | } 1742 | }, 1743 | "regex-not": { 1744 | "version": "1.0.2", 1745 | "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", 1746 | "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", 1747 | "dev": true, 1748 | "requires": { 1749 | "extend-shallow": "^3.0.2", 1750 | "safe-regex": "^1.1.0" 1751 | } 1752 | }, 1753 | "repeat-element": { 1754 | "version": "1.1.3", 1755 | "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", 1756 | "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", 1757 | "dev": true 1758 | }, 1759 | "repeat-string": { 1760 | "version": "1.6.1", 1761 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", 1762 | "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", 1763 | "dev": true 1764 | }, 1765 | "require-directory": { 1766 | "version": "2.1.1", 1767 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1768 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 1769 | "dev": true 1770 | }, 1771 | "require-main-filename": { 1772 | "version": "1.0.1", 1773 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", 1774 | "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", 1775 | "dev": true 1776 | }, 1777 | "resolve": { 1778 | "version": "1.1.7", 1779 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", 1780 | "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", 1781 | "dev": true 1782 | }, 1783 | "resolve-dir": { 1784 | "version": "1.0.1", 1785 | "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", 1786 | "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", 1787 | "dev": true, 1788 | "requires": { 1789 | "expand-tilde": "^2.0.0", 1790 | "global-modules": "^1.0.0" 1791 | } 1792 | }, 1793 | "resolve-url": { 1794 | "version": "0.2.1", 1795 | "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", 1796 | "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", 1797 | "dev": true 1798 | }, 1799 | "ret": { 1800 | "version": "0.1.15", 1801 | "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", 1802 | "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", 1803 | "dev": true 1804 | }, 1805 | "safe-regex": { 1806 | "version": "1.1.0", 1807 | "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", 1808 | "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", 1809 | "dev": true, 1810 | "requires": { 1811 | "ret": "~0.1.10" 1812 | } 1813 | }, 1814 | "semver": { 1815 | "version": "5.6.0", 1816 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", 1817 | "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", 1818 | "dev": true 1819 | }, 1820 | "set-blocking": { 1821 | "version": "2.0.0", 1822 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 1823 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", 1824 | "dev": true 1825 | }, 1826 | "set-value": { 1827 | "version": "2.0.0", 1828 | "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", 1829 | "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", 1830 | "dev": true, 1831 | "requires": { 1832 | "extend-shallow": "^2.0.1", 1833 | "is-extendable": "^0.1.1", 1834 | "is-plain-object": "^2.0.3", 1835 | "split-string": "^3.0.1" 1836 | }, 1837 | "dependencies": { 1838 | "extend-shallow": { 1839 | "version": "2.0.1", 1840 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 1841 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 1842 | "dev": true, 1843 | "requires": { 1844 | "is-extendable": "^0.1.0" 1845 | } 1846 | } 1847 | } 1848 | }, 1849 | "shebang-command": { 1850 | "version": "1.2.0", 1851 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 1852 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", 1853 | "dev": true, 1854 | "requires": { 1855 | "shebang-regex": "^1.0.0" 1856 | } 1857 | }, 1858 | "shebang-regex": { 1859 | "version": "1.0.0", 1860 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 1861 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", 1862 | "dev": true 1863 | }, 1864 | "signal-exit": { 1865 | "version": "3.0.2", 1866 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 1867 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", 1868 | "dev": true 1869 | }, 1870 | "snapdragon": { 1871 | "version": "0.8.2", 1872 | "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", 1873 | "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", 1874 | "dev": true, 1875 | "requires": { 1876 | "base": "^0.11.1", 1877 | "debug": "^2.2.0", 1878 | "define-property": "^0.2.5", 1879 | "extend-shallow": "^2.0.1", 1880 | "map-cache": "^0.2.2", 1881 | "source-map": "^0.5.6", 1882 | "source-map-resolve": "^0.5.0", 1883 | "use": "^3.1.0" 1884 | }, 1885 | "dependencies": { 1886 | "debug": { 1887 | "version": "2.6.9", 1888 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1889 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1890 | "dev": true, 1891 | "requires": { 1892 | "ms": "2.0.0" 1893 | } 1894 | }, 1895 | "define-property": { 1896 | "version": "0.2.5", 1897 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", 1898 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", 1899 | "dev": true, 1900 | "requires": { 1901 | "is-descriptor": "^0.1.0" 1902 | } 1903 | }, 1904 | "extend-shallow": { 1905 | "version": "2.0.1", 1906 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 1907 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 1908 | "dev": true, 1909 | "requires": { 1910 | "is-extendable": "^0.1.0" 1911 | } 1912 | }, 1913 | "ms": { 1914 | "version": "2.0.0", 1915 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1916 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 1917 | "dev": true 1918 | }, 1919 | "source-map": { 1920 | "version": "0.5.7", 1921 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 1922 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", 1923 | "dev": true 1924 | } 1925 | } 1926 | }, 1927 | "snapdragon-node": { 1928 | "version": "2.1.1", 1929 | "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", 1930 | "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", 1931 | "dev": true, 1932 | "requires": { 1933 | "define-property": "^1.0.0", 1934 | "isobject": "^3.0.0", 1935 | "snapdragon-util": "^3.0.1" 1936 | }, 1937 | "dependencies": { 1938 | "define-property": { 1939 | "version": "1.0.0", 1940 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", 1941 | "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", 1942 | "dev": true, 1943 | "requires": { 1944 | "is-descriptor": "^1.0.0" 1945 | } 1946 | }, 1947 | "is-accessor-descriptor": { 1948 | "version": "1.0.0", 1949 | "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", 1950 | "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", 1951 | "dev": true, 1952 | "requires": { 1953 | "kind-of": "^6.0.0" 1954 | } 1955 | }, 1956 | "is-data-descriptor": { 1957 | "version": "1.0.0", 1958 | "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", 1959 | "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", 1960 | "dev": true, 1961 | "requires": { 1962 | "kind-of": "^6.0.0" 1963 | } 1964 | }, 1965 | "is-descriptor": { 1966 | "version": "1.0.2", 1967 | "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", 1968 | "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", 1969 | "dev": true, 1970 | "requires": { 1971 | "is-accessor-descriptor": "^1.0.0", 1972 | "is-data-descriptor": "^1.0.0", 1973 | "kind-of": "^6.0.2" 1974 | } 1975 | } 1976 | } 1977 | }, 1978 | "snapdragon-util": { 1979 | "version": "3.0.1", 1980 | "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", 1981 | "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", 1982 | "dev": true, 1983 | "requires": { 1984 | "kind-of": "^3.2.0" 1985 | }, 1986 | "dependencies": { 1987 | "kind-of": { 1988 | "version": "3.2.2", 1989 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 1990 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 1991 | "dev": true, 1992 | "requires": { 1993 | "is-buffer": "^1.1.5" 1994 | } 1995 | } 1996 | } 1997 | }, 1998 | "source-map": { 1999 | "version": "0.2.0", 2000 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", 2001 | "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", 2002 | "dev": true, 2003 | "optional": true, 2004 | "requires": { 2005 | "amdefine": ">=0.0.4" 2006 | } 2007 | }, 2008 | "source-map-resolve": { 2009 | "version": "0.5.2", 2010 | "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", 2011 | "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", 2012 | "dev": true, 2013 | "requires": { 2014 | "atob": "^2.1.1", 2015 | "decode-uri-component": "^0.2.0", 2016 | "resolve-url": "^0.2.1", 2017 | "source-map-url": "^0.4.0", 2018 | "urix": "^0.1.0" 2019 | } 2020 | }, 2021 | "source-map-url": { 2022 | "version": "0.4.0", 2023 | "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", 2024 | "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", 2025 | "dev": true 2026 | }, 2027 | "split-string": { 2028 | "version": "3.1.0", 2029 | "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", 2030 | "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", 2031 | "dev": true, 2032 | "requires": { 2033 | "extend-shallow": "^3.0.0" 2034 | } 2035 | }, 2036 | "sprintf-js": { 2037 | "version": "1.0.3", 2038 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 2039 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 2040 | "dev": true 2041 | }, 2042 | "static-extend": { 2043 | "version": "0.1.2", 2044 | "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", 2045 | "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", 2046 | "dev": true, 2047 | "requires": { 2048 | "define-property": "^0.2.5", 2049 | "object-copy": "^0.1.0" 2050 | }, 2051 | "dependencies": { 2052 | "define-property": { 2053 | "version": "0.2.5", 2054 | "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", 2055 | "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", 2056 | "dev": true, 2057 | "requires": { 2058 | "is-descriptor": "^0.1.0" 2059 | } 2060 | } 2061 | } 2062 | }, 2063 | "string-width": { 2064 | "version": "2.1.1", 2065 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 2066 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 2067 | "dev": true, 2068 | "requires": { 2069 | "is-fullwidth-code-point": "^2.0.0", 2070 | "strip-ansi": "^4.0.0" 2071 | } 2072 | }, 2073 | "strip-ansi": { 2074 | "version": "4.0.0", 2075 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 2076 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 2077 | "dev": true, 2078 | "requires": { 2079 | "ansi-regex": "^3.0.0" 2080 | } 2081 | }, 2082 | "strip-eof": { 2083 | "version": "1.0.0", 2084 | "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", 2085 | "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", 2086 | "dev": true 2087 | }, 2088 | "strip-json-comments": { 2089 | "version": "2.0.1", 2090 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 2091 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 2092 | "dev": true 2093 | }, 2094 | "supports-color": { 2095 | "version": "6.0.0", 2096 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", 2097 | "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", 2098 | "dev": true, 2099 | "requires": { 2100 | "has-flag": "^3.0.0" 2101 | } 2102 | }, 2103 | "to-object-path": { 2104 | "version": "0.3.0", 2105 | "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", 2106 | "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", 2107 | "dev": true, 2108 | "requires": { 2109 | "kind-of": "^3.0.2" 2110 | }, 2111 | "dependencies": { 2112 | "kind-of": { 2113 | "version": "3.2.2", 2114 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 2115 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 2116 | "dev": true, 2117 | "requires": { 2118 | "is-buffer": "^1.1.5" 2119 | } 2120 | } 2121 | } 2122 | }, 2123 | "to-regex": { 2124 | "version": "3.0.2", 2125 | "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", 2126 | "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", 2127 | "dev": true, 2128 | "requires": { 2129 | "define-property": "^2.0.2", 2130 | "extend-shallow": "^3.0.2", 2131 | "regex-not": "^1.0.2", 2132 | "safe-regex": "^1.1.0" 2133 | } 2134 | }, 2135 | "to-regex-range": { 2136 | "version": "2.1.1", 2137 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", 2138 | "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", 2139 | "dev": true, 2140 | "requires": { 2141 | "is-number": "^3.0.0", 2142 | "repeat-string": "^1.6.1" 2143 | } 2144 | }, 2145 | "type-check": { 2146 | "version": "0.3.2", 2147 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 2148 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 2149 | "dev": true, 2150 | "requires": { 2151 | "prelude-ls": "~1.1.2" 2152 | } 2153 | }, 2154 | "uglify-js": { 2155 | "version": "3.4.10", 2156 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", 2157 | "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", 2158 | "dev": true, 2159 | "optional": true, 2160 | "requires": { 2161 | "commander": "~2.19.0", 2162 | "source-map": "~0.6.1" 2163 | }, 2164 | "dependencies": { 2165 | "source-map": { 2166 | "version": "0.6.1", 2167 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 2168 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 2169 | "dev": true, 2170 | "optional": true 2171 | } 2172 | } 2173 | }, 2174 | "union-value": { 2175 | "version": "1.0.0", 2176 | "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", 2177 | "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", 2178 | "dev": true, 2179 | "requires": { 2180 | "arr-union": "^3.1.0", 2181 | "get-value": "^2.0.6", 2182 | "is-extendable": "^0.1.1", 2183 | "set-value": "^0.4.3" 2184 | }, 2185 | "dependencies": { 2186 | "extend-shallow": { 2187 | "version": "2.0.1", 2188 | "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", 2189 | "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", 2190 | "dev": true, 2191 | "requires": { 2192 | "is-extendable": "^0.1.0" 2193 | } 2194 | }, 2195 | "set-value": { 2196 | "version": "0.4.3", 2197 | "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", 2198 | "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", 2199 | "dev": true, 2200 | "requires": { 2201 | "extend-shallow": "^2.0.1", 2202 | "is-extendable": "^0.1.1", 2203 | "is-plain-object": "^2.0.1", 2204 | "to-object-path": "^0.3.0" 2205 | } 2206 | } 2207 | } 2208 | }, 2209 | "unset-value": { 2210 | "version": "1.0.0", 2211 | "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", 2212 | "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", 2213 | "dev": true, 2214 | "requires": { 2215 | "has-value": "^0.3.1", 2216 | "isobject": "^3.0.0" 2217 | }, 2218 | "dependencies": { 2219 | "has-value": { 2220 | "version": "0.3.1", 2221 | "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", 2222 | "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", 2223 | "dev": true, 2224 | "requires": { 2225 | "get-value": "^2.0.3", 2226 | "has-values": "^0.1.4", 2227 | "isobject": "^2.0.0" 2228 | }, 2229 | "dependencies": { 2230 | "isobject": { 2231 | "version": "2.1.0", 2232 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", 2233 | "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", 2234 | "dev": true, 2235 | "requires": { 2236 | "isarray": "1.0.0" 2237 | } 2238 | } 2239 | } 2240 | }, 2241 | "has-values": { 2242 | "version": "0.1.4", 2243 | "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", 2244 | "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", 2245 | "dev": true 2246 | } 2247 | } 2248 | }, 2249 | "urix": { 2250 | "version": "0.1.0", 2251 | "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", 2252 | "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", 2253 | "dev": true 2254 | }, 2255 | "use": { 2256 | "version": "3.1.1", 2257 | "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", 2258 | "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", 2259 | "dev": true 2260 | }, 2261 | "which": { 2262 | "version": "1.3.1", 2263 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 2264 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 2265 | "dev": true, 2266 | "requires": { 2267 | "isexe": "^2.0.0" 2268 | } 2269 | }, 2270 | "which-module": { 2271 | "version": "2.0.0", 2272 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 2273 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", 2274 | "dev": true 2275 | }, 2276 | "wide-align": { 2277 | "version": "1.1.3", 2278 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", 2279 | "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", 2280 | "dev": true, 2281 | "requires": { 2282 | "string-width": "^1.0.2 || 2" 2283 | } 2284 | }, 2285 | "wordwrap": { 2286 | "version": "1.0.0", 2287 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", 2288 | "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", 2289 | "dev": true 2290 | }, 2291 | "wrap-ansi": { 2292 | "version": "2.1.0", 2293 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", 2294 | "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", 2295 | "dev": true, 2296 | "requires": { 2297 | "string-width": "^1.0.1", 2298 | "strip-ansi": "^3.0.1" 2299 | }, 2300 | "dependencies": { 2301 | "ansi-regex": { 2302 | "version": "2.1.1", 2303 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 2304 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", 2305 | "dev": true 2306 | }, 2307 | "is-fullwidth-code-point": { 2308 | "version": "1.0.0", 2309 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", 2310 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 2311 | "dev": true, 2312 | "requires": { 2313 | "number-is-nan": "^1.0.0" 2314 | } 2315 | }, 2316 | "string-width": { 2317 | "version": "1.0.2", 2318 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", 2319 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 2320 | "dev": true, 2321 | "requires": { 2322 | "code-point-at": "^1.0.0", 2323 | "is-fullwidth-code-point": "^1.0.0", 2324 | "strip-ansi": "^3.0.0" 2325 | } 2326 | }, 2327 | "strip-ansi": { 2328 | "version": "3.0.1", 2329 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 2330 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 2331 | "dev": true, 2332 | "requires": { 2333 | "ansi-regex": "^2.0.0" 2334 | } 2335 | } 2336 | } 2337 | }, 2338 | "wrappy": { 2339 | "version": "1.0.2", 2340 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2341 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 2342 | "dev": true 2343 | }, 2344 | "y18n": { 2345 | "version": "4.0.0", 2346 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", 2347 | "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", 2348 | "dev": true 2349 | }, 2350 | "yargs": { 2351 | "version": "12.0.5", 2352 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", 2353 | "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", 2354 | "dev": true, 2355 | "requires": { 2356 | "cliui": "^4.0.0", 2357 | "decamelize": "^1.2.0", 2358 | "find-up": "^3.0.0", 2359 | "get-caller-file": "^1.0.1", 2360 | "os-locale": "^3.0.0", 2361 | "require-directory": "^2.1.1", 2362 | "require-main-filename": "^1.0.1", 2363 | "set-blocking": "^2.0.0", 2364 | "string-width": "^2.0.0", 2365 | "which-module": "^2.0.0", 2366 | "y18n": "^3.2.1 || ^4.0.0", 2367 | "yargs-parser": "^11.1.1" 2368 | } 2369 | }, 2370 | "yargs-parser": { 2371 | "version": "11.1.1", 2372 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", 2373 | "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", 2374 | "dev": true, 2375 | "requires": { 2376 | "camelcase": "^5.0.0", 2377 | "decamelize": "^1.2.0" 2378 | } 2379 | }, 2380 | "yargs-unparser": { 2381 | "version": "1.5.0", 2382 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", 2383 | "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", 2384 | "dev": true, 2385 | "requires": { 2386 | "flat": "^4.1.0", 2387 | "lodash": "^4.17.11", 2388 | "yargs": "^12.0.5" 2389 | } 2390 | } 2391 | } 2392 | } 2393 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rocambole", 3 | "version": "0.8.0", 4 | "description": "Recursively walk and transform EcmaScript AST", 5 | "main": "rocambole.js", 6 | "directories": { 7 | "test": "test" 8 | }, 9 | "scripts": { 10 | "test": "istanbul test test/runner.js" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/millermedeiros/rocambole.git" 15 | }, 16 | "bugs": { 17 | "url": "https://github.com/millermedeiros/rocambole/issues" 18 | }, 19 | "keywords": [ 20 | "ast", 21 | "walk", 22 | "syntax", 23 | "source", 24 | "tree", 25 | "traversal", 26 | "falafel", 27 | "burrito", 28 | "esprima" 29 | ], 30 | "author": "Miller Medeiros ", 31 | "license": "MIT", 32 | "dependencies": { 33 | "esprima": "~4.0.0" 34 | }, 35 | "devDependencies": { 36 | "expect.js": "0.2", 37 | "istanbul": "~0.4.5", 38 | "mocha": "^6.0.2" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /rocambole.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/millermedeiros/rocambole/3acbab31b6f54e5fc6e09a5fbdf837bf4879c85e/rocambole.jpg -------------------------------------------------------------------------------- /rocambole.js: -------------------------------------------------------------------------------- 1 | /*jshint node:true */ 2 | "use strict"; 3 | 4 | 5 | var esprima = require('esprima'); 6 | 7 | 8 | 9 | // --- 10 | 11 | // we expose the flags so other tools can tweak the values (#8) 12 | exports.BYPASS_RECURSION = { 13 | root : true, 14 | comments : true, 15 | tokens : true, 16 | 17 | loc : true, 18 | range : true, 19 | 20 | parent : true, 21 | next : true, 22 | prev : true, 23 | 24 | // esprima@2.1 introduces a "handler" property on TryStatement in addition to 25 | // "handlers", which contains the same node, so we would 26 | // loop the same node twice (see jquery/esprima/issues/1031 and #264)` 27 | // 28 | // Instead, ignore the handlers list in favor of the standardized "handler" 29 | // property: https://github.com/eslint/eslint/issues/1930 30 | handlers : true, 31 | 32 | // IMPORTANT! "value" can't be bypassed since it is used by object 33 | // expression 34 | type : true, 35 | raw : true, 36 | 37 | startToken : true, 38 | endToken : true 39 | }; 40 | 41 | 42 | // --- 43 | 44 | var _addLocInfo; 45 | 46 | // --- 47 | 48 | exports.parseFn = esprima.parse; 49 | exports.parseContext = esprima; 50 | // we need range/tokens/comment info to build the tokens linked list! 51 | exports.parseOptions = { 52 | range: true, 53 | tokens: true, 54 | comment: true 55 | }; 56 | 57 | // parse string and return an augmented AST 58 | exports.parse = function parse(source, opts){ 59 | opts = opts || {}; 60 | _addLocInfo = Boolean(opts.loc); 61 | source = source.toString(); 62 | 63 | Object.keys(exports.parseOptions).forEach(function(key) { 64 | if (!(key in opts)) { 65 | opts[key] = exports.parseOptions[key]; 66 | } 67 | }); 68 | 69 | var ast = exports.parseFn.call(exports.parseContext, source, opts); 70 | 71 | // we augment just root node since program is "empty" 72 | // can't check `ast.body.length` because it might contain just comments 73 | if (!ast.tokens.length && !ast.comments.length) { 74 | ast.depth = 0; 75 | ast.startToken = ast.endToken = null; 76 | ast.toString = _nodeProto.toString; 77 | return ast; 78 | } 79 | 80 | instrumentTokens(ast, source); 81 | 82 | // update program range since it doesn't include white spaces and comments 83 | // before/after the program body by default 84 | var lastToken = ast.tokens[ast.tokens.length - 1]; 85 | ast.range[0] = ast.tokens[0].range[0]; 86 | ast.range[1] = lastToken.range[1]; 87 | if (_addLocInfo) { 88 | ast.loc.start.line = 0; 89 | ast.loc.start.column = 0; 90 | ast.loc.end.line = lastToken.loc.end.line; 91 | ast.loc.end.column = lastToken.loc.end.column; 92 | } 93 | 94 | var toString = _nodeProto.toString; 95 | var instrumentNodes = function(node, parent, prev, next){ 96 | 97 | node.parent = parent; 98 | node.prev = prev; 99 | node.next = next; 100 | node.depth = parent? parent.depth + 1 : 0; // used later for moonwalk 101 | 102 | node.toString = toString; 103 | 104 | // we do not add nextToken and prevToken to avoid updating even more 105 | // references during each remove/before/after you can grab the 106 | // prev/next token by simply accesing the startToken.prev and 107 | // endToken.next 108 | var prevToken = prev? prev.endToken : (parent? parent.startToken : null); 109 | var nextToken = parent? parent.endToken : null; 110 | node.startToken = prevToken? getNodeStartToken(prevToken, node.range) : ast.tokens[0]; 111 | node.endToken = nextToken? getNodeEndToken(nextToken, node.range) : ast.tokens[ast.tokens.length - 1]; 112 | }; 113 | recursiveWalk(ast, instrumentNodes); 114 | 115 | return ast; 116 | }; 117 | 118 | 119 | var _nodeProto = {}; 120 | 121 | // get the node string 122 | _nodeProto.toString = function(){ 123 | var str = ''; 124 | var token = this.startToken; 125 | if (!token) return str; 126 | do { 127 | str += ('raw' in token)? token.raw : token.value; 128 | token = token.next; 129 | } while (token && token !== this.endToken.next); 130 | return str; 131 | }; 132 | 133 | 134 | function getNodeStartToken(token, range){ 135 | var startRange = range[0]; 136 | while (token){ 137 | if (token.range[0] >= startRange) { 138 | return token; 139 | } 140 | token = token.next; 141 | } 142 | } 143 | 144 | function getNodeEndToken(token, range){ 145 | var endRange = range[1]; 146 | while (token){ 147 | if (token.range[1] <= endRange) { 148 | return token; 149 | } 150 | token = token.prev; 151 | } 152 | } 153 | 154 | 155 | 156 | function getPrevToken(tokens, range){ 157 | var result, token, 158 | startRange = range[0], 159 | n = tokens.length; 160 | while (n--) { 161 | token = tokens[n]; 162 | if (token.range[1] <= startRange) { 163 | result = token; 164 | break; 165 | } 166 | } 167 | return result; 168 | } 169 | 170 | 171 | 172 | 173 | 174 | 175 | function instrumentTokens(ast, source){ 176 | 177 | var tokens = ast.tokens; 178 | 179 | 180 | // --- inject comments into tokens list 181 | var comments = ast.comments; 182 | var comment, 183 | q = -1, 184 | nComments = comments.length; 185 | 186 | while (++q < nComments) { 187 | comment = comments[q]; 188 | // we edit it in place since it is faster, will also affect 189 | comment.raw = comment.type === 'Block'? '/*'+ comment.value +'*/' : '//'+ comment.value; 190 | comment.type += 'Comment'; 191 | 192 | var prevToken = getPrevToken(tokens, comment.range); 193 | var prevIndex = prevToken? tokens.indexOf(prevToken) : -1; 194 | tokens.splice(prevIndex + 1, 0, comment); 195 | } 196 | 197 | 198 | // --- inject white spaces and line breaks 199 | 200 | // we create a new array since it's simpler than using splice, it will 201 | // also avoid mistakes 202 | var result = []; 203 | 204 | // insert white spaces before start of program 205 | var wsTokens; 206 | var firstToken = ast.tokens[0]; 207 | var raw; 208 | if ( firstToken.range[0] ) { 209 | raw = source.substring(0, firstToken.range[0]); 210 | result = result.concat( getWhiteSpaceTokens(raw, null) ); 211 | } 212 | 213 | // insert white spaces between regular tokens 214 | // faster than forEach and reduce lookups 215 | var i = -1, 216 | nTokens = tokens.length, 217 | token, prev; 218 | var k, nWs; 219 | while (++i < nTokens) { 220 | token = tokens[i]; 221 | if (i) { 222 | if (prev.range[1] < token.range[0]) { 223 | wsTokens = getWhiteSpaceTokens(source.substring(prev.range[1], token.range[0]), prev); 224 | // faster than concat or push.apply 225 | k = -1; 226 | nWs = wsTokens.length; 227 | while (++k < nWs) { 228 | result.push(wsTokens[k]); 229 | } 230 | } 231 | } 232 | result.push(token); 233 | prev = token; 234 | } 235 | 236 | // insert white spaces after end of program 237 | var lastToken = ast.tokens[ast.tokens.length - 1]; 238 | if (lastToken.range[1] < source.length) { 239 | wsTokens = getWhiteSpaceTokens(source.substring(lastToken.range[1], source.length), lastToken); 240 | k = -1; 241 | nWs = wsTokens.length; 242 | while (++k < nWs) { 243 | result.push(wsTokens[k]); 244 | } 245 | } 246 | 247 | // --- instrument tokens 248 | 249 | // need to come afterwards since we add line breaks and comments 250 | var n; 251 | for (i = 0, n = result.length, token; i < n; i++) { 252 | token = result[i]; 253 | token.prev = i? result[i - 1] : undefined; 254 | token.next = result[i + 1]; 255 | token.root = ast; // used internally 256 | // original indent is very important for block comments since some 257 | // transformations require manipulation of raw comment value 258 | if ( 259 | token.type === 'BlockComment' && 260 | token.prev && token.prev.type === 'WhiteSpace' && 261 | (!token.prev.prev || (token.prev.prev.type === 'LineBreak')) 262 | ) { 263 | token.originalIndent = token.prev.value; 264 | } 265 | } 266 | 267 | ast.tokens = result; 268 | } 269 | 270 | 271 | function getWhiteSpaceTokens(raw, prev){ 272 | var whiteSpaces = getWhiteSpaces(raw); 273 | 274 | var startRange = prev? prev.range[1] : 0; 275 | // line starts at 1 !!! 276 | var startLine, startColumn; 277 | if (_addLocInfo) { 278 | startLine = prev? prev.loc.end.line : 1; 279 | startColumn = prev? prev.loc.end.column : 0; 280 | } 281 | 282 | var tokens = []; 283 | for (var i = 0, n = whiteSpaces.length, value; i < n; i++){ 284 | value = whiteSpaces[i]; 285 | 286 | var wsToken = { value : value }; 287 | var isBr = '\r\n'.indexOf(value) >= 0; 288 | wsToken.type = isBr? 'LineBreak' : 'WhiteSpace'; 289 | wsToken.range = [startRange, startRange + value.length]; 290 | 291 | if (_addLocInfo) { 292 | wsToken.loc = { 293 | start : { 294 | line : startLine, 295 | column : startColumn 296 | }, 297 | end : { 298 | line : startLine, // yes, br starts and end on same line 299 | column : startColumn + value.length 300 | } 301 | }; 302 | 303 | if (isBr) { 304 | // next token after a
always starts at zero and on next line 305 | startLine = wsToken.loc.end.line + 1; 306 | startColumn = 0; 307 | } else { 308 | startLine = wsToken.loc.end.line; 309 | startColumn = wsToken.loc.end.column; 310 | } 311 | } 312 | 313 | startRange += value.length; 314 | tokens.push(wsToken); 315 | } 316 | 317 | return tokens; 318 | } 319 | 320 | 321 | function getWhiteSpaces(source) { 322 | var result = []; 323 | var whiteSpaces = source.split(''); 324 | var buf = ''; 325 | for (var value, i = 0, nSpaces = whiteSpaces.length; i < nSpaces; i++) { 326 | value = whiteSpaces[i]; 327 | switch(value){ 328 | case '\n': 329 | if (buf === '\r') { 330 | // DOS line break 331 | result.push(buf + value); 332 | } else { 333 | if (buf) { 334 | result.push(buf); 335 | } 336 | // unix break 337 | result.push(value); 338 | } 339 | buf = ''; 340 | break; 341 | case '\r': 342 | // might be multiple consecutive Mac breaks 343 | if (buf) { 344 | result.push(buf); 345 | } 346 | buf = value; 347 | break; 348 | default: 349 | if (buf === '\r') { 350 | result.push(buf); 351 | buf = value; 352 | } else { 353 | // group multiple white spaces into same token 354 | buf += value; 355 | } 356 | } 357 | } 358 | if (buf) { 359 | result.push(buf); 360 | } 361 | return result; 362 | } 363 | 364 | 365 | 366 | exports.walk = exports.recursive = recursiveWalk; 367 | 368 | // heavily inspired by node-falafel 369 | // walk nodes recursively starting from root 370 | function recursiveWalk(node, fn, parent, prev, next){ 371 | // sparse arrays might have `null` elements, so we skip those for now 372 | // see issue #15 373 | if ( !node || fn(node, parent, prev, next) === false ) { 374 | return; // stop recursion 375 | } 376 | 377 | // faster than for in 378 | var keys = Object.keys(node), 379 | child, key; 380 | 381 | for (var i = 0, nKeys = keys.length; i < nKeys; i++) { 382 | 383 | key = keys[i]; 384 | child = node[key]; 385 | 386 | // only need to recurse real nodes and arrays 387 | // ps: typeof null == 'object' 388 | if (!child || typeof child !== 'object' || exports.BYPASS_RECURSION[key]) { 389 | continue; 390 | } 391 | 392 | // inception 393 | if (typeof child.type === 'string') { // faster than boolean coercion 394 | recursiveWalk(child, fn, node); 395 | } else if ( typeof child.length === 'number' ) { // faster than Array.isArray and boolean coercion 396 | // faster than forEach 397 | for (var k = 0, nChilds = child.length; k < nChilds; k++) { 398 | recursiveWalk(child[k], fn, node, (k? child[k - 1] : undefined), child[k + 1] ); 399 | } 400 | } 401 | 402 | } 403 | 404 | } 405 | 406 | 407 | 408 | // walk AST starting from leaf nodes 409 | exports.moonwalk = function moonwalk(ast, fn){ 410 | if (typeof ast === 'string') { 411 | ast = exports.parse(ast); 412 | } 413 | 414 | // we create a separate array for each depth and than we flatten it to 415 | // boost performance, way faster than doing an insertion sort 416 | var swap = []; 417 | recursiveWalk(ast, function(node){ 418 | if (! swap[node.depth]) { 419 | swap[node.depth] = []; 420 | } 421 | swap[node.depth].push(node); 422 | }); 423 | 424 | var nodes = []; 425 | var nDepths = swap.length, cur; 426 | while (cur = swap[--nDepths]) { 427 | for (var i = 0, n = cur.length; i < n; i++) { 428 | nodes.push(cur[i]); 429 | } 430 | } 431 | 432 | nodes.forEach(fn); 433 | return ast; 434 | }; 435 | 436 | -------------------------------------------------------------------------------- /test/files/crossroads.js: -------------------------------------------------------------------------------- 1 | /** @license 2 | * crossroads 3 | * License: MIT 4 | * Author: Miller Medeiros 5 | * Version: 0.11.0 (2012/10/31 21:44) 6 | */ 7 | 8 | (function (define) { 9 | define(['signals'], function (signals) { 10 | 11 | var crossroads, 12 | _hasOptionalGroupBug, 13 | UNDEF; 14 | 15 | // Helpers ----------- 16 | //==================== 17 | 18 | // IE 7-8 capture optional groups as empty strings while other browsers 19 | // capture as `undefined` 20 | _hasOptionalGroupBug = (/t(.+)?/).exec('t')[1] === ''; 21 | 22 | function arrayIndexOf(arr, val) { 23 | if (arr.indexOf) { 24 | return arr.indexOf(val); 25 | } else { 26 | //Array.indexOf doesn't work on IE 6-7 27 | var n = arr.length; 28 | while (n--) { 29 | if (arr[n] === val) { 30 | return n; 31 | } 32 | } 33 | return -1; 34 | } 35 | } 36 | 37 | function arrayRemove(arr, item) { 38 | var i = arrayIndexOf(arr, item); 39 | if (i !== -1) { 40 | arr.splice(i, 1); 41 | } 42 | } 43 | 44 | function isKind(val, kind) { 45 | return '[object '+ kind +']' === Object.prototype.toString.call(val); 46 | } 47 | 48 | function isRegExp(val) { 49 | return isKind(val, 'RegExp'); 50 | } 51 | 52 | function isArray(val) { 53 | return isKind(val, 'Array'); 54 | } 55 | 56 | function isFunction(val) { 57 | return typeof val === 'function'; 58 | } 59 | 60 | //borrowed from AMD-utils 61 | function typecastValue(val) { 62 | var r; 63 | if (val === null || val === 'null') { 64 | r = null; 65 | } else if (val === 'true') { 66 | r = true; 67 | } else if (val === 'false') { 68 | r = false; 69 | } else if (val === UNDEF || val === 'undefined') { 70 | r = UNDEF; 71 | } else if (val === '' || isNaN(val)) { 72 | //isNaN('') returns false 73 | r = val; 74 | } else { 75 | //parseFloat(null || '') returns NaN 76 | r = parseFloat(val); 77 | } 78 | return r; 79 | } 80 | 81 | function typecastArrayValues(values) { 82 | var n = values.length, 83 | result = []; 84 | while (n--) { 85 | result[n] = typecastValue(values[n]); 86 | } 87 | return result; 88 | } 89 | 90 | //borrowed from AMD-Utils 91 | function decodeQueryString(str, shouldTypecast) { 92 | var queryArr = (str || '').replace('?', '').split('&'), 93 | n = queryArr.length, 94 | obj = {}, 95 | item, val; 96 | while (n--) { 97 | item = queryArr[n].split('='); 98 | val = shouldTypecast ? typecastValue(item[1]) : item[1]; 99 | obj[item[0]] = (typeof val === 'string')? decodeURIComponent(val) : val; 100 | } 101 | return obj; 102 | } 103 | 104 | 105 | // Crossroads -------- 106 | //==================== 107 | 108 | /** 109 | * @constructor 110 | */ 111 | function Crossroads() { 112 | this.bypassed = new signals.Signal(); 113 | this.routed = new signals.Signal(); 114 | this._routes = []; 115 | this._prevRoutes = []; 116 | this._piped = []; 117 | this.resetState(); 118 | } 119 | 120 | Crossroads.prototype = { 121 | 122 | greedy : false, 123 | 124 | greedyEnabled : true, 125 | 126 | ignoreCase : true, 127 | 128 | ignoreState : false, 129 | 130 | shouldTypecast : false, 131 | 132 | normalizeFn : null, 133 | 134 | resetState : function(){ 135 | this._prevRoutes.length = 0; 136 | this._prevMatchedRequest = null; 137 | this._prevBypassedRequest = null; 138 | }, 139 | 140 | create : function () { 141 | return new Crossroads(); 142 | }, 143 | 144 | addRoute : function (pattern, callback, priority) { 145 | var route = new Route(pattern, callback, priority, this); 146 | this._sortedInsert(route); 147 | return route; 148 | }, 149 | 150 | removeRoute : function (route) { 151 | arrayRemove(this._routes, route); 152 | route._destroy(); 153 | }, 154 | 155 | removeAllRoutes : function () { 156 | var n = this.getNumRoutes(); 157 | while (n--) { 158 | this._routes[n]._destroy(); 159 | } 160 | this._routes.length = 0; 161 | }, 162 | 163 | parse : function (request, defaultArgs) { 164 | request = request || ''; 165 | defaultArgs = defaultArgs || []; 166 | 167 | // should only care about different requests if ignoreState isn't true 168 | if ( !this.ignoreState && 169 | (request === this._prevMatchedRequest || 170 | request === this._prevBypassedRequest) ) { 171 | return; 172 | } 173 | 174 | var routes = this._getMatchedRoutes(request), 175 | i = 0, 176 | n = routes.length, 177 | cur; 178 | 179 | if (n) { 180 | this._prevMatchedRequest = request; 181 | 182 | this._notifyPrevRoutes(routes, request); 183 | this._prevRoutes = routes; 184 | //should be incremental loop, execute routes in order 185 | while (i < n) { 186 | cur = routes[i]; 187 | cur.route.matched.dispatch.apply(cur.route.matched, defaultArgs.concat(cur.params)); 188 | cur.isFirst = !i; 189 | this.routed.dispatch.apply(this.routed, defaultArgs.concat([request, cur])); 190 | i += 1; 191 | } 192 | } else { 193 | this._prevBypassedRequest = request; 194 | this.bypassed.dispatch.apply(this.bypassed, defaultArgs.concat([request])); 195 | } 196 | 197 | this._pipeParse(request, defaultArgs); 198 | }, 199 | 200 | _notifyPrevRoutes : function(matchedRoutes, request) { 201 | var i = 0, prev; 202 | while (prev = this._prevRoutes[i++]) { 203 | //check if switched exist since route may be disposed 204 | if(prev.route.switched && this._didSwitch(prev.route, matchedRoutes)) { 205 | prev.route.switched.dispatch(request); 206 | } 207 | } 208 | }, 209 | 210 | _didSwitch : function (route, matchedRoutes){ 211 | var matched, 212 | i = 0; 213 | while (matched = matchedRoutes[i++]) { 214 | // only dispatch switched if it is going to a different route 215 | if (matched.route === route) { 216 | return false; 217 | } 218 | } 219 | return true; 220 | }, 221 | 222 | _pipeParse : function(request, defaultArgs) { 223 | var i = 0, route; 224 | while (route = this._piped[i++]) { 225 | route.parse(request, defaultArgs); 226 | } 227 | }, 228 | 229 | getNumRoutes : function () { 230 | return this._routes.length; 231 | }, 232 | 233 | _sortedInsert : function (route) { 234 | //simplified insertion sort 235 | var routes = this._routes, 236 | n = routes.length; 237 | do { --n; } while (routes[n] && route._priority <= routes[n]._priority); 238 | routes.splice(n+1, 0, route); 239 | }, 240 | 241 | _getMatchedRoutes : function (request) { 242 | var res = [], 243 | routes = this._routes, 244 | n = routes.length, 245 | route; 246 | //should be decrement loop since higher priorities are added at the end of array 247 | while (route = routes[--n]) { 248 | if ((!res.length || this.greedy || route.greedy) && route.match(request)) { 249 | res.push({ 250 | route : route, 251 | params : route._getParamsArray(request) 252 | }); 253 | } 254 | if (!this.greedyEnabled && res.length) { 255 | break; 256 | } 257 | } 258 | return res; 259 | }, 260 | 261 | pipe : function (otherRouter) { 262 | this._piped.push(otherRouter); 263 | }, 264 | 265 | unpipe : function (otherRouter) { 266 | arrayRemove(this._piped, otherRouter); 267 | }, 268 | 269 | toString : function () { 270 | return '[crossroads numRoutes:'+ this.getNumRoutes() +']'; 271 | } 272 | }; 273 | 274 | //"static" instance 275 | crossroads = new Crossroads(); 276 | crossroads.VERSION = '0.11.0'; 277 | 278 | crossroads.NORM_AS_ARRAY = function (req, vals) { 279 | return [vals.vals_]; 280 | }; 281 | 282 | crossroads.NORM_AS_OBJECT = function (req, vals) { 283 | return [vals]; 284 | }; 285 | 286 | 287 | // Route -------------- 288 | //===================== 289 | 290 | /** 291 | * @constructor 292 | */ 293 | function Route(pattern, callback, priority, router) { 294 | var isRegexPattern = isRegExp(pattern), 295 | patternLexer = crossroads.patternLexer; 296 | this._router = router; 297 | this._pattern = pattern; 298 | this._paramsIds = isRegexPattern? null : patternLexer.getParamIds(pattern); 299 | this._optionalParamsIds = isRegexPattern? null : patternLexer.getOptionalParamsIds(pattern); 300 | this._matchRegexp = isRegexPattern? pattern : patternLexer.compilePattern(pattern, router.ignoreCase); 301 | this.matched = new signals.Signal(); 302 | this.switched = new signals.Signal(); 303 | if (callback) { 304 | this.matched.add(callback); 305 | } 306 | this._priority = priority || 0; 307 | } 308 | 309 | Route.prototype = { 310 | 311 | greedy : false, 312 | 313 | rules : void(0), 314 | 315 | match : function (request) { 316 | request = request || ''; 317 | return this._matchRegexp.test(request) && this._validateParams(request); //validate params even if regexp because of `request_` rule. 318 | }, 319 | 320 | _validateParams : function (request) { 321 | var rules = this.rules, 322 | values = this._getParamsObject(request), 323 | key; 324 | for (key in rules) { 325 | // normalize_ isn't a validation rule... (#39) 326 | if(key !== 'normalize_' && rules.hasOwnProperty(key) && ! this._isValidParam(request, key, values)){ 327 | return false; 328 | } 329 | } 330 | return true; 331 | }, 332 | 333 | _isValidParam : function (request, prop, values) { 334 | var validationRule = this.rules[prop], 335 | val = values[prop], 336 | isValid = false, 337 | isQuery = (prop.indexOf('?') === 0); 338 | 339 | if (val == null && this._optionalParamsIds && arrayIndexOf(this._optionalParamsIds, prop) !== -1) { 340 | isValid = true; 341 | } 342 | else if (isRegExp(validationRule)) { 343 | if (isQuery) { 344 | val = values[prop +'_']; //use raw string 345 | } 346 | isValid = validationRule.test(val); 347 | } 348 | else if (isArray(validationRule)) { 349 | if (isQuery) { 350 | val = values[prop +'_']; //use raw string 351 | } 352 | isValid = this._isValidArrayRule(validationRule, val); 353 | } 354 | else if (isFunction(validationRule)) { 355 | isValid = validationRule(val, request, values); 356 | } 357 | 358 | return isValid; //fail silently if validationRule is from an unsupported type 359 | }, 360 | 361 | _isValidArrayRule : function (arr, val) { 362 | if (! this._router.ignoreCase) { 363 | return arrayIndexOf(arr, val) !== -1; 364 | } 365 | 366 | if (typeof val === 'string') { 367 | val = val.toLowerCase(); 368 | } 369 | 370 | var n = arr.length, 371 | item, 372 | compareVal; 373 | 374 | while (n--) { 375 | item = arr[n]; 376 | compareVal = (typeof item === 'string')? item.toLowerCase() : item; 377 | if (compareVal === val) { 378 | return true; 379 | } 380 | } 381 | return false; 382 | }, 383 | 384 | _getParamsObject : function (request) { 385 | var shouldTypecast = this._router.shouldTypecast, 386 | values = crossroads.patternLexer.getParamValues(request, this._matchRegexp, shouldTypecast), 387 | o = {}, 388 | n = values.length, 389 | param, val; 390 | while (n--) { 391 | val = values[n]; 392 | if (this._paramsIds) { 393 | param = this._paramsIds[n]; 394 | if (param.indexOf('?') === 0 && val) { 395 | //make a copy of the original string so array and 396 | //RegExp validation can be applied properly 397 | o[param +'_'] = val; 398 | //update vals_ array as well since it will be used 399 | //during dispatch 400 | val = decodeQueryString(val, shouldTypecast); 401 | values[n] = val; 402 | } 403 | // IE will capture optional groups as empty strings while other 404 | // browsers will capture `undefined` so normalize behavior. 405 | // see: #gh-58, #gh-59, #gh-60 406 | if ( _hasOptionalGroupBug && val === '' && arrayIndexOf(this._optionalParamsIds, param) !== -1 ) { 407 | val = void(0); 408 | values[n] = val; 409 | } 410 | o[param] = val; 411 | } 412 | //alias to paths and for RegExp pattern 413 | o[n] = val; 414 | } 415 | o.request_ = shouldTypecast? typecastValue(request) : request; 416 | o.vals_ = values; 417 | return o; 418 | }, 419 | 420 | _getParamsArray : function (request) { 421 | var norm = this.rules? this.rules.normalize_ : null, 422 | params; 423 | norm = norm || this._router.normalizeFn; // default normalize 424 | if (norm && isFunction(norm)) { 425 | params = norm(request, this._getParamsObject(request)); 426 | } else { 427 | params = this._getParamsObject(request).vals_; 428 | } 429 | return params; 430 | }, 431 | 432 | interpolate : function(replacements) { 433 | var str = crossroads.patternLexer.interpolate(this._pattern, replacements); 434 | if (! this._validateParams(str) ) { 435 | throw new Error('Generated string doesn\'t validate against `Route.rules`.'); 436 | } 437 | return str; 438 | }, 439 | 440 | dispose : function () { 441 | this._router.removeRoute(this); 442 | }, 443 | 444 | _destroy : function () { 445 | this.matched.dispose(); 446 | this.switched.dispose(); 447 | this.matched = this.switched = this._pattern = this._matchRegexp = null; 448 | }, 449 | 450 | toString : function () { 451 | return '[Route pattern:"'+ this._pattern +'", numListeners:'+ this.matched.getNumListeners() +']'; 452 | } 453 | 454 | }; 455 | 456 | 457 | 458 | // Pattern Lexer ------ 459 | //===================== 460 | 461 | crossroads.patternLexer = (function () { 462 | 463 | var 464 | //match chars that should be escaped on string regexp 465 | ESCAPE_CHARS_REGEXP = /[\\.+*?\^$\[\](){}\/'#]/g, 466 | 467 | //trailing slashes (begin/end of string) 468 | LOOSE_SLASHES_REGEXP = /^\/|\/$/g, 469 | LEGACY_SLASHES_REGEXP = /\/$/g, 470 | 471 | //params - everything between `{ }` or `: :` 472 | PARAMS_REGEXP = /(?:\{|:)([^}:]+)(?:\}|:)/g, 473 | 474 | //used to save params during compile (avoid escaping things that 475 | //shouldn't be escaped). 476 | TOKENS = { 477 | 'OS' : { 478 | //optional slashes 479 | //slash between `::` or `}:` or `\w:` or `:{?` or `}{?` or `\w{?` 480 | rgx : /([:}]|\w(?=\/))\/?(:|(?:\{\?))/g, 481 | save : '$1{{id}}$2', 482 | res : '\\/?' 483 | }, 484 | 'RS' : { 485 | //required slashes 486 | //used to insert slash between `:{` and `}{` 487 | rgx : /([:}])\/?(\{)/g, 488 | save : '$1{{id}}$2', 489 | res : '\\/' 490 | }, 491 | 'RQ' : { 492 | //required query string - everything in between `{? }` 493 | rgx : /\{\?([^}]+)\}/g, 494 | //everything from `?` till `#` or end of string 495 | res : '\\?([^#]+)' 496 | }, 497 | 'OQ' : { 498 | //optional query string - everything in between `:? :` 499 | rgx : /:\?([^:]+):/g, 500 | //everything from `?` till `#` or end of string 501 | res : '(?:\\?([^#]*))?' 502 | }, 503 | 'OR' : { 504 | //optional rest - everything in between `: *:` 505 | rgx : /:([^:]+)\*:/g, 506 | res : '(.*)?' // optional group to avoid passing empty string as captured 507 | }, 508 | 'RR' : { 509 | //rest param - everything in between `{ *}` 510 | rgx : /\{([^}]+)\*\}/g, 511 | res : '(.+)' 512 | }, 513 | // required/optional params should come after rest segments 514 | 'RP' : { 515 | //required params - everything between `{ }` 516 | rgx : /\{([^}]+)\}/g, 517 | res : '([^\\/?]+)' 518 | }, 519 | 'OP' : { 520 | //optional params - everything between `: :` 521 | rgx : /:([^:]+):/g, 522 | res : '([^\\/?]+)?\/?' 523 | } 524 | }, 525 | 526 | LOOSE_SLASH = 1, 527 | STRICT_SLASH = 2, 528 | LEGACY_SLASH = 3, 529 | 530 | _slashMode = LOOSE_SLASH; 531 | 532 | 533 | function precompileTokens(){ 534 | var key, cur; 535 | for (key in TOKENS) { 536 | if (TOKENS.hasOwnProperty(key)) { 537 | cur = TOKENS[key]; 538 | cur.id = '__CR_'+ key +'__'; 539 | cur.save = ('save' in cur)? cur.save.replace('{{id}}', cur.id) : cur.id; 540 | cur.rRestore = new RegExp(cur.id, 'g'); 541 | } 542 | } 543 | } 544 | precompileTokens(); 545 | 546 | 547 | function captureVals(regex, pattern) { 548 | var vals = [], match; 549 | // very important to reset lastIndex since RegExp can have "g" flag 550 | // and multiple runs might affect the result, specially if matching 551 | // same string multiple times on IE 7-8 552 | regex.lastIndex = 0; 553 | while (match = regex.exec(pattern)) { 554 | vals.push(match[1]); 555 | } 556 | return vals; 557 | } 558 | 559 | function getParamIds(pattern) { 560 | return captureVals(PARAMS_REGEXP, pattern); 561 | } 562 | 563 | function getOptionalParamsIds(pattern) { 564 | return captureVals(TOKENS.OP.rgx, pattern); 565 | } 566 | 567 | function compilePattern(pattern, ignoreCase) { 568 | pattern = pattern || ''; 569 | 570 | if(pattern){ 571 | if (_slashMode === LOOSE_SLASH) { 572 | pattern = pattern.replace(LOOSE_SLASHES_REGEXP, ''); 573 | } 574 | else if (_slashMode === LEGACY_SLASH) { 575 | pattern = pattern.replace(LEGACY_SLASHES_REGEXP, ''); 576 | } 577 | 578 | //save tokens 579 | pattern = replaceTokens(pattern, 'rgx', 'save'); 580 | //regexp escape 581 | pattern = pattern.replace(ESCAPE_CHARS_REGEXP, '\\$&'); 582 | //restore tokens 583 | pattern = replaceTokens(pattern, 'rRestore', 'res'); 584 | 585 | if (_slashMode === LOOSE_SLASH) { 586 | pattern = '\\/?'+ pattern; 587 | } 588 | } 589 | 590 | if (_slashMode !== STRICT_SLASH) { 591 | //single slash is treated as empty and end slash is optional 592 | pattern += '\\/?'; 593 | } 594 | return new RegExp('^'+ pattern + '$', ignoreCase? 'i' : ''); 595 | } 596 | 597 | function replaceTokens(pattern, regexpName, replaceName) { 598 | var cur, key; 599 | for (key in TOKENS) { 600 | if (TOKENS.hasOwnProperty(key)) { 601 | cur = TOKENS[key]; 602 | pattern = pattern.replace(cur[regexpName], cur[replaceName]); 603 | } 604 | } 605 | return pattern; 606 | } 607 | 608 | function getParamValues(request, regexp, shouldTypecast) { 609 | var vals = regexp.exec(request); 610 | if (vals) { 611 | vals.shift(); 612 | if (shouldTypecast) { 613 | vals = typecastArrayValues(vals); 614 | } 615 | } 616 | return vals; 617 | } 618 | 619 | function interpolate(pattern, replacements) { 620 | if (typeof pattern !== 'string') { 621 | throw new Error('Route pattern should be a string.'); 622 | } 623 | 624 | var replaceFn = function(match, prop){ 625 | var val; 626 | if (prop in replacements) { 627 | // make sure value is a string see #gh-54 628 | val = String(replacements[prop]); 629 | if (match.indexOf('*') === -1 && val.indexOf('/') !== -1) { 630 | throw new Error('Invalid value "'+ val +'" for segment "'+ match +'".'); 631 | } 632 | } 633 | else if (match.indexOf('{') !== -1) { 634 | throw new Error('The segment '+ match +' is required.'); 635 | } 636 | else { 637 | val = ''; 638 | } 639 | return val; 640 | }; 641 | 642 | if (! TOKENS.OS.trail) { 643 | TOKENS.OS.trail = new RegExp('(?:'+ TOKENS.OS.id +')+$'); 644 | } 645 | 646 | return pattern 647 | .replace(TOKENS.OS.rgx, TOKENS.OS.save) 648 | .replace(PARAMS_REGEXP, replaceFn) 649 | .replace(TOKENS.OS.trail, '') // remove trailing 650 | .replace(TOKENS.OS.rRestore, '/'); // add slash between segments 651 | } 652 | 653 | //API 654 | return { 655 | strict : function(){ 656 | _slashMode = STRICT_SLASH; 657 | }, 658 | loose : function(){ 659 | _slashMode = LOOSE_SLASH; 660 | }, 661 | legacy : function(){ 662 | _slashMode = LEGACY_SLASH; 663 | }, 664 | getParamIds : getParamIds, 665 | getOptionalParamsIds : getOptionalParamsIds, 666 | getParamValues : getParamValues, 667 | compilePattern : compilePattern, 668 | interpolate : interpolate 669 | }; 670 | 671 | }()); 672 | 673 | 674 | return crossroads; 675 | }); 676 | }(typeof define === 'function' && define.amd ? define : function (deps, factory) { 677 | if (typeof module !== 'undefined' && module.exports) { //Node 678 | module.exports = factory(require(deps[0])); 679 | } else { 680 | /*jshint sub:true */ 681 | window['crossroads'] = factory(window[deps[0]]); 682 | } 683 | })); 684 | -------------------------------------------------------------------------------- /test/moonwalk.spec.js: -------------------------------------------------------------------------------- 1 | /* globals describe:false, it:false */ 2 | /* jshint node:true */ 3 | "use strict"; 4 | 5 | 6 | var expect = require('expect.js'); 7 | var rocambole = require('../'); 8 | 9 | 10 | describe('moonwalk()', function () { 11 | 12 | it('should generate AST if first arg is a string', function () { 13 | var count = 0; 14 | var ast = rocambole.moonwalk("function fn(x){\n var foo = 'bar';\n if (x) {\n foo += 'baz';\n } else {\n foo += 's';\n }\n return foo;\n}", function(){ 15 | count++; 16 | }); 17 | expect( ast.body ).not.to.be(undefined); 18 | expect( ast.tokens ).not.to.be(undefined); 19 | expect( count ).to.be.greaterThan( 1 ); 20 | }); 21 | 22 | it('should work with existing AST', function () { 23 | var ast = rocambole.parse("function fn(x){\n var foo = 'bar';\n if (x) {\n foo += 'baz';\n } else {\n foo += 's';\n }\n return foo;\n}"); 24 | var count = 0; 25 | rocambole.moonwalk(ast, function(){ 26 | count++; 27 | }); 28 | expect( count ).to.be.greaterThan( 1 ); 29 | }); 30 | 31 | it('should walk AST starting from leaf nodes until it reaches the root', function () { 32 | var prevDepth = Infinity; 33 | var count = 0; 34 | var prevNode; 35 | rocambole.moonwalk("function fn(x){\n var foo = 'bar';\n if (x) {\n foo += 'baz';\n } else {\n foo += 's';\n }\n return foo;\n}", function(node){ 36 | count++; 37 | expect( node.depth <= prevDepth ).to.be( true ); 38 | prevDepth = node.depth; 39 | prevNode = node; 40 | }); 41 | expect( count ).to.be.greaterThan( 1 ); 42 | expect( prevNode.type ).to.be( 'Program' ); // reached root 43 | }); 44 | 45 | it('should skip null nodes', function(){ 46 | var count = 0; 47 | rocambole.moonwalk('[,3,[,4]]', function () { 48 | count++; 49 | }); 50 | expect(count).to.be(6); 51 | }); 52 | 53 | }); 54 | 55 | 56 | describe('recursive()', function () { 57 | 58 | it('should allow breaking the loop', function () { 59 | var ast = rocambole.parse('function fn(x){ return x * 2 }'); 60 | var count_1 = 0; 61 | rocambole.recursive(ast, function(){ 62 | count_1 += 1; 63 | }); 64 | var count_2 = 0; 65 | rocambole.recursive(ast, function(node){ 66 | count_2 += 1; 67 | if (node.type === 'BlockStatement') { 68 | return false; // break 69 | } 70 | }); 71 | expect( count_1 ).to.be( 9 ); 72 | expect( count_2 ).to.be( 5 ); 73 | }); 74 | 75 | it('should be aliased as walk() to avoid confusions', function () { 76 | expect( rocambole.walk ).to.be( rocambole.recursive ); 77 | }); 78 | 79 | }); 80 | 81 | 82 | -------------------------------------------------------------------------------- /test/parse.spec.js: -------------------------------------------------------------------------------- 1 | /*global describe:false, it:false, beforeEach:false, afterEach:false */ 2 | "use strict"; 3 | 4 | var expect = require('expect.js'); 5 | var rocambole = require('../'); 6 | 7 | 8 | describe('parse', function () { 9 | 10 | it('should parse string and return AST', function () { 11 | var ast = rocambole.parse('(function(){ return 123 })'); 12 | expect( ast.type ).to.equal( 'Program' ); 13 | expect( ast.body[0].type ).to.equal( 'ExpressionStatement' ); 14 | }); 15 | 16 | 17 | it('should include tokens before and after "program" end', function () { 18 | var ast = rocambole.parse('//foo\n(function(){ return 123 })\n//bar\n'); 19 | expect( ast.startToken.value ).to.equal( 'foo' ); 20 | expect( ast.endToken.value ).to.equal( '\n' ); 21 | ast = rocambole.parse('\n//foo\n(function(){ return 123 })\n//dolor'); 22 | expect( ast.startToken.value ).to.equal( '\n' ); 23 | expect( ast.endToken.value ).to.equal( 'dolor' ); 24 | }); 25 | 26 | 27 | it('should work with any kind of line breaks & spaces', function () { 28 | var ast = rocambole.parse('\nvar n\r\n=\n10;\r\r \t\t \n', {loc : true}); 29 | 30 | var br_1 = ast.startToken; 31 | expect( br_1.type ).to.be( 'LineBreak' ); 32 | expect( br_1.value ).to.be( '\n' ); 33 | expect( br_1.range ).to.eql( [0, 1] ); 34 | expect( br_1.loc ).to.eql({ 35 | start : { 36 | line : 1, 37 | column : 0 38 | }, 39 | end : { 40 | line : 1, 41 | column : 1 42 | } 43 | }); 44 | 45 | var ws_1 = ast.startToken.next.next; 46 | expect( ws_1.type ).to.be( 'WhiteSpace' ); 47 | expect( ws_1.value ).to.be( ' ' ); 48 | 49 | var br_2 = br_1.next.next.next.next; 50 | expect( br_2.type ).to.be( 'LineBreak' ); 51 | expect( br_2.value ).to.be( '\r\n' ); 52 | expect( br_2.range ).to.eql( [6, 8] ); 53 | expect( br_2.loc ).to.eql({ 54 | start : { 55 | line : 2, 56 | column : 5 57 | }, 58 | end : { 59 | line : 2, 60 | column : 7 61 | } 62 | }); 63 | 64 | // it's important to notice that esprima doesn't parse "\r" as line 65 | // break, so if it is not at EOF it will give conflicting "loc" info. 66 | var br_6 = ast.endToken; 67 | expect( br_6.type ).to.be( 'LineBreak' ); 68 | expect( br_6.value ).to.be( '\n' ); 69 | expect( br_6.range ).to.eql( [21, 22] ); 70 | expect( br_6.loc ).to.eql({ 71 | start : { 72 | line : 6, 73 | column : 6 74 | }, 75 | end : { 76 | line : 6, 77 | column : 7 78 | } 79 | }); 80 | 81 | var ws_2 = ast.endToken.prev; 82 | expect( ws_2.type ).to.be( 'WhiteSpace' ); 83 | expect( ws_2.value ).to.be( ' \t\t ' ); 84 | expect( ws_2.range ).to.eql( [15, 21] ); 85 | expect( ws_2.loc ).to.eql({ 86 | start : { 87 | line : 6, 88 | column : 0 89 | }, 90 | end : { 91 | line : 6, 92 | column : 6 93 | } 94 | }); 95 | 96 | var br_5 = ws_2.prev; 97 | expect( br_5.type ).to.be( 'LineBreak' ); 98 | expect( br_5.value ).to.be( '\r' ); 99 | 100 | var br_4 = br_5.prev; 101 | expect( br_4.type ).to.be( 'LineBreak' ); 102 | expect( br_4.value ).to.be( '\r' ); 103 | }); 104 | 105 | 106 | it('should not include any char that isn\'t a white space on a WhiteSpace token [issue #3]', function () { 107 | var ast = rocambole.parse("\n/* foo */\n/* bar */\nfunction foo(){\n var bar = 'baz';\n\n //foo\n //bar\n\n var lorem = 'ipsum';\n return bar + lorem;\n}"); 108 | var tk = ast.startToken; 109 | var nComments = 0; 110 | while (tk) { 111 | if (tk.type === 'WhiteSpace') { 112 | expect( tk.value ).to.match( /^[\s\t]+$/ ); 113 | } else if (tk.type === 'LineBreak') { 114 | expect( tk.value ).to.equal( '\n' ); 115 | } else if (tk.type === 'LineComment') { 116 | expect( tk.raw ).to.match( /^\/\/\w{3}$/ ); 117 | nComments++; 118 | } else if (tk.type === 'BlockComment') { 119 | expect( tk.raw ).to.match( /^\/\* \w{3} \*\/$/ ); 120 | nComments++; 121 | } 122 | tk = tk.next; 123 | } 124 | expect( nComments ).to.be( 4 ); 125 | }); 126 | 127 | 128 | it('should instrument object expression "value" node', function () { 129 | // this was a bug introduced while trying to improve performance 130 | var ast = rocambole.parse('amet(123, a, {flag : true});'); 131 | var exp = ast.body[0].expression; 132 | expect( exp.startToken ).not.to.be(undefined); 133 | expect( exp.callee.startToken ).not.to.be(undefined); 134 | expect( exp['arguments'][0].startToken ).not.to.be(undefined); 135 | expect( exp['arguments'][1].startToken ).not.to.be(undefined); 136 | expect( exp['arguments'][2].startToken ).not.to.be(undefined); 137 | expect( exp['arguments'][2].properties[0].startToken ).not.to.be(undefined); 138 | expect( exp['arguments'][2].properties[0].key.startToken ).not.to.be(undefined); 139 | expect( exp['arguments'][2].properties[0].value.startToken ).not.to.be(undefined); 140 | }); 141 | 142 | 143 | 144 | describe('Node', function () { 145 | 146 | var ast, program, expressionStatement, 147 | fnExpression, block, returnStatement; 148 | 149 | beforeEach(function(){ 150 | ast = rocambole.parse('/* block */\n(function(){\n return 123; // line\n})'); 151 | program = ast; 152 | expressionStatement = ast.body[0]; 153 | fnExpression = expressionStatement.expression; 154 | block = fnExpression.body; 155 | returnStatement = block.body[0]; 156 | }); 157 | 158 | describe('node.parent', function () { 159 | it('should add reference to parent node', function () { 160 | expect( program.parent ).to.equal( undefined ); 161 | expect( expressionStatement.parent ).to.equal( program ); 162 | expect( fnExpression.parent ).to.equal( expressionStatement ); 163 | expect( block.parent ).to.equal( fnExpression ); 164 | }); 165 | }); 166 | 167 | 168 | describe('node.toString()', function(){ 169 | it('should return the node source', function () { 170 | expect( returnStatement.type ).to.equal( 'ReturnStatement' ); 171 | expect( returnStatement.toString() ).to.equal( 'return 123;' ); 172 | }); 173 | it('should use raw value of comments', function () { 174 | expect( block.toString() ).to.equal( '{\n return 123; // line\n}' ); 175 | }); 176 | it('should use raw value of comments', function () { 177 | expect( ast.toString() ).to.equal( '/* block */\n(function(){\n return 123; // line\n})' ); 178 | }); 179 | }); 180 | 181 | 182 | describe('depth', function () { 183 | it('should add depth property to nodes', function () { 184 | expect( program.depth ).to.equal( 0 ); 185 | expect( expressionStatement.depth ).to.equal( 1 ); 186 | expect( fnExpression.depth ).to.equal( 2 ); 187 | expect( block.depth ).to.equal( 3 ); 188 | expect( returnStatement.depth ).to.equal( 4 ); 189 | }); 190 | }); 191 | 192 | 193 | describe('node.endToken', function () { 194 | it('should return last token inside node', function () { 195 | expect( program.endToken.value ).to.equal( ')' ); 196 | expect( expressionStatement.endToken.value ).to.equal( ')' ); 197 | expect( fnExpression.endToken.value ).to.equal( '}' ); 198 | expect( block.endToken.value ).to.equal( '}' ); 199 | expect( returnStatement.endToken.value ).to.equal( ';' ); 200 | }); 201 | 202 | it('should capture end token properly', function () { 203 | var ast = rocambole.parse('[1,2,[3,4,[5,6,[7,8,9]]]];'); 204 | var exp = ast.body[0].expression; 205 | expect( exp.endToken.value ).to.equal( ']' ); 206 | expect( exp.elements[0].value ).to.equal( 1 ); 207 | expect( exp.elements[0].startToken.value ).to.equal( '1' ); 208 | expect( exp.elements[0].endToken.value ).to.equal( '1' ); 209 | }); 210 | }); 211 | 212 | 213 | describe('node.startToken', function () { 214 | it('should return first token inside node', function () { 215 | expect( program.startToken.value ).to.equal( ' block ' ); 216 | expect( expressionStatement.startToken.value ).to.equal( '(' ); 217 | expect( fnExpression.startToken.value ).to.equal( 'function' ); 218 | expect( block.startToken.value ).to.equal( '{' ); 219 | expect( returnStatement.startToken.value ).to.equal( 'return' ); 220 | }); 221 | }); 222 | 223 | 224 | describe('Node.next & Node.prev', function () { 225 | it('should return reference to previous and next nodes', function () { 226 | var ast = rocambole.parse("\n/* foo */\n/* bar */\nfunction foo(){\n var bar = 'baz';\n var lorem = 'ipsum';\n return bar + lorem;\n}"); 227 | var block = ast.body[0].body.body; 228 | var firstNode = block[0]; 229 | var secondNode = block[1]; 230 | var lastNode = block[2]; 231 | expect( firstNode.prev ).to.equal( undefined ); 232 | expect( firstNode.next ).to.equal( secondNode ); 233 | expect( secondNode.prev ).to.equal( firstNode ); 234 | expect( secondNode.next ).to.equal( lastNode ); 235 | expect( lastNode.prev ).to.equal( secondNode ); 236 | expect( lastNode.next ).to.equal( undefined ); 237 | }); 238 | }); 239 | 240 | }); 241 | 242 | 243 | describe('Token', function () { 244 | 245 | it('should instrument tokens', function () { 246 | var ast = rocambole.parse('function foo(){ return "bar"; }'); 247 | var tokens = ast.tokens; 248 | 249 | expect( tokens[0].prev ).to.be(undefined); 250 | expect( tokens[0].next ).to.be( tokens[1] ); 251 | expect( tokens[1].prev ).to.be( tokens[0] ); 252 | expect( tokens[1].next ).to.be( tokens[2] ); 253 | }); 254 | 255 | it('should add range and loc info to comment tokens', function () { 256 | var ast = rocambole.parse('\n/* foo\n bar\n*/\nfunction foo(){ return "bar"; }\n// end', {loc:true}); 257 | var blockComment = ast.startToken.next; 258 | expect( blockComment.range ).to.eql( [1, 16] ); 259 | expect( blockComment.loc ).to.eql({ 260 | start : { 261 | line : 2, 262 | column : 0 263 | }, 264 | end : { 265 | line : 4, 266 | column : 2 267 | } 268 | }); 269 | var lineComment = ast.endToken; 270 | expect( lineComment.range ).to.eql( [49, 55] ); 271 | expect( lineComment.loc ).to.eql({ 272 | start : { 273 | line : 6, 274 | column : 0 275 | }, 276 | end : { 277 | line : 6, 278 | column : 6 279 | } 280 | }); 281 | }); 282 | 283 | it('should add originalIndent info to block comments', function () { 284 | var ast = rocambole.parse(' /* foo */\n\t\t// bar'); 285 | expect( ast.startToken.next.originalIndent ).to.be(' '); 286 | }); 287 | 288 | it('should not add originalIndent info to line comments', function () { 289 | var ast = rocambole.parse(' /* foo */\n\t\t// bar'); 290 | expect( ast.endToken.originalIndent ).to.be(undefined); 291 | }); 292 | 293 | it('should not add as originalIndent if prev token is not white space', function () { 294 | var ast = rocambole.parse('lorem;/* foo */\n\t\t// bar'); 295 | expect( ast.startToken.next.next.originalIndent ).to.be(undefined); 296 | }); 297 | 298 | it('should not add as originalIndent if prev token is not on a new line', function () { 299 | var ast = rocambole.parse('lorem; /* foo */\n\t\t// bar'); 300 | expect( ast.startToken.next.next.next.originalIndent ).to.be(undefined); 301 | }); 302 | 303 | it('should add as originalIndent if on a new line', function () { 304 | var ast = rocambole.parse('lorem;\n /* foo */\n\t\t// bar'); 305 | expect( ast.startToken.next.next.next.next.originalIndent ).to.be(' '); 306 | }); 307 | }); 308 | 309 | 310 | describe('export BYPASS_RECURSION', function () { 311 | it('should export BYPASS_RECURSION', function () { 312 | expect( rocambole.BYPASS_RECURSION.root ).to.be(true); 313 | }); 314 | }); 315 | 316 | 317 | describe('empty program', function () { 318 | it('should not throw if program is empty', function () { 319 | expect(function(){ 320 | rocambole.parse(''); 321 | }).not.throwError(); 322 | }); 323 | it('should return augmented AST', function () { 324 | var ast = rocambole.parse(''); 325 | expect(ast).to.eql({ 326 | type: 'Program', 327 | sourceType: 'script', 328 | body: [], 329 | range: [0,0], 330 | comments: [], 331 | tokens: [], 332 | // we check toString behavior later 333 | toString: ast.toString, 334 | startToken: null, 335 | endToken: null, 336 | depth: 0 337 | }); 338 | }); 339 | it('toString should return proper value', function() { 340 | var ast = rocambole.parse(''); 341 | expect(ast.toString()).to.be(''); 342 | }); 343 | }); 344 | 345 | 346 | describe('support anything that implements `toString` as input', function () { 347 | it('should support arrays', function () { 348 | var ast = rocambole.parse([1,2,3]); 349 | expect(ast.body[0].toString()).to.eql('1,2,3'); 350 | }); 351 | it('should support functions', function () { 352 | var ast = rocambole.parse(function doStuff(){ 353 | doStuff(1, 2); 354 | }); 355 | expect(ast.body[0].type).to.be('FunctionDeclaration'); 356 | }); 357 | }); 358 | 359 | 360 | describe('sparse array', function() { 361 | // yes, people shold not be writting code like this, but we should not 362 | // bail when that happens 363 | it('should not fail on sparse arrays', function() { 364 | var ast = rocambole.parse('[,3,[,4]]'); 365 | expect(ast.toString()).to.eql('[,3,[,4]]'); 366 | var elements = ast.body[0].expression.elements; 367 | expect(elements[0]).to.be(null); 368 | expect(elements[1].type).to.be('Literal'); 369 | expect(elements[1].value).to.be(3); 370 | }); 371 | }); 372 | 373 | describe('custom parseFn', function() { 374 | var _parseFn; 375 | var _parseContext; 376 | var _parseOptions; 377 | var empty = { 378 | type: 'Program', 379 | body: [], 380 | range: [0,0], 381 | comments: [], 382 | tokens: [] 383 | }; 384 | 385 | beforeEach(function() { 386 | _parseFn = rocambole.parseFn; 387 | _parseContext = rocambole.parseContext; 388 | _parseOptions = rocambole.parseOptions; 389 | }); 390 | 391 | afterEach(function() { 392 | rocambole.parseFn = _parseFn; 393 | rocambole.parseContext = _parseContext; 394 | rocambole.parseOptions = _parseOptions; 395 | rocambole.parseOptions.tokens = true; 396 | }); 397 | 398 | it('should allow global override of parseFn', function() { 399 | var obj = {}; 400 | 401 | expect(rocambole.parseOptions).to.eql({ 402 | range: true, 403 | comment: true, 404 | tokens: true 405 | }); 406 | 407 | rocambole.parseOptions.tokens = 567; 408 | 409 | rocambole.parseContext = obj; 410 | rocambole.parseFn = function(source, opts) { 411 | expect(this).to.be(obj); 412 | expect(opts).to.eql({ 413 | loc: true, 414 | foo: 'bar', 415 | range: 123, 416 | tokens: 567, 417 | comment: true 418 | }); 419 | expect(source).to.eql('bar()'); 420 | return empty; 421 | }; 422 | var result = rocambole.parse('bar()', { 423 | loc: true, 424 | foo: 'bar', 425 | range: 123 426 | }); 427 | expect(result).to.be(empty); 428 | }); 429 | 430 | }); 431 | 432 | }); 433 | 434 | -------------------------------------------------------------------------------- /test/perf.spec.js: -------------------------------------------------------------------------------- 1 | /*global describe:false, it:false */ 2 | "use strict"; 3 | 4 | var expect = require('expect.js'); 5 | var rocambole = require('../'); 6 | 7 | var _fs = require('fs'); 8 | 9 | // since it takes a long time to instrument jQuery we avoid doing it multiple 10 | // times and cache the result 11 | var _jqueryAST; 12 | 13 | 14 | describe('performance', function () { 15 | this.timeout(10000); 16 | 17 | describe('rocambole.parse', function () { 18 | it('should be fast :P', function () { 19 | var file = _fs.readFileSync( __dirname +'/files/crossroads.js', 'utf-8'); 20 | var startTime = process.hrtime(); 21 | var ast = rocambole.parse(file); 22 | var diff = process.hrtime(startTime); 23 | expect( diff[0] ).to.be.below( 300 ); 24 | expect( ast.startToken ).not.to.be( undefined ); 25 | }); 26 | 27 | it('should not take forever to instrument jQuery', function () { 28 | var file = _fs.readFileSync( __dirname +'/files/jquery.js', 'utf-8'); 29 | var startTime = process.hrtime(); 30 | var ast = rocambole.parse(file); 31 | var diff = process.hrtime(startTime); 32 | expect( diff[0] ).to.be.below( 10000 ); 33 | expect( ast.startToken ).not.to.be( undefined ); 34 | _jqueryAST = ast; 35 | }); 36 | }); 37 | 38 | describe('rocambole.moonwalk', function () { 39 | it('should not take forever to loop over jQuery nodes', function () { 40 | if (! _jqueryAST) { 41 | var file = _fs.readFileSync( __dirname +'/files/jquery.js', 'utf-8'); 42 | _jqueryAST = rocambole.parse(file); 43 | } 44 | var startTime = process.hrtime(); 45 | var count = 0; 46 | rocambole.moonwalk(_jqueryAST, function(node){ 47 | if (!node) throw new Error('node should not be undefined'); 48 | count += 1; 49 | }); 50 | var diff = process.hrtime(startTime); 51 | expect( diff[0] ).to.be.below( 200 ); 52 | expect( count ).to.be.above( 20000 ); 53 | }); 54 | }); 55 | 56 | }); 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /test/runner.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // we run mocha manually otherwise istanbul coverage won't work 4 | // run `npm test --coverage` to generate coverage report 5 | 6 | var Mocha = require('mocha'); 7 | 8 | var opts = { 9 | ui : 'bdd', 10 | reporter : (process.env.REPORTER || 'spec'), 11 | grep : process.env.GREP 12 | }; 13 | 14 | // we use the dot reporter on travis since it works better 15 | if (process.env.TRAVIS) { 16 | opts.reporter = 'dot'; 17 | } 18 | 19 | var m = new Mocha(opts); 20 | 21 | if (process.env.INVERT) { 22 | m.invert(); 23 | } 24 | 25 | m.addFile('test/parse.spec.js'); 26 | m.addFile('test/moonwalk.spec.js'); 27 | m.addFile('test/perf.spec.js'); 28 | 29 | m.run(function(err){ 30 | var exitCode = err? 1 : 0; 31 | process.exit(exitCode); 32 | }); 33 | 34 | --------------------------------------------------------------------------------