From 3bcb272efb5bdf9070a78bc5ac0d873725c63b7f Mon Sep 17 00:00:00 2001 From: Chris Hutchison Date: Sun, 15 Apr 2018 16:52:42 -0400 Subject: [PATCH 1/5] save --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 559ffaa..ae1924b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -uswgi==2.0.17 +uwsgi==2.0.17 From a9d38e5d1d0b855273c41b9fc31472579143c758 Mon Sep 17 00:00:00 2001 From: Chris Hutchison Date: Mon, 16 Apr 2018 00:44:45 -0400 Subject: [PATCH 2/5] save --- node_modules/.bin/acorn | 1 + node_modules/.bin/bower | 1 + node_modules/.bin/cleancss | 1 + node_modules/.bin/jade | 1 + node_modules/.bin/mkdirp | 1 + node_modules/.bin/r.js | 1 + node_modules/.bin/r_js | 1 + node_modules/.bin/uglifyjs | 1 + node_modules/.yarn-integrity | 71 + node_modules/acorn-globals/LICENSE | 19 + node_modules/acorn-globals/README.md | 76 + node_modules/acorn-globals/index.js | 180 + .../acorn-globals/node_modules/.bin/acorn | 1 + node_modules/acorn-globals/package.json | 34 + node_modules/acorn/.editorconfig | 7 + node_modules/acorn/.gitattributes | 1 + node_modules/acorn/.npmignore | 3 + node_modules/acorn/.tern-project | 6 + node_modules/acorn/.travis.yml | 6 + node_modules/acorn/AUTHORS | 43 + node_modules/acorn/LICENSE | 19 + node_modules/acorn/README.md | 396 + node_modules/acorn/bin/acorn | 71 + node_modules/acorn/bin/build-acorn.js | 82 + .../acorn/bin/generate-identifier-regex.js | 47 + node_modules/acorn/bin/update_authors.sh | 6 + node_modules/acorn/package.json | 41 + node_modules/acorn/src/bin/acorn.js | 59 + node_modules/acorn/src/expression.js | 707 + node_modules/acorn/src/identifier.js | 90 + node_modules/acorn/src/index.js | 67 + node_modules/acorn/src/location.js | 24 + node_modules/acorn/src/locutil.js | 42 + node_modules/acorn/src/loose/acorn_loose.js | 0 node_modules/acorn/src/loose/expression.js | 501 + node_modules/acorn/src/loose/index.js | 50 + node_modules/acorn/src/loose/parseutil.js | 1 + node_modules/acorn/src/loose/state.js | 160 + node_modules/acorn/src/loose/statement.js | 420 + node_modules/acorn/src/loose/tokenize.js | 108 + node_modules/acorn/src/lval.js | 215 + node_modules/acorn/src/node.js | 50 + node_modules/acorn/src/options.js | 121 + node_modules/acorn/src/parseutil.js | 102 + node_modules/acorn/src/state.js | 104 + node_modules/acorn/src/statement.js | 626 + node_modules/acorn/src/tokencontext.js | 109 + node_modules/acorn/src/tokenize.js | 682 + node_modules/acorn/src/tokentype.js | 147 + node_modules/acorn/src/util.js | 9 + node_modules/acorn/src/walk/index.js | 340 + node_modules/acorn/src/whitespace.js | 12 + node_modules/align-text/LICENSE | 21 + node_modules/align-text/README.md | 236 + node_modules/align-text/index.js | 52 + node_modules/align-text/package.json | 52 + node_modules/almond/LICENSE | 45 + node_modules/almond/README.md | 246 + node_modules/almond/almond.js | 434 + node_modules/almond/package.json | 20 + node_modules/amdefine/LICENSE | 58 + node_modules/amdefine/README.md | 171 + node_modules/amdefine/amdefine.js | 301 + node_modules/amdefine/intercept.js | 36 + node_modules/amdefine/package.json | 16 + node_modules/asap/LICENSE.md | 20 + node_modules/asap/README.md | 81 + node_modules/asap/asap.js | 113 + node_modules/asap/package.json | 13 + node_modules/bower/CHANGELOG.md | 674 + node_modules/bower/LICENSE | 19 + node_modules/bower/README.md | 200 + node_modules/bower/bin/bower | 3 + node_modules/bower/package.json | 27 + node_modules/camelcase/index.js | 27 + node_modules/camelcase/license | 21 + node_modules/camelcase/package.json | 38 + node_modules/camelcase/readme.md | 56 + node_modules/center-align/LICENSE | 21 + node_modules/center-align/README.md | 74 + node_modules/center-align/index.js | 16 + node_modules/center-align/package.json | 51 + node_modules/center-align/utils.js | 40 + node_modules/character-parser/.npmignore | 2 + node_modules/character-parser/LICENSE | 19 + node_modules/character-parser/README.md | 142 + node_modules/character-parser/index.js | 231 + node_modules/character-parser/package.json | 29 + node_modules/clean-css/History.md | 1138 + node_modules/clean-css/LICENSE | 19 + node_modules/clean-css/README.md | 369 + node_modules/clean-css/bin/cleancss | 184 + node_modules/clean-css/index.js | 1 + .../node_modules/commander/History.md | 256 + .../clean-css/node_modules/commander/LICENSE | 22 + .../node_modules/commander/Readme.md | 342 + .../clean-css/node_modules/commander/index.js | 1103 + .../node_modules/commander/package.json | 33 + node_modules/clean-css/package.json | 53 + node_modules/cliui/.coveralls.yml | 1 + node_modules/cliui/.npmignore | 2 + node_modules/cliui/.travis.yml | 7 + node_modules/cliui/LICENSE.txt | 14 + node_modules/cliui/README.md | 104 + node_modules/cliui/index.js | 273 + node_modules/cliui/package.json | 59 + node_modules/cliui/test/cliui.js | 349 + node_modules/commander/History.md | 222 + node_modules/commander/Readme.md | 300 + node_modules/commander/index.js | 1020 + node_modules/commander/package.json | 14 + node_modules/constantinople/.gitattributes | 22 + node_modules/constantinople/.npmignore | 13 + node_modules/constantinople/.travis.yml | 3 + node_modules/constantinople/LICENSE | 19 + node_modules/constantinople/README.md | 42 + node_modules/constantinople/index.js | 100 + .../constantinople/node_modules/.bin/acorn | 1 + node_modules/constantinople/package.json | 21 + node_modules/constantinople/test/index.js | 71 + node_modules/css-parse/.npmignore | 6 + node_modules/css-parse/History.md | 30 + node_modules/css-parse/Makefile | 7 + node_modules/css-parse/Readme.md | 62 + node_modules/css-parse/component.json | 8 + node_modules/css-parse/index.js | 265 + node_modules/css-parse/package.json | 12 + node_modules/css-stringify/.npmignore | 6 + node_modules/css-stringify/History.md | 30 + node_modules/css-stringify/Makefile | 7 + node_modules/css-stringify/Readme.md | 33 + node_modules/css-stringify/component.json | 8 + node_modules/css-stringify/index.js | 182 + node_modules/css-stringify/package.json | 13 + node_modules/css/.npmignore | 4 + node_modules/css/History.md | 20 + node_modules/css/Makefile | 8 + node_modules/css/Readme.md | 77 + node_modules/css/benchmark.js | 36 + node_modules/css/component.json | 13 + node_modules/css/index.js | 3 + node_modules/css/package.json | 12 + node_modules/css/test.js | 6 + node_modules/decamelize/index.js | 13 + node_modules/decamelize/license | 21 + node_modules/decamelize/package.json | 38 + node_modules/decamelize/readme.md | 48 + node_modules/graceful-readlink/.npmignore | 3 + node_modules/graceful-readlink/.travis.yml | 5 + node_modules/graceful-readlink/LICENSE | 22 + node_modules/graceful-readlink/README.md | 17 + node_modules/graceful-readlink/index.js | 12 + node_modules/graceful-readlink/package.json | 18 + node_modules/is-buffer/LICENSE | 21 + node_modules/is-buffer/README.md | 53 + node_modules/is-buffer/index.js | 21 + node_modules/is-buffer/package.json | 51 + node_modules/is-buffer/test/basic.js | 24 + node_modules/is-promise/.npmignore | 6 + node_modules/is-promise/.travis.yml | 3 + node_modules/is-promise/LICENSE | 19 + node_modules/is-promise/index.js | 5 + node_modules/is-promise/package.json | 19 + node_modules/is-promise/readme.md | 29 + node_modules/jade/.npmignore | 15 + node_modules/jade/.release.json | 1 + node_modules/jade/History.md | 991 + node_modules/jade/LICENSE | 22 + node_modules/jade/README.md | 154 + node_modules/jade/Readme_zh-cn.md | 1285 + node_modules/jade/bin/jade.js | 295 + node_modules/jade/block-code.html | 0 node_modules/jade/component.json | 16 + node_modules/jade/jade.js | 9196 +++++ node_modules/jade/node_modules/.bin/cleancss | 1 + node_modules/jade/node_modules/.bin/mkdirp | 1 + node_modules/jade/node_modules/.bin/uglifyjs | 1 + node_modules/jade/package.json | 94 + node_modules/jade/release.js | 35 + node_modules/jade/runtime.js | 252 + node_modules/jstransformer/LICENSE | 19 + node_modules/jstransformer/README.md | 103 + node_modules/jstransformer/index.js | 328 + node_modules/jstransformer/package.json | 32 + node_modules/kind-of/LICENSE | 21 + node_modules/kind-of/README.md | 261 + node_modules/kind-of/index.js | 116 + node_modules/kind-of/package.json | 90 + node_modules/lazy-cache/LICENSE | 21 + node_modules/lazy-cache/README.md | 147 + node_modules/lazy-cache/index.js | 67 + node_modules/lazy-cache/package.json | 58 + node_modules/longest/LICENSE | 21 + node_modules/longest/README.md | 65 + node_modules/longest/index.js | 37 + node_modules/longest/package.json | 43 + node_modules/minimist/.travis.yml | 4 + node_modules/minimist/LICENSE | 18 + node_modules/minimist/example/parse.js | 2 + node_modules/minimist/index.js | 187 + node_modules/minimist/package.json | 40 + node_modules/minimist/readme.markdown | 73 + node_modules/minimist/test/dash.js | 24 + node_modules/minimist/test/default_bool.js | 20 + node_modules/minimist/test/dotted.js | 16 + node_modules/minimist/test/long.js | 31 + node_modules/minimist/test/parse.js | 318 + node_modules/minimist/test/parse_modified.js | 9 + node_modules/minimist/test/short.js | 67 + node_modules/minimist/test/whitespace.js | 8 + node_modules/mkdirp/.travis.yml | 8 + node_modules/mkdirp/LICENSE | 21 + node_modules/mkdirp/bin/cmd.js | 33 + node_modules/mkdirp/bin/usage.txt | 12 + node_modules/mkdirp/examples/pow.js | 6 + node_modules/mkdirp/index.js | 98 + node_modules/mkdirp/package.json | 27 + node_modules/mkdirp/readme.markdown | 100 + node_modules/mkdirp/test/chmod.js | 41 + node_modules/mkdirp/test/clobber.js | 38 + node_modules/mkdirp/test/mkdirp.js | 28 + node_modules/mkdirp/test/opts_fs.js | 29 + node_modules/mkdirp/test/opts_fs_sync.js | 27 + node_modules/mkdirp/test/perm.js | 32 + node_modules/mkdirp/test/perm_sync.js | 36 + node_modules/mkdirp/test/race.js | 37 + node_modules/mkdirp/test/rel.js | 32 + node_modules/mkdirp/test/return.js | 25 + node_modules/mkdirp/test/return_sync.js | 24 + node_modules/mkdirp/test/root.js | 19 + node_modules/mkdirp/test/sync.js | 32 + node_modules/mkdirp/test/umask.js | 28 + node_modules/mkdirp/test/umask_sync.js | 32 + node_modules/optimist/.travis.yml | 4 + node_modules/optimist/LICENSE | 21 + node_modules/optimist/example/bool.js | 10 + .../optimist/example/boolean_double.js | 7 + .../optimist/example/boolean_single.js | 7 + node_modules/optimist/example/default_hash.js | 8 + .../optimist/example/default_singles.js | 7 + node_modules/optimist/example/divide.js | 8 + node_modules/optimist/example/line_count.js | 20 + .../optimist/example/line_count_options.js | 29 + .../optimist/example/line_count_wrap.js | 29 + node_modules/optimist/example/nonopt.js | 4 + node_modules/optimist/example/reflect.js | 2 + node_modules/optimist/example/short.js | 3 + node_modules/optimist/example/string.js | 11 + .../optimist/example/usage-options.js | 19 + node_modules/optimist/example/xup.js | 10 + node_modules/optimist/index.js | 478 + .../optimist/node_modules/wordwrap/LICENSE | 18 + .../node_modules/wordwrap/README.markdown | 70 + .../node_modules/wordwrap/example/center.js | 10 + .../node_modules/wordwrap/example/meat.js | 3 + .../optimist/node_modules/wordwrap/index.js | 76 + .../node_modules/wordwrap/package.json | 37 + .../node_modules/wordwrap/test/break.js | 30 + .../node_modules/wordwrap/test/idleness.txt | 63 + .../node_modules/wordwrap/test/wrap.js | 31 + node_modules/optimist/package.json | 38 + node_modules/optimist/readme.markdown | 487 + node_modules/optimist/test/_.js | 71 + node_modules/optimist/test/_/argv.js | 2 + node_modules/optimist/test/_/bin.js | 3 + node_modules/optimist/test/parse.js | 446 + node_modules/optimist/test/usage.js | 292 + node_modules/promise/.jshintrc | 5 + node_modules/promise/.npmignore | 6 + node_modules/promise/LICENSE | 19 + node_modules/promise/Readme.md | 221 + node_modules/promise/core.js | 5 + node_modules/promise/index.js | 6 + node_modules/promise/package.json | 25 + node_modules/promise/polyfill-done.js | 12 + node_modules/promise/polyfill.js | 10 + node_modules/repeat-string/LICENSE | 21 + node_modules/repeat-string/README.md | 136 + node_modules/repeat-string/index.js | 70 + node_modules/repeat-string/package.json | 77 + node_modules/requirejs-text/LICENSE | 45 + node_modules/requirejs-text/README.md | 206 + node_modules/requirejs-text/bower.json | 6 + node_modules/requirejs-text/package.json | 21 + node_modules/requirejs-text/text.js | 408 + node_modules/requirejs/README.md | 9 + node_modules/requirejs/bin/r.js | 30420 ++++++++++++++++ node_modules/requirejs/package.json | 20 + node_modules/requirejs/require.js | 2145 ++ node_modules/right-align/LICENSE | 21 + node_modules/right-align/README.md | 77 + node_modules/right-align/index.js | 16 + node_modules/right-align/package.json | 45 + node_modules/source-map/README.md | 510 + node_modules/source-map/package.json | 68 + node_modules/transformers/.npmignore | 2 + node_modules/transformers/README.md | 141 + node_modules/transformers/history.md | 77 + .../transformers/node_modules/.bin/uglifyjs | 1 + .../node_modules/is-promise/.npmignore | 6 + .../node_modules/is-promise/.travis.yml | 3 + .../node_modules/is-promise/LICENSE | 19 + .../node_modules/is-promise/index.js | 5 + .../node_modules/is-promise/package.json | 19 + .../node_modules/is-promise/readme.md | 29 + .../node_modules/promise/.npmignore | 6 + .../node_modules/promise/Readme.md | 85 + .../node_modules/promise/index.js | 164 + .../node_modules/promise/package.json | 23 + .../node_modules/source-map/.npmignore | 2 + .../node_modules/source-map/.travis.yml | 4 + .../node_modules/source-map/CHANGELOG.md | 194 + .../node_modules/source-map/LICENSE | 28 + .../source-map/Makefile.dryice.js | 166 + .../node_modules/source-map/README.md | 475 + .../node_modules/source-map/package.json | 65 + .../node_modules/source-map/test/run-tests.js | 62 + .../source-map/test/source-map/test-api.js | 26 + .../test/source-map/test-array-set.js | 104 + .../test/source-map/test-base64-vlq.js | 23 + .../source-map/test/source-map/test-base64.js | 35 + .../test/source-map/test-binary-search.js | 54 + .../test/source-map/test-dog-fooding.js | 84 + .../source-map/test-source-map-consumer.js | 702 + .../source-map/test-source-map-generator.js | 679 + .../test/source-map/test-source-node.js | 612 + .../source-map/test/source-map/test-util.js | 216 + .../source-map/test/source-map/util.js | 192 + .../node_modules/uglify-js/.npmignore | 2 + .../node_modules/uglify-js/README.md | 544 + .../node_modules/uglify-js/bin/uglifyjs | 370 + .../node_modules/uglify-js/package.json | 25 + .../uglify-js/test/compress/arrays.js | 12 + .../uglify-js/test/compress/blocks.js | 49 + .../uglify-js/test/compress/conditionals.js | 143 + .../uglify-js/test/compress/dead-code.js | 89 + .../uglify-js/test/compress/debugger.js | 24 + .../uglify-js/test/compress/drop-unused.js | 97 + .../uglify-js/test/compress/issue-105.js | 17 + .../uglify-js/test/compress/issue-12.js | 11 + .../uglify-js/test/compress/issue-22.js | 17 + .../uglify-js/test/compress/issue-44.js | 31 + .../uglify-js/test/compress/issue-59.js | 30 + .../uglify-js/test/compress/labels.js | 163 + .../uglify-js/test/compress/loops.js | 123 + .../uglify-js/test/compress/properties.js | 25 + .../uglify-js/test/compress/sequences.js | 161 + .../uglify-js/test/compress/switch.js | 210 + .../node_modules/uglify-js/test/run-tests.js | 170 + .../node_modules/uglify-js/tools/node.js | 164 + node_modules/transformers/package.json | 68 + node_modules/uglify-js/LICENSE | 29 + node_modules/uglify-js/README.md | 995 + node_modules/uglify-js/bin/extract-props.js | 77 + node_modules/uglify-js/bin/uglifyjs | 635 + .../node_modules/source-map/CHANGELOG.md | 301 + .../uglify-js/node_modules/source-map/LICENSE | 28 + .../node_modules/source-map/README.md | 729 + .../node_modules/source-map/package.json | 72 + .../node_modules/source-map/source-map.js | 8 + node_modules/uglify-js/package.json | 51 + node_modules/uglify-js/tools/domprops.json | 5603 +++ node_modules/uglify-js/tools/exports.js | 19 + node_modules/uglify-js/tools/node.js | 320 + node_modules/uglify-js/tools/props.html | 61 + node_modules/uglify-to-browserify/.npmignore | 14 + node_modules/uglify-to-browserify/.travis.yml | 3 + node_modules/uglify-to-browserify/LICENSE | 19 + node_modules/uglify-to-browserify/README.md | 15 + node_modules/uglify-to-browserify/index.js | 49 + .../uglify-to-browserify/package.json | 20 + .../uglify-to-browserify/test/index.js | 22 + node_modules/void-elements/.gitattributes | 1 + node_modules/void-elements/.npmignore | 1 + node_modules/void-elements/.travis.yml | 4 + node_modules/void-elements/LICENSE | 22 + node_modules/void-elements/README.md | 27 + node_modules/void-elements/index.js | 23 + node_modules/void-elements/package.json | 28 + node_modules/void-elements/pre-publish.js | 29 + node_modules/void-elements/test/index.js | 5 + node_modules/window-size/LICENSE-MIT | 22 + node_modules/window-size/README.md | 26 + node_modules/window-size/index.js | 33 + node_modules/window-size/package.json | 33 + node_modules/with/.npmignore | 2 + node_modules/with/LICENSE | 19 + node_modules/with/README.md | 81 + node_modules/with/index.js | 125 + node_modules/with/node_modules/.bin/acorn | 1 + .../with/node_modules/acorn/.editorconfig | 7 + .../with/node_modules/acorn/.gitattributes | 1 + .../with/node_modules/acorn/.npmignore | 3 + .../with/node_modules/acorn/.tern-project | 1 + .../with/node_modules/acorn/.travis.yml | 2 + node_modules/with/node_modules/acorn/AUTHORS | 38 + node_modules/with/node_modules/acorn/LICENSE | 19 + .../with/node_modules/acorn/README.md | 377 + .../with/node_modules/acorn/bin/acorn | 54 + .../node_modules/acorn/bin/build-acorn.js | 51 + .../acorn/bin/generate-identifier-regex.js | 47 + .../with/node_modules/acorn/bin/prepublish.sh | 2 + .../node_modules/acorn/bin/update_authors.sh | 6 + .../with/node_modules/acorn/bin/without_eval | 48 + .../with/node_modules/acorn/package.json | 40 + .../with/node_modules/acorn/src/expression.js | 697 + .../with/node_modules/acorn/src/identifier.js | 129 + .../with/node_modules/acorn/src/index.js | 75 + .../with/node_modules/acorn/src/location.js | 68 + .../acorn/src/loose/acorn_loose.js | 0 .../acorn/src/loose/expression.js | 511 + .../node_modules/acorn/src/loose/index.js | 50 + .../node_modules/acorn/src/loose/parseutil.js | 126 + .../node_modules/acorn/src/loose/state.js | 17 + .../node_modules/acorn/src/loose/statement.js | 419 + .../node_modules/acorn/src/loose/tokenize.js | 108 + .../with/node_modules/acorn/src/lval.js | 213 + .../with/node_modules/acorn/src/node.js | 70 + .../with/node_modules/acorn/src/options.js | 119 + .../with/node_modules/acorn/src/parseutil.js | 89 + .../with/node_modules/acorn/src/state.js | 78 + .../with/node_modules/acorn/src/statement.js | 594 + .../node_modules/acorn/src/tokencontext.js | 107 + .../with/node_modules/acorn/src/tokenize.js | 672 + .../with/node_modules/acorn/src/tokentype.js | 142 + .../with/node_modules/acorn/src/util.js | 9 + .../with/node_modules/acorn/src/walk/index.js | 291 + .../with/node_modules/acorn/src/whitespace.js | 12 + node_modules/with/package.json | 23 + node_modules/wordwrap/.npmignore | 1 + node_modules/wordwrap/README.markdown | 70 + node_modules/wordwrap/example/center.js | 10 + node_modules/wordwrap/example/meat.js | 3 + node_modules/wordwrap/index.js | 76 + node_modules/wordwrap/package.json | 37 + node_modules/wordwrap/test/break.js | 30 + node_modules/wordwrap/test/idleness.txt | 63 + node_modules/wordwrap/test/wrap.js | 31 + node_modules/yargs/CHANGELOG.md | 374 + node_modules/yargs/LICENSE | 21 + node_modules/yargs/README.md | 926 + node_modules/yargs/completion.sh.hbs | 22 + node_modules/yargs/index.js | 504 + node_modules/yargs/package.json | 85 + package.json | 12 + yarn.lock | 280 + 446 files changed, 93555 insertions(+) create mode 120000 node_modules/.bin/acorn create mode 120000 node_modules/.bin/bower create mode 120000 node_modules/.bin/cleancss create mode 120000 node_modules/.bin/jade create mode 120000 node_modules/.bin/mkdirp create mode 120000 node_modules/.bin/r.js create mode 120000 node_modules/.bin/r_js create mode 120000 node_modules/.bin/uglifyjs create mode 100644 node_modules/.yarn-integrity create mode 100644 node_modules/acorn-globals/LICENSE create mode 100644 node_modules/acorn-globals/README.md create mode 100644 node_modules/acorn-globals/index.js create mode 120000 node_modules/acorn-globals/node_modules/.bin/acorn create mode 100644 node_modules/acorn-globals/package.json create mode 100644 node_modules/acorn/.editorconfig create mode 100644 node_modules/acorn/.gitattributes create mode 100644 node_modules/acorn/.npmignore create mode 100644 node_modules/acorn/.tern-project create mode 100644 node_modules/acorn/.travis.yml create mode 100644 node_modules/acorn/AUTHORS create mode 100644 node_modules/acorn/LICENSE create mode 100644 node_modules/acorn/README.md create mode 100755 node_modules/acorn/bin/acorn create mode 100644 node_modules/acorn/bin/build-acorn.js create mode 100644 node_modules/acorn/bin/generate-identifier-regex.js create mode 100755 node_modules/acorn/bin/update_authors.sh create mode 100644 node_modules/acorn/package.json create mode 100644 node_modules/acorn/src/bin/acorn.js create mode 100644 node_modules/acorn/src/expression.js create mode 100644 node_modules/acorn/src/identifier.js create mode 100644 node_modules/acorn/src/index.js create mode 100644 node_modules/acorn/src/location.js create mode 100644 node_modules/acorn/src/locutil.js create mode 100644 node_modules/acorn/src/loose/acorn_loose.js create mode 100644 node_modules/acorn/src/loose/expression.js create mode 100644 node_modules/acorn/src/loose/index.js create mode 100644 node_modules/acorn/src/loose/parseutil.js create mode 100644 node_modules/acorn/src/loose/state.js create mode 100644 node_modules/acorn/src/loose/statement.js create mode 100644 node_modules/acorn/src/loose/tokenize.js create mode 100644 node_modules/acorn/src/lval.js create mode 100644 node_modules/acorn/src/node.js create mode 100644 node_modules/acorn/src/options.js create mode 100644 node_modules/acorn/src/parseutil.js create mode 100644 node_modules/acorn/src/state.js create mode 100644 node_modules/acorn/src/statement.js create mode 100644 node_modules/acorn/src/tokencontext.js create mode 100644 node_modules/acorn/src/tokenize.js create mode 100644 node_modules/acorn/src/tokentype.js create mode 100644 node_modules/acorn/src/util.js create mode 100644 node_modules/acorn/src/walk/index.js create mode 100644 node_modules/acorn/src/whitespace.js create mode 100644 node_modules/align-text/LICENSE create mode 100644 node_modules/align-text/README.md create mode 100644 node_modules/align-text/index.js create mode 100644 node_modules/align-text/package.json create mode 100644 node_modules/almond/LICENSE create mode 100644 node_modules/almond/README.md create mode 100644 node_modules/almond/almond.js create mode 100644 node_modules/almond/package.json create mode 100644 node_modules/amdefine/LICENSE create mode 100644 node_modules/amdefine/README.md create mode 100644 node_modules/amdefine/amdefine.js create mode 100644 node_modules/amdefine/intercept.js create mode 100644 node_modules/amdefine/package.json create mode 100644 node_modules/asap/LICENSE.md create mode 100644 node_modules/asap/README.md create mode 100644 node_modules/asap/asap.js create mode 100644 node_modules/asap/package.json create mode 100644 node_modules/bower/CHANGELOG.md create mode 100644 node_modules/bower/LICENSE create mode 100644 node_modules/bower/README.md create mode 100755 node_modules/bower/bin/bower create mode 100644 node_modules/bower/package.json create mode 100644 node_modules/camelcase/index.js create mode 100644 node_modules/camelcase/license create mode 100644 node_modules/camelcase/package.json create mode 100644 node_modules/camelcase/readme.md create mode 100644 node_modules/center-align/LICENSE create mode 100644 node_modules/center-align/README.md create mode 100644 node_modules/center-align/index.js create mode 100644 node_modules/center-align/package.json create mode 100644 node_modules/center-align/utils.js create mode 100644 node_modules/character-parser/.npmignore create mode 100644 node_modules/character-parser/LICENSE create mode 100644 node_modules/character-parser/README.md create mode 100644 node_modules/character-parser/index.js create mode 100644 node_modules/character-parser/package.json create mode 100644 node_modules/clean-css/History.md create mode 100644 node_modules/clean-css/LICENSE create mode 100644 node_modules/clean-css/README.md create mode 100755 node_modules/clean-css/bin/cleancss create mode 100644 node_modules/clean-css/index.js create mode 100644 node_modules/clean-css/node_modules/commander/History.md create mode 100644 node_modules/clean-css/node_modules/commander/LICENSE create mode 100644 node_modules/clean-css/node_modules/commander/Readme.md create mode 100644 node_modules/clean-css/node_modules/commander/index.js create mode 100644 node_modules/clean-css/node_modules/commander/package.json create mode 100644 node_modules/clean-css/package.json create mode 100644 node_modules/cliui/.coveralls.yml create mode 100644 node_modules/cliui/.npmignore create mode 100644 node_modules/cliui/.travis.yml create mode 100644 node_modules/cliui/LICENSE.txt create mode 100644 node_modules/cliui/README.md create mode 100644 node_modules/cliui/index.js create mode 100644 node_modules/cliui/package.json create mode 100644 node_modules/cliui/test/cliui.js create mode 100644 node_modules/commander/History.md create mode 100644 node_modules/commander/Readme.md create mode 100644 node_modules/commander/index.js create mode 100644 node_modules/commander/package.json create mode 100644 node_modules/constantinople/.gitattributes create mode 100644 node_modules/constantinople/.npmignore create mode 100644 node_modules/constantinople/.travis.yml create mode 100644 node_modules/constantinople/LICENSE create mode 100644 node_modules/constantinople/README.md create mode 100644 node_modules/constantinople/index.js create mode 120000 node_modules/constantinople/node_modules/.bin/acorn create mode 100644 node_modules/constantinople/package.json create mode 100644 node_modules/constantinople/test/index.js create mode 100644 node_modules/css-parse/.npmignore create mode 100644 node_modules/css-parse/History.md create mode 100644 node_modules/css-parse/Makefile create mode 100644 node_modules/css-parse/Readme.md create mode 100644 node_modules/css-parse/component.json create mode 100644 node_modules/css-parse/index.js create mode 100644 node_modules/css-parse/package.json create mode 100644 node_modules/css-stringify/.npmignore create mode 100644 node_modules/css-stringify/History.md create mode 100644 node_modules/css-stringify/Makefile create mode 100644 node_modules/css-stringify/Readme.md create mode 100644 node_modules/css-stringify/component.json create mode 100644 node_modules/css-stringify/index.js create mode 100644 node_modules/css-stringify/package.json create mode 100644 node_modules/css/.npmignore create mode 100644 node_modules/css/History.md create mode 100644 node_modules/css/Makefile create mode 100644 node_modules/css/Readme.md create mode 100644 node_modules/css/benchmark.js create mode 100644 node_modules/css/component.json create mode 100644 node_modules/css/index.js create mode 100644 node_modules/css/package.json create mode 100644 node_modules/css/test.js create mode 100644 node_modules/decamelize/index.js create mode 100644 node_modules/decamelize/license create mode 100644 node_modules/decamelize/package.json create mode 100644 node_modules/decamelize/readme.md create mode 100644 node_modules/graceful-readlink/.npmignore create mode 100644 node_modules/graceful-readlink/.travis.yml create mode 100644 node_modules/graceful-readlink/LICENSE create mode 100644 node_modules/graceful-readlink/README.md create mode 100644 node_modules/graceful-readlink/index.js create mode 100644 node_modules/graceful-readlink/package.json create mode 100644 node_modules/is-buffer/LICENSE create mode 100644 node_modules/is-buffer/README.md create mode 100644 node_modules/is-buffer/index.js create mode 100644 node_modules/is-buffer/package.json create mode 100644 node_modules/is-buffer/test/basic.js create mode 100644 node_modules/is-promise/.npmignore create mode 100644 node_modules/is-promise/.travis.yml create mode 100644 node_modules/is-promise/LICENSE create mode 100644 node_modules/is-promise/index.js create mode 100644 node_modules/is-promise/package.json create mode 100644 node_modules/is-promise/readme.md create mode 100644 node_modules/jade/.npmignore create mode 100644 node_modules/jade/.release.json create mode 100644 node_modules/jade/History.md create mode 100644 node_modules/jade/LICENSE create mode 100644 node_modules/jade/README.md create mode 100644 node_modules/jade/Readme_zh-cn.md create mode 100755 node_modules/jade/bin/jade.js create mode 100644 node_modules/jade/block-code.html create mode 100644 node_modules/jade/component.json create mode 100644 node_modules/jade/jade.js create mode 120000 node_modules/jade/node_modules/.bin/cleancss create mode 120000 node_modules/jade/node_modules/.bin/mkdirp create mode 120000 node_modules/jade/node_modules/.bin/uglifyjs create mode 100644 node_modules/jade/package.json create mode 100644 node_modules/jade/release.js create mode 100644 node_modules/jade/runtime.js create mode 100644 node_modules/jstransformer/LICENSE create mode 100644 node_modules/jstransformer/README.md create mode 100644 node_modules/jstransformer/index.js create mode 100644 node_modules/jstransformer/package.json create mode 100644 node_modules/kind-of/LICENSE create mode 100644 node_modules/kind-of/README.md create mode 100644 node_modules/kind-of/index.js create mode 100644 node_modules/kind-of/package.json create mode 100644 node_modules/lazy-cache/LICENSE create mode 100644 node_modules/lazy-cache/README.md create mode 100644 node_modules/lazy-cache/index.js create mode 100644 node_modules/lazy-cache/package.json create mode 100644 node_modules/longest/LICENSE create mode 100644 node_modules/longest/README.md create mode 100644 node_modules/longest/index.js create mode 100644 node_modules/longest/package.json create mode 100644 node_modules/minimist/.travis.yml create mode 100644 node_modules/minimist/LICENSE create mode 100644 node_modules/minimist/example/parse.js create mode 100644 node_modules/minimist/index.js create mode 100644 node_modules/minimist/package.json create mode 100644 node_modules/minimist/readme.markdown create mode 100644 node_modules/minimist/test/dash.js create mode 100644 node_modules/minimist/test/default_bool.js create mode 100644 node_modules/minimist/test/dotted.js create mode 100644 node_modules/minimist/test/long.js create mode 100644 node_modules/minimist/test/parse.js create mode 100644 node_modules/minimist/test/parse_modified.js create mode 100644 node_modules/minimist/test/short.js create mode 100644 node_modules/minimist/test/whitespace.js create mode 100644 node_modules/mkdirp/.travis.yml create mode 100644 node_modules/mkdirp/LICENSE create mode 100755 node_modules/mkdirp/bin/cmd.js create mode 100644 node_modules/mkdirp/bin/usage.txt create mode 100644 node_modules/mkdirp/examples/pow.js create mode 100644 node_modules/mkdirp/index.js create mode 100644 node_modules/mkdirp/package.json create mode 100644 node_modules/mkdirp/readme.markdown create mode 100644 node_modules/mkdirp/test/chmod.js create mode 100644 node_modules/mkdirp/test/clobber.js create mode 100644 node_modules/mkdirp/test/mkdirp.js create mode 100644 node_modules/mkdirp/test/opts_fs.js create mode 100644 node_modules/mkdirp/test/opts_fs_sync.js create mode 100644 node_modules/mkdirp/test/perm.js create mode 100644 node_modules/mkdirp/test/perm_sync.js create mode 100644 node_modules/mkdirp/test/race.js create mode 100644 node_modules/mkdirp/test/rel.js create mode 100644 node_modules/mkdirp/test/return.js create mode 100644 node_modules/mkdirp/test/return_sync.js create mode 100644 node_modules/mkdirp/test/root.js create mode 100644 node_modules/mkdirp/test/sync.js create mode 100644 node_modules/mkdirp/test/umask.js create mode 100644 node_modules/mkdirp/test/umask_sync.js create mode 100644 node_modules/optimist/.travis.yml create mode 100644 node_modules/optimist/LICENSE create mode 100644 node_modules/optimist/example/bool.js create mode 100644 node_modules/optimist/example/boolean_double.js create mode 100644 node_modules/optimist/example/boolean_single.js create mode 100644 node_modules/optimist/example/default_hash.js create mode 100644 node_modules/optimist/example/default_singles.js create mode 100644 node_modules/optimist/example/divide.js create mode 100644 node_modules/optimist/example/line_count.js create mode 100644 node_modules/optimist/example/line_count_options.js create mode 100644 node_modules/optimist/example/line_count_wrap.js create mode 100644 node_modules/optimist/example/nonopt.js create mode 100644 node_modules/optimist/example/reflect.js create mode 100644 node_modules/optimist/example/short.js create mode 100644 node_modules/optimist/example/string.js create mode 100644 node_modules/optimist/example/usage-options.js create mode 100644 node_modules/optimist/example/xup.js create mode 100644 node_modules/optimist/index.js create mode 100644 node_modules/optimist/node_modules/wordwrap/LICENSE create mode 100644 node_modules/optimist/node_modules/wordwrap/README.markdown create mode 100644 node_modules/optimist/node_modules/wordwrap/example/center.js create mode 100644 node_modules/optimist/node_modules/wordwrap/example/meat.js create mode 100644 node_modules/optimist/node_modules/wordwrap/index.js create mode 100644 node_modules/optimist/node_modules/wordwrap/package.json create mode 100644 node_modules/optimist/node_modules/wordwrap/test/break.js create mode 100644 node_modules/optimist/node_modules/wordwrap/test/idleness.txt create mode 100644 node_modules/optimist/node_modules/wordwrap/test/wrap.js create mode 100644 node_modules/optimist/package.json create mode 100644 node_modules/optimist/readme.markdown create mode 100644 node_modules/optimist/test/_.js create mode 100644 node_modules/optimist/test/_/argv.js create mode 100755 node_modules/optimist/test/_/bin.js create mode 100644 node_modules/optimist/test/parse.js create mode 100644 node_modules/optimist/test/usage.js create mode 100644 node_modules/promise/.jshintrc create mode 100644 node_modules/promise/.npmignore create mode 100644 node_modules/promise/LICENSE create mode 100644 node_modules/promise/Readme.md create mode 100644 node_modules/promise/core.js create mode 100644 node_modules/promise/index.js create mode 100644 node_modules/promise/package.json create mode 100644 node_modules/promise/polyfill-done.js create mode 100644 node_modules/promise/polyfill.js create mode 100644 node_modules/repeat-string/LICENSE create mode 100644 node_modules/repeat-string/README.md create mode 100644 node_modules/repeat-string/index.js create mode 100644 node_modules/repeat-string/package.json create mode 100644 node_modules/requirejs-text/LICENSE create mode 100644 node_modules/requirejs-text/README.md create mode 100644 node_modules/requirejs-text/bower.json create mode 100644 node_modules/requirejs-text/package.json create mode 100644 node_modules/requirejs-text/text.js create mode 100644 node_modules/requirejs/README.md create mode 100755 node_modules/requirejs/bin/r.js create mode 100644 node_modules/requirejs/package.json create mode 100644 node_modules/requirejs/require.js create mode 100644 node_modules/right-align/LICENSE create mode 100644 node_modules/right-align/README.md create mode 100644 node_modules/right-align/index.js create mode 100644 node_modules/right-align/package.json create mode 100644 node_modules/source-map/README.md create mode 100644 node_modules/source-map/package.json create mode 100644 node_modules/transformers/.npmignore create mode 100644 node_modules/transformers/README.md create mode 100644 node_modules/transformers/history.md create mode 120000 node_modules/transformers/node_modules/.bin/uglifyjs create mode 100644 node_modules/transformers/node_modules/is-promise/.npmignore create mode 100644 node_modules/transformers/node_modules/is-promise/.travis.yml create mode 100644 node_modules/transformers/node_modules/is-promise/LICENSE create mode 100644 node_modules/transformers/node_modules/is-promise/index.js create mode 100644 node_modules/transformers/node_modules/is-promise/package.json create mode 100644 node_modules/transformers/node_modules/is-promise/readme.md create mode 100644 node_modules/transformers/node_modules/promise/.npmignore create mode 100644 node_modules/transformers/node_modules/promise/Readme.md create mode 100644 node_modules/transformers/node_modules/promise/index.js create mode 100644 node_modules/transformers/node_modules/promise/package.json create mode 100644 node_modules/transformers/node_modules/source-map/.npmignore create mode 100644 node_modules/transformers/node_modules/source-map/.travis.yml create mode 100644 node_modules/transformers/node_modules/source-map/CHANGELOG.md create mode 100644 node_modules/transformers/node_modules/source-map/LICENSE create mode 100644 node_modules/transformers/node_modules/source-map/Makefile.dryice.js create mode 100644 node_modules/transformers/node_modules/source-map/README.md create mode 100644 node_modules/transformers/node_modules/source-map/package.json create mode 100755 node_modules/transformers/node_modules/source-map/test/run-tests.js create mode 100644 node_modules/transformers/node_modules/source-map/test/source-map/test-api.js create mode 100644 node_modules/transformers/node_modules/source-map/test/source-map/test-array-set.js create mode 100644 node_modules/transformers/node_modules/source-map/test/source-map/test-base64-vlq.js create mode 100644 node_modules/transformers/node_modules/source-map/test/source-map/test-base64.js create mode 100644 node_modules/transformers/node_modules/source-map/test/source-map/test-binary-search.js create mode 100644 node_modules/transformers/node_modules/source-map/test/source-map/test-dog-fooding.js create mode 100644 node_modules/transformers/node_modules/source-map/test/source-map/test-source-map-consumer.js create mode 100644 node_modules/transformers/node_modules/source-map/test/source-map/test-source-map-generator.js create mode 100644 node_modules/transformers/node_modules/source-map/test/source-map/test-source-node.js create mode 100644 node_modules/transformers/node_modules/source-map/test/source-map/test-util.js create mode 100644 node_modules/transformers/node_modules/source-map/test/source-map/util.js create mode 100644 node_modules/transformers/node_modules/uglify-js/.npmignore create mode 100644 node_modules/transformers/node_modules/uglify-js/README.md create mode 100755 node_modules/transformers/node_modules/uglify-js/bin/uglifyjs create mode 100644 node_modules/transformers/node_modules/uglify-js/package.json create mode 100644 node_modules/transformers/node_modules/uglify-js/test/compress/arrays.js create mode 100644 node_modules/transformers/node_modules/uglify-js/test/compress/blocks.js create mode 100644 node_modules/transformers/node_modules/uglify-js/test/compress/conditionals.js create mode 100644 node_modules/transformers/node_modules/uglify-js/test/compress/dead-code.js create mode 100644 node_modules/transformers/node_modules/uglify-js/test/compress/debugger.js create mode 100644 node_modules/transformers/node_modules/uglify-js/test/compress/drop-unused.js create mode 100644 node_modules/transformers/node_modules/uglify-js/test/compress/issue-105.js create mode 100644 node_modules/transformers/node_modules/uglify-js/test/compress/issue-12.js create mode 100644 node_modules/transformers/node_modules/uglify-js/test/compress/issue-22.js create mode 100644 node_modules/transformers/node_modules/uglify-js/test/compress/issue-44.js create mode 100644 node_modules/transformers/node_modules/uglify-js/test/compress/issue-59.js create mode 100644 node_modules/transformers/node_modules/uglify-js/test/compress/labels.js create mode 100644 node_modules/transformers/node_modules/uglify-js/test/compress/loops.js create mode 100644 node_modules/transformers/node_modules/uglify-js/test/compress/properties.js create mode 100644 node_modules/transformers/node_modules/uglify-js/test/compress/sequences.js create mode 100644 node_modules/transformers/node_modules/uglify-js/test/compress/switch.js create mode 100755 node_modules/transformers/node_modules/uglify-js/test/run-tests.js create mode 100644 node_modules/transformers/node_modules/uglify-js/tools/node.js create mode 100644 node_modules/transformers/package.json create mode 100644 node_modules/uglify-js/LICENSE create mode 100644 node_modules/uglify-js/README.md create mode 100644 node_modules/uglify-js/bin/extract-props.js create mode 100755 node_modules/uglify-js/bin/uglifyjs create mode 100644 node_modules/uglify-js/node_modules/source-map/CHANGELOG.md create mode 100644 node_modules/uglify-js/node_modules/source-map/LICENSE create mode 100644 node_modules/uglify-js/node_modules/source-map/README.md create mode 100644 node_modules/uglify-js/node_modules/source-map/package.json create mode 100644 node_modules/uglify-js/node_modules/source-map/source-map.js create mode 100644 node_modules/uglify-js/package.json create mode 100644 node_modules/uglify-js/tools/domprops.json create mode 100644 node_modules/uglify-js/tools/exports.js create mode 100644 node_modules/uglify-js/tools/node.js create mode 100644 node_modules/uglify-js/tools/props.html create mode 100644 node_modules/uglify-to-browserify/.npmignore create mode 100644 node_modules/uglify-to-browserify/.travis.yml create mode 100644 node_modules/uglify-to-browserify/LICENSE create mode 100644 node_modules/uglify-to-browserify/README.md create mode 100644 node_modules/uglify-to-browserify/index.js create mode 100644 node_modules/uglify-to-browserify/package.json create mode 100644 node_modules/uglify-to-browserify/test/index.js create mode 100644 node_modules/void-elements/.gitattributes create mode 100644 node_modules/void-elements/.npmignore create mode 100644 node_modules/void-elements/.travis.yml create mode 100644 node_modules/void-elements/LICENSE create mode 100644 node_modules/void-elements/README.md create mode 100644 node_modules/void-elements/index.js create mode 100644 node_modules/void-elements/package.json create mode 100644 node_modules/void-elements/pre-publish.js create mode 100644 node_modules/void-elements/test/index.js create mode 100644 node_modules/window-size/LICENSE-MIT create mode 100644 node_modules/window-size/README.md create mode 100644 node_modules/window-size/index.js create mode 100644 node_modules/window-size/package.json create mode 100644 node_modules/with/.npmignore create mode 100644 node_modules/with/LICENSE create mode 100644 node_modules/with/README.md create mode 100644 node_modules/with/index.js create mode 120000 node_modules/with/node_modules/.bin/acorn create mode 100644 node_modules/with/node_modules/acorn/.editorconfig create mode 100644 node_modules/with/node_modules/acorn/.gitattributes create mode 100644 node_modules/with/node_modules/acorn/.npmignore create mode 100644 node_modules/with/node_modules/acorn/.tern-project create mode 100644 node_modules/with/node_modules/acorn/.travis.yml create mode 100644 node_modules/with/node_modules/acorn/AUTHORS create mode 100644 node_modules/with/node_modules/acorn/LICENSE create mode 100644 node_modules/with/node_modules/acorn/README.md create mode 100755 node_modules/with/node_modules/acorn/bin/acorn create mode 100644 node_modules/with/node_modules/acorn/bin/build-acorn.js create mode 100644 node_modules/with/node_modules/acorn/bin/generate-identifier-regex.js create mode 100755 node_modules/with/node_modules/acorn/bin/prepublish.sh create mode 100755 node_modules/with/node_modules/acorn/bin/update_authors.sh create mode 100755 node_modules/with/node_modules/acorn/bin/without_eval create mode 100644 node_modules/with/node_modules/acorn/package.json create mode 100755 node_modules/with/node_modules/acorn/src/expression.js create mode 100644 node_modules/with/node_modules/acorn/src/identifier.js create mode 100644 node_modules/with/node_modules/acorn/src/index.js create mode 100755 node_modules/with/node_modules/acorn/src/location.js create mode 100644 node_modules/with/node_modules/acorn/src/loose/acorn_loose.js create mode 100644 node_modules/with/node_modules/acorn/src/loose/expression.js create mode 100644 node_modules/with/node_modules/acorn/src/loose/index.js create mode 100644 node_modules/with/node_modules/acorn/src/loose/parseutil.js create mode 100644 node_modules/with/node_modules/acorn/src/loose/state.js create mode 100644 node_modules/with/node_modules/acorn/src/loose/statement.js create mode 100644 node_modules/with/node_modules/acorn/src/loose/tokenize.js create mode 100755 node_modules/with/node_modules/acorn/src/lval.js create mode 100755 node_modules/with/node_modules/acorn/src/node.js create mode 100644 node_modules/with/node_modules/acorn/src/options.js create mode 100644 node_modules/with/node_modules/acorn/src/parseutil.js create mode 100644 node_modules/with/node_modules/acorn/src/state.js create mode 100644 node_modules/with/node_modules/acorn/src/statement.js create mode 100644 node_modules/with/node_modules/acorn/src/tokencontext.js create mode 100644 node_modules/with/node_modules/acorn/src/tokenize.js create mode 100644 node_modules/with/node_modules/acorn/src/tokentype.js create mode 100644 node_modules/with/node_modules/acorn/src/util.js create mode 100644 node_modules/with/node_modules/acorn/src/walk/index.js create mode 100644 node_modules/with/node_modules/acorn/src/whitespace.js create mode 100644 node_modules/with/package.json create mode 100644 node_modules/wordwrap/.npmignore create mode 100644 node_modules/wordwrap/README.markdown create mode 100644 node_modules/wordwrap/example/center.js create mode 100644 node_modules/wordwrap/example/meat.js create mode 100644 node_modules/wordwrap/index.js create mode 100644 node_modules/wordwrap/package.json create mode 100644 node_modules/wordwrap/test/break.js create mode 100644 node_modules/wordwrap/test/idleness.txt create mode 100644 node_modules/wordwrap/test/wrap.js create mode 100644 node_modules/yargs/CHANGELOG.md create mode 100644 node_modules/yargs/LICENSE create mode 100644 node_modules/yargs/README.md create mode 100644 node_modules/yargs/completion.sh.hbs create mode 100644 node_modules/yargs/index.js create mode 100644 node_modules/yargs/package.json create mode 100644 package.json create mode 100644 yarn.lock diff --git a/node_modules/.bin/acorn b/node_modules/.bin/acorn new file mode 120000 index 0000000..cf76760 --- /dev/null +++ b/node_modules/.bin/acorn @@ -0,0 +1 @@ +../acorn/bin/acorn \ No newline at end of file diff --git a/node_modules/.bin/bower b/node_modules/.bin/bower new file mode 120000 index 0000000..fb14129 --- /dev/null +++ b/node_modules/.bin/bower @@ -0,0 +1 @@ +../bower/bin/bower \ No newline at end of file diff --git a/node_modules/.bin/cleancss b/node_modules/.bin/cleancss new file mode 120000 index 0000000..2a3439e --- /dev/null +++ b/node_modules/.bin/cleancss @@ -0,0 +1 @@ +../clean-css/bin/cleancss \ No newline at end of file diff --git a/node_modules/.bin/jade b/node_modules/.bin/jade new file mode 120000 index 0000000..65a3bac --- /dev/null +++ b/node_modules/.bin/jade @@ -0,0 +1 @@ +../jade/bin/jade.js \ No newline at end of file diff --git a/node_modules/.bin/mkdirp b/node_modules/.bin/mkdirp new file mode 120000 index 0000000..017896c --- /dev/null +++ b/node_modules/.bin/mkdirp @@ -0,0 +1 @@ +../mkdirp/bin/cmd.js \ No newline at end of file diff --git a/node_modules/.bin/r.js b/node_modules/.bin/r.js new file mode 120000 index 0000000..2075b60 --- /dev/null +++ b/node_modules/.bin/r.js @@ -0,0 +1 @@ +../requirejs/bin/r.js \ No newline at end of file diff --git a/node_modules/.bin/r_js b/node_modules/.bin/r_js new file mode 120000 index 0000000..2075b60 --- /dev/null +++ b/node_modules/.bin/r_js @@ -0,0 +1 @@ +../requirejs/bin/r.js \ No newline at end of file diff --git a/node_modules/.bin/uglifyjs b/node_modules/.bin/uglifyjs new file mode 120000 index 0000000..4b488c9 --- /dev/null +++ b/node_modules/.bin/uglifyjs @@ -0,0 +1 @@ +../transformers/node_modules/uglify-js/bin/uglifyjs \ No newline at end of file diff --git a/node_modules/.yarn-integrity b/node_modules/.yarn-integrity new file mode 100644 index 0000000..73b6dfa --- /dev/null +++ b/node_modules/.yarn-integrity @@ -0,0 +1,71 @@ +{ + "nodeVersion": "v8.7.0", + "modulesFolders": [ + "node_modules" + ], + "flags": [], + "linkedModules": [], + "topLevelPatterns": [ + "almond@^0.3.3", + "bower@^1.8.4", + "jade@^1.11.0", + "requirejs-text@^2.0.15", + "requirejs@^2.3.5" + ], + "lockfileEntries": { + "acorn-globals@^1.0.3": "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-1.0.9.tgz#55bb5e98691507b74579d0513413217c380c54cf", + "acorn@^1.0.1": "https://registry.yarnpkg.com/acorn/-/acorn-1.2.2.tgz#c8ce27de0acc76d896d2b1fad3df588d9e82f014", + "acorn@^2.1.0": "https://registry.yarnpkg.com/acorn/-/acorn-2.7.0.tgz#ab6e7d9d886aaca8b085bc3312b79a198433f0e7", + "align-text@^0.1.1": "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117", + "align-text@^0.1.3": "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117", + "almond@^0.3.3": "https://registry.yarnpkg.com/almond/-/almond-0.3.3.tgz#a0e7c95ac7624d6417b4494b1e68bff693168a20", + "amdefine@>=0.0.4": "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5", + "asap@~1.0.0": "https://registry.yarnpkg.com/asap/-/asap-1.0.0.tgz#b2a45da5fdfa20b0496fc3768cc27c12fa916a7d", + "bower@^1.8.4": "https://registry.yarnpkg.com/bower/-/bower-1.8.4.tgz#e7876a076deb8137f7d06525dc5e8c66db82f28a", + "camelcase@^1.0.2": "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39", + "center-align@^0.1.1": "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad", + "character-parser@1.2.1": "https://registry.yarnpkg.com/character-parser/-/character-parser-1.2.1.tgz#c0dde4ab182713b919b970959a123ecc1a30fcd6", + "clean-css@^3.1.9": "https://registry.yarnpkg.com/clean-css/-/clean-css-3.4.28.tgz#bf1945e82fc808f55695e6ddeaec01400efd03ff", + "cliui@^2.1.0": "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1", + "commander@2.8.x": "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4", + "commander@~2.6.0": "https://registry.yarnpkg.com/commander/-/commander-2.6.0.tgz#9df7e52fb2a0cb0fb89058ee80c3104225f37e1d", + "constantinople@~3.0.1": "https://registry.yarnpkg.com/constantinople/-/constantinople-3.0.2.tgz#4b945d9937907bcd98ee575122c3817516544141", + "css-parse@1.0.4": "https://registry.yarnpkg.com/css-parse/-/css-parse-1.0.4.tgz#38b0503fbf9da9f54e9c1dbda60e145c77117bdd", + "css-stringify@1.0.5": "https://registry.yarnpkg.com/css-stringify/-/css-stringify-1.0.5.tgz#b0d042946db2953bb9d292900a6cb5f6d0122031", + "css@~1.0.8": "https://registry.yarnpkg.com/css/-/css-1.0.8.tgz#9386811ca82bccc9ee7fb5a732b1e2a317c8a3e7", + "decamelize@^1.0.0": "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290", + "graceful-readlink@>= 1.0.0": "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725", + "is-buffer@^1.1.5": "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be", + "is-promise@^2.0.0": "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa", + "is-promise@~1": "https://registry.yarnpkg.com/is-promise/-/is-promise-1.0.1.tgz#31573761c057e33c2e91aab9e96da08cefbe76e5", + "jade@^1.11.0": "https://registry.yarnpkg.com/jade/-/jade-1.11.0.tgz#9c80e538c12d3fb95c8d9bb9559fa0cc040405fd", + "jstransformer@0.0.2": "https://registry.yarnpkg.com/jstransformer/-/jstransformer-0.0.2.tgz#7aae29a903d196cfa0973d885d3e47947ecd76ab", + "kind-of@^3.0.2": "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64", + "lazy-cache@^1.0.3": "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e", + "longest@^1.0.1": "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097", + "minimist@0.0.8": "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d", + "mkdirp@~0.5.0": "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903", + "optimist@~0.3.5": "https://registry.yarnpkg.com/optimist/-/optimist-0.3.7.tgz#c90941ad59e4273328923074d2cf2e7cbc6ec0d9", + "promise@^6.0.1": "https://registry.yarnpkg.com/promise/-/promise-6.1.0.tgz#2ce729f6b94b45c26891ad0602c5c90e04c6eef6", + "promise@~2.0": "https://registry.yarnpkg.com/promise/-/promise-2.0.0.tgz#46648aa9d605af5d2e70c3024bf59436da02b80e", + "repeat-string@^1.5.2": "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637", + "requirejs-text@^2.0.15": "https://registry.yarnpkg.com/requirejs-text/-/requirejs-text-2.0.15.tgz#13138733613fc4457b7e1247e8cb751df7aa5429", + "requirejs@^2.3.5": "https://registry.yarnpkg.com/requirejs/-/requirejs-2.3.5.tgz#617b9acbbcb336540ef4914d790323a8d4b861b0", + "right-align@^0.1.1": "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef", + "source-map@0.4.x": "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b", + "source-map@~0.1.7": "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346", + "source-map@~0.5.1": "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc", + "transformers@2.1.0": "https://registry.yarnpkg.com/transformers/-/transformers-2.1.0.tgz#5d23cb35561dd85dc67fb8482309b47d53cce9a7", + "uglify-js@^2.4.19": "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd", + "uglify-js@~2.2.5": "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.2.5.tgz#a6e02a70d839792b9780488b7b8b184c095c99c7", + "uglify-to-browserify@~1.0.0": "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7", + "void-elements@~2.0.1": "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec", + "window-size@0.1.0": "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d", + "with@~4.0.0": "https://registry.yarnpkg.com/with/-/with-4.0.3.tgz#eefd154e9e79d2c8d3417b647a8f14d9fecce14e", + "wordwrap@0.0.2": "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f", + "wordwrap@~0.0.2": "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107", + "yargs@~3.10.0": "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" + }, + "files": [], + "artifacts": {} +} \ No newline at end of file diff --git a/node_modules/acorn-globals/LICENSE b/node_modules/acorn-globals/LICENSE new file mode 100644 index 0000000..27cc9f3 --- /dev/null +++ b/node_modules/acorn-globals/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2014 Forbes Lindesay + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/node_modules/acorn-globals/README.md b/node_modules/acorn-globals/README.md new file mode 100644 index 0000000..d8cd372 --- /dev/null +++ b/node_modules/acorn-globals/README.md @@ -0,0 +1,76 @@ +# acorn-globals + +Detect global variables in JavaScript using acorn + +[![Build Status](https://img.shields.io/travis/ForbesLindesay/acorn-globals/master.svg)](https://travis-ci.org/ForbesLindesay/acorn-globals) +[![Dependency Status](https://img.shields.io/david/ForbesLindesay/acorn-globals.svg)](https://david-dm.org/ForbesLindesay/acorn-globals) +[![NPM version](https://img.shields.io/npm/v/acorn-globals.svg)](https://www.npmjs.org/package/acorn-globals) + +## Installation + + npm install acorn-globals + +## Usage + +detect.js + +```js +var fs = require('fs'); +var detect = require('acorn-globals'); + +var src = fs.readFileSync(__dirname + '/input.js', 'utf8'); + +var scope = detect(src); +console.dir(scope); +``` + +input.js + +```js +var x = 5; +var y = 3, z = 2; + +w.foo(); +w = 2; + +RAWR=444; +RAWR.foo(); + +BLARG=3; + +foo(function () { + var BAR = 3; + process.nextTick(function (ZZZZZZZZZZZZ) { + console.log('beep boop'); + var xyz = 4; + x += 10; + x.zzzzzz; + ZZZ=6; + }); + function doom () { + } + ZZZ.foo(); + +}); + +console.log(xyz); +``` + +output: + +``` +$ node example/detect.js +[ { name: 'BLARG', nodes: [ [Object] ] }, + { name: 'RAWR', nodes: [ [Object], [Object] ] }, + { name: 'ZZZ', nodes: [ [Object], [Object] ] }, + { name: 'console', nodes: [ [Object], [Object] ] }, + { name: 'foo', nodes: [ [Object] ] }, + { name: 'process', nodes: [ [Object] ] }, + { name: 'w', nodes: [ [Object], [Object] ] }, + { name: 'xyz', nodes: [ [Object] ] } ] +``` + + +## License + + MIT diff --git a/node_modules/acorn-globals/index.js b/node_modules/acorn-globals/index.js new file mode 100644 index 0000000..ff924c9 --- /dev/null +++ b/node_modules/acorn-globals/index.js @@ -0,0 +1,180 @@ +'use strict'; + +var acorn = require('acorn'); +var walk = require('acorn/dist/walk'); + +function isScope(node) { + return node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression' || node.type === 'Program'; +} +function isBlockScope(node) { + return node.type === 'BlockStatement' || isScope(node); +} + +function declaresArguments(node) { + return node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration'; +} + +function declaresThis(node) { + return node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration'; +} + +function reallyParse(source) { + try { + return acorn.parse(source, { + ecmaVersion: 6, + allowReturnOutsideFunction: true, + allowImportExportEverywhere: true, + allowHashBang: true + }); + } catch (ex) { + return acorn.parse(source, { + ecmaVersion: 5, + allowReturnOutsideFunction: true, + allowImportExportEverywhere: true, + allowHashBang: true + }); + } +} +module.exports = findGlobals; +module.exports.parse = reallyParse; +function findGlobals(source) { + var globals = []; + var ast; + // istanbul ignore else + if (typeof source === 'string') { + ast = reallyParse(source); + } else { + ast = source; + } + // istanbul ignore if + if (!(ast && typeof ast === 'object' && ast.type === 'Program')) { + throw new TypeError('Source must be either a string of JavaScript or an acorn AST'); + } + var declareFunction = function (node) { + var fn = node; + fn.locals = fn.locals || {}; + node.params.forEach(function (node) { + declarePattern(node, fn); + }); + if (node.id) { + fn.locals[node.id.name] = true; + } + } + var declarePattern = function (node, parent) { + switch (node.type) { + case 'Identifier': + parent.locals[node.name] = true; + break; + case 'ObjectPattern': + node.properties.forEach(function (node) { + declarePattern(node.value, parent); + }); + break; + case 'ArrayPattern': + node.elements.forEach(function (node) { + if (node) declarePattern(node, parent); + }); + break; + case 'RestElement': + declarePattern(node.argument, parent); + break; + case 'AssignmentPattern': + declarePattern(node.left, parent); + break; + // istanbul ignore next + default: + throw new Error('Unrecognized pattern type: ' + node.type); + } + } + var declareModuleSpecifier = function (node, parents) { + ast.locals = ast.locals || {}; + ast.locals[node.local.name] = true; + } + walk.ancestor(ast, { + 'VariableDeclaration': function (node, parents) { + var parent = null; + for (var i = parents.length - 1; i >= 0 && parent === null; i--) { + if (node.kind === 'var' ? isScope(parents[i]) : isBlockScope(parents[i])) { + parent = parents[i]; + } + } + parent.locals = parent.locals || {}; + node.declarations.forEach(function (declaration) { + declarePattern(declaration.id, parent); + }); + }, + 'FunctionDeclaration': function (node, parents) { + var parent = null; + for (var i = parents.length - 2; i >= 0 && parent === null; i--) { + if (isScope(parents[i])) { + parent = parents[i]; + } + } + parent.locals = parent.locals || {}; + parent.locals[node.id.name] = true; + declareFunction(node); + }, + 'Function': declareFunction, + 'ClassDeclaration': function (node, parents) { + var parent = null; + for (var i = parents.length - 2; i >= 0 && parent === null; i--) { + if (isScope(parents[i])) { + parent = parents[i]; + } + } + parent.locals = parent.locals || {}; + parent.locals[node.id.name] = true; + }, + 'TryStatement': function (node) { + if (node.handler === null) return; + node.handler.body.locals = node.handler.body.locals || {}; + node.handler.body.locals[node.handler.param.name] = true; + }, + 'ImportDefaultSpecifier': declareModuleSpecifier, + 'ImportSpecifier': declareModuleSpecifier, + 'ImportNamespaceSpecifier': declareModuleSpecifier + }); + function identifier(node, parents) { + var name = node.name; + if (name === 'undefined') return; + for (var i = 0; i < parents.length; i++) { + if (name === 'arguments' && declaresArguments(parents[i])) { + return; + } + if (parents[i].locals && name in parents[i].locals) { + return; + } + } + if ( + parents[parents.length - 2] && + parents[parents.length - 2].type === 'TryStatement' && + parents[parents.length - 2].handler && + node === parents[parents.length - 2].handler.param + ) { + return; + } + node.parents = parents; + globals.push(node); + } + walk.ancestor(ast, { + 'VariablePattern': identifier, + 'Identifier': identifier, + 'ThisExpression': function (node, parents) { + for (var i = 0; i < parents.length; i++) { + if (declaresThis(parents[i])) { + return; + } + } + node.parents = parents; + globals.push(node); + } + }); + var groupedGlobals = {}; + globals.forEach(function (node) { + groupedGlobals[node.name] = (groupedGlobals[node.name] || []); + groupedGlobals[node.name].push(node); + }); + return Object.keys(groupedGlobals).sort().map(function (name) { + return {name: name, nodes: groupedGlobals[name]}; + }); +} diff --git a/node_modules/acorn-globals/node_modules/.bin/acorn b/node_modules/acorn-globals/node_modules/.bin/acorn new file mode 120000 index 0000000..fa65fee --- /dev/null +++ b/node_modules/acorn-globals/node_modules/.bin/acorn @@ -0,0 +1 @@ +../../../acorn/bin/acorn \ No newline at end of file diff --git a/node_modules/acorn-globals/package.json b/node_modules/acorn-globals/package.json new file mode 100644 index 0000000..6d0db56 --- /dev/null +++ b/node_modules/acorn-globals/package.json @@ -0,0 +1,34 @@ +{ + "name": "acorn-globals", + "version": "1.0.9", + "description": "Detect global variables in JavaScript using acorn", + "keywords": [ + "ast", + "variable", + "name", + "lexical", + "scope", + "local", + "global", + "implicit" + ], + "files": [ + "index.js", + "LICENSE" + ], + "dependencies": { + "acorn": "^2.1.0" + }, + "devDependencies": { + "testit": "^2.0.2" + }, + "scripts": { + "test": "node test" + }, + "repository": { + "type": "git", + "url": "https://github.com/ForbesLindesay/acorn-globals.git" + }, + "author": "ForbesLindesay", + "license": "MIT" +} \ No newline at end of file diff --git a/node_modules/acorn/.editorconfig b/node_modules/acorn/.editorconfig new file mode 100644 index 0000000..c14d5c6 --- /dev/null +++ b/node_modules/acorn/.editorconfig @@ -0,0 +1,7 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true diff --git a/node_modules/acorn/.gitattributes b/node_modules/acorn/.gitattributes new file mode 100644 index 0000000..fcadb2c --- /dev/null +++ b/node_modules/acorn/.gitattributes @@ -0,0 +1 @@ +* text eol=lf diff --git a/node_modules/acorn/.npmignore b/node_modules/acorn/.npmignore new file mode 100644 index 0000000..ecba291 --- /dev/null +++ b/node_modules/acorn/.npmignore @@ -0,0 +1,3 @@ +/.tern-port +/test +/local diff --git a/node_modules/acorn/.tern-project b/node_modules/acorn/.tern-project new file mode 100644 index 0000000..6718ce0 --- /dev/null +++ b/node_modules/acorn/.tern-project @@ -0,0 +1,6 @@ +{ + "plugins": { + "node": true, + "es_modules": true + } +} \ No newline at end of file diff --git a/node_modules/acorn/.travis.yml b/node_modules/acorn/.travis.yml new file mode 100644 index 0000000..f50c379 --- /dev/null +++ b/node_modules/acorn/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +sudo: false +node_js: + - '0.10' + - '0.12' + - '4' diff --git a/node_modules/acorn/AUTHORS b/node_modules/acorn/AUTHORS new file mode 100644 index 0000000..0e8f48b --- /dev/null +++ b/node_modules/acorn/AUTHORS @@ -0,0 +1,43 @@ +List of Acorn contributors. Updated before every release. + +Adrian Rakovsky +Alistair Braidwood +Andres Suarez +Aparajita Fishman +Arian Stolwijk +Artem Govorov +Brandon Mills +Charles Hughes +Conrad Irwin +David Bonnet +ForbesLindesay +Forbes Lindesay +Gilad Peleg +impinball +Ingvar Stepanyan +Jesse McCarthy +Jiaxing Wang +Joel Kemp +Johannes Herr +Jürg Lehni +keeyipchan +Kevin Kwok +krator +Marijn Haverbeke +Martin Carlberg +Mathias Bynens +Mathieu 'p01' Henri +Max Schaefer +Max Zerzouri +Mihai Bazon +Mike Rennie +Nick Fitzgerald +Oskar Schöldström +Paul Harper +Peter Rust +PlNG +r-e-d +Rich Harris +Sebastian McKenzie +Timothy Gu +zsjforcn diff --git a/node_modules/acorn/LICENSE b/node_modules/acorn/LICENSE new file mode 100644 index 0000000..d4c7fc5 --- /dev/null +++ b/node_modules/acorn/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2012-2014 by various contributors (see AUTHORS) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/acorn/README.md b/node_modules/acorn/README.md new file mode 100644 index 0000000..acd39a8 --- /dev/null +++ b/node_modules/acorn/README.md @@ -0,0 +1,396 @@ +# Acorn + +[![Build Status](https://travis-ci.org/ternjs/acorn.svg?branch=master)](https://travis-ci.org/ternjs/acorn) +[![NPM version](https://img.shields.io/npm/v/acorn.svg)](https://www.npmjs.com/package/acorn) +[Author funding status: ![maintainer happiness](https://marijnhaverbeke.nl/fund/status_s.png?force)](https://marijnhaverbeke.nl/fund/) + +A tiny, fast JavaScript parser, written completely in JavaScript. + +## Community + +Acorn is open source software released under an +[MIT license](https://github.com/ternjs/acorn/blob/master/LICENSE). + +You are welcome to +[report bugs](https://github.com/ternjs/acorn/issues) or create pull +requests on [github](https://github.com/ternjs/acorn). For questions +and discussion, please use the +[Tern discussion forum](https://discuss.ternjs.net). + +## Installation + +The easiest way to install acorn is with [`npm`][npm]. + +[npm]: https://www.npmjs.com/ + +```sh +npm install acorn +``` + +Alternately, download the source. + +```sh +git clone https://github.com/ternjs/acorn.git +``` + +## Components + +When run in a CommonJS (node.js) or AMD environment, exported values +appear in the interfaces exposed by the individual files, as usual. +When loaded in the browser (Acorn works in any JS-enabled browser more +recent than IE5) without any kind of module management, a single +global object `acorn` will be defined, and all the exported properties +will be added to that. + +### Main parser + +This is implemented in `dist/acorn.js`, and is what you get when you +`require("acorn")` in node.js. + +**parse**`(input, options)` is used to parse a JavaScript program. +The `input` parameter is a string, `options` can be undefined or an +object setting some of the options listed below. The return value will +be an abstract syntax tree object as specified by the +[ESTree spec][estree]. + +When encountering a syntax error, the parser will raise a +`SyntaxError` object with a meaningful message. The error object will +have a `pos` property that indicates the character offset at which the +error occurred, and a `loc` object that contains a `{line, column}` +object referring to that same position. + +[estree]: https://github.com/estree/estree + +- **ecmaVersion**: Indicates the ECMAScript version to parse. Must be + either 3, 5, or 6. This influences support for strict mode, the set + of reserved words, and support for new syntax features. Default is 5. + +- **sourceType**: Indicate the mode the code should be parsed in. Can be + either `"script"` or `"module"`. + +- **onInsertedSemicolon**: If given a callback, that callback will be + called whenever a missing semicolon is inserted by the parser. The + callback will be given the character offset of the point where the + semicolon is inserted as argument, and if `locations` is on, also a + `{line, column}` object representing this position. + +- **onTrailingComma**: Like `onInsertedSemicolon`, but for trailing + commas. + +- **allowReserved**: If `false`, using a reserved word will generate + an error. Defaults to `true` for `ecmaVersion` 3, `false` for higher + versions. When given the value `"never"`, reserved words and + keywords can also not be used as property names (as in Internet + Explorer's old parser). + +- **allowReturnOutsideFunction**: By default, a return statement at + the top level raises an error. Set this to `true` to accept such + code. + +- **allowImportExportEverywhere**: By default, `import` and `export` + declarations can only appear at a program's top level. Setting this + option to `true` allows them anywhere where a statement is allowed. + +- **allowHashBang**: When this is enabled (off by default), if the + code starts with the characters `#!` (as in a shellscript), the + first line will be treated as a comment. + +- **locations**: When `true`, each node has a `loc` object attached + with `start` and `end` subobjects, each of which contains the + one-based line and zero-based column numbers in `{line, column}` + form. Default is `false`. + +- **onToken**: If a function is passed for this option, each found + token will be passed in same format as tokens returned from + `tokenizer().getToken()`. + + If array is passed, each found token is pushed to it. + + Note that you are not allowed to call the parser from the + callback—that will corrupt its internal state. + +- **onComment**: If a function is passed for this option, whenever a + comment is encountered the function will be called with the + following parameters: + + - `block`: `true` if the comment is a block comment, false if it + is a line comment. + - `text`: The content of the comment. + - `start`: Character offset of the start of the comment. + - `end`: Character offset of the end of the comment. + + When the `locations` options is on, the `{line, column}` locations + of the comment’s start and end are passed as two additional + parameters. + + If array is passed for this option, each found comment is pushed + to it as object in Esprima format: + + ```javascript + { + "type": "Line" | "Block", + "value": "comment text", + "start": Number, + "end": Number, + // If `locations` option is on: + "loc": { + "start": {line: Number, column: Number} + "end": {line: Number, column: Number} + }, + // If `ranges` option is on: + "range": [Number, Number] + } + ``` + + Note that you are not allowed to call the parser from the + callback—that will corrupt its internal state. + +- **ranges**: Nodes have their start and end characters offsets + recorded in `start` and `end` properties (directly on the node, + rather than the `loc` object, which holds line/column data. To also + add a [semi-standardized][range] `range` property holding a + `[start, end]` array with the same numbers, set the `ranges` option + to `true`. + +- **program**: It is possible to parse multiple files into a single + AST by passing the tree produced by parsing the first file as the + `program` option in subsequent parses. This will add the toplevel + forms of the parsed file to the "Program" (top) node of an existing + parse tree. + +- **sourceFile**: When the `locations` option is `true`, you can pass + this option to add a `source` attribute in every node’s `loc` + object. Note that the contents of this option are not examined or + processed in any way; you are free to use whatever format you + choose. + +- **directSourceFile**: Like `sourceFile`, but a `sourceFile` property + will be added directly to the nodes, rather than the `loc` object. + +- **preserveParens**: If this option is `true`, parenthesized expressions + are represented by (non-standard) `ParenthesizedExpression` nodes + that have a single `expression` property containing the expression + inside parentheses. + +[range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 + +**parseExpressionAt**`(input, offset, options)` will parse a single +expression in a string, and return its AST. It will not complain if +there is more of the string left after the expression. + +**getLineInfo**`(input, offset)` can be used to get a `{line, +column}` object for a given program string and character offset. + +**tokenizer**`(input, options)` returns an object with a `getToken` +method that can be called repeatedly to get the next token, a `{start, +end, type, value}` object (with added `loc` property when the +`locations` option is enabled and `range` property when the `ranges` +option is enabled). When the token's type is `tokTypes.eof`, you +should stop calling the method, since it will keep returning that same +token forever. + +In ES6 environment, returned result can be used as any other +protocol-compliant iterable: + +```javascript +for (let token of acorn.tokenizer(str)) { + // iterate over the tokens +} + +// transform code to array of tokens: +var tokens = [...acorn.tokenizer(str)]; +``` + +**tokTypes** holds an object mapping names to the token type objects +that end up in the `type` properties of tokens. + +#### Note on using with [Escodegen][escodegen] + +Escodegen supports generating comments from AST, attached in +Esprima-specific format. In order to simulate same format in +Acorn, consider following example: + +```javascript +var comments = [], tokens = []; + +var ast = acorn.parse('var x = 42; // answer', { + // collect ranges for each node + ranges: true, + // collect comments in Esprima's format + onComment: comments, + // collect token ranges + onToken: tokens +}); + +// attach comments using collected information +escodegen.attachComments(ast, comments, tokens); + +// generate code +console.log(escodegen.generate(ast, {comment: true})); +// > 'var x = 42; // answer' +``` + +[escodegen]: https://github.com/estools/escodegen + +### dist/acorn_loose.js ### + +This file implements an error-tolerant parser. It exposes a single +function. The loose parser is accessible in node.js via `require("acorn/dist/acorn_loose")`. + +**parse_dammit**`(input, options)` takes the same arguments and +returns the same syntax tree as the `parse` function in `acorn.js`, +but never raises an error, and will do its best to parse syntactically +invalid code in as meaningful a way as it can. It'll insert identifier +nodes with name `"✖"` as placeholders in places where it can't make +sense of the input. Depends on `acorn.js`, because it uses the same +tokenizer. + +### dist/walk.js ### + +Implements an abstract syntax tree walker. Will store its interface in +`acorn.walk` when loaded without a module system. + +**simple**`(node, visitors, base, state)` does a 'simple' walk over +a tree. `node` should be the AST node to walk, and `visitors` an +object with properties whose names correspond to node types in the +[ESTree spec][estree]. The properties should contain functions +that will be called with the node object and, if applicable the state +at that point. The last two arguments are optional. `base` is a walker +algorithm, and `state` is a start state. The default walker will +simply visit all statements and expressions and not produce a +meaningful state. (An example of a use of state is to track scope at +each point in the tree.) + +**ancestor**`(node, visitors, base, state)` does a 'simple' walk over +a tree, building up an array of ancestor nodes (including the current node) +and passing the array to callbacks in the `state` parameter. + +**recursive**`(node, state, functions, base)` does a 'recursive' +walk, where the walker functions are responsible for continuing the +walk on the child nodes of their target node. `state` is the start +state, and `functions` should contain an object that maps node types +to walker functions. Such functions are called with `(node, state, c)` +arguments, and can cause the walk to continue on a sub-node by calling +the `c` argument on it with `(node, state)` arguments. The optional +`base` argument provides the fallback walker functions for node types +that aren't handled in the `functions` object. If not given, the +default walkers will be used. + +**make**`(functions, base)` builds a new walker object by using the +walker functions in `functions` and filling in the missing ones by +taking defaults from `base`. + +**findNodeAt**`(node, start, end, test, base, state)` tries to +locate a node in a tree at the given start and/or end offsets, which +satisfies the predicate `test`. `start` and `end` can be either `null` +(as wildcard) or a number. `test` may be a string (indicating a node +type) or a function that takes `(nodeType, node)` arguments and +returns a boolean indicating whether this node is interesting. `base` +and `state` are optional, and can be used to specify a custom walker. +Nodes are tested from inner to outer, so if two nodes match the +boundaries, the inner one will be preferred. + +**findNodeAround**`(node, pos, test, base, state)` is a lot like +`findNodeAt`, but will match any node that exists 'around' (spanning) +the given position. + +**findNodeAfter**`(node, pos, test, base, state)` is similar to +`findNodeAround`, but will match all nodes *after* the given position +(testing outer nodes before inner nodes). + +## Command line interface + +The `bin/acorn` utility can be used to parse a file from the command +line. It accepts as arguments its input file and the following +options: + +- `--ecma3|--ecma5|--ecma6`: Sets the ECMAScript version to parse. Default is + version 5. + +- `--module`: Sets the parsing mode to `"module"`. Is set to `"script"` otherwise. + +- `--locations`: Attaches a "loc" object to each node with "start" and + "end" subobjects, each of which contains the one-based line and + zero-based column numbers in `{line, column}` form. + +- `--allow-hash-bang`: If the code starts with the characters #! (as in a shellscript), the first line will be treated as a comment. + +- `--compact`: No whitespace is used in the AST output. + +- `--silent`: Do not output the AST, just return the exit status. + +- `--help`: Print the usage information and quit. + +The utility spits out the syntax tree as JSON data. + +## Build system + +Acorn is written in ECMAScript 6, as a set of small modules, in the +project's `src` directory, and compiled down to bigger ECMAScript 3 +files in `dist` using [Browserify](http://browserify.org) and +[Babel](http://babeljs.io/). If you are already using Babel, you can +consider including the modules directly. + +The command-line test runner (`npm test`) uses the ES6 modules. The +browser-based test page (`test/index.html`) uses the compiled modules. +The `bin/build-acorn.js` script builds the latter from the former. + +If you are working on Acorn, you'll probably want to try the code out +directly, without an intermediate build step. In your scripts, you can +register the Babel require shim like this: + + require("babel-core/register") + +That will allow you to directly `require` the ES6 modules. + +## Plugins + +Acorn is designed support allow plugins which, within reasonable +bounds, redefine the way the parser works. Plugins can add new token +types and new tokenizer contexts (if necessary), and extend methods in +the parser object. This is not a clean, elegant API—using it requires +an understanding of Acorn's internals, and plugins are likely to break +whenever those internals are significantly changed. But still, it is +_possible_, in this way, to create parsers for JavaScript dialects +without forking all of Acorn. And in principle it is even possible to +combine such plugins, so that if you have, for example, a plugin for +parsing types and a plugin for parsing JSX-style XML literals, you +could load them both and parse code with both JSX tags and types. + +A plugin should register itself by adding a property to +`acorn.plugins`, which holds a function. Calling `acorn.parse`, a +`plugins` option can be passed, holding an object mapping plugin names +to configuration values (or just `true` for plugins that don't take +options). After the parser object has been created, the initialization +functions for the chosen plugins are called with `(parser, +configValue)` arguments. They are expected to use the `parser.extend` +method to extend parser methods. For example, the `readToken` method +could be extended like this: + +```javascript +parser.extend("readToken", function(nextMethod) { + return function(code) { + console.log("Reading a token!") + return nextMethod.call(this, code) + } +}) +``` + +The `nextMethod` argument passed to `extend`'s second argument is the +previous value of this method, and should usually be called through to +whenever the extended method does not handle the call itself. + +Similarly, the loose parser allows plugins to register themselves via +`acorn.pluginsLoose`. The extension mechanism is the same as for the +normal parser: + +```javascript +looseParser.extend("readToken", function(nextMethod) { + return function() { + console.log("Reading a token in the loose parser!") + return nextMethod.call(this) + } +}) +``` + +There is a proof-of-concept JSX plugin in the [`acorn-jsx`](https://github.com/RReverser/acorn-jsx) project. diff --git a/node_modules/acorn/bin/acorn b/node_modules/acorn/bin/acorn new file mode 100755 index 0000000..db07909 --- /dev/null +++ b/node_modules/acorn/bin/acorn @@ -0,0 +1,71 @@ +#!/usr/bin/env node +"use strict"; + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj["default"] = obj; return newObj; } } + +var _path = require("path"); + +var _fs = require("fs"); + +var _distAcornJs = require("../dist/acorn.js"); + +var acorn = _interopRequireWildcard(_distAcornJs); + +var infile = undefined, + forceFile = undefined, + silent = false, + compact = false, + tokenize = false; +var options = {}; + +function help(status) { + var print = status == 0 ? console.log : console.error; + print("usage: " + (0, _path.basename)(process.argv[1]) + " [--ecma3|--ecma5|--ecma6]"); + print(" [--tokenize] [--locations] [---allow-hash-bang] [--compact] [--silent] [--module] [--help] [--] [infile]"); + process.exit(status); +} + +for (var i = 2; i < process.argv.length; ++i) { + var arg = process.argv[i]; + if ((arg == "-" || arg[0] != "-") && !infile) infile = arg;else if (arg == "--" && !infile && i + 2 == process.argv.length) forceFile = infile = process.argv[++i];else if (arg == "--ecma3") options.ecmaVersion = 3;else if (arg == "--ecma5") options.ecmaVersion = 5;else if (arg == "--ecma6") options.ecmaVersion = 6;else if (arg == "--locations") options.locations = true;else if (arg == "--allow-hash-bang") options.allowHashBang = true;else if (arg == "--silent") silent = true;else if (arg == "--compact") compact = true;else if (arg == "--help") help(0);else if (arg == "--tokenize") tokenize = true;else if (arg == "--module") options.sourceType = 'module';else help(1); +} + +function run(code) { + var result = undefined; + if (!tokenize) { + try { + result = acorn.parse(code, options); + } catch (e) { + console.error(e.message);process.exit(1); + } + } else { + result = []; + var tokenizer = acorn.tokenizer(code, options), + token = undefined; + while (true) { + try { + token = tokenizer.getToken(); + } catch (e) { + console.error(e.message);process.exit(1); + } + result.push(token); + if (token.type == acorn.tokTypes.eof) break; + } + } + if (!silent) console.log(JSON.stringify(result, null, compact ? null : 2)); +} + +if (forceFile || infile && infile != "-") { + run((0, _fs.readFileSync)(infile, "utf8")); +} else { + (function () { + var code = ""; + process.stdin.resume(); + process.stdin.on("data", function (chunk) { + return code += chunk; + }); + process.stdin.on("end", function () { + return run(code); + }); + })(); +} \ No newline at end of file diff --git a/node_modules/acorn/bin/build-acorn.js b/node_modules/acorn/bin/build-acorn.js new file mode 100644 index 0000000..71f2cf9 --- /dev/null +++ b/node_modules/acorn/bin/build-acorn.js @@ -0,0 +1,82 @@ +var fs = require("fs"), path = require("path") +var stream = require("stream") + +var browserify = require("browserify") +var babel = require('babel-core') +var babelify = require("babelify").configure({loose: "all"}) + +process.chdir(path.resolve(__dirname, "..")) + +browserify({standalone: "acorn"}) + .plugin(require('browserify-derequire')) + .transform(babelify) + .require("./src/index.js", {entry: true}) + .bundle() + .on("error", function (err) { console.log("Error: " + err.message) }) + .pipe(fs.createWriteStream("dist/acorn.js")) + +var ACORN_PLACEHOLDER = "this_function_call_should_be_replaced_with_a_call_to_load_acorn()"; +function acornShimPrepare(file) { + var tr = new stream.Transform + if (file == path.resolve(__dirname, "../src/index.js")) { + var sent = false + tr._transform = function(chunk, _, callback) { + if (!sent) { + sent = true + callback(null, ACORN_PLACEHOLDER); + } else { + callback() + } + } + } else { + tr._transform = function(chunk, _, callback) { callback(null, chunk) } + } + return tr +} +function acornShimComplete() { + var tr = new stream.Transform + var buffer = ""; + tr._transform = function(chunk, _, callback) { + buffer += chunk.toString("utf8"); + callback(); + }; + tr._flush = function (callback) { + tr.push(buffer.replace(ACORN_PLACEHOLDER, "module.exports = typeof acorn != 'undefined' ? acorn : require(\"./acorn\")")); + callback(null); + }; + return tr; +} + +browserify({standalone: "acorn.loose"}) + .plugin(require('browserify-derequire')) + .transform(acornShimPrepare) + .transform(babelify) + .require("./src/loose/index.js", {entry: true}) + .bundle() + .on("error", function (err) { console.log("Error: " + err.message) }) + .pipe(acornShimComplete()) + .pipe(fs.createWriteStream("dist/acorn_loose.js")) + +browserify({standalone: "acorn.walk"}) + .plugin(require('browserify-derequire')) + .transform(acornShimPrepare) + .transform(babelify) + .require("./src/walk/index.js", {entry: true}) + .bundle() + .on("error", function (err) { console.log("Error: " + err.message) }) + .pipe(acornShimComplete()) + .pipe(fs.createWriteStream("dist/walk.js")) + +babel.transformFile("./src/bin/acorn.js", function (err, result) { + if (err) return console.log("Error: " + err.message) + fs.writeFile("bin/acorn", result.code, function (err) { + if (err) return console.log("Error: " + err.message) + + // Make bin/acorn executable + if (process.platform === 'win32') + return + var stat = fs.statSync("bin/acorn") + var newPerm = stat.mode | parseInt('111', 8) + fs.chmodSync("bin/acorn", newPerm) + }) +}) diff --git a/node_modules/acorn/bin/generate-identifier-regex.js b/node_modules/acorn/bin/generate-identifier-regex.js new file mode 100644 index 0000000..0d7c50f --- /dev/null +++ b/node_modules/acorn/bin/generate-identifier-regex.js @@ -0,0 +1,47 @@ +// Note: run `npm install unicode-7.0.0` first. + +// Which Unicode version should be used? +var version = '7.0.0'; + +var start = require('unicode-' + version + '/properties/ID_Start/code-points') + .filter(function(ch) { return ch > 127; }); +var cont = [0x200c, 0x200d].concat(require('unicode-' + version + '/properties/ID_Continue/code-points') + .filter(function(ch) { return ch > 127 && start.indexOf(ch) == -1; })); + +function pad(str, width) { + while (str.length < width) str = "0" + str; + return str; +} + +function esc(code) { + var hex = code.toString(16); + if (hex.length <= 2) return "\\x" + pad(hex, 2); + else return "\\u" + pad(hex, 4); +} + +function generate(chars) { + var astral = [], re = ""; + for (var i = 0, at = 0x10000; i < chars.length; i++) { + var from = chars[i], to = from; + while (i < chars.length - 1 && chars[i + 1] == to + 1) { + i++; + to++; + } + if (to <= 0xffff) { + if (from == to) re += esc(from); + else if (from + 1 == to) re += esc(from) + esc(to); + else re += esc(from) + "-" + esc(to); + } else { + astral.push(from - at, to - from); + at = to; + } + } + return {nonASCII: re, astral: astral}; +} + +var startData = generate(start), contData = generate(cont); + +console.log(" var nonASCIIidentifierStartChars = \"" + startData.nonASCII + "\";"); +console.log(" var nonASCIIidentifierChars = \"" + contData.nonASCII + "\";"); +console.log(" var astralIdentifierStartCodes = " + JSON.stringify(startData.astral) + ";"); +console.log(" var astralIdentifierCodes = " + JSON.stringify(contData.astral) + ";"); diff --git a/node_modules/acorn/bin/update_authors.sh b/node_modules/acorn/bin/update_authors.sh new file mode 100755 index 0000000..466c8db --- /dev/null +++ b/node_modules/acorn/bin/update_authors.sh @@ -0,0 +1,6 @@ +# Combine existing list of authors with everyone known in git, sort, add header. +tail --lines=+3 AUTHORS > AUTHORS.tmp +git log --format='%aN' | grep -v abraidwood >> AUTHORS.tmp +echo -e "List of Acorn contributors. Updated before every release.\n" > AUTHORS +sort -u AUTHORS.tmp >> AUTHORS +rm -f AUTHORS.tmp diff --git a/node_modules/acorn/package.json b/node_modules/acorn/package.json new file mode 100644 index 0000000..b340164 --- /dev/null +++ b/node_modules/acorn/package.json @@ -0,0 +1,41 @@ +{ + "name": "acorn", + "description": "ECMAScript parser", + "homepage": "https://github.com/ternjs/acorn", + "main": "dist/acorn.js", + "version": "2.7.0", + "engines": { + "node": ">=0.4.0" + }, + "maintainers": [ + { + "name": "Marijn Haverbeke", + "email": "marijnh@gmail.com", + "web": "http://marijnhaverbeke.nl" + }, + { + "name": "Ingvar Stepanyan", + "email": "me@rreverser.com", + "web": "http://rreverser.com/" + } + ], + "repository": { + "type": "git", + "url": "https://github.com/ternjs/acorn.git" + }, + "license": "MIT", + "scripts": { + "prepublish": "node bin/build-acorn.js", + "test": "node test/run.js" + }, + "bin": { + "acorn": "./bin/acorn" + }, + "devDependencies": { + "babel-core": "^5.6.15", + "babelify": "^6.1.2", + "browserify": "^10.2.4", + "browserify-derequire": "^0.9.4", + "unicode-7.0.0": "~0.1.5" + } +} diff --git a/node_modules/acorn/src/bin/acorn.js b/node_modules/acorn/src/bin/acorn.js new file mode 100644 index 0000000..71a5dff --- /dev/null +++ b/node_modules/acorn/src/bin/acorn.js @@ -0,0 +1,59 @@ +#!/usr/bin/env node + +import {basename} from "path" +import {readFileSync as readFile} from "fs" +import * as acorn from "../dist/acorn.js" + +let infile, forceFile, silent = false, compact = false, tokenize = false +const options = {} + +function help(status) { + const print = (status == 0) ? console.log : console.error + print("usage: " + basename(process.argv[1]) + " [--ecma3|--ecma5|--ecma6]") + print(" [--tokenize] [--locations] [---allow-hash-bang] [--compact] [--silent] [--module] [--help] [--] [infile]") + process.exit(status) +} + +for (let i = 2; i < process.argv.length; ++i) { + const arg = process.argv[i] + if ((arg == "-" || arg[0] != "-") && !infile) infile = arg + else if (arg == "--" && !infile && i + 2 == process.argv.length) forceFile = infile = process.argv[++i] + else if (arg == "--ecma3") options.ecmaVersion = 3 + else if (arg == "--ecma5") options.ecmaVersion = 5 + else if (arg == "--ecma6") options.ecmaVersion = 6 + else if (arg == "--locations") options.locations = true + else if (arg == "--allow-hash-bang") options.allowHashBang = true + else if (arg == "--silent") silent = true + else if (arg == "--compact") compact = true + else if (arg == "--help") help(0) + else if (arg == "--tokenize") tokenize = true + else if (arg == "--module") options.sourceType = 'module' + else help(1) +} + +function run(code) { + let result + if (!tokenize) { + try { result = acorn.parse(code, options) } + catch(e) { console.error(e.message); process.exit(1) } + } else { + result = [] + let tokenizer = acorn.tokenizer(code, options), token + while (true) { + try { token = tokenizer.getToken() } + catch(e) { console.error(e.message); process.exit(1) } + result.push(token) + if (token.type == acorn.tokTypes.eof) break + } + } + if (!silent) console.log(JSON.stringify(result, null, compact ? null : 2)) +} + +if (forceFile || infile && infile != "-") { + run(readFile(infile, "utf8")) +} else { + let code = "" + process.stdin.resume() + process.stdin.on("data", chunk => code += chunk) + process.stdin.on("end", () => run(code)) +} diff --git a/node_modules/acorn/src/expression.js b/node_modules/acorn/src/expression.js new file mode 100644 index 0000000..5f5b8a3 --- /dev/null +++ b/node_modules/acorn/src/expression.js @@ -0,0 +1,707 @@ +// A recursive descent parser operates by defining functions for all +// syntactic elements, and recursively calling those, each function +// advancing the input stream and returning an AST node. Precedence +// of constructs (for example, the fact that `!x[1]` means `!(x[1])` +// instead of `(!x)[1]` is handled by the fact that the parser +// function that parses unary prefix operators is called first, and +// in turn calls the function that parses `[]` subscripts — that +// way, it'll receive the node for `x[1]` already parsed, and wraps +// *that* in the unary operator node. +// +// Acorn uses an [operator precedence parser][opp] to handle binary +// operator precedence, because it is much more compact than using +// the technique outlined above, which uses different, nesting +// functions to specify precedence, for all of the ten binary +// precedence levels that JavaScript defines. +// +// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser + +import {types as tt} from "./tokentype" +import {Parser} from "./state" + +const pp = Parser.prototype + +// Check if property name clashes with already added. +// Object/class getters and setters are not allowed to clash — +// either with each other or with an init property — and in +// strict mode, init properties are also not allowed to be repeated. + +pp.checkPropClash = function(prop, propHash) { + if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) + return + let {key} = prop, name + switch (key.type) { + case "Identifier": name = key.name; break + case "Literal": name = String(key.value); break + default: return + } + let {kind} = prop + if (this.options.ecmaVersion >= 6) { + if (name === "__proto__" && kind === "init") { + if (propHash.proto) this.raise(key.start, "Redefinition of __proto__ property"); + propHash.proto = true + } + return + } + name = "$" + name + let other = propHash[name] + if (other) { + let isGetSet = kind !== "init" + if ((this.strict || isGetSet) && other[kind] || !(isGetSet ^ other.init)) + this.raise(key.start, "Redefinition of property") + } else { + other = propHash[name] = { + init: false, + get: false, + set: false + } + } + other[kind] = true +} + +// ### Expression parsing + +// These nest, from the most general expression type at the top to +// 'atomic', nondivisible expression types at the bottom. Most of +// the functions will simply let the function(s) below them parse, +// and, *if* the syntactic construct they handle is present, wrap +// the AST node that the inner parser gave them in another node. + +// Parse a full expression. The optional arguments are used to +// forbid the `in` operator (in for loops initalization expressions) +// and provide reference for storing '=' operator inside shorthand +// property assignment in contexts where both object expression +// and object pattern might appear (so it's possible to raise +// delayed syntax error at correct position). + +pp.parseExpression = function(noIn, refDestructuringErrors) { + let startPos = this.start, startLoc = this.startLoc + let expr = this.parseMaybeAssign(noIn, refDestructuringErrors) + if (this.type === tt.comma) { + let node = this.startNodeAt(startPos, startLoc) + node.expressions = [expr] + while (this.eat(tt.comma)) node.expressions.push(this.parseMaybeAssign(noIn, refDestructuringErrors)) + return this.finishNode(node, "SequenceExpression") + } + return expr +} + +// Parse an assignment expression. This includes applications of +// operators like `+=`. + +pp.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { + if (this.type == tt._yield && this.inGenerator) return this.parseYield() + + let validateDestructuring = false + if (!refDestructuringErrors) { + refDestructuringErrors = {shorthandAssign: 0, trailingComma: 0} + validateDestructuring = true + } + let startPos = this.start, startLoc = this.startLoc + if (this.type == tt.parenL || this.type == tt.name) + this.potentialArrowAt = this.start + let left = this.parseMaybeConditional(noIn, refDestructuringErrors) + if (afterLeftParse) left = afterLeftParse.call(this, left, startPos, startLoc) + if (this.type.isAssign) { + if (validateDestructuring) this.checkPatternErrors(refDestructuringErrors, true) + let node = this.startNodeAt(startPos, startLoc) + node.operator = this.value + node.left = this.type === tt.eq ? this.toAssignable(left) : left + refDestructuringErrors.shorthandAssign = 0 // reset because shorthand default was used correctly + this.checkLVal(left) + this.next() + node.right = this.parseMaybeAssign(noIn) + return this.finishNode(node, "AssignmentExpression") + } else { + if (validateDestructuring) this.checkExpressionErrors(refDestructuringErrors, true) + } + return left +} + +// Parse a ternary conditional (`?:`) operator. + +pp.parseMaybeConditional = function(noIn, refDestructuringErrors) { + let startPos = this.start, startLoc = this.startLoc + let expr = this.parseExprOps(noIn, refDestructuringErrors) + if (this.checkExpressionErrors(refDestructuringErrors)) return expr + if (this.eat(tt.question)) { + let node = this.startNodeAt(startPos, startLoc) + node.test = expr + node.consequent = this.parseMaybeAssign() + this.expect(tt.colon) + node.alternate = this.parseMaybeAssign(noIn) + return this.finishNode(node, "ConditionalExpression") + } + return expr +} + +// Start the precedence parser. + +pp.parseExprOps = function(noIn, refDestructuringErrors) { + let startPos = this.start, startLoc = this.startLoc + let expr = this.parseMaybeUnary(refDestructuringErrors) + if (this.checkExpressionErrors(refDestructuringErrors)) return expr + return this.parseExprOp(expr, startPos, startLoc, -1, noIn) +} + +// Parse binary operators with the operator precedence parsing +// algorithm. `left` is the left-hand side of the operator. +// `minPrec` provides context that allows the function to stop and +// defer further parser to one of its callers when it encounters an +// operator that has a lower precedence than the set it is parsing. + +pp.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) { + let prec = this.type.binop + if (prec != null && (!noIn || this.type !== tt._in)) { + if (prec > minPrec) { + let node = this.startNodeAt(leftStartPos, leftStartLoc) + node.left = left + node.operator = this.value + let op = this.type + this.next() + let startPos = this.start, startLoc = this.startLoc + node.right = this.parseExprOp(this.parseMaybeUnary(), startPos, startLoc, prec, noIn) + this.finishNode(node, (op === tt.logicalOR || op === tt.logicalAND) ? "LogicalExpression" : "BinaryExpression") + return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn) + } + } + return left +} + +// Parse unary operators, both prefix and postfix. + +pp.parseMaybeUnary = function(refDestructuringErrors) { + if (this.type.prefix) { + let node = this.startNode(), update = this.type === tt.incDec + node.operator = this.value + node.prefix = true + this.next() + node.argument = this.parseMaybeUnary() + this.checkExpressionErrors(refDestructuringErrors, true) + if (update) this.checkLVal(node.argument) + else if (this.strict && node.operator === "delete" && + node.argument.type === "Identifier") + this.raise(node.start, "Deleting local variable in strict mode") + return this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression") + } + let startPos = this.start, startLoc = this.startLoc + let expr = this.parseExprSubscripts(refDestructuringErrors) + if (this.checkExpressionErrors(refDestructuringErrors)) return expr + while (this.type.postfix && !this.canInsertSemicolon()) { + let node = this.startNodeAt(startPos, startLoc) + node.operator = this.value + node.prefix = false + node.argument = expr + this.checkLVal(expr) + this.next() + expr = this.finishNode(node, "UpdateExpression") + } + return expr +} + +// Parse call, dot, and `[]`-subscript expressions. + +pp.parseExprSubscripts = function(refDestructuringErrors) { + let startPos = this.start, startLoc = this.startLoc + let expr = this.parseExprAtom(refDestructuringErrors) + let skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")"; + if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) return expr + return this.parseSubscripts(expr, startPos, startLoc) +} + +pp.parseSubscripts = function(base, startPos, startLoc, noCalls) { + for (;;) { + if (this.eat(tt.dot)) { + let node = this.startNodeAt(startPos, startLoc) + node.object = base + node.property = this.parseIdent(true) + node.computed = false + base = this.finishNode(node, "MemberExpression") + } else if (this.eat(tt.bracketL)) { + let node = this.startNodeAt(startPos, startLoc) + node.object = base + node.property = this.parseExpression() + node.computed = true + this.expect(tt.bracketR) + base = this.finishNode(node, "MemberExpression") + } else if (!noCalls && this.eat(tt.parenL)) { + let node = this.startNodeAt(startPos, startLoc) + node.callee = base + node.arguments = this.parseExprList(tt.parenR, false) + base = this.finishNode(node, "CallExpression") + } else if (this.type === tt.backQuote) { + let node = this.startNodeAt(startPos, startLoc) + node.tag = base + node.quasi = this.parseTemplate() + base = this.finishNode(node, "TaggedTemplateExpression") + } else { + return base + } + } +} + +// Parse an atomic expression — either a single token that is an +// expression, an expression started by a keyword like `function` or +// `new`, or an expression wrapped in punctuation like `()`, `[]`, +// or `{}`. + +pp.parseExprAtom = function(refDestructuringErrors) { + let node, canBeArrow = this.potentialArrowAt == this.start + switch (this.type) { + case tt._super: + if (!this.inFunction) + this.raise(this.start, "'super' outside of function or class") + case tt._this: + let type = this.type === tt._this ? "ThisExpression" : "Super" + node = this.startNode() + this.next() + return this.finishNode(node, type) + + case tt._yield: + if (this.inGenerator) this.unexpected() + + case tt.name: + let startPos = this.start, startLoc = this.startLoc + let id = this.parseIdent(this.type !== tt.name) + if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) + return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id]) + return id + + case tt.regexp: + let value = this.value + node = this.parseLiteral(value.value) + node.regex = {pattern: value.pattern, flags: value.flags} + return node + + case tt.num: case tt.string: + return this.parseLiteral(this.value) + + case tt._null: case tt._true: case tt._false: + node = this.startNode() + node.value = this.type === tt._null ? null : this.type === tt._true + node.raw = this.type.keyword + this.next() + return this.finishNode(node, "Literal") + + case tt.parenL: + return this.parseParenAndDistinguishExpression(canBeArrow) + + case tt.bracketL: + node = this.startNode() + this.next() + // check whether this is array comprehension or regular array + if (this.options.ecmaVersion >= 7 && this.type === tt._for) { + return this.parseComprehension(node, false) + } + node.elements = this.parseExprList(tt.bracketR, true, true, refDestructuringErrors) + return this.finishNode(node, "ArrayExpression") + + case tt.braceL: + return this.parseObj(false, refDestructuringErrors) + + case tt._function: + node = this.startNode() + this.next() + return this.parseFunction(node, false) + + case tt._class: + return this.parseClass(this.startNode(), false) + + case tt._new: + return this.parseNew() + + case tt.backQuote: + return this.parseTemplate() + + default: + this.unexpected() + } +} + +pp.parseLiteral = function(value) { + let node = this.startNode() + node.value = value + node.raw = this.input.slice(this.start, this.end) + this.next() + return this.finishNode(node, "Literal") +} + +pp.parseParenExpression = function() { + this.expect(tt.parenL) + let val = this.parseExpression() + this.expect(tt.parenR) + return val +} + +pp.parseParenAndDistinguishExpression = function(canBeArrow) { + let startPos = this.start, startLoc = this.startLoc, val + if (this.options.ecmaVersion >= 6) { + this.next() + + if (this.options.ecmaVersion >= 7 && this.type === tt._for) { + return this.parseComprehension(this.startNodeAt(startPos, startLoc), true) + } + + let innerStartPos = this.start, innerStartLoc = this.startLoc + let exprList = [], first = true + let refDestructuringErrors = {shorthandAssign: 0, trailingComma: 0}, spreadStart, innerParenStart + while (this.type !== tt.parenR) { + first ? first = false : this.expect(tt.comma) + if (this.type === tt.ellipsis) { + spreadStart = this.start + exprList.push(this.parseParenItem(this.parseRest())) + break + } else { + if (this.type === tt.parenL && !innerParenStart) { + innerParenStart = this.start + } + exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem)) + } + } + let innerEndPos = this.start, innerEndLoc = this.startLoc + this.expect(tt.parenR) + + if (canBeArrow && !this.canInsertSemicolon() && this.eat(tt.arrow)) { + this.checkPatternErrors(refDestructuringErrors, true) + if (innerParenStart) this.unexpected(innerParenStart) + return this.parseParenArrowList(startPos, startLoc, exprList) + } + + if (!exprList.length) this.unexpected(this.lastTokStart) + if (spreadStart) this.unexpected(spreadStart) + this.checkExpressionErrors(refDestructuringErrors, true) + + if (exprList.length > 1) { + val = this.startNodeAt(innerStartPos, innerStartLoc) + val.expressions = exprList + this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc) + } else { + val = exprList[0] + } + } else { + val = this.parseParenExpression() + } + + if (this.options.preserveParens) { + let par = this.startNodeAt(startPos, startLoc) + par.expression = val + return this.finishNode(par, "ParenthesizedExpression") + } else { + return val + } +} + +pp.parseParenItem = function(item) { + return item +} + +pp.parseParenArrowList = function(startPos, startLoc, exprList) { + return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList) +} + +// New's precedence is slightly tricky. It must allow its argument to +// be a `[]` or dot subscript expression, but not a call — at least, +// not without wrapping it in parentheses. Thus, it uses the noCalls +// argument to parseSubscripts to prevent it from consuming the +// argument list. + +const empty = [] + +pp.parseNew = function() { + let node = this.startNode() + let meta = this.parseIdent(true) + if (this.options.ecmaVersion >= 6 && this.eat(tt.dot)) { + node.meta = meta + node.property = this.parseIdent(true) + if (node.property.name !== "target") + this.raise(node.property.start, "The only valid meta property for new is new.target") + if (!this.inFunction) + this.raise(node.start, "new.target can only be used in functions") + return this.finishNode(node, "MetaProperty") + } + let startPos = this.start, startLoc = this.startLoc + node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true) + if (this.eat(tt.parenL)) node.arguments = this.parseExprList(tt.parenR, false) + else node.arguments = empty + return this.finishNode(node, "NewExpression") +} + +// Parse template expression. + +pp.parseTemplateElement = function() { + let elem = this.startNode() + elem.value = { + raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, '\n'), + cooked: this.value + } + this.next() + elem.tail = this.type === tt.backQuote + return this.finishNode(elem, "TemplateElement") +} + +pp.parseTemplate = function() { + let node = this.startNode() + this.next() + node.expressions = [] + let curElt = this.parseTemplateElement() + node.quasis = [curElt] + while (!curElt.tail) { + this.expect(tt.dollarBraceL) + node.expressions.push(this.parseExpression()) + this.expect(tt.braceR) + node.quasis.push(curElt = this.parseTemplateElement()) + } + this.next() + return this.finishNode(node, "TemplateLiteral") +} + +// Parse an object literal or binding pattern. + +pp.parseObj = function(isPattern, refDestructuringErrors) { + let node = this.startNode(), first = true, propHash = {} + node.properties = [] + this.next() + while (!this.eat(tt.braceR)) { + if (!first) { + this.expect(tt.comma) + if (this.afterTrailingComma(tt.braceR)) break + } else first = false + + let prop = this.startNode(), isGenerator, startPos, startLoc + if (this.options.ecmaVersion >= 6) { + prop.method = false + prop.shorthand = false + if (isPattern || refDestructuringErrors) { + startPos = this.start + startLoc = this.startLoc + } + if (!isPattern) + isGenerator = this.eat(tt.star) + } + this.parsePropertyName(prop) + this.parsePropertyValue(prop, isPattern, isGenerator, startPos, startLoc, refDestructuringErrors) + this.checkPropClash(prop, propHash) + node.properties.push(this.finishNode(prop, "Property")) + } + return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression") +} + +pp.parsePropertyValue = function(prop, isPattern, isGenerator, startPos, startLoc, refDestructuringErrors) { + if (this.eat(tt.colon)) { + prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors) + prop.kind = "init" + } else if (this.options.ecmaVersion >= 6 && this.type === tt.parenL) { + if (isPattern) this.unexpected() + prop.kind = "init" + prop.method = true + prop.value = this.parseMethod(isGenerator) + } else if (this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && + (prop.key.name === "get" || prop.key.name === "set") && + (this.type != tt.comma && this.type != tt.braceR)) { + if (isGenerator || isPattern) this.unexpected() + prop.kind = prop.key.name + this.parsePropertyName(prop) + prop.value = this.parseMethod(false) + let paramCount = prop.kind === "get" ? 0 : 1 + if (prop.value.params.length !== paramCount) { + let start = prop.value.start + if (prop.kind === "get") + this.raise(start, "getter should have no params"); + else + this.raise(start, "setter should have exactly one param") + } + if (prop.kind === "set" && prop.value.params[0].type === "RestElement") + this.raise(prop.value.params[0].start, "Setter cannot use rest params") + } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { + prop.kind = "init" + if (isPattern) { + if (this.keywords.test(prop.key.name) || + (this.strict ? this.reservedWordsStrictBind : this.reservedWords).test(prop.key.name)) + this.raise(prop.key.start, "Binding " + prop.key.name) + prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key) + } else if (this.type === tt.eq && refDestructuringErrors) { + if (!refDestructuringErrors.shorthandAssign) + refDestructuringErrors.shorthandAssign = this.start + prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key) + } else { + prop.value = prop.key + } + prop.shorthand = true + } else this.unexpected() +} + +pp.parsePropertyName = function(prop) { + if (this.options.ecmaVersion >= 6) { + if (this.eat(tt.bracketL)) { + prop.computed = true + prop.key = this.parseMaybeAssign() + this.expect(tt.bracketR) + return prop.key + } else { + prop.computed = false + } + } + return prop.key = (this.type === tt.num || this.type === tt.string) ? this.parseExprAtom() : this.parseIdent(true) +} + +// Initialize empty function node. + +pp.initFunction = function(node) { + node.id = null + if (this.options.ecmaVersion >= 6) { + node.generator = false + node.expression = false + } +} + +// Parse object or class method. + +pp.parseMethod = function(isGenerator) { + let node = this.startNode() + this.initFunction(node) + this.expect(tt.parenL) + node.params = this.parseBindingList(tt.parenR, false, false) + if (this.options.ecmaVersion >= 6) + node.generator = isGenerator + this.parseFunctionBody(node, false) + return this.finishNode(node, "FunctionExpression") +} + +// Parse arrow function expression with given parameters. + +pp.parseArrowExpression = function(node, params) { + this.initFunction(node) + node.params = this.toAssignableList(params, true) + this.parseFunctionBody(node, true) + return this.finishNode(node, "ArrowFunctionExpression") +} + +// Parse function body and check parameters. + +pp.parseFunctionBody = function(node, isArrowFunction) { + let isExpression = isArrowFunction && this.type !== tt.braceL + + if (isExpression) { + node.body = this.parseMaybeAssign() + node.expression = true + } else { + // Start a new scope with regard to labels and the `inFunction` + // flag (restore them to their old value afterwards). + let oldInFunc = this.inFunction, oldInGen = this.inGenerator, oldLabels = this.labels + this.inFunction = true; this.inGenerator = node.generator; this.labels = [] + node.body = this.parseBlock(true) + node.expression = false + this.inFunction = oldInFunc; this.inGenerator = oldInGen; this.labels = oldLabels + } + + // If this is a strict mode function, verify that argument names + // are not repeated, and it does not try to bind the words `eval` + // or `arguments`. + if (this.strict || !isExpression && node.body.body.length && this.isUseStrict(node.body.body[0])) { + let oldStrict = this.strict + this.strict = true + if (node.id) + this.checkLVal(node.id, true) + this.checkParams(node); + this.strict = oldStrict + } else if (isArrowFunction) { + this.checkParams(node); + } +} + +// Checks function params for various disallowed patterns such as using "eval" +// or "arguments" and duplicate parameters. + +pp.checkParams = function(node) { + let nameHash = {}; + for (let i = 0; i < node.params.length; i++) + this.checkLVal(node.params[i], true, nameHash) +}; + +// Parses a comma-separated list of expressions, and returns them as +// an array. `close` is the token type that ends the list, and +// `allowEmpty` can be turned on to allow subsequent commas with +// nothing in between them to be parsed as `null` (which is needed +// for array literals). + +pp.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) { + let elts = [], first = true + while (!this.eat(close)) { + if (!first) { + this.expect(tt.comma) + if (this.type === close && refDestructuringErrors && !refDestructuringErrors.trailingComma) { + refDestructuringErrors.trailingComma = this.lastTokStart + } + if (allowTrailingComma && this.afterTrailingComma(close)) break + } else first = false + + let elt + if (allowEmpty && this.type === tt.comma) + elt = null + else if (this.type === tt.ellipsis) + elt = this.parseSpread(refDestructuringErrors) + else + elt = this.parseMaybeAssign(false, refDestructuringErrors) + elts.push(elt) + } + return elts +} + +// Parse the next token as an identifier. If `liberal` is true (used +// when parsing properties), it will also convert keywords into +// identifiers. + +pp.parseIdent = function(liberal) { + let node = this.startNode() + if (liberal && this.options.allowReserved == "never") liberal = false + if (this.type === tt.name) { + if (!liberal && (this.strict ? this.reservedWordsStrict : this.reservedWords).test(this.value) && + (this.options.ecmaVersion >= 6 || + this.input.slice(this.start, this.end).indexOf("\\") == -1)) + this.raise(this.start, "The keyword '" + this.value + "' is reserved") + node.name = this.value + } else if (liberal && this.type.keyword) { + node.name = this.type.keyword + } else { + this.unexpected() + } + this.next() + return this.finishNode(node, "Identifier") +} + +// Parses yield expression inside generator. + +pp.parseYield = function() { + let node = this.startNode() + this.next() + if (this.type == tt.semi || this.canInsertSemicolon() || (this.type != tt.star && !this.type.startsExpr)) { + node.delegate = false + node.argument = null + } else { + node.delegate = this.eat(tt.star) + node.argument = this.parseMaybeAssign() + } + return this.finishNode(node, "YieldExpression") +} + +// Parses array and generator comprehensions. + +pp.parseComprehension = function(node, isGenerator) { + node.blocks = [] + while (this.type === tt._for) { + let block = this.startNode() + this.next() + this.expect(tt.parenL) + block.left = this.parseBindingAtom() + this.checkLVal(block.left, true) + this.expectContextual("of") + block.right = this.parseExpression() + this.expect(tt.parenR) + node.blocks.push(this.finishNode(block, "ComprehensionBlock")) + } + node.filter = this.eat(tt._if) ? this.parseParenExpression() : null + node.body = this.parseExpression() + this.expect(isGenerator ? tt.parenR : tt.bracketR) + node.generator = isGenerator + return this.finishNode(node, "ComprehensionExpression") +} diff --git a/node_modules/acorn/src/identifier.js b/node_modules/acorn/src/identifier.js new file mode 100644 index 0000000..59ead43 --- /dev/null +++ b/node_modules/acorn/src/identifier.js @@ -0,0 +1,90 @@ +// This is a trick taken from Esprima. It turns out that, on +// non-Chrome browsers, to check whether a string is in a set, a +// predicate containing a big ugly `switch` statement is faster than +// a regular expression, and on Chrome the two are about on par. +// This function uses `eval` (non-lexical) to produce such a +// predicate from a space-separated string of words. +// +// It starts by sorting the words by length. + +// Reserved word lists for various dialects of the language + +export const reservedWords = { + 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile", + 5: "class enum extends super const export import", + 6: "enum", + strict: "implements interface let package private protected public static yield", + strictBind: "eval arguments" +} + +// And the keywords + +var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this" + +export const keywords = { + 5: ecma5AndLessKeywords, + 6: ecma5AndLessKeywords + " let const class extends export import yield super" +} + +// ## Character categories + +// Big ugly regular expressions that match characters in the +// whitespace, identifier, and identifier-start categories. These +// are only applied when a character is found to actually have a +// code point above 128. +// Generated by `bin/generate-identifier-regex.js`. + +let nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0-\u08b2\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua7ad\ua7b0\ua7b1\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab5f\uab64\uab65\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc" +let nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e4-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c03\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d01-\u0d03\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19b0-\u19c0\u19c8\u19c9\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1cf8\u1cf9\u1dc0-\u1df5\u1dfc-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f1\ua900-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2d\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f" + +const nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]") +const nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]") + +nonASCIIidentifierStartChars = nonASCIIidentifierChars = null + +// These are a run-length and offset encoded representation of the +// >0xffff code points that are a valid part of identifiers. The +// offset starts at 0x10000, and each pair of numbers represents an +// offset to the next range, and then a size of the range. They were +// generated by tools/generate-identifier-regex.js +var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,17,26,6,37,11,29,3,35,5,7,2,4,43,157,99,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,98,21,11,25,71,55,7,1,65,0,16,3,2,2,2,26,45,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,955,52,76,44,33,24,27,35,42,34,4,0,13,47,15,3,22,0,38,17,2,24,133,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,32,4,287,47,21,1,2,0,185,46,82,47,21,0,60,42,502,63,32,0,449,56,1288,920,104,110,2962,1070,13266,568,8,30,114,29,19,47,17,3,32,20,6,18,881,68,12,0,67,12,16481,1,3071,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,4149,196,1340,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42710,42,4148,12,221,16355,541] +var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,1306,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,52,0,13,2,49,13,16,9,83,11,168,11,6,9,8,2,57,0,2,6,3,1,3,2,10,0,11,1,3,6,4,4,316,19,13,9,214,6,3,8,112,16,16,9,82,12,9,9,535,9,20855,9,135,4,60,6,26,9,1016,45,17,3,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,4305,6,792618,239] + +// This has a complexity linear to the value of the code. The +// assumption is that looking up astral identifier characters is +// rare. +function isInAstralSet(code, set) { + let pos = 0x10000 + for (let i = 0; i < set.length; i += 2) { + pos += set[i] + if (pos > code) return false + pos += set[i + 1] + if (pos >= code) return true + } +} + +// Test whether a given character code starts an identifier. + +export function isIdentifierStart(code, astral) { + if (code < 65) return code === 36 + if (code < 91) return true + if (code < 97) return code === 95 + if (code < 123) return true + if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) + if (astral === false) return false + return isInAstralSet(code, astralIdentifierStartCodes) +} + +// Test whether a given character is part of an identifier. + +export function isIdentifierChar(code, astral) { + if (code < 48) return code === 36 + if (code < 58) return true + if (code < 65) return false + if (code < 91) return true + if (code < 97) return code === 95 + if (code < 123) return true + if (code <= 0xffff) return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) + if (astral === false) return false + return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes) +} diff --git a/node_modules/acorn/src/index.js b/node_modules/acorn/src/index.js new file mode 100644 index 0000000..8215f1b --- /dev/null +++ b/node_modules/acorn/src/index.js @@ -0,0 +1,67 @@ +// Acorn is a tiny, fast JavaScript parser written in JavaScript. +// +// Acorn was written by Marijn Haverbeke, Ingvar Stepanyan, and +// various contributors and released under an MIT license. +// +// Git repositories for Acorn are available at +// +// http://marijnhaverbeke.nl/git/acorn +// https://github.com/ternjs/acorn.git +// +// Please use the [github bug tracker][ghbt] to report issues. +// +// [ghbt]: https://github.com/ternjs/acorn/issues +// +// This file defines the main parser interface. The library also comes +// with a [error-tolerant parser][dammit] and an +// [abstract syntax tree walker][walk], defined in other files. +// +// [dammit]: acorn_loose.js +// [walk]: util/walk.js + +import {Parser} from "./state" +import "./parseutil" +import "./statement" +import "./lval" +import "./expression" +import "./location" + +export {Parser, plugins} from "./state" +export {defaultOptions} from "./options" +export {Position, SourceLocation, getLineInfo} from "./locutil" +export {Node} from "./node" +export {TokenType, types as tokTypes} from "./tokentype" +export {TokContext, types as tokContexts} from "./tokencontext" +export {isIdentifierChar, isIdentifierStart} from "./identifier" +export {Token} from "./tokenize" +export {isNewLine, lineBreak, lineBreakG} from "./whitespace" + +export const version = "2.7.0" + +// The main exported interface (under `self.acorn` when in the +// browser) is a `parse` function that takes a code string and +// returns an abstract syntax tree as specified by [Mozilla parser +// API][api]. +// +// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API + +export function parse(input, options) { + return new Parser(options, input).parse() +} + +// This function tries to parse a single expression at a given +// offset in a string. Useful for parsing mixed-language formats +// that embed JavaScript expressions. + +export function parseExpressionAt(input, pos, options) { + let p = new Parser(options, input, pos) + p.nextToken() + return p.parseExpression() +} + +// Acorn is organized as a tokenizer and a recursive-descent parser. +// The `tokenizer` export provides an interface to the tokenizer. + +export function tokenizer(input, options) { + return new Parser(options, input) +} diff --git a/node_modules/acorn/src/location.js b/node_modules/acorn/src/location.js new file mode 100644 index 0000000..4625dc3 --- /dev/null +++ b/node_modules/acorn/src/location.js @@ -0,0 +1,24 @@ +import {Parser} from "./state" +import {Position, getLineInfo} from "./locutil" + +const pp = Parser.prototype + +// This function is used to raise exceptions on parse errors. It +// takes an offset integer (into the current `input`) to indicate +// the location of the error, attaches the position to the end +// of the error message, and then raises a `SyntaxError` with that +// message. + +pp.raise = function(pos, message) { + let loc = getLineInfo(this.input, pos) + message += " (" + loc.line + ":" + loc.column + ")" + let err = new SyntaxError(message) + err.pos = pos; err.loc = loc; err.raisedAt = this.pos + throw err +} + +pp.curPosition = function() { + if (this.options.locations) { + return new Position(this.curLine, this.pos - this.lineStart) + } +} diff --git a/node_modules/acorn/src/locutil.js b/node_modules/acorn/src/locutil.js new file mode 100644 index 0000000..5a9465e --- /dev/null +++ b/node_modules/acorn/src/locutil.js @@ -0,0 +1,42 @@ +import {lineBreakG} from "./whitespace" + +// These are used when `options.locations` is on, for the +// `startLoc` and `endLoc` properties. + +export class Position { + constructor(line, col) { + this.line = line + this.column = col + } + + offset(n) { + return new Position(this.line, this.column + n) + } +} + +export class SourceLocation { + constructor(p, start, end) { + this.start = start + this.end = end + if (p.sourceFile !== null) this.source = p.sourceFile + } +} + +// The `getLineInfo` function is mostly useful when the +// `locations` option is off (for performance reasons) and you +// want to find the line/column position for a given character +// offset. `input` should be the code string that the offset refers +// into. + +export function getLineInfo(input, offset) { + for (let line = 1, cur = 0;;) { + lineBreakG.lastIndex = cur + let match = lineBreakG.exec(input) + if (match && match.index < offset) { + ++line + cur = match.index + match[0].length + } else { + return new Position(line, offset - cur) + } + } +} diff --git a/node_modules/acorn/src/loose/acorn_loose.js b/node_modules/acorn/src/loose/acorn_loose.js new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/acorn/src/loose/expression.js b/node_modules/acorn/src/loose/expression.js new file mode 100644 index 0000000..f3712c0 --- /dev/null +++ b/node_modules/acorn/src/loose/expression.js @@ -0,0 +1,501 @@ +import {LooseParser} from "./state" +import {isDummy} from "./parseutil" +import {tokTypes as tt} from ".." + +const lp = LooseParser.prototype + +lp.checkLVal = function(expr) { + if (!expr) return expr + switch (expr.type) { + case "Identifier": + case "MemberExpression": + return expr + + case "ParenthesizedExpression": + expr.expression = this.checkLVal(expr.expression) + return expr + + default: + return this.dummyIdent() + } +} + +lp.parseExpression = function(noIn) { + let start = this.storeCurrentPos() + let expr = this.parseMaybeAssign(noIn) + if (this.tok.type === tt.comma) { + let node = this.startNodeAt(start) + node.expressions = [expr] + while (this.eat(tt.comma)) node.expressions.push(this.parseMaybeAssign(noIn)) + return this.finishNode(node, "SequenceExpression") + } + return expr +} + +lp.parseParenExpression = function() { + this.pushCx() + this.expect(tt.parenL) + let val = this.parseExpression() + this.popCx() + this.expect(tt.parenR) + return val +} + +lp.parseMaybeAssign = function(noIn) { + let start = this.storeCurrentPos() + let left = this.parseMaybeConditional(noIn) + if (this.tok.type.isAssign) { + let node = this.startNodeAt(start) + node.operator = this.tok.value + node.left = this.tok.type === tt.eq ? this.toAssignable(left) : this.checkLVal(left) + this.next() + node.right = this.parseMaybeAssign(noIn) + return this.finishNode(node, "AssignmentExpression") + } + return left +} + +lp.parseMaybeConditional = function(noIn) { + let start = this.storeCurrentPos() + let expr = this.parseExprOps(noIn) + if (this.eat(tt.question)) { + let node = this.startNodeAt(start) + node.test = expr + node.consequent = this.parseMaybeAssign() + node.alternate = this.expect(tt.colon) ? this.parseMaybeAssign(noIn) : this.dummyIdent() + return this.finishNode(node, "ConditionalExpression") + } + return expr +} + +lp.parseExprOps = function(noIn) { + let start = this.storeCurrentPos() + let indent = this.curIndent, line = this.curLineStart + return this.parseExprOp(this.parseMaybeUnary(noIn), start, -1, noIn, indent, line) +} + +lp.parseExprOp = function(left, start, minPrec, noIn, indent, line) { + if (this.curLineStart != line && this.curIndent < indent && this.tokenStartsLine()) return left + let prec = this.tok.type.binop + if (prec != null && (!noIn || this.tok.type !== tt._in)) { + if (prec > minPrec) { + let node = this.startNodeAt(start) + node.left = left + node.operator = this.tok.value + this.next() + if (this.curLineStart != line && this.curIndent < indent && this.tokenStartsLine()) { + node.right = this.dummyIdent() + } else { + let rightStart = this.storeCurrentPos() + node.right = this.parseExprOp(this.parseMaybeUnary(noIn), rightStart, prec, noIn, indent, line) + } + this.finishNode(node, /&&|\|\|/.test(node.operator) ? "LogicalExpression" : "BinaryExpression") + return this.parseExprOp(node, start, minPrec, noIn, indent, line) + } + } + return left +} + +lp.parseMaybeUnary = function(noIn) { + if (this.tok.type.prefix) { + let node = this.startNode(), update = this.tok.type === tt.incDec + node.operator = this.tok.value + node.prefix = true + this.next() + node.argument = this.parseMaybeUnary(noIn) + if (update) node.argument = this.checkLVal(node.argument) + return this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression") + } else if (this.tok.type === tt.ellipsis) { + let node = this.startNode() + this.next() + node.argument = this.parseMaybeUnary(noIn) + return this.finishNode(node, "SpreadElement") + } + let start = this.storeCurrentPos() + let expr = this.parseExprSubscripts() + while (this.tok.type.postfix && !this.canInsertSemicolon()) { + let node = this.startNodeAt(start) + node.operator = this.tok.value + node.prefix = false + node.argument = this.checkLVal(expr) + this.next() + expr = this.finishNode(node, "UpdateExpression") + } + return expr +} + +lp.parseExprSubscripts = function() { + let start = this.storeCurrentPos() + return this.parseSubscripts(this.parseExprAtom(), start, false, this.curIndent, this.curLineStart) +} + +lp.parseSubscripts = function(base, start, noCalls, startIndent, line) { + for (;;) { + if (this.curLineStart != line && this.curIndent <= startIndent && this.tokenStartsLine()) { + if (this.tok.type == tt.dot && this.curIndent == startIndent) + --startIndent + else + return base + } + + if (this.eat(tt.dot)) { + let node = this.startNodeAt(start) + node.object = base + if (this.curLineStart != line && this.curIndent <= startIndent && this.tokenStartsLine()) + node.property = this.dummyIdent() + else + node.property = this.parsePropertyAccessor() || this.dummyIdent() + node.computed = false + base = this.finishNode(node, "MemberExpression") + } else if (this.tok.type == tt.bracketL) { + this.pushCx() + this.next() + let node = this.startNodeAt(start) + node.object = base + node.property = this.parseExpression() + node.computed = true + this.popCx() + this.expect(tt.bracketR) + base = this.finishNode(node, "MemberExpression") + } else if (!noCalls && this.tok.type == tt.parenL) { + let node = this.startNodeAt(start) + node.callee = base + node.arguments = this.parseExprList(tt.parenR) + base = this.finishNode(node, "CallExpression") + } else if (this.tok.type == tt.backQuote) { + let node = this.startNodeAt(start) + node.tag = base + node.quasi = this.parseTemplate() + base = this.finishNode(node, "TaggedTemplateExpression") + } else { + return base + } + } +} + +lp.parseExprAtom = function() { + let node + switch (this.tok.type) { + case tt._this: + case tt._super: + let type = this.tok.type === tt._this ? "ThisExpression" : "Super" + node = this.startNode() + this.next() + return this.finishNode(node, type) + + case tt.name: + let start = this.storeCurrentPos() + let id = this.parseIdent() + return this.eat(tt.arrow) ? this.parseArrowExpression(this.startNodeAt(start), [id]) : id + + case tt.regexp: + node = this.startNode() + let val = this.tok.value + node.regex = {pattern: val.pattern, flags: val.flags} + node.value = val.value + node.raw = this.input.slice(this.tok.start, this.tok.end) + this.next() + return this.finishNode(node, "Literal") + + case tt.num: case tt.string: + node = this.startNode() + node.value = this.tok.value + node.raw = this.input.slice(this.tok.start, this.tok.end) + this.next() + return this.finishNode(node, "Literal") + + case tt._null: case tt._true: case tt._false: + node = this.startNode() + node.value = this.tok.type === tt._null ? null : this.tok.type === tt._true + node.raw = this.tok.type.keyword + this.next() + return this.finishNode(node, "Literal") + + case tt.parenL: + let parenStart = this.storeCurrentPos() + this.next() + let inner = this.parseExpression() + this.expect(tt.parenR) + if (this.eat(tt.arrow)) { + return this.parseArrowExpression(this.startNodeAt(parenStart), inner.expressions || (isDummy(inner) ? [] : [inner])) + } + if (this.options.preserveParens) { + let par = this.startNodeAt(parenStart) + par.expression = inner + inner = this.finishNode(par, "ParenthesizedExpression") + } + return inner + + case tt.bracketL: + node = this.startNode() + node.elements = this.parseExprList(tt.bracketR, true) + return this.finishNode(node, "ArrayExpression") + + case tt.braceL: + return this.parseObj() + + case tt._class: + return this.parseClass() + + case tt._function: + node = this.startNode() + this.next() + return this.parseFunction(node, false) + + case tt._new: + return this.parseNew() + + case tt._yield: + node = this.startNode() + this.next() + if (this.semicolon() || this.canInsertSemicolon() || (this.tok.type != tt.star && !this.tok.type.startsExpr)) { + node.delegate = false + node.argument = null + } else { + node.delegate = this.eat(tt.star) + node.argument = this.parseMaybeAssign() + } + return this.finishNode(node, "YieldExpression") + + case tt.backQuote: + return this.parseTemplate() + + default: + return this.dummyIdent() + } +} + +lp.parseNew = function() { + let node = this.startNode(), startIndent = this.curIndent, line = this.curLineStart + let meta = this.parseIdent(true) + if (this.options.ecmaVersion >= 6 && this.eat(tt.dot)) { + node.meta = meta + node.property = this.parseIdent(true) + return this.finishNode(node, "MetaProperty") + } + let start = this.storeCurrentPos() + node.callee = this.parseSubscripts(this.parseExprAtom(), start, true, startIndent, line) + if (this.tok.type == tt.parenL) { + node.arguments = this.parseExprList(tt.parenR) + } else { + node.arguments = [] + } + return this.finishNode(node, "NewExpression") +} + +lp.parseTemplateElement = function() { + let elem = this.startNode() + elem.value = { + raw: this.input.slice(this.tok.start, this.tok.end).replace(/\r\n?/g, '\n'), + cooked: this.tok.value + } + this.next() + elem.tail = this.tok.type === tt.backQuote + return this.finishNode(elem, "TemplateElement") +} + +lp.parseTemplate = function() { + let node = this.startNode() + this.next() + node.expressions = [] + let curElt = this.parseTemplateElement() + node.quasis = [curElt] + while (!curElt.tail) { + this.next() + node.expressions.push(this.parseExpression()) + if (this.expect(tt.braceR)) { + curElt = this.parseTemplateElement() + } else { + curElt = this.startNode() + curElt.value = {cooked: '', raw: ''} + curElt.tail = true + } + node.quasis.push(curElt) + } + this.expect(tt.backQuote) + return this.finishNode(node, "TemplateLiteral") +} + +lp.parseObj = function() { + let node = this.startNode() + node.properties = [] + this.pushCx() + let indent = this.curIndent + 1, line = this.curLineStart + this.eat(tt.braceL) + if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart } + while (!this.closes(tt.braceR, indent, line)) { + let prop = this.startNode(), isGenerator, start + if (this.options.ecmaVersion >= 6) { + start = this.storeCurrentPos() + prop.method = false + prop.shorthand = false + isGenerator = this.eat(tt.star) + } + this.parsePropertyName(prop) + if (isDummy(prop.key)) { if (isDummy(this.parseMaybeAssign())) this.next(); this.eat(tt.comma); continue } + if (this.eat(tt.colon)) { + prop.kind = "init" + prop.value = this.parseMaybeAssign() + } else if (this.options.ecmaVersion >= 6 && (this.tok.type === tt.parenL || this.tok.type === tt.braceL)) { + prop.kind = "init" + prop.method = true + prop.value = this.parseMethod(isGenerator) + } else if (this.options.ecmaVersion >= 5 && prop.key.type === "Identifier" && + !prop.computed && (prop.key.name === "get" || prop.key.name === "set") && + (this.tok.type != tt.comma && this.tok.type != tt.braceR)) { + prop.kind = prop.key.name + this.parsePropertyName(prop) + prop.value = this.parseMethod(false) + } else { + prop.kind = "init" + if (this.options.ecmaVersion >= 6) { + if (this.eat(tt.eq)) { + let assign = this.startNodeAt(start) + assign.operator = "=" + assign.left = prop.key + assign.right = this.parseMaybeAssign() + prop.value = this.finishNode(assign, "AssignmentExpression") + } else { + prop.value = prop.key + } + } else { + prop.value = this.dummyIdent() + } + prop.shorthand = true + } + node.properties.push(this.finishNode(prop, "Property")) + this.eat(tt.comma) + } + this.popCx() + if (!this.eat(tt.braceR)) { + // If there is no closing brace, make the node span to the start + // of the next token (this is useful for Tern) + this.last.end = this.tok.start + if (this.options.locations) this.last.loc.end = this.tok.loc.start + } + return this.finishNode(node, "ObjectExpression") +} + +lp.parsePropertyName = function(prop) { + if (this.options.ecmaVersion >= 6) { + if (this.eat(tt.bracketL)) { + prop.computed = true + prop.key = this.parseExpression() + this.expect(tt.bracketR) + return + } else { + prop.computed = false + } + } + let key = (this.tok.type === tt.num || this.tok.type === tt.string) ? this.parseExprAtom() : this.parseIdent() + prop.key = key || this.dummyIdent() +} + +lp.parsePropertyAccessor = function() { + if (this.tok.type === tt.name || this.tok.type.keyword) return this.parseIdent() +} + +lp.parseIdent = function() { + let name = this.tok.type === tt.name ? this.tok.value : this.tok.type.keyword + if (!name) return this.dummyIdent() + let node = this.startNode() + this.next() + node.name = name + return this.finishNode(node, "Identifier") +} + +lp.initFunction = function(node) { + node.id = null + node.params = [] + if (this.options.ecmaVersion >= 6) { + node.generator = false + node.expression = false + } +} + +// Convert existing expression atom to assignable pattern +// if possible. + +lp.toAssignable = function(node, binding) { + if (!node || node.type == "Identifier" || (node.type == "MemberExpression" && !binding)) { + // Okay + } else if (node.type == "ParenthesizedExpression") { + node.expression = this.toAssignable(node.expression, binding) + } else if (this.options.ecmaVersion < 6) { + return this.dummyIdent() + } else if (node.type == "ObjectExpression") { + node.type = "ObjectPattern" + let props = node.properties + for (let i = 0; i < props.length; i++) + props[i].value = this.toAssignable(props[i].value, binding) + } else if (node.type == "ArrayExpression") { + node.type = "ArrayPattern" + this.toAssignableList(node.elements, binding) + } else if (node.type == "SpreadElement") { + node.type = "RestElement" + node.argument = this.toAssignable(node.argument, binding) + } else if (node.type == "AssignmentExpression") { + node.type = "AssignmentPattern" + delete node.operator + } else { + return this.dummyIdent() + } + return node +} + +lp.toAssignableList = function(exprList, binding) { + for (let i = 0; i < exprList.length; i++) + exprList[i] = this.toAssignable(exprList[i], binding) + return exprList +} + +lp.parseFunctionParams = function(params) { + params = this.parseExprList(tt.parenR) + return this.toAssignableList(params, true) +} + +lp.parseMethod = function(isGenerator) { + let node = this.startNode() + this.initFunction(node) + node.params = this.parseFunctionParams() + node.generator = isGenerator || false + node.expression = this.options.ecmaVersion >= 6 && this.tok.type !== tt.braceL + node.body = node.expression ? this.parseMaybeAssign() : this.parseBlock() + return this.finishNode(node, "FunctionExpression") +} + +lp.parseArrowExpression = function(node, params) { + this.initFunction(node) + node.params = this.toAssignableList(params, true) + node.expression = this.tok.type !== tt.braceL + node.body = node.expression ? this.parseMaybeAssign() : this.parseBlock() + return this.finishNode(node, "ArrowFunctionExpression") +} + +lp.parseExprList = function(close, allowEmpty) { + this.pushCx() + let indent = this.curIndent, line = this.curLineStart, elts = [] + this.next(); // Opening bracket + while (!this.closes(close, indent + 1, line)) { + if (this.eat(tt.comma)) { + elts.push(allowEmpty ? null : this.dummyIdent()) + continue + } + let elt = this.parseMaybeAssign() + if (isDummy(elt)) { + if (this.closes(close, indent, line)) break + this.next() + } else { + elts.push(elt) + } + this.eat(tt.comma) + } + this.popCx() + if (!this.eat(close)) { + // If there is no closing brace, make the node span to the start + // of the next token (this is useful for Tern) + this.last.end = this.tok.start + if (this.options.locations) this.last.loc.end = this.tok.loc.start + } + return elts +} diff --git a/node_modules/acorn/src/loose/index.js b/node_modules/acorn/src/loose/index.js new file mode 100644 index 0000000..7b3fad1 --- /dev/null +++ b/node_modules/acorn/src/loose/index.js @@ -0,0 +1,50 @@ +// Acorn: Loose parser +// +// This module provides an alternative parser (`parse_dammit`) that +// exposes that same interface as `parse`, but will try to parse +// anything as JavaScript, repairing syntax error the best it can. +// There are circumstances in which it will raise an error and give +// up, but they are very rare. The resulting AST will be a mostly +// valid JavaScript AST (as per the [Mozilla parser API][api], except +// that: +// +// - Return outside functions is allowed +// +// - Label consistency (no conflicts, break only to existing labels) +// is not enforced. +// +// - Bogus Identifier nodes with a name of `"✖"` are inserted whenever +// the parser got too confused to return anything meaningful. +// +// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API +// +// The expected use for this is to *first* try `acorn.parse`, and only +// if that fails switch to `parse_dammit`. The loose parser might +// parse badly indented code incorrectly, so **don't** use it as +// your default parser. +// +// Quite a lot of acorn.js is duplicated here. The alternative was to +// add a *lot* of extra cruft to that file, making it less readable +// and slower. Copying and editing the code allowed me to make +// invasive changes and simplifications without creating a complicated +// tangle. + +import * as acorn from ".." +import {LooseParser, pluginsLoose} from "./state" +import "./tokenize" +import "./statement" +import "./expression" + +export {LooseParser, pluginsLoose} from "./state" + +acorn.defaultOptions.tabSize = 4 + +export function parse_dammit(input, options) { + let p = new LooseParser(input, options) + p.next() + return p.parseTopLevel() +} + +acorn.parse_dammit = parse_dammit +acorn.LooseParser = LooseParser +acorn.pluginsLoose = pluginsLoose diff --git a/node_modules/acorn/src/loose/parseutil.js b/node_modules/acorn/src/loose/parseutil.js new file mode 100644 index 0000000..c5ee096 --- /dev/null +++ b/node_modules/acorn/src/loose/parseutil.js @@ -0,0 +1 @@ +export function isDummy(node) { return node.name == "✖" } \ No newline at end of file diff --git a/node_modules/acorn/src/loose/state.js b/node_modules/acorn/src/loose/state.js new file mode 100644 index 0000000..de33831 --- /dev/null +++ b/node_modules/acorn/src/loose/state.js @@ -0,0 +1,160 @@ +import {tokenizer, SourceLocation, tokTypes as tt, Node, lineBreak, isNewLine} from ".." + +// Registered plugins +export const pluginsLoose = {} + +export class LooseParser { + constructor(input, options) { + this.toks = tokenizer(input, options) + this.options = this.toks.options + this.input = this.toks.input + this.tok = this.last = {type: tt.eof, start: 0, end: 0} + if (this.options.locations) { + let here = this.toks.curPosition() + this.tok.loc = new SourceLocation(this.toks, here, here) + } + this.ahead = []; // Tokens ahead + this.context = []; // Indentation contexted + this.curIndent = 0 + this.curLineStart = 0 + this.nextLineStart = this.lineEnd(this.curLineStart) + 1 + // Load plugins + this.options.pluginsLoose = options.pluginsLoose || {} + this.loadPlugins(this.options.pluginsLoose) + } + + startNode() { + return new Node(this.toks, this.tok.start, this.options.locations ? this.tok.loc.start : null) + } + + storeCurrentPos() { + return this.options.locations ? [this.tok.start, this.tok.loc.start] : this.tok.start + } + + startNodeAt(pos) { + if (this.options.locations) { + return new Node(this.toks, pos[0], pos[1]) + } else { + return new Node(this.toks, pos) + } + } + + finishNode(node, type) { + node.type = type + node.end = this.last.end + if (this.options.locations) + node.loc.end = this.last.loc.end + if (this.options.ranges) + node.range[1] = this.last.end + return node + } + + dummyNode(type) { + let dummy = this.startNode() + dummy.type = type + dummy.end = dummy.start + if (this.options.locations) + dummy.loc.end = dummy.loc.start + if (this.options.ranges) + dummy.range[1] = dummy.start + this.last = {type: tt.name, start: dummy.start, end: dummy.start, loc: dummy.loc} + return dummy + } + + dummyIdent() { + let dummy = this.dummyNode("Identifier") + dummy.name = "✖" + return dummy + } + + dummyString() { + let dummy = this.dummyNode("Literal") + dummy.value = dummy.raw = "✖" + return dummy + } + + eat(type) { + if (this.tok.type === type) { + this.next() + return true + } else { + return false + } + } + + isContextual(name) { + return this.tok.type === tt.name && this.tok.value === name + } + + eatContextual(name) { + return this.tok.value === name && this.eat(tt.name) + } + + canInsertSemicolon() { + return this.tok.type === tt.eof || this.tok.type === tt.braceR || + lineBreak.test(this.input.slice(this.last.end, this.tok.start)) + } + + semicolon() { + return this.eat(tt.semi) + } + + expect(type) { + if (this.eat(type)) return true + for (let i = 1; i <= 2; i++) { + if (this.lookAhead(i).type == type) { + for (let j = 0; j < i; j++) this.next() + return true + } + } + } + + pushCx() { + this.context.push(this.curIndent) + } + + popCx() { + this.curIndent = this.context.pop() + } + + lineEnd(pos) { + while (pos < this.input.length && !isNewLine(this.input.charCodeAt(pos))) ++pos + return pos + } + + indentationAfter(pos) { + for (let count = 0;; ++pos) { + let ch = this.input.charCodeAt(pos) + if (ch === 32) ++count + else if (ch === 9) count += this.options.tabSize + else return count + } + } + + closes(closeTok, indent, line, blockHeuristic) { + if (this.tok.type === closeTok || this.tok.type === tt.eof) return true + return line != this.curLineStart && this.curIndent < indent && this.tokenStartsLine() && + (!blockHeuristic || this.nextLineStart >= this.input.length || + this.indentationAfter(this.nextLineStart) < indent) + } + + tokenStartsLine() { + for (let p = this.tok.start - 1; p >= this.curLineStart; --p) { + let ch = this.input.charCodeAt(p) + if (ch !== 9 && ch !== 32) return false + } + return true + } + + extend(name, f) { + this[name] = f(this[name]) + } + + loadPlugins(pluginConfigs) { + for (let name in pluginConfigs) { + let plugin = pluginsLoose[name] + if (!plugin) throw new Error("Plugin '" + name + "' not found") + plugin(this, pluginConfigs[name]) + } + } +} diff --git a/node_modules/acorn/src/loose/statement.js b/node_modules/acorn/src/loose/statement.js new file mode 100644 index 0000000..cffec9e --- /dev/null +++ b/node_modules/acorn/src/loose/statement.js @@ -0,0 +1,420 @@ +import {LooseParser} from "./state" +import {isDummy} from "./parseutil" +import {getLineInfo, tokTypes as tt} from ".." + +const lp = LooseParser.prototype + +lp.parseTopLevel = function() { + let node = this.startNodeAt(this.options.locations ? [0, getLineInfo(this.input, 0)] : 0) + node.body = [] + while (this.tok.type !== tt.eof) node.body.push(this.parseStatement()) + this.last = this.tok + if (this.options.ecmaVersion >= 6) { + node.sourceType = this.options.sourceType + } + return this.finishNode(node, "Program") +} + +lp.parseStatement = function() { + let starttype = this.tok.type, node = this.startNode() + + switch (starttype) { + case tt._break: case tt._continue: + this.next() + let isBreak = starttype === tt._break + if (this.semicolon() || this.canInsertSemicolon()) { + node.label = null + } else { + node.label = this.tok.type === tt.name ? this.parseIdent() : null + this.semicolon() + } + return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") + + case tt._debugger: + this.next() + this.semicolon() + return this.finishNode(node, "DebuggerStatement") + + case tt._do: + this.next() + node.body = this.parseStatement() + node.test = this.eat(tt._while) ? this.parseParenExpression() : this.dummyIdent() + this.semicolon() + return this.finishNode(node, "DoWhileStatement") + + case tt._for: + this.next() + this.pushCx() + this.expect(tt.parenL) + if (this.tok.type === tt.semi) return this.parseFor(node, null) + if (this.tok.type === tt._var || this.tok.type === tt._let || this.tok.type === tt._const) { + let init = this.parseVar(true) + if (init.declarations.length === 1 && (this.tok.type === tt._in || this.isContextual("of"))) { + return this.parseForIn(node, init) + } + return this.parseFor(node, init) + } + let init = this.parseExpression(true) + if (this.tok.type === tt._in || this.isContextual("of")) + return this.parseForIn(node, this.toAssignable(init)) + return this.parseFor(node, init) + + case tt._function: + this.next() + return this.parseFunction(node, true) + + case tt._if: + this.next() + node.test = this.parseParenExpression() + node.consequent = this.parseStatement() + node.alternate = this.eat(tt._else) ? this.parseStatement() : null + return this.finishNode(node, "IfStatement") + + case tt._return: + this.next() + if (this.eat(tt.semi) || this.canInsertSemicolon()) node.argument = null + else { node.argument = this.parseExpression(); this.semicolon() } + return this.finishNode(node, "ReturnStatement") + + case tt._switch: + let blockIndent = this.curIndent, line = this.curLineStart + this.next() + node.discriminant = this.parseParenExpression() + node.cases = [] + this.pushCx() + this.expect(tt.braceL) + + let cur + while (!this.closes(tt.braceR, blockIndent, line, true)) { + if (this.tok.type === tt._case || this.tok.type === tt._default) { + let isCase = this.tok.type === tt._case + if (cur) this.finishNode(cur, "SwitchCase") + node.cases.push(cur = this.startNode()) + cur.consequent = [] + this.next() + if (isCase) cur.test = this.parseExpression() + else cur.test = null + this.expect(tt.colon) + } else { + if (!cur) { + node.cases.push(cur = this.startNode()) + cur.consequent = [] + cur.test = null + } + cur.consequent.push(this.parseStatement()) + } + } + if (cur) this.finishNode(cur, "SwitchCase") + this.popCx() + this.eat(tt.braceR) + return this.finishNode(node, "SwitchStatement") + + case tt._throw: + this.next() + node.argument = this.parseExpression() + this.semicolon() + return this.finishNode(node, "ThrowStatement") + + case tt._try: + this.next() + node.block = this.parseBlock() + node.handler = null + if (this.tok.type === tt._catch) { + let clause = this.startNode() + this.next() + this.expect(tt.parenL) + clause.param = this.toAssignable(this.parseExprAtom(), true) + this.expect(tt.parenR) + clause.body = this.parseBlock() + node.handler = this.finishNode(clause, "CatchClause") + } + node.finalizer = this.eat(tt._finally) ? this.parseBlock() : null + if (!node.handler && !node.finalizer) return node.block + return this.finishNode(node, "TryStatement") + + case tt._var: + case tt._let: + case tt._const: + return this.parseVar() + + case tt._while: + this.next() + node.test = this.parseParenExpression() + node.body = this.parseStatement() + return this.finishNode(node, "WhileStatement") + + case tt._with: + this.next() + node.object = this.parseParenExpression() + node.body = this.parseStatement() + return this.finishNode(node, "WithStatement") + + case tt.braceL: + return this.parseBlock() + + case tt.semi: + this.next() + return this.finishNode(node, "EmptyStatement") + + case tt._class: + return this.parseClass(true) + + case tt._import: + return this.parseImport() + + case tt._export: + return this.parseExport() + + default: + let expr = this.parseExpression() + if (isDummy(expr)) { + this.next() + if (this.tok.type === tt.eof) return this.finishNode(node, "EmptyStatement") + return this.parseStatement() + } else if (starttype === tt.name && expr.type === "Identifier" && this.eat(tt.colon)) { + node.body = this.parseStatement() + node.label = expr + return this.finishNode(node, "LabeledStatement") + } else { + node.expression = expr + this.semicolon() + return this.finishNode(node, "ExpressionStatement") + } + } +} + +lp.parseBlock = function() { + let node = this.startNode() + this.pushCx() + this.expect(tt.braceL) + let blockIndent = this.curIndent, line = this.curLineStart + node.body = [] + while (!this.closes(tt.braceR, blockIndent, line, true)) + node.body.push(this.parseStatement()) + this.popCx() + this.eat(tt.braceR) + return this.finishNode(node, "BlockStatement") +} + +lp.parseFor = function(node, init) { + node.init = init + node.test = node.update = null + if (this.eat(tt.semi) && this.tok.type !== tt.semi) node.test = this.parseExpression() + if (this.eat(tt.semi) && this.tok.type !== tt.parenR) node.update = this.parseExpression() + this.popCx() + this.expect(tt.parenR) + node.body = this.parseStatement() + return this.finishNode(node, "ForStatement") +} + +lp.parseForIn = function(node, init) { + let type = this.tok.type === tt._in ? "ForInStatement" : "ForOfStatement" + this.next() + node.left = init + node.right = this.parseExpression() + this.popCx() + this.expect(tt.parenR) + node.body = this.parseStatement() + return this.finishNode(node, type) +} + +lp.parseVar = function(noIn) { + let node = this.startNode() + node.kind = this.tok.type.keyword + this.next() + node.declarations = [] + do { + let decl = this.startNode() + decl.id = this.options.ecmaVersion >= 6 ? this.toAssignable(this.parseExprAtom(), true) : this.parseIdent() + decl.init = this.eat(tt.eq) ? this.parseMaybeAssign(noIn) : null + node.declarations.push(this.finishNode(decl, "VariableDeclarator")) + } while (this.eat(tt.comma)) + if (!node.declarations.length) { + let decl = this.startNode() + decl.id = this.dummyIdent() + node.declarations.push(this.finishNode(decl, "VariableDeclarator")) + } + if (!noIn) this.semicolon() + return this.finishNode(node, "VariableDeclaration") +} + +lp.parseClass = function(isStatement) { + let node = this.startNode() + this.next() + if (this.tok.type === tt.name) node.id = this.parseIdent() + else if (isStatement) node.id = this.dummyIdent() + else node.id = null + node.superClass = this.eat(tt._extends) ? this.parseExpression() : null + node.body = this.startNode() + node.body.body = [] + this.pushCx() + let indent = this.curIndent + 1, line = this.curLineStart + this.eat(tt.braceL) + if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart } + while (!this.closes(tt.braceR, indent, line)) { + if (this.semicolon()) continue + let method = this.startNode(), isGenerator + if (this.options.ecmaVersion >= 6) { + method.static = false + isGenerator = this.eat(tt.star) + } + this.parsePropertyName(method) + if (isDummy(method.key)) { if (isDummy(this.parseMaybeAssign())) this.next(); this.eat(tt.comma); continue } + if (method.key.type === "Identifier" && !method.computed && method.key.name === "static" && + (this.tok.type != tt.parenL && this.tok.type != tt.braceL)) { + method.static = true + isGenerator = this.eat(tt.star) + this.parsePropertyName(method) + } else { + method.static = false + } + if (this.options.ecmaVersion >= 5 && method.key.type === "Identifier" && + !method.computed && (method.key.name === "get" || method.key.name === "set") && + this.tok.type !== tt.parenL && this.tok.type !== tt.braceL) { + method.kind = method.key.name + this.parsePropertyName(method) + method.value = this.parseMethod(false) + } else { + if (!method.computed && !method.static && !isGenerator && ( + method.key.type === "Identifier" && method.key.name === "constructor" || + method.key.type === "Literal" && method.key.value === "constructor")) { + method.kind = "constructor" + } else { + method.kind = "method" + } + method.value = this.parseMethod(isGenerator) + } + node.body.body.push(this.finishNode(method, "MethodDefinition")) + } + this.popCx() + if (!this.eat(tt.braceR)) { + // If there is no closing brace, make the node span to the start + // of the next token (this is useful for Tern) + this.last.end = this.tok.start + if (this.options.locations) this.last.loc.end = this.tok.loc.start + } + this.semicolon() + this.finishNode(node.body, "ClassBody") + return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") +} + +lp.parseFunction = function(node, isStatement) { + this.initFunction(node) + if (this.options.ecmaVersion >= 6) { + node.generator = this.eat(tt.star) + } + if (this.tok.type === tt.name) node.id = this.parseIdent() + else if (isStatement) node.id = this.dummyIdent() + node.params = this.parseFunctionParams() + node.body = this.parseBlock() + return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression") +} + +lp.parseExport = function() { + let node = this.startNode() + this.next() + if (this.eat(tt.star)) { + node.source = this.eatContextual("from") ? this.parseExprAtom() : null + return this.finishNode(node, "ExportAllDeclaration") + } + if (this.eat(tt._default)) { + let expr = this.parseMaybeAssign() + if (expr.id) { + switch (expr.type) { + case "FunctionExpression": expr.type = "FunctionDeclaration"; break + case "ClassExpression": expr.type = "ClassDeclaration"; break + } + } + node.declaration = expr + this.semicolon() + return this.finishNode(node, "ExportDefaultDeclaration") + } + if (this.tok.type.keyword) { + node.declaration = this.parseStatement() + node.specifiers = [] + node.source = null + } else { + node.declaration = null + node.specifiers = this.parseExportSpecifierList() + node.source = this.eatContextual("from") ? this.parseExprAtom() : null + this.semicolon() + } + return this.finishNode(node, "ExportNamedDeclaration") +} + +lp.parseImport = function() { + let node = this.startNode() + this.next() + if (this.tok.type === tt.string) { + node.specifiers = [] + node.source = this.parseExprAtom() + node.kind = '' + } else { + let elt + if (this.tok.type === tt.name && this.tok.value !== "from") { + elt = this.startNode() + elt.local = this.parseIdent() + this.finishNode(elt, "ImportDefaultSpecifier") + this.eat(tt.comma) + } + node.specifiers = this.parseImportSpecifierList() + node.source = this.eatContextual("from") && this.tok.type == tt.string ? this.parseExprAtom() : this.dummyString() + if (elt) node.specifiers.unshift(elt) + } + this.semicolon() + return this.finishNode(node, "ImportDeclaration") +} + +lp.parseImportSpecifierList = function() { + let elts = [] + if (this.tok.type === tt.star) { + let elt = this.startNode() + this.next() + if (this.eatContextual("as")) elt.local = this.parseIdent() + elts.push(this.finishNode(elt, "ImportNamespaceSpecifier")) + } else { + let indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart + this.pushCx() + this.eat(tt.braceL) + if (this.curLineStart > continuedLine) continuedLine = this.curLineStart + while (!this.closes(tt.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) { + let elt = this.startNode() + if (this.eat(tt.star)) { + elt.local = this.eatContextual("as") ? this.parseIdent() : this.dummyIdent() + this.finishNode(elt, "ImportNamespaceSpecifier") + } else { + if (this.isContextual("from")) break + elt.imported = this.parseIdent() + if (isDummy(elt.imported)) break + elt.local = this.eatContextual("as") ? this.parseIdent() : elt.imported + this.finishNode(elt, "ImportSpecifier") + } + elts.push(elt) + this.eat(tt.comma) + } + this.eat(tt.braceR) + this.popCx() + } + return elts +} + +lp.parseExportSpecifierList = function() { + let elts = [] + let indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart + this.pushCx() + this.eat(tt.braceL) + if (this.curLineStart > continuedLine) continuedLine = this.curLineStart + while (!this.closes(tt.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) { + if (this.isContextual("from")) break + let elt = this.startNode() + elt.local = this.parseIdent() + if (isDummy(elt.local)) break + elt.exported = this.eatContextual("as") ? this.parseIdent() : elt.local + this.finishNode(elt, "ExportSpecifier") + elts.push(elt) + this.eat(tt.comma) + } + this.eat(tt.braceR) + this.popCx() + return elts +} diff --git a/node_modules/acorn/src/loose/tokenize.js b/node_modules/acorn/src/loose/tokenize.js new file mode 100644 index 0000000..c20db22 --- /dev/null +++ b/node_modules/acorn/src/loose/tokenize.js @@ -0,0 +1,108 @@ +import {tokTypes as tt, Token, isNewLine, SourceLocation, getLineInfo, lineBreakG} from ".." +import {LooseParser} from "./state" + +const lp = LooseParser.prototype + +function isSpace(ch) { + return (ch < 14 && ch > 8) || ch === 32 || ch === 160 || isNewLine(ch) +} + +lp.next = function() { + this.last = this.tok + if (this.ahead.length) + this.tok = this.ahead.shift() + else + this.tok = this.readToken() + + if (this.tok.start >= this.nextLineStart) { + while (this.tok.start >= this.nextLineStart) { + this.curLineStart = this.nextLineStart + this.nextLineStart = this.lineEnd(this.curLineStart) + 1 + } + this.curIndent = this.indentationAfter(this.curLineStart) + } +} + +lp.readToken = function() { + for (;;) { + try { + this.toks.next() + if (this.toks.type === tt.dot && + this.input.substr(this.toks.end, 1) === "." && + this.options.ecmaVersion >= 6) { + this.toks.end++ + this.toks.type = tt.ellipsis + } + return new Token(this.toks) + } catch(e) { + if (!(e instanceof SyntaxError)) throw e + + // Try to skip some text, based on the error message, and then continue + let msg = e.message, pos = e.raisedAt, replace = true + if (/unterminated/i.test(msg)) { + pos = this.lineEnd(e.pos + 1) + if (/string/.test(msg)) { + replace = {start: e.pos, end: pos, type: tt.string, value: this.input.slice(e.pos + 1, pos)} + } else if (/regular expr/i.test(msg)) { + let re = this.input.slice(e.pos, pos) + try { re = new RegExp(re) } catch(e) {} + replace = {start: e.pos, end: pos, type: tt.regexp, value: re} + } else if (/template/.test(msg)) { + replace = {start: e.pos, end: pos, + type: tt.template, + value: this.input.slice(e.pos, pos)} + } else { + replace = false + } + } else if (/invalid (unicode|regexp|number)|expecting unicode|octal literal|is reserved|directly after number|expected number in radix/i.test(msg)) { + while (pos < this.input.length && !isSpace(this.input.charCodeAt(pos))) ++pos + } else if (/character escape|expected hexadecimal/i.test(msg)) { + while (pos < this.input.length) { + let ch = this.input.charCodeAt(pos++) + if (ch === 34 || ch === 39 || isNewLine(ch)) break + } + } else if (/unexpected character/i.test(msg)) { + pos++ + replace = false + } else if (/regular expression/i.test(msg)) { + replace = true + } else { + throw e + } + this.resetTo(pos) + if (replace === true) replace = {start: pos, end: pos, type: tt.name, value: "✖"} + if (replace) { + if (this.options.locations) + replace.loc = new SourceLocation( + this.toks, + getLineInfo(this.input, replace.start), + getLineInfo(this.input, replace.end)) + return replace + } + } + } +} + +lp.resetTo = function(pos) { + this.toks.pos = pos + let ch = this.input.charAt(pos - 1) + this.toks.exprAllowed = !ch || /[\[\{\(,;:?\/*=+\-~!|&%^<>]/.test(ch) || + /[enwfd]/.test(ch) && + /\b(keywords|case|else|return|throw|new|in|(instance|type)of|delete|void)$/.test(this.input.slice(pos - 10, pos)) + + if (this.options.locations) { + this.toks.curLine = 1 + this.toks.lineStart = lineBreakG.lastIndex = 0 + let match + while ((match = lineBreakG.exec(this.input)) && match.index < pos) { + ++this.toks.curLine + this.toks.lineStart = match.index + match[0].length + } + } +} + +lp.lookAhead = function(n) { + while (n > this.ahead.length) + this.ahead.push(this.readToken()) + return this.ahead[n - 1] +} diff --git a/node_modules/acorn/src/lval.js b/node_modules/acorn/src/lval.js new file mode 100644 index 0000000..1e2508e --- /dev/null +++ b/node_modules/acorn/src/lval.js @@ -0,0 +1,215 @@ +import {types as tt} from "./tokentype" +import {Parser} from "./state" +import {has} from "./util" + +const pp = Parser.prototype + +// Convert existing expression atom to assignable pattern +// if possible. + +pp.toAssignable = function(node, isBinding) { + if (this.options.ecmaVersion >= 6 && node) { + switch (node.type) { + case "Identifier": + case "ObjectPattern": + case "ArrayPattern": + break + + case "ObjectExpression": + node.type = "ObjectPattern" + for (let i = 0; i < node.properties.length; i++) { + let prop = node.properties[i] + if (prop.kind !== "init") this.raise(prop.key.start, "Object pattern can't contain getter or setter") + this.toAssignable(prop.value, isBinding) + } + break + + case "ArrayExpression": + node.type = "ArrayPattern" + this.toAssignableList(node.elements, isBinding) + break + + case "AssignmentExpression": + if (node.operator === "=") { + node.type = "AssignmentPattern" + delete node.operator + // falls through to AssignmentPattern + } else { + this.raise(node.left.end, "Only '=' operator can be used for specifying default value.") + break; + } + + case "AssignmentPattern": + if (node.right.type === "YieldExpression") + this.raise(node.right.start, "Yield expression cannot be a default value") + break; + + case "ParenthesizedExpression": + node.expression = this.toAssignable(node.expression, isBinding) + break + + case "MemberExpression": + if (!isBinding) break + + default: + this.raise(node.start, "Assigning to rvalue") + } + } + return node +} + +// Convert list of expression atoms to binding list. + +pp.toAssignableList = function(exprList, isBinding) { + let end = exprList.length + if (end) { + let last = exprList[end - 1] + if (last && last.type == "RestElement") { + --end + } else if (last && last.type == "SpreadElement") { + last.type = "RestElement" + let arg = last.argument + this.toAssignable(arg, isBinding) + if (arg.type !== "Identifier" && arg.type !== "MemberExpression" && arg.type !== "ArrayPattern") + this.unexpected(arg.start) + --end + } + + if (isBinding && last.type === "RestElement" && last.argument.type !== "Identifier") + this.unexpected(last.argument.start); + } + for (let i = 0; i < end; i++) { + let elt = exprList[i] + if (elt) this.toAssignable(elt, isBinding) + } + return exprList +} + +// Parses spread element. + +pp.parseSpread = function(refDestructuringErrors) { + let node = this.startNode() + this.next() + node.argument = this.parseMaybeAssign(refDestructuringErrors) + return this.finishNode(node, "SpreadElement") +} + +pp.parseRest = function(allowNonIdent) { + let node = this.startNode() + this.next() + + // RestElement inside of a function parameter must be an identifier + if (allowNonIdent) node.argument = this.type === tt.name ? this.parseIdent() : this.unexpected() + else node.argument = this.type === tt.name || this.type === tt.bracketL ? this.parseBindingAtom() : this.unexpected() + + return this.finishNode(node, "RestElement") +} + +// Parses lvalue (assignable) atom. + +pp.parseBindingAtom = function() { + if (this.options.ecmaVersion < 6) return this.parseIdent() + switch (this.type) { + case tt.name: + return this.parseIdent() + + case tt.bracketL: + let node = this.startNode() + this.next() + node.elements = this.parseBindingList(tt.bracketR, true, true) + return this.finishNode(node, "ArrayPattern") + + case tt.braceL: + return this.parseObj(true) + + default: + this.unexpected() + } +} + +pp.parseBindingList = function(close, allowEmpty, allowTrailingComma, allowNonIdent) { + let elts = [], first = true + while (!this.eat(close)) { + if (first) first = false + else this.expect(tt.comma) + if (allowEmpty && this.type === tt.comma) { + elts.push(null) + } else if (allowTrailingComma && this.afterTrailingComma(close)) { + break + } else if (this.type === tt.ellipsis) { + let rest = this.parseRest(allowNonIdent) + this.parseBindingListItem(rest) + elts.push(rest) + this.expect(close) + break + } else { + let elem = this.parseMaybeDefault(this.start, this.startLoc) + this.parseBindingListItem(elem) + elts.push(elem) + } + } + return elts +} + +pp.parseBindingListItem = function(param) { + return param +} + +// Parses assignment pattern around given atom if possible. + +pp.parseMaybeDefault = function(startPos, startLoc, left) { + left = left || this.parseBindingAtom() + if (this.options.ecmaVersion < 6 || !this.eat(tt.eq)) return left + let node = this.startNodeAt(startPos, startLoc) + node.left = left + node.right = this.parseMaybeAssign() + return this.finishNode(node, "AssignmentPattern") +} + +// Verify that a node is an lval — something that can be assigned +// to. + +pp.checkLVal = function(expr, isBinding, checkClashes) { + switch (expr.type) { + case "Identifier": + if (this.strict && this.reservedWordsStrictBind.test(expr.name)) + this.raise(expr.start, (isBinding ? "Binding " : "Assigning to ") + expr.name + " in strict mode") + if (checkClashes) { + if (has(checkClashes, expr.name)) + this.raise(expr.start, "Argument name clash") + checkClashes[expr.name] = true + } + break + + case "MemberExpression": + if (isBinding) this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " member expression") + break + + case "ObjectPattern": + for (let i = 0; i < expr.properties.length; i++) + this.checkLVal(expr.properties[i].value, isBinding, checkClashes) + break + + case "ArrayPattern": + for (let i = 0; i < expr.elements.length; i++) { + let elem = expr.elements[i] + if (elem) this.checkLVal(elem, isBinding, checkClashes) + } + break + + case "AssignmentPattern": + this.checkLVal(expr.left, isBinding, checkClashes) + break + + case "RestElement": + this.checkLVal(expr.argument, isBinding, checkClashes) + break + + case "ParenthesizedExpression": + this.checkLVal(expr.expression, isBinding, checkClashes) + break + + default: + this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " rvalue") + } +} diff --git a/node_modules/acorn/src/node.js b/node_modules/acorn/src/node.js new file mode 100644 index 0000000..76b5b09 --- /dev/null +++ b/node_modules/acorn/src/node.js @@ -0,0 +1,50 @@ +import {Parser} from "./state" +import {SourceLocation} from "./locutil" + +export class Node { + constructor(parser, pos, loc) { + this.type = "" + this.start = pos + this.end = 0 + if (parser.options.locations) + this.loc = new SourceLocation(parser, loc) + if (parser.options.directSourceFile) + this.sourceFile = parser.options.directSourceFile + if (parser.options.ranges) + this.range = [pos, 0] + } +} + +// Start an AST node, attaching a start offset. + +const pp = Parser.prototype + +pp.startNode = function() { + return new Node(this, this.start, this.startLoc) +} + +pp.startNodeAt = function(pos, loc) { + return new Node(this, pos, loc) +} + +// Finish an AST node, adding `type` and `end` properties. + +function finishNodeAt(node, type, pos, loc) { + node.type = type + node.end = pos + if (this.options.locations) + node.loc.end = loc + if (this.options.ranges) + node.range[1] = pos + return node +} + +pp.finishNode = function(node, type) { + return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc) +} + +// Finish node at given position + +pp.finishNodeAt = function(node, type, pos, loc) { + return finishNodeAt.call(this, node, type, pos, loc) +} diff --git a/node_modules/acorn/src/options.js b/node_modules/acorn/src/options.js new file mode 100644 index 0000000..f2d2981 --- /dev/null +++ b/node_modules/acorn/src/options.js @@ -0,0 +1,121 @@ +import {has, isArray} from "./util" +import {SourceLocation} from "./locutil" + +// A second optional argument can be given to further configure +// the parser process. These options are recognized: + +export const defaultOptions = { + // `ecmaVersion` indicates the ECMAScript version to parse. Must + // be either 3, or 5, or 6. This influences support for strict + // mode, the set of reserved words, support for getters and + // setters and other features. + ecmaVersion: 5, + // Source type ("script" or "module") for different semantics + sourceType: "script", + // `onInsertedSemicolon` can be a callback that will be called + // when a semicolon is automatically inserted. It will be passed + // th position of the comma as an offset, and if `locations` is + // enabled, it is given the location as a `{line, column}` object + // as second argument. + onInsertedSemicolon: null, + // `onTrailingComma` is similar to `onInsertedSemicolon`, but for + // trailing commas. + onTrailingComma: null, + // By default, reserved words are only enforced if ecmaVersion >= 5. + // Set `allowReserved` to a boolean value to explicitly turn this on + // an off. When this option has the value "never", reserved words + // and keywords can also not be used as property names. + allowReserved: null, + // When enabled, a return at the top level is not considered an + // error. + allowReturnOutsideFunction: false, + // When enabled, import/export statements are not constrained to + // appearing at the top of the program. + allowImportExportEverywhere: false, + // When enabled, hashbang directive in the beginning of file + // is allowed and treated as a line comment. + allowHashBang: false, + // When `locations` is on, `loc` properties holding objects with + // `start` and `end` properties in `{line, column}` form (with + // line being 1-based and column 0-based) will be attached to the + // nodes. + locations: false, + // A function can be passed as `onToken` option, which will + // cause Acorn to call that function with object in the same + // format as tokens returned from `tokenizer().getToken()`. Note + // that you are not allowed to call the parser from the + // callback—that will corrupt its internal state. + onToken: null, + // A function can be passed as `onComment` option, which will + // cause Acorn to call that function with `(block, text, start, + // end)` parameters whenever a comment is skipped. `block` is a + // boolean indicating whether this is a block (`/* */`) comment, + // `text` is the content of the comment, and `start` and `end` are + // character offsets that denote the start and end of the comment. + // When the `locations` option is on, two more parameters are + // passed, the full `{line, column}` locations of the start and + // end of the comments. Note that you are not allowed to call the + // parser from the callback—that will corrupt its internal state. + onComment: null, + // Nodes have their start and end characters offsets recorded in + // `start` and `end` properties (directly on the node, rather than + // the `loc` object, which holds line/column data. To also add a + // [semi-standardized][range] `range` property holding a `[start, + // end]` array with the same numbers, set the `ranges` option to + // `true`. + // + // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 + ranges: false, + // It is possible to parse multiple files into a single AST by + // passing the tree produced by parsing the first file as + // `program` option in subsequent parses. This will add the + // toplevel forms of the parsed file to the `Program` (top) node + // of an existing parse tree. + program: null, + // When `locations` is on, you can pass this to record the source + // file in every node's `loc` object. + sourceFile: null, + // This value, if given, is stored in every node, whether + // `locations` is on or off. + directSourceFile: null, + // When enabled, parenthesized expressions are represented by + // (non-standard) ParenthesizedExpression nodes + preserveParens: false, + plugins: {} +} + +// Interpret and default an options object + +export function getOptions(opts) { + let options = {} + for (let opt in defaultOptions) + options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt] + if (options.allowReserved == null) + options.allowReserved = options.ecmaVersion < 5 + + if (isArray(options.onToken)) { + let tokens = options.onToken + options.onToken = (token) => tokens.push(token) + } + if (isArray(options.onComment)) + options.onComment = pushComment(options, options.onComment) + + return options +} + +function pushComment(options, array) { + return function (block, text, start, end, startLoc, endLoc) { + let comment = { + type: block ? 'Block' : 'Line', + value: text, + start: start, + end: end + } + if (options.locations) + comment.loc = new SourceLocation(this, startLoc, endLoc) + if (options.ranges) + comment.range = [start, end] + array.push(comment) + } +} + diff --git a/node_modules/acorn/src/parseutil.js b/node_modules/acorn/src/parseutil.js new file mode 100644 index 0000000..9c71c48 --- /dev/null +++ b/node_modules/acorn/src/parseutil.js @@ -0,0 +1,102 @@ +import {types as tt} from "./tokentype" +import {Parser} from "./state" +import {lineBreak} from "./whitespace" + +const pp = Parser.prototype + +// ## Parser utilities + +// Test whether a statement node is the string literal `"use strict"`. + +pp.isUseStrict = function(stmt) { + return this.options.ecmaVersion >= 5 && stmt.type === "ExpressionStatement" && + stmt.expression.type === "Literal" && + stmt.expression.raw.slice(1, -1) === "use strict" +} + +// Predicate that tests whether the next token is of the given +// type, and if yes, consumes it as a side effect. + +pp.eat = function(type) { + if (this.type === type) { + this.next() + return true + } else { + return false + } +} + +// Tests whether parsed token is a contextual keyword. + +pp.isContextual = function(name) { + return this.type === tt.name && this.value === name +} + +// Consumes contextual keyword if possible. + +pp.eatContextual = function(name) { + return this.value === name && this.eat(tt.name) +} + +// Asserts that following token is given contextual keyword. + +pp.expectContextual = function(name) { + if (!this.eatContextual(name)) this.unexpected() +} + +// Test whether a semicolon can be inserted at the current position. + +pp.canInsertSemicolon = function() { + return this.type === tt.eof || + this.type === tt.braceR || + lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) +} + +pp.insertSemicolon = function() { + if (this.canInsertSemicolon()) { + if (this.options.onInsertedSemicolon) + this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc) + return true + } +} + +// Consume a semicolon, or, failing that, see if we are allowed to +// pretend that there is a semicolon at this position. + +pp.semicolon = function() { + if (!this.eat(tt.semi) && !this.insertSemicolon()) this.unexpected() +} + +pp.afterTrailingComma = function(tokType) { + if (this.type == tokType) { + if (this.options.onTrailingComma) + this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc) + this.next() + return true + } +} + +// Expect a token of a given type. If found, consume it, otherwise, +// raise an unexpected token error. + +pp.expect = function(type) { + this.eat(type) || this.unexpected() +} + +// Raise an unexpected token error. + +pp.unexpected = function(pos) { + this.raise(pos != null ? pos : this.start, "Unexpected token") +} + +pp.checkPatternErrors = function(refDestructuringErrors, andThrow) { + let pos = refDestructuringErrors && refDestructuringErrors.trailingComma + if (!andThrow) return !!pos + if (pos) this.raise(pos, "Trailing comma is not permitted in destructuring patterns") +} + +pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) { + let pos = refDestructuringErrors && refDestructuringErrors.shorthandAssign + if (!andThrow) return !!pos + if (pos) this.raise(pos, "Shorthand property assignments are valid only in destructuring patterns") +} diff --git a/node_modules/acorn/src/state.js b/node_modules/acorn/src/state.js new file mode 100644 index 0000000..3a0d5ff --- /dev/null +++ b/node_modules/acorn/src/state.js @@ -0,0 +1,104 @@ +import {reservedWords, keywords} from "./identifier" +import {types as tt} from "./tokentype" +import {lineBreak} from "./whitespace" +import {getOptions} from "./options" + +// Registered plugins +export const plugins = {} + +function keywordRegexp(words) { + return new RegExp("^(" + words.replace(/ /g, "|") + ")$") +} + +export class Parser { + constructor(options, input, startPos) { + this.options = options = getOptions(options) + this.sourceFile = options.sourceFile + this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5]) + let reserved = options.allowReserved ? "" : + reservedWords[options.ecmaVersion] + (options.sourceType == "module" ? " await" : "") + this.reservedWords = keywordRegexp(reserved) + let reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict + this.reservedWordsStrict = keywordRegexp(reservedStrict) + this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind) + this.input = String(input) + + // Used to signal to callers of `readWord1` whether the word + // contained any escape sequences. This is needed because words with + // escape sequences must not be interpreted as keywords. + this.containsEsc = false; + + // Load plugins + this.loadPlugins(options.plugins) + + // Set up token state + + // The current position of the tokenizer in the input. + if (startPos) { + this.pos = startPos + this.lineStart = Math.max(0, this.input.lastIndexOf("\n", startPos)) + this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length + } else { + this.pos = this.lineStart = 0 + this.curLine = 1 + } + + // Properties of the current token: + // Its type + this.type = tt.eof + // For tokens that include more information than their type, the value + this.value = null + // Its start and end offset + this.start = this.end = this.pos + // And, if locations are used, the {line, column} object + // corresponding to those offsets + this.startLoc = this.endLoc = this.curPosition() + + // Position information for the previous token + this.lastTokEndLoc = this.lastTokStartLoc = null + this.lastTokStart = this.lastTokEnd = this.pos + + // The context stack is used to superficially track syntactic + // context to predict whether a regular expression is allowed in a + // given position. + this.context = this.initialContext() + this.exprAllowed = true + + // Figure out if it's a module code. + this.strict = this.inModule = options.sourceType === "module" + + // Used to signify the start of a potential arrow function + this.potentialArrowAt = -1 + + // Flags to track whether we are in a function, a generator. + this.inFunction = this.inGenerator = false + // Labels in scope. + this.labels = [] + + // If enabled, skip leading hashbang line. + if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === '#!') + this.skipLineComment(2) + } + + // DEPRECATED Kept for backwards compatibility until 3.0 in case a plugin uses them + isKeyword(word) { return this.keywords.test(word) } + isReservedWord(word) { return this.reservedWords.test(word) } + + extend(name, f) { + this[name] = f(this[name]) + } + + loadPlugins(pluginConfigs) { + for (let name in pluginConfigs) { + let plugin = plugins[name] + if (!plugin) throw new Error("Plugin '" + name + "' not found") + plugin(this, pluginConfigs[name]) + } + } + + parse() { + let node = this.options.program || this.startNode() + this.nextToken() + return this.parseTopLevel(node) + } +} diff --git a/node_modules/acorn/src/statement.js b/node_modules/acorn/src/statement.js new file mode 100644 index 0000000..7ade79f --- /dev/null +++ b/node_modules/acorn/src/statement.js @@ -0,0 +1,626 @@ +import {types as tt} from "./tokentype" +import {Parser} from "./state" +import {lineBreak} from "./whitespace" + +const pp = Parser.prototype + +// ### Statement parsing + +// Parse a program. Initializes the parser, reads any number of +// statements, and wraps them in a Program node. Optionally takes a +// `program` argument. If present, the statements will be appended +// to its body instead of creating a new node. + +pp.parseTopLevel = function(node) { + let first = true + if (!node.body) node.body = [] + while (this.type !== tt.eof) { + let stmt = this.parseStatement(true, true) + node.body.push(stmt) + if (first) { + if (this.isUseStrict(stmt)) this.setStrict(true) + first = false + } + } + this.next() + if (this.options.ecmaVersion >= 6) { + node.sourceType = this.options.sourceType + } + return this.finishNode(node, "Program") +} + +const loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"} + +// Parse a single statement. +// +// If expecting a statement and finding a slash operator, parse a +// regular expression literal. This is to handle cases like +// `if (foo) /blah/.exec(foo)`, where looking at the previous token +// does not help. + +pp.parseStatement = function(declaration, topLevel) { + let starttype = this.type, node = this.startNode() + + // Most types of statements are recognized by the keyword they + // start with. Many are trivial to parse, some require a bit of + // complexity. + + switch (starttype) { + case tt._break: case tt._continue: return this.parseBreakContinueStatement(node, starttype.keyword) + case tt._debugger: return this.parseDebuggerStatement(node) + case tt._do: return this.parseDoStatement(node) + case tt._for: return this.parseForStatement(node) + case tt._function: + if (!declaration && this.options.ecmaVersion >= 6) this.unexpected() + return this.parseFunctionStatement(node) + case tt._class: + if (!declaration) this.unexpected() + return this.parseClass(node, true) + case tt._if: return this.parseIfStatement(node) + case tt._return: return this.parseReturnStatement(node) + case tt._switch: return this.parseSwitchStatement(node) + case tt._throw: return this.parseThrowStatement(node) + case tt._try: return this.parseTryStatement(node) + case tt._let: case tt._const: if (!declaration) this.unexpected() // NOTE: falls through to _var + case tt._var: return this.parseVarStatement(node, starttype) + case tt._while: return this.parseWhileStatement(node) + case tt._with: return this.parseWithStatement(node) + case tt.braceL: return this.parseBlock() + case tt.semi: return this.parseEmptyStatement(node) + case tt._export: + case tt._import: + if (!this.options.allowImportExportEverywhere) { + if (!topLevel) + this.raise(this.start, "'import' and 'export' may only appear at the top level") + if (!this.inModule) + this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'") + } + return starttype === tt._import ? this.parseImport(node) : this.parseExport(node) + + // If the statement does not start with a statement keyword or a + // brace, it's an ExpressionStatement or LabeledStatement. We + // simply start parsing an expression, and afterwards, if the + // next token is a colon and the expression was a simple + // Identifier node, we switch to interpreting it as a label. + default: + let maybeName = this.value, expr = this.parseExpression() + if (starttype === tt.name && expr.type === "Identifier" && this.eat(tt.colon)) + return this.parseLabeledStatement(node, maybeName, expr) + else return this.parseExpressionStatement(node, expr) + } +} + +pp.parseBreakContinueStatement = function(node, keyword) { + let isBreak = keyword == "break" + this.next() + if (this.eat(tt.semi) || this.insertSemicolon()) node.label = null + else if (this.type !== tt.name) this.unexpected() + else { + node.label = this.parseIdent() + this.semicolon() + } + + // Verify that there is an actual destination to break or + // continue to. + for (var i = 0; i < this.labels.length; ++i) { + let lab = this.labels[i] + if (node.label == null || lab.name === node.label.name) { + if (lab.kind != null && (isBreak || lab.kind === "loop")) break + if (node.label && isBreak) break + } + } + if (i === this.labels.length) this.raise(node.start, "Unsyntactic " + keyword) + return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") +} + +pp.parseDebuggerStatement = function(node) { + this.next() + this.semicolon() + return this.finishNode(node, "DebuggerStatement") +} + +pp.parseDoStatement = function(node) { + this.next() + this.labels.push(loopLabel) + node.body = this.parseStatement(false) + this.labels.pop() + this.expect(tt._while) + node.test = this.parseParenExpression() + if (this.options.ecmaVersion >= 6) + this.eat(tt.semi) + else + this.semicolon() + return this.finishNode(node, "DoWhileStatement") +} + +// Disambiguating between a `for` and a `for`/`in` or `for`/`of` +// loop is non-trivial. Basically, we have to parse the init `var` +// statement or expression, disallowing the `in` operator (see +// the second parameter to `parseExpression`), and then check +// whether the next token is `in` or `of`. When there is no init +// part (semicolon immediately after the opening parenthesis), it +// is a regular `for` loop. + +pp.parseForStatement = function(node) { + this.next() + this.labels.push(loopLabel) + this.expect(tt.parenL) + if (this.type === tt.semi) return this.parseFor(node, null) + if (this.type === tt._var || this.type === tt._let || this.type === tt._const) { + let init = this.startNode(), varKind = this.type + this.next() + this.parseVar(init, true, varKind) + this.finishNode(init, "VariableDeclaration") + if ((this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init.declarations.length === 1 && + !(varKind !== tt._var && init.declarations[0].init)) + return this.parseForIn(node, init) + return this.parseFor(node, init) + } + let refDestructuringErrors = {shorthandAssign: 0, trailingComma: 0} + let init = this.parseExpression(true, refDestructuringErrors) + if (this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) { + this.checkPatternErrors(refDestructuringErrors, true) + this.toAssignable(init) + this.checkLVal(init) + return this.parseForIn(node, init) + } else { + this.checkExpressionErrors(refDestructuringErrors, true) + } + return this.parseFor(node, init) +} + +pp.parseFunctionStatement = function(node) { + this.next() + return this.parseFunction(node, true) +} + +pp.parseIfStatement = function(node) { + this.next() + node.test = this.parseParenExpression() + node.consequent = this.parseStatement(false) + node.alternate = this.eat(tt._else) ? this.parseStatement(false) : null + return this.finishNode(node, "IfStatement") +} + +pp.parseReturnStatement = function(node) { + if (!this.inFunction && !this.options.allowReturnOutsideFunction) + this.raise(this.start, "'return' outside of function") + this.next() + + // In `return` (and `break`/`continue`), the keywords with + // optional arguments, we eagerly look for a semicolon or the + // possibility to insert one. + + if (this.eat(tt.semi) || this.insertSemicolon()) node.argument = null + else { node.argument = this.parseExpression(); this.semicolon() } + return this.finishNode(node, "ReturnStatement") +} + +pp.parseSwitchStatement = function(node) { + this.next() + node.discriminant = this.parseParenExpression() + node.cases = [] + this.expect(tt.braceL) + this.labels.push(switchLabel) + + // Statements under must be grouped (by label) in SwitchCase + // nodes. `cur` is used to keep the node that we are currently + // adding statements to. + + for (var cur, sawDefault = false; this.type != tt.braceR;) { + if (this.type === tt._case || this.type === tt._default) { + let isCase = this.type === tt._case + if (cur) this.finishNode(cur, "SwitchCase") + node.cases.push(cur = this.startNode()) + cur.consequent = [] + this.next() + if (isCase) { + cur.test = this.parseExpression() + } else { + if (sawDefault) this.raise(this.lastTokStart, "Multiple default clauses") + sawDefault = true + cur.test = null + } + this.expect(tt.colon) + } else { + if (!cur) this.unexpected() + cur.consequent.push(this.parseStatement(true)) + } + } + if (cur) this.finishNode(cur, "SwitchCase") + this.next() // Closing brace + this.labels.pop() + return this.finishNode(node, "SwitchStatement") +} + +pp.parseThrowStatement = function(node) { + this.next() + if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) + this.raise(this.lastTokEnd, "Illegal newline after throw") + node.argument = this.parseExpression() + this.semicolon() + return this.finishNode(node, "ThrowStatement") +} + +// Reused empty array added for node fields that are always empty. + +const empty = [] + +pp.parseTryStatement = function(node) { + this.next() + node.block = this.parseBlock() + node.handler = null + if (this.type === tt._catch) { + let clause = this.startNode() + this.next() + this.expect(tt.parenL) + clause.param = this.parseBindingAtom() + this.checkLVal(clause.param, true) + this.expect(tt.parenR) + clause.body = this.parseBlock() + node.handler = this.finishNode(clause, "CatchClause") + } + node.finalizer = this.eat(tt._finally) ? this.parseBlock() : null + if (!node.handler && !node.finalizer) + this.raise(node.start, "Missing catch or finally clause") + return this.finishNode(node, "TryStatement") +} + +pp.parseVarStatement = function(node, kind) { + this.next() + this.parseVar(node, false, kind) + this.semicolon() + return this.finishNode(node, "VariableDeclaration") +} + +pp.parseWhileStatement = function(node) { + this.next() + node.test = this.parseParenExpression() + this.labels.push(loopLabel) + node.body = this.parseStatement(false) + this.labels.pop() + return this.finishNode(node, "WhileStatement") +} + +pp.parseWithStatement = function(node) { + if (this.strict) this.raise(this.start, "'with' in strict mode") + this.next() + node.object = this.parseParenExpression() + node.body = this.parseStatement(false) + return this.finishNode(node, "WithStatement") +} + +pp.parseEmptyStatement = function(node) { + this.next() + return this.finishNode(node, "EmptyStatement") +} + +pp.parseLabeledStatement = function(node, maybeName, expr) { + for (let i = 0; i < this.labels.length; ++i) + if (this.labels[i].name === maybeName) this.raise(expr.start, "Label '" + maybeName + "' is already declared") + let kind = this.type.isLoop ? "loop" : this.type === tt._switch ? "switch" : null + for (let i = this.labels.length - 1; i >= 0; i--) { + let label = this.labels[i] + if (label.statementStart == node.start) { + label.statementStart = this.start; + label.kind = kind; + } else break; + } + this.labels.push({name: maybeName, kind: kind, statementStart: this.start}) + node.body = this.parseStatement(true) + this.labels.pop() + node.label = expr + return this.finishNode(node, "LabeledStatement") +} + +pp.parseExpressionStatement = function(node, expr) { + node.expression = expr + this.semicolon() + return this.finishNode(node, "ExpressionStatement") +} + +// Parse a semicolon-enclosed block of statements, handling `"use +// strict"` declarations when `allowStrict` is true (used for +// function bodies). + +pp.parseBlock = function(allowStrict) { + let node = this.startNode(), first = true, oldStrict + node.body = [] + this.expect(tt.braceL) + while (!this.eat(tt.braceR)) { + let stmt = this.parseStatement(true) + node.body.push(stmt) + if (first && allowStrict && this.isUseStrict(stmt)) { + oldStrict = this.strict + this.setStrict(this.strict = true) + } + first = false + } + if (oldStrict === false) this.setStrict(false) + return this.finishNode(node, "BlockStatement") +} + +// Parse a regular `for` loop. The disambiguation code in +// `parseStatement` will already have parsed the init statement or +// expression. + +pp.parseFor = function(node, init) { + node.init = init + this.expect(tt.semi) + node.test = this.type === tt.semi ? null : this.parseExpression() + this.expect(tt.semi) + node.update = this.type === tt.parenR ? null : this.parseExpression() + this.expect(tt.parenR) + node.body = this.parseStatement(false) + this.labels.pop() + return this.finishNode(node, "ForStatement") +} + +// Parse a `for`/`in` and `for`/`of` loop, which are almost +// same from parser's perspective. + +pp.parseForIn = function(node, init) { + let type = this.type === tt._in ? "ForInStatement" : "ForOfStatement" + this.next() + node.left = init + node.right = this.parseExpression() + this.expect(tt.parenR) + node.body = this.parseStatement(false) + this.labels.pop() + return this.finishNode(node, type) +} + +// Parse a list of variable declarations. + +pp.parseVar = function(node, isFor, kind) { + node.declarations = [] + node.kind = kind.keyword + for (;;) { + let decl = this.startNode() + this.parseVarId(decl) + if (this.eat(tt.eq)) { + decl.init = this.parseMaybeAssign(isFor) + } else if (kind === tt._const && !(this.type === tt._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) { + this.unexpected() + } else if (decl.id.type != "Identifier" && !(isFor && (this.type === tt._in || this.isContextual("of")))) { + this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value") + } else { + decl.init = null + } + node.declarations.push(this.finishNode(decl, "VariableDeclarator")) + if (!this.eat(tt.comma)) break + } + return node +} + +pp.parseVarId = function(decl) { + decl.id = this.parseBindingAtom() + this.checkLVal(decl.id, true) +} + +// Parse a function declaration or literal (depending on the +// `isStatement` parameter). + +pp.parseFunction = function(node, isStatement, allowExpressionBody) { + this.initFunction(node) + if (this.options.ecmaVersion >= 6) + node.generator = this.eat(tt.star) + if (isStatement || this.type === tt.name) + node.id = this.parseIdent() + this.parseFunctionParams(node) + this.parseFunctionBody(node, allowExpressionBody) + return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression") +} + +pp.parseFunctionParams = function(node) { + this.expect(tt.parenL) + node.params = this.parseBindingList(tt.parenR, false, false, true) +} + +// Parse a class declaration or literal (depending on the +// `isStatement` parameter). + +pp.parseClass = function(node, isStatement) { + this.next() + this.parseClassId(node, isStatement) + this.parseClassSuper(node) + let classBody = this.startNode() + let hadConstructor = false + classBody.body = [] + this.expect(tt.braceL) + while (!this.eat(tt.braceR)) { + if (this.eat(tt.semi)) continue + let method = this.startNode() + let isGenerator = this.eat(tt.star) + let isMaybeStatic = this.type === tt.name && this.value === "static" + this.parsePropertyName(method) + method.static = isMaybeStatic && this.type !== tt.parenL + if (method.static) { + if (isGenerator) this.unexpected() + isGenerator = this.eat(tt.star) + this.parsePropertyName(method) + } + method.kind = "method" + let isGetSet = false + if (!method.computed) { + let {key} = method + if (!isGenerator && key.type === "Identifier" && this.type !== tt.parenL && (key.name === "get" || key.name === "set")) { + isGetSet = true + method.kind = key.name + key = this.parsePropertyName(method) + } + if (!method.static && (key.type === "Identifier" && key.name === "constructor" || + key.type === "Literal" && key.value === "constructor")) { + if (hadConstructor) this.raise(key.start, "Duplicate constructor in the same class") + if (isGetSet) this.raise(key.start, "Constructor can't have get/set modifier") + if (isGenerator) this.raise(key.start, "Constructor can't be a generator") + method.kind = "constructor" + hadConstructor = true + } + } + this.parseClassMethod(classBody, method, isGenerator) + if (isGetSet) { + let paramCount = method.kind === "get" ? 0 : 1 + if (method.value.params.length !== paramCount) { + let start = method.value.start + if (method.kind === "get") + this.raise(start, "getter should have no params"); + else + this.raise(start, "setter should have exactly one param") + } + if (method.kind === "set" && method.value.params[0].type === "RestElement") + this.raise(method.value.params[0].start, "Setter cannot use rest params") + } + } + node.body = this.finishNode(classBody, "ClassBody") + return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") +} + +pp.parseClassMethod = function(classBody, method, isGenerator) { + method.value = this.parseMethod(isGenerator) + classBody.body.push(this.finishNode(method, "MethodDefinition")) +} + +pp.parseClassId = function(node, isStatement) { + node.id = this.type === tt.name ? this.parseIdent() : isStatement ? this.unexpected() : null +} + +pp.parseClassSuper = function(node) { + node.superClass = this.eat(tt._extends) ? this.parseExprSubscripts() : null +} + +// Parses module export declaration. + +pp.parseExport = function(node) { + this.next() + // export * from '...' + if (this.eat(tt.star)) { + this.expectContextual("from") + node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected() + this.semicolon() + return this.finishNode(node, "ExportAllDeclaration") + } + if (this.eat(tt._default)) { // export default ... + let expr = this.parseMaybeAssign() + let needsSemi = true + if (expr.type == "FunctionExpression" || + expr.type == "ClassExpression") { + needsSemi = false + if (expr.id) { + expr.type = expr.type == "FunctionExpression" + ? "FunctionDeclaration" + : "ClassDeclaration" + } + } + node.declaration = expr + if (needsSemi) this.semicolon() + return this.finishNode(node, "ExportDefaultDeclaration") + } + // export var|const|let|function|class ... + if (this.shouldParseExportStatement()) { + node.declaration = this.parseStatement(true) + node.specifiers = [] + node.source = null + } else { // export { x, y as z } [from '...'] + node.declaration = null + node.specifiers = this.parseExportSpecifiers() + if (this.eatContextual("from")) { + node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected() + } else { + // check for keywords used as local names + for (let i = 0; i < node.specifiers.length; i++) { + if (this.keywords.test(node.specifiers[i].local.name) || this.reservedWords.test(node.specifiers[i].local.name)) { + this.unexpected(node.specifiers[i].local.start) + } + } + + node.source = null + } + this.semicolon() + } + return this.finishNode(node, "ExportNamedDeclaration") +} + +pp.shouldParseExportStatement = function() { + return this.type.keyword +} + +// Parses a comma-separated list of module exports. + +pp.parseExportSpecifiers = function() { + let nodes = [], first = true + // export { x, y as z } [from '...'] + this.expect(tt.braceL) + while (!this.eat(tt.braceR)) { + if (!first) { + this.expect(tt.comma) + if (this.afterTrailingComma(tt.braceR)) break + } else first = false + + let node = this.startNode() + node.local = this.parseIdent(this.type === tt._default) + node.exported = this.eatContextual("as") ? this.parseIdent(true) : node.local + nodes.push(this.finishNode(node, "ExportSpecifier")) + } + return nodes +} + +// Parses import declaration. + +pp.parseImport = function(node) { + this.next() + // import '...' + if (this.type === tt.string) { + node.specifiers = empty + node.source = this.parseExprAtom() + } else { + node.specifiers = this.parseImportSpecifiers() + this.expectContextual("from") + node.source = this.type === tt.string ? this.parseExprAtom() : this.unexpected() + } + this.semicolon() + return this.finishNode(node, "ImportDeclaration") +} + +// Parses a comma-separated list of module imports. + +pp.parseImportSpecifiers = function() { + let nodes = [], first = true + if (this.type === tt.name) { + // import defaultObj, { x, y as z } from '...' + let node = this.startNode() + node.local = this.parseIdent() + this.checkLVal(node.local, true) + nodes.push(this.finishNode(node, "ImportDefaultSpecifier")) + if (!this.eat(tt.comma)) return nodes + } + if (this.type === tt.star) { + let node = this.startNode() + this.next() + this.expectContextual("as") + node.local = this.parseIdent() + this.checkLVal(node.local, true) + nodes.push(this.finishNode(node, "ImportNamespaceSpecifier")) + return nodes + } + this.expect(tt.braceL) + while (!this.eat(tt.braceR)) { + if (!first) { + this.expect(tt.comma) + if (this.afterTrailingComma(tt.braceR)) break + } else first = false + + let node = this.startNode() + node.imported = this.parseIdent(true) + if (this.eatContextual("as")) { + node.local = this.parseIdent() + } else { + node.local = node.imported + if (this.isKeyword(node.local.name)) this.unexpected(node.local.start) + if (this.reservedWordsStrict.test(node.local.name)) this.raise(node.local.start, "The keyword '" + node.local.name + "' is reserved") + } + this.checkLVal(node.local, true) + nodes.push(this.finishNode(node, "ImportSpecifier")) + } + return nodes +} diff --git a/node_modules/acorn/src/tokencontext.js b/node_modules/acorn/src/tokencontext.js new file mode 100644 index 0000000..c76fc9d --- /dev/null +++ b/node_modules/acorn/src/tokencontext.js @@ -0,0 +1,109 @@ +// The algorithm used to determine whether a regexp can appear at a +// given point in the program is loosely based on sweet.js' approach. +// See https://github.com/mozilla/sweet.js/wiki/design + +import {Parser} from "./state" +import {types as tt} from "./tokentype" +import {lineBreak} from "./whitespace" + +export class TokContext { + constructor(token, isExpr, preserveSpace, override) { + this.token = token + this.isExpr = !!isExpr + this.preserveSpace = !!preserveSpace + this.override = override + } +} + +export const types = { + b_stat: new TokContext("{", false), + b_expr: new TokContext("{", true), + b_tmpl: new TokContext("${", true), + p_stat: new TokContext("(", false), + p_expr: new TokContext("(", true), + q_tmpl: new TokContext("`", true, true, p => p.readTmplToken()), + f_expr: new TokContext("function", true) +} + +const pp = Parser.prototype + +pp.initialContext = function() { + return [types.b_stat] +} + +pp.braceIsBlock = function(prevType) { + if (prevType === tt.colon) { + let parent = this.curContext() + if (parent === types.b_stat || parent === types.b_expr) + return !parent.isExpr + } + if (prevType === tt._return) + return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) + if (prevType === tt._else || prevType === tt.semi || prevType === tt.eof || prevType === tt.parenR) + return true + if (prevType == tt.braceL) + return this.curContext() === types.b_stat + return !this.exprAllowed +} + +pp.updateContext = function(prevType) { + let update, type = this.type + if (type.keyword && prevType == tt.dot) + this.exprAllowed = false + else if (update = type.updateContext) + update.call(this, prevType) + else + this.exprAllowed = type.beforeExpr +} + +// Token-specific context update code + +tt.parenR.updateContext = tt.braceR.updateContext = function() { + if (this.context.length == 1) { + this.exprAllowed = true + return + } + let out = this.context.pop() + if (out === types.b_stat && this.curContext() === types.f_expr) { + this.context.pop() + this.exprAllowed = false + } else if (out === types.b_tmpl) { + this.exprAllowed = true + } else { + this.exprAllowed = !out.isExpr + } +} + +tt.braceL.updateContext = function(prevType) { + this.context.push(this.braceIsBlock(prevType) ? types.b_stat : types.b_expr) + this.exprAllowed = true +} + +tt.dollarBraceL.updateContext = function() { + this.context.push(types.b_tmpl) + this.exprAllowed = true +} + +tt.parenL.updateContext = function(prevType) { + let statementParens = prevType === tt._if || prevType === tt._for || prevType === tt._with || prevType === tt._while + this.context.push(statementParens ? types.p_stat : types.p_expr) + this.exprAllowed = true +} + +tt.incDec.updateContext = function() { + // tokExprAllowed stays unchanged +} + +tt._function.updateContext = function() { + if (this.curContext() !== types.b_stat) + this.context.push(types.f_expr) + this.exprAllowed = false +} + +tt.backQuote.updateContext = function() { + if (this.curContext() === types.q_tmpl) + this.context.pop() + else + this.context.push(types.q_tmpl) + this.exprAllowed = false +} diff --git a/node_modules/acorn/src/tokenize.js b/node_modules/acorn/src/tokenize.js new file mode 100644 index 0000000..1b2bd95 --- /dev/null +++ b/node_modules/acorn/src/tokenize.js @@ -0,0 +1,682 @@ +import {isIdentifierStart, isIdentifierChar} from "./identifier" +import {types as tt, keywords as keywordTypes} from "./tokentype" +import {Parser} from "./state" +import {SourceLocation} from "./locutil" +import {lineBreak, lineBreakG, isNewLine, nonASCIIwhitespace} from "./whitespace" + +// Object type used to represent tokens. Note that normally, tokens +// simply exist as properties on the parser object. This is only +// used for the onToken callback and the external tokenizer. + +export class Token { + constructor(p) { + this.type = p.type + this.value = p.value + this.start = p.start + this.end = p.end + if (p.options.locations) + this.loc = new SourceLocation(p, p.startLoc, p.endLoc) + if (p.options.ranges) + this.range = [p.start, p.end] + } +} + +// ## Tokenizer + +const pp = Parser.prototype + +// Are we running under Rhino? +const isRhino = typeof Packages == "object" && Object.prototype.toString.call(Packages) == "[object JavaPackage]" + +// Move to the next token + +pp.next = function() { + if (this.options.onToken) + this.options.onToken(new Token(this)) + + this.lastTokEnd = this.end + this.lastTokStart = this.start + this.lastTokEndLoc = this.endLoc + this.lastTokStartLoc = this.startLoc + this.nextToken() +} + +pp.getToken = function() { + this.next() + return new Token(this) +} + +// If we're in an ES6 environment, make parsers iterable +if (typeof Symbol !== "undefined") + pp[Symbol.iterator] = function () { + let self = this + return {next: function () { + let token = self.getToken() + return { + done: token.type === tt.eof, + value: token + } + }} + } + +// Toggle strict mode. Re-reads the next number or string to please +// pedantic tests (`"use strict"; 010;` should fail). + +pp.setStrict = function(strict) { + this.strict = strict + if (this.type !== tt.num && this.type !== tt.string) return + this.pos = this.start + if (this.options.locations) { + while (this.pos < this.lineStart) { + this.lineStart = this.input.lastIndexOf("\n", this.lineStart - 2) + 1 + --this.curLine + } + } + this.nextToken() +} + +pp.curContext = function() { + return this.context[this.context.length - 1] +} + +// Read a single token, updating the parser object's token-related +// properties. + +pp.nextToken = function() { + let curContext = this.curContext() + if (!curContext || !curContext.preserveSpace) this.skipSpace() + + this.start = this.pos + if (this.options.locations) this.startLoc = this.curPosition() + if (this.pos >= this.input.length) return this.finishToken(tt.eof) + + if (curContext.override) return curContext.override(this) + else this.readToken(this.fullCharCodeAtPos()) +} + +pp.readToken = function(code) { + // Identifier or keyword. '\uXXXX' sequences are allowed in + // identifiers, so '\' also dispatches to that. + if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */) + return this.readWord() + + return this.getTokenFromCode(code) +} + +pp.fullCharCodeAtPos = function() { + let code = this.input.charCodeAt(this.pos) + if (code <= 0xd7ff || code >= 0xe000) return code + let next = this.input.charCodeAt(this.pos + 1) + return (code << 10) + next - 0x35fdc00 +} + +pp.skipBlockComment = function() { + let startLoc = this.options.onComment && this.curPosition() + let start = this.pos, end = this.input.indexOf("*/", this.pos += 2) + if (end === -1) this.raise(this.pos - 2, "Unterminated comment") + this.pos = end + 2 + if (this.options.locations) { + lineBreakG.lastIndex = start + let match + while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) { + ++this.curLine + this.lineStart = match.index + match[0].length + } + } + if (this.options.onComment) + this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos, + startLoc, this.curPosition()) +} + +pp.skipLineComment = function(startSkip) { + let start = this.pos + let startLoc = this.options.onComment && this.curPosition() + let ch = this.input.charCodeAt(this.pos+=startSkip) + while (this.pos < this.input.length && ch !== 10 && ch !== 13 && ch !== 8232 && ch !== 8233) { + ++this.pos + ch = this.input.charCodeAt(this.pos) + } + if (this.options.onComment) + this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, + startLoc, this.curPosition()) +} + +// Called at the start of the parse and after every token. Skips +// whitespace and comments, and. + +pp.skipSpace = function() { + loop: while (this.pos < this.input.length) { + let ch = this.input.charCodeAt(this.pos) + switch (ch) { + case 32: case 160: // ' ' + ++this.pos + break + case 13: + if (this.input.charCodeAt(this.pos + 1) === 10) { + ++this.pos + } + case 10: case 8232: case 8233: + ++this.pos + if (this.options.locations) { + ++this.curLine + this.lineStart = this.pos + } + break + case 47: // '/' + switch (this.input.charCodeAt(this.pos + 1)) { + case 42: // '*' + this.skipBlockComment() + break + case 47: + this.skipLineComment(2) + break + default: + break loop + } + break + default: + if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { + ++this.pos + } else { + break loop + } + } + } +} + +// Called at the end of every token. Sets `end`, `val`, and +// maintains `context` and `exprAllowed`, and skips the space after +// the token, so that the next one's `start` will point at the +// right position. + +pp.finishToken = function(type, val) { + this.end = this.pos + if (this.options.locations) this.endLoc = this.curPosition() + let prevType = this.type + this.type = type + this.value = val + + this.updateContext(prevType) +} + +// ### Token reading + +// This is the function that is called to fetch the next token. It +// is somewhat obscure, because it works in character codes rather +// than characters, and because operator parsing has been inlined +// into it. +// +// All in the name of speed. +// +pp.readToken_dot = function() { + let next = this.input.charCodeAt(this.pos + 1) + if (next >= 48 && next <= 57) return this.readNumber(true) + let next2 = this.input.charCodeAt(this.pos + 2) + if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.' + this.pos += 3 + return this.finishToken(tt.ellipsis) + } else { + ++this.pos + return this.finishToken(tt.dot) + } +} + +pp.readToken_slash = function() { // '/' + let next = this.input.charCodeAt(this.pos + 1) + if (this.exprAllowed) {++this.pos; return this.readRegexp();} + if (next === 61) return this.finishOp(tt.assign, 2) + return this.finishOp(tt.slash, 1) +} + +pp.readToken_mult_modulo = function(code) { // '%*' + let next = this.input.charCodeAt(this.pos + 1) + if (next === 61) return this.finishOp(tt.assign, 2) + return this.finishOp(code === 42 ? tt.star : tt.modulo, 1) +} + +pp.readToken_pipe_amp = function(code) { // '|&' + let next = this.input.charCodeAt(this.pos + 1) + if (next === code) return this.finishOp(code === 124 ? tt.logicalOR : tt.logicalAND, 2) + if (next === 61) return this.finishOp(tt.assign, 2) + return this.finishOp(code === 124 ? tt.bitwiseOR : tt.bitwiseAND, 1) +} + +pp.readToken_caret = function() { // '^' + let next = this.input.charCodeAt(this.pos + 1) + if (next === 61) return this.finishOp(tt.assign, 2) + return this.finishOp(tt.bitwiseXOR, 1) +} + +pp.readToken_plus_min = function(code) { // '+-' + let next = this.input.charCodeAt(this.pos + 1) + if (next === code) { + if (next == 45 && this.input.charCodeAt(this.pos + 2) == 62 && + lineBreak.test(this.input.slice(this.lastTokEnd, this.pos))) { + // A `-->` line comment + this.skipLineComment(3) + this.skipSpace() + return this.nextToken() + } + return this.finishOp(tt.incDec, 2) + } + if (next === 61) return this.finishOp(tt.assign, 2) + return this.finishOp(tt.plusMin, 1) +} + +pp.readToken_lt_gt = function(code) { // '<>' + let next = this.input.charCodeAt(this.pos + 1) + let size = 1 + if (next === code) { + size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2 + if (this.input.charCodeAt(this.pos + size) === 61) return this.finishOp(tt.assign, size + 1) + return this.finishOp(tt.bitShift, size) + } + if (next == 33 && code == 60 && this.input.charCodeAt(this.pos + 2) == 45 && + this.input.charCodeAt(this.pos + 3) == 45) { + if (this.inModule) this.unexpected() + // ` +

foo

+

bar

+``` + +Jade 同样支持不输出的注释,加一个短横线就行了: + +```jade +//- will not output within markup +p foo +p bar +``` + +渲染为: + +```html +

foo

+

bar

+``` + + +### 块注释 + +块注释也是支持的: + +```jade +body + // + #content + h1 Example +``` + +渲染为: + +```html + + + +``` + +Jade 同样很好的支持了条件注释: + +```jade +body + //if IE + a(href='http://www.mozilla.com/en-US/firefox/') Get Firefox +``` + +渲染为: + +```html + + + +``` + + +### 内联 + +Jade 支持以自然的方式定义标签嵌套: + +```jade +ul + li.first + a(href='#') foo + li + a(href='#') bar + li.last + a(href='#') baz +``` + + +### 块展开 + +块展开可以帮助你在一行内创建嵌套的标签,下面的例子和上面的是一样的: + +```jade +ul + li.first: a(href='#') foo + li: a(href='#') bar + li.last: a(href='#') baz +``` + + +### Case + +`case` 表达式按下面这样的形式写: + +```jade +html + body + friends = 10 + case friends + when 0 + p you have no friends + when 1 + p you have a friend + default + p you have #{friends} friends +``` + +块展开在这里也可以使用: + +```jade +friends = 5 + +html + body + case friends + when 0: p you have no friends + when 1: p you have a friend + default: p you have #{friends} friends +``` + + +### 属性 + +Jade 现在支持使用 `(` 和 `)` 作为属性分隔符 + +```jade +a(href='/login', title='View login page') Login +``` + +当一个值是 `undefined` 或者 `null` 属性 _不_ 会被加上, +所以呢,它不会编译出 'something="null"'. + +```jade +div(something=null) +``` + +Boolean 属性也是支持的: + +```jade +input(type="checkbox", checked) +``` + +使用代码的 Boolean 属性只有当属性为 `true` 时才会输出: + +```jade +input(type="checkbox", checked=someValue) +``` + +多行同样也是可用的: + +```jade +input(type='checkbox', + name='agreement', + checked) +``` + +多行的时候可以不加逗号: + +```jade +input(type='checkbox' + name='agreement' + checked) +``` + +加点空格,格式好看一点?同样支持 + +```jade +input( + type='checkbox' + name='agreement' + checked) +``` + +冒号也是支持的: + +```jade +rss(xmlns:atom="atom") +``` + +假如我有一个 `user` 对象 `{ id: 12, name: 'tobi' }` +我们希望创建一个指向 `/user/12` 的链接 `href`, 我们可以使用普通的 JavaScript 字符串连接,如下: + +```jade +a(href='/user/' + user.id)= user.name +``` + +或者我们使用 Jade 的修改方式, 这个我想很多使用 Ruby 或者 CoffeeScript 的人会看起来像普通的 JS..: + +```jade +a(href='/user/#{user.id}')= user.name +``` + +`class` 属性是一个特殊的属性,你可以直接传递一个数组,比如 `bodyClasses = ['user', 'authenticated']` : + +```jade +body(class=bodyClasses) +``` + + +### HTML + +内联的 HTML 是可以的,我们可以使用管道定义一段文本 : + +```jade +html + body + |

Title

+ |

foo bar baz

+``` + +或者我们可以使用 `.` 来告诉 Jade 我们需要一段文本: + +```jade +html + body. +

Title

+

foo bar baz

+``` + +上面的两个例子都会渲染成相同的结果: + +```jade +

Title

+

foo bar baz

+ +``` + + 这条规则适应于在 Jade 里的任何文本: + +``` +html + body + h1 User #{name} +``` + +
+### Doctypes + +添加文档类型只需要简单的使用 `!!!`, 或者 `doctype` 跟上下面的可选项: + +```jade +!!! +``` + +会渲染出 _transitional_ 文档类型, 或者: + +```jade +!!! 5 +``` + +或 + +```jade +!!! html +``` + +或 + +```jade +doctype html +``` + +Doctype 是大小写不敏感的, 所以下面两个是一样的: + +```jade +doctype Basic +doctype basic +``` + +当然也是可以直接传递一段文档类型的文本: + +```jade +doctype html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" +``` + +渲染后: + +```html + +``` + +会输出 _HTML5_ 文档类型. 下面的默认的文档类型,可以很简单的扩展: + +```javascript +var doctypes = exports.doctypes = { + '5': '', + 'xml': '', + 'default': '', + 'transitional': '', + 'strict': '', + 'frameset': '', + '1.1': '', + 'basic': '', + 'mobile': '' +}; +``` + +通过下面的代码可以很简单的改变默认的文档类型: + +```javascript + jade.doctypes.default = 'whatever you want'; +``` + + +## 过滤器 + +过滤器前缀 `:`, 比如 `:markdown` 会把下面块里的文本交给专门的函数进行处理。查看顶部 _特性_ 里有哪些可用的过滤器。 + +```jade +body + :markdown + Woah! jade _and_ markdown, very **cool** + we can even link to [stuff](http://google.com) +``` + +渲染为: + +```html +

Woah! jade and markdown, very cool we can even link to stuff

+``` + + +## 代码 + +Jade 目前支持三种类型的可执行代码。第一种是前缀 `-`, 这是不会被输出的: + +```jade +- var foo = 'bar'; +``` + +这可以用在条件语句或者循环中: + +```jade +- for (var key in obj) + p= obj[key] +``` + +由于 Jade 的缓存技术,下面的代码也是可以的: + +```jade +- if (foo) + ul + li yay + li foo + li worked +- else + p oh no! didnt work +``` + +哈哈,甚至是很长的循环也是可以的: + + - if (items.length) + ul + - items.forEach(function(item){ + li= item + - }) + +所以你想要的! + +下一步我们要 _转义_ 输出的代码,比如我们返回一个值,只要前缀一个 `=`: + +```jade +- var foo = 'bar' += foo +h1= foo +``` + +它会渲染为 `bar

bar

`. 为了安全起见,使用 `=` 输出的代码默认是转义的,如果想直接输出不转义的值可以使用 `!=`: + +```jade +p!= aVarContainingMoreHTML +``` + +Jade 同样是设计师友好的,它可以使 JavaScript 更直接更富表现力。比如下面的赋值语句是相等的,同时表达式还是通常的 JavaScript: + +```jade +- var foo = 'foo ' + 'bar' +foo = 'foo ' + 'bar' +``` + +Jade 会把 `if`, `else if`, `else`, `until`, `while`, `unless` 同别的优先对待, 但是你得记住它们还是普通的 JavaScript: + +```jade +if foo == 'bar' + ul + li yay + li foo + li worked +else + p oh no! didnt work +``` + +
+## 循环 + +尽管已经支持 JavaScript 原生代码,Jade 还是支持了一些特殊的标签,它们可以让模板更加易于理解,其中之一就是 `each`, 这种形式: + +```jade +each VAL[, KEY] in OBJ +``` + +一个遍历数组的例子 : + +```jade +- var items = ["one", "two", "three"] +each item in items + li= item +``` + +渲染为: + +```html +
  • one
  • +
  • two
  • +
  • three
  • +``` + +遍历一个数组同时带上索引: + +```jade +items = ["one", "two", "three"] +each item, i in items + li #{item}: #{i} +``` + +渲染为: + +```html +
  • one: 0
  • +
  • two: 1
  • +
  • three: 2
  • +``` + +遍历一个数组的键值: + +```jade +obj = { foo: 'bar' } +each val, key in obj + li #{key}: #{val} +``` + +将会渲染为:`
  • foo: bar
  • ` + +Jade 在内部会把这些语句转换成原生的 JavaScript 语句,就像使用 `users.forEach(function(user){`, 词法作用域和嵌套会像在普通的 JavaScript 中一样: + +```jade +each user in users + each role in user.roles + li= role +``` + +如果你喜欢,也可以使用 `for` : + +```jade +for user in users + for role in user.roles + li= role +``` + +
    +## 条件语句 + +Jade 条件语句和使用了(`-`) 前缀的 JavaScript 语句是一致的,然后它允许你不使用圆括号,这样会看上去对设计师更友好一点, +同时要在心里记住这个表达式渲染出的是 _常规_ JavaScript: + +```jade +for user in users + if user.role == 'admin' + p #{user.name} is an admin + else + p= user.name +``` + +和下面的使用了常规 JavaScript 的代码是相等的: + +```jade +for user in users + - if (user.role == 'admin') + p #{user.name} is an admin + - else + p= user.name +``` + +Jade 同时支持 `unless`, 这和 `if (!(expr))` 是等价的: + +```jade +for user in users + unless user.isAnonymous + p + | Click to view + a(href='/users/' + user.id)= user.name +``` + + +## 模板继承 + +Jade 支持通过 `block` 和 `extends` 关键字来实现模板继承。 一个块就是一个 Jade 的 block ,它将在子模板中实现,同时是支持递归的。 + +Jade 块如果没有内容,Jade 会添加默认内容,下面的代码默认会输出 `block scripts`, `block content`, 和 `block foot`. + +```jade +html + head + h1 My Site - #{title} + block scripts + script(src='/jquery.js') + body + block content + block foot + #footer + p some footer content +``` + +现在我们来继承这个布局,简单创建一个新文件,像下面那样直接使用 `extends`,给定路径(可以选择带 `.jade` 扩展名或者不带). 你可以定义一个或者更多的块来覆盖父级块内容, 注意到这里的 `foot` 块 _没有_ 定义,所以它还会输出父级的 "some footer content"。 + +```jade +extends extend-layout + +block scripts + script(src='/jquery.js') + script(src='/pets.js') + +block content + h1= title + each pet in pets + include pet +``` + +同样可以在一个子块里添加块,就像下面实现的块 `content` 里又定义了两个可以被实现的块 `sidebar` 和 `primary`,或者子模板直接实现 `content`。 + +```jade +extends regular-layout + +block content + .sidebar + block sidebar + p nothing + .primary + block primary + p nothing +``` + + + +## 前置、追加代码块 + +Jade允许你 _替换_ (默认)、 _前置_ 和 _追加_ blocks. 比如,假设你希望在 _所有_ 页面的头部都加上默认的脚本,你可以这么做: + + +```jade +html + head + block head + script(src='/vendor/jquery.js') + script(src='/vendor/caustic.js') + body + block content +``` + +现在假设你有一个Javascript游戏的页面,你希望在默认的脚本之外添加一些游戏相关的脚本,你可以直接`append`上代码块: + + +```jade +extends layout + +block append head + script(src='/vendor/three.js') + script(src='/game.js') +``` + +使用 `block append` 或 `block prepend` 时 `block` 是可选的: + +```jade +extends layout + +append head + script(src='/vendor/three.js') + script(src='/game.js') +``` + + +## 包含 + +Includes 允许你静态包含一段 Jade, 或者别的存放在单个文件中的东西比如 CSS, HTML 非常常见的例子是包含头部和页脚。 假设我们有一个下面目录结构的文件夹: + +``` +./layout.jade +./includes/ + ./head.jade + ./tail.jade +``` + +下面是 `layout.jade` 的内容: + +```jade +html + include includes/head + body + h1 My Site + p Welcome to my super amazing site. + include includes/foot +``` + +这两个包含 `includes/head` 和 `includes/foot` 都会读取相对于给 `layout.jade` 参数`filename` 的路径的文件, 这是一个绝对路径,不用担心Express帮你搞定这些了。Include 会解析这些文件,并且插入到已经生成的语法树中,然后渲染为你期待的内容: + +```html + + + My Site + + + +

    My Site

    +

    Welcome to my super lame site.

    + + + +``` + +前面已经提到,`include` 可以包含比如 HTML 或者 CSS 这样的内容。给定一个扩展名后,Jade 不会把这个文件当作一个 Jade 源代码,并且会把它当作一个普通文本包含进来: + +``` +html + head + //- css and js have simple filters that wrap them in +