From f9c9c66d988e49eb8b9aaf1b5c36eb82b3d02939 Mon Sep 17 00:00:00 2001 From: ren4t Date: Mon, 10 Oct 2022 13:44:24 +0300 Subject: [PATCH 1/2] homework7 --- homework7/project_express/.idea/.gitignore | 8 + .../.idea/jsLibraryMappings.xml | 6 + homework7/project_express/.idea/misc.xml | 6 + homework7/project_express/.idea/modules.xml | 8 + .../project_express/.idea/project_express.iml | 12 + .../project_express/node_modules/.bin/mime | 15 + .../node_modules/.bin/mime.cmd | 17 + .../node_modules/.bin/mime.ps1 | 18 + .../project_express/node_modules/.bin/nodemon | 12 + .../node_modules/.bin/nodemon.cmd | 17 + .../node_modules/.bin/nodemon.ps1 | 28 + .../node_modules/.bin/nodetouch | 12 + .../node_modules/.bin/nodetouch.cmd | 17 + .../node_modules/.bin/nodetouch.ps1 | 28 + .../project_express/node_modules/.bin/nopt | 12 + .../node_modules/.bin/nopt.cmd | 17 + .../node_modules/.bin/nopt.ps1 | 28 + .../project_express/node_modules/.bin/require | 12 + .../node_modules/.bin/require.cmd | 17 + .../node_modules/.bin/require.ps1 | 28 + .../project_express/node_modules/.bin/semver | 12 + .../node_modules/.bin/semver.cmd | 17 + .../node_modules/.bin/semver.ps1 | 28 + .../node_modules/.bin/uglifyjs | 12 + .../node_modules/.bin/uglifyjs.cmd | 17 + .../node_modules/.bin/uglifyjs.ps1 | 28 + .../node_modules/.package-lock.json | 882 ++ .../node_modules/abbrev/LICENSE | 46 + .../node_modules/abbrev/README.md | 23 + .../node_modules/abbrev/abbrev.js | 61 + .../node_modules/abbrev/package.json | 21 + .../node_modules/accepts/HISTORY.md | 236 + .../node_modules/accepts/LICENSE | 23 + .../node_modules/accepts/README.md | 142 + .../node_modules/accepts/index.js | 238 + .../node_modules/accepts/package.json | 86 + .../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/anymatch/LICENSE | 15 + .../node_modules/anymatch/README.md | 87 + .../node_modules/anymatch/index.d.ts | 19 + .../node_modules/anymatch/index.js | 104 + .../node_modules/anymatch/package.json | 48 + .../node_modules/array-flatten/LICENSE | 21 + .../node_modules/array-flatten/README.md | 43 + .../array-flatten/array-flatten.js | 64 + .../node_modules/array-flatten/package.json | 64 + .../node_modules/async/LICENSE | 19 + .../node_modules/async/README.md | 1425 +++ .../node_modules/async/component.json | 11 + .../node_modules/async/lib/async.js | 958 ++ .../node_modules/async/package.json | 36 + .../balanced-match/.github/FUNDING.yml | 2 + .../node_modules/balanced-match/LICENSE.md | 21 + .../node_modules/balanced-match/README.md | 97 + .../node_modules/balanced-match/index.js | 62 + .../node_modules/balanced-match/package.json | 48 + .../binary-extensions/binary-extensions.json | 260 + .../binary-extensions.json.d.ts | 3 + .../node_modules/binary-extensions/index.d.ts | 14 + .../node_modules/binary-extensions/index.js | 1 + .../node_modules/binary-extensions/license | 9 + .../binary-extensions/package.json | 38 + .../node_modules/binary-extensions/readme.md | 41 + .../node_modules/body-parser/HISTORY.md | 609 ++ .../node_modules/body-parser/LICENSE | 23 + .../node_modules/body-parser/README.md | 443 + .../node_modules/body-parser/index.js | 157 + .../node_modules/body-parser/lib/read.js | 181 + .../body-parser/lib/types/json.js | 230 + .../node_modules/body-parser/lib/types/raw.js | 101 + .../body-parser/lib/types/text.js | 121 + .../body-parser/lib/types/urlencoded.js | 284 + .../node_modules/body-parser/package.json | 91 + .../node_modules/brace-expansion/LICENSE | 21 + .../node_modules/brace-expansion/README.md | 129 + .../node_modules/brace-expansion/index.js | 201 + .../node_modules/brace-expansion/package.json | 47 + .../node_modules/braces/CHANGELOG.md | 184 + .../node_modules/braces/LICENSE | 21 + .../node_modules/braces/README.md | 593 ++ .../node_modules/braces/index.js | 170 + .../node_modules/braces/lib/compile.js | 57 + .../node_modules/braces/lib/constants.js | 57 + .../node_modules/braces/lib/expand.js | 113 + .../node_modules/braces/lib/parse.js | 333 + .../node_modules/braces/lib/stringify.js | 32 + .../node_modules/braces/lib/utils.js | 112 + .../node_modules/braces/package.json | 77 + .../node_modules/bytes/History.md | 87 + .../node_modules/bytes/LICENSE | 23 + .../node_modules/bytes/Readme.md | 126 + .../node_modules/bytes/index.js | 162 + .../node_modules/bytes/package.json | 84 + .../node_modules/chokidar/LICENSE | 21 + .../node_modules/chokidar/README.md | 308 + .../node_modules/chokidar/index.js | 973 ++ .../node_modules/chokidar/lib/constants.js | 65 + .../chokidar/lib/fsevents-handler.js | 524 ++ .../chokidar/lib/nodefs-handler.js | 654 ++ .../node_modules/chokidar/package.json | 85 + .../node_modules/chokidar/types/index.d.ts | 188 + .../node_modules/concat-map/.travis.yml | 4 + .../node_modules/concat-map/LICENSE | 18 + .../node_modules/concat-map/README.markdown | 62 + .../node_modules/concat-map/example/map.js | 6 + .../node_modules/concat-map/index.js | 13 + .../node_modules/concat-map/package.json | 43 + .../node_modules/concat-map/test/map.js | 39 + .../content-disposition/HISTORY.md | 55 + .../node_modules/content-disposition/LICENSE | 22 + .../content-disposition/README.md | 148 + .../node_modules/content-disposition/index.js | 458 + .../content-disposition/package.json | 79 + .../node_modules/content-type/HISTORY.md | 24 + .../node_modules/content-type/LICENSE | 22 + .../node_modules/content-type/README.md | 92 + .../node_modules/content-type/index.js | 222 + .../node_modules/content-type/package.json | 76 + .../node_modules/cookie-signature/.npmignore | 4 + .../node_modules/cookie-signature/History.md | 38 + .../node_modules/cookie-signature/Readme.md | 42 + .../node_modules/cookie-signature/index.js | 51 + .../cookie-signature/package.json | 57 + .../node_modules/cookie/HISTORY.md | 123 + .../node_modules/cookie/LICENSE | 24 + .../node_modules/cookie/README.md | 253 + .../node_modules/cookie/index.js | 198 + .../node_modules/cookie/package.json | 78 + .../node_modules/debug/.coveralls.yml | 1 + .../node_modules/debug/.eslintrc | 11 + .../node_modules/debug/.npmignore | 9 + .../node_modules/debug/.travis.yml | 14 + .../node_modules/debug/CHANGELOG.md | 362 + .../node_modules/debug/LICENSE | 19 + .../node_modules/debug/Makefile | 50 + .../node_modules/debug/README.md | 312 + .../node_modules/debug/component.json | 19 + .../node_modules/debug/karma.conf.js | 70 + .../node_modules/debug/node.js | 1 + .../node_modules/debug/package.json | 91 + .../node_modules/debug/src/browser.js | 185 + .../node_modules/debug/src/debug.js | 202 + .../node_modules/debug/src/index.js | 10 + .../node_modules/debug/src/inspector-log.js | 15 + .../node_modules/debug/src/node.js | 248 + .../node_modules/depd/History.md | 96 + .../project_express/node_modules/depd/LICENSE | 22 + .../node_modules/depd/Readme.md | 280 + .../node_modules/depd/index.js | 522 ++ .../node_modules/depd/lib/browser/index.js | 77 + .../depd/lib/compat/callsite-tostring.js | 103 + .../depd/lib/compat/event-listener-count.js | 22 + .../node_modules/depd/lib/compat/index.js | 79 + .../node_modules/depd/package.json | 79 + .../node_modules/destroy/LICENSE | 22 + .../node_modules/destroy/README.md | 60 + .../node_modules/destroy/index.js | 75 + .../node_modules/destroy/package.json | 71 + .../node_modules/ee-first/LICENSE | 22 + .../node_modules/ee-first/README.md | 80 + .../node_modules/ee-first/index.js | 95 + .../node_modules/ee-first/package.json | 63 + .../node_modules/encodeurl/HISTORY.md | 14 + .../node_modules/encodeurl/LICENSE | 22 + .../node_modules/encodeurl/README.md | 128 + .../node_modules/encodeurl/index.js | 60 + .../node_modules/encodeurl/package.json | 78 + .../node_modules/escape-html/LICENSE | 24 + .../node_modules/escape-html/Readme.md | 43 + .../node_modules/escape-html/index.js | 78 + .../node_modules/escape-html/package.json | 59 + .../node_modules/etag/HISTORY.md | 83 + .../project_express/node_modules/etag/LICENSE | 22 + .../node_modules/etag/README.md | 159 + .../node_modules/etag/index.js | 131 + .../node_modules/etag/package.json | 86 + .../node_modules/express/History.md | 3477 +++++++ .../node_modules/express/LICENSE | 24 + .../node_modules/express/Readme.md | 155 + .../node_modules/express/index.js | 11 + .../node_modules/express/lib/application.js | 644 ++ .../node_modules/express/lib/express.js | 116 + .../express/lib/middleware/init.js | 43 + .../express/lib/middleware/query.js | 47 + .../node_modules/express/lib/request.js | 525 ++ .../node_modules/express/lib/response.js | 1142 +++ .../node_modules/express/lib/router/index.js | 662 ++ .../node_modules/express/lib/router/layer.js | 181 + .../node_modules/express/lib/router/route.js | 216 + .../node_modules/express/lib/utils.js | 306 + .../node_modules/express/lib/view.js | 182 + .../node_modules/express/package.json | 154 + .../node_modules/fill-range/LICENSE | 21 + .../node_modules/fill-range/README.md | 237 + .../node_modules/fill-range/index.js | 249 + .../node_modules/fill-range/package.json | 69 + .../node_modules/finalhandler/HISTORY.md | 187 + .../node_modules/finalhandler/LICENSE | 22 + .../node_modules/finalhandler/README.md | 148 + .../node_modules/finalhandler/index.js | 331 + .../node_modules/finalhandler/package.json | 80 + .../node_modules/forwarded/HISTORY.md | 16 + .../node_modules/forwarded/LICENSE | 22 + .../node_modules/forwarded/README.md | 57 + .../node_modules/forwarded/index.js | 76 + .../node_modules/forwarded/package.json | 78 + .../node_modules/fresh/HISTORY.md | 70 + .../node_modules/fresh/LICENSE | 23 + .../node_modules/fresh/README.md | 119 + .../node_modules/fresh/index.js | 137 + .../node_modules/fresh/package.json | 90 + .../node_modules/glob-parent/CHANGELOG.md | 110 + .../node_modules/glob-parent/LICENSE | 15 + .../node_modules/glob-parent/README.md | 137 + .../node_modules/glob-parent/index.js | 42 + .../node_modules/glob-parent/package.json | 48 + .../node_modules/has-flag/index.js | 8 + .../node_modules/has-flag/license | 9 + .../node_modules/has-flag/package.json | 44 + .../node_modules/has-flag/readme.md | 70 + .../node_modules/http-errors/HISTORY.md | 149 + .../node_modules/http-errors/LICENSE | 23 + .../node_modules/http-errors/README.md | 163 + .../node_modules/http-errors/index.js | 266 + .../node_modules/http-errors/package.json | 93 + .../node_modules/iconv-lite/Changelog.md | 162 + .../node_modules/iconv-lite/LICENSE | 21 + .../node_modules/iconv-lite/README.md | 156 + .../iconv-lite/encodings/dbcs-codec.js | 555 ++ .../iconv-lite/encodings/dbcs-data.js | 176 + .../iconv-lite/encodings/index.js | 22 + .../iconv-lite/encodings/internal.js | 188 + .../iconv-lite/encodings/sbcs-codec.js | 72 + .../encodings/sbcs-data-generated.js | 451 + .../iconv-lite/encodings/sbcs-data.js | 174 + .../encodings/tables/big5-added.json | 122 + .../iconv-lite/encodings/tables/cp936.json | 264 + .../iconv-lite/encodings/tables/cp949.json | 273 + .../iconv-lite/encodings/tables/cp950.json | 177 + .../iconv-lite/encodings/tables/eucjp.json | 182 + .../encodings/tables/gb18030-ranges.json | 1 + .../encodings/tables/gbk-added.json | 55 + .../iconv-lite/encodings/tables/shiftjis.json | 125 + .../iconv-lite/encodings/utf16.js | 177 + .../node_modules/iconv-lite/encodings/utf7.js | 290 + .../iconv-lite/lib/bom-handling.js | 52 + .../iconv-lite/lib/extend-node.js | 217 + .../node_modules/iconv-lite/lib/index.d.ts | 24 + .../node_modules/iconv-lite/lib/index.js | 153 + .../node_modules/iconv-lite/lib/streams.js | 121 + .../node_modules/iconv-lite/package.json | 77 + .../node_modules/ignore-by-default/LICENSE | 14 + .../node_modules/ignore-by-default/README.md | 26 + .../node_modules/ignore-by-default/index.js | 12 + .../ignore-by-default/package.json | 34 + .../node_modules/inherits/LICENSE | 16 + .../node_modules/inherits/README.md | 42 + .../node_modules/inherits/inherits.js | 7 + .../node_modules/inherits/inherits_browser.js | 23 + .../node_modules/inherits/package.json | 61 + .../node_modules/ipaddr.js/LICENSE | 19 + .../node_modules/ipaddr.js/README.md | 233 + .../node_modules/ipaddr.js/ipaddr.min.js | 1 + .../node_modules/ipaddr.js/lib/ipaddr.js | 673 ++ .../node_modules/ipaddr.js/lib/ipaddr.js.d.ts | 68 + .../node_modules/ipaddr.js/package.json | 70 + .../node_modules/is-binary-path/index.d.ts | 17 + .../node_modules/is-binary-path/index.js | 7 + .../node_modules/is-binary-path/license | 9 + .../node_modules/is-binary-path/package.json | 40 + .../node_modules/is-binary-path/readme.md | 34 + .../node_modules/is-extglob/LICENSE | 21 + .../node_modules/is-extglob/README.md | 107 + .../node_modules/is-extglob/index.js | 20 + .../node_modules/is-extglob/package.json | 69 + .../node_modules/is-glob/LICENSE | 21 + .../node_modules/is-glob/README.md | 206 + .../node_modules/is-glob/index.js | 150 + .../node_modules/is-glob/package.json | 81 + .../node_modules/is-number/LICENSE | 21 + .../node_modules/is-number/README.md | 187 + .../node_modules/is-number/index.js | 18 + .../node_modules/is-number/package.json | 82 + .../node_modules/media-typer/HISTORY.md | 22 + .../node_modules/media-typer/LICENSE | 22 + .../node_modules/media-typer/README.md | 81 + .../node_modules/media-typer/index.js | 270 + .../node_modules/media-typer/package.json | 61 + .../node_modules/merge-descriptors/HISTORY.md | 21 + .../node_modules/merge-descriptors/LICENSE | 23 + .../node_modules/merge-descriptors/README.md | 48 + .../node_modules/merge-descriptors/index.js | 60 + .../merge-descriptors/package.json | 69 + .../node_modules/methods/HISTORY.md | 29 + .../node_modules/methods/LICENSE | 24 + .../node_modules/methods/README.md | 51 + .../node_modules/methods/index.js | 69 + .../node_modules/methods/package.json | 79 + .../node_modules/mime-db/HISTORY.md | 446 + .../node_modules/mime-db/LICENSE | 22 + .../node_modules/mime-db/README.md | 102 + .../node_modules/mime-db/db.json | 8176 +++++++++++++++++ .../node_modules/mime-db/index.js | 11 + .../node_modules/mime-db/package.json | 102 + .../node_modules/mime-types/HISTORY.md | 333 + .../node_modules/mime-types/LICENSE | 23 + .../node_modules/mime-types/README.md | 123 + .../node_modules/mime-types/index.js | 188 + .../node_modules/mime-types/package.json | 88 + .../node_modules/mime/.npmignore | 0 .../node_modules/mime/CHANGELOG.md | 164 + .../project_express/node_modules/mime/LICENSE | 21 + .../node_modules/mime/README.md | 90 + .../project_express/node_modules/mime/cli.js | 8 + .../project_express/node_modules/mime/mime.js | 108 + .../node_modules/mime/package.json | 73 + .../node_modules/mime/src/build.js | 53 + .../node_modules/mime/src/test.js | 60 + .../node_modules/mime/types.json | 1 + .../node_modules/minimatch/LICENSE | 15 + .../node_modules/minimatch/README.md | 230 + .../node_modules/minimatch/minimatch.js | 947 ++ .../node_modules/minimatch/package.json | 33 + .../project_express/node_modules/ms/index.js | 152 + .../node_modules/ms/license.md | 21 + .../node_modules/ms/package.json | 69 + .../project_express/node_modules/ms/readme.md | 51 + .../node_modules/negotiator/HISTORY.md | 103 + .../node_modules/negotiator/LICENSE | 24 + .../node_modules/negotiator/README.md | 203 + .../node_modules/negotiator/index.js | 124 + .../node_modules/negotiator/lib/charset.js | 169 + .../node_modules/negotiator/lib/encoding.js | 184 + .../node_modules/negotiator/lib/language.js | 179 + .../node_modules/negotiator/lib/mediaType.js | 294 + .../node_modules/negotiator/package.json | 84 + .../node_modules/nodemon/LICENSE | 21 + .../node_modules/nodemon/README.md | 423 + .../node_modules/nodemon/bin/nodemon.js | 16 + .../node_modules/nodemon/bin/windows-kill.exe | Bin 0 -> 80384 bytes .../node_modules/nodemon/doc/cli/authors.txt | 8 + .../node_modules/nodemon/doc/cli/config.txt | 44 + .../node_modules/nodemon/doc/cli/help.txt | 29 + .../node_modules/nodemon/doc/cli/logo.txt | 20 + .../node_modules/nodemon/doc/cli/options.txt | 36 + .../node_modules/nodemon/doc/cli/topics.txt | 8 + .../node_modules/nodemon/doc/cli/usage.txt | 3 + .../node_modules/nodemon/doc/cli/whoami.txt | 9 + .../node_modules/nodemon/lib/cli/index.js | 49 + .../node_modules/nodemon/lib/cli/parse.js | 230 + .../nodemon/lib/config/command.js | 43 + .../nodemon/lib/config/defaults.js | 28 + .../node_modules/nodemon/lib/config/exec.js | 225 + .../node_modules/nodemon/lib/config/index.js | 93 + .../node_modules/nodemon/lib/config/load.js | 256 + .../node_modules/nodemon/lib/help/index.js | 27 + .../node_modules/nodemon/lib/index.js | 1 + .../node_modules/nodemon/lib/monitor/index.js | 4 + .../node_modules/nodemon/lib/monitor/match.js | 276 + .../node_modules/nodemon/lib/monitor/run.js | 541 ++ .../nodemon/lib/monitor/signals.js | 34 + .../node_modules/nodemon/lib/monitor/watch.js | 239 + .../node_modules/nodemon/lib/nodemon.js | 311 + .../node_modules/nodemon/lib/rules/add.js | 89 + .../node_modules/nodemon/lib/rules/index.js | 53 + .../node_modules/nodemon/lib/rules/parse.js | 43 + .../node_modules/nodemon/lib/spawn.js | 73 + .../node_modules/nodemon/lib/utils/bus.js | 44 + .../node_modules/nodemon/lib/utils/clone.js | 40 + .../node_modules/nodemon/lib/utils/colour.js | 26 + .../node_modules/nodemon/lib/utils/index.js | 102 + .../node_modules/nodemon/lib/utils/log.js | 82 + .../node_modules/nodemon/lib/utils/merge.js | 47 + .../node_modules/nodemon/lib/version.js | 100 + .../nodemon/node_modules/debug/CHANGELOG.md | 395 + .../nodemon/node_modules/debug/LICENSE | 19 + .../nodemon/node_modules/debug/README.md | 437 + .../nodemon/node_modules/debug/node.js | 1 + .../nodemon/node_modules/debug/package.json | 51 + .../nodemon/node_modules/debug/src/browser.js | 180 + .../nodemon/node_modules/debug/src/common.js | 249 + .../nodemon/node_modules/debug/src/index.js | 12 + .../nodemon/node_modules/debug/src/node.js | 177 + .../nodemon/node_modules/ms/index.js | 162 + .../nodemon/node_modules/ms/license.md | 21 + .../nodemon/node_modules/ms/package.json | 38 + .../nodemon/node_modules/ms/readme.md | 59 + .../node_modules/nodemon/package.json | 74 + .../node_modules/nopt/.npmignore | 0 .../project_express/node_modules/nopt/LICENSE | 23 + .../node_modules/nopt/README.md | 208 + .../node_modules/nopt/bin/nopt.js | 44 + .../node_modules/nopt/examples/my-program.js | 30 + .../node_modules/nopt/lib/nopt.js | 552 ++ .../node_modules/nopt/package.json | 12 + .../node_modules/normalize-path/LICENSE | 21 + .../node_modules/normalize-path/README.md | 127 + .../node_modules/normalize-path/index.js | 35 + .../node_modules/normalize-path/package.json | 77 + .../node_modules/on-finished/HISTORY.md | 88 + .../node_modules/on-finished/LICENSE | 23 + .../node_modules/on-finished/README.md | 154 + .../node_modules/on-finished/index.js | 196 + .../node_modules/on-finished/package.json | 73 + .../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 + .../optimist/example/default_hash.js | 8 + .../optimist/example/default_singles.js | 7 + .../node_modules/optimist/example/divide.js | 8 + .../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 + .../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/parseurl/HISTORY.md | 58 + .../node_modules/parseurl/LICENSE | 24 + .../node_modules/parseurl/README.md | 133 + .../node_modules/parseurl/index.js | 158 + .../node_modules/parseurl/package.json | 81 + .../node_modules/path-to-regexp/History.md | 36 + .../node_modules/path-to-regexp/LICENSE | 21 + .../node_modules/path-to-regexp/Readme.md | 35 + .../node_modules/path-to-regexp/index.js | 129 + .../node_modules/path-to-regexp/package.json | 59 + .../node_modules/picomatch/CHANGELOG.md | 136 + .../node_modules/picomatch/LICENSE | 21 + .../node_modules/picomatch/README.md | 708 ++ .../node_modules/picomatch/index.js | 3 + .../node_modules/picomatch/lib/constants.js | 179 + .../node_modules/picomatch/lib/parse.js | 1091 +++ .../node_modules/picomatch/lib/picomatch.js | 342 + .../node_modules/picomatch/lib/scan.js | 391 + .../node_modules/picomatch/lib/utils.js | 64 + .../node_modules/picomatch/package.json | 81 + .../node_modules/proxy-addr/HISTORY.md | 155 + .../node_modules/proxy-addr/LICENSE | 22 + .../node_modules/proxy-addr/README.md | 155 + .../node_modules/proxy-addr/index.js | 327 + .../node_modules/proxy-addr/package.json | 82 + .../node_modules/pstree.remy/.travis.yml | 8 + .../node_modules/pstree.remy/LICENSE | 7 + .../node_modules/pstree.remy/README.md | 26 + .../node_modules/pstree.remy/lib/index.js | 37 + .../node_modules/pstree.remy/lib/tree.js | 37 + .../node_modules/pstree.remy/lib/utils.js | 53 + .../node_modules/pstree.remy/package.json | 33 + .../pstree.remy/tests/fixtures/index.js | 13 + .../pstree.remy/tests/fixtures/out1 | 10 + .../pstree.remy/tests/fixtures/out2 | 29 + .../pstree.remy/tests/index.test.js | 51 + .../node_modules/qs/.editorconfig | 30 + .../node_modules/qs/.eslintignore | 1 + .../project_express/node_modules/qs/.eslintrc | 21 + .../node_modules/qs/CHANGELOG.md | 256 + .../project_express/node_modules/qs/LICENSE | 28 + .../project_express/node_modules/qs/README.md | 570 ++ .../node_modules/qs/dist/qs.js | 782 ++ .../node_modules/qs/lib/formats.js | 18 + .../node_modules/qs/lib/index.js | 11 + .../node_modules/qs/lib/parse.js | 242 + .../node_modules/qs/lib/stringify.js | 269 + .../node_modules/qs/lib/utils.js | 230 + .../node_modules/qs/package.json | 87 + .../node_modules/qs/test/.eslintrc | 17 + .../node_modules/qs/test/index.js | 7 + .../node_modules/qs/test/parse.js | 676 ++ .../node_modules/qs/test/stringify.js | 679 ++ .../node_modules/qs/test/utils.js | 136 + .../node_modules/range-parser/HISTORY.md | 56 + .../node_modules/range-parser/LICENSE | 23 + .../node_modules/range-parser/README.md | 84 + .../node_modules/range-parser/index.js | 162 + .../node_modules/range-parser/package.json | 91 + .../node_modules/raw-body/HISTORY.md | 270 + .../node_modules/raw-body/LICENSE | 22 + .../node_modules/raw-body/README.md | 219 + .../node_modules/raw-body/index.d.ts | 87 + .../node_modules/raw-body/index.js | 286 + .../node_modules/raw-body/package.json | 90 + .../node_modules/readdirp/LICENSE | 21 + .../node_modules/readdirp/README.md | 122 + .../node_modules/readdirp/index.d.ts | 43 + .../node_modules/readdirp/index.js | 287 + .../node_modules/readdirp/package.json | 122 + .../node_modules/require/.npmignore | 1 + .../node_modules/require/Changelog | 136 + .../node_modules/require/LICENSE | 19 + .../node_modules/require/README.md | 75 + .../require/bin/require-command.js | 69 + .../node_modules/require/compiler.js | 162 + .../node_modules/require/example/client.js | 4 + .../node_modules/require/example/compile.js | 8 + .../node_modules/require/example/connect.js | 7 + .../node_modules/require/example/index.html | 8 + .../node_modules/require/example/package.json | 16 + .../require/example/raphael_circle.html | 4 + .../require/example/raphael_circle.js | 5 + .../node_modules/require/example/server.js | 20 + .../require/example/shared/dependency.js | 4 + .../node_modules/require/lib/getCode.js | 6 + .../require/lib/getDependencyLevels.js | 59 + .../require/lib/getRequireStatements.js | 6 + .../node_modules/require/lib/resolve.js | 72 + .../node_modules/require/package.json | 23 + .../node_modules/require/server.js | 185 + .../node_modules/safe-buffer/LICENSE | 21 + .../node_modules/safe-buffer/README.md | 584 ++ .../node_modules/safe-buffer/index.d.ts | 187 + .../node_modules/safe-buffer/index.js | 62 + .../node_modules/safe-buffer/package.json | 63 + .../node_modules/safer-buffer/LICENSE | 21 + .../safer-buffer/Porting-Buffer.md | 268 + .../node_modules/safer-buffer/Readme.md | 156 + .../node_modules/safer-buffer/dangerous.js | 58 + .../node_modules/safer-buffer/package.json | 60 + .../node_modules/safer-buffer/safer.js | 77 + .../node_modules/safer-buffer/tests.js | 406 + .../node_modules/semver/CHANGELOG.md | 39 + .../node_modules/semver/LICENSE | 15 + .../node_modules/semver/README.md | 412 + .../node_modules/semver/bin/semver | 160 + .../node_modules/semver/package.json | 28 + .../node_modules/semver/range.bnf | 16 + .../node_modules/semver/semver.js | 1483 +++ .../node_modules/send/HISTORY.md | 496 + .../project_express/node_modules/send/LICENSE | 23 + .../node_modules/send/README.md | 329 + .../node_modules/send/index.js | 1129 +++ .../send/node_modules/ms/index.js | 162 + .../send/node_modules/ms/license.md | 21 + .../send/node_modules/ms/package.json | 69 + .../send/node_modules/ms/readme.md | 60 + .../node_modules/send/package.json | 106 + .../node_modules/serve-static/HISTORY.md | 451 + .../node_modules/serve-static/LICENSE | 25 + .../node_modules/serve-static/README.md | 259 + .../node_modules/serve-static/index.js | 210 + .../node_modules/serve-static/package.json | 77 + .../node_modules/setprototypeof/LICENSE | 13 + .../node_modules/setprototypeof/README.md | 31 + .../node_modules/setprototypeof/index.d.ts | 2 + .../node_modules/setprototypeof/index.js | 17 + .../node_modules/setprototypeof/package.json | 64 + .../node_modules/setprototypeof/test/index.js | 24 + .../simple-update-notifier/LICENSE | 21 + .../simple-update-notifier/README.md | 67 + .../simple-update-notifier/build/index.d.ts | 12 + .../simple-update-notifier/build/index.js | 202 + .../node_modules/.bin/semver | 12 + .../node_modules/.bin/semver.cmd | 17 + .../node_modules/.bin/semver.ps1 | 28 + .../node_modules/semver/CHANGELOG.md | 74 + .../node_modules/semver/LICENSE | 15 + .../node_modules/semver/README.md | 499 + .../node_modules/semver/bin/semver.js | 173 + .../node_modules/semver/classes/comparator.js | 139 + .../node_modules/semver/classes/index.js | 5 + .../node_modules/semver/classes/range.js | 448 + .../node_modules/semver/classes/semver.js | 290 + .../node_modules/semver/functions/clean.js | 6 + .../node_modules/semver/functions/cmp.js | 48 + .../node_modules/semver/functions/coerce.js | 51 + .../semver/functions/compare-build.js | 7 + .../semver/functions/compare-loose.js | 3 + .../node_modules/semver/functions/compare.js | 5 + .../node_modules/semver/functions/diff.js | 25 + .../node_modules/semver/functions/eq.js | 3 + .../node_modules/semver/functions/gt.js | 3 + .../node_modules/semver/functions/gte.js | 3 + .../node_modules/semver/functions/inc.js | 15 + .../node_modules/semver/functions/lt.js | 3 + .../node_modules/semver/functions/lte.js | 3 + .../node_modules/semver/functions/major.js | 3 + .../node_modules/semver/functions/minor.js | 3 + .../node_modules/semver/functions/neq.js | 3 + .../node_modules/semver/functions/parse.js | 37 + .../node_modules/semver/functions/patch.js | 3 + .../semver/functions/prerelease.js | 6 + .../node_modules/semver/functions/rcompare.js | 3 + .../node_modules/semver/functions/rsort.js | 3 + .../semver/functions/satisfies.js | 10 + .../node_modules/semver/functions/sort.js | 3 + .../node_modules/semver/functions/valid.js | 6 + .../node_modules/semver/index.js | 64 + .../node_modules/semver/internal/constants.js | 17 + .../node_modules/semver/internal/debug.js | 9 + .../semver/internal/identifiers.js | 23 + .../node_modules/semver/internal/re.js | 179 + .../node_modules/semver/package.json | 34 + .../node_modules/semver/range.bnf | 16 + .../node_modules/semver/ranges/gtr.js | 4 + .../node_modules/semver/ranges/intersects.js | 7 + .../node_modules/semver/ranges/ltr.js | 4 + .../semver/ranges/max-satisfying.js | 25 + .../semver/ranges/min-satisfying.js | 24 + .../node_modules/semver/ranges/min-version.js | 57 + .../node_modules/semver/ranges/outside.js | 80 + .../semver/ranges/to-comparators.js | 8 + .../node_modules/semver/ranges/valid.js | 11 + .../simple-update-notifier/package.json | 97 + .../src/borderedText.ts | 12 + .../simple-update-notifier/src/cache.spec.ts | 12 + .../simple-update-notifier/src/cache.ts | 41 + .../src/getDistVersion.spec.ts | 35 + .../src/getDistVersion.ts | 29 + .../src/hasNewVersion.spec.ts | 82 + .../src/hasNewVersion.ts | 30 + .../simple-update-notifier/src/index.spec.ts | 27 + .../simple-update-notifier/src/index.ts | 28 + .../simple-update-notifier/src/isNpmOrYarn.ts | 12 + .../simple-update-notifier/src/types.ts | 7 + .../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 + .../source-map/build/assert-shim.js | 56 + .../source-map/build/mini-require.js | 152 + .../source-map/build/prefix-source-map.jsm | 20 + .../source-map/build/prefix-utils.jsm | 18 + .../source-map/build/suffix-browser.js | 8 + .../source-map/build/suffix-source-map.jsm | 6 + .../source-map/build/suffix-utils.jsm | 21 + .../source-map/build/test-prefix.js | 8 + .../source-map/build/test-suffix.js | 3 + .../node_modules/source-map/lib/source-map.js | 8 + .../source-map/lib/source-map/array-set.js | 97 + .../source-map/lib/source-map/base64-vlq.js | 142 + .../source-map/lib/source-map/base64.js | 42 + .../lib/source-map/binary-search.js | 80 + .../source-map/lib/source-map/mapping-list.js | 86 + .../lib/source-map/source-map-consumer.js | 575 ++ .../lib/source-map/source-map-generator.js | 400 + .../source-map/lib/source-map/source-node.js | 414 + .../source-map/lib/source-map/util.js | 319 + .../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/statuses/HISTORY.md | 65 + .../node_modules/statuses/LICENSE | 23 + .../node_modules/statuses/README.md | 127 + .../node_modules/statuses/codes.json | 66 + .../node_modules/statuses/index.js | 113 + .../node_modules/statuses/package.json | 90 + .../node_modules/std/Animation.js | 57 + .../node_modules/std/Changelog | 179 + .../project_express/node_modules/std/Class.js | 80 + .../project_express/node_modules/std/LICENSE | 22 + .../node_modules/std/ListPromise.js | 47 + .../node_modules/std/Logger.js | 81 + .../node_modules/std/Promise.js | 40 + .../node_modules/std/Publisher.js | 28 + .../node_modules/std/README.md | 16 + .../node_modules/std/arrayToObject.js | 5 + .../node_modules/std/assert/deepEqual.js | 88 + .../node_modules/std/asyncEach.js | 63 + .../node_modules/std/asyncMap.js | 27 + .../node_modules/std/base64.js | 128 + .../project_express/node_modules/std/bind.js | 50 + .../node_modules/std/blockFunction.js | 44 + .../node_modules/std/browser.js | 119 + .../project_express/node_modules/std/check.js | 3 + .../node_modules/std/client.js | 87 + .../project_express/node_modules/std/clip.js | 3 + .../node_modules/std/cookie.js | 33 + .../project_express/node_modules/std/copy.js | 10 + .../project_express/node_modules/std/crc32.js | 28 + .../node_modules/std/create.js | 22 + .../project_express/node_modules/std/curry.js | 10 + .../node_modules/std/defineGetter.js | 29 + .../project_express/node_modules/std/delay.js | 51 + .../node_modules/std/delayed.js | 11 + .../project_express/node_modules/std/each.js | 20 + .../node_modules/std/extend.js | 40 + .../node_modules/std/filter.js | 38 + .../project_express/node_modules/std/find.js | 7 + .../node_modules/std/flatten.js | 3 + .../project_express/node_modules/std/flip.js | 5 + .../project_express/node_modules/std/index.js | 20 + .../node_modules/std/inverse.js | 7 + .../node_modules/std/invoke.js | 19 + .../node_modules/std/invokeWith.js | 17 + .../node_modules/std/isArguments.js | 3 + .../node_modules/std/isArray.js | 12 + .../node_modules/std/isFunction.js | 3 + .../node_modules/std/isObject.js | 3 + .../project_express/node_modules/std/json.js | 482 + .../project_express/node_modules/std/keys.js | 14 + .../project_express/node_modules/std/last.js | 6 + .../project_express/node_modules/std/map.js | 13 + .../project_express/node_modules/std/merge.js | 7 + .../node_modules/std/nextTick.js | 14 + .../project_express/node_modules/std/once.js | 13 + .../node_modules/std/options.js | 9 + .../project_express/node_modules/std/pack.js | 349 + .../node_modules/std/package.json | 17 + .../node_modules/std/parallel.js | 17 + .../project_express/node_modules/std/popup.js | 26 + .../project_express/node_modules/std/proto.js | 39 + .../project_express/node_modules/std/rand.js | 3 + .../node_modules/std/recall.js | 4 + .../node_modules/std/remove.js | 8 + .../node_modules/std/repeat.js | 4 + .../project_express/node_modules/std/round.js | 7 + .../node_modules/std/router.js | 71 + .../project_express/node_modules/std/slice.js | 12 + .../project_express/node_modules/std/strip.js | 5 + .../project_express/node_modules/std/sum.js | 8 + .../node_modules/std/throttle.js | 14 + .../project_express/node_modules/std/time.js | 109 + .../project_express/node_modules/std/trim.js | 4 + .../node_modules/std/unique.js | 22 + .../node_modules/std/unpack.js | 361 + .../project_express/node_modules/std/url.js | 112 + .../node_modules/std/utf8_encode.js | 47 + .../node_modules/std/waitFor.js | 13 + .../project_express/node_modules/std/xhr.js | 89 + .../node_modules/supports-color/browser.js | 5 + .../node_modules/supports-color/index.js | 131 + .../node_modules/supports-color/license | 9 + .../node_modules/supports-color/package.json | 53 + .../node_modules/supports-color/readme.md | 66 + .../node_modules/to-regex-range/LICENSE | 21 + .../node_modules/to-regex-range/README.md | 305 + .../node_modules/to-regex-range/index.js | 288 + .../node_modules/to-regex-range/package.json | 88 + .../node_modules/toidentifier/LICENSE | 21 + .../node_modules/toidentifier/README.md | 61 + .../node_modules/toidentifier/index.js | 30 + .../node_modules/toidentifier/package.json | 76 + .../node_modules/touch/LICENSE | 15 + .../node_modules/touch/README.md | 52 + .../node_modules/touch/bin/nodetouch.js | 112 + .../node_modules/touch/index.js | 224 + .../node_modules/touch/package.json | 28 + .../node_modules/type-is/HISTORY.md | 259 + .../node_modules/type-is/LICENSE | 23 + .../node_modules/type-is/README.md | 170 + .../node_modules/type-is/index.js | 266 + .../node_modules/type-is/package.json | 85 + .../node_modules/uglify-js/.npmignore | 2 + .../node_modules/uglify-js/LICENSE | 29 + .../node_modules/uglify-js/README.md | 567 ++ .../node_modules/uglify-js/bin/uglifyjs | 398 + .../node_modules/uglify-js/lib/ast.js | 985 ++ .../node_modules/uglify-js/lib/compress.js | 1985 ++++ .../node_modules/uglify-js/lib/mozilla-ast.js | 267 + .../node_modules/uglify-js/lib/output.js | 1225 +++ .../node_modules/uglify-js/lib/parse.js | 1401 +++ .../node_modules/uglify-js/lib/scope.js | 580 ++ .../node_modules/uglify-js/lib/sourcemap.js | 81 + .../node_modules/uglify-js/lib/transform.js | 218 + .../node_modules/uglify-js/lib/utils.js | 288 + .../node_modules/uglify-js/package.json | 26 + .../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 | 40 + .../uglify-js/test/compress/sequences.js | 161 + .../uglify-js/test/compress/switch.js | 260 + .../uglify-js/test/compress/typeof.js | 25 + .../node_modules/uglify-js/test/run-tests.js | 170 + .../node_modules/uglify-js/tools/node.js | 165 + .../undefsafe/.github/workflows/release.yml | 25 + .../node_modules/undefsafe/.jscsrc | 13 + .../node_modules/undefsafe/.jshintrc | 16 + .../node_modules/undefsafe/.travis.yml | 18 + .../node_modules/undefsafe/LICENSE | 22 + .../node_modules/undefsafe/README.md | 63 + .../node_modules/undefsafe/example.js | 14 + .../node_modules/undefsafe/lib/undefsafe.js | 125 + .../node_modules/undefsafe/package.json | 34 + .../node_modules/unpipe/HISTORY.md | 4 + .../node_modules/unpipe/LICENSE | 22 + .../node_modules/unpipe/README.md | 43 + .../node_modules/unpipe/index.js | 69 + .../node_modules/unpipe/package.json | 63 + .../node_modules/utils-merge/.npmignore | 9 + .../node_modules/utils-merge/LICENSE | 20 + .../node_modules/utils-merge/README.md | 34 + .../node_modules/utils-merge/index.js | 23 + .../node_modules/utils-merge/package.json | 66 + .../node_modules/vary/HISTORY.md | 39 + .../project_express/node_modules/vary/LICENSE | 22 + .../node_modules/vary/README.md | 101 + .../node_modules/vary/index.js | 149 + .../node_modules/vary/package.json | 78 + .../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 + .../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 + homework7/project_express/package-lock.json | 1567 ++++ homework7/project_express/package.json | 17 + .../public/copy/js/CartComponent.js | 94 + .../public/copy/js/ErrorComp.js | 20 + .../public/copy/js/FilterComp.js | 13 + .../public/copy/js/ProductComponent.js | 45 + .../project_express/public/copy/js/main.js | 254 + .../public/css/images/subscribe.jpg | Bin 0 -> 131033 bytes .../project_express/public/css/normalize.css | 349 + .../project_express/public/css/style.css | 785 ++ .../project_express/public/images/bars.png | Bin 0 -> 174 bytes .../project_express/public/images/cart.png | Bin 0 -> 716 bytes .../project_express/public/images/cart.svg | 5 + .../public/images/chevronLeft.svg | 3 + .../public/images/chevronRight.svg | 3 + .../public/images/featured/1.jpg | Bin 0 -> 93945 bytes .../public/images/featured/2.jpg | Bin 0 -> 50693 bytes .../public/images/featured/3.jpg | Bin 0 -> 80895 bytes .../public/images/featured/4.jpg | Bin 0 -> 51885 bytes .../public/images/featured/5.jpg | Bin 0 -> 93122 bytes .../public/images/featured/6.jpg | Bin 0 -> 96512 bytes .../project_express/public/images/filter.svg | 3 + .../public/images/filterArrow.svg | 3 + .../public/images/filterHover.svg | 3 + .../project_express/public/images/logo.png | Bin 0 -> 2364 bytes .../project_express/public/images/search.png | Bin 0 -> 667 bytes .../public/images/services/assurance.svg | 3 + .../public/images/services/delivery.svg | 3 + .../public/images/services/discount.svg | 3 + .../public/images/subscribe.jpg | Bin 0 -> 131033 bytes .../public/images/subscribeUser.png | Bin 0 -> 17526 bytes .../project_express/public/images/user.png | Bin 0 -> 718 bytes homework7/project_express/public/index.html | 250 + homework7/project_express/public/js/main.js | 62 + .../public/js/mycartComponent.js | 91 + .../public/js/myproductComponent.js | 55 + homework7/project_express/server/cart.js | 24 + .../project_express/server/cartRouter.js | 25 + .../project_express/server/db/products.json | 38 + .../project_express/server/db/userCart.json | 20 + homework7/project_express/server/handler.js | 27 + homework7/project_express/server/server.js | 32 + 878 files changed, 111631 insertions(+) create mode 100644 homework7/project_express/.idea/.gitignore create mode 100644 homework7/project_express/.idea/jsLibraryMappings.xml create mode 100644 homework7/project_express/.idea/misc.xml create mode 100644 homework7/project_express/.idea/modules.xml create mode 100644 homework7/project_express/.idea/project_express.iml create mode 100644 homework7/project_express/node_modules/.bin/mime create mode 100644 homework7/project_express/node_modules/.bin/mime.cmd create mode 100644 homework7/project_express/node_modules/.bin/mime.ps1 create mode 100644 homework7/project_express/node_modules/.bin/nodemon create mode 100644 homework7/project_express/node_modules/.bin/nodemon.cmd create mode 100644 homework7/project_express/node_modules/.bin/nodemon.ps1 create mode 100644 homework7/project_express/node_modules/.bin/nodetouch create mode 100644 homework7/project_express/node_modules/.bin/nodetouch.cmd create mode 100644 homework7/project_express/node_modules/.bin/nodetouch.ps1 create mode 100644 homework7/project_express/node_modules/.bin/nopt create mode 100644 homework7/project_express/node_modules/.bin/nopt.cmd create mode 100644 homework7/project_express/node_modules/.bin/nopt.ps1 create mode 100644 homework7/project_express/node_modules/.bin/require create mode 100644 homework7/project_express/node_modules/.bin/require.cmd create mode 100644 homework7/project_express/node_modules/.bin/require.ps1 create mode 100644 homework7/project_express/node_modules/.bin/semver create mode 100644 homework7/project_express/node_modules/.bin/semver.cmd create mode 100644 homework7/project_express/node_modules/.bin/semver.ps1 create mode 100644 homework7/project_express/node_modules/.bin/uglifyjs create mode 100644 homework7/project_express/node_modules/.bin/uglifyjs.cmd create mode 100644 homework7/project_express/node_modules/.bin/uglifyjs.ps1 create mode 100644 homework7/project_express/node_modules/.package-lock.json create mode 100644 homework7/project_express/node_modules/abbrev/LICENSE create mode 100644 homework7/project_express/node_modules/abbrev/README.md create mode 100644 homework7/project_express/node_modules/abbrev/abbrev.js create mode 100644 homework7/project_express/node_modules/abbrev/package.json create mode 100644 homework7/project_express/node_modules/accepts/HISTORY.md create mode 100644 homework7/project_express/node_modules/accepts/LICENSE create mode 100644 homework7/project_express/node_modules/accepts/README.md create mode 100644 homework7/project_express/node_modules/accepts/index.js create mode 100644 homework7/project_express/node_modules/accepts/package.json create mode 100644 homework7/project_express/node_modules/amdefine/LICENSE create mode 100644 homework7/project_express/node_modules/amdefine/README.md create mode 100644 homework7/project_express/node_modules/amdefine/amdefine.js create mode 100644 homework7/project_express/node_modules/amdefine/intercept.js create mode 100644 homework7/project_express/node_modules/amdefine/package.json create mode 100644 homework7/project_express/node_modules/anymatch/LICENSE create mode 100644 homework7/project_express/node_modules/anymatch/README.md create mode 100644 homework7/project_express/node_modules/anymatch/index.d.ts create mode 100644 homework7/project_express/node_modules/anymatch/index.js create mode 100644 homework7/project_express/node_modules/anymatch/package.json create mode 100644 homework7/project_express/node_modules/array-flatten/LICENSE create mode 100644 homework7/project_express/node_modules/array-flatten/README.md create mode 100644 homework7/project_express/node_modules/array-flatten/array-flatten.js create mode 100644 homework7/project_express/node_modules/array-flatten/package.json create mode 100644 homework7/project_express/node_modules/async/LICENSE create mode 100644 homework7/project_express/node_modules/async/README.md create mode 100644 homework7/project_express/node_modules/async/component.json create mode 100644 homework7/project_express/node_modules/async/lib/async.js create mode 100644 homework7/project_express/node_modules/async/package.json create mode 100644 homework7/project_express/node_modules/balanced-match/.github/FUNDING.yml create mode 100644 homework7/project_express/node_modules/balanced-match/LICENSE.md create mode 100644 homework7/project_express/node_modules/balanced-match/README.md create mode 100644 homework7/project_express/node_modules/balanced-match/index.js create mode 100644 homework7/project_express/node_modules/balanced-match/package.json create mode 100644 homework7/project_express/node_modules/binary-extensions/binary-extensions.json create mode 100644 homework7/project_express/node_modules/binary-extensions/binary-extensions.json.d.ts create mode 100644 homework7/project_express/node_modules/binary-extensions/index.d.ts create mode 100644 homework7/project_express/node_modules/binary-extensions/index.js create mode 100644 homework7/project_express/node_modules/binary-extensions/license create mode 100644 homework7/project_express/node_modules/binary-extensions/package.json create mode 100644 homework7/project_express/node_modules/binary-extensions/readme.md create mode 100644 homework7/project_express/node_modules/body-parser/HISTORY.md create mode 100644 homework7/project_express/node_modules/body-parser/LICENSE create mode 100644 homework7/project_express/node_modules/body-parser/README.md create mode 100644 homework7/project_express/node_modules/body-parser/index.js create mode 100644 homework7/project_express/node_modules/body-parser/lib/read.js create mode 100644 homework7/project_express/node_modules/body-parser/lib/types/json.js create mode 100644 homework7/project_express/node_modules/body-parser/lib/types/raw.js create mode 100644 homework7/project_express/node_modules/body-parser/lib/types/text.js create mode 100644 homework7/project_express/node_modules/body-parser/lib/types/urlencoded.js create mode 100644 homework7/project_express/node_modules/body-parser/package.json create mode 100644 homework7/project_express/node_modules/brace-expansion/LICENSE create mode 100644 homework7/project_express/node_modules/brace-expansion/README.md create mode 100644 homework7/project_express/node_modules/brace-expansion/index.js create mode 100644 homework7/project_express/node_modules/brace-expansion/package.json create mode 100644 homework7/project_express/node_modules/braces/CHANGELOG.md create mode 100644 homework7/project_express/node_modules/braces/LICENSE create mode 100644 homework7/project_express/node_modules/braces/README.md create mode 100644 homework7/project_express/node_modules/braces/index.js create mode 100644 homework7/project_express/node_modules/braces/lib/compile.js create mode 100644 homework7/project_express/node_modules/braces/lib/constants.js create mode 100644 homework7/project_express/node_modules/braces/lib/expand.js create mode 100644 homework7/project_express/node_modules/braces/lib/parse.js create mode 100644 homework7/project_express/node_modules/braces/lib/stringify.js create mode 100644 homework7/project_express/node_modules/braces/lib/utils.js create mode 100644 homework7/project_express/node_modules/braces/package.json create mode 100644 homework7/project_express/node_modules/bytes/History.md create mode 100644 homework7/project_express/node_modules/bytes/LICENSE create mode 100644 homework7/project_express/node_modules/bytes/Readme.md create mode 100644 homework7/project_express/node_modules/bytes/index.js create mode 100644 homework7/project_express/node_modules/bytes/package.json create mode 100644 homework7/project_express/node_modules/chokidar/LICENSE create mode 100644 homework7/project_express/node_modules/chokidar/README.md create mode 100644 homework7/project_express/node_modules/chokidar/index.js create mode 100644 homework7/project_express/node_modules/chokidar/lib/constants.js create mode 100644 homework7/project_express/node_modules/chokidar/lib/fsevents-handler.js create mode 100644 homework7/project_express/node_modules/chokidar/lib/nodefs-handler.js create mode 100644 homework7/project_express/node_modules/chokidar/package.json create mode 100644 homework7/project_express/node_modules/chokidar/types/index.d.ts create mode 100644 homework7/project_express/node_modules/concat-map/.travis.yml create mode 100644 homework7/project_express/node_modules/concat-map/LICENSE create mode 100644 homework7/project_express/node_modules/concat-map/README.markdown create mode 100644 homework7/project_express/node_modules/concat-map/example/map.js create mode 100644 homework7/project_express/node_modules/concat-map/index.js create mode 100644 homework7/project_express/node_modules/concat-map/package.json create mode 100644 homework7/project_express/node_modules/concat-map/test/map.js create mode 100644 homework7/project_express/node_modules/content-disposition/HISTORY.md create mode 100644 homework7/project_express/node_modules/content-disposition/LICENSE create mode 100644 homework7/project_express/node_modules/content-disposition/README.md create mode 100644 homework7/project_express/node_modules/content-disposition/index.js create mode 100644 homework7/project_express/node_modules/content-disposition/package.json create mode 100644 homework7/project_express/node_modules/content-type/HISTORY.md create mode 100644 homework7/project_express/node_modules/content-type/LICENSE create mode 100644 homework7/project_express/node_modules/content-type/README.md create mode 100644 homework7/project_express/node_modules/content-type/index.js create mode 100644 homework7/project_express/node_modules/content-type/package.json create mode 100644 homework7/project_express/node_modules/cookie-signature/.npmignore create mode 100644 homework7/project_express/node_modules/cookie-signature/History.md create mode 100644 homework7/project_express/node_modules/cookie-signature/Readme.md create mode 100644 homework7/project_express/node_modules/cookie-signature/index.js create mode 100644 homework7/project_express/node_modules/cookie-signature/package.json create mode 100644 homework7/project_express/node_modules/cookie/HISTORY.md create mode 100644 homework7/project_express/node_modules/cookie/LICENSE create mode 100644 homework7/project_express/node_modules/cookie/README.md create mode 100644 homework7/project_express/node_modules/cookie/index.js create mode 100644 homework7/project_express/node_modules/cookie/package.json create mode 100644 homework7/project_express/node_modules/debug/.coveralls.yml create mode 100644 homework7/project_express/node_modules/debug/.eslintrc create mode 100644 homework7/project_express/node_modules/debug/.npmignore create mode 100644 homework7/project_express/node_modules/debug/.travis.yml create mode 100644 homework7/project_express/node_modules/debug/CHANGELOG.md create mode 100644 homework7/project_express/node_modules/debug/LICENSE create mode 100644 homework7/project_express/node_modules/debug/Makefile create mode 100644 homework7/project_express/node_modules/debug/README.md create mode 100644 homework7/project_express/node_modules/debug/component.json create mode 100644 homework7/project_express/node_modules/debug/karma.conf.js create mode 100644 homework7/project_express/node_modules/debug/node.js create mode 100644 homework7/project_express/node_modules/debug/package.json create mode 100644 homework7/project_express/node_modules/debug/src/browser.js create mode 100644 homework7/project_express/node_modules/debug/src/debug.js create mode 100644 homework7/project_express/node_modules/debug/src/index.js create mode 100644 homework7/project_express/node_modules/debug/src/inspector-log.js create mode 100644 homework7/project_express/node_modules/debug/src/node.js create mode 100644 homework7/project_express/node_modules/depd/History.md create mode 100644 homework7/project_express/node_modules/depd/LICENSE create mode 100644 homework7/project_express/node_modules/depd/Readme.md create mode 100644 homework7/project_express/node_modules/depd/index.js create mode 100644 homework7/project_express/node_modules/depd/lib/browser/index.js create mode 100644 homework7/project_express/node_modules/depd/lib/compat/callsite-tostring.js create mode 100644 homework7/project_express/node_modules/depd/lib/compat/event-listener-count.js create mode 100644 homework7/project_express/node_modules/depd/lib/compat/index.js create mode 100644 homework7/project_express/node_modules/depd/package.json create mode 100644 homework7/project_express/node_modules/destroy/LICENSE create mode 100644 homework7/project_express/node_modules/destroy/README.md create mode 100644 homework7/project_express/node_modules/destroy/index.js create mode 100644 homework7/project_express/node_modules/destroy/package.json create mode 100644 homework7/project_express/node_modules/ee-first/LICENSE create mode 100644 homework7/project_express/node_modules/ee-first/README.md create mode 100644 homework7/project_express/node_modules/ee-first/index.js create mode 100644 homework7/project_express/node_modules/ee-first/package.json create mode 100644 homework7/project_express/node_modules/encodeurl/HISTORY.md create mode 100644 homework7/project_express/node_modules/encodeurl/LICENSE create mode 100644 homework7/project_express/node_modules/encodeurl/README.md create mode 100644 homework7/project_express/node_modules/encodeurl/index.js create mode 100644 homework7/project_express/node_modules/encodeurl/package.json create mode 100644 homework7/project_express/node_modules/escape-html/LICENSE create mode 100644 homework7/project_express/node_modules/escape-html/Readme.md create mode 100644 homework7/project_express/node_modules/escape-html/index.js create mode 100644 homework7/project_express/node_modules/escape-html/package.json create mode 100644 homework7/project_express/node_modules/etag/HISTORY.md create mode 100644 homework7/project_express/node_modules/etag/LICENSE create mode 100644 homework7/project_express/node_modules/etag/README.md create mode 100644 homework7/project_express/node_modules/etag/index.js create mode 100644 homework7/project_express/node_modules/etag/package.json create mode 100644 homework7/project_express/node_modules/express/History.md create mode 100644 homework7/project_express/node_modules/express/LICENSE create mode 100644 homework7/project_express/node_modules/express/Readme.md create mode 100644 homework7/project_express/node_modules/express/index.js create mode 100644 homework7/project_express/node_modules/express/lib/application.js create mode 100644 homework7/project_express/node_modules/express/lib/express.js create mode 100644 homework7/project_express/node_modules/express/lib/middleware/init.js create mode 100644 homework7/project_express/node_modules/express/lib/middleware/query.js create mode 100644 homework7/project_express/node_modules/express/lib/request.js create mode 100644 homework7/project_express/node_modules/express/lib/response.js create mode 100644 homework7/project_express/node_modules/express/lib/router/index.js create mode 100644 homework7/project_express/node_modules/express/lib/router/layer.js create mode 100644 homework7/project_express/node_modules/express/lib/router/route.js create mode 100644 homework7/project_express/node_modules/express/lib/utils.js create mode 100644 homework7/project_express/node_modules/express/lib/view.js create mode 100644 homework7/project_express/node_modules/express/package.json create mode 100644 homework7/project_express/node_modules/fill-range/LICENSE create mode 100644 homework7/project_express/node_modules/fill-range/README.md create mode 100644 homework7/project_express/node_modules/fill-range/index.js create mode 100644 homework7/project_express/node_modules/fill-range/package.json create mode 100644 homework7/project_express/node_modules/finalhandler/HISTORY.md create mode 100644 homework7/project_express/node_modules/finalhandler/LICENSE create mode 100644 homework7/project_express/node_modules/finalhandler/README.md create mode 100644 homework7/project_express/node_modules/finalhandler/index.js create mode 100644 homework7/project_express/node_modules/finalhandler/package.json create mode 100644 homework7/project_express/node_modules/forwarded/HISTORY.md create mode 100644 homework7/project_express/node_modules/forwarded/LICENSE create mode 100644 homework7/project_express/node_modules/forwarded/README.md create mode 100644 homework7/project_express/node_modules/forwarded/index.js create mode 100644 homework7/project_express/node_modules/forwarded/package.json create mode 100644 homework7/project_express/node_modules/fresh/HISTORY.md create mode 100644 homework7/project_express/node_modules/fresh/LICENSE create mode 100644 homework7/project_express/node_modules/fresh/README.md create mode 100644 homework7/project_express/node_modules/fresh/index.js create mode 100644 homework7/project_express/node_modules/fresh/package.json create mode 100644 homework7/project_express/node_modules/glob-parent/CHANGELOG.md create mode 100644 homework7/project_express/node_modules/glob-parent/LICENSE create mode 100644 homework7/project_express/node_modules/glob-parent/README.md create mode 100644 homework7/project_express/node_modules/glob-parent/index.js create mode 100644 homework7/project_express/node_modules/glob-parent/package.json create mode 100644 homework7/project_express/node_modules/has-flag/index.js create mode 100644 homework7/project_express/node_modules/has-flag/license create mode 100644 homework7/project_express/node_modules/has-flag/package.json create mode 100644 homework7/project_express/node_modules/has-flag/readme.md create mode 100644 homework7/project_express/node_modules/http-errors/HISTORY.md create mode 100644 homework7/project_express/node_modules/http-errors/LICENSE create mode 100644 homework7/project_express/node_modules/http-errors/README.md create mode 100644 homework7/project_express/node_modules/http-errors/index.js create mode 100644 homework7/project_express/node_modules/http-errors/package.json create mode 100644 homework7/project_express/node_modules/iconv-lite/Changelog.md create mode 100644 homework7/project_express/node_modules/iconv-lite/LICENSE create mode 100644 homework7/project_express/node_modules/iconv-lite/README.md create mode 100644 homework7/project_express/node_modules/iconv-lite/encodings/dbcs-codec.js create mode 100644 homework7/project_express/node_modules/iconv-lite/encodings/dbcs-data.js create mode 100644 homework7/project_express/node_modules/iconv-lite/encodings/index.js create mode 100644 homework7/project_express/node_modules/iconv-lite/encodings/internal.js create mode 100644 homework7/project_express/node_modules/iconv-lite/encodings/sbcs-codec.js create mode 100644 homework7/project_express/node_modules/iconv-lite/encodings/sbcs-data-generated.js create mode 100644 homework7/project_express/node_modules/iconv-lite/encodings/sbcs-data.js create mode 100644 homework7/project_express/node_modules/iconv-lite/encodings/tables/big5-added.json create mode 100644 homework7/project_express/node_modules/iconv-lite/encodings/tables/cp936.json create mode 100644 homework7/project_express/node_modules/iconv-lite/encodings/tables/cp949.json create mode 100644 homework7/project_express/node_modules/iconv-lite/encodings/tables/cp950.json create mode 100644 homework7/project_express/node_modules/iconv-lite/encodings/tables/eucjp.json create mode 100644 homework7/project_express/node_modules/iconv-lite/encodings/tables/gb18030-ranges.json create mode 100644 homework7/project_express/node_modules/iconv-lite/encodings/tables/gbk-added.json create mode 100644 homework7/project_express/node_modules/iconv-lite/encodings/tables/shiftjis.json create mode 100644 homework7/project_express/node_modules/iconv-lite/encodings/utf16.js create mode 100644 homework7/project_express/node_modules/iconv-lite/encodings/utf7.js create mode 100644 homework7/project_express/node_modules/iconv-lite/lib/bom-handling.js create mode 100644 homework7/project_express/node_modules/iconv-lite/lib/extend-node.js create mode 100644 homework7/project_express/node_modules/iconv-lite/lib/index.d.ts create mode 100644 homework7/project_express/node_modules/iconv-lite/lib/index.js create mode 100644 homework7/project_express/node_modules/iconv-lite/lib/streams.js create mode 100644 homework7/project_express/node_modules/iconv-lite/package.json create mode 100644 homework7/project_express/node_modules/ignore-by-default/LICENSE create mode 100644 homework7/project_express/node_modules/ignore-by-default/README.md create mode 100644 homework7/project_express/node_modules/ignore-by-default/index.js create mode 100644 homework7/project_express/node_modules/ignore-by-default/package.json create mode 100644 homework7/project_express/node_modules/inherits/LICENSE create mode 100644 homework7/project_express/node_modules/inherits/README.md create mode 100644 homework7/project_express/node_modules/inherits/inherits.js create mode 100644 homework7/project_express/node_modules/inherits/inherits_browser.js create mode 100644 homework7/project_express/node_modules/inherits/package.json create mode 100644 homework7/project_express/node_modules/ipaddr.js/LICENSE create mode 100644 homework7/project_express/node_modules/ipaddr.js/README.md create mode 100644 homework7/project_express/node_modules/ipaddr.js/ipaddr.min.js create mode 100644 homework7/project_express/node_modules/ipaddr.js/lib/ipaddr.js create mode 100644 homework7/project_express/node_modules/ipaddr.js/lib/ipaddr.js.d.ts create mode 100644 homework7/project_express/node_modules/ipaddr.js/package.json create mode 100644 homework7/project_express/node_modules/is-binary-path/index.d.ts create mode 100644 homework7/project_express/node_modules/is-binary-path/index.js create mode 100644 homework7/project_express/node_modules/is-binary-path/license create mode 100644 homework7/project_express/node_modules/is-binary-path/package.json create mode 100644 homework7/project_express/node_modules/is-binary-path/readme.md create mode 100644 homework7/project_express/node_modules/is-extglob/LICENSE create mode 100644 homework7/project_express/node_modules/is-extglob/README.md create mode 100644 homework7/project_express/node_modules/is-extglob/index.js create mode 100644 homework7/project_express/node_modules/is-extglob/package.json create mode 100644 homework7/project_express/node_modules/is-glob/LICENSE create mode 100644 homework7/project_express/node_modules/is-glob/README.md create mode 100644 homework7/project_express/node_modules/is-glob/index.js create mode 100644 homework7/project_express/node_modules/is-glob/package.json create mode 100644 homework7/project_express/node_modules/is-number/LICENSE create mode 100644 homework7/project_express/node_modules/is-number/README.md create mode 100644 homework7/project_express/node_modules/is-number/index.js create mode 100644 homework7/project_express/node_modules/is-number/package.json create mode 100644 homework7/project_express/node_modules/media-typer/HISTORY.md create mode 100644 homework7/project_express/node_modules/media-typer/LICENSE create mode 100644 homework7/project_express/node_modules/media-typer/README.md create mode 100644 homework7/project_express/node_modules/media-typer/index.js create mode 100644 homework7/project_express/node_modules/media-typer/package.json create mode 100644 homework7/project_express/node_modules/merge-descriptors/HISTORY.md create mode 100644 homework7/project_express/node_modules/merge-descriptors/LICENSE create mode 100644 homework7/project_express/node_modules/merge-descriptors/README.md create mode 100644 homework7/project_express/node_modules/merge-descriptors/index.js create mode 100644 homework7/project_express/node_modules/merge-descriptors/package.json create mode 100644 homework7/project_express/node_modules/methods/HISTORY.md create mode 100644 homework7/project_express/node_modules/methods/LICENSE create mode 100644 homework7/project_express/node_modules/methods/README.md create mode 100644 homework7/project_express/node_modules/methods/index.js create mode 100644 homework7/project_express/node_modules/methods/package.json create mode 100644 homework7/project_express/node_modules/mime-db/HISTORY.md create mode 100644 homework7/project_express/node_modules/mime-db/LICENSE create mode 100644 homework7/project_express/node_modules/mime-db/README.md create mode 100644 homework7/project_express/node_modules/mime-db/db.json create mode 100644 homework7/project_express/node_modules/mime-db/index.js create mode 100644 homework7/project_express/node_modules/mime-db/package.json create mode 100644 homework7/project_express/node_modules/mime-types/HISTORY.md create mode 100644 homework7/project_express/node_modules/mime-types/LICENSE create mode 100644 homework7/project_express/node_modules/mime-types/README.md create mode 100644 homework7/project_express/node_modules/mime-types/index.js create mode 100644 homework7/project_express/node_modules/mime-types/package.json create mode 100644 homework7/project_express/node_modules/mime/.npmignore create mode 100644 homework7/project_express/node_modules/mime/CHANGELOG.md create mode 100644 homework7/project_express/node_modules/mime/LICENSE create mode 100644 homework7/project_express/node_modules/mime/README.md create mode 100644 homework7/project_express/node_modules/mime/cli.js create mode 100644 homework7/project_express/node_modules/mime/mime.js create mode 100644 homework7/project_express/node_modules/mime/package.json create mode 100644 homework7/project_express/node_modules/mime/src/build.js create mode 100644 homework7/project_express/node_modules/mime/src/test.js create mode 100644 homework7/project_express/node_modules/mime/types.json create mode 100644 homework7/project_express/node_modules/minimatch/LICENSE create mode 100644 homework7/project_express/node_modules/minimatch/README.md create mode 100644 homework7/project_express/node_modules/minimatch/minimatch.js create mode 100644 homework7/project_express/node_modules/minimatch/package.json create mode 100644 homework7/project_express/node_modules/ms/index.js create mode 100644 homework7/project_express/node_modules/ms/license.md create mode 100644 homework7/project_express/node_modules/ms/package.json create mode 100644 homework7/project_express/node_modules/ms/readme.md create mode 100644 homework7/project_express/node_modules/negotiator/HISTORY.md create mode 100644 homework7/project_express/node_modules/negotiator/LICENSE create mode 100644 homework7/project_express/node_modules/negotiator/README.md create mode 100644 homework7/project_express/node_modules/negotiator/index.js create mode 100644 homework7/project_express/node_modules/negotiator/lib/charset.js create mode 100644 homework7/project_express/node_modules/negotiator/lib/encoding.js create mode 100644 homework7/project_express/node_modules/negotiator/lib/language.js create mode 100644 homework7/project_express/node_modules/negotiator/lib/mediaType.js create mode 100644 homework7/project_express/node_modules/negotiator/package.json create mode 100644 homework7/project_express/node_modules/nodemon/LICENSE create mode 100644 homework7/project_express/node_modules/nodemon/README.md create mode 100644 homework7/project_express/node_modules/nodemon/bin/nodemon.js create mode 100644 homework7/project_express/node_modules/nodemon/bin/windows-kill.exe create mode 100644 homework7/project_express/node_modules/nodemon/doc/cli/authors.txt create mode 100644 homework7/project_express/node_modules/nodemon/doc/cli/config.txt create mode 100644 homework7/project_express/node_modules/nodemon/doc/cli/help.txt create mode 100644 homework7/project_express/node_modules/nodemon/doc/cli/logo.txt create mode 100644 homework7/project_express/node_modules/nodemon/doc/cli/options.txt create mode 100644 homework7/project_express/node_modules/nodemon/doc/cli/topics.txt create mode 100644 homework7/project_express/node_modules/nodemon/doc/cli/usage.txt create mode 100644 homework7/project_express/node_modules/nodemon/doc/cli/whoami.txt create mode 100644 homework7/project_express/node_modules/nodemon/lib/cli/index.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/cli/parse.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/config/command.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/config/defaults.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/config/exec.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/config/index.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/config/load.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/help/index.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/index.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/monitor/index.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/monitor/match.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/monitor/run.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/monitor/signals.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/monitor/watch.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/nodemon.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/rules/add.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/rules/index.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/rules/parse.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/spawn.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/utils/bus.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/utils/clone.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/utils/colour.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/utils/index.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/utils/log.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/utils/merge.js create mode 100644 homework7/project_express/node_modules/nodemon/lib/version.js create mode 100644 homework7/project_express/node_modules/nodemon/node_modules/debug/CHANGELOG.md create mode 100644 homework7/project_express/node_modules/nodemon/node_modules/debug/LICENSE create mode 100644 homework7/project_express/node_modules/nodemon/node_modules/debug/README.md create mode 100644 homework7/project_express/node_modules/nodemon/node_modules/debug/node.js create mode 100644 homework7/project_express/node_modules/nodemon/node_modules/debug/package.json create mode 100644 homework7/project_express/node_modules/nodemon/node_modules/debug/src/browser.js create mode 100644 homework7/project_express/node_modules/nodemon/node_modules/debug/src/common.js create mode 100644 homework7/project_express/node_modules/nodemon/node_modules/debug/src/index.js create mode 100644 homework7/project_express/node_modules/nodemon/node_modules/debug/src/node.js create mode 100644 homework7/project_express/node_modules/nodemon/node_modules/ms/index.js create mode 100644 homework7/project_express/node_modules/nodemon/node_modules/ms/license.md create mode 100644 homework7/project_express/node_modules/nodemon/node_modules/ms/package.json create mode 100644 homework7/project_express/node_modules/nodemon/node_modules/ms/readme.md create mode 100644 homework7/project_express/node_modules/nodemon/package.json create mode 100644 homework7/project_express/node_modules/nopt/.npmignore create mode 100644 homework7/project_express/node_modules/nopt/LICENSE create mode 100644 homework7/project_express/node_modules/nopt/README.md create mode 100644 homework7/project_express/node_modules/nopt/bin/nopt.js create mode 100644 homework7/project_express/node_modules/nopt/examples/my-program.js create mode 100644 homework7/project_express/node_modules/nopt/lib/nopt.js create mode 100644 homework7/project_express/node_modules/nopt/package.json create mode 100644 homework7/project_express/node_modules/normalize-path/LICENSE create mode 100644 homework7/project_express/node_modules/normalize-path/README.md create mode 100644 homework7/project_express/node_modules/normalize-path/index.js create mode 100644 homework7/project_express/node_modules/normalize-path/package.json create mode 100644 homework7/project_express/node_modules/on-finished/HISTORY.md create mode 100644 homework7/project_express/node_modules/on-finished/LICENSE create mode 100644 homework7/project_express/node_modules/on-finished/README.md create mode 100644 homework7/project_express/node_modules/on-finished/index.js create mode 100644 homework7/project_express/node_modules/on-finished/package.json create mode 100644 homework7/project_express/node_modules/optimist/.travis.yml create mode 100644 homework7/project_express/node_modules/optimist/LICENSE create mode 100644 homework7/project_express/node_modules/optimist/example/bool.js create mode 100644 homework7/project_express/node_modules/optimist/example/boolean_double.js create mode 100644 homework7/project_express/node_modules/optimist/example/boolean_single.js create mode 100644 homework7/project_express/node_modules/optimist/example/default_hash.js create mode 100644 homework7/project_express/node_modules/optimist/example/default_singles.js create mode 100644 homework7/project_express/node_modules/optimist/example/divide.js create mode 100644 homework7/project_express/node_modules/optimist/example/line_count.js create mode 100644 homework7/project_express/node_modules/optimist/example/line_count_options.js create mode 100644 homework7/project_express/node_modules/optimist/example/line_count_wrap.js create mode 100644 homework7/project_express/node_modules/optimist/example/nonopt.js create mode 100644 homework7/project_express/node_modules/optimist/example/reflect.js create mode 100644 homework7/project_express/node_modules/optimist/example/short.js create mode 100644 homework7/project_express/node_modules/optimist/example/string.js create mode 100644 homework7/project_express/node_modules/optimist/example/usage-options.js create mode 100644 homework7/project_express/node_modules/optimist/example/xup.js create mode 100644 homework7/project_express/node_modules/optimist/index.js create mode 100644 homework7/project_express/node_modules/optimist/package.json create mode 100644 homework7/project_express/node_modules/optimist/readme.markdown create mode 100644 homework7/project_express/node_modules/optimist/test/_.js create mode 100644 homework7/project_express/node_modules/optimist/test/_/argv.js create mode 100644 homework7/project_express/node_modules/optimist/test/_/bin.js create mode 100644 homework7/project_express/node_modules/optimist/test/parse.js create mode 100644 homework7/project_express/node_modules/optimist/test/usage.js create mode 100644 homework7/project_express/node_modules/parseurl/HISTORY.md create mode 100644 homework7/project_express/node_modules/parseurl/LICENSE create mode 100644 homework7/project_express/node_modules/parseurl/README.md create mode 100644 homework7/project_express/node_modules/parseurl/index.js create mode 100644 homework7/project_express/node_modules/parseurl/package.json create mode 100644 homework7/project_express/node_modules/path-to-regexp/History.md create mode 100644 homework7/project_express/node_modules/path-to-regexp/LICENSE create mode 100644 homework7/project_express/node_modules/path-to-regexp/Readme.md create mode 100644 homework7/project_express/node_modules/path-to-regexp/index.js create mode 100644 homework7/project_express/node_modules/path-to-regexp/package.json create mode 100644 homework7/project_express/node_modules/picomatch/CHANGELOG.md create mode 100644 homework7/project_express/node_modules/picomatch/LICENSE create mode 100644 homework7/project_express/node_modules/picomatch/README.md create mode 100644 homework7/project_express/node_modules/picomatch/index.js create mode 100644 homework7/project_express/node_modules/picomatch/lib/constants.js create mode 100644 homework7/project_express/node_modules/picomatch/lib/parse.js create mode 100644 homework7/project_express/node_modules/picomatch/lib/picomatch.js create mode 100644 homework7/project_express/node_modules/picomatch/lib/scan.js create mode 100644 homework7/project_express/node_modules/picomatch/lib/utils.js create mode 100644 homework7/project_express/node_modules/picomatch/package.json create mode 100644 homework7/project_express/node_modules/proxy-addr/HISTORY.md create mode 100644 homework7/project_express/node_modules/proxy-addr/LICENSE create mode 100644 homework7/project_express/node_modules/proxy-addr/README.md create mode 100644 homework7/project_express/node_modules/proxy-addr/index.js create mode 100644 homework7/project_express/node_modules/proxy-addr/package.json create mode 100644 homework7/project_express/node_modules/pstree.remy/.travis.yml create mode 100644 homework7/project_express/node_modules/pstree.remy/LICENSE create mode 100644 homework7/project_express/node_modules/pstree.remy/README.md create mode 100644 homework7/project_express/node_modules/pstree.remy/lib/index.js create mode 100644 homework7/project_express/node_modules/pstree.remy/lib/tree.js create mode 100644 homework7/project_express/node_modules/pstree.remy/lib/utils.js create mode 100644 homework7/project_express/node_modules/pstree.remy/package.json create mode 100644 homework7/project_express/node_modules/pstree.remy/tests/fixtures/index.js create mode 100644 homework7/project_express/node_modules/pstree.remy/tests/fixtures/out1 create mode 100644 homework7/project_express/node_modules/pstree.remy/tests/fixtures/out2 create mode 100644 homework7/project_express/node_modules/pstree.remy/tests/index.test.js create mode 100644 homework7/project_express/node_modules/qs/.editorconfig create mode 100644 homework7/project_express/node_modules/qs/.eslintignore create mode 100644 homework7/project_express/node_modules/qs/.eslintrc create mode 100644 homework7/project_express/node_modules/qs/CHANGELOG.md create mode 100644 homework7/project_express/node_modules/qs/LICENSE create mode 100644 homework7/project_express/node_modules/qs/README.md create mode 100644 homework7/project_express/node_modules/qs/dist/qs.js create mode 100644 homework7/project_express/node_modules/qs/lib/formats.js create mode 100644 homework7/project_express/node_modules/qs/lib/index.js create mode 100644 homework7/project_express/node_modules/qs/lib/parse.js create mode 100644 homework7/project_express/node_modules/qs/lib/stringify.js create mode 100644 homework7/project_express/node_modules/qs/lib/utils.js create mode 100644 homework7/project_express/node_modules/qs/package.json create mode 100644 homework7/project_express/node_modules/qs/test/.eslintrc create mode 100644 homework7/project_express/node_modules/qs/test/index.js create mode 100644 homework7/project_express/node_modules/qs/test/parse.js create mode 100644 homework7/project_express/node_modules/qs/test/stringify.js create mode 100644 homework7/project_express/node_modules/qs/test/utils.js create mode 100644 homework7/project_express/node_modules/range-parser/HISTORY.md create mode 100644 homework7/project_express/node_modules/range-parser/LICENSE create mode 100644 homework7/project_express/node_modules/range-parser/README.md create mode 100644 homework7/project_express/node_modules/range-parser/index.js create mode 100644 homework7/project_express/node_modules/range-parser/package.json create mode 100644 homework7/project_express/node_modules/raw-body/HISTORY.md create mode 100644 homework7/project_express/node_modules/raw-body/LICENSE create mode 100644 homework7/project_express/node_modules/raw-body/README.md create mode 100644 homework7/project_express/node_modules/raw-body/index.d.ts create mode 100644 homework7/project_express/node_modules/raw-body/index.js create mode 100644 homework7/project_express/node_modules/raw-body/package.json create mode 100644 homework7/project_express/node_modules/readdirp/LICENSE create mode 100644 homework7/project_express/node_modules/readdirp/README.md create mode 100644 homework7/project_express/node_modules/readdirp/index.d.ts create mode 100644 homework7/project_express/node_modules/readdirp/index.js create mode 100644 homework7/project_express/node_modules/readdirp/package.json create mode 100644 homework7/project_express/node_modules/require/.npmignore create mode 100644 homework7/project_express/node_modules/require/Changelog create mode 100644 homework7/project_express/node_modules/require/LICENSE create mode 100644 homework7/project_express/node_modules/require/README.md create mode 100644 homework7/project_express/node_modules/require/bin/require-command.js create mode 100644 homework7/project_express/node_modules/require/compiler.js create mode 100644 homework7/project_express/node_modules/require/example/client.js create mode 100644 homework7/project_express/node_modules/require/example/compile.js create mode 100644 homework7/project_express/node_modules/require/example/connect.js create mode 100644 homework7/project_express/node_modules/require/example/index.html create mode 100644 homework7/project_express/node_modules/require/example/package.json create mode 100644 homework7/project_express/node_modules/require/example/raphael_circle.html create mode 100644 homework7/project_express/node_modules/require/example/raphael_circle.js create mode 100644 homework7/project_express/node_modules/require/example/server.js create mode 100644 homework7/project_express/node_modules/require/example/shared/dependency.js create mode 100644 homework7/project_express/node_modules/require/lib/getCode.js create mode 100644 homework7/project_express/node_modules/require/lib/getDependencyLevels.js create mode 100644 homework7/project_express/node_modules/require/lib/getRequireStatements.js create mode 100644 homework7/project_express/node_modules/require/lib/resolve.js create mode 100644 homework7/project_express/node_modules/require/package.json create mode 100644 homework7/project_express/node_modules/require/server.js create mode 100644 homework7/project_express/node_modules/safe-buffer/LICENSE create mode 100644 homework7/project_express/node_modules/safe-buffer/README.md create mode 100644 homework7/project_express/node_modules/safe-buffer/index.d.ts create mode 100644 homework7/project_express/node_modules/safe-buffer/index.js create mode 100644 homework7/project_express/node_modules/safe-buffer/package.json create mode 100644 homework7/project_express/node_modules/safer-buffer/LICENSE create mode 100644 homework7/project_express/node_modules/safer-buffer/Porting-Buffer.md create mode 100644 homework7/project_express/node_modules/safer-buffer/Readme.md create mode 100644 homework7/project_express/node_modules/safer-buffer/dangerous.js create mode 100644 homework7/project_express/node_modules/safer-buffer/package.json create mode 100644 homework7/project_express/node_modules/safer-buffer/safer.js create mode 100644 homework7/project_express/node_modules/safer-buffer/tests.js create mode 100644 homework7/project_express/node_modules/semver/CHANGELOG.md create mode 100644 homework7/project_express/node_modules/semver/LICENSE create mode 100644 homework7/project_express/node_modules/semver/README.md create mode 100644 homework7/project_express/node_modules/semver/bin/semver create mode 100644 homework7/project_express/node_modules/semver/package.json create mode 100644 homework7/project_express/node_modules/semver/range.bnf create mode 100644 homework7/project_express/node_modules/semver/semver.js create mode 100644 homework7/project_express/node_modules/send/HISTORY.md create mode 100644 homework7/project_express/node_modules/send/LICENSE create mode 100644 homework7/project_express/node_modules/send/README.md create mode 100644 homework7/project_express/node_modules/send/index.js create mode 100644 homework7/project_express/node_modules/send/node_modules/ms/index.js create mode 100644 homework7/project_express/node_modules/send/node_modules/ms/license.md create mode 100644 homework7/project_express/node_modules/send/node_modules/ms/package.json create mode 100644 homework7/project_express/node_modules/send/node_modules/ms/readme.md create mode 100644 homework7/project_express/node_modules/send/package.json create mode 100644 homework7/project_express/node_modules/serve-static/HISTORY.md create mode 100644 homework7/project_express/node_modules/serve-static/LICENSE create mode 100644 homework7/project_express/node_modules/serve-static/README.md create mode 100644 homework7/project_express/node_modules/serve-static/index.js create mode 100644 homework7/project_express/node_modules/serve-static/package.json create mode 100644 homework7/project_express/node_modules/setprototypeof/LICENSE create mode 100644 homework7/project_express/node_modules/setprototypeof/README.md create mode 100644 homework7/project_express/node_modules/setprototypeof/index.d.ts create mode 100644 homework7/project_express/node_modules/setprototypeof/index.js create mode 100644 homework7/project_express/node_modules/setprototypeof/package.json create mode 100644 homework7/project_express/node_modules/setprototypeof/test/index.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/LICENSE create mode 100644 homework7/project_express/node_modules/simple-update-notifier/README.md create mode 100644 homework7/project_express/node_modules/simple-update-notifier/build/index.d.ts create mode 100644 homework7/project_express/node_modules/simple-update-notifier/build/index.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver.cmd create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver.ps1 create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/CHANGELOG.md create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/LICENSE create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/README.md create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/bin/semver.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/comparator.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/index.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/range.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/semver.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/clean.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/cmp.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/coerce.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare-build.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare-loose.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/diff.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/eq.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/gt.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/gte.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/inc.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/lt.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/lte.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/major.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/minor.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/neq.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/parse.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/patch.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/prerelease.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/rcompare.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/rsort.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/satisfies.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/sort.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/valid.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/index.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/constants.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/debug.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/identifiers.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/re.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/package.json create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/range.bnf create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/gtr.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/intersects.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/ltr.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/max-satisfying.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/min-satisfying.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/min-version.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/outside.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/to-comparators.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/valid.js create mode 100644 homework7/project_express/node_modules/simple-update-notifier/package.json create mode 100644 homework7/project_express/node_modules/simple-update-notifier/src/borderedText.ts create mode 100644 homework7/project_express/node_modules/simple-update-notifier/src/cache.spec.ts create mode 100644 homework7/project_express/node_modules/simple-update-notifier/src/cache.ts create mode 100644 homework7/project_express/node_modules/simple-update-notifier/src/getDistVersion.spec.ts create mode 100644 homework7/project_express/node_modules/simple-update-notifier/src/getDistVersion.ts create mode 100644 homework7/project_express/node_modules/simple-update-notifier/src/hasNewVersion.spec.ts create mode 100644 homework7/project_express/node_modules/simple-update-notifier/src/hasNewVersion.ts create mode 100644 homework7/project_express/node_modules/simple-update-notifier/src/index.spec.ts create mode 100644 homework7/project_express/node_modules/simple-update-notifier/src/index.ts create mode 100644 homework7/project_express/node_modules/simple-update-notifier/src/isNpmOrYarn.ts create mode 100644 homework7/project_express/node_modules/simple-update-notifier/src/types.ts create mode 100644 homework7/project_express/node_modules/source-map/.npmignore create mode 100644 homework7/project_express/node_modules/source-map/.travis.yml create mode 100644 homework7/project_express/node_modules/source-map/CHANGELOG.md create mode 100644 homework7/project_express/node_modules/source-map/LICENSE create mode 100644 homework7/project_express/node_modules/source-map/Makefile.dryice.js create mode 100644 homework7/project_express/node_modules/source-map/README.md create mode 100644 homework7/project_express/node_modules/source-map/build/assert-shim.js create mode 100644 homework7/project_express/node_modules/source-map/build/mini-require.js create mode 100644 homework7/project_express/node_modules/source-map/build/prefix-source-map.jsm create mode 100644 homework7/project_express/node_modules/source-map/build/prefix-utils.jsm create mode 100644 homework7/project_express/node_modules/source-map/build/suffix-browser.js create mode 100644 homework7/project_express/node_modules/source-map/build/suffix-source-map.jsm create mode 100644 homework7/project_express/node_modules/source-map/build/suffix-utils.jsm create mode 100644 homework7/project_express/node_modules/source-map/build/test-prefix.js create mode 100644 homework7/project_express/node_modules/source-map/build/test-suffix.js create mode 100644 homework7/project_express/node_modules/source-map/lib/source-map.js create mode 100644 homework7/project_express/node_modules/source-map/lib/source-map/array-set.js create mode 100644 homework7/project_express/node_modules/source-map/lib/source-map/base64-vlq.js create mode 100644 homework7/project_express/node_modules/source-map/lib/source-map/base64.js create mode 100644 homework7/project_express/node_modules/source-map/lib/source-map/binary-search.js create mode 100644 homework7/project_express/node_modules/source-map/lib/source-map/mapping-list.js create mode 100644 homework7/project_express/node_modules/source-map/lib/source-map/source-map-consumer.js create mode 100644 homework7/project_express/node_modules/source-map/lib/source-map/source-map-generator.js create mode 100644 homework7/project_express/node_modules/source-map/lib/source-map/source-node.js create mode 100644 homework7/project_express/node_modules/source-map/lib/source-map/util.js create mode 100644 homework7/project_express/node_modules/source-map/package.json create mode 100644 homework7/project_express/node_modules/source-map/test/run-tests.js create mode 100644 homework7/project_express/node_modules/source-map/test/source-map/test-api.js create mode 100644 homework7/project_express/node_modules/source-map/test/source-map/test-array-set.js create mode 100644 homework7/project_express/node_modules/source-map/test/source-map/test-base64-vlq.js create mode 100644 homework7/project_express/node_modules/source-map/test/source-map/test-base64.js create mode 100644 homework7/project_express/node_modules/source-map/test/source-map/test-binary-search.js create mode 100644 homework7/project_express/node_modules/source-map/test/source-map/test-dog-fooding.js create mode 100644 homework7/project_express/node_modules/source-map/test/source-map/test-source-map-consumer.js create mode 100644 homework7/project_express/node_modules/source-map/test/source-map/test-source-map-generator.js create mode 100644 homework7/project_express/node_modules/source-map/test/source-map/test-source-node.js create mode 100644 homework7/project_express/node_modules/source-map/test/source-map/test-util.js create mode 100644 homework7/project_express/node_modules/source-map/test/source-map/util.js create mode 100644 homework7/project_express/node_modules/statuses/HISTORY.md create mode 100644 homework7/project_express/node_modules/statuses/LICENSE create mode 100644 homework7/project_express/node_modules/statuses/README.md create mode 100644 homework7/project_express/node_modules/statuses/codes.json create mode 100644 homework7/project_express/node_modules/statuses/index.js create mode 100644 homework7/project_express/node_modules/statuses/package.json create mode 100644 homework7/project_express/node_modules/std/Animation.js create mode 100644 homework7/project_express/node_modules/std/Changelog create mode 100644 homework7/project_express/node_modules/std/Class.js create mode 100644 homework7/project_express/node_modules/std/LICENSE create mode 100644 homework7/project_express/node_modules/std/ListPromise.js create mode 100644 homework7/project_express/node_modules/std/Logger.js create mode 100644 homework7/project_express/node_modules/std/Promise.js create mode 100644 homework7/project_express/node_modules/std/Publisher.js create mode 100644 homework7/project_express/node_modules/std/README.md create mode 100644 homework7/project_express/node_modules/std/arrayToObject.js create mode 100644 homework7/project_express/node_modules/std/assert/deepEqual.js create mode 100644 homework7/project_express/node_modules/std/asyncEach.js create mode 100644 homework7/project_express/node_modules/std/asyncMap.js create mode 100644 homework7/project_express/node_modules/std/base64.js create mode 100644 homework7/project_express/node_modules/std/bind.js create mode 100644 homework7/project_express/node_modules/std/blockFunction.js create mode 100644 homework7/project_express/node_modules/std/browser.js create mode 100644 homework7/project_express/node_modules/std/check.js create mode 100644 homework7/project_express/node_modules/std/client.js create mode 100644 homework7/project_express/node_modules/std/clip.js create mode 100644 homework7/project_express/node_modules/std/cookie.js create mode 100644 homework7/project_express/node_modules/std/copy.js create mode 100644 homework7/project_express/node_modules/std/crc32.js create mode 100644 homework7/project_express/node_modules/std/create.js create mode 100644 homework7/project_express/node_modules/std/curry.js create mode 100644 homework7/project_express/node_modules/std/defineGetter.js create mode 100644 homework7/project_express/node_modules/std/delay.js create mode 100644 homework7/project_express/node_modules/std/delayed.js create mode 100644 homework7/project_express/node_modules/std/each.js create mode 100644 homework7/project_express/node_modules/std/extend.js create mode 100644 homework7/project_express/node_modules/std/filter.js create mode 100644 homework7/project_express/node_modules/std/find.js create mode 100644 homework7/project_express/node_modules/std/flatten.js create mode 100644 homework7/project_express/node_modules/std/flip.js create mode 100644 homework7/project_express/node_modules/std/index.js create mode 100644 homework7/project_express/node_modules/std/inverse.js create mode 100644 homework7/project_express/node_modules/std/invoke.js create mode 100644 homework7/project_express/node_modules/std/invokeWith.js create mode 100644 homework7/project_express/node_modules/std/isArguments.js create mode 100644 homework7/project_express/node_modules/std/isArray.js create mode 100644 homework7/project_express/node_modules/std/isFunction.js create mode 100644 homework7/project_express/node_modules/std/isObject.js create mode 100644 homework7/project_express/node_modules/std/json.js create mode 100644 homework7/project_express/node_modules/std/keys.js create mode 100644 homework7/project_express/node_modules/std/last.js create mode 100644 homework7/project_express/node_modules/std/map.js create mode 100644 homework7/project_express/node_modules/std/merge.js create mode 100644 homework7/project_express/node_modules/std/nextTick.js create mode 100644 homework7/project_express/node_modules/std/once.js create mode 100644 homework7/project_express/node_modules/std/options.js create mode 100644 homework7/project_express/node_modules/std/pack.js create mode 100644 homework7/project_express/node_modules/std/package.json create mode 100644 homework7/project_express/node_modules/std/parallel.js create mode 100644 homework7/project_express/node_modules/std/popup.js create mode 100644 homework7/project_express/node_modules/std/proto.js create mode 100644 homework7/project_express/node_modules/std/rand.js create mode 100644 homework7/project_express/node_modules/std/recall.js create mode 100644 homework7/project_express/node_modules/std/remove.js create mode 100644 homework7/project_express/node_modules/std/repeat.js create mode 100644 homework7/project_express/node_modules/std/round.js create mode 100644 homework7/project_express/node_modules/std/router.js create mode 100644 homework7/project_express/node_modules/std/slice.js create mode 100644 homework7/project_express/node_modules/std/strip.js create mode 100644 homework7/project_express/node_modules/std/sum.js create mode 100644 homework7/project_express/node_modules/std/throttle.js create mode 100644 homework7/project_express/node_modules/std/time.js create mode 100644 homework7/project_express/node_modules/std/trim.js create mode 100644 homework7/project_express/node_modules/std/unique.js create mode 100644 homework7/project_express/node_modules/std/unpack.js create mode 100644 homework7/project_express/node_modules/std/url.js create mode 100644 homework7/project_express/node_modules/std/utf8_encode.js create mode 100644 homework7/project_express/node_modules/std/waitFor.js create mode 100644 homework7/project_express/node_modules/std/xhr.js create mode 100644 homework7/project_express/node_modules/supports-color/browser.js create mode 100644 homework7/project_express/node_modules/supports-color/index.js create mode 100644 homework7/project_express/node_modules/supports-color/license create mode 100644 homework7/project_express/node_modules/supports-color/package.json create mode 100644 homework7/project_express/node_modules/supports-color/readme.md create mode 100644 homework7/project_express/node_modules/to-regex-range/LICENSE create mode 100644 homework7/project_express/node_modules/to-regex-range/README.md create mode 100644 homework7/project_express/node_modules/to-regex-range/index.js create mode 100644 homework7/project_express/node_modules/to-regex-range/package.json create mode 100644 homework7/project_express/node_modules/toidentifier/LICENSE create mode 100644 homework7/project_express/node_modules/toidentifier/README.md create mode 100644 homework7/project_express/node_modules/toidentifier/index.js create mode 100644 homework7/project_express/node_modules/toidentifier/package.json create mode 100644 homework7/project_express/node_modules/touch/LICENSE create mode 100644 homework7/project_express/node_modules/touch/README.md create mode 100644 homework7/project_express/node_modules/touch/bin/nodetouch.js create mode 100644 homework7/project_express/node_modules/touch/index.js create mode 100644 homework7/project_express/node_modules/touch/package.json create mode 100644 homework7/project_express/node_modules/type-is/HISTORY.md create mode 100644 homework7/project_express/node_modules/type-is/LICENSE create mode 100644 homework7/project_express/node_modules/type-is/README.md create mode 100644 homework7/project_express/node_modules/type-is/index.js create mode 100644 homework7/project_express/node_modules/type-is/package.json create mode 100644 homework7/project_express/node_modules/uglify-js/.npmignore create mode 100644 homework7/project_express/node_modules/uglify-js/LICENSE create mode 100644 homework7/project_express/node_modules/uglify-js/README.md create mode 100644 homework7/project_express/node_modules/uglify-js/bin/uglifyjs create mode 100644 homework7/project_express/node_modules/uglify-js/lib/ast.js create mode 100644 homework7/project_express/node_modules/uglify-js/lib/compress.js create mode 100644 homework7/project_express/node_modules/uglify-js/lib/mozilla-ast.js create mode 100644 homework7/project_express/node_modules/uglify-js/lib/output.js create mode 100644 homework7/project_express/node_modules/uglify-js/lib/parse.js create mode 100644 homework7/project_express/node_modules/uglify-js/lib/scope.js create mode 100644 homework7/project_express/node_modules/uglify-js/lib/sourcemap.js create mode 100644 homework7/project_express/node_modules/uglify-js/lib/transform.js create mode 100644 homework7/project_express/node_modules/uglify-js/lib/utils.js create mode 100644 homework7/project_express/node_modules/uglify-js/package.json create mode 100644 homework7/project_express/node_modules/uglify-js/test/compress/arrays.js create mode 100644 homework7/project_express/node_modules/uglify-js/test/compress/blocks.js create mode 100644 homework7/project_express/node_modules/uglify-js/test/compress/conditionals.js create mode 100644 homework7/project_express/node_modules/uglify-js/test/compress/dead-code.js create mode 100644 homework7/project_express/node_modules/uglify-js/test/compress/debugger.js create mode 100644 homework7/project_express/node_modules/uglify-js/test/compress/drop-unused.js create mode 100644 homework7/project_express/node_modules/uglify-js/test/compress/issue-105.js create mode 100644 homework7/project_express/node_modules/uglify-js/test/compress/issue-12.js create mode 100644 homework7/project_express/node_modules/uglify-js/test/compress/issue-22.js create mode 100644 homework7/project_express/node_modules/uglify-js/test/compress/issue-44.js create mode 100644 homework7/project_express/node_modules/uglify-js/test/compress/issue-59.js create mode 100644 homework7/project_express/node_modules/uglify-js/test/compress/labels.js create mode 100644 homework7/project_express/node_modules/uglify-js/test/compress/loops.js create mode 100644 homework7/project_express/node_modules/uglify-js/test/compress/properties.js create mode 100644 homework7/project_express/node_modules/uglify-js/test/compress/sequences.js create mode 100644 homework7/project_express/node_modules/uglify-js/test/compress/switch.js create mode 100644 homework7/project_express/node_modules/uglify-js/test/compress/typeof.js create mode 100644 homework7/project_express/node_modules/uglify-js/test/run-tests.js create mode 100644 homework7/project_express/node_modules/uglify-js/tools/node.js create mode 100644 homework7/project_express/node_modules/undefsafe/.github/workflows/release.yml create mode 100644 homework7/project_express/node_modules/undefsafe/.jscsrc create mode 100644 homework7/project_express/node_modules/undefsafe/.jshintrc create mode 100644 homework7/project_express/node_modules/undefsafe/.travis.yml create mode 100644 homework7/project_express/node_modules/undefsafe/LICENSE create mode 100644 homework7/project_express/node_modules/undefsafe/README.md create mode 100644 homework7/project_express/node_modules/undefsafe/example.js create mode 100644 homework7/project_express/node_modules/undefsafe/lib/undefsafe.js create mode 100644 homework7/project_express/node_modules/undefsafe/package.json create mode 100644 homework7/project_express/node_modules/unpipe/HISTORY.md create mode 100644 homework7/project_express/node_modules/unpipe/LICENSE create mode 100644 homework7/project_express/node_modules/unpipe/README.md create mode 100644 homework7/project_express/node_modules/unpipe/index.js create mode 100644 homework7/project_express/node_modules/unpipe/package.json create mode 100644 homework7/project_express/node_modules/utils-merge/.npmignore create mode 100644 homework7/project_express/node_modules/utils-merge/LICENSE create mode 100644 homework7/project_express/node_modules/utils-merge/README.md create mode 100644 homework7/project_express/node_modules/utils-merge/index.js create mode 100644 homework7/project_express/node_modules/utils-merge/package.json create mode 100644 homework7/project_express/node_modules/vary/HISTORY.md create mode 100644 homework7/project_express/node_modules/vary/LICENSE create mode 100644 homework7/project_express/node_modules/vary/README.md create mode 100644 homework7/project_express/node_modules/vary/index.js create mode 100644 homework7/project_express/node_modules/vary/package.json create mode 100644 homework7/project_express/node_modules/wordwrap/LICENSE create mode 100644 homework7/project_express/node_modules/wordwrap/README.markdown create mode 100644 homework7/project_express/node_modules/wordwrap/example/center.js create mode 100644 homework7/project_express/node_modules/wordwrap/example/meat.js create mode 100644 homework7/project_express/node_modules/wordwrap/index.js create mode 100644 homework7/project_express/node_modules/wordwrap/package.json create mode 100644 homework7/project_express/node_modules/wordwrap/test/break.js create mode 100644 homework7/project_express/node_modules/wordwrap/test/idleness.txt create mode 100644 homework7/project_express/node_modules/wordwrap/test/wrap.js create mode 100644 homework7/project_express/package-lock.json create mode 100644 homework7/project_express/package.json create mode 100644 homework7/project_express/public/copy/js/CartComponent.js create mode 100644 homework7/project_express/public/copy/js/ErrorComp.js create mode 100644 homework7/project_express/public/copy/js/FilterComp.js create mode 100644 homework7/project_express/public/copy/js/ProductComponent.js create mode 100644 homework7/project_express/public/copy/js/main.js create mode 100644 homework7/project_express/public/css/images/subscribe.jpg create mode 100644 homework7/project_express/public/css/normalize.css create mode 100644 homework7/project_express/public/css/style.css create mode 100644 homework7/project_express/public/images/bars.png create mode 100644 homework7/project_express/public/images/cart.png create mode 100644 homework7/project_express/public/images/cart.svg create mode 100644 homework7/project_express/public/images/chevronLeft.svg create mode 100644 homework7/project_express/public/images/chevronRight.svg create mode 100644 homework7/project_express/public/images/featured/1.jpg create mode 100644 homework7/project_express/public/images/featured/2.jpg create mode 100644 homework7/project_express/public/images/featured/3.jpg create mode 100644 homework7/project_express/public/images/featured/4.jpg create mode 100644 homework7/project_express/public/images/featured/5.jpg create mode 100644 homework7/project_express/public/images/featured/6.jpg create mode 100644 homework7/project_express/public/images/filter.svg create mode 100644 homework7/project_express/public/images/filterArrow.svg create mode 100644 homework7/project_express/public/images/filterHover.svg create mode 100644 homework7/project_express/public/images/logo.png create mode 100644 homework7/project_express/public/images/search.png create mode 100644 homework7/project_express/public/images/services/assurance.svg create mode 100644 homework7/project_express/public/images/services/delivery.svg create mode 100644 homework7/project_express/public/images/services/discount.svg create mode 100644 homework7/project_express/public/images/subscribe.jpg create mode 100644 homework7/project_express/public/images/subscribeUser.png create mode 100644 homework7/project_express/public/images/user.png create mode 100644 homework7/project_express/public/index.html create mode 100644 homework7/project_express/public/js/main.js create mode 100644 homework7/project_express/public/js/mycartComponent.js create mode 100644 homework7/project_express/public/js/myproductComponent.js create mode 100644 homework7/project_express/server/cart.js create mode 100644 homework7/project_express/server/cartRouter.js create mode 100644 homework7/project_express/server/db/products.json create mode 100644 homework7/project_express/server/db/userCart.json create mode 100644 homework7/project_express/server/handler.js create mode 100644 homework7/project_express/server/server.js diff --git a/homework7/project_express/.idea/.gitignore b/homework7/project_express/.idea/.gitignore new file mode 100644 index 0000000..73f69e0 --- /dev/null +++ b/homework7/project_express/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/homework7/project_express/.idea/jsLibraryMappings.xml b/homework7/project_express/.idea/jsLibraryMappings.xml new file mode 100644 index 0000000..d23208f --- /dev/null +++ b/homework7/project_express/.idea/jsLibraryMappings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/homework7/project_express/.idea/misc.xml b/homework7/project_express/.idea/misc.xml new file mode 100644 index 0000000..28a804d --- /dev/null +++ b/homework7/project_express/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/homework7/project_express/.idea/modules.xml b/homework7/project_express/.idea/modules.xml new file mode 100644 index 0000000..4875f51 --- /dev/null +++ b/homework7/project_express/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/homework7/project_express/.idea/project_express.iml b/homework7/project_express/.idea/project_express.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/homework7/project_express/.idea/project_express.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/homework7/project_express/node_modules/.bin/mime b/homework7/project_express/node_modules/.bin/mime new file mode 100644 index 0000000..91e5e16 --- /dev/null +++ b/homework7/project_express/node_modules/.bin/mime @@ -0,0 +1,15 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; +esac + +if [ -x "$basedir/node" ]; then + "$basedir/node" "$basedir/../mime/cli.js" "$@" + ret=$? +else + node "$basedir/../mime/cli.js" "$@" + ret=$? +fi +exit $ret diff --git a/homework7/project_express/node_modules/.bin/mime.cmd b/homework7/project_express/node_modules/.bin/mime.cmd new file mode 100644 index 0000000..746a279 --- /dev/null +++ b/homework7/project_express/node_modules/.bin/mime.cmd @@ -0,0 +1,17 @@ +@ECHO off +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +"%_prog%" "%dp0%\..\mime\cli.js" %* +ENDLOCAL +EXIT /b %errorlevel% +:find_dp0 +SET dp0=%~dp0 +EXIT /b diff --git a/homework7/project_express/node_modules/.bin/mime.ps1 b/homework7/project_express/node_modules/.bin/mime.ps1 new file mode 100644 index 0000000..a6f6f47 --- /dev/null +++ b/homework7/project_express/node_modules/.bin/mime.ps1 @@ -0,0 +1,18 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + & "$basedir/node$exe" "$basedir/../mime/cli.js" $args + $ret=$LASTEXITCODE +} else { + & "node$exe" "$basedir/../mime/cli.js" $args + $ret=$LASTEXITCODE +} +exit $ret diff --git a/homework7/project_express/node_modules/.bin/nodemon b/homework7/project_express/node_modules/.bin/nodemon new file mode 100644 index 0000000..4d75661 --- /dev/null +++ b/homework7/project_express/node_modules/.bin/nodemon @@ -0,0 +1,12 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../nodemon/bin/nodemon.js" "$@" +else + exec node "$basedir/../nodemon/bin/nodemon.js" "$@" +fi diff --git a/homework7/project_express/node_modules/.bin/nodemon.cmd b/homework7/project_express/node_modules/.bin/nodemon.cmd new file mode 100644 index 0000000..55acf8a --- /dev/null +++ b/homework7/project_express/node_modules/.bin/nodemon.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\nodemon\bin\nodemon.js" %* diff --git a/homework7/project_express/node_modules/.bin/nodemon.ps1 b/homework7/project_express/node_modules/.bin/nodemon.ps1 new file mode 100644 index 0000000..d4e3f5d --- /dev/null +++ b/homework7/project_express/node_modules/.bin/nodemon.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../nodemon/bin/nodemon.js" $args + } else { + & "$basedir/node$exe" "$basedir/../nodemon/bin/nodemon.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../nodemon/bin/nodemon.js" $args + } else { + & "node$exe" "$basedir/../nodemon/bin/nodemon.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/homework7/project_express/node_modules/.bin/nodetouch b/homework7/project_express/node_modules/.bin/nodetouch new file mode 100644 index 0000000..03f8b4d --- /dev/null +++ b/homework7/project_express/node_modules/.bin/nodetouch @@ -0,0 +1,12 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../touch/bin/nodetouch.js" "$@" +else + exec node "$basedir/../touch/bin/nodetouch.js" "$@" +fi diff --git a/homework7/project_express/node_modules/.bin/nodetouch.cmd b/homework7/project_express/node_modules/.bin/nodetouch.cmd new file mode 100644 index 0000000..8298b91 --- /dev/null +++ b/homework7/project_express/node_modules/.bin/nodetouch.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\touch\bin\nodetouch.js" %* diff --git a/homework7/project_express/node_modules/.bin/nodetouch.ps1 b/homework7/project_express/node_modules/.bin/nodetouch.ps1 new file mode 100644 index 0000000..5f68b4c --- /dev/null +++ b/homework7/project_express/node_modules/.bin/nodetouch.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../touch/bin/nodetouch.js" $args + } else { + & "$basedir/node$exe" "$basedir/../touch/bin/nodetouch.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../touch/bin/nodetouch.js" $args + } else { + & "node$exe" "$basedir/../touch/bin/nodetouch.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/homework7/project_express/node_modules/.bin/nopt b/homework7/project_express/node_modules/.bin/nopt new file mode 100644 index 0000000..f1ec43b --- /dev/null +++ b/homework7/project_express/node_modules/.bin/nopt @@ -0,0 +1,12 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../nopt/bin/nopt.js" "$@" +else + exec node "$basedir/../nopt/bin/nopt.js" "$@" +fi diff --git a/homework7/project_express/node_modules/.bin/nopt.cmd b/homework7/project_express/node_modules/.bin/nopt.cmd new file mode 100644 index 0000000..a7f38b3 --- /dev/null +++ b/homework7/project_express/node_modules/.bin/nopt.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\nopt\bin\nopt.js" %* diff --git a/homework7/project_express/node_modules/.bin/nopt.ps1 b/homework7/project_express/node_modules/.bin/nopt.ps1 new file mode 100644 index 0000000..9d6ba56 --- /dev/null +++ b/homework7/project_express/node_modules/.bin/nopt.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../nopt/bin/nopt.js" $args + } else { + & "$basedir/node$exe" "$basedir/../nopt/bin/nopt.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../nopt/bin/nopt.js" $args + } else { + & "node$exe" "$basedir/../nopt/bin/nopt.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/homework7/project_express/node_modules/.bin/require b/homework7/project_express/node_modules/.bin/require new file mode 100644 index 0000000..f2aed69 --- /dev/null +++ b/homework7/project_express/node_modules/.bin/require @@ -0,0 +1,12 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../require/bin/require-command.js" "$@" +else + exec node "$basedir/../require/bin/require-command.js" "$@" +fi diff --git a/homework7/project_express/node_modules/.bin/require.cmd b/homework7/project_express/node_modules/.bin/require.cmd new file mode 100644 index 0000000..ffa7894 --- /dev/null +++ b/homework7/project_express/node_modules/.bin/require.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\require\bin\require-command.js" %* diff --git a/homework7/project_express/node_modules/.bin/require.ps1 b/homework7/project_express/node_modules/.bin/require.ps1 new file mode 100644 index 0000000..ee58c8f --- /dev/null +++ b/homework7/project_express/node_modules/.bin/require.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../require/bin/require-command.js" $args + } else { + & "$basedir/node$exe" "$basedir/../require/bin/require-command.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../require/bin/require-command.js" $args + } else { + & "node$exe" "$basedir/../require/bin/require-command.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/homework7/project_express/node_modules/.bin/semver b/homework7/project_express/node_modules/.bin/semver new file mode 100644 index 0000000..86cee84 --- /dev/null +++ b/homework7/project_express/node_modules/.bin/semver @@ -0,0 +1,12 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../semver/bin/semver" "$@" +else + exec node "$basedir/../semver/bin/semver" "$@" +fi diff --git a/homework7/project_express/node_modules/.bin/semver.cmd b/homework7/project_express/node_modules/.bin/semver.cmd new file mode 100644 index 0000000..22d9286 --- /dev/null +++ b/homework7/project_express/node_modules/.bin/semver.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\semver\bin\semver" %* diff --git a/homework7/project_express/node_modules/.bin/semver.ps1 b/homework7/project_express/node_modules/.bin/semver.ps1 new file mode 100644 index 0000000..98c1b09 --- /dev/null +++ b/homework7/project_express/node_modules/.bin/semver.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../semver/bin/semver" $args + } else { + & "$basedir/node$exe" "$basedir/../semver/bin/semver" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../semver/bin/semver" $args + } else { + & "node$exe" "$basedir/../semver/bin/semver" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/homework7/project_express/node_modules/.bin/uglifyjs b/homework7/project_express/node_modules/.bin/uglifyjs new file mode 100644 index 0000000..1d0ff19 --- /dev/null +++ b/homework7/project_express/node_modules/.bin/uglifyjs @@ -0,0 +1,12 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../uglify-js/bin/uglifyjs" "$@" +else + exec node "$basedir/../uglify-js/bin/uglifyjs" "$@" +fi diff --git a/homework7/project_express/node_modules/.bin/uglifyjs.cmd b/homework7/project_express/node_modules/.bin/uglifyjs.cmd new file mode 100644 index 0000000..17a9df1 --- /dev/null +++ b/homework7/project_express/node_modules/.bin/uglifyjs.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\uglify-js\bin\uglifyjs" %* diff --git a/homework7/project_express/node_modules/.bin/uglifyjs.ps1 b/homework7/project_express/node_modules/.bin/uglifyjs.ps1 new file mode 100644 index 0000000..5e0bc56 --- /dev/null +++ b/homework7/project_express/node_modules/.bin/uglifyjs.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../uglify-js/bin/uglifyjs" $args + } else { + & "$basedir/node$exe" "$basedir/../uglify-js/bin/uglifyjs" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../uglify-js/bin/uglifyjs" $args + } else { + & "node$exe" "$basedir/../uglify-js/bin/uglifyjs" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/homework7/project_express/node_modules/.package-lock.json b/homework7/project_express/node_modules/.package-lock.json new file mode 100644 index 0000000..3c54ba4 --- /dev/null +++ b/homework7/project_express/node_modules/.package-lock.json @@ -0,0 +1,882 @@ +{ + "name": "project_express", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "node_modules/async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dependencies": { + "mime-db": "1.44.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nodemon": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", + "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha512-TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ==", + "dependencies": { + "wordwrap": "~0.0.2" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dependencies": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, + "node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require": { + "version": "2.4.20", + "resolved": "https://registry.npmjs.org/require/-/require-2.4.20.tgz", + "integrity": "sha512-7eop5rvh38qhQQQOoUyf68meVIcxT2yFySNywTbxoEECgkX4KDqqDRaEszfvFnuB3fuZVjDdJZ1TI/Esr16RRA==", + "dependencies": { + "std": "0.1.40", + "uglify-js": "2.3.0" + }, + "bin": { + "require": "bin/require-command.js" + }, + "engines": { + "browsers": "*", + "node": "*" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/simple-update-notifier": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", + "integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==", + "dependencies": { + "semver": "~7.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha512-VtCvB9SIQhk3aF6h+N85EaqIaBFIAfZ9Cu+NJHHVvc8BbEcnvDcFw6sqQ2dQrT6SlOrZq3tIvyD9+EGq/lJryQ==", + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/std": { + "version": "0.1.40", + "resolved": "https://registry.npmjs.org/std/-/std-0.1.40.tgz", + "integrity": "sha512-wUf57hkDGCoVShrhPA8Q7lAg2Qosk+FaMlECmAsr1A4/rL2NRXFHQGBcgMUFKVkPEemJFW9gzjCQisRty14ohg==", + "engines": { + "node": "*" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/uglify-js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.3.0.tgz", + "integrity": "sha512-AQvbxRKdaQeYADywQaao0k8Tj+7NGEVTne6xwgX1yQpv/G8b0CKdIw70HkCptwfvNGDsVe+0Bng3U9hfWbxxfg==", + "dependencies": { + "async": "~0.2.6", + "optimist": "~0.3.5", + "source-map": "~0.1.7" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==", + "engines": { + "node": ">=0.4.0" + } + } + } +} diff --git a/homework7/project_express/node_modules/abbrev/LICENSE b/homework7/project_express/node_modules/abbrev/LICENSE new file mode 100644 index 0000000..9bcfa9d --- /dev/null +++ b/homework7/project_express/node_modules/abbrev/LICENSE @@ -0,0 +1,46 @@ +This software is dual-licensed under the ISC and MIT licenses. +You may use this software under EITHER of the following licenses. + +---------- + +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +---------- + +Copyright Isaac Z. Schlueter and Contributors +All rights reserved. + +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/homework7/project_express/node_modules/abbrev/README.md b/homework7/project_express/node_modules/abbrev/README.md new file mode 100644 index 0000000..99746fe --- /dev/null +++ b/homework7/project_express/node_modules/abbrev/README.md @@ -0,0 +1,23 @@ +# abbrev-js + +Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev). + +Usage: + + var abbrev = require("abbrev"); + abbrev("foo", "fool", "folding", "flop"); + + // returns: + { fl: 'flop' + , flo: 'flop' + , flop: 'flop' + , fol: 'folding' + , fold: 'folding' + , foldi: 'folding' + , foldin: 'folding' + , folding: 'folding' + , foo: 'foo' + , fool: 'fool' + } + +This is handy for command-line scripts, or other cases where you want to be able to accept shorthands. diff --git a/homework7/project_express/node_modules/abbrev/abbrev.js b/homework7/project_express/node_modules/abbrev/abbrev.js new file mode 100644 index 0000000..7b1dc5d --- /dev/null +++ b/homework7/project_express/node_modules/abbrev/abbrev.js @@ -0,0 +1,61 @@ +module.exports = exports = abbrev.abbrev = abbrev + +abbrev.monkeyPatch = monkeyPatch + +function monkeyPatch () { + Object.defineProperty(Array.prototype, 'abbrev', { + value: function () { return abbrev(this) }, + enumerable: false, configurable: true, writable: true + }) + + Object.defineProperty(Object.prototype, 'abbrev', { + value: function () { return abbrev(Object.keys(this)) }, + enumerable: false, configurable: true, writable: true + }) +} + +function abbrev (list) { + if (arguments.length !== 1 || !Array.isArray(list)) { + list = Array.prototype.slice.call(arguments, 0) + } + for (var i = 0, l = list.length, args = [] ; i < l ; i ++) { + args[i] = typeof list[i] === "string" ? list[i] : String(list[i]) + } + + // sort them lexicographically, so that they're next to their nearest kin + args = args.sort(lexSort) + + // walk through each, seeing how much it has in common with the next and previous + var abbrevs = {} + , prev = "" + for (var i = 0, l = args.length ; i < l ; i ++) { + var current = args[i] + , next = args[i + 1] || "" + , nextMatches = true + , prevMatches = true + if (current === next) continue + for (var j = 0, cl = current.length ; j < cl ; j ++) { + var curChar = current.charAt(j) + nextMatches = nextMatches && curChar === next.charAt(j) + prevMatches = prevMatches && curChar === prev.charAt(j) + if (!nextMatches && !prevMatches) { + j ++ + break + } + } + prev = current + if (j === cl) { + abbrevs[current] = current + continue + } + for (var a = current.substr(0, j) ; j <= cl ; j ++) { + abbrevs[a] = current + a += current.charAt(j) + } + } + return abbrevs +} + +function lexSort (a, b) { + return a === b ? 0 : a > b ? 1 : -1 +} diff --git a/homework7/project_express/node_modules/abbrev/package.json b/homework7/project_express/node_modules/abbrev/package.json new file mode 100644 index 0000000..bf4e801 --- /dev/null +++ b/homework7/project_express/node_modules/abbrev/package.json @@ -0,0 +1,21 @@ +{ + "name": "abbrev", + "version": "1.1.1", + "description": "Like ruby's abbrev module, but in js", + "author": "Isaac Z. Schlueter ", + "main": "abbrev.js", + "scripts": { + "test": "tap test.js --100", + "preversion": "npm test", + "postversion": "npm publish", + "postpublish": "git push origin --all; git push origin --tags" + }, + "repository": "http://github.com/isaacs/abbrev-js", + "license": "ISC", + "devDependencies": { + "tap": "^10.1" + }, + "files": [ + "abbrev.js" + ] +} diff --git a/homework7/project_express/node_modules/accepts/HISTORY.md b/homework7/project_express/node_modules/accepts/HISTORY.md new file mode 100644 index 0000000..0bf0417 --- /dev/null +++ b/homework7/project_express/node_modules/accepts/HISTORY.md @@ -0,0 +1,236 @@ +1.3.7 / 2019-04-29 +================== + + * deps: negotiator@0.6.2 + - Fix sorting charset, encoding, and language with extra parameters + +1.3.6 / 2019-04-28 +================== + + * deps: mime-types@~2.1.24 + - deps: mime-db@~1.40.0 + +1.3.5 / 2018-02-28 +================== + + * deps: mime-types@~2.1.18 + - deps: mime-db@~1.33.0 + +1.3.4 / 2017-08-22 +================== + + * deps: mime-types@~2.1.16 + - deps: mime-db@~1.29.0 + +1.3.3 / 2016-05-02 +================== + + * deps: mime-types@~2.1.11 + - deps: mime-db@~1.23.0 + * deps: negotiator@0.6.1 + - perf: improve `Accept` parsing speed + - perf: improve `Accept-Charset` parsing speed + - perf: improve `Accept-Encoding` parsing speed + - perf: improve `Accept-Language` parsing speed + +1.3.2 / 2016-03-08 +================== + + * deps: mime-types@~2.1.10 + - Fix extension of `application/dash+xml` + - Update primary extension for `audio/mp4` + - deps: mime-db@~1.22.0 + +1.3.1 / 2016-01-19 +================== + + * deps: mime-types@~2.1.9 + - deps: mime-db@~1.21.0 + +1.3.0 / 2015-09-29 +================== + + * deps: mime-types@~2.1.7 + - deps: mime-db@~1.19.0 + * deps: negotiator@0.6.0 + - Fix including type extensions in parameters in `Accept` parsing + - Fix parsing `Accept` parameters with quoted equals + - Fix parsing `Accept` parameters with quoted semicolons + - Lazy-load modules from main entry point + - perf: delay type concatenation until needed + - perf: enable strict mode + - perf: hoist regular expressions + - perf: remove closures getting spec properties + - perf: remove a closure from media type parsing + - perf: remove property delete from media type parsing + +1.2.13 / 2015-09-06 +=================== + + * deps: mime-types@~2.1.6 + - deps: mime-db@~1.18.0 + +1.2.12 / 2015-07-30 +=================== + + * deps: mime-types@~2.1.4 + - deps: mime-db@~1.16.0 + +1.2.11 / 2015-07-16 +=================== + + * deps: mime-types@~2.1.3 + - deps: mime-db@~1.15.0 + +1.2.10 / 2015-07-01 +=================== + + * deps: mime-types@~2.1.2 + - deps: mime-db@~1.14.0 + +1.2.9 / 2015-06-08 +================== + + * deps: mime-types@~2.1.1 + - perf: fix deopt during mapping + +1.2.8 / 2015-06-07 +================== + + * deps: mime-types@~2.1.0 + - deps: mime-db@~1.13.0 + * perf: avoid argument reassignment & argument slice + * perf: avoid negotiator recursive construction + * perf: enable strict mode + * perf: remove unnecessary bitwise operator + +1.2.7 / 2015-05-10 +================== + + * deps: negotiator@0.5.3 + - Fix media type parameter matching to be case-insensitive + +1.2.6 / 2015-05-07 +================== + + * deps: mime-types@~2.0.11 + - deps: mime-db@~1.9.1 + * deps: negotiator@0.5.2 + - Fix comparing media types with quoted values + - Fix splitting media types with quoted commas + +1.2.5 / 2015-03-13 +================== + + * deps: mime-types@~2.0.10 + - deps: mime-db@~1.8.0 + +1.2.4 / 2015-02-14 +================== + + * Support Node.js 0.6 + * deps: mime-types@~2.0.9 + - deps: mime-db@~1.7.0 + * deps: negotiator@0.5.1 + - Fix preference sorting to be stable for long acceptable lists + +1.2.3 / 2015-01-31 +================== + + * deps: mime-types@~2.0.8 + - deps: mime-db@~1.6.0 + +1.2.2 / 2014-12-30 +================== + + * deps: mime-types@~2.0.7 + - deps: mime-db@~1.5.0 + +1.2.1 / 2014-12-30 +================== + + * deps: mime-types@~2.0.5 + - deps: mime-db@~1.3.1 + +1.2.0 / 2014-12-19 +================== + + * deps: negotiator@0.5.0 + - Fix list return order when large accepted list + - Fix missing identity encoding when q=0 exists + - Remove dynamic building of Negotiator class + +1.1.4 / 2014-12-10 +================== + + * deps: mime-types@~2.0.4 + - deps: mime-db@~1.3.0 + +1.1.3 / 2014-11-09 +================== + + * deps: mime-types@~2.0.3 + - deps: mime-db@~1.2.0 + +1.1.2 / 2014-10-14 +================== + + * deps: negotiator@0.4.9 + - Fix error when media type has invalid parameter + +1.1.1 / 2014-09-28 +================== + + * deps: mime-types@~2.0.2 + - deps: mime-db@~1.1.0 + * deps: negotiator@0.4.8 + - Fix all negotiations to be case-insensitive + - Stable sort preferences of same quality according to client order + +1.1.0 / 2014-09-02 +================== + + * update `mime-types` + +1.0.7 / 2014-07-04 +================== + + * Fix wrong type returned from `type` when match after unknown extension + +1.0.6 / 2014-06-24 +================== + + * deps: negotiator@0.4.7 + +1.0.5 / 2014-06-20 +================== + + * fix crash when unknown extension given + +1.0.4 / 2014-06-19 +================== + + * use `mime-types` + +1.0.3 / 2014-06-11 +================== + + * deps: negotiator@0.4.6 + - Order by specificity when quality is the same + +1.0.2 / 2014-05-29 +================== + + * Fix interpretation when header not in request + * deps: pin negotiator@0.4.5 + +1.0.1 / 2014-01-18 +================== + + * Identity encoding isn't always acceptable + * deps: negotiator@~0.4.0 + +1.0.0 / 2013-12-27 +================== + + * Genesis diff --git a/homework7/project_express/node_modules/accepts/LICENSE b/homework7/project_express/node_modules/accepts/LICENSE new file mode 100644 index 0000000..0616607 --- /dev/null +++ b/homework7/project_express/node_modules/accepts/LICENSE @@ -0,0 +1,23 @@ +(The MIT License) + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2015 Douglas Christopher Wilson + +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/homework7/project_express/node_modules/accepts/README.md b/homework7/project_express/node_modules/accepts/README.md new file mode 100644 index 0000000..66a2f54 --- /dev/null +++ b/homework7/project_express/node_modules/accepts/README.md @@ -0,0 +1,142 @@ +# accepts + +[![NPM Version][npm-version-image]][npm-url] +[![NPM Downloads][npm-downloads-image]][npm-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Higher level content negotiation based on [negotiator](https://www.npmjs.com/package/negotiator). +Extracted from [koa](https://www.npmjs.com/package/koa) for general use. + +In addition to negotiator, it allows: + +- Allows types as an array or arguments list, ie `(['text/html', 'application/json'])` + as well as `('text/html', 'application/json')`. +- Allows type shorthands such as `json`. +- Returns `false` when no types match +- Treats non-existent headers as `*` + +## Installation + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```sh +$ npm install accepts +``` + +## API + + + +```js +var accepts = require('accepts') +``` + +### accepts(req) + +Create a new `Accepts` object for the given `req`. + +#### .charset(charsets) + +Return the first accepted charset. If nothing in `charsets` is accepted, +then `false` is returned. + +#### .charsets() + +Return the charsets that the request accepts, in the order of the client's +preference (most preferred first). + +#### .encoding(encodings) + +Return the first accepted encoding. If nothing in `encodings` is accepted, +then `false` is returned. + +#### .encodings() + +Return the encodings that the request accepts, in the order of the client's +preference (most preferred first). + +#### .language(languages) + +Return the first accepted language. If nothing in `languages` is accepted, +then `false` is returned. + +#### .languages() + +Return the languages that the request accepts, in the order of the client's +preference (most preferred first). + +#### .type(types) + +Return the first accepted type (and it is returned as the same text as what +appears in the `types` array). If nothing in `types` is accepted, then `false` +is returned. + +The `types` array can contain full MIME types or file extensions. Any value +that is not a full MIME types is passed to `require('mime-types').lookup`. + +#### .types() + +Return the types that the request accepts, in the order of the client's +preference (most preferred first). + +## Examples + +### Simple type negotiation + +This simple example shows how to use `accepts` to return a different typed +respond body based on what the client wants to accept. The server lists it's +preferences in order and will get back the best match between the client and +server. + +```js +var accepts = require('accepts') +var http = require('http') + +function app (req, res) { + var accept = accepts(req) + + // the order of this list is significant; should be server preferred order + switch (accept.type(['json', 'html'])) { + case 'json': + res.setHeader('Content-Type', 'application/json') + res.write('{"hello":"world!"}') + break + case 'html': + res.setHeader('Content-Type', 'text/html') + res.write('hello, world!') + break + default: + // the fallback is text/plain, so no need to specify it above + res.setHeader('Content-Type', 'text/plain') + res.write('hello, world!') + break + } + + res.end() +} + +http.createServer(app).listen(3000) +``` + +You can test this out with the cURL program: +```sh +curl -I -H'Accept: text/html' http://localhost:3000/ +``` + +## License + +[MIT](LICENSE) + +[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/accepts/master +[coveralls-url]: https://coveralls.io/r/jshttp/accepts?branch=master +[node-version-image]: https://badgen.net/npm/node/accepts +[node-version-url]: https://nodejs.org/en/download +[npm-downloads-image]: https://badgen.net/npm/dm/accepts +[npm-url]: https://npmjs.org/package/accepts +[npm-version-image]: https://badgen.net/npm/v/accepts +[travis-image]: https://badgen.net/travis/jshttp/accepts/master +[travis-url]: https://travis-ci.org/jshttp/accepts diff --git a/homework7/project_express/node_modules/accepts/index.js b/homework7/project_express/node_modules/accepts/index.js new file mode 100644 index 0000000..e9b2f63 --- /dev/null +++ b/homework7/project_express/node_modules/accepts/index.js @@ -0,0 +1,238 @@ +/*! + * accepts + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var Negotiator = require('negotiator') +var mime = require('mime-types') + +/** + * Module exports. + * @public + */ + +module.exports = Accepts + +/** + * Create a new Accepts object for the given req. + * + * @param {object} req + * @public + */ + +function Accepts (req) { + if (!(this instanceof Accepts)) { + return new Accepts(req) + } + + this.headers = req.headers + this.negotiator = new Negotiator(req) +} + +/** + * Check if the given `type(s)` is acceptable, returning + * the best match when true, otherwise `undefined`, in which + * case you should respond with 406 "Not Acceptable". + * + * The `type` value may be a single mime type string + * such as "application/json", the extension name + * such as "json" or an array `["json", "html", "text/plain"]`. When a list + * or array is given the _best_ match, if any is returned. + * + * Examples: + * + * // Accept: text/html + * this.types('html'); + * // => "html" + * + * // Accept: text/*, application/json + * this.types('html'); + * // => "html" + * this.types('text/html'); + * // => "text/html" + * this.types('json', 'text'); + * // => "json" + * this.types('application/json'); + * // => "application/json" + * + * // Accept: text/*, application/json + * this.types('image/png'); + * this.types('png'); + * // => undefined + * + * // Accept: text/*;q=.5, application/json + * this.types(['html', 'json']); + * this.types('html', 'json'); + * // => "json" + * + * @param {String|Array} types... + * @return {String|Array|Boolean} + * @public + */ + +Accepts.prototype.type = +Accepts.prototype.types = function (types_) { + var types = types_ + + // support flattened arguments + if (types && !Array.isArray(types)) { + types = new Array(arguments.length) + for (var i = 0; i < types.length; i++) { + types[i] = arguments[i] + } + } + + // no types, return all requested types + if (!types || types.length === 0) { + return this.negotiator.mediaTypes() + } + + // no accept header, return first given type + if (!this.headers.accept) { + return types[0] + } + + var mimes = types.map(extToMime) + var accepts = this.negotiator.mediaTypes(mimes.filter(validMime)) + var first = accepts[0] + + return first + ? types[mimes.indexOf(first)] + : false +} + +/** + * Return accepted encodings or best fit based on `encodings`. + * + * Given `Accept-Encoding: gzip, deflate` + * an array sorted by quality is returned: + * + * ['gzip', 'deflate'] + * + * @param {String|Array} encodings... + * @return {String|Array} + * @public + */ + +Accepts.prototype.encoding = +Accepts.prototype.encodings = function (encodings_) { + var encodings = encodings_ + + // support flattened arguments + if (encodings && !Array.isArray(encodings)) { + encodings = new Array(arguments.length) + for (var i = 0; i < encodings.length; i++) { + encodings[i] = arguments[i] + } + } + + // no encodings, return all requested encodings + if (!encodings || encodings.length === 0) { + return this.negotiator.encodings() + } + + return this.negotiator.encodings(encodings)[0] || false +} + +/** + * Return accepted charsets or best fit based on `charsets`. + * + * Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5` + * an array sorted by quality is returned: + * + * ['utf-8', 'utf-7', 'iso-8859-1'] + * + * @param {String|Array} charsets... + * @return {String|Array} + * @public + */ + +Accepts.prototype.charset = +Accepts.prototype.charsets = function (charsets_) { + var charsets = charsets_ + + // support flattened arguments + if (charsets && !Array.isArray(charsets)) { + charsets = new Array(arguments.length) + for (var i = 0; i < charsets.length; i++) { + charsets[i] = arguments[i] + } + } + + // no charsets, return all requested charsets + if (!charsets || charsets.length === 0) { + return this.negotiator.charsets() + } + + return this.negotiator.charsets(charsets)[0] || false +} + +/** + * Return accepted languages or best fit based on `langs`. + * + * Given `Accept-Language: en;q=0.8, es, pt` + * an array sorted by quality is returned: + * + * ['es', 'pt', 'en'] + * + * @param {String|Array} langs... + * @return {Array|String} + * @public + */ + +Accepts.prototype.lang = +Accepts.prototype.langs = +Accepts.prototype.language = +Accepts.prototype.languages = function (languages_) { + var languages = languages_ + + // support flattened arguments + if (languages && !Array.isArray(languages)) { + languages = new Array(arguments.length) + for (var i = 0; i < languages.length; i++) { + languages[i] = arguments[i] + } + } + + // no languages, return all requested languages + if (!languages || languages.length === 0) { + return this.negotiator.languages() + } + + return this.negotiator.languages(languages)[0] || false +} + +/** + * Convert extnames to mime. + * + * @param {String} type + * @return {String} + * @private + */ + +function extToMime (type) { + return type.indexOf('/') === -1 + ? mime.lookup(type) + : type +} + +/** + * Check if mime is valid. + * + * @param {String} type + * @return {String} + * @private + */ + +function validMime (type) { + return typeof type === 'string' +} diff --git a/homework7/project_express/node_modules/accepts/package.json b/homework7/project_express/node_modules/accepts/package.json new file mode 100644 index 0000000..1bbe63b --- /dev/null +++ b/homework7/project_express/node_modules/accepts/package.json @@ -0,0 +1,86 @@ +{ + "_from": "accepts@~1.3.7", + "_id": "accepts@1.3.7", + "_inBundle": false, + "_integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "_location": "/accepts", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "accepts@~1.3.7", + "name": "accepts", + "escapedName": "accepts", + "rawSpec": "~1.3.7", + "saveSpec": null, + "fetchSpec": "~1.3.7" + }, + "_requiredBy": [ + "/express" + ], + "_resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "_shasum": "531bc726517a3b2b41f850021c6cc15eaab507cd", + "_spec": "accepts@~1.3.7", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\express", + "bugs": { + "url": "https://github.com/jshttp/accepts/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "Jonathan Ong", + "email": "me@jongleberry.com", + "url": "http://jongleberry.com" + } + ], + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "deprecated": false, + "description": "Higher-level content negotiation", + "devDependencies": { + "deep-equal": "1.0.1", + "eslint": "5.16.0", + "eslint-config-standard": "12.0.0", + "eslint-plugin-import": "2.17.2", + "eslint-plugin-markdown": "1.0.0", + "eslint-plugin-node": "8.0.1", + "eslint-plugin-promise": "4.1.1", + "eslint-plugin-standard": "4.0.0", + "mocha": "6.1.4", + "nyc": "14.0.0" + }, + "engines": { + "node": ">= 0.6" + }, + "files": [ + "LICENSE", + "HISTORY.md", + "index.js" + ], + "homepage": "https://github.com/jshttp/accepts#readme", + "keywords": [ + "content", + "negotiation", + "accept", + "accepts" + ], + "license": "MIT", + "name": "accepts", + "repository": { + "type": "git", + "url": "git+https://github.com/jshttp/accepts.git" + }, + "scripts": { + "lint": "eslint --plugin markdown --ext js,md .", + "test": "mocha --reporter spec --check-leaks --bail test/", + "test-cov": "nyc --reporter=html --reporter=text npm test", + "test-travis": "nyc --reporter=text npm test" + }, + "version": "1.3.7" +} diff --git a/homework7/project_express/node_modules/amdefine/LICENSE b/homework7/project_express/node_modules/amdefine/LICENSE new file mode 100644 index 0000000..9b25ee0 --- /dev/null +++ b/homework7/project_express/node_modules/amdefine/LICENSE @@ -0,0 +1,58 @@ +amdefine is released under two licenses: new BSD, and MIT. You may pick the +license that best suits your development needs. The text of both licenses are +provided below. + + +The "New" BSD License: +---------------------- + +Copyright (c) 2011-2016, The Dojo Foundation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the Dojo Foundation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +MIT License +----------- + +Copyright (c) 2011-2016, The Dojo Foundation + +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/homework7/project_express/node_modules/amdefine/README.md b/homework7/project_express/node_modules/amdefine/README.md new file mode 100644 index 0000000..037a6e8 --- /dev/null +++ b/homework7/project_express/node_modules/amdefine/README.md @@ -0,0 +1,171 @@ +# amdefine + +A module that can be used to implement AMD's define() in Node. This allows you +to code to the AMD API and have the module work in node programs without +requiring those other programs to use AMD. + +## Usage + +**1)** Update your package.json to indicate amdefine as a dependency: + +```javascript + "dependencies": { + "amdefine": ">=0.1.0" + } +``` + +Then run `npm install` to get amdefine into your project. + +**2)** At the top of each module that uses define(), place this code: + +```javascript +if (typeof define !== 'function') { var define = require('amdefine')(module) } +``` + +**Only use these snippets** when loading amdefine. If you preserve the basic structure, +with the braces, it will be stripped out when using the [RequireJS optimizer](#optimizer). + +You can add spaces, line breaks and even require amdefine with a local path, but +keep the rest of the structure to get the stripping behavior. + +As you may know, because `if` statements in JavaScript don't have their own scope, the var +declaration in the above snippet is made whether the `if` expression is truthy or not. If +RequireJS is loaded then the declaration is superfluous because `define` is already already +declared in the same scope in RequireJS. Fortunately JavaScript handles multiple `var` +declarations of the same variable in the same scope gracefully. + +If you want to deliver amdefine.js with your code rather than specifying it as a dependency +with npm, then just download the latest release and refer to it using a relative path: + +[Latest Version](https://github.com/jrburke/amdefine/raw/latest/amdefine.js) + +### amdefine/intercept + +Consider this very experimental. + +Instead of pasting the piece of text for the amdefine setup of a `define` +variable in each module you create or consume, you can use `amdefine/intercept` +instead. It will automatically insert the above snippet in each .js file loaded +by Node. + +**Warning**: you should only use this if you are creating an application that +is consuming AMD style defined()'d modules that are distributed via npm and want +to run that code in Node. + +For library code where you are not sure if it will be used by others in Node or +in the browser, then explicitly depending on amdefine and placing the code +snippet above is suggested path, instead of using `amdefine/intercept`. The +intercept module affects all .js files loaded in the Node app, and it is +inconsiderate to modify global state like that unless you are also controlling +the top level app. + +#### Why distribute AMD-style modules via npm? + +npm has a lot of weaknesses for front-end use (installed layout is not great, +should have better support for the `baseUrl + moduleID + '.js' style of loading, +single file JS installs), but some people want a JS package manager and are +willing to live with those constraints. If that is you, but still want to author +in AMD style modules to get dynamic require([]), better direct source usage and +powerful loader plugin support in the browser, then this tool can help. + +#### amdefine/intercept usage + +Just require it in your top level app module (for example index.js, server.js): + +```javascript +require('amdefine/intercept'); +``` + +The module does not return a value, so no need to assign the result to a local +variable. + +Then just require() code as you normally would with Node's require(). Any .js +loaded after the intercept require will have the amdefine check injected in +the .js source as it is loaded. It does not modify the source on disk, just +prepends some content to the text of the module as it is loaded by Node. + +#### How amdefine/intercept works + +It overrides the `Module._extensions['.js']` in Node to automatically prepend +the amdefine snippet above. So, it will affect any .js file loaded by your +app. + +## define() usage + +It is best if you use the anonymous forms of define() in your module: + +```javascript +define(function (require) { + var dependency = require('dependency'); +}); +``` + +or + +```javascript +define(['dependency'], function (dependency) { + +}); +``` + +## RequireJS optimizer integration. + +Version 1.0.3 of the [RequireJS optimizer](http://requirejs.org/docs/optimization.html) +will have support for stripping the `if (typeof define !== 'function')` check +mentioned above, so you can include this snippet for code that runs in the +browser, but avoid taking the cost of the if() statement once the code is +optimized for deployment. + +## Node 0.4 Support + +If you want to support Node 0.4, then add `require` as the second parameter to amdefine: + +```javascript +//Only if you want Node 0.4. If using 0.5 or later, use the above snippet. +if (typeof define !== 'function') { var define = require('amdefine')(module, require) } +``` + +## Limitations + +### Synchronous vs Asynchronous + +amdefine creates a define() function that is callable by your code. It will +execute and trace dependencies and call the factory function *synchronously*, +to keep the behavior in line with Node's synchronous dependency tracing. + +The exception: calling AMD's callback-style require() from inside a factory +function. The require callback is called on process.nextTick(): + +```javascript +define(function (require) { + require(['a'], function(a) { + //'a' is loaded synchronously, but + //this callback is called on process.nextTick(). + }); +}); +``` + +### Loader Plugins + +Loader plugins are supported as long as they call their load() callbacks +synchronously. So ones that do network requests will not work. However plugins +like [text](http://requirejs.org/docs/api.html#text) can load text files locally. + +The plugin API's `load.fromText()` is **not supported** in amdefine, so this means +transpiler plugins like the [CoffeeScript loader plugin](https://github.com/jrburke/require-cs) +will not work. This may be fixable, but it is a bit complex, and I do not have +enough node-fu to figure it out yet. See the source for amdefine.js if you want +to get an idea of the issues involved. + +## Tests + +To run the tests, cd to **tests** and run: + +``` +node all.js +node all-intercept.js +``` + +## License + +New BSD and MIT. Check the LICENSE file for all the details. diff --git a/homework7/project_express/node_modules/amdefine/amdefine.js b/homework7/project_express/node_modules/amdefine/amdefine.js new file mode 100644 index 0000000..ca830ba --- /dev/null +++ b/homework7/project_express/node_modules/amdefine/amdefine.js @@ -0,0 +1,301 @@ +/** vim: et:ts=4:sw=4:sts=4 + * @license amdefine 1.0.1 Copyright (c) 2011-2016, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/amdefine for details + */ + +/*jslint node: true */ +/*global module, process */ +'use strict'; + +/** + * Creates a define for node. + * @param {Object} module the "module" object that is defined by Node for the + * current module. + * @param {Function} [requireFn]. Node's require function for the current module. + * It only needs to be passed in Node versions before 0.5, when module.require + * did not exist. + * @returns {Function} a define function that is usable for the current node + * module. + */ +function amdefine(module, requireFn) { + 'use strict'; + var defineCache = {}, + loaderCache = {}, + alreadyCalled = false, + path = require('path'), + makeRequire, stringRequire; + + /** + * Trims the . and .. from an array of path segments. + * It will keep a leading path segment if a .. will become + * the first path segment, to help with module name lookups, + * which act like paths, but can be remapped. But the end result, + * all paths that use this function should look normalized. + * NOTE: this method MODIFIES the input array. + * @param {Array} ary the array of path segments. + */ + function trimDots(ary) { + var i, part; + for (i = 0; ary[i]; i+= 1) { + part = ary[i]; + if (part === '.') { + ary.splice(i, 1); + i -= 1; + } else if (part === '..') { + if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { + //End of the line. Keep at least one non-dot + //path segment at the front so it can be mapped + //correctly to disk. Otherwise, there is likely + //no path mapping for a path starting with '..'. + //This can still fail, but catches the most reasonable + //uses of .. + break; + } else if (i > 0) { + ary.splice(i - 1, 2); + i -= 2; + } + } + } + } + + function normalize(name, baseName) { + var baseParts; + + //Adjust any relative paths. + if (name && name.charAt(0) === '.') { + //If have a base name, try to normalize against it, + //otherwise, assume it is a top-level require that will + //be relative to baseUrl in the end. + if (baseName) { + baseParts = baseName.split('/'); + baseParts = baseParts.slice(0, baseParts.length - 1); + baseParts = baseParts.concat(name.split('/')); + trimDots(baseParts); + name = baseParts.join('/'); + } + } + + return name; + } + + /** + * Create the normalize() function passed to a loader plugin's + * normalize method. + */ + function makeNormalize(relName) { + return function (name) { + return normalize(name, relName); + }; + } + + function makeLoad(id) { + function load(value) { + loaderCache[id] = value; + } + + load.fromText = function (id, text) { + //This one is difficult because the text can/probably uses + //define, and any relative paths and requires should be relative + //to that id was it would be found on disk. But this would require + //bootstrapping a module/require fairly deeply from node core. + //Not sure how best to go about that yet. + throw new Error('amdefine does not implement load.fromText'); + }; + + return load; + } + + makeRequire = function (systemRequire, exports, module, relId) { + function amdRequire(deps, callback) { + if (typeof deps === 'string') { + //Synchronous, single module require('') + return stringRequire(systemRequire, exports, module, deps, relId); + } else { + //Array of dependencies with a callback. + + //Convert the dependencies to modules. + deps = deps.map(function (depName) { + return stringRequire(systemRequire, exports, module, depName, relId); + }); + + //Wait for next tick to call back the require call. + if (callback) { + process.nextTick(function () { + callback.apply(null, deps); + }); + } + } + } + + amdRequire.toUrl = function (filePath) { + if (filePath.indexOf('.') === 0) { + return normalize(filePath, path.dirname(module.filename)); + } else { + return filePath; + } + }; + + return amdRequire; + }; + + //Favor explicit value, passed in if the module wants to support Node 0.4. + requireFn = requireFn || function req() { + return module.require.apply(module, arguments); + }; + + function runFactory(id, deps, factory) { + var r, e, m, result; + + if (id) { + e = loaderCache[id] = {}; + m = { + id: id, + uri: __filename, + exports: e + }; + r = makeRequire(requireFn, e, m, id); + } else { + //Only support one define call per file + if (alreadyCalled) { + throw new Error('amdefine with no module ID cannot be called more than once per file.'); + } + alreadyCalled = true; + + //Use the real variables from node + //Use module.exports for exports, since + //the exports in here is amdefine exports. + e = module.exports; + m = module; + r = makeRequire(requireFn, e, m, module.id); + } + + //If there are dependencies, they are strings, so need + //to convert them to dependency values. + if (deps) { + deps = deps.map(function (depName) { + return r(depName); + }); + } + + //Call the factory with the right dependencies. + if (typeof factory === 'function') { + result = factory.apply(m.exports, deps); + } else { + result = factory; + } + + if (result !== undefined) { + m.exports = result; + if (id) { + loaderCache[id] = m.exports; + } + } + } + + stringRequire = function (systemRequire, exports, module, id, relId) { + //Split the ID by a ! so that + var index = id.indexOf('!'), + originalId = id, + prefix, plugin; + + if (index === -1) { + id = normalize(id, relId); + + //Straight module lookup. If it is one of the special dependencies, + //deal with it, otherwise, delegate to node. + if (id === 'require') { + return makeRequire(systemRequire, exports, module, relId); + } else if (id === 'exports') { + return exports; + } else if (id === 'module') { + return module; + } else if (loaderCache.hasOwnProperty(id)) { + return loaderCache[id]; + } else if (defineCache[id]) { + runFactory.apply(null, defineCache[id]); + return loaderCache[id]; + } else { + if(systemRequire) { + return systemRequire(originalId); + } else { + throw new Error('No module with ID: ' + id); + } + } + } else { + //There is a plugin in play. + prefix = id.substring(0, index); + id = id.substring(index + 1, id.length); + + plugin = stringRequire(systemRequire, exports, module, prefix, relId); + + if (plugin.normalize) { + id = plugin.normalize(id, makeNormalize(relId)); + } else { + //Normalize the ID normally. + id = normalize(id, relId); + } + + if (loaderCache[id]) { + return loaderCache[id]; + } else { + plugin.load(id, makeRequire(systemRequire, exports, module, relId), makeLoad(id), {}); + + return loaderCache[id]; + } + } + }; + + //Create a define function specific to the module asking for amdefine. + function define(id, deps, factory) { + if (Array.isArray(id)) { + factory = deps; + deps = id; + id = undefined; + } else if (typeof id !== 'string') { + factory = id; + id = deps = undefined; + } + + if (deps && !Array.isArray(deps)) { + factory = deps; + deps = undefined; + } + + if (!deps) { + deps = ['require', 'exports', 'module']; + } + + //Set up properties for this module. If an ID, then use + //internal cache. If no ID, then use the external variables + //for this node module. + if (id) { + //Put the module in deep freeze until there is a + //require call for it. + defineCache[id] = [id, deps, factory]; + } else { + runFactory(id, deps, factory); + } + } + + //define.require, which has access to all the values in the + //cache. Useful for AMD modules that all have IDs in the file, + //but need to finally export a value to node based on one of those + //IDs. + define.require = function (id) { + if (loaderCache[id]) { + return loaderCache[id]; + } + + if (defineCache[id]) { + runFactory.apply(null, defineCache[id]); + return loaderCache[id]; + } + }; + + define.amd = {}; + + return define; +} + +module.exports = amdefine; diff --git a/homework7/project_express/node_modules/amdefine/intercept.js b/homework7/project_express/node_modules/amdefine/intercept.js new file mode 100644 index 0000000..771a983 --- /dev/null +++ b/homework7/project_express/node_modules/amdefine/intercept.js @@ -0,0 +1,36 @@ +/*jshint node: true */ +var inserted, + Module = require('module'), + fs = require('fs'), + existingExtFn = Module._extensions['.js'], + amdefineRegExp = /amdefine\.js/; + +inserted = "if (typeof define !== 'function') {var define = require('amdefine')(module)}"; + +//From the node/lib/module.js source: +function stripBOM(content) { + // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) + // because the buffer-to-string conversion in `fs.readFileSync()` + // translates it to FEFF, the UTF-16 BOM. + if (content.charCodeAt(0) === 0xFEFF) { + content = content.slice(1); + } + return content; +} + +//Also adapted from the node/lib/module.js source: +function intercept(module, filename) { + var content = stripBOM(fs.readFileSync(filename, 'utf8')); + + if (!amdefineRegExp.test(module.id)) { + content = inserted + content; + } + + module._compile(content, filename); +} + +intercept._id = 'amdefine/intercept'; + +if (!existingExtFn._id || existingExtFn._id !== intercept._id) { + Module._extensions['.js'] = intercept; +} diff --git a/homework7/project_express/node_modules/amdefine/package.json b/homework7/project_express/node_modules/amdefine/package.json new file mode 100644 index 0000000..8be1714 --- /dev/null +++ b/homework7/project_express/node_modules/amdefine/package.json @@ -0,0 +1,16 @@ +{ + "name": "amdefine", + "description": "Provide AMD's define() API for declaring modules in the AMD format", + "version": "1.0.1", + "homepage": "http://github.com/jrburke/amdefine", + "author": "James Burke (http://github.com/jrburke)", + "license": "BSD-3-Clause OR MIT", + "repository": { + "type": "git", + "url": "https://github.com/jrburke/amdefine.git" + }, + "main": "./amdefine.js", + "engines": { + "node": ">=0.4.2" + } +} diff --git a/homework7/project_express/node_modules/anymatch/LICENSE b/homework7/project_express/node_modules/anymatch/LICENSE new file mode 100644 index 0000000..491766c --- /dev/null +++ b/homework7/project_express/node_modules/anymatch/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) 2019 Elan Shanker, Paul Miller (https://paulmillr.com) + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/homework7/project_express/node_modules/anymatch/README.md b/homework7/project_express/node_modules/anymatch/README.md new file mode 100644 index 0000000..1dd67f5 --- /dev/null +++ b/homework7/project_express/node_modules/anymatch/README.md @@ -0,0 +1,87 @@ +anymatch [![Build Status](https://travis-ci.org/micromatch/anymatch.svg?branch=master)](https://travis-ci.org/micromatch/anymatch) [![Coverage Status](https://img.shields.io/coveralls/micromatch/anymatch.svg?branch=master)](https://coveralls.io/r/micromatch/anymatch?branch=master) +====== +Javascript module to match a string against a regular expression, glob, string, +or function that takes the string as an argument and returns a truthy or falsy +value. The matcher can also be an array of any or all of these. Useful for +allowing a very flexible user-defined config to define things like file paths. + +__Note: This module has Bash-parity, please be aware that Windows-style backslashes are not supported as separators. See https://github.com/micromatch/micromatch#backslashes for more information.__ + + +Usage +----- +```sh +npm install anymatch +``` + +#### anymatch(matchers, testString, [returnIndex], [options]) +* __matchers__: (_Array|String|RegExp|Function_) +String to be directly matched, string with glob patterns, regular expression +test, function that takes the testString as an argument and returns a truthy +value if it should be matched, or an array of any number and mix of these types. +* __testString__: (_String|Array_) The string to test against the matchers. If +passed as an array, the first element of the array will be used as the +`testString` for non-function matchers, while the entire array will be applied +as the arguments for function matchers. +* __options__: (_Object_ [optional]_) Any of the [picomatch](https://github.com/micromatch/picomatch#options) options. + * __returnIndex__: (_Boolean [optional]_) If true, return the array index of +the first matcher that that testString matched, or -1 if no match, instead of a +boolean result. + +```js +const anymatch = require('anymatch'); + +const matchers = [ 'path/to/file.js', 'path/anyjs/**/*.js', /foo.js$/, string => string.includes('bar') && string.length > 10 ] ; + +anymatch(matchers, 'path/to/file.js'); // true +anymatch(matchers, 'path/anyjs/baz.js'); // true +anymatch(matchers, 'path/to/foo.js'); // true +anymatch(matchers, 'path/to/bar.js'); // true +anymatch(matchers, 'bar.js'); // false + +// returnIndex = true +anymatch(matchers, 'foo.js', {returnIndex: true}); // 2 +anymatch(matchers, 'path/anyjs/foo.js', {returnIndex: true}); // 1 + +// any picomatc + +// using globs to match directories and their children +anymatch('node_modules', 'node_modules'); // true +anymatch('node_modules', 'node_modules/somelib/index.js'); // false +anymatch('node_modules/**', 'node_modules/somelib/index.js'); // true +anymatch('node_modules/**', '/absolute/path/to/node_modules/somelib/index.js'); // false +anymatch('**/node_modules/**', '/absolute/path/to/node_modules/somelib/index.js'); // true + +const matcher = anymatch(matchers); +['foo.js', 'bar.js'].filter(matcher); // [ 'foo.js' ] +anymatch master* ❯ + +``` + +#### anymatch(matchers) +You can also pass in only your matcher(s) to get a curried function that has +already been bound to the provided matching criteria. This can be used as an +`Array#filter` callback. + +```js +var matcher = anymatch(matchers); + +matcher('path/to/file.js'); // true +matcher('path/anyjs/baz.js', true); // 1 + +['foo.js', 'bar.js'].filter(matcher); // ['foo.js'] +``` + +Changelog +---------- +[See release notes page on GitHub](https://github.com/micromatch/anymatch/releases) + +- **v3.0:** Removed `startIndex` and `endIndex` arguments. Node 8.x-only. +- **v2.0:** [micromatch](https://github.com/jonschlinkert/micromatch) moves away from minimatch-parity and inline with Bash. This includes handling backslashes differently (see https://github.com/micromatch/micromatch#backslashes for more information). +- **v1.2:** anymatch uses [micromatch](https://github.com/jonschlinkert/micromatch) +for glob pattern matching. Issues with glob pattern matching should be +reported directly to the [micromatch issue tracker](https://github.com/jonschlinkert/micromatch/issues). + +License +------- +[ISC](https://raw.github.com/micromatch/anymatch/master/LICENSE) diff --git a/homework7/project_express/node_modules/anymatch/index.d.ts b/homework7/project_express/node_modules/anymatch/index.d.ts new file mode 100644 index 0000000..196d061 --- /dev/null +++ b/homework7/project_express/node_modules/anymatch/index.d.ts @@ -0,0 +1,19 @@ +type AnymatchFn = (testString: string) => boolean; +type AnymatchPattern = string|RegExp|AnymatchFn; +type AnymatchMatcher = AnymatchPattern|AnymatchPattern[] +type AnymatchTester = { + (testString: string|any[], returnIndex: true): number; + (testString: string|any[]): boolean; +} + +type PicomatchOptions = {dot: boolean}; + +declare const anymatch: { + (matchers: AnymatchMatcher): AnymatchTester; + (matchers: AnymatchMatcher, testString: string|any[], returnIndex: true | PicomatchOptions): number; + (matchers: AnymatchMatcher, testString: string|any[]): boolean; +} + +export {AnymatchMatcher as Matcher} +export {AnymatchTester as Tester} +export default anymatch diff --git a/homework7/project_express/node_modules/anymatch/index.js b/homework7/project_express/node_modules/anymatch/index.js new file mode 100644 index 0000000..9fb3ebb --- /dev/null +++ b/homework7/project_express/node_modules/anymatch/index.js @@ -0,0 +1,104 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { value: true }); + +const picomatch = require('picomatch'); +const normalizePath = require('normalize-path'); + +/** + * @typedef {(testString: string) => boolean} AnymatchFn + * @typedef {string|RegExp|AnymatchFn} AnymatchPattern + * @typedef {AnymatchPattern|AnymatchPattern[]} AnymatchMatcher + */ +const BANG = '!'; +const DEFAULT_OPTIONS = {returnIndex: false}; +const arrify = (item) => Array.isArray(item) ? item : [item]; + +/** + * @param {AnymatchPattern} matcher + * @param {object} options + * @returns {AnymatchFn} + */ +const createPattern = (matcher, options) => { + if (typeof matcher === 'function') { + return matcher; + } + if (typeof matcher === 'string') { + const glob = picomatch(matcher, options); + return (string) => matcher === string || glob(string); + } + if (matcher instanceof RegExp) { + return (string) => matcher.test(string); + } + return (string) => false; +}; + +/** + * @param {Array} patterns + * @param {Array} negPatterns + * @param {String|Array} args + * @param {Boolean} returnIndex + * @returns {boolean|number} + */ +const matchPatterns = (patterns, negPatterns, args, returnIndex) => { + const isList = Array.isArray(args); + const _path = isList ? args[0] : args; + if (!isList && typeof _path !== 'string') { + throw new TypeError('anymatch: second argument must be a string: got ' + + Object.prototype.toString.call(_path)) + } + const path = normalizePath(_path); + + for (let index = 0; index < negPatterns.length; index++) { + const nglob = negPatterns[index]; + if (nglob(path)) { + return returnIndex ? -1 : false; + } + } + + const applied = isList && [path].concat(args.slice(1)); + for (let index = 0; index < patterns.length; index++) { + const pattern = patterns[index]; + if (isList ? pattern(...applied) : pattern(path)) { + return returnIndex ? index : true; + } + } + + return returnIndex ? -1 : false; +}; + +/** + * @param {AnymatchMatcher} matchers + * @param {Array|string} testString + * @param {object} options + * @returns {boolean|number|Function} + */ +const anymatch = (matchers, testString, options = DEFAULT_OPTIONS) => { + if (matchers == null) { + throw new TypeError('anymatch: specify first argument'); + } + const opts = typeof options === 'boolean' ? {returnIndex: options} : options; + const returnIndex = opts.returnIndex || false; + + // Early cache for matchers. + const mtchers = arrify(matchers); + const negatedGlobs = mtchers + .filter(item => typeof item === 'string' && item.charAt(0) === BANG) + .map(item => item.slice(1)) + .map(item => picomatch(item, opts)); + const patterns = mtchers + .filter(item => typeof item !== 'string' || (typeof item === 'string' && item.charAt(0) !== BANG)) + .map(matcher => createPattern(matcher, opts)); + + if (testString == null) { + return (testString, ri = false) => { + const returnIndex = typeof ri === 'boolean' ? ri : false; + return matchPatterns(patterns, negatedGlobs, testString, returnIndex); + } + } + + return matchPatterns(patterns, negatedGlobs, testString, returnIndex); +}; + +anymatch.default = anymatch; +module.exports = anymatch; diff --git a/homework7/project_express/node_modules/anymatch/package.json b/homework7/project_express/node_modules/anymatch/package.json new file mode 100644 index 0000000..f9b5284 --- /dev/null +++ b/homework7/project_express/node_modules/anymatch/package.json @@ -0,0 +1,48 @@ +{ + "name": "anymatch", + "version": "3.1.2", + "description": "Matches strings against configurable strings, globs, regular expressions, and/or functions", + "files": [ + "index.js", + "index.d.ts" + ], + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "author": { + "name": "Elan Shanker", + "url": "https://github.com/es128" + }, + "license": "ISC", + "homepage": "https://github.com/micromatch/anymatch", + "repository": { + "type": "git", + "url": "https://github.com/micromatch/anymatch" + }, + "keywords": [ + "match", + "any", + "string", + "file", + "fs", + "list", + "glob", + "regex", + "regexp", + "regular", + "expression", + "function" + ], + "scripts": { + "test": "nyc mocha", + "mocha": "mocha" + }, + "devDependencies": { + "mocha": "^6.1.3", + "nyc": "^14.0.0" + }, + "engines": { + "node": ">= 8" + } +} diff --git a/homework7/project_express/node_modules/array-flatten/LICENSE b/homework7/project_express/node_modules/array-flatten/LICENSE new file mode 100644 index 0000000..983fbe8 --- /dev/null +++ b/homework7/project_express/node_modules/array-flatten/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) + +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/homework7/project_express/node_modules/array-flatten/README.md b/homework7/project_express/node_modules/array-flatten/README.md new file mode 100644 index 0000000..91fa5b6 --- /dev/null +++ b/homework7/project_express/node_modules/array-flatten/README.md @@ -0,0 +1,43 @@ +# Array Flatten + +[![NPM version][npm-image]][npm-url] +[![NPM downloads][downloads-image]][downloads-url] +[![Build status][travis-image]][travis-url] +[![Test coverage][coveralls-image]][coveralls-url] + +> Flatten an array of nested arrays into a single flat array. Accepts an optional depth. + +## Installation + +``` +npm install array-flatten --save +``` + +## Usage + +```javascript +var flatten = require('array-flatten') + +flatten([1, [2, [3, [4, [5], 6], 7], 8], 9]) +//=> [1, 2, 3, 4, 5, 6, 7, 8, 9] + +flatten([1, [2, [3, [4, [5], 6], 7], 8], 9], 2) +//=> [1, 2, 3, [4, [5], 6], 7, 8, 9] + +(function () { + flatten(arguments) //=> [1, 2, 3] +})(1, [2, 3]) +``` + +## License + +MIT + +[npm-image]: https://img.shields.io/npm/v/array-flatten.svg?style=flat +[npm-url]: https://npmjs.org/package/array-flatten +[downloads-image]: https://img.shields.io/npm/dm/array-flatten.svg?style=flat +[downloads-url]: https://npmjs.org/package/array-flatten +[travis-image]: https://img.shields.io/travis/blakeembrey/array-flatten.svg?style=flat +[travis-url]: https://travis-ci.org/blakeembrey/array-flatten +[coveralls-image]: https://img.shields.io/coveralls/blakeembrey/array-flatten.svg?style=flat +[coveralls-url]: https://coveralls.io/r/blakeembrey/array-flatten?branch=master diff --git a/homework7/project_express/node_modules/array-flatten/array-flatten.js b/homework7/project_express/node_modules/array-flatten/array-flatten.js new file mode 100644 index 0000000..089117b --- /dev/null +++ b/homework7/project_express/node_modules/array-flatten/array-flatten.js @@ -0,0 +1,64 @@ +'use strict' + +/** + * Expose `arrayFlatten`. + */ +module.exports = arrayFlatten + +/** + * Recursive flatten function with depth. + * + * @param {Array} array + * @param {Array} result + * @param {Number} depth + * @return {Array} + */ +function flattenWithDepth (array, result, depth) { + for (var i = 0; i < array.length; i++) { + var value = array[i] + + if (depth > 0 && Array.isArray(value)) { + flattenWithDepth(value, result, depth - 1) + } else { + result.push(value) + } + } + + return result +} + +/** + * Recursive flatten function. Omitting depth is slightly faster. + * + * @param {Array} array + * @param {Array} result + * @return {Array} + */ +function flattenForever (array, result) { + for (var i = 0; i < array.length; i++) { + var value = array[i] + + if (Array.isArray(value)) { + flattenForever(value, result) + } else { + result.push(value) + } + } + + return result +} + +/** + * Flatten an array, with the ability to define a depth. + * + * @param {Array} array + * @param {Number} depth + * @return {Array} + */ +function arrayFlatten (array, depth) { + if (depth == null) { + return flattenForever(array, []) + } + + return flattenWithDepth(array, [], depth) +} diff --git a/homework7/project_express/node_modules/array-flatten/package.json b/homework7/project_express/node_modules/array-flatten/package.json new file mode 100644 index 0000000..81593a2 --- /dev/null +++ b/homework7/project_express/node_modules/array-flatten/package.json @@ -0,0 +1,64 @@ +{ + "_from": "array-flatten@1.1.1", + "_id": "array-flatten@1.1.1", + "_inBundle": false, + "_integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "_location": "/array-flatten", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "array-flatten@1.1.1", + "name": "array-flatten", + "escapedName": "array-flatten", + "rawSpec": "1.1.1", + "saveSpec": null, + "fetchSpec": "1.1.1" + }, + "_requiredBy": [ + "/express" + ], + "_resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "_shasum": "9a5f699051b1e7073328f2a008968b64ea2955d2", + "_spec": "array-flatten@1.1.1", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\express", + "author": { + "name": "Blake Embrey", + "email": "hello@blakeembrey.com", + "url": "http://blakeembrey.me" + }, + "bugs": { + "url": "https://github.com/blakeembrey/array-flatten/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Flatten an array of nested arrays into a single flat array", + "devDependencies": { + "istanbul": "^0.3.13", + "mocha": "^2.2.4", + "pre-commit": "^1.0.7", + "standard": "^3.7.3" + }, + "files": [ + "array-flatten.js", + "LICENSE" + ], + "homepage": "https://github.com/blakeembrey/array-flatten", + "keywords": [ + "array", + "flatten", + "arguments", + "depth" + ], + "license": "MIT", + "main": "array-flatten.js", + "name": "array-flatten", + "repository": { + "type": "git", + "url": "git://github.com/blakeembrey/array-flatten.git" + }, + "scripts": { + "test": "istanbul cover _mocha -- -R spec" + }, + "version": "1.1.1" +} diff --git a/homework7/project_express/node_modules/async/LICENSE b/homework7/project_express/node_modules/async/LICENSE new file mode 100644 index 0000000..b7f9d50 --- /dev/null +++ b/homework7/project_express/node_modules/async/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Caolan McMahon + +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/homework7/project_express/node_modules/async/README.md b/homework7/project_express/node_modules/async/README.md new file mode 100644 index 0000000..951f76e --- /dev/null +++ b/homework7/project_express/node_modules/async/README.md @@ -0,0 +1,1425 @@ +# Async.js + +Async is a utility module which provides straight-forward, powerful functions +for working with asynchronous JavaScript. Although originally designed for +use with [node.js](http://nodejs.org), it can also be used directly in the +browser. Also supports [component](https://github.com/component/component). + +Async provides around 20 functions that include the usual 'functional' +suspects (map, reduce, filter, each…) as well as some common patterns +for asynchronous control flow (parallel, series, waterfall…). All these +functions assume you follow the node.js convention of providing a single +callback as the last argument of your async function. + + +## Quick Examples + +```javascript +async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file +}); + +async.filter(['file1','file2','file3'], fs.exists, function(results){ + // results now equals an array of the existing files +}); + +async.parallel([ + function(){ ... }, + function(){ ... } +], callback); + +async.series([ + function(){ ... }, + function(){ ... } +]); +``` + +There are many more functions available so take a look at the docs below for a +full list. This module aims to be comprehensive, so if you feel anything is +missing please create a GitHub issue for it. + +## Common Pitfalls + +### Binding a context to an iterator + +This section is really about bind, not about async. If you are wondering how to +make async execute your iterators in a given context, or are confused as to why +a method of another library isn't working as an iterator, study this example: + +```js +// Here is a simple object with an (unnecessarily roundabout) squaring method +var AsyncSquaringLibrary = { + squareExponent: 2, + square: function(number, callback){ + var result = Math.pow(number, this.squareExponent); + setTimeout(function(){ + callback(null, result); + }, 200); + } +}; + +async.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){ + // result is [NaN, NaN, NaN] + // This fails because the `this.squareExponent` expression in the square + // function is not evaluated in the context of AsyncSquaringLibrary, and is + // therefore undefined. +}); + +async.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){ + // result is [1, 4, 9] + // With the help of bind we can attach a context to the iterator before + // passing it to async. Now the square function will be executed in its + // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent` + // will be as expected. +}); +``` + +## Download + +The source is available for download from +[GitHub](http://github.com/caolan/async). +Alternatively, you can install using Node Package Manager (npm): + + npm install async + +__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed + +## In the Browser + +So far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage: + +```html + + +``` + +## Documentation + +### Collections + +* [each](#each) +* [eachSeries](#eachSeries) +* [eachLimit](#eachLimit) +* [map](#map) +* [mapSeries](#mapSeries) +* [mapLimit](#mapLimit) +* [filter](#filter) +* [filterSeries](#filterSeries) +* [reject](#reject) +* [rejectSeries](#rejectSeries) +* [reduce](#reduce) +* [reduceRight](#reduceRight) +* [detect](#detect) +* [detectSeries](#detectSeries) +* [sortBy](#sortBy) +* [some](#some) +* [every](#every) +* [concat](#concat) +* [concatSeries](#concatSeries) + +### Control Flow + +* [series](#series) +* [parallel](#parallel) +* [parallelLimit](#parallellimittasks-limit-callback) +* [whilst](#whilst) +* [doWhilst](#doWhilst) +* [until](#until) +* [doUntil](#doUntil) +* [forever](#forever) +* [waterfall](#waterfall) +* [compose](#compose) +* [applyEach](#applyEach) +* [applyEachSeries](#applyEachSeries) +* [queue](#queue) +* [cargo](#cargo) +* [auto](#auto) +* [iterator](#iterator) +* [apply](#apply) +* [nextTick](#nextTick) +* [times](#times) +* [timesSeries](#timesSeries) + +### Utils + +* [memoize](#memoize) +* [unmemoize](#unmemoize) +* [log](#log) +* [dir](#dir) +* [noConflict](#noConflict) + + +## Collections + + + +### each(arr, iterator, callback) + +Applies an iterator function to each item in an array, in parallel. +The iterator is called with an item from the list and a callback for when it +has finished. If the iterator passes an error to this callback, the main +callback for the each function is immediately called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err) which must be called once it has + completed. If no error has occured, the callback should be run without + arguments or with an explicit null argument. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + +```js +// assuming openFiles is an array of file names and saveFile is a function +// to save the modified contents of that file: + +async.each(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error +}); +``` + +--------------------------------------- + + + +### eachSeries(arr, iterator, callback) + +The same as each only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. This means the iterator functions will complete in order. + + +--------------------------------------- + + + +### eachLimit(arr, limit, iterator, callback) + +The same as each only no more than "limit" iterators will be simultaneously +running at any time. + +Note that the items are not processed in batches, so there is no guarantee that + the first "limit" iterator functions will complete before any others are +started. + +__Arguments__ + +* arr - An array to iterate over. +* limit - The maximum number of iterators to run at any time. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err) which must be called once it has + completed. If no error has occured, the callback should be run without + arguments or with an explicit null argument. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + +```js +// Assume documents is an array of JSON objects and requestApi is a +// function that interacts with a rate-limited REST api. + +async.eachLimit(documents, 20, requestApi, function(err){ + // if any of the saves produced an error, err would equal that error +}); +``` + +--------------------------------------- + + +### map(arr, iterator, callback) + +Produces a new array of values by mapping each value in the given array through +the iterator function. The iterator is called with an item from the array and a +callback for when it has finished processing. The callback takes 2 arguments, +an error and the transformed item from the array. If the iterator passes an +error to this callback, the main callback for the map function is immediately +called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order, however +the results array will be in the same order as the original array. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, transformed) which must be called once + it has completed with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + +```js +async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file +}); +``` + +--------------------------------------- + + +### mapSeries(arr, iterator, callback) + +The same as map only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +--------------------------------------- + + +### mapLimit(arr, limit, iterator, callback) + +The same as map only no more than "limit" iterators will be simultaneously +running at any time. + +Note that the items are not processed in batches, so there is no guarantee that + the first "limit" iterator functions will complete before any others are +started. + +__Arguments__ + +* arr - An array to iterate over. +* limit - The maximum number of iterators to run at any time. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, transformed) which must be called once + it has completed with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + +```js +async.mapLimit(['file1','file2','file3'], 1, fs.stat, function(err, results){ + // results is now an array of stats for each file +}); +``` + +--------------------------------------- + + +### filter(arr, iterator, callback) + +__Alias:__ select + +Returns a new array of all the values which pass an async truth test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like fs.exists. This operation is +performed in parallel, but the results array will be in the same order as the +original. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(results) - A callback which is called after all the iterator + functions have finished. + +__Example__ + +```js +async.filter(['file1','file2','file3'], fs.exists, function(results){ + // results now equals an array of the existing files +}); +``` + +--------------------------------------- + + +### filterSeries(arr, iterator, callback) + +__alias:__ selectSeries + +The same as filter only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + +--------------------------------------- + + +### reject(arr, iterator, callback) + +The opposite of filter. Removes values that pass an async truth test. + +--------------------------------------- + + +### rejectSeries(arr, iterator, callback) + +The same as reject, only the iterator is applied to each item in the array +in series. + + +--------------------------------------- + + +### reduce(arr, memo, iterator, callback) + +__aliases:__ inject, foldl + +Reduces a list of values into a single value using an async iterator to return +each successive step. Memo is the initial state of the reduction. This +function only operates in series. For performance reasons, it may make sense to +split a call to this function into a parallel map, then use the normal +Array.prototype.reduce on the results. This function is for situations where +each step in the reduction needs to be async, if you can get the data before +reducing it then it's probably a good idea to do so. + +__Arguments__ + +* arr - An array to iterate over. +* memo - The initial state of the reduction. +* iterator(memo, item, callback) - A function applied to each item in the + array to produce the next step in the reduction. The iterator is passed a + callback(err, reduction) which accepts an optional error as its first + argument, and the state of the reduction as the second. If an error is + passed to the callback, the reduction is stopped and the main callback is + immediately called with the error. +* callback(err, result) - A callback which is called after all the iterator + functions have finished. Result is the reduced value. + +__Example__ + +```js +async.reduce([1,2,3], 0, function(memo, item, callback){ + // pointless async: + process.nextTick(function(){ + callback(null, memo + item) + }); +}, function(err, result){ + // result is now equal to the last value of memo, which is 6 +}); +``` + +--------------------------------------- + + +### reduceRight(arr, memo, iterator, callback) + +__Alias:__ foldr + +Same as reduce, only operates on the items in the array in reverse order. + + +--------------------------------------- + + +### detect(arr, iterator, callback) + +Returns the first value in a list that passes an async truth test. The +iterator is applied in parallel, meaning the first iterator to return true will +fire the detect callback with that result. That means the result might not be +the first item in the original array (in terms of order) that passes the test. + +If order within the original array is important then look at detectSeries. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + the first item in the array that passes the truth test (iterator) or the + value undefined if none passed. + +__Example__ + +```js +async.detect(['file1','file2','file3'], fs.exists, function(result){ + // result now equals the first file in the list that exists +}); +``` + +--------------------------------------- + + +### detectSeries(arr, iterator, callback) + +The same as detect, only the iterator is applied to each item in the array +in series. This means the result is always the first in the original array (in +terms of array order) that passes the truth test. + + +--------------------------------------- + + +### sortBy(arr, iterator, callback) + +Sorts a list by the results of running each value through an async iterator. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, sortValue) which must be called once it + has completed with an error (which can be null) and a value to use as the sort + criteria. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is the items from + the original array sorted by the values returned by the iterator calls. + +__Example__ + +```js +async.sortBy(['file1','file2','file3'], function(file, callback){ + fs.stat(file, function(err, stats){ + callback(err, stats.mtime); + }); +}, function(err, results){ + // results is now the original array of files sorted by + // modified date +}); +``` + +--------------------------------------- + + +### some(arr, iterator, callback) + +__Alias:__ any + +Returns true if at least one element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like fs.exists. Once any iterator +call returns true, the main callback is immediately called. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + either true or false depending on the values of the async tests. + +__Example__ + +```js +async.some(['file1','file2','file3'], fs.exists, function(result){ + // if result is true then at least one of the files exists +}); +``` + +--------------------------------------- + + +### every(arr, iterator, callback) + +__Alias:__ all + +Returns true if every element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like fs.exists. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(result) - A callback which is called after all the iterator + functions have finished. Result will be either true or false depending on + the values of the async tests. + +__Example__ + +```js +async.every(['file1','file2','file3'], fs.exists, function(result){ + // if result is true then every file exists +}); +``` + +--------------------------------------- + + +### concat(arr, iterator, callback) + +Applies an iterator to each item in a list, concatenating the results. Returns the +concatenated list. The iterators are called in parallel, and the results are +concatenated as they return. There is no guarantee that the results array will +be returned in the original order of the arguments passed to the iterator function. + +__Arguments__ + +* arr - An array to iterate over +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, results) which must be called once it + has completed with an error (which can be null) and an array of results. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array containing + the concatenated results of the iterator function. + +__Example__ + +```js +async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories +}); +``` + +--------------------------------------- + + +### concatSeries(arr, iterator, callback) + +Same as async.concat, but executes in series instead of parallel. + + +## Control Flow + + +### series(tasks, [callback]) + +Run an array of functions in series, each one running once the previous +function has completed. If any functions in the series pass an error to its +callback, no more functions are run and the callback for the series is +immediately called with the value of the error. Once the tasks have completed, +the results are passed to the final callback as an array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.series. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback(err, result) it must call on completion with an error (which can + be null) and an optional result value. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +__Example__ + +```js +async.series([ + function(callback){ + // do some stuff ... + callback(null, 'one'); + }, + function(callback){ + // do some more stuff ... + callback(null, 'two'); + } +], +// optional callback +function(err, results){ + // results is now equal to ['one', 'two'] +}); + + +// an example using an object instead of an array +async.series({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + } +}, +function(err, results) { + // results is now equal to: {one: 1, two: 2} +}); +``` + +--------------------------------------- + + +### parallel(tasks, [callback]) + +Run an array of functions in parallel, without waiting until the previous +function has completed. If any of the functions pass an error to its +callback, the main callback is immediately called with the value of the error. +Once the tasks have completed, the results are passed to the final callback as an +array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.parallel. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback(err, result) it must call on completion with an error (which can + be null) and an optional result value. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +__Example__ + +```js +async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + } +], +// optional callback +function(err, results){ + // the results array will equal ['one','two'] even though + // the second function had a shorter timeout. +}); + + +// an example using an object instead of an array +async.parallel({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + } +}, +function(err, results) { + // results is now equals to: {one: 1, two: 2} +}); +``` + +--------------------------------------- + + +### parallelLimit(tasks, limit, [callback]) + +The same as parallel only the tasks are executed in parallel with a maximum of "limit" +tasks executing at any time. + +Note that the tasks are not executed in batches, so there is no guarantee that +the first "limit" tasks will complete before any others are started. + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback(err, result) it must call on completion with an error (which can + be null) and an optional result value. +* limit - The maximum number of tasks to run at any time. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +--------------------------------------- + + +### whilst(test, fn, callback) + +Repeatedly call fn, while test returns true. Calls the callback when stopped, +or an error occurs. + +__Arguments__ + +* test() - synchronous truth test to perform before each execution of fn. +* fn(callback) - A function to call each time the test passes. The function is + passed a callback(err) which must be called once it has completed with an + optional error argument. +* callback(err) - A callback which is called after the test fails and repeated + execution of fn has stopped. + +__Example__ + +```js +var count = 0; + +async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } +); +``` + +--------------------------------------- + + +### doWhilst(fn, test, callback) + +The post check version of whilst. To reflect the difference in the order of operations `test` and `fn` arguments are switched. `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript. + +--------------------------------------- + + +### until(test, fn, callback) + +Repeatedly call fn, until test returns true. Calls the callback when stopped, +or an error occurs. + +The inverse of async.whilst. + +--------------------------------------- + + +### doUntil(fn, test, callback) + +Like doWhilst except the test is inverted. Note the argument ordering differs from `until`. + +--------------------------------------- + + +### forever(fn, callback) + +Calls the asynchronous function 'fn' repeatedly, in series, indefinitely. +If an error is passed to fn's callback then 'callback' is called with the +error, otherwise it will never be called. + +--------------------------------------- + + +### waterfall(tasks, [callback]) + +Runs an array of functions in series, each passing their results to the next in +the array. However, if any of the functions pass an error to the callback, the +next function is not executed and the main callback is immediately called with +the error. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a + callback(err, result1, result2, ...) it must call on completion. The first + argument is an error (which can be null) and any further arguments will be + passed as arguments in order to the next task. +* callback(err, [results]) - An optional callback to run once all the functions + have completed. This will be passed the results of the last task's callback. + + + +__Example__ + +```js +async.waterfall([ + function(callback){ + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + callback(null, 'three'); + }, + function(arg1, callback){ + // arg1 now equals 'three' + callback(null, 'done'); + } +], function (err, result) { + // result now equals 'done' +}); +``` + +--------------------------------------- + +### compose(fn1, fn2...) + +Creates a function which is a composition of the passed asynchronous +functions. Each function consumes the return value of the function that +follows. Composing functions f(), g() and h() would produce the result of +f(g(h())), only this version uses callbacks to obtain the return values. + +Each function is executed with the `this` binding of the composed function. + +__Arguments__ + +* functions... - the asynchronous functions to compose + + +__Example__ + +```js +function add1(n, callback) { + setTimeout(function () { + callback(null, n + 1); + }, 10); +} + +function mul3(n, callback) { + setTimeout(function () { + callback(null, n * 3); + }, 10); +} + +var add1mul3 = async.compose(mul3, add1); + +add1mul3(4, function (err, result) { + // result now equals 15 +}); +``` + +--------------------------------------- + +### applyEach(fns, args..., callback) + +Applies the provided arguments to each function in the array, calling the +callback after all functions have completed. If you only provide the first +argument then it will return a function which lets you pass in the +arguments as if it were a single function call. + +__Arguments__ + +* fns - the asynchronous functions to all call with the same arguments +* args... - any number of separate arguments to pass to the function +* callback - the final argument should be the callback, called when all + functions have completed processing + + +__Example__ + +```js +async.applyEach([enableSearch, updateSchema], 'bucket', callback); + +// partial application example: +async.each( + buckets, + async.applyEach([enableSearch, updateSchema]), + callback +); +``` + +--------------------------------------- + + +### applyEachSeries(arr, iterator, callback) + +The same as applyEach only the functions are applied in series. + +--------------------------------------- + + +### queue(worker, concurrency) + +Creates a queue object with the specified concurrency. Tasks added to the +queue will be processed in parallel (up to the concurrency limit). If all +workers are in progress, the task is queued until one is available. Once +a worker has completed a task, the task's callback is called. + +__Arguments__ + +* worker(task, callback) - An asynchronous function for processing a queued + task, which must call its callback(err) argument when finished, with an + optional error as an argument. +* concurrency - An integer for determining how many worker functions should be + run in parallel. + +__Queue objects__ + +The queue object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* concurrency - an integer for determining how many worker functions should be + run in parallel. This property can be changed after a queue is created to + alter the concurrency on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. + instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list. +* unshift(task, [callback]) - add a new task to the front of the queue. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + +```js +// create a queue object with concurrency 2 + +var q = async.queue(function (task, callback) { + console.log('hello ' + task.name); + callback(); +}, 2); + + +// assign a callback +q.drain = function() { + console.log('all items have been processed'); +} + +// add some items to the queue + +q.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); +}); +q.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); +}); + +// add some items to the queue (batch-wise) + +q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) { + console.log('finished processing bar'); +}); + +// add some items to the front of the queue + +q.unshift({name: 'bar'}, function (err) { + console.log('finished processing bar'); +}); +``` + +--------------------------------------- + + +### cargo(worker, [payload]) + +Creates a cargo object with the specified payload. Tasks added to the +cargo will be processed altogether (up to the payload limit). If the +worker is in progress, the task is queued until it is available. Once +the worker has completed some tasks, each callback of those tasks is called. + +__Arguments__ + +* worker(tasks, callback) - An asynchronous function for processing an array of + queued tasks, which must call its callback(err) argument when finished, with + an optional error as an argument. +* payload - An optional integer for determining how many tasks should be + processed per round; if omitted, the default is unlimited. + +__Cargo objects__ + +The cargo object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* payload - an integer for determining how many tasks should be + process per round. This property can be changed after a cargo is created to + alter the payload on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. + instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + +```js +// create a cargo object with payload 2 + +var cargo = async.cargo(function (tasks, callback) { + for(var i=0; i +### auto(tasks, [callback]) + +Determines the best order for running functions based on their requirements. +Each function can optionally depend on other functions being completed first, +and each function is run as soon as its requirements are satisfied. If any of +the functions pass an error to their callback, that function will not complete +(so any other functions depending on it will not run) and the main callback +will be called immediately with the error. Functions also receive an object +containing the results of functions which have completed so far. + +Note, all functions are called with a results object as a second argument, +so it is unsafe to pass functions in the tasks object which cannot handle the +extra argument. For example, this snippet of code: + +```js +async.auto({ + readData: async.apply(fs.readFile, 'data.txt', 'utf-8') +}, callback); +``` + +will have the effect of calling readFile with the results object as the last +argument, which will fail: + +```js +fs.readFile('data.txt', 'utf-8', cb, {}); +``` + +Instead, wrap the call to readFile in a function which does not forward the +results object: + +```js +async.auto({ + readData: function(cb, results){ + fs.readFile('data.txt', 'utf-8', cb); + } +}, callback); +``` + +__Arguments__ + +* tasks - An object literal containing named functions or an array of + requirements, with the function itself the last item in the array. The key + used for each function or array is used when specifying requirements. The + function receives two arguments: (1) a callback(err, result) which must be + called when finished, passing an error (which can be null) and the result of + the function's execution, and (2) a results object, containing the results of + the previously executed functions. +* callback(err, results) - An optional callback which is called when all the + tasks have been completed. The callback will receive an error as an argument + if any tasks pass an error to their callback. Results will always be passed + but if an error occurred, no other tasks will be performed, and the results + object will only contain partial results. + + +__Example__ + +```js +async.auto({ + get_data: function(callback){ + // async code to get some data + }, + make_folder: function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + }, + write_file: ['get_data', 'make_folder', function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + callback(null, filename); + }], + email_link: ['write_file', function(callback, results){ + // once the file is written let's email a link to it... + // results.write_file contains the filename returned by write_file. + }] +}); +``` + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + +```js +async.parallel([ + function(callback){ + // async code to get some data + }, + function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + } +], +function(err, results){ + async.series([ + function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + }, + function(callback){ + // once the file is written let's email a link to it... + } + ]); +}); +``` + +For a complicated series of async tasks using the auto function makes adding +new tasks much easier and makes the code more readable. + + +--------------------------------------- + + +### iterator(tasks) + +Creates an iterator function which calls the next function in the array, +returning a continuation to call the next one after that. It's also possible to +'peek' the next iterator by doing iterator.next(). + +This function is used internally by the async module but can be useful when +you want to manually control the flow of functions in series. + +__Arguments__ + +* tasks - An array of functions to run. + +__Example__ + +```js +var iterator = async.iterator([ + function(){ sys.p('one'); }, + function(){ sys.p('two'); }, + function(){ sys.p('three'); } +]); + +node> var iterator2 = iterator(); +'one' +node> var iterator3 = iterator2(); +'two' +node> iterator3(); +'three' +node> var nextfn = iterator2.next(); +node> nextfn(); +'three' +``` + +--------------------------------------- + + +### apply(function, arguments..) + +Creates a continuation function with some arguments already applied, a useful +shorthand when combined with other control flow functions. Any arguments +passed to the returned function are added to the arguments originally passed +to apply. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to automatically apply when the + continuation is called. + +__Example__ + +```js +// using apply + +async.parallel([ + async.apply(fs.writeFile, 'testfile1', 'test1'), + async.apply(fs.writeFile, 'testfile2', 'test2'), +]); + + +// the same process without using apply + +async.parallel([ + function(callback){ + fs.writeFile('testfile1', 'test1', callback); + }, + function(callback){ + fs.writeFile('testfile2', 'test2', callback); + } +]); +``` + +It's possible to pass any number of additional arguments when calling the +continuation: + +```js +node> var fn = async.apply(sys.puts, 'one'); +node> fn('two', 'three'); +one +two +three +``` + +--------------------------------------- + + +### nextTick(callback) + +Calls the callback on a later loop around the event loop. In node.js this just +calls process.nextTick, in the browser it falls back to setImmediate(callback) +if available, otherwise setTimeout(callback, 0), which means other higher priority +events may precede the execution of the callback. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* callback - The function to call on a later loop around the event loop. + +__Example__ + +```js +var call_order = []; +async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two'] +}); +call_order.push('one') +``` + + +### times(n, callback) + +Calls the callback n times and accumulates results in the same manner +you would use with async.map. + +__Arguments__ + +* n - The number of times to run the function. +* callback - The function to call n times. + +__Example__ + +```js +// Pretend this is some complicated async factory +var createUser = function(id, callback) { + callback(null, { + id: 'user' + id + }) +} +// generate 5 users +async.times(5, function(n, next){ + createUser(n, function(err, user) { + next(err, user) + }) +}, function(err, users) { + // we should now have 5 users +}); +``` + + +### timesSeries(n, callback) + +The same as times only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +## Utils + + +### memoize(fn, [hasher]) + +Caches the results of an async function. When creating a hash to store function +results against, the callback is omitted from the hash and an optional hash +function can be used. + +The cache of results is exposed as the `memo` property of the function returned +by `memoize`. + +__Arguments__ + +* fn - the function you to proxy and cache results from. +* hasher - an optional function for generating a custom hash for storing + results, it has all the arguments applied to it apart from the callback, and + must be synchronous. + +__Example__ + +```js +var slow_fn = function (name, callback) { + // do something + callback(null, result); +}; +var fn = async.memoize(slow_fn); + +// fn can now be used as if it were slow_fn +fn('some name', function () { + // callback +}); +``` + + +### unmemoize(fn) + +Undoes a memoized function, reverting it to the original, unmemoized +form. Comes handy in tests. + +__Arguments__ + +* fn - the memoized function + + +### log(function, arguments) + +Logs the result of an async function to the console. Only works in node.js or +in browsers that support console.log and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.log is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + +```js +var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); +}; +``` +```js +node> async.log(hello, 'world'); +'hello world' +``` + +--------------------------------------- + + +### dir(function, arguments) + +Logs the result of an async function to the console using console.dir to +display the properties of the resulting object. Only works in node.js or +in browsers that support console.dir and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.dir is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + +```js +var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); +}; +``` +```js +node> async.dir(hello, 'world'); +{hello: 'world'} +``` + +--------------------------------------- + + +### noConflict() + +Changes the value of async back to its original value, returning a reference to the +async object. diff --git a/homework7/project_express/node_modules/async/component.json b/homework7/project_express/node_modules/async/component.json new file mode 100644 index 0000000..bbb0115 --- /dev/null +++ b/homework7/project_express/node_modules/async/component.json @@ -0,0 +1,11 @@ +{ + "name": "async", + "repo": "caolan/async", + "description": "Higher-order functions and common patterns for asynchronous code", + "version": "0.1.23", + "keywords": [], + "dependencies": {}, + "development": {}, + "main": "lib/async.js", + "scripts": [ "lib/async.js" ] +} diff --git a/homework7/project_express/node_modules/async/lib/async.js b/homework7/project_express/node_modules/async/lib/async.js new file mode 100644 index 0000000..1eebb15 --- /dev/null +++ b/homework7/project_express/node_modules/async/lib/async.js @@ -0,0 +1,958 @@ +/*global setImmediate: false, setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root, previous_async; + + root = this; + if (root != null) { + previous_async = root.async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + function only_once(fn) { + var called = false; + return function() { + if (called) throw new Error("Callback was already called."); + called = true; + fn.apply(root, arguments); + } + } + + //// cross-browser compatiblity functions //// + + var _each = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _each(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _each(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + if (typeof setImmediate === 'function') { + async.nextTick = function (fn) { + // not a direct alias for IE10 compatibility + setImmediate(fn); + }; + async.setImmediate = async.nextTick; + } + else { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + async.setImmediate = async.nextTick; + } + } + else { + async.nextTick = process.nextTick; + if (typeof setImmediate !== 'undefined') { + async.setImmediate = function (fn) { + // not a direct alias for IE10 compatibility + setImmediate(fn); + }; + } + else { + async.setImmediate = async.nextTick; + } + } + + async.each = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + _each(arr, function (x) { + iterator(x, only_once(function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed >= arr.length) { + callback(null); + } + } + })); + }); + }; + async.forEach = async.each; + + async.eachSeries = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed >= arr.length) { + callback(null); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + async.forEachSeries = async.eachSeries; + + async.eachLimit = function (arr, limit, iterator, callback) { + var fn = _eachLimit(limit); + fn.apply(null, [arr, iterator, callback]); + }; + async.forEachLimit = async.eachLimit; + + var _eachLimit = function (limit) { + + return function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed >= arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + started += 1; + running += 1; + iterator(arr[started - 1], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed >= arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + } + })(); + }; + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.each].concat(args)); + }; + }; + var doParallelLimit = function(limit, fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [_eachLimit(limit)].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.eachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + async.mapLimit = function (arr, limit, iterator, callback) { + return _mapLimit(limit)(arr, iterator, callback); + }; + + var _mapLimit = function(limit) { + return doParallelLimit(limit, _asyncMap); + }; + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.eachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + main_callback = function () {}; + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + async.sortBy = function (arr, iterator, callback) { + async.map(arr, function (x, callback) { + iterator(x, function (err, criteria) { + if (err) { + callback(err); + } + else { + callback(null, {value: x, criteria: criteria}); + } + }); + }, function (err, results) { + if (err) { + return callback(err); + } + else { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var results = {}; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _each(listeners.slice(0), function (fn) { + fn(); + }); + }; + + addListener(function () { + if (_keys(results).length === keys.length) { + callback(null, results); + callback = function () {}; + } + }); + + _each(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + if (err) { + var safeResults = {}; + _each(_keys(results), function(rkey) { + safeResults[rkey] = results[rkey]; + }); + safeResults[k] = args; + callback(err, safeResults); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + results[k] = args; + async.setImmediate(taskComplete); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true) && !results.hasOwnProperty(k); + }; + if (ready()) { + task[task.length - 1](taskCallback, results); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor !== Array) { + var err = new Error('First argument to waterfall must be an array of functions'); + return callback(err); + } + if (!tasks.length) { + return callback(); + } + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback.apply(null, arguments); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.setImmediate(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + var _parallel = function(eachfn, tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + eachfn.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + eachfn.each(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.parallel = function (tasks, callback) { + _parallel({ map: async.map, each: async.each }, tasks, callback); + }; + + async.parallelLimit = function(tasks, limit, callback) { + _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback); + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.eachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + if (tasks.length) { + tasks[index].apply(null, arguments); + } + return fn.next(); + }; + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1): null; + }; + return fn; + }; + return makeCallback(0); + }; + + async.apply = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.doWhilst = function (iterator, test, callback) { + iterator(function (err) { + if (err) { + return callback(err); + } + if (test()) { + async.doWhilst(iterator, test, callback); + } + else { + callback(); + } + }); + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.doUntil = function (iterator, test, callback) { + iterator(function (err) { + if (err) { + return callback(err); + } + if (!test()) { + async.doUntil(iterator, test, callback); + } + else { + callback(); + } + }); + }; + + async.queue = function (worker, concurrency) { + if (concurrency === undefined) { + concurrency = 1; + } + function _insert(q, data, pos, callback) { + if(data.constructor !== Array) { + data = [data]; + } + _each(data, function(task) { + var item = { + data: task, + callback: typeof callback === 'function' ? callback : null + }; + + if (pos) { + q.tasks.unshift(item); + } else { + q.tasks.push(item); + } + + if (q.saturated && q.tasks.length === concurrency) { + q.saturated(); + } + async.setImmediate(q.process); + }); + } + + var workers = 0; + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + _insert(q, data, false, callback); + }, + unshift: function (data, callback) { + _insert(q, data, true, callback); + }, + process: function () { + if (workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift(); + if (q.empty && q.tasks.length === 0) { + q.empty(); + } + workers += 1; + var next = function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if (q.drain && q.tasks.length + workers === 0) { + q.drain(); + } + q.process(); + }; + var cb = only_once(next); + worker(task.data, cb); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + } + }; + return q; + }; + + async.cargo = function (worker, payload) { + var working = false, + tasks = []; + + var cargo = { + tasks: tasks, + payload: payload, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + if(data.constructor !== Array) { + data = [data]; + } + _each(data, function(task) { + tasks.push({ + data: task, + callback: typeof callback === 'function' ? callback : null + }); + if (cargo.saturated && tasks.length === payload) { + cargo.saturated(); + } + }); + async.setImmediate(cargo.process); + }, + process: function process() { + if (working) return; + if (tasks.length === 0) { + if(cargo.drain) cargo.drain(); + return; + } + + var ts = typeof payload === 'number' + ? tasks.splice(0, payload) + : tasks.splice(0); + + var ds = _map(ts, function (task) { + return task.data; + }); + + if(cargo.empty) cargo.empty(); + working = true; + worker(ds, function () { + working = false; + + var args = arguments; + _each(ts, function (data) { + if (data.callback) { + data.callback.apply(null, args); + } + }); + + process(); + }); + }, + length: function () { + return tasks.length; + }, + running: function () { + return working; + } + }; + return cargo; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _each(args, function (x) { + console[name](x); + }); + } + } + }])); + }; + }; + async.log = _console_fn('log'); + async.dir = _console_fn('dir'); + /*async.info = _console_fn('info'); + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ + + async.memoize = function (fn, hasher) { + var memo = {}; + var queues = {}; + hasher = hasher || function (x) { + return x; + }; + var memoized = function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else if (key in queues) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([function () { + memo[key] = arguments; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments); + } + }])); + } + }; + memoized.memo = memo; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + }; + }; + + async.times = function (count, iterator, callback) { + var counter = []; + for (var i = 0; i < count; i++) { + counter.push(i); + } + return async.map(counter, iterator, callback); + }; + + async.timesSeries = function (count, iterator, callback) { + var counter = []; + for (var i = 0; i < count; i++) { + counter.push(i); + } + return async.mapSeries(counter, iterator, callback); + }; + + async.compose = function (/* functions... */) { + var fns = Array.prototype.reverse.call(arguments); + return function () { + var that = this; + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + async.reduce(fns, args, function (newargs, fn, cb) { + fn.apply(that, newargs.concat([function () { + var err = arguments[0]; + var nextargs = Array.prototype.slice.call(arguments, 1); + cb(err, nextargs); + }])) + }, + function (err, results) { + callback.apply(that, [err].concat(results)); + }); + }; + }; + + var _applyEach = function (eachfn, fns /*args...*/) { + var go = function () { + var that = this; + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + return eachfn(fns, function (fn, cb) { + fn.apply(that, args.concat([cb])); + }, + callback); + }; + if (arguments.length > 2) { + var args = Array.prototype.slice.call(arguments, 2); + return go.apply(this, args); + } + else { + return go; + } + }; + async.applyEach = doParallel(_applyEach); + async.applyEachSeries = doSeries(_applyEach); + + async.forever = function (fn, callback) { + function next(err) { + if (err) { + if (callback) { + return callback(err); + } + throw err; + } + fn(next); + } + next(); + }; + + // AMD / RequireJS + if (typeof define !== 'undefined' && define.amd) { + define([], function () { + return async; + }); + } + // Node.js + else if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + // included directly via + +This is like calling require('client') from inside ./example. +[Read more on node's require path resolution](http://nodejs.org/api/modules.html) + +Compile +======= +(You'll want to do this before you deploy to production) + + require compile ./example/client.js > client.min.js + +Use programmatically +==================== +In node: + + require('require/server').listen(1234) + +or mount it on an http server you're already running + + var server = http.createServer(function(req, res) { }) + require('require/server').mount(server) + server.listen(8080, 'localhost') + +or, as connect middleware + + connect.createServer( + connect.static(__dirname + '/example'), + require('require/server').connect() + ) + +Compile programmatically: + + var compiler = require('require/compiler') + console.log(compiler.compile('./example/client.js')) + console.log(compiler.compileCode('require("./example/client")')) + +The compiler supports all the options of https://github.com/mishoo/UglifyJS, e.g. + + compiler.compile('./example/client.js', { beautify:true, ascii_only:true }) diff --git a/homework7/project_express/node_modules/require/bin/require-command.js b/homework7/project_express/node_modules/require/bin/require-command.js new file mode 100644 index 0000000..6211b0b --- /dev/null +++ b/homework7/project_express/node_modules/require/bin/require-command.js @@ -0,0 +1,69 @@ +#!/usr/bin/env node + +var path = require('path'), + server = require('../server'), + compiler = require('../compiler') + +var opts = { + port: 1234, + host: 'localhost', + command: null, + path: null +} + +var args = [].slice.call(process.argv, 2) + +opts.command = args.shift() +opts.path = path.resolve(args.shift()) + +while (args.length) { + var arg = args.shift() + switch(arg) { + case '--port': + opts.port = args.shift() + break + case '--host': + opts.host = args.shift() + break + case '--root': + opts.root = args.shift() + break + case '--usePagePort': + if (args[0] && args[0][0] != '-') { + console.log('Unexpected value for --usePagePort flag', args[0]) + process.exit(1) + } + opts.usePagePort = true + break + default: + console.log('Unknown option', arg) + process.exit(1) + break + } +} + +switch (opts.command) { + case 'serve': + if (!opts.path) { + console.log('Specify a path to serve from, e.g. require serve ./example') + process.exit(1) + } + server.listen(opts) + console.log('serving from', opts.path, 'on', 'http://'+opts.host+':'+opts.port) + break + case 'compile': + if (!opts.path) { + console.log('Specify a single file to compile, e.g. require compile ./path/to/file.js') + process.exit(1) + } + console.log(compiler.compile(opts.path)) + break + default: + if (opts.command) { + console.log('Unknown command', '"' + opts.command + '".', 'Try "require serve" or "require compile"') + } else { + console.log('You need to give a command, e.g. "require serve" or "require compile"') + } + process.exit(1) +} + diff --git a/homework7/project_express/node_modules/require/compiler.js b/homework7/project_express/node_modules/require/compiler.js new file mode 100644 index 0000000..ff30f51 --- /dev/null +++ b/homework7/project_express/node_modules/require/compiler.js @@ -0,0 +1,162 @@ +var fs = require('fs') +var path = require('path') +var extend = require('std/extend') +var each = require('std/each') +var getCode = require('./lib/getCode') +var resolve = require('./lib/resolve') +var getRequireStatements = require('./lib/getRequireStatements') + +module.exports = { + compile: compileFile, + compileHTML: compileHTMLFile, + compileCode: compileCode +} + +/* api + *****/ +function compileFile(filePath, opts) { + filePath = path.resolve(filePath) + opts = extend(opts, { basePath:path.dirname(filePath), toplevel:true }) + var code = getCode(filePath) + return _compile(code, opts, filePath) +} + +function compileCode(code, opts) { + opts = extend(opts, { basePath:process.cwd(), toplevel:true }) + return _compile(code, opts, '') +} + +function compileHTMLFile(filePath, opts) { + var html = fs.readFileSync(filePath).toString() + while (match = html.match(/') + html = html.replace(BACKREFERENCE_WORKAROUND, '\$\&') + } + return html +} + + +var _compile = function(code, opts, mainModule) { + var code = 'var __require__ = {}, require=function(){}\n' + _compileModule(code, opts.basePath, mainModule) + if (opts.minify === false) { return code } // TODO use uglifyjs' beautifier? + + var UglifyJS = require('uglify-js') + var result = UglifyJS.minify(code, { + fromString:true, + mangle:true, + output: { + // http://lisperator.net/uglifyjs/codegen + indent_start : 0, // start indentation on every line (only when `beautify`) + indent_level : 4, // indentation level (only when `beautify`) + quote_keys : false, // quote all keys in object literals? + space_colon : true, // add a space after colon signs? + ascii_only : false, // output ASCII-safe? (encodes Unicode characters as ASCII) + inline_script : false, // escape " + + + test + + + + diff --git a/homework7/project_express/node_modules/require/example/package.json b/homework7/project_express/node_modules/require/example/package.json new file mode 100644 index 0000000..4a43812 --- /dev/null +++ b/homework7/project_express/node_modules/require/example/package.json @@ -0,0 +1,16 @@ +{ + "author": "", + "name": "testApp", + "version": "0.0.0", + "repository": { + "url": "" + }, + "directories": { + "lib": "." + }, + "engines": { + "node": "*" + }, + "dependencies": {}, + "devDependencies": {} +} \ No newline at end of file diff --git a/homework7/project_express/node_modules/require/example/raphael_circle.html b/homework7/project_express/node_modules/require/example/raphael_circle.html new file mode 100644 index 0000000..86e0c30 --- /dev/null +++ b/homework7/project_express/node_modules/require/example/raphael_circle.html @@ -0,0 +1,4 @@ + + + + diff --git a/homework7/project_express/node_modules/require/example/raphael_circle.js b/homework7/project_express/node_modules/require/example/raphael_circle.js new file mode 100644 index 0000000..0c6e1c6 --- /dev/null +++ b/homework7/project_express/node_modules/require/example/raphael_circle.js @@ -0,0 +1,5 @@ +var raphael = require('raphael'), + canvas = document.body.appendChild(document.createElement('div')), + paper = raphael(canvas) + +paper.circle(50, 50, 40) diff --git a/homework7/project_express/node_modules/require/example/server.js b/homework7/project_express/node_modules/require/example/server.js new file mode 100644 index 0000000..0b8adbf --- /dev/null +++ b/homework7/project_express/node_modules/require/example/server.js @@ -0,0 +1,20 @@ +var http = require('http'), + fs = require('fs'), + dependency = require('./shared/dependency'), + requireServer = require('../server') // this would be require('require/server') in most applications + +var base = __dirname + '/', + root = 'require' +var server = http.createServer(function(req, res) { + if (requireServer.isRequireRequest(req)) { return } + fs.readFile(base + (req.url.substr(1) || 'index.html'), function(err, content) { + if (err) { return res.end(err.stack) } + res.end(content) + }) +}) + +requireServer.mount(server, __dirname) + +server.listen(8080) + +console.log('shared dependency:', dependency) diff --git a/homework7/project_express/node_modules/require/example/shared/dependency.js b/homework7/project_express/node_modules/require/example/shared/dependency.js new file mode 100644 index 0000000..8cdb2ae --- /dev/null +++ b/homework7/project_express/node_modules/require/example/shared/dependency.js @@ -0,0 +1,4 @@ +module.exports = { + foo: 'bar', + cat: 'qwe' +} diff --git a/homework7/project_express/node_modules/require/lib/getCode.js b/homework7/project_express/node_modules/require/lib/getCode.js new file mode 100644 index 0000000..5febcea --- /dev/null +++ b/homework7/project_express/node_modules/require/lib/getCode.js @@ -0,0 +1,6 @@ +var fs = require('fs') + +module.exports = function readCode(filePath) { + if (!filePath.match(/\.js$/)) { filePath += '.js' } + return fs.readFileSync(filePath).toString() +} \ No newline at end of file diff --git a/homework7/project_express/node_modules/require/lib/getDependencyLevels.js b/homework7/project_express/node_modules/require/lib/getDependencyLevels.js new file mode 100644 index 0000000..af92e43 --- /dev/null +++ b/homework7/project_express/node_modules/require/lib/getDependencyLevels.js @@ -0,0 +1,59 @@ +var each = require('std/each') +var getCode = require('./getCode') +var getRequireStatements = require('./getRequireStatements') +var resolve = require('./resolve') + +module.exports = getDependencyLevels + +function getDependencyLevels(mainModulePath) { + var leaves = [] + var root = [] + root.isRoot = true + root.path = mainModulePath + _buildDependencyTreeOf(root) + + var levels = [] + var seenPaths = {} + _buildLevel(leaves) + + return levels + + // builds full dependency tree, noting every dependency of every node + function _buildDependencyTreeOf(node) { + var requireStatements = getRequireStatements(getCode(node.path)) + if (requireStatements.length == 0) { + return leaves.push(node) + } + each(requireStatements, function(requireStatement) { + var childNode = [] + childNode.path = resolve.requireStatement(requireStatement, node.path) + childNode.parent = node + node.push(childNode) + _buildDependencyTreeOf(childNode) + }) + node.waitingForNumChildren = node.length + } + + // builds a list of dependency levels, where nodes in each level is dependent only on nodes in levels below it + // the dependency levels allow for parallel loading of every file in any given level + function _buildLevel(nodes) { + var level = [] + levels.push(level) + var parents = [] + each(nodes, function(node) { + if (!seenPaths[node.path]) { + seenPaths[node.path] = true + level.push(node.path) + } + if (node.isRoot) { return } + + node.parent.waitingForNumChildren -= 1 + + if (node.parent.waitingForNumChildren == 0) { + parents.push(node.parent) + } + }) + if (!parents.length) { return } + _buildLevel(parents) + } +} diff --git a/homework7/project_express/node_modules/require/lib/getRequireStatements.js b/homework7/project_express/node_modules/require/lib/getRequireStatements.js new file mode 100644 index 0000000..ecc9470 --- /dev/null +++ b/homework7/project_express/node_modules/require/lib/getRequireStatements.js @@ -0,0 +1,6 @@ +module.exports = getRequireStatements + +var _globalRequireRegex = /require\s*\(['"][\w\/\.-]*['"]\)/g +function getRequireStatements(code) { + return code.match(_globalRequireRegex) || [] +} diff --git a/homework7/project_express/node_modules/require/lib/resolve.js b/homework7/project_express/node_modules/require/lib/resolve.js new file mode 100644 index 0000000..bbeaafc --- /dev/null +++ b/homework7/project_express/node_modules/require/lib/resolve.js @@ -0,0 +1,72 @@ +var path = require('path') +var fs = require('fs') +var existsSync = fs.existsSync || path.existsSync + +var _nodePaths = (process.env.NODE_PATH ? process.env.NODE_PATH.split(':') : []) +_nodePaths.push(process.cwd()) + +module.exports = { + path: resolvePath, + _nodePaths:_nodePaths, + requireStatement: resolveRequireStatement +} + +function resolvePath(searchPath, pathBase) { + if (searchPath[0] == '.') { + // relative path, e.g. require("./foo") + return _findModuleMain(path.resolve(pathBase, searchPath)) + } + + var searchParts = searchPath.split('/') + var componentName = searchParts[searchParts.length - 1] + var name = searchParts.shift() + var rest = searchParts.join('/') + + // npm-style path, e.g. require("npm"). + // Climb parent directories in search for "node_modules" + var modulePath = _findModuleMain(path.resolve(pathBase, 'node_modules', searchPath)) + if (modulePath) { return modulePath } + + if (pathBase != '/') { + // not yet at the root - keep climbing! + return resolvePath(searchPath, path.resolve(pathBase, '..')) + } + + return '' +} + +var _pathnameGroupingRegex = /require\s*\(['"]([\w\/\.-]*)['"]\)/ +function resolveRequireStatement(requireStmnt, currentPath) { + var rawPath = requireStmnt.match(_pathnameGroupingRegex)[1] + var resolvedPath = resolvePath(rawPath, path.dirname(currentPath)) + + if (!resolvedPath && rawPath[0] != '.' && rawPath[0] != '/') { + for (var i=0; i<_nodePaths.length; i++) { + resolvedPath = _findModuleMain(path.resolve(_nodePaths[i], rawPath)) + if (resolvedPath) { break } + } + } + + if (!resolvedPath) { throw 'Could not resolve "'+rawPath+'" in "'+currentPath+'"' } + return resolvedPath +} + +function _findModuleMain(absModulePath, tryFileName) { + var foundPath = '' + function attempt(aPath) { + if (foundPath) { return } + if (existsSync(aPath)) { foundPath = aPath } + } + attempt(absModulePath + '.js') + try { + var package = JSON.parse(fs.readFileSync(absModulePath + '/package.json').toString()) + attempt(path.resolve(absModulePath, package.main+'.js')) + attempt(path.resolve(absModulePath, package.main)) + } catch(e) {} + attempt(absModulePath + '/index.js') + + if (tryFileName) { attempt(absModulePath + '/' + tryFileName + '.js') } + return foundPath +} + + diff --git a/homework7/project_express/node_modules/require/package.json b/homework7/project_express/node_modules/require/package.json new file mode 100644 index 0000000..52b8dfb --- /dev/null +++ b/homework7/project_express/node_modules/require/package.json @@ -0,0 +1,23 @@ +{ + "name": "require", + "description": "javascript module management! brings node's require statement to the browser", + "version": "2.4.20", + "homepage": "https://github.com/marcuswestin/require", + "main": "./require", + "bin": "./bin/require-command.js", + "engines": { + "node": "*", + "browsers": "*" + }, + "repository": { + "type": "git", + "url": "git://github.com/marcuswestin/require.git" + }, + "author": "Marcus Westin (http://marcuswest.in)", + "dependencies": { + "uglify-js": "2.3.0", + "std": "0.1.40" + }, + "devDependencies": {}, + "directories": {} +} diff --git a/homework7/project_express/node_modules/require/server.js b/homework7/project_express/node_modules/require/server.js new file mode 100644 index 0000000..9f34d1c --- /dev/null +++ b/homework7/project_express/node_modules/require/server.js @@ -0,0 +1,185 @@ +var http = require('http') +var fs = require('fs') +var path = require('path') +var extend = require('std/extend') +var isObject = require('std/isObject') +var map = require('std/map') +var each = require('std/each') +var getDependencyLevels = require('./lib/getDependencyLevels') +var getRequireStatements = require('./lib/getRequireStatements') +var getCode = require('./lib/getCode') +var resolve = require('./lib/resolve') + +module.exports = { + listen: listen, + mount: mount, + connect: connect, + isRequireRequest: isRequireRequest, + handleRequest: handleRequest +} + +function listen(portOrOpts) { + var _opts = (isObject(portOrOpts) ? portOrOpts : { port:portOrOpts || 1234 }) + opts.handleAllRequests = true + mount(http.createServer(), _opts).listen(opts.port, opts.host) +} + +function mount(server, _opts) { + setOpts(_opts) + return server.on('request', _checkRequest) +} + +function connect(opts) { + setOpts(opts) + return _checkRequest +} + +function _checkRequest(req, res, next) { + if (isRequireRequest(req) || opts.handleAllRequests) { + handleRequest(req, res) + } else { + next && next() + } +} + +function isRequireRequest(req) { + return req.url.substr(1, opts.root.length) == opts.root +} + +/* options + *********/ +var opts = { + path: process.cwd(), + root: 'require', + port: null, + host: null +} +function setOpts(_opts) { + opts = extend(_opts, opts) + if (opts.path) { + resolve._nodePaths.push(opts.path) + } +} +function getUrlBase() { + var basePort = (!opts.usePagePort && opts.port) + if (opts.host && basePort) { + return '//' + opts.host + ':' + basePort + '/' + opts.root + '/' + } else { + return '/' + opts.root + '/' + } +} + +/* request handlers + ******************/ +function handleRequest(req, res) { + var reqPath = _normalizeURL(req.url).substr(opts.root.length + 2) + if (reqPath.match(/\.js$/)) { + _handleModuleRequest(reqPath, res) + } else { + _handleMainModuleRequest(reqPath, req, res) + } + + function _normalizeURL(url) { + return url.replace(/\?.*/g, '').replace(/\/js$/, '.js') + } +} + +function _handleMainModuleRequest(reqPath, req, res) { + var mainModulePath = resolve.path('./' + reqPath, opts.path) + if (!mainModulePath) { return _sendError(res, 'Could not find module "'+reqPath+'" from "'+opts.path+'"') } + + try { var dependencyTree = getDependencyLevels(mainModulePath) } + catch(err) { return _sendError(res, 'in getDependencyLevels: ' + (err.message || err)) } + + var userAgent = req.headers['user-agent'] + var isMobile = userAgent.match('iPad') || userAgent.match('iPod') || userAgent.match('iPhone') || userAgent.match('Android') + + var response = isMobile ? _getMobilePayload() : _getNormalPayload() + + res.writeHead(200, { 'Cache-Control':'no-cache', 'Expires':'Fri, 31 Dec 1998 12:00:00 GMT', 'Content-Length':response.length, 'Content-Type':'text/javascript' }) + res.end(response) + + function _getMobilePayload() { + var result = ['__require__={loadNextModule:function(){},onModuleLoaded:function(){}}'] + each(dependencyTree, function(level) { + each(level, function(dependency) { + result.push(';(function(){ '+_getModuleCode(res, dependency)+' }());') + }) + }) + return new Buffer(result.join('\n')) + } + + function _getNormalPayload() { + var paramsString = map([getUrlBase(), dependencyTree], JSON.stringify).join(',\n\t\t') + return new Buffer('\t('+clientBootstrapFn.toString()+')(\n\t\t'+paramsString+'\n\t)') + + function clientBootstrapFn(urlBase, levels) { + // This function gets sent to the client as toString + __require__ = { + loadNextLevel: loadNextLevel, + onModuleLoaded: onModuleLoaded + } + + var currentLevel = null + loadNextLevel() + + function loadNextLevel() { + if (!levels.length) { return } // all done! + currentLevel = levels.shift() + var head = document.getElementsByTagName('head')[0] + for (var i=0; i + +* `array` {Array} + +Allocates a new `Buffer` using an `array` of octets. + +```js +const buf = Buffer.from([0x62,0x75,0x66,0x66,0x65,0x72]); + // creates a new Buffer containing ASCII bytes + // ['b','u','f','f','e','r'] +``` + +A `TypeError` will be thrown if `array` is not an `Array`. + +### Class Method: Buffer.from(arrayBuffer[, byteOffset[, length]]) + + +* `arrayBuffer` {ArrayBuffer} The `.buffer` property of a `TypedArray` or + a `new ArrayBuffer()` +* `byteOffset` {Number} Default: `0` +* `length` {Number} Default: `arrayBuffer.length - byteOffset` + +When passed a reference to the `.buffer` property of a `TypedArray` instance, +the newly created `Buffer` will share the same allocated memory as the +TypedArray. + +```js +const arr = new Uint16Array(2); +arr[0] = 5000; +arr[1] = 4000; + +const buf = Buffer.from(arr.buffer); // shares the memory with arr; + +console.log(buf); + // Prints: + +// changing the TypedArray changes the Buffer also +arr[1] = 6000; + +console.log(buf); + // Prints: +``` + +The optional `byteOffset` and `length` arguments specify a memory range within +the `arrayBuffer` that will be shared by the `Buffer`. + +```js +const ab = new ArrayBuffer(10); +const buf = Buffer.from(ab, 0, 2); +console.log(buf.length); + // Prints: 2 +``` + +A `TypeError` will be thrown if `arrayBuffer` is not an `ArrayBuffer`. + +### Class Method: Buffer.from(buffer) + + +* `buffer` {Buffer} + +Copies the passed `buffer` data onto a new `Buffer` instance. + +```js +const buf1 = Buffer.from('buffer'); +const buf2 = Buffer.from(buf1); + +buf1[0] = 0x61; +console.log(buf1.toString()); + // 'auffer' +console.log(buf2.toString()); + // 'buffer' (copy is not changed) +``` + +A `TypeError` will be thrown if `buffer` is not a `Buffer`. + +### Class Method: Buffer.from(str[, encoding]) + + +* `str` {String} String to encode. +* `encoding` {String} Encoding to use, Default: `'utf8'` + +Creates a new `Buffer` containing the given JavaScript string `str`. If +provided, the `encoding` parameter identifies the character encoding. +If not provided, `encoding` defaults to `'utf8'`. + +```js +const buf1 = Buffer.from('this is a tést'); +console.log(buf1.toString()); + // prints: this is a tést +console.log(buf1.toString('ascii')); + // prints: this is a tC)st + +const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex'); +console.log(buf2.toString()); + // prints: this is a tést +``` + +A `TypeError` will be thrown if `str` is not a string. + +### Class Method: Buffer.alloc(size[, fill[, encoding]]) + + +* `size` {Number} +* `fill` {Value} Default: `undefined` +* `encoding` {String} Default: `utf8` + +Allocates a new `Buffer` of `size` bytes. If `fill` is `undefined`, the +`Buffer` will be *zero-filled*. + +```js +const buf = Buffer.alloc(5); +console.log(buf); + // +``` + +The `size` must be less than or equal to the value of +`require('buffer').kMaxLength` (on 64-bit architectures, `kMaxLength` is +`(2^31)-1`). Otherwise, a [`RangeError`][] is thrown. A zero-length Buffer will +be created if a `size` less than or equal to 0 is specified. + +If `fill` is specified, the allocated `Buffer` will be initialized by calling +`buf.fill(fill)`. See [`buf.fill()`][] for more information. + +```js +const buf = Buffer.alloc(5, 'a'); +console.log(buf); + // +``` + +If both `fill` and `encoding` are specified, the allocated `Buffer` will be +initialized by calling `buf.fill(fill, encoding)`. For example: + +```js +const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64'); +console.log(buf); + // +``` + +Calling `Buffer.alloc(size)` can be significantly slower than the alternative +`Buffer.allocUnsafe(size)` but ensures that the newly created `Buffer` instance +contents will *never contain sensitive data*. + +A `TypeError` will be thrown if `size` is not a number. + +### Class Method: Buffer.allocUnsafe(size) + + +* `size` {Number} + +Allocates a new *non-zero-filled* `Buffer` of `size` bytes. The `size` must +be less than or equal to the value of `require('buffer').kMaxLength` (on 64-bit +architectures, `kMaxLength` is `(2^31)-1`). Otherwise, a [`RangeError`][] is +thrown. A zero-length Buffer will be created if a `size` less than or equal to +0 is specified. + +The underlying memory for `Buffer` instances created in this way is *not +initialized*. The contents of the newly created `Buffer` are unknown and +*may contain sensitive data*. Use [`buf.fill(0)`][] to initialize such +`Buffer` instances to zeroes. + +```js +const buf = Buffer.allocUnsafe(5); +console.log(buf); + // + // (octets will be different, every time) +buf.fill(0); +console.log(buf); + // +``` + +A `TypeError` will be thrown if `size` is not a number. + +Note that the `Buffer` module pre-allocates an internal `Buffer` instance of +size `Buffer.poolSize` that is used as a pool for the fast allocation of new +`Buffer` instances created using `Buffer.allocUnsafe(size)` (and the deprecated +`new Buffer(size)` constructor) only when `size` is less than or equal to +`Buffer.poolSize >> 1` (floor of `Buffer.poolSize` divided by two). The default +value of `Buffer.poolSize` is `8192` but can be modified. + +Use of this pre-allocated internal memory pool is a key difference between +calling `Buffer.alloc(size, fill)` vs. `Buffer.allocUnsafe(size).fill(fill)`. +Specifically, `Buffer.alloc(size, fill)` will *never* use the internal Buffer +pool, while `Buffer.allocUnsafe(size).fill(fill)` *will* use the internal +Buffer pool if `size` is less than or equal to half `Buffer.poolSize`. The +difference is subtle but can be important when an application requires the +additional performance that `Buffer.allocUnsafe(size)` provides. + +### Class Method: Buffer.allocUnsafeSlow(size) + + +* `size` {Number} + +Allocates a new *non-zero-filled* and non-pooled `Buffer` of `size` bytes. The +`size` must be less than or equal to the value of +`require('buffer').kMaxLength` (on 64-bit architectures, `kMaxLength` is +`(2^31)-1`). Otherwise, a [`RangeError`][] is thrown. A zero-length Buffer will +be created if a `size` less than or equal to 0 is specified. + +The underlying memory for `Buffer` instances created in this way is *not +initialized*. The contents of the newly created `Buffer` are unknown and +*may contain sensitive data*. Use [`buf.fill(0)`][] to initialize such +`Buffer` instances to zeroes. + +When using `Buffer.allocUnsafe()` to allocate new `Buffer` instances, +allocations under 4KB are, by default, sliced from a single pre-allocated +`Buffer`. This allows applications to avoid the garbage collection overhead of +creating many individually allocated Buffers. This approach improves both +performance and memory usage by eliminating the need to track and cleanup as +many `Persistent` objects. + +However, in the case where a developer may need to retain a small chunk of +memory from a pool for an indeterminate amount of time, it may be appropriate +to create an un-pooled Buffer instance using `Buffer.allocUnsafeSlow()` then +copy out the relevant bits. + +```js +// need to keep around a few small chunks of memory +const store = []; + +socket.on('readable', () => { + const data = socket.read(); + // allocate for retained data + const sb = Buffer.allocUnsafeSlow(10); + // copy the data into the new allocation + data.copy(sb, 0, 0, 10); + store.push(sb); +}); +``` + +Use of `Buffer.allocUnsafeSlow()` should be used only as a last resort *after* +a developer has observed undue memory retention in their applications. + +A `TypeError` will be thrown if `size` is not a number. + +### All the Rest + +The rest of the `Buffer` API is exactly the same as in node.js. +[See the docs](https://nodejs.org/api/buffer.html). + + +## Related links + +- [Node.js issue: Buffer(number) is unsafe](https://github.com/nodejs/node/issues/4660) +- [Node.js Enhancement Proposal: Buffer.from/Buffer.alloc/Buffer.zalloc/Buffer() soft-deprecate](https://github.com/nodejs/node-eps/pull/4) + +## Why is `Buffer` unsafe? + +Today, the node.js `Buffer` constructor is overloaded to handle many different argument +types like `String`, `Array`, `Object`, `TypedArrayView` (`Uint8Array`, etc.), +`ArrayBuffer`, and also `Number`. + +The API is optimized for convenience: you can throw any type at it, and it will try to do +what you want. + +Because the Buffer constructor is so powerful, you often see code like this: + +```js +// Convert UTF-8 strings to hex +function toHex (str) { + return new Buffer(str).toString('hex') +} +``` + +***But what happens if `toHex` is called with a `Number` argument?*** + +### Remote Memory Disclosure + +If an attacker can make your program call the `Buffer` constructor with a `Number` +argument, then they can make it allocate uninitialized memory from the node.js process. +This could potentially disclose TLS private keys, user data, or database passwords. + +When the `Buffer` constructor is passed a `Number` argument, it returns an +**UNINITIALIZED** block of memory of the specified `size`. When you create a `Buffer` like +this, you **MUST** overwrite the contents before returning it to the user. + +From the [node.js docs](https://nodejs.org/api/buffer.html#buffer_new_buffer_size): + +> `new Buffer(size)` +> +> - `size` Number +> +> The underlying memory for `Buffer` instances created in this way is not initialized. +> **The contents of a newly created `Buffer` are unknown and could contain sensitive +> data.** Use `buf.fill(0)` to initialize a Buffer to zeroes. + +(Emphasis our own.) + +Whenever the programmer intended to create an uninitialized `Buffer` you often see code +like this: + +```js +var buf = new Buffer(16) + +// Immediately overwrite the uninitialized buffer with data from another buffer +for (var i = 0; i < buf.length; i++) { + buf[i] = otherBuf[i] +} +``` + + +### Would this ever be a problem in real code? + +Yes. It's surprisingly common to forget to check the type of your variables in a +dynamically-typed language like JavaScript. + +Usually the consequences of assuming the wrong type is that your program crashes with an +uncaught exception. But the failure mode for forgetting to check the type of arguments to +the `Buffer` constructor is more catastrophic. + +Here's an example of a vulnerable service that takes a JSON payload and converts it to +hex: + +```js +// Take a JSON payload {str: "some string"} and convert it to hex +var server = http.createServer(function (req, res) { + var data = '' + req.setEncoding('utf8') + req.on('data', function (chunk) { + data += chunk + }) + req.on('end', function () { + var body = JSON.parse(data) + res.end(new Buffer(body.str).toString('hex')) + }) +}) + +server.listen(8080) +``` + +In this example, an http client just has to send: + +```json +{ + "str": 1000 +} +``` + +and it will get back 1,000 bytes of uninitialized memory from the server. + +This is a very serious bug. It's similar in severity to the +[the Heartbleed bug](http://heartbleed.com/) that allowed disclosure of OpenSSL process +memory by remote attackers. + + +### Which real-world packages were vulnerable? + +#### [`bittorrent-dht`](https://www.npmjs.com/package/bittorrent-dht) + +[Mathias Buus](https://github.com/mafintosh) and I +([Feross Aboukhadijeh](http://feross.org/)) found this issue in one of our own packages, +[`bittorrent-dht`](https://www.npmjs.com/package/bittorrent-dht). The bug would allow +anyone on the internet to send a series of messages to a user of `bittorrent-dht` and get +them to reveal 20 bytes at a time of uninitialized memory from the node.js process. + +Here's +[the commit](https://github.com/feross/bittorrent-dht/commit/6c7da04025d5633699800a99ec3fbadf70ad35b8) +that fixed it. We released a new fixed version, created a +[Node Security Project disclosure](https://nodesecurity.io/advisories/68), and deprecated all +vulnerable versions on npm so users will get a warning to upgrade to a newer version. + +#### [`ws`](https://www.npmjs.com/package/ws) + +That got us wondering if there were other vulnerable packages. Sure enough, within a short +period of time, we found the same issue in [`ws`](https://www.npmjs.com/package/ws), the +most popular WebSocket implementation in node.js. + +If certain APIs were called with `Number` parameters instead of `String` or `Buffer` as +expected, then uninitialized server memory would be disclosed to the remote peer. + +These were the vulnerable methods: + +```js +socket.send(number) +socket.ping(number) +socket.pong(number) +``` + +Here's a vulnerable socket server with some echo functionality: + +```js +server.on('connection', function (socket) { + socket.on('message', function (message) { + message = JSON.parse(message) + if (message.type === 'echo') { + socket.send(message.data) // send back the user's message + } + }) +}) +``` + +`socket.send(number)` called on the server, will disclose server memory. + +Here's [the release](https://github.com/websockets/ws/releases/tag/1.0.1) where the issue +was fixed, with a more detailed explanation. Props to +[Arnout Kazemier](https://github.com/3rd-Eden) for the quick fix. Here's the +[Node Security Project disclosure](https://nodesecurity.io/advisories/67). + + +### What's the solution? + +It's important that node.js offers a fast way to get memory otherwise performance-critical +applications would needlessly get a lot slower. + +But we need a better way to *signal our intent* as programmers. **When we want +uninitialized memory, we should request it explicitly.** + +Sensitive functionality should not be packed into a developer-friendly API that loosely +accepts many different types. This type of API encourages the lazy practice of passing +variables in without checking the type very carefully. + +#### A new API: `Buffer.allocUnsafe(number)` + +The functionality of creating buffers with uninitialized memory should be part of another +API. We propose `Buffer.allocUnsafe(number)`. This way, it's not part of an API that +frequently gets user input of all sorts of different types passed into it. + +```js +var buf = Buffer.allocUnsafe(16) // careful, uninitialized memory! + +// Immediately overwrite the uninitialized buffer with data from another buffer +for (var i = 0; i < buf.length; i++) { + buf[i] = otherBuf[i] +} +``` + + +### How do we fix node.js core? + +We sent [a PR to node.js core](https://github.com/nodejs/node/pull/4514) (merged as +`semver-major`) which defends against one case: + +```js +var str = 16 +new Buffer(str, 'utf8') +``` + +In this situation, it's implied that the programmer intended the first argument to be a +string, since they passed an encoding as a second argument. Today, node.js will allocate +uninitialized memory in the case of `new Buffer(number, encoding)`, which is probably not +what the programmer intended. + +But this is only a partial solution, since if the programmer does `new Buffer(variable)` +(without an `encoding` parameter) there's no way to know what they intended. If `variable` +is sometimes a number, then uninitialized memory will sometimes be returned. + +### What's the real long-term fix? + +We could deprecate and remove `new Buffer(number)` and use `Buffer.allocUnsafe(number)` when +we need uninitialized memory. But that would break 1000s of packages. + +~~We believe the best solution is to:~~ + +~~1. Change `new Buffer(number)` to return safe, zeroed-out memory~~ + +~~2. Create a new API for creating uninitialized Buffers. We propose: `Buffer.allocUnsafe(number)`~~ + +#### Update + +We now support adding three new APIs: + +- `Buffer.from(value)` - convert from any type to a buffer +- `Buffer.alloc(size)` - create a zero-filled buffer +- `Buffer.allocUnsafe(size)` - create an uninitialized buffer with given size + +This solves the core problem that affected `ws` and `bittorrent-dht` which is +`Buffer(variable)` getting tricked into taking a number argument. + +This way, existing code continues working and the impact on the npm ecosystem will be +minimal. Over time, npm maintainers can migrate performance-critical code to use +`Buffer.allocUnsafe(number)` instead of `new Buffer(number)`. + + +### Conclusion + +We think there's a serious design issue with the `Buffer` API as it exists today. It +promotes insecure software by putting high-risk functionality into a convenient API +with friendly "developer ergonomics". + +This wasn't merely a theoretical exercise because we found the issue in some of the +most popular npm packages. + +Fortunately, there's an easy fix that can be applied today. Use `safe-buffer` in place of +`buffer`. + +```js +var Buffer = require('safe-buffer').Buffer +``` + +Eventually, we hope that node.js core can switch to this new, safer behavior. We believe +the impact on the ecosystem would be minimal since it's not a breaking change. +Well-maintained, popular packages would be updated to use `Buffer.alloc` quickly, while +older, insecure packages would magically become safe from this attack vector. + + +## links + +- [Node.js PR: buffer: throw if both length and enc are passed](https://github.com/nodejs/node/pull/4514) +- [Node Security Project disclosure for `ws`](https://nodesecurity.io/advisories/67) +- [Node Security Project disclosure for`bittorrent-dht`](https://nodesecurity.io/advisories/68) + + +## credit + +The original issues in `bittorrent-dht` +([disclosure](https://nodesecurity.io/advisories/68)) and +`ws` ([disclosure](https://nodesecurity.io/advisories/67)) were discovered by +[Mathias Buus](https://github.com/mafintosh) and +[Feross Aboukhadijeh](http://feross.org/). + +Thanks to [Adam Baldwin](https://github.com/evilpacket) for helping disclose these issues +and for his work running the [Node Security Project](https://nodesecurity.io/). + +Thanks to [John Hiesey](https://github.com/jhiesey) for proofreading this README and +auditing the code. + + +## license + +MIT. Copyright (C) [Feross Aboukhadijeh](http://feross.org) diff --git a/homework7/project_express/node_modules/safe-buffer/index.d.ts b/homework7/project_express/node_modules/safe-buffer/index.d.ts new file mode 100644 index 0000000..e9fed80 --- /dev/null +++ b/homework7/project_express/node_modules/safe-buffer/index.d.ts @@ -0,0 +1,187 @@ +declare module "safe-buffer" { + export class Buffer { + length: number + write(string: string, offset?: number, length?: number, encoding?: string): number; + toString(encoding?: string, start?: number, end?: number): string; + toJSON(): { type: 'Buffer', data: any[] }; + equals(otherBuffer: Buffer): boolean; + compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number; + copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number; + slice(start?: number, end?: number): Buffer; + writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number; + readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number; + readIntLE(offset: number, byteLength: number, noAssert?: boolean): number; + readIntBE(offset: number, byteLength: number, noAssert?: boolean): number; + readUInt8(offset: number, noAssert?: boolean): number; + readUInt16LE(offset: number, noAssert?: boolean): number; + readUInt16BE(offset: number, noAssert?: boolean): number; + readUInt32LE(offset: number, noAssert?: boolean): number; + readUInt32BE(offset: number, noAssert?: boolean): number; + readInt8(offset: number, noAssert?: boolean): number; + readInt16LE(offset: number, noAssert?: boolean): number; + readInt16BE(offset: number, noAssert?: boolean): number; + readInt32LE(offset: number, noAssert?: boolean): number; + readInt32BE(offset: number, noAssert?: boolean): number; + readFloatLE(offset: number, noAssert?: boolean): number; + readFloatBE(offset: number, noAssert?: boolean): number; + readDoubleLE(offset: number, noAssert?: boolean): number; + readDoubleBE(offset: number, noAssert?: boolean): number; + swap16(): Buffer; + swap32(): Buffer; + swap64(): Buffer; + writeUInt8(value: number, offset: number, noAssert?: boolean): number; + writeUInt16LE(value: number, offset: number, noAssert?: boolean): number; + writeUInt16BE(value: number, offset: number, noAssert?: boolean): number; + writeUInt32LE(value: number, offset: number, noAssert?: boolean): number; + writeUInt32BE(value: number, offset: number, noAssert?: boolean): number; + writeInt8(value: number, offset: number, noAssert?: boolean): number; + writeInt16LE(value: number, offset: number, noAssert?: boolean): number; + writeInt16BE(value: number, offset: number, noAssert?: boolean): number; + writeInt32LE(value: number, offset: number, noAssert?: boolean): number; + writeInt32BE(value: number, offset: number, noAssert?: boolean): number; + writeFloatLE(value: number, offset: number, noAssert?: boolean): number; + writeFloatBE(value: number, offset: number, noAssert?: boolean): number; + writeDoubleLE(value: number, offset: number, noAssert?: boolean): number; + writeDoubleBE(value: number, offset: number, noAssert?: boolean): number; + fill(value: any, offset?: number, end?: number): this; + indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number; + lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number; + includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean; + + /** + * Allocates a new buffer containing the given {str}. + * + * @param str String to store in buffer. + * @param encoding encoding to use, optional. Default is 'utf8' + */ + constructor (str: string, encoding?: string); + /** + * Allocates a new buffer of {size} octets. + * + * @param size count of octets to allocate. + */ + constructor (size: number); + /** + * Allocates a new buffer containing the given {array} of octets. + * + * @param array The octets to store. + */ + constructor (array: Uint8Array); + /** + * Produces a Buffer backed by the same allocated memory as + * the given {ArrayBuffer}. + * + * + * @param arrayBuffer The ArrayBuffer with which to share memory. + */ + constructor (arrayBuffer: ArrayBuffer); + /** + * Allocates a new buffer containing the given {array} of octets. + * + * @param array The octets to store. + */ + constructor (array: any[]); + /** + * Copies the passed {buffer} data onto a new {Buffer} instance. + * + * @param buffer The buffer to copy. + */ + constructor (buffer: Buffer); + prototype: Buffer; + /** + * Allocates a new Buffer using an {array} of octets. + * + * @param array + */ + static from(array: any[]): Buffer; + /** + * When passed a reference to the .buffer property of a TypedArray instance, + * the newly created Buffer will share the same allocated memory as the TypedArray. + * The optional {byteOffset} and {length} arguments specify a memory range + * within the {arrayBuffer} that will be shared by the Buffer. + * + * @param arrayBuffer The .buffer property of a TypedArray or a new ArrayBuffer() + * @param byteOffset + * @param length + */ + static from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer; + /** + * Copies the passed {buffer} data onto a new Buffer instance. + * + * @param buffer + */ + static from(buffer: Buffer): Buffer; + /** + * Creates a new Buffer containing the given JavaScript string {str}. + * If provided, the {encoding} parameter identifies the character encoding. + * If not provided, {encoding} defaults to 'utf8'. + * + * @param str + */ + static from(str: string, encoding?: string): Buffer; + /** + * Returns true if {obj} is a Buffer + * + * @param obj object to test. + */ + static isBuffer(obj: any): obj is Buffer; + /** + * Returns true if {encoding} is a valid encoding argument. + * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex' + * + * @param encoding string to test. + */ + static isEncoding(encoding: string): boolean; + /** + * Gives the actual byte length of a string. encoding defaults to 'utf8'. + * This is not the same as String.prototype.length since that returns the number of characters in a string. + * + * @param string string to test. + * @param encoding encoding used to evaluate (defaults to 'utf8') + */ + static byteLength(string: string, encoding?: string): number; + /** + * Returns a buffer which is the result of concatenating all the buffers in the list together. + * + * If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer. + * If the list has exactly one item, then the first item of the list is returned. + * If the list has more than one item, then a new Buffer is created. + * + * @param list An array of Buffer objects to concatenate + * @param totalLength Total length of the buffers when concatenated. + * If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly. + */ + static concat(list: Buffer[], totalLength?: number): Buffer; + /** + * The same as buf1.compare(buf2). + */ + static compare(buf1: Buffer, buf2: Buffer): number; + /** + * Allocates a new buffer of {size} octets. + * + * @param size count of octets to allocate. + * @param fill if specified, buffer will be initialized by calling buf.fill(fill). + * If parameter is omitted, buffer will be filled with zeros. + * @param encoding encoding used for call to buf.fill while initalizing + */ + static alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer; + /** + * Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents + * of the newly created Buffer are unknown and may contain sensitive data. + * + * @param size count of octets to allocate + */ + static allocUnsafe(size: number): Buffer; + /** + * Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents + * of the newly created Buffer are unknown and may contain sensitive data. + * + * @param size count of octets to allocate + */ + static allocUnsafeSlow(size: number): Buffer; + } +} \ No newline at end of file diff --git a/homework7/project_express/node_modules/safe-buffer/index.js b/homework7/project_express/node_modules/safe-buffer/index.js new file mode 100644 index 0000000..22438da --- /dev/null +++ b/homework7/project_express/node_modules/safe-buffer/index.js @@ -0,0 +1,62 @@ +/* eslint-disable node/no-deprecated-api */ +var buffer = require('buffer') +var Buffer = buffer.Buffer + +// alternative to using Object.keys for old browsers +function copyProps (src, dst) { + for (var key in src) { + dst[key] = src[key] + } +} +if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { + module.exports = buffer +} else { + // Copy properties from require('buffer') + copyProps(buffer, exports) + exports.Buffer = SafeBuffer +} + +function SafeBuffer (arg, encodingOrOffset, length) { + return Buffer(arg, encodingOrOffset, length) +} + +// Copy static methods from Buffer +copyProps(Buffer, SafeBuffer) + +SafeBuffer.from = function (arg, encodingOrOffset, length) { + if (typeof arg === 'number') { + throw new TypeError('Argument must not be a number') + } + return Buffer(arg, encodingOrOffset, length) +} + +SafeBuffer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + var buf = Buffer(size) + if (fill !== undefined) { + if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + } else { + buf.fill(0) + } + return buf +} + +SafeBuffer.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return Buffer(size) +} + +SafeBuffer.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return buffer.SlowBuffer(size) +} diff --git a/homework7/project_express/node_modules/safe-buffer/package.json b/homework7/project_express/node_modules/safe-buffer/package.json new file mode 100644 index 0000000..eb76d92 --- /dev/null +++ b/homework7/project_express/node_modules/safe-buffer/package.json @@ -0,0 +1,63 @@ +{ + "_from": "safe-buffer@5.1.2", + "_id": "safe-buffer@5.1.2", + "_inBundle": false, + "_integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "_location": "/safe-buffer", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "safe-buffer@5.1.2", + "name": "safe-buffer", + "escapedName": "safe-buffer", + "rawSpec": "5.1.2", + "saveSpec": null, + "fetchSpec": "5.1.2" + }, + "_requiredBy": [ + "/content-disposition", + "/express" + ], + "_resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "_shasum": "991ec69d296e0313747d59bdfd2b745c35f8828d", + "_spec": "safe-buffer@5.1.2", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\express", + "author": { + "name": "Feross Aboukhadijeh", + "email": "feross@feross.org", + "url": "http://feross.org" + }, + "bugs": { + "url": "https://github.com/feross/safe-buffer/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Safer Node.js Buffer API", + "devDependencies": { + "standard": "*", + "tape": "^4.0.0" + }, + "homepage": "https://github.com/feross/safe-buffer", + "keywords": [ + "buffer", + "buffer allocate", + "node security", + "safe", + "safe-buffer", + "security", + "uninitialized" + ], + "license": "MIT", + "main": "index.js", + "name": "safe-buffer", + "repository": { + "type": "git", + "url": "git://github.com/feross/safe-buffer.git" + }, + "scripts": { + "test": "standard && tape test/*.js" + }, + "types": "index.d.ts", + "version": "5.1.2" +} diff --git a/homework7/project_express/node_modules/safer-buffer/LICENSE b/homework7/project_express/node_modules/safer-buffer/LICENSE new file mode 100644 index 0000000..4fe9e6f --- /dev/null +++ b/homework7/project_express/node_modules/safer-buffer/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Nikita Skovoroda + +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/homework7/project_express/node_modules/safer-buffer/Porting-Buffer.md b/homework7/project_express/node_modules/safer-buffer/Porting-Buffer.md new file mode 100644 index 0000000..68d86ba --- /dev/null +++ b/homework7/project_express/node_modules/safer-buffer/Porting-Buffer.md @@ -0,0 +1,268 @@ +# Porting to the Buffer.from/Buffer.alloc API + + +## Overview + +- [Variant 1: Drop support for Node.js ≤ 4.4.x and 5.0.0 — 5.9.x.](#variant-1) (*recommended*) +- [Variant 2: Use a polyfill](#variant-2) +- [Variant 3: manual detection, with safeguards](#variant-3) + +### Finding problematic bits of code using grep + +Just run `grep -nrE '[^a-zA-Z](Slow)?Buffer\s*\(' --exclude-dir node_modules`. + +It will find all the potentially unsafe places in your own code (with some considerably unlikely +exceptions). + +### Finding problematic bits of code using Node.js 8 + +If you’re using Node.js ≥ 8.0.0 (which is recommended), Node.js exposes multiple options that help with finding the relevant pieces of code: + +- `--trace-warnings` will make Node.js show a stack trace for this warning and other warnings that are printed by Node.js. +- `--trace-deprecation` does the same thing, but only for deprecation warnings. +- `--pending-deprecation` will show more types of deprecation warnings. In particular, it will show the `Buffer()` deprecation warning, even on Node.js 8. + +You can set these flags using an environment variable: + +```console +$ export NODE_OPTIONS='--trace-warnings --pending-deprecation' +$ cat example.js +'use strict'; +const foo = new Buffer('foo'); +$ node example.js +(node:7147) [DEP0005] DeprecationWarning: The Buffer() and new Buffer() constructors are not recommended for use due to security and usability concerns. Please use the new Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() construction methods instead. + at showFlaggedDeprecation (buffer.js:127:13) + at new Buffer (buffer.js:148:3) + at Object. (/path/to/example.js:2:13) + [... more stack trace lines ...] +``` + +### Finding problematic bits of code using linters + +Eslint rules [no-buffer-constructor](https://eslint.org/docs/rules/no-buffer-constructor) +or +[node/no-deprecated-api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) +also find calls to deprecated `Buffer()` API. Those rules are included in some pre-sets. + +There is a drawback, though, that it doesn't always +[work correctly](https://github.com/chalker/safer-buffer#why-not-safe-buffer) when `Buffer` is +overriden e.g. with a polyfill, so recommended is a combination of this and some other method +described above. + + +## Variant 1: Drop support for Node.js ≤ 4.4.x and 5.0.0 — 5.9.x. + +This is the recommended solution nowadays that would imply only minimal overhead. + +The Node.js 5.x release line has been unsupported since July 2016, and the Node.js 4.x release line reaches its End of Life in April 2018 (→ [Schedule](https://github.com/nodejs/Release#release-schedule)). This means that these versions of Node.js will *not* receive any updates, even in case of security issues, so using these release lines should be avoided, if at all possible. + +What you would do in this case is to convert all `new Buffer()` or `Buffer()` calls to use `Buffer.alloc()` or `Buffer.from()`, in the following way: + +- For `new Buffer(number)`, replace it with `Buffer.alloc(number)`. +- For `new Buffer(string)` (or `new Buffer(string, encoding)`), replace it with `Buffer.from(string)` (or `Buffer.from(string, encoding)`). +- For all other combinations of arguments (these are much rarer), also replace `new Buffer(...arguments)` with `Buffer.from(...arguments)`. + +Note that `Buffer.alloc()` is also _faster_ on the current Node.js versions than +`new Buffer(size).fill(0)`, which is what you would otherwise need to ensure zero-filling. + +Enabling eslint rule [no-buffer-constructor](https://eslint.org/docs/rules/no-buffer-constructor) +or +[node/no-deprecated-api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) +is recommended to avoid accidential unsafe Buffer API usage. + +There is also a [JSCodeshift codemod](https://github.com/joyeecheung/node-dep-codemod#dep005) +for automatically migrating Buffer constructors to `Buffer.alloc()` or `Buffer.from()`. +Note that it currently only works with cases where the arguments are literals or where the +constructor is invoked with two arguments. + +_If you currently support those older Node.js versions and dropping them would be a semver-major change +for you, or if you support older branches of your packages, consider using [Variant 2](#variant-2) +or [Variant 3](#variant-3) on older branches, so people using those older branches will also receive +the fix. That way, you will eradicate potential issues caused by unguarded Buffer API usage and +your users will not observe a runtime deprecation warning when running your code on Node.js 10._ + + +## Variant 2: Use a polyfill + +Utilize [safer-buffer](https://www.npmjs.com/package/safer-buffer) as a polyfill to support older +Node.js versions. + +You would take exacly the same steps as in [Variant 1](#variant-1), but with a polyfill +`const Buffer = require('safer-buffer').Buffer` in all files where you use the new `Buffer` api. + +Make sure that you do not use old `new Buffer` API — in any files where the line above is added, +using old `new Buffer()` API will _throw_. It will be easy to notice that in CI, though. + +Alternatively, you could use [buffer-from](https://www.npmjs.com/package/buffer-from) and/or +[buffer-alloc](https://www.npmjs.com/package/buffer-alloc) [ponyfills](https://ponyfill.com/) — +those are great, the only downsides being 4 deps in the tree and slightly more code changes to +migrate off them (as you would be using e.g. `Buffer.from` under a different name). If you need only +`Buffer.from` polyfilled — `buffer-from` alone which comes with no extra dependencies. + +_Alternatively, you could use [safe-buffer](https://www.npmjs.com/package/safe-buffer) — it also +provides a polyfill, but takes a different approach which has +[it's drawbacks](https://github.com/chalker/safer-buffer#why-not-safe-buffer). It will allow you +to also use the older `new Buffer()` API in your code, though — but that's arguably a benefit, as +it is problematic, can cause issues in your code, and will start emitting runtime deprecation +warnings starting with Node.js 10._ + +Note that in either case, it is important that you also remove all calls to the old Buffer +API manually — just throwing in `safe-buffer` doesn't fix the problem by itself, it just provides +a polyfill for the new API. I have seen people doing that mistake. + +Enabling eslint rule [no-buffer-constructor](https://eslint.org/docs/rules/no-buffer-constructor) +or +[node/no-deprecated-api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) +is recommended. + +_Don't forget to drop the polyfill usage once you drop support for Node.js < 4.5.0._ + + +## Variant 3 — manual detection, with safeguards + +This is useful if you create Buffer instances in only a few places (e.g. one), or you have your own +wrapper around them. + +### Buffer(0) + +This special case for creating empty buffers can be safely replaced with `Buffer.concat([])`, which +returns the same result all the way down to Node.js 0.8.x. + +### Buffer(notNumber) + +Before: + +```js +var buf = new Buffer(notNumber, encoding); +``` + +After: + +```js +var buf; +if (Buffer.from && Buffer.from !== Uint8Array.from) { + buf = Buffer.from(notNumber, encoding); +} else { + if (typeof notNumber === 'number') + throw new Error('The "size" argument must be of type number.'); + buf = new Buffer(notNumber, encoding); +} +``` + +`encoding` is optional. + +Note that the `typeof notNumber` before `new Buffer` is required (for cases when `notNumber` argument is not +hard-coded) and _is not caused by the deprecation of Buffer constructor_ — it's exactly _why_ the +Buffer constructor is deprecated. Ecosystem packages lacking this type-check caused numereous +security issues — situations when unsanitized user input could end up in the `Buffer(arg)` create +problems ranging from DoS to leaking sensitive information to the attacker from the process memory. + +When `notNumber` argument is hardcoded (e.g. literal `"abc"` or `[0,1,2]`), the `typeof` check can +be omitted. + +Also note that using TypeScript does not fix this problem for you — when libs written in +`TypeScript` are used from JS, or when user input ends up there — it behaves exactly as pure JS, as +all type checks are translation-time only and are not present in the actual JS code which TS +compiles to. + +### Buffer(number) + +For Node.js 0.10.x (and below) support: + +```js +var buf; +if (Buffer.alloc) { + buf = Buffer.alloc(number); +} else { + buf = new Buffer(number); + buf.fill(0); +} +``` + +Otherwise (Node.js ≥ 0.12.x): + +```js +const buf = Buffer.alloc ? Buffer.alloc(number) : new Buffer(number).fill(0); +``` + +## Regarding Buffer.allocUnsafe + +Be extra cautious when using `Buffer.allocUnsafe`: + * Don't use it if you don't have a good reason to + * e.g. you probably won't ever see a performance difference for small buffers, in fact, those + might be even faster with `Buffer.alloc()`, + * if your code is not in the hot code path — you also probably won't notice a difference, + * keep in mind that zero-filling minimizes the potential risks. + * If you use it, make sure that you never return the buffer in a partially-filled state, + * if you are writing to it sequentially — always truncate it to the actuall written length + +Errors in handling buffers allocated with `Buffer.allocUnsafe` could result in various issues, +ranged from undefined behaviour of your code to sensitive data (user input, passwords, certs) +leaking to the remote attacker. + +_Note that the same applies to `new Buffer` usage without zero-filling, depending on the Node.js +version (and lacking type checks also adds DoS to the list of potential problems)._ + + +## FAQ + + +### What is wrong with the `Buffer` constructor? + +The `Buffer` constructor could be used to create a buffer in many different ways: + +- `new Buffer(42)` creates a `Buffer` of 42 bytes. Before Node.js 8, this buffer contained + *arbitrary memory* for performance reasons, which could include anything ranging from + program source code to passwords and encryption keys. +- `new Buffer('abc')` creates a `Buffer` that contains the UTF-8-encoded version of + the string `'abc'`. A second argument could specify another encoding: For example, + `new Buffer(string, 'base64')` could be used to convert a Base64 string into the original + sequence of bytes that it represents. +- There are several other combinations of arguments. + +This meant that, in code like `var buffer = new Buffer(foo);`, *it is not possible to tell +what exactly the contents of the generated buffer are* without knowing the type of `foo`. + +Sometimes, the value of `foo` comes from an external source. For example, this function +could be exposed as a service on a web server, converting a UTF-8 string into its Base64 form: + +``` +function stringToBase64(req, res) { + // The request body should have the format of `{ string: 'foobar' }` + const rawBytes = new Buffer(req.body.string) + const encoded = rawBytes.toString('base64') + res.end({ encoded: encoded }) +} +``` + +Note that this code does *not* validate the type of `req.body.string`: + +- `req.body.string` is expected to be a string. If this is the case, all goes well. +- `req.body.string` is controlled by the client that sends the request. +- If `req.body.string` is the *number* `50`, the `rawBytes` would be 50 bytes: + - Before Node.js 8, the content would be uninitialized + - After Node.js 8, the content would be `50` bytes with the value `0` + +Because of the missing type check, an attacker could intentionally send a number +as part of the request. Using this, they can either: + +- Read uninitialized memory. This **will** leak passwords, encryption keys and other + kinds of sensitive information. (Information leak) +- Force the program to allocate a large amount of memory. For example, when specifying + `500000000` as the input value, each request will allocate 500MB of memory. + This can be used to either exhaust the memory available of a program completely + and make it crash, or slow it down significantly. (Denial of Service) + +Both of these scenarios are considered serious security issues in a real-world +web server context. + +when using `Buffer.from(req.body.string)` instead, passing a number will always +throw an exception instead, giving a controlled behaviour that can always be +handled by the program. + + +### The `Buffer()` constructor has been deprecated for a while. Is this really an issue? + +Surveys of code in the `npm` ecosystem have shown that the `Buffer()` constructor is still +widely used. This includes new code, and overall usage of such code has actually been +*increasing*. diff --git a/homework7/project_express/node_modules/safer-buffer/Readme.md b/homework7/project_express/node_modules/safer-buffer/Readme.md new file mode 100644 index 0000000..14b0822 --- /dev/null +++ b/homework7/project_express/node_modules/safer-buffer/Readme.md @@ -0,0 +1,156 @@ +# safer-buffer [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![javascript style guide][standard-image]][standard-url] [![Security Responsible Disclosure][secuirty-image]][secuirty-url] + +[travis-image]: https://travis-ci.org/ChALkeR/safer-buffer.svg?branch=master +[travis-url]: https://travis-ci.org/ChALkeR/safer-buffer +[npm-image]: https://img.shields.io/npm/v/safer-buffer.svg +[npm-url]: https://npmjs.org/package/safer-buffer +[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg +[standard-url]: https://standardjs.com +[secuirty-image]: https://img.shields.io/badge/Security-Responsible%20Disclosure-green.svg +[secuirty-url]: https://github.com/nodejs/security-wg/blob/master/processes/responsible_disclosure_template.md + +Modern Buffer API polyfill without footguns, working on Node.js from 0.8 to current. + +## How to use? + +First, port all `Buffer()` and `new Buffer()` calls to `Buffer.alloc()` and `Buffer.from()` API. + +Then, to achieve compatibility with outdated Node.js versions (`<4.5.0` and 5.x `<5.9.0`), use +`const Buffer = require('safer-buffer').Buffer` in all files where you make calls to the new +Buffer API. _Use `var` instead of `const` if you need that for your Node.js version range support._ + +Also, see the +[porting Buffer](https://github.com/ChALkeR/safer-buffer/blob/master/Porting-Buffer.md) guide. + +## Do I need it? + +Hopefully, not — dropping support for outdated Node.js versions should be fine nowdays, and that +is the recommended path forward. You _do_ need to port to the `Buffer.alloc()` and `Buffer.from()` +though. + +See the [porting guide](https://github.com/ChALkeR/safer-buffer/blob/master/Porting-Buffer.md) +for a better description. + +## Why not [safe-buffer](https://npmjs.com/safe-buffer)? + +_In short: while `safe-buffer` serves as a polyfill for the new API, it allows old API usage and +itself contains footguns._ + +`safe-buffer` could be used safely to get the new API while still keeping support for older +Node.js versions (like this module), but while analyzing ecosystem usage of the old Buffer API +I found out that `safe-buffer` is itself causing problems in some cases. + +For example, consider the following snippet: + +```console +$ cat example.unsafe.js +console.log(Buffer(20)) +$ ./node-v6.13.0-linux-x64/bin/node example.unsafe.js + +$ standard example.unsafe.js +standard: Use JavaScript Standard Style (https://standardjs.com) + /home/chalker/repo/safer-buffer/example.unsafe.js:2:13: 'Buffer()' was deprecated since v6. Use 'Buffer.alloc()' or 'Buffer.from()' (use 'https://www.npmjs.com/package/safe-buffer' for '<4.5.0') instead. +``` + +This is allocates and writes to console an uninitialized chunk of memory. +[standard](https://www.npmjs.com/package/standard) linter (among others) catch that and warn people +to avoid using unsafe API. + +Let's now throw in `safe-buffer`! + +```console +$ cat example.safe-buffer.js +const Buffer = require('safe-buffer').Buffer +console.log(Buffer(20)) +$ standard example.safe-buffer.js +$ ./node-v6.13.0-linux-x64/bin/node example.safe-buffer.js + +``` + +See the problem? Adding in `safe-buffer` _magically removes the lint warning_, but the behavior +remains identiсal to what we had before, and when launched on Node.js 6.x LTS — this dumps out +chunks of uninitialized memory. +_And this code will still emit runtime warnings on Node.js 10.x and above._ + +That was done by design. I first considered changing `safe-buffer`, prohibiting old API usage or +emitting warnings on it, but that significantly diverges from `safe-buffer` design. After some +discussion, it was decided to move my approach into a separate package, and _this is that separate +package_. + +This footgun is not imaginary — I observed top-downloaded packages doing that kind of thing, +«fixing» the lint warning by blindly including `safe-buffer` without any actual changes. + +Also in some cases, even if the API _was_ migrated to use of safe Buffer API — a random pull request +can bring unsafe Buffer API usage back to the codebase by adding new calls — and that could go +unnoticed even if you have a linter prohibiting that (becase of the reason stated above), and even +pass CI. _I also observed that being done in popular packages._ + +Some examples: + * [webdriverio](https://github.com/webdriverio/webdriverio/commit/05cbd3167c12e4930f09ef7cf93b127ba4effae4#diff-124380949022817b90b622871837d56cR31) + (a module with 548 759 downloads/month), + * [websocket-stream](https://github.com/maxogden/websocket-stream/commit/c9312bd24d08271687d76da0fe3c83493871cf61) + (218 288 d/m, fix in [maxogden/websocket-stream#142](https://github.com/maxogden/websocket-stream/pull/142)), + * [node-serialport](https://github.com/node-serialport/node-serialport/commit/e8d9d2b16c664224920ce1c895199b1ce2def48c) + (113 138 d/m, fix in [node-serialport/node-serialport#1510](https://github.com/node-serialport/node-serialport/pull/1510)), + * [karma](https://github.com/karma-runner/karma/commit/3d94b8cf18c695104ca195334dc75ff054c74eec) + (3 973 193 d/m, fix in [karma-runner/karma#2947](https://github.com/karma-runner/karma/pull/2947)), + * [spdy-transport](https://github.com/spdy-http2/spdy-transport/commit/5375ac33f4a62a4f65bcfc2827447d42a5dbe8b1) + (5 970 727 d/m, fix in [spdy-http2/spdy-transport#53](https://github.com/spdy-http2/spdy-transport/pull/53)). + * And there are a lot more over the ecosystem. + +I filed a PR at +[mysticatea/eslint-plugin-node#110](https://github.com/mysticatea/eslint-plugin-node/pull/110) to +partially fix that (for cases when that lint rule is used), but it is a semver-major change for +linter rules and presets, so it would take significant time for that to reach actual setups. +_It also hasn't been released yet (2018-03-20)._ + +Also, `safer-buffer` discourages the usage of `.allocUnsafe()`, which is often done by a mistake. +It still supports it with an explicit concern barier, by placing it under +`require('safer-buffer/dangereous')`. + +## But isn't throwing bad? + +Not really. It's an error that could be noticed and fixed early, instead of causing havoc later like +unguarded `new Buffer()` calls that end up receiving user input can do. + +This package affects only the files where `var Buffer = require('safer-buffer').Buffer` was done, so +it is really simple to keep track of things and make sure that you don't mix old API usage with that. +Also, CI should hint anything that you might have missed. + +New commits, if tested, won't land new usage of unsafe Buffer API this way. +_Node.js 10.x also deals with that by printing a runtime depecation warning._ + +### Would it affect third-party modules? + +No, unless you explicitly do an awful thing like monkey-patching or overriding the built-in `Buffer`. +Don't do that. + +### But I don't want throwing… + +That is also fine! + +Also, it could be better in some cases when you don't comprehensive enough test coverage. + +In that case — just don't override `Buffer` and use +`var SaferBuffer = require('safer-buffer').Buffer` instead. + +That way, everything using `Buffer` natively would still work, but there would be two drawbacks: + +* `Buffer.from`/`Buffer.alloc` won't be polyfilled — use `SaferBuffer.from` and + `SaferBuffer.alloc` instead. +* You are still open to accidentally using the insecure deprecated API — use a linter to catch that. + +Note that using a linter to catch accidential `Buffer` constructor usage in this case is strongly +recommended. `Buffer` is not overriden in this usecase, so linters won't get confused. + +## «Without footguns»? + +Well, it is still possible to do _some_ things with `Buffer` API, e.g. accessing `.buffer` property +on older versions and duping things from there. You shouldn't do that in your code, probabably. + +The intention is to remove the most significant footguns that affect lots of packages in the +ecosystem, and to do it in the proper way. + +Also, this package doesn't protect against security issues affecting some Node.js versions, so for +usage in your own production code, it is still recommended to update to a Node.js version +[supported by upstream](https://github.com/nodejs/release#release-schedule). diff --git a/homework7/project_express/node_modules/safer-buffer/dangerous.js b/homework7/project_express/node_modules/safer-buffer/dangerous.js new file mode 100644 index 0000000..ca41fdc --- /dev/null +++ b/homework7/project_express/node_modules/safer-buffer/dangerous.js @@ -0,0 +1,58 @@ +/* eslint-disable node/no-deprecated-api */ + +'use strict' + +var buffer = require('buffer') +var Buffer = buffer.Buffer +var safer = require('./safer.js') +var Safer = safer.Buffer + +var dangerous = {} + +var key + +for (key in safer) { + if (!safer.hasOwnProperty(key)) continue + dangerous[key] = safer[key] +} + +var Dangereous = dangerous.Buffer = {} + +// Copy Safer API +for (key in Safer) { + if (!Safer.hasOwnProperty(key)) continue + Dangereous[key] = Safer[key] +} + +// Copy those missing unsafe methods, if they are present +for (key in Buffer) { + if (!Buffer.hasOwnProperty(key)) continue + if (Dangereous.hasOwnProperty(key)) continue + Dangereous[key] = Buffer[key] +} + +if (!Dangereous.allocUnsafe) { + Dangereous.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('The "size" argument must be of type number. Received type ' + typeof size) + } + if (size < 0 || size >= 2 * (1 << 30)) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } + return Buffer(size) + } +} + +if (!Dangereous.allocUnsafeSlow) { + Dangereous.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('The "size" argument must be of type number. Received type ' + typeof size) + } + if (size < 0 || size >= 2 * (1 << 30)) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } + return buffer.SlowBuffer(size) + } +} + +module.exports = dangerous diff --git a/homework7/project_express/node_modules/safer-buffer/package.json b/homework7/project_express/node_modules/safer-buffer/package.json new file mode 100644 index 0000000..19230ab --- /dev/null +++ b/homework7/project_express/node_modules/safer-buffer/package.json @@ -0,0 +1,60 @@ +{ + "_from": "safer-buffer@>= 2.1.2 < 3", + "_id": "safer-buffer@2.1.2", + "_inBundle": false, + "_integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "_location": "/safer-buffer", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "safer-buffer@>= 2.1.2 < 3", + "name": "safer-buffer", + "escapedName": "safer-buffer", + "rawSpec": ">= 2.1.2 < 3", + "saveSpec": null, + "fetchSpec": ">= 2.1.2 < 3" + }, + "_requiredBy": [ + "/iconv-lite" + ], + "_resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "_shasum": "44fa161b0187b9549dd84bb91802f9bd8385cd6a", + "_spec": "safer-buffer@>= 2.1.2 < 3", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\iconv-lite", + "author": { + "name": "Nikita Skovoroda", + "email": "chalkerx@gmail.com", + "url": "https://github.com/ChALkeR" + }, + "bugs": { + "url": "https://github.com/ChALkeR/safer-buffer/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Modern Buffer API polyfill without footguns", + "devDependencies": { + "standard": "^11.0.1", + "tape": "^4.9.0" + }, + "files": [ + "Porting-Buffer.md", + "Readme.md", + "tests.js", + "dangerous.js", + "safer.js" + ], + "homepage": "https://github.com/ChALkeR/safer-buffer#readme", + "license": "MIT", + "main": "safer.js", + "name": "safer-buffer", + "repository": { + "type": "git", + "url": "git+https://github.com/ChALkeR/safer-buffer.git" + }, + "scripts": { + "browserify-test": "browserify --external tape tests.js > browserify-tests.js && tape browserify-tests.js", + "test": "standard && tape tests.js" + }, + "version": "2.1.2" +} diff --git a/homework7/project_express/node_modules/safer-buffer/safer.js b/homework7/project_express/node_modules/safer-buffer/safer.js new file mode 100644 index 0000000..37c7e1a --- /dev/null +++ b/homework7/project_express/node_modules/safer-buffer/safer.js @@ -0,0 +1,77 @@ +/* eslint-disable node/no-deprecated-api */ + +'use strict' + +var buffer = require('buffer') +var Buffer = buffer.Buffer + +var safer = {} + +var key + +for (key in buffer) { + if (!buffer.hasOwnProperty(key)) continue + if (key === 'SlowBuffer' || key === 'Buffer') continue + safer[key] = buffer[key] +} + +var Safer = safer.Buffer = {} +for (key in Buffer) { + if (!Buffer.hasOwnProperty(key)) continue + if (key === 'allocUnsafe' || key === 'allocUnsafeSlow') continue + Safer[key] = Buffer[key] +} + +safer.Buffer.prototype = Buffer.prototype + +if (!Safer.from || Safer.from === Uint8Array.from) { + Safer.from = function (value, encodingOrOffset, length) { + if (typeof value === 'number') { + throw new TypeError('The "value" argument must not be of type number. Received type ' + typeof value) + } + if (value && typeof value.length === 'undefined') { + throw new TypeError('The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type ' + typeof value) + } + return Buffer(value, encodingOrOffset, length) + } +} + +if (!Safer.alloc) { + Safer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('The "size" argument must be of type number. Received type ' + typeof size) + } + if (size < 0 || size >= 2 * (1 << 30)) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } + var buf = Buffer(size) + if (!fill || fill.length === 0) { + buf.fill(0) + } else if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + return buf + } +} + +if (!safer.kStringMaxLength) { + try { + safer.kStringMaxLength = process.binding('buffer').kStringMaxLength + } catch (e) { + // we can't determine kStringMaxLength in environments where process.binding + // is unsupported, so let's not set it + } +} + +if (!safer.constants) { + safer.constants = { + MAX_LENGTH: safer.kMaxLength + } + if (safer.kStringMaxLength) { + safer.constants.MAX_STRING_LENGTH = safer.kStringMaxLength + } +} + +module.exports = safer diff --git a/homework7/project_express/node_modules/safer-buffer/tests.js b/homework7/project_express/node_modules/safer-buffer/tests.js new file mode 100644 index 0000000..7ed2777 --- /dev/null +++ b/homework7/project_express/node_modules/safer-buffer/tests.js @@ -0,0 +1,406 @@ +/* eslint-disable node/no-deprecated-api */ + +'use strict' + +var test = require('tape') + +var buffer = require('buffer') + +var index = require('./') +var safer = require('./safer') +var dangerous = require('./dangerous') + +/* Inheritance tests */ + +test('Default is Safer', function (t) { + t.equal(index, safer) + t.notEqual(safer, dangerous) + t.notEqual(index, dangerous) + t.end() +}) + +test('Is not a function', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(typeof impl, 'object') + t.equal(typeof impl.Buffer, 'object') + }); + [buffer].forEach(function (impl) { + t.equal(typeof impl, 'object') + t.equal(typeof impl.Buffer, 'function') + }) + t.end() +}) + +test('Constructor throws', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.throws(function () { impl.Buffer() }) + t.throws(function () { impl.Buffer(0) }) + t.throws(function () { impl.Buffer('a') }) + t.throws(function () { impl.Buffer('a', 'utf-8') }) + t.throws(function () { return new impl.Buffer() }) + t.throws(function () { return new impl.Buffer(0) }) + t.throws(function () { return new impl.Buffer('a') }) + t.throws(function () { return new impl.Buffer('a', 'utf-8') }) + }) + t.end() +}) + +test('Safe methods exist', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(typeof impl.Buffer.alloc, 'function', 'alloc') + t.equal(typeof impl.Buffer.from, 'function', 'from') + }) + t.end() +}) + +test('Unsafe methods exist only in Dangerous', function (t) { + [index, safer].forEach(function (impl) { + t.equal(typeof impl.Buffer.allocUnsafe, 'undefined') + t.equal(typeof impl.Buffer.allocUnsafeSlow, 'undefined') + }); + [dangerous].forEach(function (impl) { + t.equal(typeof impl.Buffer.allocUnsafe, 'function') + t.equal(typeof impl.Buffer.allocUnsafeSlow, 'function') + }) + t.end() +}) + +test('Generic methods/properties are defined and equal', function (t) { + ['poolSize', 'isBuffer', 'concat', 'byteLength'].forEach(function (method) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer[method], buffer.Buffer[method], method) + t.notEqual(typeof impl.Buffer[method], 'undefined', method) + }) + }) + t.end() +}) + +test('Built-in buffer static methods/properties are inherited', function (t) { + Object.keys(buffer).forEach(function (method) { + if (method === 'SlowBuffer' || method === 'Buffer') return; + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl[method], buffer[method], method) + t.notEqual(typeof impl[method], 'undefined', method) + }) + }) + t.end() +}) + +test('Built-in Buffer static methods/properties are inherited', function (t) { + Object.keys(buffer.Buffer).forEach(function (method) { + if (method === 'allocUnsafe' || method === 'allocUnsafeSlow') return; + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer[method], buffer.Buffer[method], method) + t.notEqual(typeof impl.Buffer[method], 'undefined', method) + }) + }) + t.end() +}) + +test('.prototype property of Buffer is inherited', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer.prototype, buffer.Buffer.prototype, 'prototype') + t.notEqual(typeof impl.Buffer.prototype, 'undefined', 'prototype') + }) + t.end() +}) + +test('All Safer methods are present in Dangerous', function (t) { + Object.keys(safer).forEach(function (method) { + if (method === 'Buffer') return; + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl[method], safer[method], method) + if (method !== 'kStringMaxLength') { + t.notEqual(typeof impl[method], 'undefined', method) + } + }) + }) + Object.keys(safer.Buffer).forEach(function (method) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer[method], safer.Buffer[method], method) + t.notEqual(typeof impl.Buffer[method], 'undefined', method) + }) + }) + t.end() +}) + +test('Safe methods from Dangerous methods are present in Safer', function (t) { + Object.keys(dangerous).forEach(function (method) { + if (method === 'Buffer') return; + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl[method], dangerous[method], method) + if (method !== 'kStringMaxLength') { + t.notEqual(typeof impl[method], 'undefined', method) + } + }) + }) + Object.keys(dangerous.Buffer).forEach(function (method) { + if (method === 'allocUnsafe' || method === 'allocUnsafeSlow') return; + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer[method], dangerous.Buffer[method], method) + t.notEqual(typeof impl.Buffer[method], 'undefined', method) + }) + }) + t.end() +}) + +/* Behaviour tests */ + +test('Methods return Buffers', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(0))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(0, 10))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(0, 'a'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(10))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(10, 'x'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(9, 'ab'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from(''))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from('string'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from('string', 'utf-8'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from([0, 42, 3]))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from(new Uint8Array([0, 42, 3])))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from([]))) + }); + ['allocUnsafe', 'allocUnsafeSlow'].forEach(function (method) { + t.ok(buffer.Buffer.isBuffer(dangerous.Buffer[method](0))) + t.ok(buffer.Buffer.isBuffer(dangerous.Buffer[method](10))) + }) + t.end() +}) + +test('Constructor is buffer.Buffer', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer.alloc(0).constructor, buffer.Buffer) + t.equal(impl.Buffer.alloc(0, 10).constructor, buffer.Buffer) + t.equal(impl.Buffer.alloc(0, 'a').constructor, buffer.Buffer) + t.equal(impl.Buffer.alloc(10).constructor, buffer.Buffer) + t.equal(impl.Buffer.alloc(10, 'x').constructor, buffer.Buffer) + t.equal(impl.Buffer.alloc(9, 'ab').constructor, buffer.Buffer) + t.equal(impl.Buffer.from('').constructor, buffer.Buffer) + t.equal(impl.Buffer.from('string').constructor, buffer.Buffer) + t.equal(impl.Buffer.from('string', 'utf-8').constructor, buffer.Buffer) + t.equal(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64').constructor, buffer.Buffer) + t.equal(impl.Buffer.from([0, 42, 3]).constructor, buffer.Buffer) + t.equal(impl.Buffer.from(new Uint8Array([0, 42, 3])).constructor, buffer.Buffer) + t.equal(impl.Buffer.from([]).constructor, buffer.Buffer) + }); + [0, 10, 100].forEach(function (arg) { + t.equal(dangerous.Buffer.allocUnsafe(arg).constructor, buffer.Buffer) + t.equal(dangerous.Buffer.allocUnsafeSlow(arg).constructor, buffer.SlowBuffer(0).constructor) + }) + t.end() +}) + +test('Invalid calls throw', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.throws(function () { impl.Buffer.from(0) }) + t.throws(function () { impl.Buffer.from(10) }) + t.throws(function () { impl.Buffer.from(10, 'utf-8') }) + t.throws(function () { impl.Buffer.from('string', 'invalid encoding') }) + t.throws(function () { impl.Buffer.from(-10) }) + t.throws(function () { impl.Buffer.from(1e90) }) + t.throws(function () { impl.Buffer.from(Infinity) }) + t.throws(function () { impl.Buffer.from(-Infinity) }) + t.throws(function () { impl.Buffer.from(NaN) }) + t.throws(function () { impl.Buffer.from(null) }) + t.throws(function () { impl.Buffer.from(undefined) }) + t.throws(function () { impl.Buffer.from() }) + t.throws(function () { impl.Buffer.from({}) }) + t.throws(function () { impl.Buffer.alloc('') }) + t.throws(function () { impl.Buffer.alloc('string') }) + t.throws(function () { impl.Buffer.alloc('string', 'utf-8') }) + t.throws(function () { impl.Buffer.alloc('b25ldHdvdGhyZWU=', 'base64') }) + t.throws(function () { impl.Buffer.alloc(-10) }) + t.throws(function () { impl.Buffer.alloc(1e90) }) + t.throws(function () { impl.Buffer.alloc(2 * (1 << 30)) }) + t.throws(function () { impl.Buffer.alloc(Infinity) }) + t.throws(function () { impl.Buffer.alloc(-Infinity) }) + t.throws(function () { impl.Buffer.alloc(null) }) + t.throws(function () { impl.Buffer.alloc(undefined) }) + t.throws(function () { impl.Buffer.alloc() }) + t.throws(function () { impl.Buffer.alloc([]) }) + t.throws(function () { impl.Buffer.alloc([0, 42, 3]) }) + t.throws(function () { impl.Buffer.alloc({}) }) + }); + ['allocUnsafe', 'allocUnsafeSlow'].forEach(function (method) { + t.throws(function () { dangerous.Buffer[method]('') }) + t.throws(function () { dangerous.Buffer[method]('string') }) + t.throws(function () { dangerous.Buffer[method]('string', 'utf-8') }) + t.throws(function () { dangerous.Buffer[method](2 * (1 << 30)) }) + t.throws(function () { dangerous.Buffer[method](Infinity) }) + if (dangerous.Buffer[method] === buffer.Buffer.allocUnsafe) { + t.skip('Skipping, older impl of allocUnsafe coerced negative sizes to 0') + } else { + t.throws(function () { dangerous.Buffer[method](-10) }) + t.throws(function () { dangerous.Buffer[method](-1e90) }) + t.throws(function () { dangerous.Buffer[method](-Infinity) }) + } + t.throws(function () { dangerous.Buffer[method](null) }) + t.throws(function () { dangerous.Buffer[method](undefined) }) + t.throws(function () { dangerous.Buffer[method]() }) + t.throws(function () { dangerous.Buffer[method]([]) }) + t.throws(function () { dangerous.Buffer[method]([0, 42, 3]) }) + t.throws(function () { dangerous.Buffer[method]({}) }) + }) + t.end() +}) + +test('Buffers have appropriate lengths', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer.alloc(0).length, 0) + t.equal(impl.Buffer.alloc(10).length, 10) + t.equal(impl.Buffer.from('').length, 0) + t.equal(impl.Buffer.from('string').length, 6) + t.equal(impl.Buffer.from('string', 'utf-8').length, 6) + t.equal(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64').length, 11) + t.equal(impl.Buffer.from([0, 42, 3]).length, 3) + t.equal(impl.Buffer.from(new Uint8Array([0, 42, 3])).length, 3) + t.equal(impl.Buffer.from([]).length, 0) + }); + ['allocUnsafe', 'allocUnsafeSlow'].forEach(function (method) { + t.equal(dangerous.Buffer[method](0).length, 0) + t.equal(dangerous.Buffer[method](10).length, 10) + }) + t.end() +}) + +test('Buffers have appropriate lengths (2)', function (t) { + t.equal(index.Buffer.alloc, safer.Buffer.alloc) + t.equal(index.Buffer.alloc, dangerous.Buffer.alloc) + var ok = true; + [ safer.Buffer.alloc, + dangerous.Buffer.allocUnsafe, + dangerous.Buffer.allocUnsafeSlow + ].forEach(function (method) { + for (var i = 0; i < 1e2; i++) { + var length = Math.round(Math.random() * 1e5) + var buf = method(length) + if (!buffer.Buffer.isBuffer(buf)) ok = false + if (buf.length !== length) ok = false + } + }) + t.ok(ok) + t.end() +}) + +test('.alloc(size) is zero-filled and has correct length', function (t) { + t.equal(index.Buffer.alloc, safer.Buffer.alloc) + t.equal(index.Buffer.alloc, dangerous.Buffer.alloc) + var ok = true + for (var i = 0; i < 1e2; i++) { + var length = Math.round(Math.random() * 2e6) + var buf = index.Buffer.alloc(length) + if (!buffer.Buffer.isBuffer(buf)) ok = false + if (buf.length !== length) ok = false + var j + for (j = 0; j < length; j++) { + if (buf[j] !== 0) ok = false + } + buf.fill(1) + for (j = 0; j < length; j++) { + if (buf[j] !== 1) ok = false + } + } + t.ok(ok) + t.end() +}) + +test('.allocUnsafe / .allocUnsafeSlow are fillable and have correct lengths', function (t) { + ['allocUnsafe', 'allocUnsafeSlow'].forEach(function (method) { + var ok = true + for (var i = 0; i < 1e2; i++) { + var length = Math.round(Math.random() * 2e6) + var buf = dangerous.Buffer[method](length) + if (!buffer.Buffer.isBuffer(buf)) ok = false + if (buf.length !== length) ok = false + buf.fill(0, 0, length) + var j + for (j = 0; j < length; j++) { + if (buf[j] !== 0) ok = false + } + buf.fill(1, 0, length) + for (j = 0; j < length; j++) { + if (buf[j] !== 1) ok = false + } + } + t.ok(ok, method) + }) + t.end() +}) + +test('.alloc(size, fill) is `fill`-filled', function (t) { + t.equal(index.Buffer.alloc, safer.Buffer.alloc) + t.equal(index.Buffer.alloc, dangerous.Buffer.alloc) + var ok = true + for (var i = 0; i < 1e2; i++) { + var length = Math.round(Math.random() * 2e6) + var fill = Math.round(Math.random() * 255) + var buf = index.Buffer.alloc(length, fill) + if (!buffer.Buffer.isBuffer(buf)) ok = false + if (buf.length !== length) ok = false + for (var j = 0; j < length; j++) { + if (buf[j] !== fill) ok = false + } + } + t.ok(ok) + t.end() +}) + +test('.alloc(size, fill) is `fill`-filled', function (t) { + t.equal(index.Buffer.alloc, safer.Buffer.alloc) + t.equal(index.Buffer.alloc, dangerous.Buffer.alloc) + var ok = true + for (var i = 0; i < 1e2; i++) { + var length = Math.round(Math.random() * 2e6) + var fill = Math.round(Math.random() * 255) + var buf = index.Buffer.alloc(length, fill) + if (!buffer.Buffer.isBuffer(buf)) ok = false + if (buf.length !== length) ok = false + for (var j = 0; j < length; j++) { + if (buf[j] !== fill) ok = false + } + } + t.ok(ok) + t.deepEqual(index.Buffer.alloc(9, 'a'), index.Buffer.alloc(9, 97)) + t.notDeepEqual(index.Buffer.alloc(9, 'a'), index.Buffer.alloc(9, 98)) + + var tmp = new buffer.Buffer(2) + tmp.fill('ok') + if (tmp[1] === tmp[0]) { + // Outdated Node.js + t.deepEqual(index.Buffer.alloc(5, 'ok'), index.Buffer.from('ooooo')) + } else { + t.deepEqual(index.Buffer.alloc(5, 'ok'), index.Buffer.from('okoko')) + } + t.notDeepEqual(index.Buffer.alloc(5, 'ok'), index.Buffer.from('kokok')) + + t.end() +}) + +test('safer.Buffer.from returns results same as Buffer constructor', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.deepEqual(impl.Buffer.from(''), new buffer.Buffer('')) + t.deepEqual(impl.Buffer.from('string'), new buffer.Buffer('string')) + t.deepEqual(impl.Buffer.from('string', 'utf-8'), new buffer.Buffer('string', 'utf-8')) + t.deepEqual(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64'), new buffer.Buffer('b25ldHdvdGhyZWU=', 'base64')) + t.deepEqual(impl.Buffer.from([0, 42, 3]), new buffer.Buffer([0, 42, 3])) + t.deepEqual(impl.Buffer.from(new Uint8Array([0, 42, 3])), new buffer.Buffer(new Uint8Array([0, 42, 3]))) + t.deepEqual(impl.Buffer.from([]), new buffer.Buffer([])) + }) + t.end() +}) + +test('safer.Buffer.from returns consistent results', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.deepEqual(impl.Buffer.from(''), impl.Buffer.alloc(0)) + t.deepEqual(impl.Buffer.from([]), impl.Buffer.alloc(0)) + t.deepEqual(impl.Buffer.from(new Uint8Array([])), impl.Buffer.alloc(0)) + t.deepEqual(impl.Buffer.from('string', 'utf-8'), impl.Buffer.from('string')) + t.deepEqual(impl.Buffer.from('string'), impl.Buffer.from([115, 116, 114, 105, 110, 103])) + t.deepEqual(impl.Buffer.from('string'), impl.Buffer.from(impl.Buffer.from('string'))) + t.deepEqual(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64'), impl.Buffer.from('onetwothree')) + t.notDeepEqual(impl.Buffer.from('b25ldHdvdGhyZWU='), impl.Buffer.from('onetwothree')) + }) + t.end() +}) diff --git a/homework7/project_express/node_modules/semver/CHANGELOG.md b/homework7/project_express/node_modules/semver/CHANGELOG.md new file mode 100644 index 0000000..66304fd --- /dev/null +++ b/homework7/project_express/node_modules/semver/CHANGELOG.md @@ -0,0 +1,39 @@ +# changes log + +## 5.7 + +* Add `minVersion` method + +## 5.6 + +* Move boolean `loose` param to an options object, with + backwards-compatibility protection. +* Add ability to opt out of special prerelease version handling with + the `includePrerelease` option flag. + +## 5.5 + +* Add version coercion capabilities + +## 5.4 + +* Add intersection checking + +## 5.3 + +* Add `minSatisfying` method + +## 5.2 + +* Add `prerelease(v)` that returns prerelease components + +## 5.1 + +* Add Backus-Naur for ranges +* Remove excessively cute inspection methods + +## 5.0 + +* Remove AMD/Browserified build artifacts +* Fix ltr and gtr when using the `*` range +* Fix for range `*` with a prerelease identifier diff --git a/homework7/project_express/node_modules/semver/LICENSE b/homework7/project_express/node_modules/semver/LICENSE new file mode 100644 index 0000000..19129e3 --- /dev/null +++ b/homework7/project_express/node_modules/semver/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/homework7/project_express/node_modules/semver/README.md b/homework7/project_express/node_modules/semver/README.md new file mode 100644 index 0000000..f8dfa5a --- /dev/null +++ b/homework7/project_express/node_modules/semver/README.md @@ -0,0 +1,412 @@ +semver(1) -- The semantic versioner for npm +=========================================== + +## Install + +```bash +npm install --save semver +```` + +## Usage + +As a node module: + +```js +const semver = require('semver') + +semver.valid('1.2.3') // '1.2.3' +semver.valid('a.b.c') // null +semver.clean(' =v1.2.3 ') // '1.2.3' +semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true +semver.gt('1.2.3', '9.8.7') // false +semver.lt('1.2.3', '9.8.7') // true +semver.minVersion('>=1.0.0') // '1.0.0' +semver.valid(semver.coerce('v2')) // '2.0.0' +semver.valid(semver.coerce('42.6.7.9.3-alpha')) // '42.6.7' +``` + +As a command-line utility: + +``` +$ semver -h + +A JavaScript implementation of the https://semver.org/ specification +Copyright Isaac Z. Schlueter + +Usage: semver [options] [ [...]] +Prints valid versions sorted by SemVer precedence + +Options: +-r --range + Print versions that match the specified range. + +-i --increment [] + Increment a version by the specified level. Level can + be one of: major, minor, patch, premajor, preminor, + prepatch, or prerelease. Default level is 'patch'. + Only one version may be specified. + +--preid + Identifier to be used to prefix premajor, preminor, + prepatch or prerelease version increments. + +-l --loose + Interpret versions and ranges loosely + +-p --include-prerelease + Always include prerelease versions in range matching + +-c --coerce + Coerce a string into SemVer if possible + (does not imply --loose) + +Program exits successfully if any valid version satisfies +all supplied ranges, and prints all satisfying versions. + +If no satisfying versions are found, then exits failure. + +Versions are printed in ascending order, so supplying +multiple versions to the utility will just sort them. +``` + +## Versions + +A "version" is described by the `v2.0.0` specification found at +. + +A leading `"="` or `"v"` character is stripped off and ignored. + +## Ranges + +A `version range` is a set of `comparators` which specify versions +that satisfy the range. + +A `comparator` is composed of an `operator` and a `version`. The set +of primitive `operators` is: + +* `<` Less than +* `<=` Less than or equal to +* `>` Greater than +* `>=` Greater than or equal to +* `=` Equal. If no operator is specified, then equality is assumed, + so this operator is optional, but MAY be included. + +For example, the comparator `>=1.2.7` would match the versions +`1.2.7`, `1.2.8`, `2.5.3`, and `1.3.9`, but not the versions `1.2.6` +or `1.1.0`. + +Comparators can be joined by whitespace to form a `comparator set`, +which is satisfied by the **intersection** of all of the comparators +it includes. + +A range is composed of one or more comparator sets, joined by `||`. A +version matches a range if and only if every comparator in at least +one of the `||`-separated comparator sets is satisfied by the version. + +For example, the range `>=1.2.7 <1.3.0` would match the versions +`1.2.7`, `1.2.8`, and `1.2.99`, but not the versions `1.2.6`, `1.3.0`, +or `1.1.0`. + +The range `1.2.7 || >=1.2.9 <2.0.0` would match the versions `1.2.7`, +`1.2.9`, and `1.4.6`, but not the versions `1.2.8` or `2.0.0`. + +### Prerelease Tags + +If a version has a prerelease tag (for example, `1.2.3-alpha.3`) then +it will only be allowed to satisfy comparator sets if at least one +comparator with the same `[major, minor, patch]` tuple also has a +prerelease tag. + +For example, the range `>1.2.3-alpha.3` would be allowed to match the +version `1.2.3-alpha.7`, but it would *not* be satisfied by +`3.4.5-alpha.9`, even though `3.4.5-alpha.9` is technically "greater +than" `1.2.3-alpha.3` according to the SemVer sort rules. The version +range only accepts prerelease tags on the `1.2.3` version. The +version `3.4.5` *would* satisfy the range, because it does not have a +prerelease flag, and `3.4.5` is greater than `1.2.3-alpha.7`. + +The purpose for this behavior is twofold. First, prerelease versions +frequently are updated very quickly, and contain many breaking changes +that are (by the author's design) not yet fit for public consumption. +Therefore, by default, they are excluded from range matching +semantics. + +Second, a user who has opted into using a prerelease version has +clearly indicated the intent to use *that specific* set of +alpha/beta/rc versions. By including a prerelease tag in the range, +the user is indicating that they are aware of the risk. However, it +is still not appropriate to assume that they have opted into taking a +similar risk on the *next* set of prerelease versions. + +Note that this behavior can be suppressed (treating all prerelease +versions as if they were normal versions, for the purpose of range +matching) by setting the `includePrerelease` flag on the options +object to any +[functions](https://github.com/npm/node-semver#functions) that do +range matching. + +#### Prerelease Identifiers + +The method `.inc` takes an additional `identifier` string argument that +will append the value of the string as a prerelease identifier: + +```javascript +semver.inc('1.2.3', 'prerelease', 'beta') +// '1.2.4-beta.0' +``` + +command-line example: + +```bash +$ semver 1.2.3 -i prerelease --preid beta +1.2.4-beta.0 +``` + +Which then can be used to increment further: + +```bash +$ semver 1.2.4-beta.0 -i prerelease +1.2.4-beta.1 +``` + +### Advanced Range Syntax + +Advanced range syntax desugars to primitive comparators in +deterministic ways. + +Advanced ranges may be combined in the same way as primitive +comparators using white space or `||`. + +#### Hyphen Ranges `X.Y.Z - A.B.C` + +Specifies an inclusive set. + +* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4` + +If a partial version is provided as the first version in the inclusive +range, then the missing pieces are replaced with zeroes. + +* `1.2 - 2.3.4` := `>=1.2.0 <=2.3.4` + +If a partial version is provided as the second version in the +inclusive range, then all versions that start with the supplied parts +of the tuple are accepted, but nothing that would be greater than the +provided tuple parts. + +* `1.2.3 - 2.3` := `>=1.2.3 <2.4.0` +* `1.2.3 - 2` := `>=1.2.3 <3.0.0` + +#### X-Ranges `1.2.x` `1.X` `1.2.*` `*` + +Any of `X`, `x`, or `*` may be used to "stand in" for one of the +numeric values in the `[major, minor, patch]` tuple. + +* `*` := `>=0.0.0` (Any version satisfies) +* `1.x` := `>=1.0.0 <2.0.0` (Matching major version) +* `1.2.x` := `>=1.2.0 <1.3.0` (Matching major and minor versions) + +A partial version range is treated as an X-Range, so the special +character is in fact optional. + +* `""` (empty string) := `*` := `>=0.0.0` +* `1` := `1.x.x` := `>=1.0.0 <2.0.0` +* `1.2` := `1.2.x` := `>=1.2.0 <1.3.0` + +#### Tilde Ranges `~1.2.3` `~1.2` `~1` + +Allows patch-level changes if a minor version is specified on the +comparator. Allows minor-level changes if not. + +* `~1.2.3` := `>=1.2.3 <1.(2+1).0` := `>=1.2.3 <1.3.0` +* `~1.2` := `>=1.2.0 <1.(2+1).0` := `>=1.2.0 <1.3.0` (Same as `1.2.x`) +* `~1` := `>=1.0.0 <(1+1).0.0` := `>=1.0.0 <2.0.0` (Same as `1.x`) +* `~0.2.3` := `>=0.2.3 <0.(2+1).0` := `>=0.2.3 <0.3.0` +* `~0.2` := `>=0.2.0 <0.(2+1).0` := `>=0.2.0 <0.3.0` (Same as `0.2.x`) +* `~0` := `>=0.0.0 <(0+1).0.0` := `>=0.0.0 <1.0.0` (Same as `0.x`) +* `~1.2.3-beta.2` := `>=1.2.3-beta.2 <1.3.0` Note that prereleases in + the `1.2.3` version will be allowed, if they are greater than or + equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but + `1.2.4-beta.2` would not, because it is a prerelease of a + different `[major, minor, patch]` tuple. + +#### Caret Ranges `^1.2.3` `^0.2.5` `^0.0.4` + +Allows changes that do not modify the left-most non-zero digit in the +`[major, minor, patch]` tuple. In other words, this allows patch and +minor updates for versions `1.0.0` and above, patch updates for +versions `0.X >=0.1.0`, and *no* updates for versions `0.0.X`. + +Many authors treat a `0.x` version as if the `x` were the major +"breaking-change" indicator. + +Caret ranges are ideal when an author may make breaking changes +between `0.2.4` and `0.3.0` releases, which is a common practice. +However, it presumes that there will *not* be breaking changes between +`0.2.4` and `0.2.5`. It allows for changes that are presumed to be +additive (but non-breaking), according to commonly observed practices. + +* `^1.2.3` := `>=1.2.3 <2.0.0` +* `^0.2.3` := `>=0.2.3 <0.3.0` +* `^0.0.3` := `>=0.0.3 <0.0.4` +* `^1.2.3-beta.2` := `>=1.2.3-beta.2 <2.0.0` Note that prereleases in + the `1.2.3` version will be allowed, if they are greater than or + equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but + `1.2.4-beta.2` would not, because it is a prerelease of a + different `[major, minor, patch]` tuple. +* `^0.0.3-beta` := `>=0.0.3-beta <0.0.4` Note that prereleases in the + `0.0.3` version *only* will be allowed, if they are greater than or + equal to `beta`. So, `0.0.3-pr.2` would be allowed. + +When parsing caret ranges, a missing `patch` value desugars to the +number `0`, but will allow flexibility within that value, even if the +major and minor versions are both `0`. + +* `^1.2.x` := `>=1.2.0 <2.0.0` +* `^0.0.x` := `>=0.0.0 <0.1.0` +* `^0.0` := `>=0.0.0 <0.1.0` + +A missing `minor` and `patch` values will desugar to zero, but also +allow flexibility within those values, even if the major version is +zero. + +* `^1.x` := `>=1.0.0 <2.0.0` +* `^0.x` := `>=0.0.0 <1.0.0` + +### Range Grammar + +Putting all this together, here is a Backus-Naur grammar for ranges, +for the benefit of parser authors: + +```bnf +range-set ::= range ( logical-or range ) * +logical-or ::= ( ' ' ) * '||' ( ' ' ) * +range ::= hyphen | simple ( ' ' simple ) * | '' +hyphen ::= partial ' - ' partial +simple ::= primitive | partial | tilde | caret +primitive ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial +partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )? +xr ::= 'x' | 'X' | '*' | nr +nr ::= '0' | ['1'-'9'] ( ['0'-'9'] ) * +tilde ::= '~' partial +caret ::= '^' partial +qualifier ::= ( '-' pre )? ( '+' build )? +pre ::= parts +build ::= parts +parts ::= part ( '.' part ) * +part ::= nr | [-0-9A-Za-z]+ +``` + +## Functions + +All methods and classes take a final `options` object argument. All +options in this object are `false` by default. The options supported +are: + +- `loose` Be more forgiving about not-quite-valid semver strings. + (Any resulting output will always be 100% strict compliant, of + course.) For backwards compatibility reasons, if the `options` + argument is a boolean value instead of an object, it is interpreted + to be the `loose` param. +- `includePrerelease` Set to suppress the [default + behavior](https://github.com/npm/node-semver#prerelease-tags) of + excluding prerelease tagged versions from ranges unless they are + explicitly opted into. + +Strict-mode Comparators and Ranges will be strict about the SemVer +strings that they parse. + +* `valid(v)`: Return the parsed version, or null if it's not valid. +* `inc(v, release)`: Return the version incremented by the release + type (`major`, `premajor`, `minor`, `preminor`, `patch`, + `prepatch`, or `prerelease`), or null if it's not valid + * `premajor` in one call will bump the version up to the next major + version and down to a prerelease of that major version. + `preminor`, and `prepatch` work the same way. + * If called from a non-prerelease version, the `prerelease` will work the + same as `prepatch`. It increments the patch version, then makes a + prerelease. If the input version is already a prerelease it simply + increments it. +* `prerelease(v)`: Returns an array of prerelease components, or null + if none exist. Example: `prerelease('1.2.3-alpha.1') -> ['alpha', 1]` +* `major(v)`: Return the major version number. +* `minor(v)`: Return the minor version number. +* `patch(v)`: Return the patch version number. +* `intersects(r1, r2, loose)`: Return true if the two supplied ranges + or comparators intersect. +* `parse(v)`: Attempt to parse a string as a semantic version, returning either + a `SemVer` object or `null`. + +### Comparison + +* `gt(v1, v2)`: `v1 > v2` +* `gte(v1, v2)`: `v1 >= v2` +* `lt(v1, v2)`: `v1 < v2` +* `lte(v1, v2)`: `v1 <= v2` +* `eq(v1, v2)`: `v1 == v2` This is true if they're logically equivalent, + even if they're not the exact same string. You already know how to + compare strings. +* `neq(v1, v2)`: `v1 != v2` The opposite of `eq`. +* `cmp(v1, comparator, v2)`: Pass in a comparison string, and it'll call + the corresponding function above. `"==="` and `"!=="` do simple + string comparison, but are included for completeness. Throws if an + invalid comparison string is provided. +* `compare(v1, v2)`: Return `0` if `v1 == v2`, or `1` if `v1` is greater, or `-1` if + `v2` is greater. Sorts in ascending order if passed to `Array.sort()`. +* `rcompare(v1, v2)`: The reverse of compare. Sorts an array of versions + in descending order when passed to `Array.sort()`. +* `diff(v1, v2)`: Returns difference between two versions by the release type + (`major`, `premajor`, `minor`, `preminor`, `patch`, `prepatch`, or `prerelease`), + or null if the versions are the same. + +### Comparators + +* `intersects(comparator)`: Return true if the comparators intersect + +### Ranges + +* `validRange(range)`: Return the valid range or null if it's not valid +* `satisfies(version, range)`: Return true if the version satisfies the + range. +* `maxSatisfying(versions, range)`: Return the highest version in the list + that satisfies the range, or `null` if none of them do. +* `minSatisfying(versions, range)`: Return the lowest version in the list + that satisfies the range, or `null` if none of them do. +* `minVersion(range)`: Return the lowest version that can possibly match + the given range. +* `gtr(version, range)`: Return `true` if version is greater than all the + versions possible in the range. +* `ltr(version, range)`: Return `true` if version is less than all the + versions possible in the range. +* `outside(version, range, hilo)`: Return true if the version is outside + the bounds of the range in either the high or low direction. The + `hilo` argument must be either the string `'>'` or `'<'`. (This is + the function called by `gtr` and `ltr`.) +* `intersects(range)`: Return true if any of the ranges comparators intersect + +Note that, since ranges may be non-contiguous, a version might not be +greater than a range, less than a range, *or* satisfy a range! For +example, the range `1.2 <1.2.9 || >2.0.0` would have a hole from `1.2.9` +until `2.0.0`, so the version `1.2.10` would not be greater than the +range (because `2.0.1` satisfies, which is higher), nor less than the +range (since `1.2.8` satisfies, which is lower), and it also does not +satisfy the range. + +If you want to know if a version satisfies or does not satisfy a +range, use the `satisfies(version, range)` function. + +### Coercion + +* `coerce(version)`: Coerces a string to semver if possible + +This aims to provide a very forgiving translation of a non-semver string to +semver. It looks for the first digit in a string, and consumes all +remaining characters which satisfy at least a partial semver (e.g., `1`, +`1.2`, `1.2.3`) up to the max permitted length (256 characters). Longer +versions are simply truncated (`4.6.3.9.2-alpha2` becomes `4.6.3`). All +surrounding text is simply ignored (`v3.4 replaces v3.3.1` becomes +`3.4.0`). Only text which lacks digits will fail coercion (`version one` +is not valid). The maximum length for any semver component considered for +coercion is 16 characters; longer components will be ignored +(`10000000000000000.4.7.4` becomes `4.7.4`). The maximum value for any +semver component is `Number.MAX_SAFE_INTEGER || (2**53 - 1)`; higher value +components are invalid (`9999999999999999.4.7.4` is likely invalid). diff --git a/homework7/project_express/node_modules/semver/bin/semver b/homework7/project_express/node_modules/semver/bin/semver new file mode 100644 index 0000000..801e77f --- /dev/null +++ b/homework7/project_express/node_modules/semver/bin/semver @@ -0,0 +1,160 @@ +#!/usr/bin/env node +// Standalone semver comparison program. +// Exits successfully and prints matching version(s) if +// any supplied version is valid and passes all tests. + +var argv = process.argv.slice(2) + +var versions = [] + +var range = [] + +var inc = null + +var version = require('../package.json').version + +var loose = false + +var includePrerelease = false + +var coerce = false + +var identifier + +var semver = require('../semver') + +var reverse = false + +var options = {} + +main() + +function main () { + if (!argv.length) return help() + while (argv.length) { + var a = argv.shift() + var indexOfEqualSign = a.indexOf('=') + if (indexOfEqualSign !== -1) { + a = a.slice(0, indexOfEqualSign) + argv.unshift(a.slice(indexOfEqualSign + 1)) + } + switch (a) { + case '-rv': case '-rev': case '--rev': case '--reverse': + reverse = true + break + case '-l': case '--loose': + loose = true + break + case '-p': case '--include-prerelease': + includePrerelease = true + break + case '-v': case '--version': + versions.push(argv.shift()) + break + case '-i': case '--inc': case '--increment': + switch (argv[0]) { + case 'major': case 'minor': case 'patch': case 'prerelease': + case 'premajor': case 'preminor': case 'prepatch': + inc = argv.shift() + break + default: + inc = 'patch' + break + } + break + case '--preid': + identifier = argv.shift() + break + case '-r': case '--range': + range.push(argv.shift()) + break + case '-c': case '--coerce': + coerce = true + break + case '-h': case '--help': case '-?': + return help() + default: + versions.push(a) + break + } + } + + var options = { loose: loose, includePrerelease: includePrerelease } + + versions = versions.map(function (v) { + return coerce ? (semver.coerce(v) || { version: v }).version : v + }).filter(function (v) { + return semver.valid(v) + }) + if (!versions.length) return fail() + if (inc && (versions.length !== 1 || range.length)) { return failInc() } + + for (var i = 0, l = range.length; i < l; i++) { + versions = versions.filter(function (v) { + return semver.satisfies(v, range[i], options) + }) + if (!versions.length) return fail() + } + return success(versions) +} + +function failInc () { + console.error('--inc can only be used on a single version with no range') + fail() +} + +function fail () { process.exit(1) } + +function success () { + var compare = reverse ? 'rcompare' : 'compare' + versions.sort(function (a, b) { + return semver[compare](a, b, options) + }).map(function (v) { + return semver.clean(v, options) + }).map(function (v) { + return inc ? semver.inc(v, inc, options, identifier) : v + }).forEach(function (v, i, _) { console.log(v) }) +} + +function help () { + console.log(['SemVer ' + version, + '', + 'A JavaScript implementation of the https://semver.org/ specification', + 'Copyright Isaac Z. Schlueter', + '', + 'Usage: semver [options] [ [...]]', + 'Prints valid versions sorted by SemVer precedence', + '', + 'Options:', + '-r --range ', + ' Print versions that match the specified range.', + '', + '-i --increment []', + ' Increment a version by the specified level. Level can', + ' be one of: major, minor, patch, premajor, preminor,', + " prepatch, or prerelease. Default level is 'patch'.", + ' Only one version may be specified.', + '', + '--preid ', + ' Identifier to be used to prefix premajor, preminor,', + ' prepatch or prerelease version increments.', + '', + '-l --loose', + ' Interpret versions and ranges loosely', + '', + '-p --include-prerelease', + ' Always include prerelease versions in range matching', + '', + '-c --coerce', + ' Coerce a string into SemVer if possible', + ' (does not imply --loose)', + '', + 'Program exits successfully if any valid version satisfies', + 'all supplied ranges, and prints all satisfying versions.', + '', + 'If no satisfying versions are found, then exits failure.', + '', + 'Versions are printed in ascending order, so supplying', + 'multiple versions to the utility will just sort them.' + ].join('\n')) +} diff --git a/homework7/project_express/node_modules/semver/package.json b/homework7/project_express/node_modules/semver/package.json new file mode 100644 index 0000000..69d2db1 --- /dev/null +++ b/homework7/project_express/node_modules/semver/package.json @@ -0,0 +1,28 @@ +{ + "name": "semver", + "version": "5.7.1", + "description": "The semantic version parser used by npm.", + "main": "semver.js", + "scripts": { + "test": "tap", + "preversion": "npm test", + "postversion": "npm publish", + "postpublish": "git push origin --all; git push origin --tags" + }, + "devDependencies": { + "tap": "^13.0.0-rc.18" + }, + "license": "ISC", + "repository": "https://github.com/npm/node-semver", + "bin": { + "semver": "./bin/semver" + }, + "files": [ + "bin", + "range.bnf", + "semver.js" + ], + "tap": { + "check-coverage": true + } +} diff --git a/homework7/project_express/node_modules/semver/range.bnf b/homework7/project_express/node_modules/semver/range.bnf new file mode 100644 index 0000000..d4c6ae0 --- /dev/null +++ b/homework7/project_express/node_modules/semver/range.bnf @@ -0,0 +1,16 @@ +range-set ::= range ( logical-or range ) * +logical-or ::= ( ' ' ) * '||' ( ' ' ) * +range ::= hyphen | simple ( ' ' simple ) * | '' +hyphen ::= partial ' - ' partial +simple ::= primitive | partial | tilde | caret +primitive ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial +partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )? +xr ::= 'x' | 'X' | '*' | nr +nr ::= '0' | [1-9] ( [0-9] ) * +tilde ::= '~' partial +caret ::= '^' partial +qualifier ::= ( '-' pre )? ( '+' build )? +pre ::= parts +build ::= parts +parts ::= part ( '.' part ) * +part ::= nr | [-0-9A-Za-z]+ diff --git a/homework7/project_express/node_modules/semver/semver.js b/homework7/project_express/node_modules/semver/semver.js new file mode 100644 index 0000000..d315d5d --- /dev/null +++ b/homework7/project_express/node_modules/semver/semver.js @@ -0,0 +1,1483 @@ +exports = module.exports = SemVer + +var debug +/* istanbul ignore next */ +if (typeof process === 'object' && + process.env && + process.env.NODE_DEBUG && + /\bsemver\b/i.test(process.env.NODE_DEBUG)) { + debug = function () { + var args = Array.prototype.slice.call(arguments, 0) + args.unshift('SEMVER') + console.log.apply(console, args) + } +} else { + debug = function () {} +} + +// Note: this is the semver.org version of the spec that it implements +// Not necessarily the package version of this code. +exports.SEMVER_SPEC_VERSION = '2.0.0' + +var MAX_LENGTH = 256 +var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || + /* istanbul ignore next */ 9007199254740991 + +// Max safe segment length for coercion. +var MAX_SAFE_COMPONENT_LENGTH = 16 + +// The actual regexps go on exports.re +var re = exports.re = [] +var src = exports.src = [] +var R = 0 + +// The following Regular Expressions can be used for tokenizing, +// validating, and parsing SemVer version strings. + +// ## Numeric Identifier +// A single `0`, or a non-zero digit followed by zero or more digits. + +var NUMERICIDENTIFIER = R++ +src[NUMERICIDENTIFIER] = '0|[1-9]\\d*' +var NUMERICIDENTIFIERLOOSE = R++ +src[NUMERICIDENTIFIERLOOSE] = '[0-9]+' + +// ## Non-numeric Identifier +// Zero or more digits, followed by a letter or hyphen, and then zero or +// more letters, digits, or hyphens. + +var NONNUMERICIDENTIFIER = R++ +src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*' + +// ## Main Version +// Three dot-separated numeric identifiers. + +var MAINVERSION = R++ +src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + + '(' + src[NUMERICIDENTIFIER] + ')\\.' + + '(' + src[NUMERICIDENTIFIER] + ')' + +var MAINVERSIONLOOSE = R++ +src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + + '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + + '(' + src[NUMERICIDENTIFIERLOOSE] + ')' + +// ## Pre-release Version Identifier +// A numeric identifier, or a non-numeric identifier. + +var PRERELEASEIDENTIFIER = R++ +src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + + '|' + src[NONNUMERICIDENTIFIER] + ')' + +var PRERELEASEIDENTIFIERLOOSE = R++ +src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + + '|' + src[NONNUMERICIDENTIFIER] + ')' + +// ## Pre-release Version +// Hyphen, followed by one or more dot-separated pre-release version +// identifiers. + +var PRERELEASE = R++ +src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + + '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))' + +var PRERELEASELOOSE = R++ +src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + + '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))' + +// ## Build Metadata Identifier +// Any combination of digits, letters, or hyphens. + +var BUILDIDENTIFIER = R++ +src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+' + +// ## Build Metadata +// Plus sign, followed by one or more period-separated build metadata +// identifiers. + +var BUILD = R++ +src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + + '(?:\\.' + src[BUILDIDENTIFIER] + ')*))' + +// ## Full Version String +// A main version, followed optionally by a pre-release version and +// build metadata. + +// Note that the only major, minor, patch, and pre-release sections of +// the version string are capturing groups. The build metadata is not a +// capturing group, because it should not ever be used in version +// comparison. + +var FULL = R++ +var FULLPLAIN = 'v?' + src[MAINVERSION] + + src[PRERELEASE] + '?' + + src[BUILD] + '?' + +src[FULL] = '^' + FULLPLAIN + '$' + +// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. +// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty +// common in the npm registry. +var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + + src[PRERELEASELOOSE] + '?' + + src[BUILD] + '?' + +var LOOSE = R++ +src[LOOSE] = '^' + LOOSEPLAIN + '$' + +var GTLT = R++ +src[GTLT] = '((?:<|>)?=?)' + +// Something like "2.*" or "1.2.x". +// Note that "x.x" is a valid xRange identifer, meaning "any version" +// Only the first item is strictly required. +var XRANGEIDENTIFIERLOOSE = R++ +src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*' +var XRANGEIDENTIFIER = R++ +src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*' + +var XRANGEPLAIN = R++ +src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + + '(?:' + src[PRERELEASE] + ')?' + + src[BUILD] + '?' + + ')?)?' + +var XRANGEPLAINLOOSE = R++ +src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:' + src[PRERELEASELOOSE] + ')?' + + src[BUILD] + '?' + + ')?)?' + +var XRANGE = R++ +src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$' +var XRANGELOOSE = R++ +src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$' + +// Coercion. +// Extract anything that could conceivably be a part of a valid semver +var COERCE = R++ +src[COERCE] = '(?:^|[^\\d])' + + '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' + + '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + + '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + + '(?:$|[^\\d])' + +// Tilde ranges. +// Meaning is "reasonably at or greater than" +var LONETILDE = R++ +src[LONETILDE] = '(?:~>?)' + +var TILDETRIM = R++ +src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+' +re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g') +var tildeTrimReplace = '$1~' + +var TILDE = R++ +src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$' +var TILDELOOSE = R++ +src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$' + +// Caret ranges. +// Meaning is "at least and backwards compatible with" +var LONECARET = R++ +src[LONECARET] = '(?:\\^)' + +var CARETTRIM = R++ +src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+' +re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g') +var caretTrimReplace = '$1^' + +var CARET = R++ +src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$' +var CARETLOOSE = R++ +src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$' + +// A simple gt/lt/eq thing, or just "" to indicate "any version" +var COMPARATORLOOSE = R++ +src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$' +var COMPARATOR = R++ +src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$' + +// An expression to strip any whitespace between the gtlt and the thing +// it modifies, so that `> 1.2.3` ==> `>1.2.3` +var COMPARATORTRIM = R++ +src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + + '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')' + +// this one has to use the /g flag +re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g') +var comparatorTrimReplace = '$1$2$3' + +// Something like `1.2.3 - 1.2.4` +// Note that these all use the loose form, because they'll be +// checked against either the strict or loose comparator form +// later. +var HYPHENRANGE = R++ +src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + + '\\s+-\\s+' + + '(' + src[XRANGEPLAIN] + ')' + + '\\s*$' + +var HYPHENRANGELOOSE = R++ +src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + + '\\s+-\\s+' + + '(' + src[XRANGEPLAINLOOSE] + ')' + + '\\s*$' + +// Star ranges basically just allow anything at all. +var STAR = R++ +src[STAR] = '(<|>)?=?\\s*\\*' + +// Compile to actual regexp objects. +// All are flag-free, unless they were created above with a flag. +for (var i = 0; i < R; i++) { + debug(i, src[i]) + if (!re[i]) { + re[i] = new RegExp(src[i]) + } +} + +exports.parse = parse +function parse (version, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (version instanceof SemVer) { + return version + } + + if (typeof version !== 'string') { + return null + } + + if (version.length > MAX_LENGTH) { + return null + } + + var r = options.loose ? re[LOOSE] : re[FULL] + if (!r.test(version)) { + return null + } + + try { + return new SemVer(version, options) + } catch (er) { + return null + } +} + +exports.valid = valid +function valid (version, options) { + var v = parse(version, options) + return v ? v.version : null +} + +exports.clean = clean +function clean (version, options) { + var s = parse(version.trim().replace(/^[=v]+/, ''), options) + return s ? s.version : null +} + +exports.SemVer = SemVer + +function SemVer (version, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + if (version instanceof SemVer) { + if (version.loose === options.loose) { + return version + } else { + version = version.version + } + } else if (typeof version !== 'string') { + throw new TypeError('Invalid Version: ' + version) + } + + if (version.length > MAX_LENGTH) { + throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') + } + + if (!(this instanceof SemVer)) { + return new SemVer(version, options) + } + + debug('SemVer', version, options) + this.options = options + this.loose = !!options.loose + + var m = version.trim().match(options.loose ? re[LOOSE] : re[FULL]) + + if (!m) { + throw new TypeError('Invalid Version: ' + version) + } + + this.raw = version + + // these are actually numbers + this.major = +m[1] + this.minor = +m[2] + this.patch = +m[3] + + if (this.major > MAX_SAFE_INTEGER || this.major < 0) { + throw new TypeError('Invalid major version') + } + + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { + throw new TypeError('Invalid minor version') + } + + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { + throw new TypeError('Invalid patch version') + } + + // numberify any prerelease numeric ids + if (!m[4]) { + this.prerelease = [] + } else { + this.prerelease = m[4].split('.').map(function (id) { + if (/^[0-9]+$/.test(id)) { + var num = +id + if (num >= 0 && num < MAX_SAFE_INTEGER) { + return num + } + } + return id + }) + } + + this.build = m[5] ? m[5].split('.') : [] + this.format() +} + +SemVer.prototype.format = function () { + this.version = this.major + '.' + this.minor + '.' + this.patch + if (this.prerelease.length) { + this.version += '-' + this.prerelease.join('.') + } + return this.version +} + +SemVer.prototype.toString = function () { + return this.version +} + +SemVer.prototype.compare = function (other) { + debug('SemVer.compare', this.version, this.options, other) + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + return this.compareMain(other) || this.comparePre(other) +} + +SemVer.prototype.compareMain = function (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + return compareIdentifiers(this.major, other.major) || + compareIdentifiers(this.minor, other.minor) || + compareIdentifiers(this.patch, other.patch) +} + +SemVer.prototype.comparePre = function (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + // NOT having a prerelease is > having one + if (this.prerelease.length && !other.prerelease.length) { + return -1 + } else if (!this.prerelease.length && other.prerelease.length) { + return 1 + } else if (!this.prerelease.length && !other.prerelease.length) { + return 0 + } + + var i = 0 + do { + var a = this.prerelease[i] + var b = other.prerelease[i] + debug('prerelease compare', i, a, b) + if (a === undefined && b === undefined) { + return 0 + } else if (b === undefined) { + return 1 + } else if (a === undefined) { + return -1 + } else if (a === b) { + continue + } else { + return compareIdentifiers(a, b) + } + } while (++i) +} + +// preminor will bump the version up to the next minor release, and immediately +// down to pre-release. premajor and prepatch work the same way. +SemVer.prototype.inc = function (release, identifier) { + switch (release) { + case 'premajor': + this.prerelease.length = 0 + this.patch = 0 + this.minor = 0 + this.major++ + this.inc('pre', identifier) + break + case 'preminor': + this.prerelease.length = 0 + this.patch = 0 + this.minor++ + this.inc('pre', identifier) + break + case 'prepatch': + // If this is already a prerelease, it will bump to the next version + // drop any prereleases that might already exist, since they are not + // relevant at this point. + this.prerelease.length = 0 + this.inc('patch', identifier) + this.inc('pre', identifier) + break + // If the input is a non-prerelease version, this acts the same as + // prepatch. + case 'prerelease': + if (this.prerelease.length === 0) { + this.inc('patch', identifier) + } + this.inc('pre', identifier) + break + + case 'major': + // If this is a pre-major version, bump up to the same major version. + // Otherwise increment major. + // 1.0.0-5 bumps to 1.0.0 + // 1.1.0 bumps to 2.0.0 + if (this.minor !== 0 || + this.patch !== 0 || + this.prerelease.length === 0) { + this.major++ + } + this.minor = 0 + this.patch = 0 + this.prerelease = [] + break + case 'minor': + // If this is a pre-minor version, bump up to the same minor version. + // Otherwise increment minor. + // 1.2.0-5 bumps to 1.2.0 + // 1.2.1 bumps to 1.3.0 + if (this.patch !== 0 || this.prerelease.length === 0) { + this.minor++ + } + this.patch = 0 + this.prerelease = [] + break + case 'patch': + // If this is not a pre-release version, it will increment the patch. + // If it is a pre-release it will bump up to the same patch version. + // 1.2.0-5 patches to 1.2.0 + // 1.2.0 patches to 1.2.1 + if (this.prerelease.length === 0) { + this.patch++ + } + this.prerelease = [] + break + // This probably shouldn't be used publicly. + // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. + case 'pre': + if (this.prerelease.length === 0) { + this.prerelease = [0] + } else { + var i = this.prerelease.length + while (--i >= 0) { + if (typeof this.prerelease[i] === 'number') { + this.prerelease[i]++ + i = -2 + } + } + if (i === -1) { + // didn't increment anything + this.prerelease.push(0) + } + } + if (identifier) { + // 1.2.0-beta.1 bumps to 1.2.0-beta.2, + // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 + if (this.prerelease[0] === identifier) { + if (isNaN(this.prerelease[1])) { + this.prerelease = [identifier, 0] + } + } else { + this.prerelease = [identifier, 0] + } + } + break + + default: + throw new Error('invalid increment argument: ' + release) + } + this.format() + this.raw = this.version + return this +} + +exports.inc = inc +function inc (version, release, loose, identifier) { + if (typeof (loose) === 'string') { + identifier = loose + loose = undefined + } + + try { + return new SemVer(version, loose).inc(release, identifier).version + } catch (er) { + return null + } +} + +exports.diff = diff +function diff (version1, version2) { + if (eq(version1, version2)) { + return null + } else { + var v1 = parse(version1) + var v2 = parse(version2) + var prefix = '' + if (v1.prerelease.length || v2.prerelease.length) { + prefix = 'pre' + var defaultResult = 'prerelease' + } + for (var key in v1) { + if (key === 'major' || key === 'minor' || key === 'patch') { + if (v1[key] !== v2[key]) { + return prefix + key + } + } + } + return defaultResult // may be undefined + } +} + +exports.compareIdentifiers = compareIdentifiers + +var numeric = /^[0-9]+$/ +function compareIdentifiers (a, b) { + var anum = numeric.test(a) + var bnum = numeric.test(b) + + if (anum && bnum) { + a = +a + b = +b + } + + return a === b ? 0 + : (anum && !bnum) ? -1 + : (bnum && !anum) ? 1 + : a < b ? -1 + : 1 +} + +exports.rcompareIdentifiers = rcompareIdentifiers +function rcompareIdentifiers (a, b) { + return compareIdentifiers(b, a) +} + +exports.major = major +function major (a, loose) { + return new SemVer(a, loose).major +} + +exports.minor = minor +function minor (a, loose) { + return new SemVer(a, loose).minor +} + +exports.patch = patch +function patch (a, loose) { + return new SemVer(a, loose).patch +} + +exports.compare = compare +function compare (a, b, loose) { + return new SemVer(a, loose).compare(new SemVer(b, loose)) +} + +exports.compareLoose = compareLoose +function compareLoose (a, b) { + return compare(a, b, true) +} + +exports.rcompare = rcompare +function rcompare (a, b, loose) { + return compare(b, a, loose) +} + +exports.sort = sort +function sort (list, loose) { + return list.sort(function (a, b) { + return exports.compare(a, b, loose) + }) +} + +exports.rsort = rsort +function rsort (list, loose) { + return list.sort(function (a, b) { + return exports.rcompare(a, b, loose) + }) +} + +exports.gt = gt +function gt (a, b, loose) { + return compare(a, b, loose) > 0 +} + +exports.lt = lt +function lt (a, b, loose) { + return compare(a, b, loose) < 0 +} + +exports.eq = eq +function eq (a, b, loose) { + return compare(a, b, loose) === 0 +} + +exports.neq = neq +function neq (a, b, loose) { + return compare(a, b, loose) !== 0 +} + +exports.gte = gte +function gte (a, b, loose) { + return compare(a, b, loose) >= 0 +} + +exports.lte = lte +function lte (a, b, loose) { + return compare(a, b, loose) <= 0 +} + +exports.cmp = cmp +function cmp (a, op, b, loose) { + switch (op) { + case '===': + if (typeof a === 'object') + a = a.version + if (typeof b === 'object') + b = b.version + return a === b + + case '!==': + if (typeof a === 'object') + a = a.version + if (typeof b === 'object') + b = b.version + return a !== b + + case '': + case '=': + case '==': + return eq(a, b, loose) + + case '!=': + return neq(a, b, loose) + + case '>': + return gt(a, b, loose) + + case '>=': + return gte(a, b, loose) + + case '<': + return lt(a, b, loose) + + case '<=': + return lte(a, b, loose) + + default: + throw new TypeError('Invalid operator: ' + op) + } +} + +exports.Comparator = Comparator +function Comparator (comp, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (comp instanceof Comparator) { + if (comp.loose === !!options.loose) { + return comp + } else { + comp = comp.value + } + } + + if (!(this instanceof Comparator)) { + return new Comparator(comp, options) + } + + debug('comparator', comp, options) + this.options = options + this.loose = !!options.loose + this.parse(comp) + + if (this.semver === ANY) { + this.value = '' + } else { + this.value = this.operator + this.semver.version + } + + debug('comp', this) +} + +var ANY = {} +Comparator.prototype.parse = function (comp) { + var r = this.options.loose ? re[COMPARATORLOOSE] : re[COMPARATOR] + var m = comp.match(r) + + if (!m) { + throw new TypeError('Invalid comparator: ' + comp) + } + + this.operator = m[1] + if (this.operator === '=') { + this.operator = '' + } + + // if it literally is just '>' or '' then allow anything. + if (!m[2]) { + this.semver = ANY + } else { + this.semver = new SemVer(m[2], this.options.loose) + } +} + +Comparator.prototype.toString = function () { + return this.value +} + +Comparator.prototype.test = function (version) { + debug('Comparator.test', version, this.options.loose) + + if (this.semver === ANY) { + return true + } + + if (typeof version === 'string') { + version = new SemVer(version, this.options) + } + + return cmp(version, this.operator, this.semver, this.options) +} + +Comparator.prototype.intersects = function (comp, options) { + if (!(comp instanceof Comparator)) { + throw new TypeError('a Comparator is required') + } + + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + var rangeTmp + + if (this.operator === '') { + rangeTmp = new Range(comp.value, options) + return satisfies(this.value, rangeTmp, options) + } else if (comp.operator === '') { + rangeTmp = new Range(this.value, options) + return satisfies(comp.semver, rangeTmp, options) + } + + var sameDirectionIncreasing = + (this.operator === '>=' || this.operator === '>') && + (comp.operator === '>=' || comp.operator === '>') + var sameDirectionDecreasing = + (this.operator === '<=' || this.operator === '<') && + (comp.operator === '<=' || comp.operator === '<') + var sameSemVer = this.semver.version === comp.semver.version + var differentDirectionsInclusive = + (this.operator === '>=' || this.operator === '<=') && + (comp.operator === '>=' || comp.operator === '<=') + var oppositeDirectionsLessThan = + cmp(this.semver, '<', comp.semver, options) && + ((this.operator === '>=' || this.operator === '>') && + (comp.operator === '<=' || comp.operator === '<')) + var oppositeDirectionsGreaterThan = + cmp(this.semver, '>', comp.semver, options) && + ((this.operator === '<=' || this.operator === '<') && + (comp.operator === '>=' || comp.operator === '>')) + + return sameDirectionIncreasing || sameDirectionDecreasing || + (sameSemVer && differentDirectionsInclusive) || + oppositeDirectionsLessThan || oppositeDirectionsGreaterThan +} + +exports.Range = Range +function Range (range, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (range instanceof Range) { + if (range.loose === !!options.loose && + range.includePrerelease === !!options.includePrerelease) { + return range + } else { + return new Range(range.raw, options) + } + } + + if (range instanceof Comparator) { + return new Range(range.value, options) + } + + if (!(this instanceof Range)) { + return new Range(range, options) + } + + this.options = options + this.loose = !!options.loose + this.includePrerelease = !!options.includePrerelease + + // First, split based on boolean or || + this.raw = range + this.set = range.split(/\s*\|\|\s*/).map(function (range) { + return this.parseRange(range.trim()) + }, this).filter(function (c) { + // throw out any that are not relevant for whatever reason + return c.length + }) + + if (!this.set.length) { + throw new TypeError('Invalid SemVer Range: ' + range) + } + + this.format() +} + +Range.prototype.format = function () { + this.range = this.set.map(function (comps) { + return comps.join(' ').trim() + }).join('||').trim() + return this.range +} + +Range.prototype.toString = function () { + return this.range +} + +Range.prototype.parseRange = function (range) { + var loose = this.options.loose + range = range.trim() + // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` + var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE] + range = range.replace(hr, hyphenReplace) + debug('hyphen replace', range) + // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` + range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace) + debug('comparator trim', range, re[COMPARATORTRIM]) + + // `~ 1.2.3` => `~1.2.3` + range = range.replace(re[TILDETRIM], tildeTrimReplace) + + // `^ 1.2.3` => `^1.2.3` + range = range.replace(re[CARETTRIM], caretTrimReplace) + + // normalize spaces + range = range.split(/\s+/).join(' ') + + // At this point, the range is completely trimmed and + // ready to be split into comparators. + + var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR] + var set = range.split(' ').map(function (comp) { + return parseComparator(comp, this.options) + }, this).join(' ').split(/\s+/) + if (this.options.loose) { + // in loose mode, throw out any that are not valid comparators + set = set.filter(function (comp) { + return !!comp.match(compRe) + }) + } + set = set.map(function (comp) { + return new Comparator(comp, this.options) + }, this) + + return set +} + +Range.prototype.intersects = function (range, options) { + if (!(range instanceof Range)) { + throw new TypeError('a Range is required') + } + + return this.set.some(function (thisComparators) { + return thisComparators.every(function (thisComparator) { + return range.set.some(function (rangeComparators) { + return rangeComparators.every(function (rangeComparator) { + return thisComparator.intersects(rangeComparator, options) + }) + }) + }) + }) +} + +// Mostly just for testing and legacy API reasons +exports.toComparators = toComparators +function toComparators (range, options) { + return new Range(range, options).set.map(function (comp) { + return comp.map(function (c) { + return c.value + }).join(' ').trim().split(' ') + }) +} + +// comprised of xranges, tildes, stars, and gtlt's at this point. +// already replaced the hyphen ranges +// turn into a set of JUST comparators. +function parseComparator (comp, options) { + debug('comp', comp, options) + comp = replaceCarets(comp, options) + debug('caret', comp) + comp = replaceTildes(comp, options) + debug('tildes', comp) + comp = replaceXRanges(comp, options) + debug('xrange', comp) + comp = replaceStars(comp, options) + debug('stars', comp) + return comp +} + +function isX (id) { + return !id || id.toLowerCase() === 'x' || id === '*' +} + +// ~, ~> --> * (any, kinda silly) +// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 +// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 +// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 +// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 +// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 +function replaceTildes (comp, options) { + return comp.trim().split(/\s+/).map(function (comp) { + return replaceTilde(comp, options) + }).join(' ') +} + +function replaceTilde (comp, options) { + var r = options.loose ? re[TILDELOOSE] : re[TILDE] + return comp.replace(r, function (_, M, m, p, pr) { + debug('tilde', comp, _, M, m, p, pr) + var ret + + if (isX(M)) { + ret = '' + } else if (isX(m)) { + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' + } else if (isX(p)) { + // ~1.2 == >=1.2.0 <1.3.0 + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' + } else if (pr) { + debug('replaceTilde pr', pr) + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + M + '.' + (+m + 1) + '.0' + } else { + // ~1.2.3 == >=1.2.3 <1.3.0 + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + (+m + 1) + '.0' + } + + debug('tilde return', ret) + return ret + }) +} + +// ^ --> * (any, kinda silly) +// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 +// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 +// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 +// ^1.2.3 --> >=1.2.3 <2.0.0 +// ^1.2.0 --> >=1.2.0 <2.0.0 +function replaceCarets (comp, options) { + return comp.trim().split(/\s+/).map(function (comp) { + return replaceCaret(comp, options) + }).join(' ') +} + +function replaceCaret (comp, options) { + debug('caret', comp, options) + var r = options.loose ? re[CARETLOOSE] : re[CARET] + return comp.replace(r, function (_, M, m, p, pr) { + debug('caret', comp, _, M, m, p, pr) + var ret + + if (isX(M)) { + ret = '' + } else if (isX(m)) { + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' + } else if (isX(p)) { + if (M === '0') { + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' + } else { + ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0' + } + } else if (pr) { + debug('replaceCaret pr', pr) + if (M === '0') { + if (m === '0') { + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + M + '.' + m + '.' + (+p + 1) + } else { + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + M + '.' + (+m + 1) + '.0' + } + } else { + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + (+M + 1) + '.0.0' + } + } else { + debug('no pr') + if (M === '0') { + if (m === '0') { + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + m + '.' + (+p + 1) + } else { + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + (+m + 1) + '.0' + } + } else { + ret = '>=' + M + '.' + m + '.' + p + + ' <' + (+M + 1) + '.0.0' + } + } + + debug('caret return', ret) + return ret + }) +} + +function replaceXRanges (comp, options) { + debug('replaceXRanges', comp, options) + return comp.split(/\s+/).map(function (comp) { + return replaceXRange(comp, options) + }).join(' ') +} + +function replaceXRange (comp, options) { + comp = comp.trim() + var r = options.loose ? re[XRANGELOOSE] : re[XRANGE] + return comp.replace(r, function (ret, gtlt, M, m, p, pr) { + debug('xRange', comp, ret, gtlt, M, m, p, pr) + var xM = isX(M) + var xm = xM || isX(m) + var xp = xm || isX(p) + var anyX = xp + + if (gtlt === '=' && anyX) { + gtlt = '' + } + + if (xM) { + if (gtlt === '>' || gtlt === '<') { + // nothing is allowed + ret = '<0.0.0' + } else { + // nothing is forbidden + ret = '*' + } + } else if (gtlt && anyX) { + // we know patch is an x, because we have any x at all. + // replace X with 0 + if (xm) { + m = 0 + } + p = 0 + + if (gtlt === '>') { + // >1 => >=2.0.0 + // >1.2 => >=1.3.0 + // >1.2.3 => >= 1.2.4 + gtlt = '>=' + if (xm) { + M = +M + 1 + m = 0 + p = 0 + } else { + m = +m + 1 + p = 0 + } + } else if (gtlt === '<=') { + // <=0.7.x is actually <0.8.0, since any 0.7.x should + // pass. Similarly, <=7.x is actually <8.0.0, etc. + gtlt = '<' + if (xm) { + M = +M + 1 + } else { + m = +m + 1 + } + } + + ret = gtlt + M + '.' + m + '.' + p + } else if (xm) { + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' + } else if (xp) { + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' + } + + debug('xRange return', ret) + + return ret + }) +} + +// Because * is AND-ed with everything else in the comparator, +// and '' means "any version", just remove the *s entirely. +function replaceStars (comp, options) { + debug('replaceStars', comp, options) + // Looseness is ignored here. star is always as loose as it gets! + return comp.trim().replace(re[STAR], '') +} + +// This function is passed to string.replace(re[HYPHENRANGE]) +// M, m, patch, prerelease, build +// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 +// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do +// 1.2 - 3.4 => >=1.2.0 <3.5.0 +function hyphenReplace ($0, + from, fM, fm, fp, fpr, fb, + to, tM, tm, tp, tpr, tb) { + if (isX(fM)) { + from = '' + } else if (isX(fm)) { + from = '>=' + fM + '.0.0' + } else if (isX(fp)) { + from = '>=' + fM + '.' + fm + '.0' + } else { + from = '>=' + from + } + + if (isX(tM)) { + to = '' + } else if (isX(tm)) { + to = '<' + (+tM + 1) + '.0.0' + } else if (isX(tp)) { + to = '<' + tM + '.' + (+tm + 1) + '.0' + } else if (tpr) { + to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr + } else { + to = '<=' + to + } + + return (from + ' ' + to).trim() +} + +// if ANY of the sets match ALL of its comparators, then pass +Range.prototype.test = function (version) { + if (!version) { + return false + } + + if (typeof version === 'string') { + version = new SemVer(version, this.options) + } + + for (var i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version, this.options)) { + return true + } + } + return false +} + +function testSet (set, version, options) { + for (var i = 0; i < set.length; i++) { + if (!set[i].test(version)) { + return false + } + } + + if (version.prerelease.length && !options.includePrerelease) { + // Find the set of versions that are allowed to have prereleases + // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 + // That should allow `1.2.3-pr.2` to pass. + // However, `1.2.4-alpha.notready` should NOT be allowed, + // even though it's within the range set by the comparators. + for (i = 0; i < set.length; i++) { + debug(set[i].semver) + if (set[i].semver === ANY) { + continue + } + + if (set[i].semver.prerelease.length > 0) { + var allowed = set[i].semver + if (allowed.major === version.major && + allowed.minor === version.minor && + allowed.patch === version.patch) { + return true + } + } + } + + // Version has a -pre, but it's not one of the ones we like. + return false + } + + return true +} + +exports.satisfies = satisfies +function satisfies (version, range, options) { + try { + range = new Range(range, options) + } catch (er) { + return false + } + return range.test(version) +} + +exports.maxSatisfying = maxSatisfying +function maxSatisfying (versions, range, options) { + var max = null + var maxSV = null + try { + var rangeObj = new Range(range, options) + } catch (er) { + return null + } + versions.forEach(function (v) { + if (rangeObj.test(v)) { + // satisfies(v, range, options) + if (!max || maxSV.compare(v) === -1) { + // compare(max, v, true) + max = v + maxSV = new SemVer(max, options) + } + } + }) + return max +} + +exports.minSatisfying = minSatisfying +function minSatisfying (versions, range, options) { + var min = null + var minSV = null + try { + var rangeObj = new Range(range, options) + } catch (er) { + return null + } + versions.forEach(function (v) { + if (rangeObj.test(v)) { + // satisfies(v, range, options) + if (!min || minSV.compare(v) === 1) { + // compare(min, v, true) + min = v + minSV = new SemVer(min, options) + } + } + }) + return min +} + +exports.minVersion = minVersion +function minVersion (range, loose) { + range = new Range(range, loose) + + var minver = new SemVer('0.0.0') + if (range.test(minver)) { + return minver + } + + minver = new SemVer('0.0.0-0') + if (range.test(minver)) { + return minver + } + + minver = null + for (var i = 0; i < range.set.length; ++i) { + var comparators = range.set[i] + + comparators.forEach(function (comparator) { + // Clone to avoid manipulating the comparator's semver object. + var compver = new SemVer(comparator.semver.version) + switch (comparator.operator) { + case '>': + if (compver.prerelease.length === 0) { + compver.patch++ + } else { + compver.prerelease.push(0) + } + compver.raw = compver.format() + /* fallthrough */ + case '': + case '>=': + if (!minver || gt(minver, compver)) { + minver = compver + } + break + case '<': + case '<=': + /* Ignore maximum versions */ + break + /* istanbul ignore next */ + default: + throw new Error('Unexpected operation: ' + comparator.operator) + } + }) + } + + if (minver && range.test(minver)) { + return minver + } + + return null +} + +exports.validRange = validRange +function validRange (range, options) { + try { + // Return '*' instead of '' so that truthiness works. + // This will throw if it's invalid anyway + return new Range(range, options).range || '*' + } catch (er) { + return null + } +} + +// Determine if version is less than all the versions possible in the range +exports.ltr = ltr +function ltr (version, range, options) { + return outside(version, range, '<', options) +} + +// Determine if version is greater than all the versions possible in the range. +exports.gtr = gtr +function gtr (version, range, options) { + return outside(version, range, '>', options) +} + +exports.outside = outside +function outside (version, range, hilo, options) { + version = new SemVer(version, options) + range = new Range(range, options) + + var gtfn, ltefn, ltfn, comp, ecomp + switch (hilo) { + case '>': + gtfn = gt + ltefn = lte + ltfn = lt + comp = '>' + ecomp = '>=' + break + case '<': + gtfn = lt + ltefn = gte + ltfn = gt + comp = '<' + ecomp = '<=' + break + default: + throw new TypeError('Must provide a hilo val of "<" or ">"') + } + + // If it satisifes the range it is not outside + if (satisfies(version, range, options)) { + return false + } + + // From now on, variable terms are as if we're in "gtr" mode. + // but note that everything is flipped for the "ltr" function. + + for (var i = 0; i < range.set.length; ++i) { + var comparators = range.set[i] + + var high = null + var low = null + + comparators.forEach(function (comparator) { + if (comparator.semver === ANY) { + comparator = new Comparator('>=0.0.0') + } + high = high || comparator + low = low || comparator + if (gtfn(comparator.semver, high.semver, options)) { + high = comparator + } else if (ltfn(comparator.semver, low.semver, options)) { + low = comparator + } + }) + + // If the edge version comparator has a operator then our version + // isn't outside it + if (high.operator === comp || high.operator === ecomp) { + return false + } + + // If the lowest version comparator has an operator and our version + // is less than it then it isn't higher than the range + if ((!low.operator || low.operator === comp) && + ltefn(version, low.semver)) { + return false + } else if (low.operator === ecomp && ltfn(version, low.semver)) { + return false + } + } + return true +} + +exports.prerelease = prerelease +function prerelease (version, options) { + var parsed = parse(version, options) + return (parsed && parsed.prerelease.length) ? parsed.prerelease : null +} + +exports.intersects = intersects +function intersects (r1, r2, options) { + r1 = new Range(r1, options) + r2 = new Range(r2, options) + return r1.intersects(r2) +} + +exports.coerce = coerce +function coerce (version) { + if (version instanceof SemVer) { + return version + } + + if (typeof version !== 'string') { + return null + } + + var match = version.match(re[COERCE]) + + if (match == null) { + return null + } + + return parse(match[1] + + '.' + (match[2] || '0') + + '.' + (match[3] || '0')) +} diff --git a/homework7/project_express/node_modules/send/HISTORY.md b/homework7/project_express/node_modules/send/HISTORY.md new file mode 100644 index 0000000..d14ac06 --- /dev/null +++ b/homework7/project_express/node_modules/send/HISTORY.md @@ -0,0 +1,496 @@ +0.17.1 / 2019-05-10 +=================== + + * Set stricter CSP header in redirect & error responses + * deps: range-parser@~1.2.1 + +0.17.0 / 2019-05-03 +=================== + + * deps: http-errors@~1.7.2 + - Set constructor name when possible + - Use `toidentifier` module to make class names + - deps: depd@~1.1.2 + - deps: setprototypeof@1.1.1 + - deps: statuses@'>= 1.5.0 < 2' + * deps: mime@1.6.0 + - Add extensions for JPEG-2000 images + - Add new `font/*` types from IANA + - Add WASM mapping + - Update `.bdoc` to `application/bdoc` + - Update `.bmp` to `image/bmp` + - Update `.m4a` to `audio/mp4` + - Update `.rtf` to `application/rtf` + - Update `.wav` to `audio/wav` + - Update `.xml` to `application/xml` + - Update generic extensions to `application/octet-stream`: + `.deb`, `.dll`, `.dmg`, `.exe`, `.iso`, `.msi` + - Use mime-score module to resolve extension conflicts + * deps: ms@2.1.1 + - Add `week`/`w` support + - Fix negative number handling + * deps: statuses@~1.5.0 + * perf: remove redundant `path.normalize` call + +0.16.2 / 2018-02-07 +=================== + + * Fix incorrect end tag in default error & redirects + * deps: depd@~1.1.2 + - perf: remove argument reassignment + * deps: encodeurl@~1.0.2 + - Fix encoding `%` as last character + * deps: statuses@~1.4.0 + +0.16.1 / 2017-09-29 +=================== + + * Fix regression in edge-case behavior for empty `path` + +0.16.0 / 2017-09-27 +=================== + + * Add `immutable` option + * Fix missing `` in default error & redirects + * Use instance methods on steam to check for listeners + * deps: mime@1.4.1 + - Add 70 new types for file extensions + - Set charset as "UTF-8" for .js and .json + * perf: improve path validation speed + +0.15.6 / 2017-09-22 +=================== + + * deps: debug@2.6.9 + * perf: improve `If-Match` token parsing + +0.15.5 / 2017-09-20 +=================== + + * deps: etag@~1.8.1 + - perf: replace regular expression with substring + * deps: fresh@0.5.2 + - Fix handling of modified headers with invalid dates + - perf: improve ETag match loop + - perf: improve `If-None-Match` token parsing + +0.15.4 / 2017-08-05 +=================== + + * deps: debug@2.6.8 + * deps: depd@~1.1.1 + - Remove unnecessary `Buffer` loading + * deps: http-errors@~1.6.2 + - deps: depd@1.1.1 + +0.15.3 / 2017-05-16 +=================== + + * deps: debug@2.6.7 + - deps: ms@2.0.0 + * deps: ms@2.0.0 + +0.15.2 / 2017-04-26 +=================== + + * deps: debug@2.6.4 + - Fix `DEBUG_MAX_ARRAY_LENGTH` + - deps: ms@0.7.3 + * deps: ms@1.0.0 + +0.15.1 / 2017-03-04 +=================== + + * Fix issue when `Date.parse` does not return `NaN` on invalid date + * Fix strict violation in broken environments + +0.15.0 / 2017-02-25 +=================== + + * Support `If-Match` and `If-Unmodified-Since` headers + * Add `res` and `path` arguments to `directory` event + * Remove usage of `res._headers` private field + - Improves compatibility with Node.js 8 nightly + * Send complete HTML document in redirect & error responses + * Set default CSP header in redirect & error responses + * Use `res.getHeaderNames()` when available + * Use `res.headersSent` when available + * deps: debug@2.6.1 + - Allow colors in workers + - Deprecated `DEBUG_FD` environment variable set to `3` or higher + - Fix error when running under React Native + - Use same color for same namespace + - deps: ms@0.7.2 + * deps: etag@~1.8.0 + * deps: fresh@0.5.0 + - Fix false detection of `no-cache` request directive + - Fix incorrect result when `If-None-Match` has both `*` and ETags + - Fix weak `ETag` matching to match spec + - perf: delay reading header values until needed + - perf: enable strict mode + - perf: hoist regular expressions + - perf: remove duplicate conditional + - perf: remove unnecessary boolean coercions + - perf: skip checking modified time if ETag check failed + - perf: skip parsing `If-None-Match` when no `ETag` header + - perf: use `Date.parse` instead of `new Date` + * deps: http-errors@~1.6.1 + - Make `message` property enumerable for `HttpError`s + - deps: setprototypeof@1.0.3 + +0.14.2 / 2017-01-23 +=================== + + * deps: http-errors@~1.5.1 + - deps: inherits@2.0.3 + - deps: setprototypeof@1.0.2 + - deps: statuses@'>= 1.3.1 < 2' + * deps: ms@0.7.2 + * deps: statuses@~1.3.1 + +0.14.1 / 2016-06-09 +=================== + + * Fix redirect error when `path` contains raw non-URL characters + * Fix redirect when `path` starts with multiple forward slashes + +0.14.0 / 2016-06-06 +=================== + + * Add `acceptRanges` option + * Add `cacheControl` option + * Attempt to combine multiple ranges into single range + * Correctly inherit from `Stream` class + * Fix `Content-Range` header in 416 responses when using `start`/`end` options + * Fix `Content-Range` header missing from default 416 responses + * Ignore non-byte `Range` headers + * deps: http-errors@~1.5.0 + - Add `HttpError` export, for `err instanceof createError.HttpError` + - Support new code `421 Misdirected Request` + - Use `setprototypeof` module to replace `__proto__` setting + - deps: inherits@2.0.1 + - deps: statuses@'>= 1.3.0 < 2' + - perf: enable strict mode + * deps: range-parser@~1.2.0 + - Fix incorrectly returning -1 when there is at least one valid range + - perf: remove internal function + * deps: statuses@~1.3.0 + - Add `421 Misdirected Request` + - perf: enable strict mode + * perf: remove argument reassignment + +0.13.2 / 2016-03-05 +=================== + + * Fix invalid `Content-Type` header when `send.mime.default_type` unset + +0.13.1 / 2016-01-16 +=================== + + * deps: depd@~1.1.0 + - Support web browser loading + - perf: enable strict mode + * deps: destroy@~1.0.4 + - perf: enable strict mode + * deps: escape-html@~1.0.3 + - perf: enable strict mode + - perf: optimize string replacement + - perf: use faster string coercion + * deps: range-parser@~1.0.3 + - perf: enable strict mode + +0.13.0 / 2015-06-16 +=================== + + * Allow Node.js HTTP server to set `Date` response header + * Fix incorrectly removing `Content-Location` on 304 response + * Improve the default redirect response headers + * Send appropriate headers on default error response + * Use `http-errors` for standard emitted errors + * Use `statuses` instead of `http` module for status messages + * deps: escape-html@1.0.2 + * deps: etag@~1.7.0 + - Improve stat performance by removing hashing + * deps: fresh@0.3.0 + - Add weak `ETag` matching support + * deps: on-finished@~2.3.0 + - Add defined behavior for HTTP `CONNECT` requests + - Add defined behavior for HTTP `Upgrade` requests + - deps: ee-first@1.1.1 + * perf: enable strict mode + * perf: remove unnecessary array allocations + +0.12.3 / 2015-05-13 +=================== + + * deps: debug@~2.2.0 + - deps: ms@0.7.1 + * deps: depd@~1.0.1 + * deps: etag@~1.6.0 + - Improve support for JXcore + - Support "fake" stats objects in environments without `fs` + * deps: ms@0.7.1 + - Prevent extraordinarily long inputs + * deps: on-finished@~2.2.1 + +0.12.2 / 2015-03-13 +=================== + + * Throw errors early for invalid `extensions` or `index` options + * deps: debug@~2.1.3 + - Fix high intensity foreground color for bold + - deps: ms@0.7.0 + +0.12.1 / 2015-02-17 +=================== + + * Fix regression sending zero-length files + +0.12.0 / 2015-02-16 +=================== + + * Always read the stat size from the file + * Fix mutating passed-in `options` + * deps: mime@1.3.4 + +0.11.1 / 2015-01-20 +=================== + + * Fix `root` path disclosure + +0.11.0 / 2015-01-05 +=================== + + * deps: debug@~2.1.1 + * deps: etag@~1.5.1 + - deps: crc@3.2.1 + * deps: ms@0.7.0 + - Add `milliseconds` + - Add `msecs` + - Add `secs` + - Add `mins` + - Add `hrs` + - Add `yrs` + * deps: on-finished@~2.2.0 + +0.10.1 / 2014-10-22 +=================== + + * deps: on-finished@~2.1.1 + - Fix handling of pipelined requests + +0.10.0 / 2014-10-15 +=================== + + * deps: debug@~2.1.0 + - Implement `DEBUG_FD` env variable support + * deps: depd@~1.0.0 + * deps: etag@~1.5.0 + - Improve string performance + - Slightly improve speed for weak ETags over 1KB + +0.9.3 / 2014-09-24 +================== + + * deps: etag@~1.4.0 + - Support "fake" stats objects + +0.9.2 / 2014-09-15 +================== + + * deps: depd@0.4.5 + * deps: etag@~1.3.1 + * deps: range-parser@~1.0.2 + +0.9.1 / 2014-09-07 +================== + + * deps: fresh@0.2.4 + +0.9.0 / 2014-09-07 +================== + + * Add `lastModified` option + * Use `etag` to generate `ETag` header + * deps: debug@~2.0.0 + +0.8.5 / 2014-09-04 +================== + + * Fix malicious path detection for empty string path + +0.8.4 / 2014-09-04 +================== + + * Fix a path traversal issue when using `root` + +0.8.3 / 2014-08-16 +================== + + * deps: destroy@1.0.3 + - renamed from dethroy + * deps: on-finished@2.1.0 + +0.8.2 / 2014-08-14 +================== + + * Work around `fd` leak in Node.js 0.10 for `fs.ReadStream` + * deps: dethroy@1.0.2 + +0.8.1 / 2014-08-05 +================== + + * Fix `extensions` behavior when file already has extension + +0.8.0 / 2014-08-05 +================== + + * Add `extensions` option + +0.7.4 / 2014-08-04 +================== + + * Fix serving index files without root dir + +0.7.3 / 2014-07-29 +================== + + * Fix incorrect 403 on Windows and Node.js 0.11 + +0.7.2 / 2014-07-27 +================== + + * deps: depd@0.4.4 + - Work-around v8 generating empty stack traces + +0.7.1 / 2014-07-26 +================== + + * deps: depd@0.4.3 + - Fix exception when global `Error.stackTraceLimit` is too low + +0.7.0 / 2014-07-20 +================== + + * Deprecate `hidden` option; use `dotfiles` option + * Add `dotfiles` option + * deps: debug@1.0.4 + * deps: depd@0.4.2 + - Add `TRACE_DEPRECATION` environment variable + - Remove non-standard grey color from color output + - Support `--no-deprecation` argument + - Support `--trace-deprecation` argument + +0.6.0 / 2014-07-11 +================== + + * Deprecate `from` option; use `root` option + * Deprecate `send.etag()` -- use `etag` in `options` + * Deprecate `send.hidden()` -- use `hidden` in `options` + * Deprecate `send.index()` -- use `index` in `options` + * Deprecate `send.maxage()` -- use `maxAge` in `options` + * Deprecate `send.root()` -- use `root` in `options` + * Cap `maxAge` value to 1 year + * deps: debug@1.0.3 + - Add support for multiple wildcards in namespaces + +0.5.0 / 2014-06-28 +================== + + * Accept string for `maxAge` (converted by `ms`) + * Add `headers` event + * Include link in default redirect response + * Use `EventEmitter.listenerCount` to count listeners + +0.4.3 / 2014-06-11 +================== + + * Do not throw un-catchable error on file open race condition + * Use `escape-html` for HTML escaping + * deps: debug@1.0.2 + - fix some debugging output colors on node.js 0.8 + * deps: finished@1.2.2 + * deps: fresh@0.2.2 + +0.4.2 / 2014-06-09 +================== + + * fix "event emitter leak" warnings + * deps: debug@1.0.1 + * deps: finished@1.2.1 + +0.4.1 / 2014-06-02 +================== + + * Send `max-age` in `Cache-Control` in correct format + +0.4.0 / 2014-05-27 +================== + + * Calculate ETag with md5 for reduced collisions + * Fix wrong behavior when index file matches directory + * Ignore stream errors after request ends + - Goodbye `EBADF, read` + * Skip directories in index file search + * deps: debug@0.8.1 + +0.3.0 / 2014-04-24 +================== + + * Fix sending files with dots without root set + * Coerce option types + * Accept API options in options object + * Set etags to "weak" + * Include file path in etag + * Make "Can't set headers after they are sent." catchable + * Send full entity-body for multi range requests + * Default directory access to 403 when index disabled + * Support multiple index paths + * Support "If-Range" header + * Control whether to generate etags + * deps: mime@1.2.11 + +0.2.0 / 2014-01-29 +================== + + * update range-parser and fresh + +0.1.4 / 2013-08-11 +================== + + * update fresh + +0.1.3 / 2013-07-08 +================== + + * Revert "Fix fd leak" + +0.1.2 / 2013-07-03 +================== + + * Fix fd leak + +0.1.0 / 2012-08-25 +================== + + * add options parameter to send() that is passed to fs.createReadStream() [kanongil] + +0.0.4 / 2012-08-16 +================== + + * allow custom "Accept-Ranges" definition + +0.0.3 / 2012-07-16 +================== + + * fix normalization of the root directory. Closes #3 + +0.0.2 / 2012-07-09 +================== + + * add passing of req explicitly for now (YUCK) + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/homework7/project_express/node_modules/send/LICENSE b/homework7/project_express/node_modules/send/LICENSE new file mode 100644 index 0000000..4aa69e8 --- /dev/null +++ b/homework7/project_express/node_modules/send/LICENSE @@ -0,0 +1,23 @@ +(The MIT License) + +Copyright (c) 2012 TJ Holowaychuk +Copyright (c) 2014-2016 Douglas Christopher Wilson + +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/homework7/project_express/node_modules/send/README.md b/homework7/project_express/node_modules/send/README.md new file mode 100644 index 0000000..179e8c3 --- /dev/null +++ b/homework7/project_express/node_modules/send/README.md @@ -0,0 +1,329 @@ +# send + +[![NPM Version][npm-version-image]][npm-url] +[![NPM Downloads][npm-downloads-image]][npm-url] +[![Linux Build][travis-image]][travis-url] +[![Windows Build][appveyor-image]][appveyor-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Send is a library for streaming files from the file system as a http response +supporting partial responses (Ranges), conditional-GET negotiation (If-Match, +If-Unmodified-Since, If-None-Match, If-Modified-Since), high test coverage, +and granular events which may be leveraged to take appropriate actions in your +application or framework. + +Looking to serve up entire folders mapped to URLs? Try [serve-static](https://www.npmjs.org/package/serve-static). + +## Installation + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```bash +$ npm install send +``` + +## API + + + +```js +var send = require('send') +``` + +### send(req, path, [options]) + +Create a new `SendStream` for the given path to send to a `res`. The `req` is +the Node.js HTTP request and the `path` is a urlencoded path to send (urlencoded, +not the actual file-system path). + +#### Options + +##### acceptRanges + +Enable or disable accepting ranged requests, defaults to true. +Disabling this will not send `Accept-Ranges` and ignore the contents +of the `Range` request header. + +##### cacheControl + +Enable or disable setting `Cache-Control` response header, defaults to +true. Disabling this will ignore the `immutable` and `maxAge` options. + +##### dotfiles + +Set how "dotfiles" are treated when encountered. A dotfile is a file +or directory that begins with a dot ("."). Note this check is done on +the path itself without checking if the path actually exists on the +disk. If `root` is specified, only the dotfiles above the root are +checked (i.e. the root itself can be within a dotfile when when set +to "deny"). + + - `'allow'` No special treatment for dotfiles. + - `'deny'` Send a 403 for any request for a dotfile. + - `'ignore'` Pretend like the dotfile does not exist and 404. + +The default value is _similar_ to `'ignore'`, with the exception that +this default will not ignore the files within a directory that begins +with a dot, for backward-compatibility. + +##### end + +Byte offset at which the stream ends, defaults to the length of the file +minus 1. The end is inclusive in the stream, meaning `end: 3` will include +the 4th byte in the stream. + +##### etag + +Enable or disable etag generation, defaults to true. + +##### extensions + +If a given file doesn't exist, try appending one of the given extensions, +in the given order. By default, this is disabled (set to `false`). An +example value that will serve extension-less HTML files: `['html', 'htm']`. +This is skipped if the requested file already has an extension. + +##### immutable + +Enable or diable the `immutable` directive in the `Cache-Control` response +header, defaults to `false`. If set to `true`, the `maxAge` option should +also be specified to enable caching. The `immutable` directive will prevent +supported clients from making conditional requests during the life of the +`maxAge` option to check if the file has changed. + +##### index + +By default send supports "index.html" files, to disable this +set `false` or to supply a new index pass a string or an array +in preferred order. + +##### lastModified + +Enable or disable `Last-Modified` header, defaults to true. Uses the file +system's last modified value. + +##### maxAge + +Provide a max-age in milliseconds for http caching, defaults to 0. +This can also be a string accepted by the +[ms](https://www.npmjs.org/package/ms#readme) module. + +##### root + +Serve files relative to `path`. + +##### start + +Byte offset at which the stream starts, defaults to 0. The start is inclusive, +meaning `start: 2` will include the 3rd byte in the stream. + +#### Events + +The `SendStream` is an event emitter and will emit the following events: + + - `error` an error occurred `(err)` + - `directory` a directory was requested `(res, path)` + - `file` a file was requested `(path, stat)` + - `headers` the headers are about to be set on a file `(res, path, stat)` + - `stream` file streaming has started `(stream)` + - `end` streaming has completed + +#### .pipe + +The `pipe` method is used to pipe the response into the Node.js HTTP response +object, typically `send(req, path, options).pipe(res)`. + +### .mime + +The `mime` export is the global instance of of the +[`mime` npm module](https://www.npmjs.com/package/mime). + +This is used to configure the MIME types that are associated with file extensions +as well as other options for how to resolve the MIME type of a file (like the +default type to use for an unknown file extension). + +## Error-handling + +By default when no `error` listeners are present an automatic response will be +made, otherwise you have full control over the response, aka you may show a 5xx +page etc. + +## Caching + +It does _not_ perform internal caching, you should use a reverse proxy cache +such as Varnish for this, or those fancy things called CDNs. If your +application is small enough that it would benefit from single-node memory +caching, it's small enough that it does not need caching at all ;). + +## Debugging + +To enable `debug()` instrumentation output export __DEBUG__: + +``` +$ DEBUG=send node app +``` + +## Running tests + +``` +$ npm install +$ npm test +``` + +## Examples + +### Serve a specific file + +This simple example will send a specific file to all requests. + +```js +var http = require('http') +var send = require('send') + +var server = http.createServer(function onRequest (req, res) { + send(req, '/path/to/index.html') + .pipe(res) +}) + +server.listen(3000) +``` + +### Serve all files from a directory + +This simple example will just serve up all the files in a +given directory as the top-level. For example, a request +`GET /foo.txt` will send back `/www/public/foo.txt`. + +```js +var http = require('http') +var parseUrl = require('parseurl') +var send = require('send') + +var server = http.createServer(function onRequest (req, res) { + send(req, parseUrl(req).pathname, { root: '/www/public' }) + .pipe(res) +}) + +server.listen(3000) +``` + +### Custom file types + +```js +var http = require('http') +var parseUrl = require('parseurl') +var send = require('send') + +// Default unknown types to text/plain +send.mime.default_type = 'text/plain' + +// Add a custom type +send.mime.define({ + 'application/x-my-type': ['x-mt', 'x-mtt'] +}) + +var server = http.createServer(function onRequest (req, res) { + send(req, parseUrl(req).pathname, { root: '/www/public' }) + .pipe(res) +}) + +server.listen(3000) +``` + +### Custom directory index view + +This is a example of serving up a structure of directories with a +custom function to render a listing of a directory. + +```js +var http = require('http') +var fs = require('fs') +var parseUrl = require('parseurl') +var send = require('send') + +// Transfer arbitrary files from within /www/example.com/public/* +// with a custom handler for directory listing +var server = http.createServer(function onRequest (req, res) { + send(req, parseUrl(req).pathname, { index: false, root: '/www/public' }) + .once('directory', directory) + .pipe(res) +}) + +server.listen(3000) + +// Custom directory handler +function directory (res, path) { + var stream = this + + // redirect to trailing slash for consistent url + if (!stream.hasTrailingSlash()) { + return stream.redirect(path) + } + + // get directory list + fs.readdir(path, function onReaddir (err, list) { + if (err) return stream.error(err) + + // render an index for the directory + res.setHeader('Content-Type', 'text/plain; charset=UTF-8') + res.end(list.join('\n') + '\n') + }) +} +``` + +### Serving from a root directory with custom error-handling + +```js +var http = require('http') +var parseUrl = require('parseurl') +var send = require('send') + +var server = http.createServer(function onRequest (req, res) { + // your custom error-handling logic: + function error (err) { + res.statusCode = err.status || 500 + res.end(err.message) + } + + // your custom headers + function headers (res, path, stat) { + // serve all files for download + res.setHeader('Content-Disposition', 'attachment') + } + + // your custom directory handling logic: + function redirect () { + res.statusCode = 301 + res.setHeader('Location', req.url + '/') + res.end('Redirecting to ' + req.url + '/') + } + + // transfer arbitrary files from within + // /www/example.com/public/* + send(req, parseUrl(req).pathname, { root: '/www/public' }) + .on('error', error) + .on('directory', redirect) + .on('headers', headers) + .pipe(res) +}) + +server.listen(3000) +``` + +## License + +[MIT](LICENSE) + +[appveyor-image]: https://badgen.net/appveyor/ci/dougwilson/send/master?label=windows +[appveyor-url]: https://ci.appveyor.com/project/dougwilson/send +[coveralls-image]: https://badgen.net/coveralls/c/github/pillarjs/send/master +[coveralls-url]: https://coveralls.io/r/pillarjs/send?branch=master +[node-image]: https://badgen.net/npm/node/send +[node-url]: https://nodejs.org/en/download/ +[npm-downloads-image]: https://badgen.net/npm/dm/send +[npm-url]: https://npmjs.org/package/send +[npm-version-image]: https://badgen.net/npm/v/send +[travis-image]: https://badgen.net/travis/pillarjs/send/master?label=linux +[travis-url]: https://travis-ci.org/pillarjs/send diff --git a/homework7/project_express/node_modules/send/index.js b/homework7/project_express/node_modules/send/index.js new file mode 100644 index 0000000..fca2112 --- /dev/null +++ b/homework7/project_express/node_modules/send/index.js @@ -0,0 +1,1129 @@ +/*! + * send + * Copyright(c) 2012 TJ Holowaychuk + * Copyright(c) 2014-2016 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var createError = require('http-errors') +var debug = require('debug')('send') +var deprecate = require('depd')('send') +var destroy = require('destroy') +var encodeUrl = require('encodeurl') +var escapeHtml = require('escape-html') +var etag = require('etag') +var fresh = require('fresh') +var fs = require('fs') +var mime = require('mime') +var ms = require('ms') +var onFinished = require('on-finished') +var parseRange = require('range-parser') +var path = require('path') +var statuses = require('statuses') +var Stream = require('stream') +var util = require('util') + +/** + * Path function references. + * @private + */ + +var extname = path.extname +var join = path.join +var normalize = path.normalize +var resolve = path.resolve +var sep = path.sep + +/** + * Regular expression for identifying a bytes Range header. + * @private + */ + +var BYTES_RANGE_REGEXP = /^ *bytes=/ + +/** + * Maximum value allowed for the max age. + * @private + */ + +var MAX_MAXAGE = 60 * 60 * 24 * 365 * 1000 // 1 year + +/** + * Regular expression to match a path with a directory up component. + * @private + */ + +var UP_PATH_REGEXP = /(?:^|[\\/])\.\.(?:[\\/]|$)/ + +/** + * Module exports. + * @public + */ + +module.exports = send +module.exports.mime = mime + +/** + * Return a `SendStream` for `req` and `path`. + * + * @param {object} req + * @param {string} path + * @param {object} [options] + * @return {SendStream} + * @public + */ + +function send (req, path, options) { + return new SendStream(req, path, options) +} + +/** + * Initialize a `SendStream` with the given `path`. + * + * @param {Request} req + * @param {String} path + * @param {object} [options] + * @private + */ + +function SendStream (req, path, options) { + Stream.call(this) + + var opts = options || {} + + this.options = opts + this.path = path + this.req = req + + this._acceptRanges = opts.acceptRanges !== undefined + ? Boolean(opts.acceptRanges) + : true + + this._cacheControl = opts.cacheControl !== undefined + ? Boolean(opts.cacheControl) + : true + + this._etag = opts.etag !== undefined + ? Boolean(opts.etag) + : true + + this._dotfiles = opts.dotfiles !== undefined + ? opts.dotfiles + : 'ignore' + + if (this._dotfiles !== 'ignore' && this._dotfiles !== 'allow' && this._dotfiles !== 'deny') { + throw new TypeError('dotfiles option must be "allow", "deny", or "ignore"') + } + + this._hidden = Boolean(opts.hidden) + + if (opts.hidden !== undefined) { + deprecate('hidden: use dotfiles: \'' + (this._hidden ? 'allow' : 'ignore') + '\' instead') + } + + // legacy support + if (opts.dotfiles === undefined) { + this._dotfiles = undefined + } + + this._extensions = opts.extensions !== undefined + ? normalizeList(opts.extensions, 'extensions option') + : [] + + this._immutable = opts.immutable !== undefined + ? Boolean(opts.immutable) + : false + + this._index = opts.index !== undefined + ? normalizeList(opts.index, 'index option') + : ['index.html'] + + this._lastModified = opts.lastModified !== undefined + ? Boolean(opts.lastModified) + : true + + this._maxage = opts.maxAge || opts.maxage + this._maxage = typeof this._maxage === 'string' + ? ms(this._maxage) + : Number(this._maxage) + this._maxage = !isNaN(this._maxage) + ? Math.min(Math.max(0, this._maxage), MAX_MAXAGE) + : 0 + + this._root = opts.root + ? resolve(opts.root) + : null + + if (!this._root && opts.from) { + this.from(opts.from) + } +} + +/** + * Inherits from `Stream`. + */ + +util.inherits(SendStream, Stream) + +/** + * Enable or disable etag generation. + * + * @param {Boolean} val + * @return {SendStream} + * @api public + */ + +SendStream.prototype.etag = deprecate.function(function etag (val) { + this._etag = Boolean(val) + debug('etag %s', this._etag) + return this +}, 'send.etag: pass etag as option') + +/** + * Enable or disable "hidden" (dot) files. + * + * @param {Boolean} path + * @return {SendStream} + * @api public + */ + +SendStream.prototype.hidden = deprecate.function(function hidden (val) { + this._hidden = Boolean(val) + this._dotfiles = undefined + debug('hidden %s', this._hidden) + return this +}, 'send.hidden: use dotfiles option') + +/** + * Set index `paths`, set to a falsy + * value to disable index support. + * + * @param {String|Boolean|Array} paths + * @return {SendStream} + * @api public + */ + +SendStream.prototype.index = deprecate.function(function index (paths) { + var index = !paths ? [] : normalizeList(paths, 'paths argument') + debug('index %o', paths) + this._index = index + return this +}, 'send.index: pass index as option') + +/** + * Set root `path`. + * + * @param {String} path + * @return {SendStream} + * @api public + */ + +SendStream.prototype.root = function root (path) { + this._root = resolve(String(path)) + debug('root %s', this._root) + return this +} + +SendStream.prototype.from = deprecate.function(SendStream.prototype.root, + 'send.from: pass root as option') + +SendStream.prototype.root = deprecate.function(SendStream.prototype.root, + 'send.root: pass root as option') + +/** + * Set max-age to `maxAge`. + * + * @param {Number} maxAge + * @return {SendStream} + * @api public + */ + +SendStream.prototype.maxage = deprecate.function(function maxage (maxAge) { + this._maxage = typeof maxAge === 'string' + ? ms(maxAge) + : Number(maxAge) + this._maxage = !isNaN(this._maxage) + ? Math.min(Math.max(0, this._maxage), MAX_MAXAGE) + : 0 + debug('max-age %d', this._maxage) + return this +}, 'send.maxage: pass maxAge as option') + +/** + * Emit error with `status`. + * + * @param {number} status + * @param {Error} [err] + * @private + */ + +SendStream.prototype.error = function error (status, err) { + // emit if listeners instead of responding + if (hasListeners(this, 'error')) { + return this.emit('error', createError(status, err, { + expose: false + })) + } + + var res = this.res + var msg = statuses[status] || String(status) + var doc = createHtmlDocument('Error', escapeHtml(msg)) + + // clear existing headers + clearHeaders(res) + + // add error headers + if (err && err.headers) { + setHeaders(res, err.headers) + } + + // send basic response + res.statusCode = status + res.setHeader('Content-Type', 'text/html; charset=UTF-8') + res.setHeader('Content-Length', Buffer.byteLength(doc)) + res.setHeader('Content-Security-Policy', "default-src 'none'") + res.setHeader('X-Content-Type-Options', 'nosniff') + res.end(doc) +} + +/** + * Check if the pathname ends with "/". + * + * @return {boolean} + * @private + */ + +SendStream.prototype.hasTrailingSlash = function hasTrailingSlash () { + return this.path[this.path.length - 1] === '/' +} + +/** + * Check if this is a conditional GET request. + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.isConditionalGET = function isConditionalGET () { + return this.req.headers['if-match'] || + this.req.headers['if-unmodified-since'] || + this.req.headers['if-none-match'] || + this.req.headers['if-modified-since'] +} + +/** + * Check if the request preconditions failed. + * + * @return {boolean} + * @private + */ + +SendStream.prototype.isPreconditionFailure = function isPreconditionFailure () { + var req = this.req + var res = this.res + + // if-match + var match = req.headers['if-match'] + if (match) { + var etag = res.getHeader('ETag') + return !etag || (match !== '*' && parseTokenList(match).every(function (match) { + return match !== etag && match !== 'W/' + etag && 'W/' + match !== etag + })) + } + + // if-unmodified-since + var unmodifiedSince = parseHttpDate(req.headers['if-unmodified-since']) + if (!isNaN(unmodifiedSince)) { + var lastModified = parseHttpDate(res.getHeader('Last-Modified')) + return isNaN(lastModified) || lastModified > unmodifiedSince + } + + return false +} + +/** + * Strip content-* header fields. + * + * @private + */ + +SendStream.prototype.removeContentHeaderFields = function removeContentHeaderFields () { + var res = this.res + var headers = getHeaderNames(res) + + for (var i = 0; i < headers.length; i++) { + var header = headers[i] + if (header.substr(0, 8) === 'content-' && header !== 'content-location') { + res.removeHeader(header) + } + } +} + +/** + * Respond with 304 not modified. + * + * @api private + */ + +SendStream.prototype.notModified = function notModified () { + var res = this.res + debug('not modified') + this.removeContentHeaderFields() + res.statusCode = 304 + res.end() +} + +/** + * Raise error that headers already sent. + * + * @api private + */ + +SendStream.prototype.headersAlreadySent = function headersAlreadySent () { + var err = new Error('Can\'t set headers after they are sent.') + debug('headers already sent') + this.error(500, err) +} + +/** + * Check if the request is cacheable, aka + * responded with 2xx or 304 (see RFC 2616 section 14.2{5,6}). + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.isCachable = function isCachable () { + var statusCode = this.res.statusCode + return (statusCode >= 200 && statusCode < 300) || + statusCode === 304 +} + +/** + * Handle stat() error. + * + * @param {Error} error + * @private + */ + +SendStream.prototype.onStatError = function onStatError (error) { + switch (error.code) { + case 'ENAMETOOLONG': + case 'ENOENT': + case 'ENOTDIR': + this.error(404, error) + break + default: + this.error(500, error) + break + } +} + +/** + * Check if the cache is fresh. + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.isFresh = function isFresh () { + return fresh(this.req.headers, { + 'etag': this.res.getHeader('ETag'), + 'last-modified': this.res.getHeader('Last-Modified') + }) +} + +/** + * Check if the range is fresh. + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.isRangeFresh = function isRangeFresh () { + var ifRange = this.req.headers['if-range'] + + if (!ifRange) { + return true + } + + // if-range as etag + if (ifRange.indexOf('"') !== -1) { + var etag = this.res.getHeader('ETag') + return Boolean(etag && ifRange.indexOf(etag) !== -1) + } + + // if-range as modified date + var lastModified = this.res.getHeader('Last-Modified') + return parseHttpDate(lastModified) <= parseHttpDate(ifRange) +} + +/** + * Redirect to path. + * + * @param {string} path + * @private + */ + +SendStream.prototype.redirect = function redirect (path) { + var res = this.res + + if (hasListeners(this, 'directory')) { + this.emit('directory', res, path) + return + } + + if (this.hasTrailingSlash()) { + this.error(403) + return + } + + var loc = encodeUrl(collapseLeadingSlashes(this.path + '/')) + var doc = createHtmlDocument('Redirecting', 'Redirecting to ' + + escapeHtml(loc) + '') + + // redirect + res.statusCode = 301 + res.setHeader('Content-Type', 'text/html; charset=UTF-8') + res.setHeader('Content-Length', Buffer.byteLength(doc)) + res.setHeader('Content-Security-Policy', "default-src 'none'") + res.setHeader('X-Content-Type-Options', 'nosniff') + res.setHeader('Location', loc) + res.end(doc) +} + +/** + * Pipe to `res. + * + * @param {Stream} res + * @return {Stream} res + * @api public + */ + +SendStream.prototype.pipe = function pipe (res) { + // root path + var root = this._root + + // references + this.res = res + + // decode the path + var path = decode(this.path) + if (path === -1) { + this.error(400) + return res + } + + // null byte(s) + if (~path.indexOf('\0')) { + this.error(400) + return res + } + + var parts + if (root !== null) { + // normalize + if (path) { + path = normalize('.' + sep + path) + } + + // malicious path + if (UP_PATH_REGEXP.test(path)) { + debug('malicious path "%s"', path) + this.error(403) + return res + } + + // explode path parts + parts = path.split(sep) + + // join / normalize from optional root dir + path = normalize(join(root, path)) + } else { + // ".." is malicious without "root" + if (UP_PATH_REGEXP.test(path)) { + debug('malicious path "%s"', path) + this.error(403) + return res + } + + // explode path parts + parts = normalize(path).split(sep) + + // resolve the path + path = resolve(path) + } + + // dotfile handling + if (containsDotFile(parts)) { + var access = this._dotfiles + + // legacy support + if (access === undefined) { + access = parts[parts.length - 1][0] === '.' + ? (this._hidden ? 'allow' : 'ignore') + : 'allow' + } + + debug('%s dotfile "%s"', access, path) + switch (access) { + case 'allow': + break + case 'deny': + this.error(403) + return res + case 'ignore': + default: + this.error(404) + return res + } + } + + // index file support + if (this._index.length && this.hasTrailingSlash()) { + this.sendIndex(path) + return res + } + + this.sendFile(path) + return res +} + +/** + * Transfer `path`. + * + * @param {String} path + * @api public + */ + +SendStream.prototype.send = function send (path, stat) { + var len = stat.size + var options = this.options + var opts = {} + var res = this.res + var req = this.req + var ranges = req.headers.range + var offset = options.start || 0 + + if (headersSent(res)) { + // impossible to send now + this.headersAlreadySent() + return + } + + debug('pipe "%s"', path) + + // set header fields + this.setHeader(path, stat) + + // set content-type + this.type(path) + + // conditional GET support + if (this.isConditionalGET()) { + if (this.isPreconditionFailure()) { + this.error(412) + return + } + + if (this.isCachable() && this.isFresh()) { + this.notModified() + return + } + } + + // adjust len to start/end options + len = Math.max(0, len - offset) + if (options.end !== undefined) { + var bytes = options.end - offset + 1 + if (len > bytes) len = bytes + } + + // Range support + if (this._acceptRanges && BYTES_RANGE_REGEXP.test(ranges)) { + // parse + ranges = parseRange(len, ranges, { + combine: true + }) + + // If-Range support + if (!this.isRangeFresh()) { + debug('range stale') + ranges = -2 + } + + // unsatisfiable + if (ranges === -1) { + debug('range unsatisfiable') + + // Content-Range + res.setHeader('Content-Range', contentRange('bytes', len)) + + // 416 Requested Range Not Satisfiable + return this.error(416, { + headers: { 'Content-Range': res.getHeader('Content-Range') } + }) + } + + // valid (syntactically invalid/multiple ranges are treated as a regular response) + if (ranges !== -2 && ranges.length === 1) { + debug('range %j', ranges) + + // Content-Range + res.statusCode = 206 + res.setHeader('Content-Range', contentRange('bytes', len, ranges[0])) + + // adjust for requested range + offset += ranges[0].start + len = ranges[0].end - ranges[0].start + 1 + } + } + + // clone options + for (var prop in options) { + opts[prop] = options[prop] + } + + // set read options + opts.start = offset + opts.end = Math.max(offset, offset + len - 1) + + // content-length + res.setHeader('Content-Length', len) + + // HEAD support + if (req.method === 'HEAD') { + res.end() + return + } + + this.stream(path, opts) +} + +/** + * Transfer file for `path`. + * + * @param {String} path + * @api private + */ +SendStream.prototype.sendFile = function sendFile (path) { + var i = 0 + var self = this + + debug('stat "%s"', path) + fs.stat(path, function onstat (err, stat) { + if (err && err.code === 'ENOENT' && !extname(path) && path[path.length - 1] !== sep) { + // not found, check extensions + return next(err) + } + if (err) return self.onStatError(err) + if (stat.isDirectory()) return self.redirect(path) + self.emit('file', path, stat) + self.send(path, stat) + }) + + function next (err) { + if (self._extensions.length <= i) { + return err + ? self.onStatError(err) + : self.error(404) + } + + var p = path + '.' + self._extensions[i++] + + debug('stat "%s"', p) + fs.stat(p, function (err, stat) { + if (err) return next(err) + if (stat.isDirectory()) return next() + self.emit('file', p, stat) + self.send(p, stat) + }) + } +} + +/** + * Transfer index for `path`. + * + * @param {String} path + * @api private + */ +SendStream.prototype.sendIndex = function sendIndex (path) { + var i = -1 + var self = this + + function next (err) { + if (++i >= self._index.length) { + if (err) return self.onStatError(err) + return self.error(404) + } + + var p = join(path, self._index[i]) + + debug('stat "%s"', p) + fs.stat(p, function (err, stat) { + if (err) return next(err) + if (stat.isDirectory()) return next() + self.emit('file', p, stat) + self.send(p, stat) + }) + } + + next() +} + +/** + * Stream `path` to the response. + * + * @param {String} path + * @param {Object} options + * @api private + */ + +SendStream.prototype.stream = function stream (path, options) { + // TODO: this is all lame, refactor meeee + var finished = false + var self = this + var res = this.res + + // pipe + var stream = fs.createReadStream(path, options) + this.emit('stream', stream) + stream.pipe(res) + + // response finished, done with the fd + onFinished(res, function onfinished () { + finished = true + destroy(stream) + }) + + // error handling code-smell + stream.on('error', function onerror (err) { + // request already finished + if (finished) return + + // clean up stream + finished = true + destroy(stream) + + // error + self.onStatError(err) + }) + + // end + stream.on('end', function onend () { + self.emit('end') + }) +} + +/** + * Set content-type based on `path` + * if it hasn't been explicitly set. + * + * @param {String} path + * @api private + */ + +SendStream.prototype.type = function type (path) { + var res = this.res + + if (res.getHeader('Content-Type')) return + + var type = mime.lookup(path) + + if (!type) { + debug('no content-type') + return + } + + var charset = mime.charsets.lookup(type) + + debug('content-type %s', type) + res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : '')) +} + +/** + * Set response header fields, most + * fields may be pre-defined. + * + * @param {String} path + * @param {Object} stat + * @api private + */ + +SendStream.prototype.setHeader = function setHeader (path, stat) { + var res = this.res + + this.emit('headers', res, path, stat) + + if (this._acceptRanges && !res.getHeader('Accept-Ranges')) { + debug('accept ranges') + res.setHeader('Accept-Ranges', 'bytes') + } + + if (this._cacheControl && !res.getHeader('Cache-Control')) { + var cacheControl = 'public, max-age=' + Math.floor(this._maxage / 1000) + + if (this._immutable) { + cacheControl += ', immutable' + } + + debug('cache-control %s', cacheControl) + res.setHeader('Cache-Control', cacheControl) + } + + if (this._lastModified && !res.getHeader('Last-Modified')) { + var modified = stat.mtime.toUTCString() + debug('modified %s', modified) + res.setHeader('Last-Modified', modified) + } + + if (this._etag && !res.getHeader('ETag')) { + var val = etag(stat) + debug('etag %s', val) + res.setHeader('ETag', val) + } +} + +/** + * Clear all headers from a response. + * + * @param {object} res + * @private + */ + +function clearHeaders (res) { + var headers = getHeaderNames(res) + + for (var i = 0; i < headers.length; i++) { + res.removeHeader(headers[i]) + } +} + +/** + * Collapse all leading slashes into a single slash + * + * @param {string} str + * @private + */ +function collapseLeadingSlashes (str) { + for (var i = 0; i < str.length; i++) { + if (str[i] !== '/') { + break + } + } + + return i > 1 + ? '/' + str.substr(i) + : str +} + +/** + * Determine if path parts contain a dotfile. + * + * @api private + */ + +function containsDotFile (parts) { + for (var i = 0; i < parts.length; i++) { + var part = parts[i] + if (part.length > 1 && part[0] === '.') { + return true + } + } + + return false +} + +/** + * Create a Content-Range header. + * + * @param {string} type + * @param {number} size + * @param {array} [range] + */ + +function contentRange (type, size, range) { + return type + ' ' + (range ? range.start + '-' + range.end : '*') + '/' + size +} + +/** + * Create a minimal HTML document. + * + * @param {string} title + * @param {string} body + * @private + */ + +function createHtmlDocument (title, body) { + return '\n' + + '\n' + + '\n' + + '\n' + + '' + title + '\n' + + '\n' + + '\n' + + '
' + body + '
\n' + + '\n' + + '\n' +} + +/** + * decodeURIComponent. + * + * Allows V8 to only deoptimize this fn instead of all + * of send(). + * + * @param {String} path + * @api private + */ + +function decode (path) { + try { + return decodeURIComponent(path) + } catch (err) { + return -1 + } +} + +/** + * Get the header names on a respnse. + * + * @param {object} res + * @returns {array[string]} + * @private + */ + +function getHeaderNames (res) { + return typeof res.getHeaderNames !== 'function' + ? Object.keys(res._headers || {}) + : res.getHeaderNames() +} + +/** + * Determine if emitter has listeners of a given type. + * + * The way to do this check is done three different ways in Node.js >= 0.8 + * so this consolidates them into a minimal set using instance methods. + * + * @param {EventEmitter} emitter + * @param {string} type + * @returns {boolean} + * @private + */ + +function hasListeners (emitter, type) { + var count = typeof emitter.listenerCount !== 'function' + ? emitter.listeners(type).length + : emitter.listenerCount(type) + + return count > 0 +} + +/** + * Determine if the response headers have been sent. + * + * @param {object} res + * @returns {boolean} + * @private + */ + +function headersSent (res) { + return typeof res.headersSent !== 'boolean' + ? Boolean(res._header) + : res.headersSent +} + +/** + * Normalize the index option into an array. + * + * @param {boolean|string|array} val + * @param {string} name + * @private + */ + +function normalizeList (val, name) { + var list = [].concat(val || []) + + for (var i = 0; i < list.length; i++) { + if (typeof list[i] !== 'string') { + throw new TypeError(name + ' must be array of strings or false') + } + } + + return list +} + +/** + * Parse an HTTP Date into a number. + * + * @param {string} date + * @private + */ + +function parseHttpDate (date) { + var timestamp = date && Date.parse(date) + + return typeof timestamp === 'number' + ? timestamp + : NaN +} + +/** + * Parse a HTTP token list. + * + * @param {string} str + * @private + */ + +function parseTokenList (str) { + var end = 0 + var list = [] + var start = 0 + + // gather tokens + for (var i = 0, len = str.length; i < len; i++) { + switch (str.charCodeAt(i)) { + case 0x20: /* */ + if (start === end) { + start = end = i + 1 + } + break + case 0x2c: /* , */ + list.push(str.substring(start, end)) + start = end = i + 1 + break + default: + end = i + 1 + break + } + } + + // final token + list.push(str.substring(start, end)) + + return list +} + +/** + * Set an object of headers on a response. + * + * @param {object} res + * @param {object} headers + * @private + */ + +function setHeaders (res, headers) { + var keys = Object.keys(headers) + + for (var i = 0; i < keys.length; i++) { + var key = keys[i] + res.setHeader(key, headers[key]) + } +} diff --git a/homework7/project_express/node_modules/send/node_modules/ms/index.js b/homework7/project_express/node_modules/send/node_modules/ms/index.js new file mode 100644 index 0000000..7229750 --- /dev/null +++ b/homework7/project_express/node_modules/send/node_modules/ms/index.js @@ -0,0 +1,162 @@ +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var w = d * 7; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + +module.exports = function(val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse(val); + } else if (type === 'number' && isNaN(val) === false) { + return options.long ? fmtLong(val) : fmtShort(val); + } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^((?:\d+)?\-?\d?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'weeks': + case 'week': + case 'w': + return n * w; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtShort(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return Math.round(ms / d) + 'd'; + } + if (msAbs >= h) { + return Math.round(ms / h) + 'h'; + } + if (msAbs >= m) { + return Math.round(ms / m) + 'm'; + } + if (msAbs >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtLong(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return plural(ms, msAbs, d, 'day'); + } + if (msAbs >= h) { + return plural(ms, msAbs, h, 'hour'); + } + if (msAbs >= m) { + return plural(ms, msAbs, m, 'minute'); + } + if (msAbs >= s) { + return plural(ms, msAbs, s, 'second'); + } + return ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, msAbs, n, name) { + var isPlural = msAbs >= n * 1.5; + return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : ''); +} diff --git a/homework7/project_express/node_modules/send/node_modules/ms/license.md b/homework7/project_express/node_modules/send/node_modules/ms/license.md new file mode 100644 index 0000000..69b6125 --- /dev/null +++ b/homework7/project_express/node_modules/send/node_modules/ms/license.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Zeit, Inc. + +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/homework7/project_express/node_modules/send/node_modules/ms/package.json b/homework7/project_express/node_modules/send/node_modules/ms/package.json new file mode 100644 index 0000000..dbff5cf --- /dev/null +++ b/homework7/project_express/node_modules/send/node_modules/ms/package.json @@ -0,0 +1,69 @@ +{ + "_from": "ms@2.1.1", + "_id": "ms@2.1.1", + "_inBundle": false, + "_integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "_location": "/send/ms", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "ms@2.1.1", + "name": "ms", + "escapedName": "ms", + "rawSpec": "2.1.1", + "saveSpec": null, + "fetchSpec": "2.1.1" + }, + "_requiredBy": [ + "/send" + ], + "_resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "_shasum": "30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a", + "_spec": "ms@2.1.1", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\send", + "bugs": { + "url": "https://github.com/zeit/ms/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Tiny millisecond conversion utility", + "devDependencies": { + "eslint": "4.12.1", + "expect.js": "0.3.1", + "husky": "0.14.3", + "lint-staged": "5.0.0", + "mocha": "4.0.1" + }, + "eslintConfig": { + "extends": "eslint:recommended", + "env": { + "node": true, + "es6": true + } + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/zeit/ms#readme", + "license": "MIT", + "lint-staged": { + "*.js": [ + "npm run lint", + "prettier --single-quote --write", + "git add" + ] + }, + "main": "./index", + "name": "ms", + "repository": { + "type": "git", + "url": "git+https://github.com/zeit/ms.git" + }, + "scripts": { + "lint": "eslint lib/* bin/*", + "precommit": "lint-staged", + "test": "mocha tests.js" + }, + "version": "2.1.1" +} diff --git a/homework7/project_express/node_modules/send/node_modules/ms/readme.md b/homework7/project_express/node_modules/send/node_modules/ms/readme.md new file mode 100644 index 0000000..bb76729 --- /dev/null +++ b/homework7/project_express/node_modules/send/node_modules/ms/readme.md @@ -0,0 +1,60 @@ +# ms + +[![Build Status](https://travis-ci.org/zeit/ms.svg?branch=master)](https://travis-ci.org/zeit/ms) +[![Slack Channel](http://zeit-slackin.now.sh/badge.svg)](https://zeit.chat/) + +Use this package to easily convert various time formats to milliseconds. + +## Examples + +```js +ms('2 days') // 172800000 +ms('1d') // 86400000 +ms('10h') // 36000000 +ms('2.5 hrs') // 9000000 +ms('2h') // 7200000 +ms('1m') // 60000 +ms('5s') // 5000 +ms('1y') // 31557600000 +ms('100') // 100 +ms('-3 days') // -259200000 +ms('-1h') // -3600000 +ms('-200') // -200 +``` + +### Convert from Milliseconds + +```js +ms(60000) // "1m" +ms(2 * 60000) // "2m" +ms(-3 * 60000) // "-3m" +ms(ms('10 hours')) // "10h" +``` + +### Time Format Written-Out + +```js +ms(60000, { long: true }) // "1 minute" +ms(2 * 60000, { long: true }) // "2 minutes" +ms(-3 * 60000, { long: true }) // "-3 minutes" +ms(ms('10 hours'), { long: true }) // "10 hours" +``` + +## Features + +- Works both in [Node.js](https://nodejs.org) and in the browser +- If a number is supplied to `ms`, a string with a unit is returned +- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`) +- If you pass a string with a number and a valid unit, the number of equivalent milliseconds is returned + +## Related Packages + +- [ms.macro](https://github.com/knpwrs/ms.macro) - Run `ms` as a macro at build-time. + +## Caught a Bug? + +1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device +2. Link the package to the global module directory: `npm link` +3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, Node.js will now use your clone of ms! + +As always, you can run the tests using: `npm test` diff --git a/homework7/project_express/node_modules/send/package.json b/homework7/project_express/node_modules/send/package.json new file mode 100644 index 0000000..4a6d66f --- /dev/null +++ b/homework7/project_express/node_modules/send/package.json @@ -0,0 +1,106 @@ +{ + "_from": "send@0.17.1", + "_id": "send@0.17.1", + "_inBundle": false, + "_integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "_location": "/send", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "send@0.17.1", + "name": "send", + "escapedName": "send", + "rawSpec": "0.17.1", + "saveSpec": null, + "fetchSpec": "0.17.1" + }, + "_requiredBy": [ + "/express", + "/serve-static" + ], + "_resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "_shasum": "c1d8b059f7900f7466dd4938bdc44e11ddb376c8", + "_spec": "send@0.17.1", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\express", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "bugs": { + "url": "https://github.com/pillarjs/send/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "James Wyatt Cready", + "email": "jcready@gmail.com" + }, + { + "name": "Jesús Leganés Combarro", + "email": "piranna@gmail.com" + } + ], + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "deprecated": false, + "description": "Better streaming static file server with Range and conditional-GET support", + "devDependencies": { + "after": "0.8.2", + "eslint": "5.16.0", + "eslint-config-standard": "12.0.0", + "eslint-plugin-import": "2.17.2", + "eslint-plugin-markdown": "1.0.0", + "eslint-plugin-node": "8.0.1", + "eslint-plugin-promise": "4.1.1", + "eslint-plugin-standard": "4.0.0", + "istanbul": "0.4.5", + "mocha": "6.1.4", + "supertest": "4.0.2" + }, + "engines": { + "node": ">= 0.8.0" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "README.md", + "index.js" + ], + "homepage": "https://github.com/pillarjs/send#readme", + "keywords": [ + "static", + "file", + "server" + ], + "license": "MIT", + "name": "send", + "repository": { + "type": "git", + "url": "git+https://github.com/pillarjs/send.git" + }, + "scripts": { + "lint": "eslint --plugin markdown --ext js,md .", + "test": "mocha --check-leaks --reporter spec --bail", + "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --check-leaks --reporter spec", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --check-leaks --reporter dot" + }, + "version": "0.17.1" +} diff --git a/homework7/project_express/node_modules/serve-static/HISTORY.md b/homework7/project_express/node_modules/serve-static/HISTORY.md new file mode 100644 index 0000000..7203e4f --- /dev/null +++ b/homework7/project_express/node_modules/serve-static/HISTORY.md @@ -0,0 +1,451 @@ +1.14.1 / 2019-05-10 +=================== + + * Set stricter CSP header in redirect response + * deps: send@0.17.1 + - deps: range-parser@~1.2.1 + +1.14.0 / 2019-05-07 +=================== + + * deps: parseurl@~1.3.3 + * deps: send@0.17.0 + - deps: http-errors@~1.7.2 + - deps: mime@1.6.0 + - deps: ms@2.1.1 + - deps: statuses@~1.5.0 + - perf: remove redundant `path.normalize` call + +1.13.2 / 2018-02-07 +=================== + + * Fix incorrect end tag in redirects + * deps: encodeurl@~1.0.2 + - Fix encoding `%` as last character + * deps: send@0.16.2 + - deps: depd@~1.1.2 + - deps: encodeurl@~1.0.2 + - deps: statuses@~1.4.0 + +1.13.1 / 2017-09-29 +=================== + + * Fix regression when `root` is incorrectly set to a file + * deps: send@0.16.1 + +1.13.0 / 2017-09-27 +=================== + + * deps: send@0.16.0 + - Add 70 new types for file extensions + - Add `immutable` option + - Fix missing `` in default error & redirects + - Set charset as "UTF-8" for .js and .json + - Use instance methods on steam to check for listeners + - deps: mime@1.4.1 + - perf: improve path validation speed + +1.12.6 / 2017-09-22 +=================== + + * deps: send@0.15.6 + - deps: debug@2.6.9 + - perf: improve `If-Match` token parsing + * perf: improve slash collapsing + +1.12.5 / 2017-09-21 +=================== + + * deps: parseurl@~1.3.2 + - perf: reduce overhead for full URLs + - perf: unroll the "fast-path" `RegExp` + * deps: send@0.15.5 + - Fix handling of modified headers with invalid dates + - deps: etag@~1.8.1 + - deps: fresh@0.5.2 + +1.12.4 / 2017-08-05 +=================== + + * deps: send@0.15.4 + - deps: debug@2.6.8 + - deps: depd@~1.1.1 + - deps: http-errors@~1.6.2 + +1.12.3 / 2017-05-16 +=================== + + * deps: send@0.15.3 + - deps: debug@2.6.7 + +1.12.2 / 2017-04-26 +=================== + + * deps: send@0.15.2 + - deps: debug@2.6.4 + +1.12.1 / 2017-03-04 +=================== + + * deps: send@0.15.1 + - Fix issue when `Date.parse` does not return `NaN` on invalid date + - Fix strict violation in broken environments + +1.12.0 / 2017-02-25 +=================== + + * Send complete HTML document in redirect response + * Set default CSP header in redirect response + * deps: send@0.15.0 + - Fix false detection of `no-cache` request directive + - Fix incorrect result when `If-None-Match` has both `*` and ETags + - Fix weak `ETag` matching to match spec + - Remove usage of `res._headers` private field + - Support `If-Match` and `If-Unmodified-Since` headers + - Use `res.getHeaderNames()` when available + - Use `res.headersSent` when available + - deps: debug@2.6.1 + - deps: etag@~1.8.0 + - deps: fresh@0.5.0 + - deps: http-errors@~1.6.1 + +1.11.2 / 2017-01-23 +=================== + + * deps: send@0.14.2 + - deps: http-errors@~1.5.1 + - deps: ms@0.7.2 + - deps: statuses@~1.3.1 + +1.11.1 / 2016-06-10 +=================== + + * Fix redirect error when `req.url` contains raw non-URL characters + * deps: send@0.14.1 + +1.11.0 / 2016-06-07 +=================== + + * Use status code 301 for redirects + * deps: send@0.14.0 + - Add `acceptRanges` option + - Add `cacheControl` option + - Attempt to combine multiple ranges into single range + - Correctly inherit from `Stream` class + - Fix `Content-Range` header in 416 responses when using `start`/`end` options + - Fix `Content-Range` header missing from default 416 responses + - Ignore non-byte `Range` headers + - deps: http-errors@~1.5.0 + - deps: range-parser@~1.2.0 + - deps: statuses@~1.3.0 + - perf: remove argument reassignment + +1.10.3 / 2016-05-30 +=================== + + * deps: send@0.13.2 + - Fix invalid `Content-Type` header when `send.mime.default_type` unset + +1.10.2 / 2016-01-19 +=================== + + * deps: parseurl@~1.3.1 + - perf: enable strict mode + +1.10.1 / 2016-01-16 +=================== + + * deps: escape-html@~1.0.3 + - perf: enable strict mode + - perf: optimize string replacement + - perf: use faster string coercion + * deps: send@0.13.1 + - deps: depd@~1.1.0 + - deps: destroy@~1.0.4 + - deps: escape-html@~1.0.3 + - deps: range-parser@~1.0.3 + +1.10.0 / 2015-06-17 +=================== + + * Add `fallthrough` option + - Allows declaring this middleware is the final destination + - Provides better integration with Express patterns + * Fix reading options from options prototype + * Improve the default redirect response headers + * deps: escape-html@1.0.2 + * deps: send@0.13.0 + - Allow Node.js HTTP server to set `Date` response header + - Fix incorrectly removing `Content-Location` on 304 response + - Improve the default redirect response headers + - Send appropriate headers on default error response + - Use `http-errors` for standard emitted errors + - Use `statuses` instead of `http` module for status messages + - deps: escape-html@1.0.2 + - deps: etag@~1.7.0 + - deps: fresh@0.3.0 + - deps: on-finished@~2.3.0 + - perf: enable strict mode + - perf: remove unnecessary array allocations + * perf: enable strict mode + * perf: remove argument reassignment + +1.9.3 / 2015-05-14 +================== + + * deps: send@0.12.3 + - deps: debug@~2.2.0 + - deps: depd@~1.0.1 + - deps: etag@~1.6.0 + - deps: ms@0.7.1 + - deps: on-finished@~2.2.1 + +1.9.2 / 2015-03-14 +================== + + * deps: send@0.12.2 + - Throw errors early for invalid `extensions` or `index` options + - deps: debug@~2.1.3 + +1.9.1 / 2015-02-17 +================== + + * deps: send@0.12.1 + - Fix regression sending zero-length files + +1.9.0 / 2015-02-16 +================== + + * deps: send@0.12.0 + - Always read the stat size from the file + - Fix mutating passed-in `options` + - deps: mime@1.3.4 + +1.8.1 / 2015-01-20 +================== + + * Fix redirect loop in Node.js 0.11.14 + * deps: send@0.11.1 + - Fix root path disclosure + +1.8.0 / 2015-01-05 +================== + + * deps: send@0.11.0 + - deps: debug@~2.1.1 + - deps: etag@~1.5.1 + - deps: ms@0.7.0 + - deps: on-finished@~2.2.0 + +1.7.2 / 2015-01-02 +================== + + * Fix potential open redirect when mounted at root + +1.7.1 / 2014-10-22 +================== + + * deps: send@0.10.1 + - deps: on-finished@~2.1.1 + +1.7.0 / 2014-10-15 +================== + + * deps: send@0.10.0 + - deps: debug@~2.1.0 + - deps: depd@~1.0.0 + - deps: etag@~1.5.0 + +1.6.5 / 2015-02-04 +================== + + * Fix potential open redirect when mounted at root + - Back-ported from v1.7.2 + +1.6.4 / 2014-10-08 +================== + + * Fix redirect loop when index file serving disabled + +1.6.3 / 2014-09-24 +================== + + * deps: send@0.9.3 + - deps: etag@~1.4.0 + +1.6.2 / 2014-09-15 +================== + + * deps: send@0.9.2 + - deps: depd@0.4.5 + - deps: etag@~1.3.1 + - deps: range-parser@~1.0.2 + +1.6.1 / 2014-09-07 +================== + + * deps: send@0.9.1 + - deps: fresh@0.2.4 + +1.6.0 / 2014-09-07 +================== + + * deps: send@0.9.0 + - Add `lastModified` option + - Use `etag` to generate `ETag` header + - deps: debug@~2.0.0 + +1.5.4 / 2014-09-04 +================== + + * deps: send@0.8.5 + - Fix a path traversal issue when using `root` + - Fix malicious path detection for empty string path + +1.5.3 / 2014-08-17 +================== + + * deps: send@0.8.3 + +1.5.2 / 2014-08-14 +================== + + * deps: send@0.8.2 + - Work around `fd` leak in Node.js 0.10 for `fs.ReadStream` + +1.5.1 / 2014-08-09 +================== + + * Fix parsing of weird `req.originalUrl` values + * deps: parseurl@~1.3.0 + * deps: utils-merge@1.0.0 + +1.5.0 / 2014-08-05 +================== + + * deps: send@0.8.1 + - Add `extensions` option + +1.4.4 / 2014-08-04 +================== + + * deps: send@0.7.4 + - Fix serving index files without root dir + +1.4.3 / 2014-07-29 +================== + + * deps: send@0.7.3 + - Fix incorrect 403 on Windows and Node.js 0.11 + +1.4.2 / 2014-07-27 +================== + + * deps: send@0.7.2 + - deps: depd@0.4.4 + +1.4.1 / 2014-07-26 +================== + + * deps: send@0.7.1 + - deps: depd@0.4.3 + +1.4.0 / 2014-07-21 +================== + + * deps: parseurl@~1.2.0 + - Cache URLs based on original value + - Remove no-longer-needed URL mis-parse work-around + - Simplify the "fast-path" `RegExp` + * deps: send@0.7.0 + - Add `dotfiles` option + - deps: debug@1.0.4 + - deps: depd@0.4.2 + +1.3.2 / 2014-07-11 +================== + + * deps: send@0.6.0 + - Cap `maxAge` value to 1 year + - deps: debug@1.0.3 + +1.3.1 / 2014-07-09 +================== + + * deps: parseurl@~1.1.3 + - faster parsing of href-only URLs + +1.3.0 / 2014-06-28 +================== + + * Add `setHeaders` option + * Include HTML link in redirect response + * deps: send@0.5.0 + - Accept string for `maxAge` (converted by `ms`) + +1.2.3 / 2014-06-11 +================== + + * deps: send@0.4.3 + - Do not throw un-catchable error on file open race condition + - Use `escape-html` for HTML escaping + - deps: debug@1.0.2 + - deps: finished@1.2.2 + - deps: fresh@0.2.2 + +1.2.2 / 2014-06-09 +================== + + * deps: send@0.4.2 + - fix "event emitter leak" warnings + - deps: debug@1.0.1 + - deps: finished@1.2.1 + +1.2.1 / 2014-06-02 +================== + + * use `escape-html` for escaping + * deps: send@0.4.1 + - Send `max-age` in `Cache-Control` in correct format + +1.2.0 / 2014-05-29 +================== + + * deps: send@0.4.0 + - Calculate ETag with md5 for reduced collisions + - Fix wrong behavior when index file matches directory + - Ignore stream errors after request ends + - Skip directories in index file search + - deps: debug@0.8.1 + +1.1.0 / 2014-04-24 +================== + + * Accept options directly to `send` module + * deps: send@0.3.0 + +1.0.4 / 2014-04-07 +================== + + * Resolve relative paths at middleware setup + * Use parseurl to parse the URL from request + +1.0.3 / 2014-03-20 +================== + + * Do not rely on connect-like environments + +1.0.2 / 2014-03-06 +================== + + * deps: send@0.2.0 + +1.0.1 / 2014-03-05 +================== + + * Add mime export for back-compat + +1.0.0 / 2014-03-05 +================== + + * Genesis from `connect` diff --git a/homework7/project_express/node_modules/serve-static/LICENSE b/homework7/project_express/node_modules/serve-static/LICENSE new file mode 100644 index 0000000..cbe62e8 --- /dev/null +++ b/homework7/project_express/node_modules/serve-static/LICENSE @@ -0,0 +1,25 @@ +(The MIT License) + +Copyright (c) 2010 Sencha Inc. +Copyright (c) 2011 LearnBoost +Copyright (c) 2011 TJ Holowaychuk +Copyright (c) 2014-2016 Douglas Christopher Wilson + +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/homework7/project_express/node_modules/serve-static/README.md b/homework7/project_express/node_modules/serve-static/README.md new file mode 100644 index 0000000..7cce428 --- /dev/null +++ b/homework7/project_express/node_modules/serve-static/README.md @@ -0,0 +1,259 @@ +# serve-static + +[![NPM Version][npm-version-image]][npm-url] +[![NPM Downloads][npm-downloads-image]][npm-url] +[![Linux Build][travis-image]][travis-url] +[![Windows Build][appveyor-image]][appveyor-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +## Install + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```sh +$ npm install serve-static +``` + +## API + + + +```js +var serveStatic = require('serve-static') +``` + +### serveStatic(root, options) + +Create a new middleware function to serve files from within a given root +directory. The file to serve will be determined by combining `req.url` +with the provided root directory. When a file is not found, instead of +sending a 404 response, this module will instead call `next()` to move on +to the next middleware, allowing for stacking and fall-backs. + +#### Options + +##### acceptRanges + +Enable or disable accepting ranged requests, defaults to true. +Disabling this will not send `Accept-Ranges` and ignore the contents +of the `Range` request header. + +##### cacheControl + +Enable or disable setting `Cache-Control` response header, defaults to +true. Disabling this will ignore the `immutable` and `maxAge` options. + +##### dotfiles + + Set how "dotfiles" are treated when encountered. A dotfile is a file +or directory that begins with a dot ("."). Note this check is done on +the path itself without checking if the path actually exists on the +disk. If `root` is specified, only the dotfiles above the root are +checked (i.e. the root itself can be within a dotfile when set +to "deny"). + + - `'allow'` No special treatment for dotfiles. + - `'deny'` Deny a request for a dotfile and 403/`next()`. + - `'ignore'` Pretend like the dotfile does not exist and 404/`next()`. + +The default value is similar to `'ignore'`, with the exception that this +default will not ignore the files within a directory that begins with a dot. + +##### etag + +Enable or disable etag generation, defaults to true. + +##### extensions + +Set file extension fallbacks. When set, if a file is not found, the given +extensions will be added to the file name and search for. The first that +exists will be served. Example: `['html', 'htm']`. + +The default value is `false`. + +##### fallthrough + +Set the middleware to have client errors fall-through as just unhandled +requests, otherwise forward a client error. The difference is that client +errors like a bad request or a request to a non-existent file will cause +this middleware to simply `next()` to your next middleware when this value +is `true`. When this value is `false`, these errors (even 404s), will invoke +`next(err)`. + +Typically `true` is desired such that multiple physical directories can be +mapped to the same web address or for routes to fill in non-existent files. + +The value `false` can be used if this middleware is mounted at a path that +is designed to be strictly a single file system directory, which allows for +short-circuiting 404s for less overhead. This middleware will also reply to +all methods. + +The default value is `true`. + +##### immutable + +Enable or disable the `immutable` directive in the `Cache-Control` response +header, defaults to `false`. If set to `true`, the `maxAge` option should +also be specified to enable caching. The `immutable` directive will prevent +supported clients from making conditional requests during the life of the +`maxAge` option to check if the file has changed. + +##### index + +By default this module will send "index.html" files in response to a request +on a directory. To disable this set `false` or to supply a new index pass a +string or an array in preferred order. + +##### lastModified + +Enable or disable `Last-Modified` header, defaults to true. Uses the file +system's last modified value. + +##### maxAge + +Provide a max-age in milliseconds for http caching, defaults to 0. This +can also be a string accepted by the [ms](https://www.npmjs.org/package/ms#readme) +module. + +##### redirect + +Redirect to trailing "/" when the pathname is a dir. Defaults to `true`. + +##### setHeaders + +Function to set custom headers on response. Alterations to the headers need to +occur synchronously. The function is called as `fn(res, path, stat)`, where +the arguments are: + + - `res` the response object + - `path` the file path that is being sent + - `stat` the stat object of the file that is being sent + +## Examples + +### Serve files with vanilla node.js http server + +```js +var finalhandler = require('finalhandler') +var http = require('http') +var serveStatic = require('serve-static') + +// Serve up public/ftp folder +var serve = serveStatic('public/ftp', { 'index': ['index.html', 'index.htm'] }) + +// Create server +var server = http.createServer(function onRequest (req, res) { + serve(req, res, finalhandler(req, res)) +}) + +// Listen +server.listen(3000) +``` + +### Serve all files as downloads + +```js +var contentDisposition = require('content-disposition') +var finalhandler = require('finalhandler') +var http = require('http') +var serveStatic = require('serve-static') + +// Serve up public/ftp folder +var serve = serveStatic('public/ftp', { + 'index': false, + 'setHeaders': setHeaders +}) + +// Set header to force download +function setHeaders (res, path) { + res.setHeader('Content-Disposition', contentDisposition(path)) +} + +// Create server +var server = http.createServer(function onRequest (req, res) { + serve(req, res, finalhandler(req, res)) +}) + +// Listen +server.listen(3000) +``` + +### Serving using express + +#### Simple + +This is a simple example of using Express. + +```js +var express = require('express') +var serveStatic = require('serve-static') + +var app = express() + +app.use(serveStatic('public/ftp', { 'index': ['default.html', 'default.htm'] })) +app.listen(3000) +``` + +#### Multiple roots + +This example shows a simple way to search through multiple directories. +Files are look for in `public-optimized/` first, then `public/` second as +a fallback. + +```js +var express = require('express') +var path = require('path') +var serveStatic = require('serve-static') + +var app = express() + +app.use(serveStatic(path.join(__dirname, 'public-optimized'))) +app.use(serveStatic(path.join(__dirname, 'public'))) +app.listen(3000) +``` + +#### Different settings for paths + +This example shows how to set a different max age depending on the served +file type. In this example, HTML files are not cached, while everything else +is for 1 day. + +```js +var express = require('express') +var path = require('path') +var serveStatic = require('serve-static') + +var app = express() + +app.use(serveStatic(path.join(__dirname, 'public'), { + maxAge: '1d', + setHeaders: setCustomCacheControl +})) + +app.listen(3000) + +function setCustomCacheControl (res, path) { + if (serveStatic.mime.lookup(path) === 'text/html') { + // Custom Cache-Control for HTML files + res.setHeader('Cache-Control', 'public, max-age=0') + } +} +``` + +## License + +[MIT](LICENSE) + +[appveyor-image]: https://badgen.net/appveyor/ci/dougwilson/serve-static/master?label=windows +[appveyor-url]: https://ci.appveyor.com/project/dougwilson/serve-static +[coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/serve-static/master +[coveralls-url]: https://coveralls.io/r/expressjs/serve-static?branch=master +[node-image]: https://badgen.net/npm/node/serve-static +[node-url]: https://nodejs.org/en/download/ +[npm-downloads-image]: https://badgen.net/npm/dm/serve-static +[npm-url]: https://npmjs.org/package/serve-static +[npm-version-image]: https://badgen.net/npm/v/serve-static +[travis-image]: https://badgen.net/travis/expressjs/serve-static/master?label=linux +[travis-url]: https://travis-ci.org/expressjs/serve-static diff --git a/homework7/project_express/node_modules/serve-static/index.js b/homework7/project_express/node_modules/serve-static/index.js new file mode 100644 index 0000000..b7d3984 --- /dev/null +++ b/homework7/project_express/node_modules/serve-static/index.js @@ -0,0 +1,210 @@ +/*! + * serve-static + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * Copyright(c) 2014-2016 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var encodeUrl = require('encodeurl') +var escapeHtml = require('escape-html') +var parseUrl = require('parseurl') +var resolve = require('path').resolve +var send = require('send') +var url = require('url') + +/** + * Module exports. + * @public + */ + +module.exports = serveStatic +module.exports.mime = send.mime + +/** + * @param {string} root + * @param {object} [options] + * @return {function} + * @public + */ + +function serveStatic (root, options) { + if (!root) { + throw new TypeError('root path required') + } + + if (typeof root !== 'string') { + throw new TypeError('root path must be a string') + } + + // copy options object + var opts = Object.create(options || null) + + // fall-though + var fallthrough = opts.fallthrough !== false + + // default redirect + var redirect = opts.redirect !== false + + // headers listener + var setHeaders = opts.setHeaders + + if (setHeaders && typeof setHeaders !== 'function') { + throw new TypeError('option setHeaders must be function') + } + + // setup options for send + opts.maxage = opts.maxage || opts.maxAge || 0 + opts.root = resolve(root) + + // construct directory listener + var onDirectory = redirect + ? createRedirectDirectoryListener() + : createNotFoundDirectoryListener() + + return function serveStatic (req, res, next) { + if (req.method !== 'GET' && req.method !== 'HEAD') { + if (fallthrough) { + return next() + } + + // method not allowed + res.statusCode = 405 + res.setHeader('Allow', 'GET, HEAD') + res.setHeader('Content-Length', '0') + res.end() + return + } + + var forwardError = !fallthrough + var originalUrl = parseUrl.original(req) + var path = parseUrl(req).pathname + + // make sure redirect occurs at mount + if (path === '/' && originalUrl.pathname.substr(-1) !== '/') { + path = '' + } + + // create send stream + var stream = send(req, path, opts) + + // add directory handler + stream.on('directory', onDirectory) + + // add headers listener + if (setHeaders) { + stream.on('headers', setHeaders) + } + + // add file listener for fallthrough + if (fallthrough) { + stream.on('file', function onFile () { + // once file is determined, always forward error + forwardError = true + }) + } + + // forward errors + stream.on('error', function error (err) { + if (forwardError || !(err.statusCode < 500)) { + next(err) + return + } + + next() + }) + + // pipe + stream.pipe(res) + } +} + +/** + * Collapse all leading slashes into a single slash + * @private + */ +function collapseLeadingSlashes (str) { + for (var i = 0; i < str.length; i++) { + if (str.charCodeAt(i) !== 0x2f /* / */) { + break + } + } + + return i > 1 + ? '/' + str.substr(i) + : str +} + +/** + * Create a minimal HTML document. + * + * @param {string} title + * @param {string} body + * @private + */ + +function createHtmlDocument (title, body) { + return '\n' + + '\n' + + '\n' + + '\n' + + '' + title + '\n' + + '\n' + + '\n' + + '
' + body + '
\n' + + '\n' + + '\n' +} + +/** + * Create a directory listener that just 404s. + * @private + */ + +function createNotFoundDirectoryListener () { + return function notFound () { + this.error(404) + } +} + +/** + * Create a directory listener that performs a redirect. + * @private + */ + +function createRedirectDirectoryListener () { + return function redirect (res) { + if (this.hasTrailingSlash()) { + this.error(404) + return + } + + // get original URL + var originalUrl = parseUrl.original(this.req) + + // append trailing slash + originalUrl.path = null + originalUrl.pathname = collapseLeadingSlashes(originalUrl.pathname + '/') + + // reformat the URL + var loc = encodeUrl(url.format(originalUrl)) + var doc = createHtmlDocument('Redirecting', 'Redirecting to ' + + escapeHtml(loc) + '') + + // send redirect response + res.statusCode = 301 + res.setHeader('Content-Type', 'text/html; charset=UTF-8') + res.setHeader('Content-Length', Buffer.byteLength(doc)) + res.setHeader('Content-Security-Policy', "default-src 'none'") + res.setHeader('X-Content-Type-Options', 'nosniff') + res.setHeader('Location', loc) + res.end(doc) + } +} diff --git a/homework7/project_express/node_modules/serve-static/package.json b/homework7/project_express/node_modules/serve-static/package.json new file mode 100644 index 0000000..0a0a8aa --- /dev/null +++ b/homework7/project_express/node_modules/serve-static/package.json @@ -0,0 +1,77 @@ +{ + "_from": "serve-static@1.14.1", + "_id": "serve-static@1.14.1", + "_inBundle": false, + "_integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "_location": "/serve-static", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "serve-static@1.14.1", + "name": "serve-static", + "escapedName": "serve-static", + "rawSpec": "1.14.1", + "saveSpec": null, + "fetchSpec": "1.14.1" + }, + "_requiredBy": [ + "/express" + ], + "_resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "_shasum": "666e636dc4f010f7ef29970a88a674320898b2f9", + "_spec": "serve-static@1.14.1", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\express", + "author": { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + "bugs": { + "url": "https://github.com/expressjs/serve-static/issues" + }, + "bundleDependencies": false, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "deprecated": false, + "description": "Serve static files", + "devDependencies": { + "eslint": "5.16.0", + "eslint-config-standard": "12.0.0", + "eslint-plugin-import": "2.17.2", + "eslint-plugin-markdown": "1.0.0", + "eslint-plugin-node": "8.0.1", + "eslint-plugin-promise": "4.1.1", + "eslint-plugin-standard": "4.0.0", + "istanbul": "0.4.5", + "mocha": "6.1.4", + "safe-buffer": "5.1.2", + "supertest": "4.0.2" + }, + "engines": { + "node": ">= 0.8.0" + }, + "files": [ + "LICENSE", + "HISTORY.md", + "index.js" + ], + "homepage": "https://github.com/expressjs/serve-static#readme", + "license": "MIT", + "name": "serve-static", + "repository": { + "type": "git", + "url": "git+https://github.com/expressjs/serve-static.git" + }, + "scripts": { + "lint": "eslint --plugin markdown --ext js,md .", + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "version": "node scripts/version-history.js && git add HISTORY.md" + }, + "version": "1.14.1" +} diff --git a/homework7/project_express/node_modules/setprototypeof/LICENSE b/homework7/project_express/node_modules/setprototypeof/LICENSE new file mode 100644 index 0000000..61afa2f --- /dev/null +++ b/homework7/project_express/node_modules/setprototypeof/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2015, Wes Todd + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/homework7/project_express/node_modules/setprototypeof/README.md b/homework7/project_express/node_modules/setprototypeof/README.md new file mode 100644 index 0000000..f120044 --- /dev/null +++ b/homework7/project_express/node_modules/setprototypeof/README.md @@ -0,0 +1,31 @@ +# Polyfill for `Object.setPrototypeOf` + +[![NPM Version](https://img.shields.io/npm/v/setprototypeof.svg)](https://npmjs.org/package/setprototypeof) +[![NPM Downloads](https://img.shields.io/npm/dm/setprototypeof.svg)](https://npmjs.org/package/setprototypeof) +[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](https://github.com/standard/standard) + +A simple cross platform implementation to set the prototype of an instianted object. Supports all modern browsers and at least back to IE8. + +## Usage: + +``` +$ npm install --save setprototypeof +``` + +```javascript +var setPrototypeOf = require('setprototypeof') + +var obj = {} +setPrototypeOf(obj, { + foo: function () { + return 'bar' + } +}) +obj.foo() // bar +``` + +TypeScript is also supported: + +```typescript +import setPrototypeOf = require('setprototypeof') +``` diff --git a/homework7/project_express/node_modules/setprototypeof/index.d.ts b/homework7/project_express/node_modules/setprototypeof/index.d.ts new file mode 100644 index 0000000..f108ecd --- /dev/null +++ b/homework7/project_express/node_modules/setprototypeof/index.d.ts @@ -0,0 +1,2 @@ +declare function setPrototypeOf(o: any, proto: object | null): any; +export = setPrototypeOf; diff --git a/homework7/project_express/node_modules/setprototypeof/index.js b/homework7/project_express/node_modules/setprototypeof/index.js new file mode 100644 index 0000000..81fd5d7 --- /dev/null +++ b/homework7/project_express/node_modules/setprototypeof/index.js @@ -0,0 +1,17 @@ +'use strict' +/* eslint no-proto: 0 */ +module.exports = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array ? setProtoOf : mixinProperties) + +function setProtoOf (obj, proto) { + obj.__proto__ = proto + return obj +} + +function mixinProperties (obj, proto) { + for (var prop in proto) { + if (!obj.hasOwnProperty(prop)) { + obj[prop] = proto[prop] + } + } + return obj +} diff --git a/homework7/project_express/node_modules/setprototypeof/package.json b/homework7/project_express/node_modules/setprototypeof/package.json new file mode 100644 index 0000000..bb3daca --- /dev/null +++ b/homework7/project_express/node_modules/setprototypeof/package.json @@ -0,0 +1,64 @@ +{ + "_from": "setprototypeof@1.1.1", + "_id": "setprototypeof@1.1.1", + "_inBundle": false, + "_integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "_location": "/setprototypeof", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "setprototypeof@1.1.1", + "name": "setprototypeof", + "escapedName": "setprototypeof", + "rawSpec": "1.1.1", + "saveSpec": null, + "fetchSpec": "1.1.1" + }, + "_requiredBy": [ + "/express", + "/http-errors" + ], + "_resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "_shasum": "7e95acb24aa92f5885e0abef5ba131330d4ae683", + "_spec": "setprototypeof@1.1.1", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\express", + "author": { + "name": "Wes Todd" + }, + "bugs": { + "url": "https://github.com/wesleytodd/setprototypeof/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "A small polyfill for Object.setprototypeof", + "devDependencies": { + "mocha": "^5.2.0", + "standard": "^12.0.1" + }, + "homepage": "https://github.com/wesleytodd/setprototypeof", + "keywords": [ + "polyfill", + "object", + "setprototypeof" + ], + "license": "ISC", + "main": "index.js", + "name": "setprototypeof", + "repository": { + "type": "git", + "url": "git+https://github.com/wesleytodd/setprototypeof.git" + }, + "scripts": { + "node010": "NODE_VER=0.10 MOCHA_VER=3 npm run testversion", + "node11": "NODE_VER=11 npm run testversion", + "node4": "NODE_VER=4 npm run testversion", + "node6": "NODE_VER=6 npm run testversion", + "node9": "NODE_VER=9 npm run testversion", + "test": "standard && mocha", + "testallversions": "npm run node010 && npm run node4 && npm run node6 && npm run node9 && npm run node11", + "testversion": "docker run -it --rm -v $(PWD):/usr/src/app -w /usr/src/app node:${NODE_VER} npm install mocha@${MOCHA_VER:-latest} && npm t" + }, + "typings": "index.d.ts", + "version": "1.1.1" +} diff --git a/homework7/project_express/node_modules/setprototypeof/test/index.js b/homework7/project_express/node_modules/setprototypeof/test/index.js new file mode 100644 index 0000000..afeb4dd --- /dev/null +++ b/homework7/project_express/node_modules/setprototypeof/test/index.js @@ -0,0 +1,24 @@ +'use strict' +/* eslint-env mocha */ +/* eslint no-proto: 0 */ +var assert = require('assert') +var setPrototypeOf = require('..') + +describe('setProtoOf(obj, proto)', function () { + it('should merge objects', function () { + var obj = { a: 1, b: 2 } + var proto = { b: 3, c: 4 } + var mergeObj = setPrototypeOf(obj, proto) + + if (Object.getPrototypeOf) { + assert.strictEqual(Object.getPrototypeOf(obj), proto) + } else if ({ __proto__: [] } instanceof Array) { + assert.strictEqual(obj.__proto__, proto) + } else { + assert.strictEqual(obj.a, 1) + assert.strictEqual(obj.b, 2) + assert.strictEqual(obj.c, 4) + } + assert.strictEqual(mergeObj, obj) + }) +}) diff --git a/homework7/project_express/node_modules/simple-update-notifier/LICENSE b/homework7/project_express/node_modules/simple-update-notifier/LICENSE new file mode 100644 index 0000000..1e0b0c1 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Alex Brazier + +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/homework7/project_express/node_modules/simple-update-notifier/README.md b/homework7/project_express/node_modules/simple-update-notifier/README.md new file mode 100644 index 0000000..6061412 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/README.md @@ -0,0 +1,67 @@ +# simple-update-notifier [![GitHub stars](https://img.shields.io/github/stars/alexbrazier/simple-update-notifier?label=Star%20Project&style=social)](https://github.com/alexbrazier/simple-update-notifier/stargazers) + +[![CI](https://github.com/alexbrazier/simple-update-notifier/workflows/Build%20and%20Deploy/badge.svg)](https://github.com/alexbrazier/simple-update-notifier/actions) +[![Dependencies](https://img.shields.io/librariesio/release/npm/simple-update-notifier)](https://www.npmjs.com/package/simple-update-notifier?activeTab=dependencies) +[![npm](https://img.shields.io/npm/v/simple-update-notifier)](https://www.npmjs.com/package/simple-update-notifier) +[![npm bundle size](https://img.shields.io/bundlephobia/min/simple-update-notifier)](https://bundlephobia.com/result?p=simple-update-notifier) +[![npm downloads](https://img.shields.io/npm/dw/simple-update-notifier)](https://www.npmjs.com/package/simple-update-notifier) +[![License](https://img.shields.io/npm/l/simple-update-notifier)](./LICENSE) + +Simple update notifier to check for npm updates for cli applications. + +Demo in terminal showing an update is required + +Checks for updates for an npm module and outputs to the command line if there is one available. The result is cached for the specified time so it doesn't check every time the app runs. + +## Install + +```bash +npm install simple-update-notifier +OR +yarn add simple-update-notifier +``` + +## Usage + +```js +import updateNotifier from 'update-notifier'; +import packageJson from './package.json' assert { type: 'json' }; + +updateNotifier({ pkg: packageJson }); +``` + +### Options + +#### pkg + +Type: `object` + +##### name + +_Required_\ +Type: `string` + +##### version + +_Required_\ +Type: `string` + +#### updateCheckInterval + +Type: `number`\ +Default: `1000 * 60 * 60 * 24` _(1 day)_ +How often to check for updates. + +#### shouldNotifyInNpmScript + +Type: `boolean`\ +Default: `false` + +Allows notification to be shown when running as an npm script. + +#### distTag + +Type: `string`\ +Default: `'latest'` + +Which [dist-tag](https://docs.npmjs.com/adding-dist-tags-to-packages) to use to find the latest version. diff --git a/homework7/project_express/node_modules/simple-update-notifier/build/index.d.ts b/homework7/project_express/node_modules/simple-update-notifier/build/index.d.ts new file mode 100644 index 0000000..36cd5f4 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/build/index.d.ts @@ -0,0 +1,12 @@ +interface IUpdate { + pkg: { + name: string; + version: string; + }; + updateCheckInterval?: number; + shouldNotifyInNpmScript?: boolean; + distTag?: string; + alwaysRun?: boolean; +} +declare const simpleUpdateNotifier: (args: IUpdate) => Promise; +export { simpleUpdateNotifier as default }; diff --git a/homework7/project_express/node_modules/simple-update-notifier/build/index.js b/homework7/project_express/node_modules/simple-update-notifier/build/index.js new file mode 100644 index 0000000..ffa01fa --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/build/index.js @@ -0,0 +1,202 @@ +'use strict'; + +var process$1 = require('process'); +var semver = require('semver'); +var os = require('os'); +var path = require('path'); +var fs = require('fs'); +var https = require('https'); + +function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } + +var process__default = /*#__PURE__*/_interopDefaultLegacy(process$1); +var semver__default = /*#__PURE__*/_interopDefaultLegacy(semver); +var os__default = /*#__PURE__*/_interopDefaultLegacy(os); +var path__default = /*#__PURE__*/_interopDefaultLegacy(path); +var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs); +var https__default = /*#__PURE__*/_interopDefaultLegacy(https); + +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ + +function __awaiter(thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +} + +function __generator(thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +} + +var packageJson = process__default["default"].env.npm_package_json; +var userAgent = process__default["default"].env.npm_config_user_agent; +var isNpm6 = Boolean(userAgent && userAgent.startsWith('npm')); +var isNpm7 = Boolean(packageJson && packageJson.endsWith('package.json')); +var isNpm = isNpm6 || isNpm7; +var isYarn = Boolean(userAgent && userAgent.startsWith('yarn')); +var isNpmOrYarn = isNpm || isYarn; + +var homeDirectory = os__default["default"].homedir(); +var configDir = process.env.XDG_CONFIG_HOME || + path__default["default"].join(homeDirectory, '.config', 'simple-update-notifier'); +var getConfigFile = function (packageName) { + return path__default["default"].join(configDir, "".concat(packageName, ".json")); +}; +var createConfigDir = function () { + if (!fs__default["default"].existsSync(configDir)) { + fs__default["default"].mkdirSync(configDir, { recursive: true }); + } +}; +var getLastUpdate = function (packageName) { + var configFile = getConfigFile(packageName); + try { + if (!fs__default["default"].existsSync(configFile)) { + return undefined; + } + var file = JSON.parse(fs__default["default"].readFileSync(configFile, 'utf8')); + return file.lastUpdateCheck; + } + catch (_a) { + return undefined; + } +}; +var saveLastUpdate = function (packageName) { + var configFile = getConfigFile(packageName); + fs__default["default"].writeFileSync(configFile, JSON.stringify({ lastUpdateCheck: new Date().getTime() })); +}; + +var getDistVersion = function (packageName, distTag) { return __awaiter(void 0, void 0, void 0, function () { + var url; + return __generator(this, function (_a) { + url = "https://registry.npmjs.org/-/package/".concat(packageName, "/dist-tags"); + return [2 /*return*/, new Promise(function (resolve, reject) { + https__default["default"] + .get(url, function (res) { + var body = ''; + res.on('data', function (chunk) { return (body += chunk); }); + res.on('end', function () { + try { + var json = JSON.parse(body); + var version = json[distTag]; + if (!version) { + reject(new Error('Error getting version')); + } + resolve(version); + } + catch (_a) { + reject(new Error('Could not parse version response')); + } + }); + }) + .on('error', function (err) { return reject(err); }); + })]; + }); +}); }; + +var hasNewVersion = function (_a) { + var pkg = _a.pkg, _b = _a.updateCheckInterval, updateCheckInterval = _b === void 0 ? 1000 * 60 * 60 * 24 : _b, _c = _a.distTag, distTag = _c === void 0 ? 'latest' : _c, alwaysRun = _a.alwaysRun; + return __awaiter(void 0, void 0, void 0, function () { + var lastUpdateCheck, latestVersion; + return __generator(this, function (_d) { + switch (_d.label) { + case 0: + createConfigDir(); + lastUpdateCheck = getLastUpdate(pkg.name); + if (!(alwaysRun || + !lastUpdateCheck || + lastUpdateCheck < new Date().getTime() - updateCheckInterval)) return [3 /*break*/, 2]; + return [4 /*yield*/, getDistVersion(pkg.name, distTag)]; + case 1: + latestVersion = _d.sent(); + saveLastUpdate(pkg.name); + if (semver__default["default"].gt(latestVersion, pkg.version)) { + return [2 /*return*/, latestVersion]; + } + return [2 /*return*/, false]; + case 2: return [2 /*return*/, false]; + } + }); + }); +}; + +var borderedText = function (text) { + var lines = text.split('\n'); + var width = Math.max.apply(Math, lines.map(function (l) { return l.length; })); + var res = ["\u250C".concat('─'.repeat(width + 2), "\u2510")]; + for (var _i = 0, lines_1 = lines; _i < lines_1.length; _i++) { + var line = lines_1[_i]; + res.push("\u2502 ".concat(line.padEnd(width), " \u2502")); + } + res.push("\u2514".concat('─'.repeat(width + 2), "\u2518")); + return res.join('\n'); +}; + +var simpleUpdateNotifier = function (args) { return __awaiter(void 0, void 0, void 0, function () { + var latestVersion; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + if (!args.alwaysRun && + (!process.stdout.isTTY || (isNpmOrYarn && !args.shouldNotifyInNpmScript))) { + return [2 /*return*/]; + } + _b.label = 1; + case 1: + _b.trys.push([1, 3, , 4]); + return [4 /*yield*/, hasNewVersion(args)]; + case 2: + latestVersion = _b.sent(); + if (latestVersion) { + console.log(borderedText("New version of ".concat(args.pkg.name, " available!\nCurrent Version: ").concat(args.pkg.version, "\nLatest Version: ").concat(latestVersion))); + } + return [3 /*break*/, 4]; + case 3: + _b.sent(); + return [3 /*break*/, 4]; + case 4: return [2 /*return*/]; + } + }); +}); }; + +module.exports = simpleUpdateNotifier; diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver b/homework7/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver new file mode 100644 index 0000000..77443e7 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver @@ -0,0 +1,12 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../semver/bin/semver.js" "$@" +else + exec node "$basedir/../semver/bin/semver.js" "$@" +fi diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver.cmd b/homework7/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver.cmd new file mode 100644 index 0000000..9913fa9 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\semver\bin\semver.js" %* diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver.ps1 b/homework7/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver.ps1 new file mode 100644 index 0000000..314717a --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args + } else { + & "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../semver/bin/semver.js" $args + } else { + & "node$exe" "$basedir/../semver/bin/semver.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/CHANGELOG.md b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/CHANGELOG.md new file mode 100644 index 0000000..d366696 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/CHANGELOG.md @@ -0,0 +1,74 @@ +# changes log + +## 6.3.0 + +* Expose the token enum on the exports + +## 6.2.0 + +* Coerce numbers to strings when passed to semver.coerce() +* Add `rtl` option to coerce from right to left + +## 6.1.3 + +* Handle X-ranges properly in includePrerelease mode + +## 6.1.2 + +* Do not throw when testing invalid version strings + +## 6.1.1 + +* Add options support for semver.coerce() +* Handle undefined version passed to Range.test + +## 6.1.0 + +* Add semver.compareBuild function +* Support `*` in semver.intersects + +## 6.0 + +* Fix `intersects` logic. + + This is technically a bug fix, but since it is also a change to behavior + that may require users updating their code, it is marked as a major + version increment. + +## 5.7 + +* Add `minVersion` method + +## 5.6 + +* Move boolean `loose` param to an options object, with + backwards-compatibility protection. +* Add ability to opt out of special prerelease version handling with + the `includePrerelease` option flag. + +## 5.5 + +* Add version coercion capabilities + +## 5.4 + +* Add intersection checking + +## 5.3 + +* Add `minSatisfying` method + +## 5.2 + +* Add `prerelease(v)` that returns prerelease components + +## 5.1 + +* Add Backus-Naur for ranges +* Remove excessively cute inspection methods + +## 5.0 + +* Remove AMD/Browserified build artifacts +* Fix ltr and gtr when using the `*` range +* Fix for range `*` with a prerelease identifier diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/LICENSE b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/LICENSE new file mode 100644 index 0000000..19129e3 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/README.md b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/README.md new file mode 100644 index 0000000..1546458 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/README.md @@ -0,0 +1,499 @@ +semver(1) -- The semantic versioner for npm +=========================================== + +## Install + +```bash +npm install semver +```` + +## Usage + +As a node module: + +```js +const semver = require('semver') + +semver.valid('1.2.3') // '1.2.3' +semver.valid('a.b.c') // null +semver.clean(' =v1.2.3 ') // '1.2.3' +semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true +semver.gt('1.2.3', '9.8.7') // false +semver.lt('1.2.3', '9.8.7') // true +semver.minVersion('>=1.0.0') // '1.0.0' +semver.valid(semver.coerce('v2')) // '2.0.0' +semver.valid(semver.coerce('42.6.7.9.3-alpha')) // '42.6.7' +``` + +As a command-line utility: + +``` +$ semver -h + +A JavaScript implementation of the https://semver.org/ specification +Copyright Isaac Z. Schlueter + +Usage: semver [options] [ [...]] +Prints valid versions sorted by SemVer precedence + +Options: +-r --range + Print versions that match the specified range. + +-i --increment [] + Increment a version by the specified level. Level can + be one of: major, minor, patch, premajor, preminor, + prepatch, or prerelease. Default level is 'patch'. + Only one version may be specified. + +--preid + Identifier to be used to prefix premajor, preminor, + prepatch or prerelease version increments. + +-l --loose + Interpret versions and ranges loosely + +-p --include-prerelease + Always include prerelease versions in range matching + +-c --coerce + Coerce a string into SemVer if possible + (does not imply --loose) + +--rtl + Coerce version strings right to left + +--ltr + Coerce version strings left to right (default) + +Program exits successfully if any valid version satisfies +all supplied ranges, and prints all satisfying versions. + +If no satisfying versions are found, then exits failure. + +Versions are printed in ascending order, so supplying +multiple versions to the utility will just sort them. +``` + +## Versions + +A "version" is described by the `v2.0.0` specification found at +. + +A leading `"="` or `"v"` character is stripped off and ignored. + +## Ranges + +A `version range` is a set of `comparators` which specify versions +that satisfy the range. + +A `comparator` is composed of an `operator` and a `version`. The set +of primitive `operators` is: + +* `<` Less than +* `<=` Less than or equal to +* `>` Greater than +* `>=` Greater than or equal to +* `=` Equal. If no operator is specified, then equality is assumed, + so this operator is optional, but MAY be included. + +For example, the comparator `>=1.2.7` would match the versions +`1.2.7`, `1.2.8`, `2.5.3`, and `1.3.9`, but not the versions `1.2.6` +or `1.1.0`. + +Comparators can be joined by whitespace to form a `comparator set`, +which is satisfied by the **intersection** of all of the comparators +it includes. + +A range is composed of one or more comparator sets, joined by `||`. A +version matches a range if and only if every comparator in at least +one of the `||`-separated comparator sets is satisfied by the version. + +For example, the range `>=1.2.7 <1.3.0` would match the versions +`1.2.7`, `1.2.8`, and `1.2.99`, but not the versions `1.2.6`, `1.3.0`, +or `1.1.0`. + +The range `1.2.7 || >=1.2.9 <2.0.0` would match the versions `1.2.7`, +`1.2.9`, and `1.4.6`, but not the versions `1.2.8` or `2.0.0`. + +### Prerelease Tags + +If a version has a prerelease tag (for example, `1.2.3-alpha.3`) then +it will only be allowed to satisfy comparator sets if at least one +comparator with the same `[major, minor, patch]` tuple also has a +prerelease tag. + +For example, the range `>1.2.3-alpha.3` would be allowed to match the +version `1.2.3-alpha.7`, but it would *not* be satisfied by +`3.4.5-alpha.9`, even though `3.4.5-alpha.9` is technically "greater +than" `1.2.3-alpha.3` according to the SemVer sort rules. The version +range only accepts prerelease tags on the `1.2.3` version. The +version `3.4.5` *would* satisfy the range, because it does not have a +prerelease flag, and `3.4.5` is greater than `1.2.3-alpha.7`. + +The purpose for this behavior is twofold. First, prerelease versions +frequently are updated very quickly, and contain many breaking changes +that are (by the author's design) not yet fit for public consumption. +Therefore, by default, they are excluded from range matching +semantics. + +Second, a user who has opted into using a prerelease version has +clearly indicated the intent to use *that specific* set of +alpha/beta/rc versions. By including a prerelease tag in the range, +the user is indicating that they are aware of the risk. However, it +is still not appropriate to assume that they have opted into taking a +similar risk on the *next* set of prerelease versions. + +Note that this behavior can be suppressed (treating all prerelease +versions as if they were normal versions, for the purpose of range +matching) by setting the `includePrerelease` flag on the options +object to any +[functions](https://github.com/npm/node-semver#functions) that do +range matching. + +#### Prerelease Identifiers + +The method `.inc` takes an additional `identifier` string argument that +will append the value of the string as a prerelease identifier: + +```javascript +semver.inc('1.2.3', 'prerelease', 'beta') +// '1.2.4-beta.0' +``` + +command-line example: + +```bash +$ semver 1.2.3 -i prerelease --preid beta +1.2.4-beta.0 +``` + +Which then can be used to increment further: + +```bash +$ semver 1.2.4-beta.0 -i prerelease +1.2.4-beta.1 +``` + +### Advanced Range Syntax + +Advanced range syntax desugars to primitive comparators in +deterministic ways. + +Advanced ranges may be combined in the same way as primitive +comparators using white space or `||`. + +#### Hyphen Ranges `X.Y.Z - A.B.C` + +Specifies an inclusive set. + +* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4` + +If a partial version is provided as the first version in the inclusive +range, then the missing pieces are replaced with zeroes. + +* `1.2 - 2.3.4` := `>=1.2.0 <=2.3.4` + +If a partial version is provided as the second version in the +inclusive range, then all versions that start with the supplied parts +of the tuple are accepted, but nothing that would be greater than the +provided tuple parts. + +* `1.2.3 - 2.3` := `>=1.2.3 <2.4.0` +* `1.2.3 - 2` := `>=1.2.3 <3.0.0` + +#### X-Ranges `1.2.x` `1.X` `1.2.*` `*` + +Any of `X`, `x`, or `*` may be used to "stand in" for one of the +numeric values in the `[major, minor, patch]` tuple. + +* `*` := `>=0.0.0` (Any version satisfies) +* `1.x` := `>=1.0.0 <2.0.0` (Matching major version) +* `1.2.x` := `>=1.2.0 <1.3.0` (Matching major and minor versions) + +A partial version range is treated as an X-Range, so the special +character is in fact optional. + +* `""` (empty string) := `*` := `>=0.0.0` +* `1` := `1.x.x` := `>=1.0.0 <2.0.0` +* `1.2` := `1.2.x` := `>=1.2.0 <1.3.0` + +#### Tilde Ranges `~1.2.3` `~1.2` `~1` + +Allows patch-level changes if a minor version is specified on the +comparator. Allows minor-level changes if not. + +* `~1.2.3` := `>=1.2.3 <1.(2+1).0` := `>=1.2.3 <1.3.0` +* `~1.2` := `>=1.2.0 <1.(2+1).0` := `>=1.2.0 <1.3.0` (Same as `1.2.x`) +* `~1` := `>=1.0.0 <(1+1).0.0` := `>=1.0.0 <2.0.0` (Same as `1.x`) +* `~0.2.3` := `>=0.2.3 <0.(2+1).0` := `>=0.2.3 <0.3.0` +* `~0.2` := `>=0.2.0 <0.(2+1).0` := `>=0.2.0 <0.3.0` (Same as `0.2.x`) +* `~0` := `>=0.0.0 <(0+1).0.0` := `>=0.0.0 <1.0.0` (Same as `0.x`) +* `~1.2.3-beta.2` := `>=1.2.3-beta.2 <1.3.0` Note that prereleases in + the `1.2.3` version will be allowed, if they are greater than or + equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but + `1.2.4-beta.2` would not, because it is a prerelease of a + different `[major, minor, patch]` tuple. + +#### Caret Ranges `^1.2.3` `^0.2.5` `^0.0.4` + +Allows changes that do not modify the left-most non-zero element in the +`[major, minor, patch]` tuple. In other words, this allows patch and +minor updates for versions `1.0.0` and above, patch updates for +versions `0.X >=0.1.0`, and *no* updates for versions `0.0.X`. + +Many authors treat a `0.x` version as if the `x` were the major +"breaking-change" indicator. + +Caret ranges are ideal when an author may make breaking changes +between `0.2.4` and `0.3.0` releases, which is a common practice. +However, it presumes that there will *not* be breaking changes between +`0.2.4` and `0.2.5`. It allows for changes that are presumed to be +additive (but non-breaking), according to commonly observed practices. + +* `^1.2.3` := `>=1.2.3 <2.0.0` +* `^0.2.3` := `>=0.2.3 <0.3.0` +* `^0.0.3` := `>=0.0.3 <0.0.4` +* `^1.2.3-beta.2` := `>=1.2.3-beta.2 <2.0.0` Note that prereleases in + the `1.2.3` version will be allowed, if they are greater than or + equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but + `1.2.4-beta.2` would not, because it is a prerelease of a + different `[major, minor, patch]` tuple. +* `^0.0.3-beta` := `>=0.0.3-beta <0.0.4` Note that prereleases in the + `0.0.3` version *only* will be allowed, if they are greater than or + equal to `beta`. So, `0.0.3-pr.2` would be allowed. + +When parsing caret ranges, a missing `patch` value desugars to the +number `0`, but will allow flexibility within that value, even if the +major and minor versions are both `0`. + +* `^1.2.x` := `>=1.2.0 <2.0.0` +* `^0.0.x` := `>=0.0.0 <0.1.0` +* `^0.0` := `>=0.0.0 <0.1.0` + +A missing `minor` and `patch` values will desugar to zero, but also +allow flexibility within those values, even if the major version is +zero. + +* `^1.x` := `>=1.0.0 <2.0.0` +* `^0.x` := `>=0.0.0 <1.0.0` + +### Range Grammar + +Putting all this together, here is a Backus-Naur grammar for ranges, +for the benefit of parser authors: + +```bnf +range-set ::= range ( logical-or range ) * +logical-or ::= ( ' ' ) * '||' ( ' ' ) * +range ::= hyphen | simple ( ' ' simple ) * | '' +hyphen ::= partial ' - ' partial +simple ::= primitive | partial | tilde | caret +primitive ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial +partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )? +xr ::= 'x' | 'X' | '*' | nr +nr ::= '0' | ['1'-'9'] ( ['0'-'9'] ) * +tilde ::= '~' partial +caret ::= '^' partial +qualifier ::= ( '-' pre )? ( '+' build )? +pre ::= parts +build ::= parts +parts ::= part ( '.' part ) * +part ::= nr | [-0-9A-Za-z]+ +``` + +## Functions + +All methods and classes take a final `options` object argument. All +options in this object are `false` by default. The options supported +are: + +- `loose` Be more forgiving about not-quite-valid semver strings. + (Any resulting output will always be 100% strict compliant, of + course.) For backwards compatibility reasons, if the `options` + argument is a boolean value instead of an object, it is interpreted + to be the `loose` param. +- `includePrerelease` Set to suppress the [default + behavior](https://github.com/npm/node-semver#prerelease-tags) of + excluding prerelease tagged versions from ranges unless they are + explicitly opted into. + +Strict-mode Comparators and Ranges will be strict about the SemVer +strings that they parse. + +* `valid(v)`: Return the parsed version, or null if it's not valid. +* `inc(v, release)`: Return the version incremented by the release + type (`major`, `premajor`, `minor`, `preminor`, `patch`, + `prepatch`, or `prerelease`), or null if it's not valid + * `premajor` in one call will bump the version up to the next major + version and down to a prerelease of that major version. + `preminor`, and `prepatch` work the same way. + * If called from a non-prerelease version, the `prerelease` will work the + same as `prepatch`. It increments the patch version, then makes a + prerelease. If the input version is already a prerelease it simply + increments it. +* `prerelease(v)`: Returns an array of prerelease components, or null + if none exist. Example: `prerelease('1.2.3-alpha.1') -> ['alpha', 1]` +* `major(v)`: Return the major version number. +* `minor(v)`: Return the minor version number. +* `patch(v)`: Return the patch version number. +* `intersects(r1, r2, loose)`: Return true if the two supplied ranges + or comparators intersect. +* `parse(v)`: Attempt to parse a string as a semantic version, returning either + a `SemVer` object or `null`. + +### Comparison + +* `gt(v1, v2)`: `v1 > v2` +* `gte(v1, v2)`: `v1 >= v2` +* `lt(v1, v2)`: `v1 < v2` +* `lte(v1, v2)`: `v1 <= v2` +* `eq(v1, v2)`: `v1 == v2` This is true if they're logically equivalent, + even if they're not the exact same string. You already know how to + compare strings. +* `neq(v1, v2)`: `v1 != v2` The opposite of `eq`. +* `cmp(v1, comparator, v2)`: Pass in a comparison string, and it'll call + the corresponding function above. `"==="` and `"!=="` do simple + string comparison, but are included for completeness. Throws if an + invalid comparison string is provided. +* `compare(v1, v2)`: Return `0` if `v1 == v2`, or `1` if `v1` is greater, or `-1` if + `v2` is greater. Sorts in ascending order if passed to `Array.sort()`. +* `rcompare(v1, v2)`: The reverse of compare. Sorts an array of versions + in descending order when passed to `Array.sort()`. +* `compareBuild(v1, v2)`: The same as `compare` but considers `build` when two versions + are equal. Sorts in ascending order if passed to `Array.sort()`. + `v2` is greater. Sorts in ascending order if passed to `Array.sort()`. +* `diff(v1, v2)`: Returns difference between two versions by the release type + (`major`, `premajor`, `minor`, `preminor`, `patch`, `prepatch`, or `prerelease`), + or null if the versions are the same. + +### Comparators + +* `intersects(comparator)`: Return true if the comparators intersect + +### Ranges + +* `validRange(range)`: Return the valid range or null if it's not valid +* `satisfies(version, range)`: Return true if the version satisfies the + range. +* `maxSatisfying(versions, range)`: Return the highest version in the list + that satisfies the range, or `null` if none of them do. +* `minSatisfying(versions, range)`: Return the lowest version in the list + that satisfies the range, or `null` if none of them do. +* `minVersion(range)`: Return the lowest version that can possibly match + the given range. +* `gtr(version, range)`: Return `true` if version is greater than all the + versions possible in the range. +* `ltr(version, range)`: Return `true` if version is less than all the + versions possible in the range. +* `outside(version, range, hilo)`: Return true if the version is outside + the bounds of the range in either the high or low direction. The + `hilo` argument must be either the string `'>'` or `'<'`. (This is + the function called by `gtr` and `ltr`.) +* `intersects(range)`: Return true if any of the ranges comparators intersect + +Note that, since ranges may be non-contiguous, a version might not be +greater than a range, less than a range, *or* satisfy a range! For +example, the range `1.2 <1.2.9 || >2.0.0` would have a hole from `1.2.9` +until `2.0.0`, so the version `1.2.10` would not be greater than the +range (because `2.0.1` satisfies, which is higher), nor less than the +range (since `1.2.8` satisfies, which is lower), and it also does not +satisfy the range. + +If you want to know if a version satisfies or does not satisfy a +range, use the `satisfies(version, range)` function. + +### Coercion + +* `coerce(version, options)`: Coerces a string to semver if possible + +This aims to provide a very forgiving translation of a non-semver string to +semver. It looks for the first digit in a string, and consumes all +remaining characters which satisfy at least a partial semver (e.g., `1`, +`1.2`, `1.2.3`) up to the max permitted length (256 characters). Longer +versions are simply truncated (`4.6.3.9.2-alpha2` becomes `4.6.3`). All +surrounding text is simply ignored (`v3.4 replaces v3.3.1` becomes +`3.4.0`). Only text which lacks digits will fail coercion (`version one` +is not valid). The maximum length for any semver component considered for +coercion is 16 characters; longer components will be ignored +(`10000000000000000.4.7.4` becomes `4.7.4`). The maximum value for any +semver component is `Number.MAX_SAFE_INTEGER || (2**53 - 1)`; higher value +components are invalid (`9999999999999999.4.7.4` is likely invalid). + +If the `options.rtl` flag is set, then `coerce` will return the right-most +coercible tuple that does not share an ending index with a longer coercible +tuple. For example, `1.2.3.4` will return `2.3.4` in rtl mode, not +`4.0.0`. `1.2.3/4` will return `4.0.0`, because the `4` is not a part of +any other overlapping SemVer tuple. + +### Clean + +* `clean(version)`: Clean a string to be a valid semver if possible + +This will return a cleaned and trimmed semver version. If the provided +version is not valid a null will be returned. This does not work for +ranges. + +ex. +* `s.clean(' = v 2.1.5foo')`: `null` +* `s.clean(' = v 2.1.5foo', { loose: true })`: `'2.1.5-foo'` +* `s.clean(' = v 2.1.5-foo')`: `null` +* `s.clean(' = v 2.1.5-foo', { loose: true })`: `'2.1.5-foo'` +* `s.clean('=v2.1.5')`: `'2.1.5'` +* `s.clean(' =v2.1.5')`: `2.1.5` +* `s.clean(' 2.1.5 ')`: `'2.1.5'` +* `s.clean('~1.0.0')`: `null` + +## Exported Modules + + + +You may pull in just the part of this semver utility that you need, if you +are sensitive to packing and tree-shaking concerns. The main +`require('semver')` export uses getter functions to lazily load the parts +of the API that are used. + +The following modules are available: + +* `require('semver')` +* `require('semver/classes')` +* `require('semver/classes/comparator')` +* `require('semver/classes/range')` +* `require('semver/classes/semver')` +* `require('semver/functions/clean')` +* `require('semver/functions/cmp')` +* `require('semver/functions/coerce')` +* `require('semver/functions/compare')` +* `require('semver/functions/compare-build')` +* `require('semver/functions/compare-loose')` +* `require('semver/functions/diff')` +* `require('semver/functions/eq')` +* `require('semver/functions/gt')` +* `require('semver/functions/gte')` +* `require('semver/functions/inc')` +* `require('semver/functions/lt')` +* `require('semver/functions/lte')` +* `require('semver/functions/major')` +* `require('semver/functions/minor')` +* `require('semver/functions/neq')` +* `require('semver/functions/parse')` +* `require('semver/functions/patch')` +* `require('semver/functions/prerelease')` +* `require('semver/functions/rcompare')` +* `require('semver/functions/rsort')` +* `require('semver/functions/satisfies')` +* `require('semver/functions/sort')` +* `require('semver/functions/valid')` +* `require('semver/ranges/gtr')` +* `require('semver/ranges/intersects')` +* `require('semver/ranges/ltr')` +* `require('semver/ranges/max-satisfying')` +* `require('semver/ranges/min-satisfying')` +* `require('semver/ranges/min-version')` +* `require('semver/ranges/outside')` +* `require('semver/ranges/to-comparators')` +* `require('semver/ranges/valid')` diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/bin/semver.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/bin/semver.js new file mode 100644 index 0000000..73fe295 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/bin/semver.js @@ -0,0 +1,173 @@ +#!/usr/bin/env node +// Standalone semver comparison program. +// Exits successfully and prints matching version(s) if +// any supplied version is valid and passes all tests. + +const argv = process.argv.slice(2) + +let versions = [] + +const range = [] + +let inc = null + +const version = require('../package.json').version + +let loose = false + +let includePrerelease = false + +let coerce = false + +let rtl = false + +let identifier + +const semver = require('../') + +let reverse = false + +const options = {} + +const main = () => { + if (!argv.length) return help() + while (argv.length) { + let a = argv.shift() + const indexOfEqualSign = a.indexOf('=') + if (indexOfEqualSign !== -1) { + a = a.slice(0, indexOfEqualSign) + argv.unshift(a.slice(indexOfEqualSign + 1)) + } + switch (a) { + case '-rv': case '-rev': case '--rev': case '--reverse': + reverse = true + break + case '-l': case '--loose': + loose = true + break + case '-p': case '--include-prerelease': + includePrerelease = true + break + case '-v': case '--version': + versions.push(argv.shift()) + break + case '-i': case '--inc': case '--increment': + switch (argv[0]) { + case 'major': case 'minor': case 'patch': case 'prerelease': + case 'premajor': case 'preminor': case 'prepatch': + inc = argv.shift() + break + default: + inc = 'patch' + break + } + break + case '--preid': + identifier = argv.shift() + break + case '-r': case '--range': + range.push(argv.shift()) + break + case '-c': case '--coerce': + coerce = true + break + case '--rtl': + rtl = true + break + case '--ltr': + rtl = false + break + case '-h': case '--help': case '-?': + return help() + default: + versions.push(a) + break + } + } + + const options = { loose: loose, includePrerelease: includePrerelease, rtl: rtl } + + versions = versions.map((v) => { + return coerce ? (semver.coerce(v, options) || { version: v }).version : v + }).filter((v) => { + return semver.valid(v) + }) + if (!versions.length) return fail() + if (inc && (versions.length !== 1 || range.length)) { return failInc() } + + for (let i = 0, l = range.length; i < l; i++) { + versions = versions.filter((v) => { + return semver.satisfies(v, range[i], options) + }) + if (!versions.length) return fail() + } + return success(versions) +} + + +const failInc = () => { + console.error('--inc can only be used on a single version with no range') + fail() +} + +const fail = () => process.exit(1) + +const success = () => { + const compare = reverse ? 'rcompare' : 'compare' + versions.sort((a, b) => { + return semver[compare](a, b, options) + }).map((v) => { + return semver.clean(v, options) + }).map((v) => { + return inc ? semver.inc(v, inc, options, identifier) : v + }).forEach((v, i, _) => { console.log(v) }) +} + +const help = () => console.log( +`SemVer ${version} + +A JavaScript implementation of the https://semver.org/ specification +Copyright Isaac Z. Schlueter + +Usage: semver [options] [ [...]] +Prints valid versions sorted by SemVer precedence + +Options: +-r --range + Print versions that match the specified range. + +-i --increment [] + Increment a version by the specified level. Level can + be one of: major, minor, patch, premajor, preminor, + prepatch, or prerelease. Default level is 'patch'. + Only one version may be specified. + +--preid + Identifier to be used to prefix premajor, preminor, + prepatch or prerelease version increments. + +-l --loose + Interpret versions and ranges loosely + +-p --include-prerelease + Always include prerelease versions in range matching + +-c --coerce + Coerce a string into SemVer if possible + (does not imply --loose) + +--rtl + Coerce version strings right to left + +--ltr + Coerce version strings left to right (default) + +Program exits successfully if any valid version satisfies +all supplied ranges, and prints all satisfying versions. + +If no satisfying versions are found, then exits failure. + +Versions are printed in ascending order, so supplying +multiple versions to the utility will just sort them.`) + +main() diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/comparator.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/comparator.js new file mode 100644 index 0000000..3595792 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/comparator.js @@ -0,0 +1,139 @@ +const ANY = Symbol('SemVer ANY') +// hoisted class for cyclic dependency +class Comparator { + static get ANY () { + return ANY + } + constructor (comp, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (comp instanceof Comparator) { + if (comp.loose === !!options.loose) { + return comp + } else { + comp = comp.value + } + } + + debug('comparator', comp, options) + this.options = options + this.loose = !!options.loose + this.parse(comp) + + if (this.semver === ANY) { + this.value = '' + } else { + this.value = this.operator + this.semver.version + } + + debug('comp', this) + } + + parse (comp) { + const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR] + const m = comp.match(r) + + if (!m) { + throw new TypeError(`Invalid comparator: ${comp}`) + } + + this.operator = m[1] !== undefined ? m[1] : '' + if (this.operator === '=') { + this.operator = '' + } + + // if it literally is just '>' or '' then allow anything. + if (!m[2]) { + this.semver = ANY + } else { + this.semver = new SemVer(m[2], this.options.loose) + } + } + + toString () { + return this.value + } + + test (version) { + debug('Comparator.test', version, this.options.loose) + + if (this.semver === ANY || version === ANY) { + return true + } + + if (typeof version === 'string') { + try { + version = new SemVer(version, this.options) + } catch (er) { + return false + } + } + + return cmp(version, this.operator, this.semver, this.options) + } + + intersects (comp, options) { + if (!(comp instanceof Comparator)) { + throw new TypeError('a Comparator is required') + } + + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (this.operator === '') { + if (this.value === '') { + return true + } + return new Range(comp.value, options).test(this.value) + } else if (comp.operator === '') { + if (comp.value === '') { + return true + } + return new Range(this.value, options).test(comp.semver) + } + + const sameDirectionIncreasing = + (this.operator === '>=' || this.operator === '>') && + (comp.operator === '>=' || comp.operator === '>') + const sameDirectionDecreasing = + (this.operator === '<=' || this.operator === '<') && + (comp.operator === '<=' || comp.operator === '<') + const sameSemVer = this.semver.version === comp.semver.version + const differentDirectionsInclusive = + (this.operator === '>=' || this.operator === '<=') && + (comp.operator === '>=' || comp.operator === '<=') + const oppositeDirectionsLessThan = + cmp(this.semver, '<', comp.semver, options) && + (this.operator === '>=' || this.operator === '>') && + (comp.operator === '<=' || comp.operator === '<') + const oppositeDirectionsGreaterThan = + cmp(this.semver, '>', comp.semver, options) && + (this.operator === '<=' || this.operator === '<') && + (comp.operator === '>=' || comp.operator === '>') + + return ( + sameDirectionIncreasing || + sameDirectionDecreasing || + (sameSemVer && differentDirectionsInclusive) || + oppositeDirectionsLessThan || + oppositeDirectionsGreaterThan + ) + } +} + +module.exports = Comparator + +const {re, t} = require('../internal/re') +const cmp = require('../functions/cmp') +const debug = require('../internal/debug') +const SemVer = require('./semver') +const Range = require('./range') diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/index.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/index.js new file mode 100644 index 0000000..198b84d --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/index.js @@ -0,0 +1,5 @@ +module.exports = { + SemVer: require('./semver.js'), + Range: require('./range.js'), + Comparator: require('./comparator.js') +} diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/range.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/range.js new file mode 100644 index 0000000..90876c3 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/range.js @@ -0,0 +1,448 @@ +// hoisted class for cyclic dependency +class Range { + constructor (range, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (range instanceof Range) { + if ( + range.loose === !!options.loose && + range.includePrerelease === !!options.includePrerelease + ) { + return range + } else { + return new Range(range.raw, options) + } + } + + if (range instanceof Comparator) { + // just put it in the set and return + this.raw = range.value + this.set = [[range]] + this.format() + return this + } + + this.options = options + this.loose = !!options.loose + this.includePrerelease = !!options.includePrerelease + + // First, split based on boolean or || + this.raw = range + this.set = range + .split(/\s*\|\|\s*/) + // map the range to a 2d array of comparators + .map(range => this.parseRange(range.trim())) + // throw out any comparator lists that are empty + // this generally means that it was not a valid range, which is allowed + // in loose mode, but will still throw if the WHOLE range is invalid. + .filter(c => c.length) + + if (!this.set.length) { + throw new TypeError(`Invalid SemVer Range: ${range}`) + } + + this.format() + } + + format () { + this.range = this.set + .map((comps) => { + return comps.join(' ').trim() + }) + .join('||') + .trim() + return this.range + } + + toString () { + return this.range + } + + parseRange (range) { + const loose = this.options.loose + range = range.trim() + // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` + const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE] + range = range.replace(hr, hyphenReplace) + debug('hyphen replace', range) + // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` + range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace) + debug('comparator trim', range, re[t.COMPARATORTRIM]) + + // `~ 1.2.3` => `~1.2.3` + range = range.replace(re[t.TILDETRIM], tildeTrimReplace) + + // `^ 1.2.3` => `^1.2.3` + range = range.replace(re[t.CARETTRIM], caretTrimReplace) + + // normalize spaces + range = range.split(/\s+/).join(' ') + + // At this point, the range is completely trimmed and + // ready to be split into comparators. + + const compRe = loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR] + return range + .split(' ') + .map(comp => parseComparator(comp, this.options)) + .join(' ') + .split(/\s+/) + // in loose mode, throw out any that are not valid comparators + .filter(this.options.loose ? comp => !!comp.match(compRe) : () => true) + .map(comp => new Comparator(comp, this.options)) + } + + intersects (range, options) { + if (!(range instanceof Range)) { + throw new TypeError('a Range is required') + } + + return this.set.some((thisComparators) => { + return ( + isSatisfiable(thisComparators, options) && + range.set.some((rangeComparators) => { + return ( + isSatisfiable(rangeComparators, options) && + thisComparators.every((thisComparator) => { + return rangeComparators.every((rangeComparator) => { + return thisComparator.intersects(rangeComparator, options) + }) + }) + ) + }) + ) + }) + } + + // if ANY of the sets match ALL of its comparators, then pass + test (version) { + if (!version) { + return false + } + + if (typeof version === 'string') { + try { + version = new SemVer(version, this.options) + } catch (er) { + return false + } + } + + for (let i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version, this.options)) { + return true + } + } + return false + } +} +module.exports = Range + +const Comparator = require('./comparator') +const debug = require('../internal/debug') +const SemVer = require('./semver') +const { + re, + t, + comparatorTrimReplace, + tildeTrimReplace, + caretTrimReplace +} = require('../internal/re') + +// take a set of comparators and determine whether there +// exists a version which can satisfy it +const isSatisfiable = (comparators, options) => { + let result = true + const remainingComparators = comparators.slice() + let testComparator = remainingComparators.pop() + + while (result && remainingComparators.length) { + result = remainingComparators.every((otherComparator) => { + return testComparator.intersects(otherComparator, options) + }) + + testComparator = remainingComparators.pop() + } + + return result +} + +// comprised of xranges, tildes, stars, and gtlt's at this point. +// already replaced the hyphen ranges +// turn into a set of JUST comparators. +const parseComparator = (comp, options) => { + debug('comp', comp, options) + comp = replaceCarets(comp, options) + debug('caret', comp) + comp = replaceTildes(comp, options) + debug('tildes', comp) + comp = replaceXRanges(comp, options) + debug('xrange', comp) + comp = replaceStars(comp, options) + debug('stars', comp) + return comp +} + +const isX = id => !id || id.toLowerCase() === 'x' || id === '*' + +// ~, ~> --> * (any, kinda silly) +// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 +// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 +// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 +// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 +// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 +const replaceTildes = (comp, options) => + comp.trim().split(/\s+/).map((comp) => { + return replaceTilde(comp, options) + }).join(' ') + +const replaceTilde = (comp, options) => { + const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE] + return comp.replace(r, (_, M, m, p, pr) => { + debug('tilde', comp, _, M, m, p, pr) + let ret + + if (isX(M)) { + ret = '' + } else if (isX(m)) { + ret = `>=${M}.0.0 <${+M + 1}.0.0` + } else if (isX(p)) { + // ~1.2 == >=1.2.0 <1.3.0 + ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0` + } else if (pr) { + debug('replaceTilde pr', pr) + ret = `>=${M}.${m}.${p}-${pr + } <${M}.${+m + 1}.0` + } else { + // ~1.2.3 == >=1.2.3 <1.3.0 + ret = `>=${M}.${m}.${p + } <${M}.${+m + 1}.0` + } + + debug('tilde return', ret) + return ret + }) +} + +// ^ --> * (any, kinda silly) +// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 +// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 +// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 +// ^1.2.3 --> >=1.2.3 <2.0.0 +// ^1.2.0 --> >=1.2.0 <2.0.0 +const replaceCarets = (comp, options) => + comp.trim().split(/\s+/).map((comp) => { + return replaceCaret(comp, options) + }).join(' ') + +const replaceCaret = (comp, options) => { + debug('caret', comp, options) + const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET] + return comp.replace(r, (_, M, m, p, pr) => { + debug('caret', comp, _, M, m, p, pr) + let ret + + if (isX(M)) { + ret = '' + } else if (isX(m)) { + ret = `>=${M}.0.0 <${+M + 1}.0.0` + } else if (isX(p)) { + if (M === '0') { + ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0` + } else { + ret = `>=${M}.${m}.0 <${+M + 1}.0.0` + } + } else if (pr) { + debug('replaceCaret pr', pr) + if (M === '0') { + if (m === '0') { + ret = `>=${M}.${m}.${p}-${pr + } <${M}.${m}.${+p + 1}` + } else { + ret = `>=${M}.${m}.${p}-${pr + } <${M}.${+m + 1}.0` + } + } else { + ret = `>=${M}.${m}.${p}-${pr + } <${+M + 1}.0.0` + } + } else { + debug('no pr') + if (M === '0') { + if (m === '0') { + ret = `>=${M}.${m}.${p + } <${M}.${m}.${+p + 1}` + } else { + ret = `>=${M}.${m}.${p + } <${M}.${+m + 1}.0` + } + } else { + ret = `>=${M}.${m}.${p + } <${+M + 1}.0.0` + } + } + + debug('caret return', ret) + return ret + }) +} + +const replaceXRanges = (comp, options) => { + debug('replaceXRanges', comp, options) + return comp.split(/\s+/).map((comp) => { + return replaceXRange(comp, options) + }).join(' ') +} + +const replaceXRange = (comp, options) => { + comp = comp.trim() + const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE] + return comp.replace(r, (ret, gtlt, M, m, p, pr) => { + debug('xRange', comp, ret, gtlt, M, m, p, pr) + const xM = isX(M) + const xm = xM || isX(m) + const xp = xm || isX(p) + const anyX = xp + + if (gtlt === '=' && anyX) { + gtlt = '' + } + + // if we're including prereleases in the match, then we need + // to fix this to -0, the lowest possible prerelease value + pr = options.includePrerelease ? '-0' : '' + + if (xM) { + if (gtlt === '>' || gtlt === '<') { + // nothing is allowed + ret = '<0.0.0-0' + } else { + // nothing is forbidden + ret = '*' + } + } else if (gtlt && anyX) { + // we know patch is an x, because we have any x at all. + // replace X with 0 + if (xm) { + m = 0 + } + p = 0 + + if (gtlt === '>') { + // >1 => >=2.0.0 + // >1.2 => >=1.3.0 + gtlt = '>=' + if (xm) { + M = +M + 1 + m = 0 + p = 0 + } else { + m = +m + 1 + p = 0 + } + } else if (gtlt === '<=') { + // <=0.7.x is actually <0.8.0, since any 0.7.x should + // pass. Similarly, <=7.x is actually <8.0.0, etc. + gtlt = '<' + if (xm) { + M = +M + 1 + } else { + m = +m + 1 + } + } + + ret = `${gtlt + M}.${m}.${p}${pr}` + } else if (xm) { + ret = `>=${M}.0.0${pr} <${+M + 1}.0.0${pr}` + } else if (xp) { + ret = `>=${M}.${m}.0${pr + } <${M}.${+m + 1}.0${pr}` + } + + debug('xRange return', ret) + + return ret + }) +} + +// Because * is AND-ed with everything else in the comparator, +// and '' means "any version", just remove the *s entirely. +const replaceStars = (comp, options) => { + debug('replaceStars', comp, options) + // Looseness is ignored here. star is always as loose as it gets! + return comp.trim().replace(re[t.STAR], '') +} + +// This function is passed to string.replace(re[t.HYPHENRANGE]) +// M, m, patch, prerelease, build +// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 +// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do +// 1.2 - 3.4 => >=1.2.0 <3.5.0 +const hyphenReplace = ($0, + from, fM, fm, fp, fpr, fb, + to, tM, tm, tp, tpr, tb) => { + if (isX(fM)) { + from = '' + } else if (isX(fm)) { + from = `>=${fM}.0.0` + } else if (isX(fp)) { + from = `>=${fM}.${fm}.0` + } else { + from = `>=${from}` + } + + if (isX(tM)) { + to = '' + } else if (isX(tm)) { + to = `<${+tM + 1}.0.0` + } else if (isX(tp)) { + to = `<${tM}.${+tm + 1}.0` + } else if (tpr) { + to = `<=${tM}.${tm}.${tp}-${tpr}` + } else { + to = `<=${to}` + } + + return (`${from} ${to}`).trim() +} + +const testSet = (set, version, options) => { + for (let i = 0; i < set.length; i++) { + if (!set[i].test(version)) { + return false + } + } + + if (version.prerelease.length && !options.includePrerelease) { + // Find the set of versions that are allowed to have prereleases + // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 + // That should allow `1.2.3-pr.2` to pass. + // However, `1.2.4-alpha.notready` should NOT be allowed, + // even though it's within the range set by the comparators. + for (let i = 0; i < set.length; i++) { + debug(set[i].semver) + if (set[i].semver === Comparator.ANY) { + continue + } + + if (set[i].semver.prerelease.length > 0) { + const allowed = set[i].semver + if (allowed.major === version.major && + allowed.minor === version.minor && + allowed.patch === version.patch) { + return true + } + } + } + + // Version has a -pre, but it's not one of the ones we like. + return false + } + + return true +} diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/semver.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/semver.js new file mode 100644 index 0000000..73247ad --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/semver.js @@ -0,0 +1,290 @@ +const debug = require('../internal/debug') +const { MAX_LENGTH, MAX_SAFE_INTEGER } = require('../internal/constants') +const { re, t } = require('../internal/re') + +const { compareIdentifiers } = require('../internal/identifiers') +class SemVer { + constructor (version, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + if (version instanceof SemVer) { + if (version.loose === !!options.loose && + version.includePrerelease === !!options.includePrerelease) { + return version + } else { + version = version.version + } + } else if (typeof version !== 'string') { + throw new TypeError(`Invalid Version: ${version}`) + } + + if (version.length > MAX_LENGTH) { + throw new TypeError( + `version is longer than ${MAX_LENGTH} characters` + ) + } + + debug('SemVer', version, options) + this.options = options + this.loose = !!options.loose + // this isn't actually relevant for versions, but keep it so that we + // don't run into trouble passing this.options around. + this.includePrerelease = !!options.includePrerelease + + const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]) + + if (!m) { + throw new TypeError(`Invalid Version: ${version}`) + } + + this.raw = version + + // these are actually numbers + this.major = +m[1] + this.minor = +m[2] + this.patch = +m[3] + + if (this.major > MAX_SAFE_INTEGER || this.major < 0) { + throw new TypeError('Invalid major version') + } + + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { + throw new TypeError('Invalid minor version') + } + + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { + throw new TypeError('Invalid patch version') + } + + // numberify any prerelease numeric ids + if (!m[4]) { + this.prerelease = [] + } else { + this.prerelease = m[4].split('.').map((id) => { + if (/^[0-9]+$/.test(id)) { + const num = +id + if (num >= 0 && num < MAX_SAFE_INTEGER) { + return num + } + } + return id + }) + } + + this.build = m[5] ? m[5].split('.') : [] + this.format() + } + + format () { + this.version = `${this.major}.${this.minor}.${this.patch}` + if (this.prerelease.length) { + this.version += `-${this.prerelease.join('.')}` + } + return this.version + } + + toString () { + return this.version + } + + compare (other) { + debug('SemVer.compare', this.version, this.options, other) + if (!(other instanceof SemVer)) { + if (typeof other === 'string' && other === this.version) { + return 0 + } + other = new SemVer(other, this.options) + } + + if (other.version === this.version) { + return 0 + } + + return this.compareMain(other) || this.comparePre(other) + } + + compareMain (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + return ( + compareIdentifiers(this.major, other.major) || + compareIdentifiers(this.minor, other.minor) || + compareIdentifiers(this.patch, other.patch) + ) + } + + comparePre (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + // NOT having a prerelease is > having one + if (this.prerelease.length && !other.prerelease.length) { + return -1 + } else if (!this.prerelease.length && other.prerelease.length) { + return 1 + } else if (!this.prerelease.length && !other.prerelease.length) { + return 0 + } + + let i = 0 + do { + const a = this.prerelease[i] + const b = other.prerelease[i] + debug('prerelease compare', i, a, b) + if (a === undefined && b === undefined) { + return 0 + } else if (b === undefined) { + return 1 + } else if (a === undefined) { + return -1 + } else if (a === b) { + continue + } else { + return compareIdentifiers(a, b) + } + } while (++i) + } + + compareBuild (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + let i = 0 + do { + const a = this.build[i] + const b = other.build[i] + debug('prerelease compare', i, a, b) + if (a === undefined && b === undefined) { + return 0 + } else if (b === undefined) { + return 1 + } else if (a === undefined) { + return -1 + } else if (a === b) { + continue + } else { + return compareIdentifiers(a, b) + } + } while (++i) + } + + // preminor will bump the version up to the next minor release, and immediately + // down to pre-release. premajor and prepatch work the same way. + inc (release, identifier) { + switch (release) { + case 'premajor': + this.prerelease.length = 0 + this.patch = 0 + this.minor = 0 + this.major++ + this.inc('pre', identifier) + break + case 'preminor': + this.prerelease.length = 0 + this.patch = 0 + this.minor++ + this.inc('pre', identifier) + break + case 'prepatch': + // If this is already a prerelease, it will bump to the next version + // drop any prereleases that might already exist, since they are not + // relevant at this point. + this.prerelease.length = 0 + this.inc('patch', identifier) + this.inc('pre', identifier) + break + // If the input is a non-prerelease version, this acts the same as + // prepatch. + case 'prerelease': + if (this.prerelease.length === 0) { + this.inc('patch', identifier) + } + this.inc('pre', identifier) + break + + case 'major': + // If this is a pre-major version, bump up to the same major version. + // Otherwise increment major. + // 1.0.0-5 bumps to 1.0.0 + // 1.1.0 bumps to 2.0.0 + if ( + this.minor !== 0 || + this.patch !== 0 || + this.prerelease.length === 0 + ) { + this.major++ + } + this.minor = 0 + this.patch = 0 + this.prerelease = [] + break + case 'minor': + // If this is a pre-minor version, bump up to the same minor version. + // Otherwise increment minor. + // 1.2.0-5 bumps to 1.2.0 + // 1.2.1 bumps to 1.3.0 + if (this.patch !== 0 || this.prerelease.length === 0) { + this.minor++ + } + this.patch = 0 + this.prerelease = [] + break + case 'patch': + // If this is not a pre-release version, it will increment the patch. + // If it is a pre-release it will bump up to the same patch version. + // 1.2.0-5 patches to 1.2.0 + // 1.2.0 patches to 1.2.1 + if (this.prerelease.length === 0) { + this.patch++ + } + this.prerelease = [] + break + // This probably shouldn't be used publicly. + // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction. + case 'pre': + if (this.prerelease.length === 0) { + this.prerelease = [0] + } else { + let i = this.prerelease.length + while (--i >= 0) { + if (typeof this.prerelease[i] === 'number') { + this.prerelease[i]++ + i = -2 + } + } + if (i === -1) { + // didn't increment anything + this.prerelease.push(0) + } + } + if (identifier) { + // 1.2.0-beta.1 bumps to 1.2.0-beta.2, + // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 + if (this.prerelease[0] === identifier) { + if (isNaN(this.prerelease[1])) { + this.prerelease = [identifier, 0] + } + } else { + this.prerelease = [identifier, 0] + } + } + break + + default: + throw new Error(`invalid increment argument: ${release}`) + } + this.format() + this.raw = this.version + return this + } +} + +module.exports = SemVer diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/clean.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/clean.js new file mode 100644 index 0000000..811fe6b --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/clean.js @@ -0,0 +1,6 @@ +const parse = require('./parse') +const clean = (version, options) => { + const s = parse(version.trim().replace(/^[=v]+/, ''), options) + return s ? s.version : null +} +module.exports = clean diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/cmp.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/cmp.js new file mode 100644 index 0000000..3b89db7 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/cmp.js @@ -0,0 +1,48 @@ +const eq = require('./eq') +const neq = require('./neq') +const gt = require('./gt') +const gte = require('./gte') +const lt = require('./lt') +const lte = require('./lte') + +const cmp = (a, op, b, loose) => { + switch (op) { + case '===': + if (typeof a === 'object') + a = a.version + if (typeof b === 'object') + b = b.version + return a === b + + case '!==': + if (typeof a === 'object') + a = a.version + if (typeof b === 'object') + b = b.version + return a !== b + + case '': + case '=': + case '==': + return eq(a, b, loose) + + case '!=': + return neq(a, b, loose) + + case '>': + return gt(a, b, loose) + + case '>=': + return gte(a, b, loose) + + case '<': + return lt(a, b, loose) + + case '<=': + return lte(a, b, loose) + + default: + throw new TypeError(`Invalid operator: ${op}`) + } +} +module.exports = cmp diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/coerce.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/coerce.js new file mode 100644 index 0000000..106ca71 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/coerce.js @@ -0,0 +1,51 @@ +const SemVer = require('../classes/semver') +const parse = require('./parse') +const {re, t} = require('../internal/re') + +const coerce = (version, options) => { + if (version instanceof SemVer) { + return version + } + + if (typeof version === 'number') { + version = String(version) + } + + if (typeof version !== 'string') { + return null + } + + options = options || {} + + let match = null + if (!options.rtl) { + match = version.match(re[t.COERCE]) + } else { + // Find the right-most coercible string that does not share + // a terminus with a more left-ward coercible string. + // Eg, '1.2.3.4' wants to coerce '2.3.4', not '3.4' or '4' + // + // Walk through the string checking with a /g regexp + // Manually set the index so as to pick up overlapping matches. + // Stop when we get a match that ends at the string end, since no + // coercible string can be more right-ward without the same terminus. + let next + while ((next = re[t.COERCERTL].exec(version)) && + (!match || match.index + match[0].length !== version.length) + ) { + if (!match || + next.index + next[0].length !== match.index + match[0].length) { + match = next + } + re[t.COERCERTL].lastIndex = next.index + next[1].length + next[2].length + } + // leave it in a clean state + re[t.COERCERTL].lastIndex = -1 + } + + if (match === null) + return null + + return parse(`${match[2]}.${match[3] || '0'}.${match[4] || '0'}`, options) +} +module.exports = coerce diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare-build.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare-build.js new file mode 100644 index 0000000..9eb881b --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare-build.js @@ -0,0 +1,7 @@ +const SemVer = require('../classes/semver') +const compareBuild = (a, b, loose) => { + const versionA = new SemVer(a, loose) + const versionB = new SemVer(b, loose) + return versionA.compare(versionB) || versionA.compareBuild(versionB) +} +module.exports = compareBuild diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare-loose.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare-loose.js new file mode 100644 index 0000000..4881fbe --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare-loose.js @@ -0,0 +1,3 @@ +const compare = require('./compare') +const compareLoose = (a, b) => compare(a, b, true) +module.exports = compareLoose diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare.js new file mode 100644 index 0000000..748b7af --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare.js @@ -0,0 +1,5 @@ +const SemVer = require('../classes/semver') +const compare = (a, b, loose) => + new SemVer(a, loose).compare(new SemVer(b, loose)) + +module.exports = compare diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/diff.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/diff.js new file mode 100644 index 0000000..1493666 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/diff.js @@ -0,0 +1,25 @@ +const parse = require('./parse') +const eq = require('./eq') + +const diff = (version1, version2) => { + if (eq(version1, version2)) { + return null + } else { + const v1 = parse(version1) + const v2 = parse(version2) + let prefix = '' + if (v1.prerelease.length || v2.prerelease.length) { + prefix = 'pre' + var defaultResult = 'prerelease' + } + for (const key in v1) { + if (key === 'major' || key === 'minor' || key === 'patch') { + if (v1[key] !== v2[key]) { + return prefix + key + } + } + } + return defaultResult // may be undefined + } +} +module.exports = diff diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/eq.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/eq.js new file mode 100644 index 0000000..271fed9 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/eq.js @@ -0,0 +1,3 @@ +const compare = require('./compare') +const eq = (a, b, loose) => compare(a, b, loose) === 0 +module.exports = eq diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/gt.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/gt.js new file mode 100644 index 0000000..d9b2156 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/gt.js @@ -0,0 +1,3 @@ +const compare = require('./compare') +const gt = (a, b, loose) => compare(a, b, loose) > 0 +module.exports = gt diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/gte.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/gte.js new file mode 100644 index 0000000..5aeaa63 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/gte.js @@ -0,0 +1,3 @@ +const compare = require('./compare') +const gte = (a, b, loose) => compare(a, b, loose) >= 0 +module.exports = gte diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/inc.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/inc.js new file mode 100644 index 0000000..aa4d83a --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/inc.js @@ -0,0 +1,15 @@ +const SemVer = require('../classes/semver') + +const inc = (version, release, options, identifier) => { + if (typeof (options) === 'string') { + identifier = options + options = undefined + } + + try { + return new SemVer(version, options).inc(release, identifier).version + } catch (er) { + return null + } +} +module.exports = inc diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/lt.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/lt.js new file mode 100644 index 0000000..b440ab7 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/lt.js @@ -0,0 +1,3 @@ +const compare = require('./compare') +const lt = (a, b, loose) => compare(a, b, loose) < 0 +module.exports = lt diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/lte.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/lte.js new file mode 100644 index 0000000..6dcc956 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/lte.js @@ -0,0 +1,3 @@ +const compare = require('./compare') +const lte = (a, b, loose) => compare(a, b, loose) <= 0 +module.exports = lte diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/major.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/major.js new file mode 100644 index 0000000..4283165 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/major.js @@ -0,0 +1,3 @@ +const SemVer = require('../classes/semver') +const major = (a, loose) => new SemVer(a, loose).major +module.exports = major diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/minor.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/minor.js new file mode 100644 index 0000000..57b3455 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/minor.js @@ -0,0 +1,3 @@ +const SemVer = require('../classes/semver') +const minor = (a, loose) => new SemVer(a, loose).minor +module.exports = minor diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/neq.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/neq.js new file mode 100644 index 0000000..f944c01 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/neq.js @@ -0,0 +1,3 @@ +const compare = require('./compare') +const neq = (a, b, loose) => compare(a, b, loose) !== 0 +module.exports = neq diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/parse.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/parse.js new file mode 100644 index 0000000..457fee0 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/parse.js @@ -0,0 +1,37 @@ +const {MAX_LENGTH} = require('../internal/constants') +const { re, t } = require('../internal/re') +const SemVer = require('../classes/semver') + +const parse = (version, options) => { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (version instanceof SemVer) { + return version + } + + if (typeof version !== 'string') { + return null + } + + if (version.length > MAX_LENGTH) { + return null + } + + const r = options.loose ? re[t.LOOSE] : re[t.FULL] + if (!r.test(version)) { + return null + } + + try { + return new SemVer(version, options) + } catch (er) { + return null + } +} + +module.exports = parse diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/patch.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/patch.js new file mode 100644 index 0000000..63afca2 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/patch.js @@ -0,0 +1,3 @@ +const SemVer = require('../classes/semver') +const patch = (a, loose) => new SemVer(a, loose).patch +module.exports = patch diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/prerelease.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/prerelease.js new file mode 100644 index 0000000..06aa132 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/prerelease.js @@ -0,0 +1,6 @@ +const parse = require('./parse') +const prerelease = (version, options) => { + const parsed = parse(version, options) + return (parsed && parsed.prerelease.length) ? parsed.prerelease : null +} +module.exports = prerelease diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/rcompare.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/rcompare.js new file mode 100644 index 0000000..0ac509e --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/rcompare.js @@ -0,0 +1,3 @@ +const compare = require('./compare') +const rcompare = (a, b, loose) => compare(b, a, loose) +module.exports = rcompare diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/rsort.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/rsort.js new file mode 100644 index 0000000..82404c5 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/rsort.js @@ -0,0 +1,3 @@ +const compareBuild = require('./compare-build') +const rsort = (list, loose) => list.sort((a, b) => compareBuild(b, a, loose)) +module.exports = rsort diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/satisfies.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/satisfies.js new file mode 100644 index 0000000..50af1c1 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/satisfies.js @@ -0,0 +1,10 @@ +const Range = require('../classes/range') +const satisfies = (version, range, options) => { + try { + range = new Range(range, options) + } catch (er) { + return false + } + return range.test(version) +} +module.exports = satisfies diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/sort.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/sort.js new file mode 100644 index 0000000..4d10917 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/sort.js @@ -0,0 +1,3 @@ +const compareBuild = require('./compare-build') +const sort = (list, loose) => list.sort((a, b) => compareBuild(a, b, loose)) +module.exports = sort diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/valid.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/valid.js new file mode 100644 index 0000000..f27bae1 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/valid.js @@ -0,0 +1,6 @@ +const parse = require('./parse') +const valid = (version, options) => { + const v = parse(version, options) + return v ? v.version : null +} +module.exports = valid diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/index.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/index.js new file mode 100644 index 0000000..068f8b4 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/index.js @@ -0,0 +1,64 @@ +const lrCache = {} +const lazyRequire = (path, subkey) => { + const module = lrCache[path] || (lrCache[path] = require(path)) + return subkey ? module[subkey] : module +} + +const lazyExport = (key, path, subkey) => { + Object.defineProperty(exports, key, { + get: () => { + const res = lazyRequire(path, subkey) + Object.defineProperty(exports, key, { + value: res, + enumerable: true, + configurable: true + }) + return res + }, + configurable: true, + enumerable: true + }) +} + +lazyExport('re', './internal/re', 're') +lazyExport('src', './internal/re', 'src') +lazyExport('tokens', './internal/re', 't') +lazyExport('SEMVER_SPEC_VERSION', './internal/constants', 'SEMVER_SPEC_VERSION') +lazyExport('SemVer', './classes/semver') +lazyExport('compareIdentifiers', './internal/identifiers', 'compareIdentifiers') +lazyExport('rcompareIdentifiers', './internal/identifiers', 'rcompareIdentifiers') +lazyExport('parse', './functions/parse') +lazyExport('valid', './functions/valid') +lazyExport('clean', './functions/clean') +lazyExport('inc', './functions/inc') +lazyExport('diff', './functions/diff') +lazyExport('major', './functions/major') +lazyExport('minor', './functions/minor') +lazyExport('patch', './functions/patch') +lazyExport('prerelease', './functions/prerelease') +lazyExport('compare', './functions/compare') +lazyExport('rcompare', './functions/rcompare') +lazyExport('compareLoose', './functions/compare-loose') +lazyExport('compareBuild', './functions/compare-build') +lazyExport('sort', './functions/sort') +lazyExport('rsort', './functions/rsort') +lazyExport('gt', './functions/gt') +lazyExport('lt', './functions/lt') +lazyExport('eq', './functions/eq') +lazyExport('neq', './functions/neq') +lazyExport('gte', './functions/gte') +lazyExport('lte', './functions/lte') +lazyExport('cmp', './functions/cmp') +lazyExport('coerce', './functions/coerce') +lazyExport('Comparator', './classes/comparator') +lazyExport('Range', './classes/range') +lazyExport('satisfies', './functions/satisfies') +lazyExport('toComparators', './ranges/to-comparators') +lazyExport('maxSatisfying', './ranges/max-satisfying') +lazyExport('minSatisfying', './ranges/min-satisfying') +lazyExport('minVersion', './ranges/min-version') +lazyExport('validRange', './ranges/valid') +lazyExport('outside', './ranges/outside') +lazyExport('gtr', './ranges/gtr') +lazyExport('ltr', './ranges/ltr') +lazyExport('intersects', './ranges/intersects') diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/constants.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/constants.js new file mode 100644 index 0000000..49df215 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/constants.js @@ -0,0 +1,17 @@ +// Note: this is the semver.org version of the spec that it implements +// Not necessarily the package version of this code. +const SEMVER_SPEC_VERSION = '2.0.0' + +const MAX_LENGTH = 256 +const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || + /* istanbul ignore next */ 9007199254740991 + +// Max safe segment length for coercion. +const MAX_SAFE_COMPONENT_LENGTH = 16 + +module.exports = { + SEMVER_SPEC_VERSION, + MAX_LENGTH, + MAX_SAFE_INTEGER, + MAX_SAFE_COMPONENT_LENGTH +} diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/debug.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/debug.js new file mode 100644 index 0000000..1c00e13 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/debug.js @@ -0,0 +1,9 @@ +const debug = ( + typeof process === 'object' && + process.env && + process.env.NODE_DEBUG && + /\bsemver\b/i.test(process.env.NODE_DEBUG) +) ? (...args) => console.error('SEMVER', ...args) + : () => {} + +module.exports = debug diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/identifiers.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/identifiers.js new file mode 100644 index 0000000..ed13094 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/identifiers.js @@ -0,0 +1,23 @@ +const numeric = /^[0-9]+$/ +const compareIdentifiers = (a, b) => { + const anum = numeric.test(a) + const bnum = numeric.test(b) + + if (anum && bnum) { + a = +a + b = +b + } + + return a === b ? 0 + : (anum && !bnum) ? -1 + : (bnum && !anum) ? 1 + : a < b ? -1 + : 1 +} + +const rcompareIdentifiers = (a, b) => compareIdentifiers(b, a) + +module.exports = { + compareIdentifiers, + rcompareIdentifiers +} diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/re.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/re.js new file mode 100644 index 0000000..0e8fb52 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/re.js @@ -0,0 +1,179 @@ +const { MAX_SAFE_COMPONENT_LENGTH } = require('./constants') +const debug = require('./debug') +exports = module.exports = {} + +// The actual regexps go on exports.re +const re = exports.re = [] +const src = exports.src = [] +const t = exports.t = {} +let R = 0 + +const createToken = (name, value, isGlobal) => { + const index = R++ + debug(index, value) + t[name] = index + src[index] = value + re[index] = new RegExp(value, isGlobal ? 'g' : undefined) +} + +// The following Regular Expressions can be used for tokenizing, +// validating, and parsing SemVer version strings. + +// ## Numeric Identifier +// A single `0`, or a non-zero digit followed by zero or more digits. + +createToken('NUMERICIDENTIFIER', '0|[1-9]\\d*') +createToken('NUMERICIDENTIFIERLOOSE', '[0-9]+') + +// ## Non-numeric Identifier +// Zero or more digits, followed by a letter or hyphen, and then zero or +// more letters, digits, or hyphens. + +createToken('NONNUMERICIDENTIFIER', '\\d*[a-zA-Z-][a-zA-Z0-9-]*') + +// ## Main Version +// Three dot-separated numeric identifiers. + +createToken('MAINVERSION', `(${src[t.NUMERICIDENTIFIER]})\\.` + + `(${src[t.NUMERICIDENTIFIER]})\\.` + + `(${src[t.NUMERICIDENTIFIER]})`) + +createToken('MAINVERSIONLOOSE', `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` + + `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` + + `(${src[t.NUMERICIDENTIFIERLOOSE]})`) + +// ## Pre-release Version Identifier +// A numeric identifier, or a non-numeric identifier. + +createToken('PRERELEASEIDENTIFIER', `(?:${src[t.NUMERICIDENTIFIER] +}|${src[t.NONNUMERICIDENTIFIER]})`) + +createToken('PRERELEASEIDENTIFIERLOOSE', `(?:${src[t.NUMERICIDENTIFIERLOOSE] +}|${src[t.NONNUMERICIDENTIFIER]})`) + +// ## Pre-release Version +// Hyphen, followed by one or more dot-separated pre-release version +// identifiers. + +createToken('PRERELEASE', `(?:-(${src[t.PRERELEASEIDENTIFIER] +}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`) + +createToken('PRERELEASELOOSE', `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE] +}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`) + +// ## Build Metadata Identifier +// Any combination of digits, letters, or hyphens. + +createToken('BUILDIDENTIFIER', '[0-9A-Za-z-]+') + +// ## Build Metadata +// Plus sign, followed by one or more period-separated build metadata +// identifiers. + +createToken('BUILD', `(?:\\+(${src[t.BUILDIDENTIFIER] +}(?:\\.${src[t.BUILDIDENTIFIER]})*))`) + +// ## Full Version String +// A main version, followed optionally by a pre-release version and +// build metadata. + +// Note that the only major, minor, patch, and pre-release sections of +// the version string are capturing groups. The build metadata is not a +// capturing group, because it should not ever be used in version +// comparison. + +createToken('FULLPLAIN', `v?${src[t.MAINVERSION] +}${src[t.PRERELEASE]}?${ + src[t.BUILD]}?`) + +createToken('FULL', `^${src[t.FULLPLAIN]}$`) + +// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. +// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty +// common in the npm registry. +createToken('LOOSEPLAIN', `[v=\\s]*${src[t.MAINVERSIONLOOSE] +}${src[t.PRERELEASELOOSE]}?${ + src[t.BUILD]}?`) + +createToken('LOOSE', `^${src[t.LOOSEPLAIN]}$`) + +createToken('GTLT', '((?:<|>)?=?)') + +// Something like "2.*" or "1.2.x". +// Note that "x.x" is a valid xRange identifer, meaning "any version" +// Only the first item is strictly required. +createToken('XRANGEIDENTIFIERLOOSE', `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`) +createToken('XRANGEIDENTIFIER', `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`) + +createToken('XRANGEPLAIN', `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})` + + `(?:\\.(${src[t.XRANGEIDENTIFIER]})` + + `(?:\\.(${src[t.XRANGEIDENTIFIER]})` + + `(?:${src[t.PRERELEASE]})?${ + src[t.BUILD]}?` + + `)?)?`) + +createToken('XRANGEPLAINLOOSE', `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})` + + `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` + + `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` + + `(?:${src[t.PRERELEASELOOSE]})?${ + src[t.BUILD]}?` + + `)?)?`) + +createToken('XRANGE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`) +createToken('XRANGELOOSE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`) + +// Coercion. +// Extract anything that could conceivably be a part of a valid semver +createToken('COERCE', `${'(^|[^\\d])' + + '(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` + + `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` + + `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` + + `(?:$|[^\\d])`) +createToken('COERCERTL', src[t.COERCE], true) + +// Tilde ranges. +// Meaning is "reasonably at or greater than" +createToken('LONETILDE', '(?:~>?)') + +createToken('TILDETRIM', `(\\s*)${src[t.LONETILDE]}\\s+`, true) +exports.tildeTrimReplace = '$1~' + +createToken('TILDE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`) +createToken('TILDELOOSE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`) + +// Caret ranges. +// Meaning is "at least and backwards compatible with" +createToken('LONECARET', '(?:\\^)') + +createToken('CARETTRIM', `(\\s*)${src[t.LONECARET]}\\s+`, true) +exports.caretTrimReplace = '$1^' + +createToken('CARET', `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`) +createToken('CARETLOOSE', `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`) + +// A simple gt/lt/eq thing, or just "" to indicate "any version" +createToken('COMPARATORLOOSE', `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`) +createToken('COMPARATOR', `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`) + +// An expression to strip any whitespace between the gtlt and the thing +// it modifies, so that `> 1.2.3` ==> `>1.2.3` +createToken('COMPARATORTRIM', `(\\s*)${src[t.GTLT] +}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true) +exports.comparatorTrimReplace = '$1$2$3' + +// Something like `1.2.3 - 1.2.4` +// Note that these all use the loose form, because they'll be +// checked against either the strict or loose comparator form +// later. +createToken('HYPHENRANGE', `^\\s*(${src[t.XRANGEPLAIN]})` + + `\\s+-\\s+` + + `(${src[t.XRANGEPLAIN]})` + + `\\s*$`) + +createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` + + `\\s+-\\s+` + + `(${src[t.XRANGEPLAINLOOSE]})` + + `\\s*$`) + +// Star ranges basically just allow anything at all. +createToken('STAR', '(<|>)?=?\\s*\\*') diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/package.json b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/package.json new file mode 100644 index 0000000..88574c0 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/package.json @@ -0,0 +1,34 @@ +{ + "name": "semver", + "version": "7.0.0", + "description": "The semantic version parser used by npm.", + "main": "index.js", + "scripts": { + "test": "tap", + "snap": "tap", + "preversion": "npm test", + "postversion": "npm publish", + "postpublish": "git push origin --follow-tags" + }, + "devDependencies": { + "tap": "^14.10.1" + }, + "license": "ISC", + "repository": "https://github.com/npm/node-semver", + "bin": { + "semver": "./bin/semver.js" + }, + "files": [ + "bin", + "range.bnf", + "classes", + "functions", + "internal", + "ranges", + "index.js" + ], + "tap": { + "check-coverage": true, + "coverage-map": "map.js" + } +} diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/range.bnf b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/range.bnf new file mode 100644 index 0000000..d4c6ae0 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/range.bnf @@ -0,0 +1,16 @@ +range-set ::= range ( logical-or range ) * +logical-or ::= ( ' ' ) * '||' ( ' ' ) * +range ::= hyphen | simple ( ' ' simple ) * | '' +hyphen ::= partial ' - ' partial +simple ::= primitive | partial | tilde | caret +primitive ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial +partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )? +xr ::= 'x' | 'X' | '*' | nr +nr ::= '0' | [1-9] ( [0-9] ) * +tilde ::= '~' partial +caret ::= '^' partial +qualifier ::= ( '-' pre )? ( '+' build )? +pre ::= parts +build ::= parts +parts ::= part ( '.' part ) * +part ::= nr | [-0-9A-Za-z]+ diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/gtr.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/gtr.js new file mode 100644 index 0000000..db7e355 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/gtr.js @@ -0,0 +1,4 @@ +// Determine if version is greater than all the versions possible in the range. +const outside = require('./outside') +const gtr = (version, range, options) => outside(version, range, '>', options) +module.exports = gtr diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/intersects.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/intersects.js new file mode 100644 index 0000000..3d1a6f3 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/intersects.js @@ -0,0 +1,7 @@ +const Range = require('../classes/range') +const intersects = (r1, r2, options) => { + r1 = new Range(r1, options) + r2 = new Range(r2, options) + return r1.intersects(r2) +} +module.exports = intersects diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/ltr.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/ltr.js new file mode 100644 index 0000000..528a885 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/ltr.js @@ -0,0 +1,4 @@ +const outside = require('./outside') +// Determine if version is less than all the versions possible in the range +const ltr = (version, range, options) => outside(version, range, '<', options) +module.exports = ltr diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/max-satisfying.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/max-satisfying.js new file mode 100644 index 0000000..6e3d993 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/max-satisfying.js @@ -0,0 +1,25 @@ +const SemVer = require('../classes/semver') +const Range = require('../classes/range') + +const maxSatisfying = (versions, range, options) => { + let max = null + let maxSV = null + let rangeObj = null + try { + rangeObj = new Range(range, options) + } catch (er) { + return null + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + // satisfies(v, range, options) + if (!max || maxSV.compare(v) === -1) { + // compare(max, v, true) + max = v + maxSV = new SemVer(max, options) + } + } + }) + return max +} +module.exports = maxSatisfying diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/min-satisfying.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/min-satisfying.js new file mode 100644 index 0000000..9b60974 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/min-satisfying.js @@ -0,0 +1,24 @@ +const SemVer = require('../classes/semver') +const Range = require('../classes/range') +const minSatisfying = (versions, range, options) => { + let min = null + let minSV = null + let rangeObj = null + try { + rangeObj = new Range(range, options) + } catch (er) { + return null + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + // satisfies(v, range, options) + if (!min || minSV.compare(v) === 1) { + // compare(min, v, true) + min = v + minSV = new SemVer(min, options) + } + } + }) + return min +} +module.exports = minSatisfying diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/min-version.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/min-version.js new file mode 100644 index 0000000..7118d23 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/min-version.js @@ -0,0 +1,57 @@ +const SemVer = require('../classes/semver') +const Range = require('../classes/range') +const gt = require('../functions/gt') + +const minVersion = (range, loose) => { + range = new Range(range, loose) + + let minver = new SemVer('0.0.0') + if (range.test(minver)) { + return minver + } + + minver = new SemVer('0.0.0-0') + if (range.test(minver)) { + return minver + } + + minver = null + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i] + + comparators.forEach((comparator) => { + // Clone to avoid manipulating the comparator's semver object. + const compver = new SemVer(comparator.semver.version) + switch (comparator.operator) { + case '>': + if (compver.prerelease.length === 0) { + compver.patch++ + } else { + compver.prerelease.push(0) + } + compver.raw = compver.format() + /* fallthrough */ + case '': + case '>=': + if (!minver || gt(minver, compver)) { + minver = compver + } + break + case '<': + case '<=': + /* Ignore maximum versions */ + break + /* istanbul ignore next */ + default: + throw new Error(`Unexpected operation: ${comparator.operator}`) + } + }) + } + + if (minver && range.test(minver)) { + return minver + } + + return null +} +module.exports = minVersion diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/outside.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/outside.js new file mode 100644 index 0000000..e35ed11 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/outside.js @@ -0,0 +1,80 @@ +const SemVer = require('../classes/semver') +const Comparator = require('../classes/comparator') +const {ANY} = Comparator +const Range = require('../classes/range') +const satisfies = require('../functions/satisfies') +const gt = require('../functions/gt') +const lt = require('../functions/lt') +const lte = require('../functions/lte') +const gte = require('../functions/gte') + +const outside = (version, range, hilo, options) => { + version = new SemVer(version, options) + range = new Range(range, options) + + let gtfn, ltefn, ltfn, comp, ecomp + switch (hilo) { + case '>': + gtfn = gt + ltefn = lte + ltfn = lt + comp = '>' + ecomp = '>=' + break + case '<': + gtfn = lt + ltefn = gte + ltfn = gt + comp = '<' + ecomp = '<=' + break + default: + throw new TypeError('Must provide a hilo val of "<" or ">"') + } + + // If it satisifes the range it is not outside + if (satisfies(version, range, options)) { + return false + } + + // From now on, variable terms are as if we're in "gtr" mode. + // but note that everything is flipped for the "ltr" function. + + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i] + + let high = null + let low = null + + comparators.forEach((comparator) => { + if (comparator.semver === ANY) { + comparator = new Comparator('>=0.0.0') + } + high = high || comparator + low = low || comparator + if (gtfn(comparator.semver, high.semver, options)) { + high = comparator + } else if (ltfn(comparator.semver, low.semver, options)) { + low = comparator + } + }) + + // If the edge version comparator has a operator then our version + // isn't outside it + if (high.operator === comp || high.operator === ecomp) { + return false + } + + // If the lowest version comparator has an operator and our version + // is less than it then it isn't higher than the range + if ((!low.operator || low.operator === comp) && + ltefn(version, low.semver)) { + return false + } else if (low.operator === ecomp && ltfn(version, low.semver)) { + return false + } + } + return true +} + +module.exports = outside diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/to-comparators.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/to-comparators.js new file mode 100644 index 0000000..6c8bc7e --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/to-comparators.js @@ -0,0 +1,8 @@ +const Range = require('../classes/range') + +// Mostly just for testing and legacy API reasons +const toComparators = (range, options) => + new Range(range, options).set + .map(comp => comp.map(c => c.value).join(' ').trim().split(' ')) + +module.exports = toComparators diff --git a/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/valid.js b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/valid.js new file mode 100644 index 0000000..365f356 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/valid.js @@ -0,0 +1,11 @@ +const Range = require('../classes/range') +const validRange = (range, options) => { + try { + // Return '*' instead of '' so that truthiness works. + // This will throw if it's invalid anyway + return new Range(range, options).range || '*' + } catch (er) { + return null + } +} +module.exports = validRange diff --git a/homework7/project_express/node_modules/simple-update-notifier/package.json b/homework7/project_express/node_modules/simple-update-notifier/package.json new file mode 100644 index 0000000..8c0f330 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/package.json @@ -0,0 +1,97 @@ +{ + "name": "simple-update-notifier", + "version": "1.0.7", + "description": "Simple update notifier to check for npm updates for cli applications", + "main": "build/index.js", + "types": "build/index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/alexbrazier/simple-update-notifier.git" + }, + "homepage": "https://github.com/alexbrazier/simple-update-notifier.git", + "author": "alexbrazier", + "license": "MIT", + "engines": { + "node": ">=8.10.0" + }, + "scripts": { + "test": "jest src", + "build": "rollup -c rollup.config.js", + "prettier:check": "prettier --check src/**/*.ts", + "prettier": "prettier --write src/**/*.ts", + "eslint": "eslint src/**/*.ts", + "lint": "yarn prettier:check && yarn eslint", + "prepare": "yarn lint && yarn build", + "release": "release-it" + }, + "dependencies": { + "semver": "~7.0.0" + }, + "devDependencies": { + "@babel/preset-env": "^7.18.2", + "@babel/preset-typescript": "^7.17.12", + "@release-it/conventional-changelog": "^5.0.0", + "@types/jest": "^28.1.3", + "@types/node": "^18.0.0", + "@typescript-eslint/eslint-plugin": "^5.29.0", + "@typescript-eslint/parser": "^5.29.0", + "eslint": "^8.18.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-prettier": "^4.0.0", + "jest": "^28.1.1", + "prettier": "^2.7.1", + "release-it": "^15.1.1", + "rollup": "^2.75.7", + "rollup-plugin-ts": "^3.0.2", + "typescript": "^4.7.4" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org/" + }, + "files": [ + "build", + "src" + ], + "release-it": { + "git": { + "commitMessage": "chore: release ${version}", + "tagName": "v${version}" + }, + "npm": { + "publish": true + }, + "github": { + "release": true + }, + "plugins": { + "@release-it/conventional-changelog": { + "preset": "angular", + "infile": "CHANGELOG.md" + } + } + }, + "eslintConfig": { + "plugins": [ + "@typescript-eslint", + "prettier" + ], + "extends": [ + "prettier", + "eslint:recommended", + "plugin:@typescript-eslint/recommended" + ], + "parser": "@typescript-eslint/parser", + "rules": { + "prettier/prettier": [ + "error", + { + "quoteProps": "consistent", + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "es5", + "useTabs": false + } + ] + } + } +} diff --git a/homework7/project_express/node_modules/simple-update-notifier/src/borderedText.ts b/homework7/project_express/node_modules/simple-update-notifier/src/borderedText.ts new file mode 100644 index 0000000..7145ac2 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/src/borderedText.ts @@ -0,0 +1,12 @@ +const borderedText = (text: string) => { + const lines = text.split('\n'); + const width = Math.max(...lines.map((l) => l.length)); + const res = [`┌${'─'.repeat(width + 2)}┐`]; + for (const line of lines) { + res.push(`│ ${line.padEnd(width)} │`); + } + res.push(`└${'─'.repeat(width + 2)}┘`); + return res.join('\n'); +}; + +export default borderedText; diff --git a/homework7/project_express/node_modules/simple-update-notifier/src/cache.spec.ts b/homework7/project_express/node_modules/simple-update-notifier/src/cache.spec.ts new file mode 100644 index 0000000..cea66fa --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/src/cache.spec.ts @@ -0,0 +1,12 @@ +import { createConfigDir, getLastUpdate, saveLastUpdate } from './cache'; + +createConfigDir(); + +jest.useFakeTimers().setSystemTime(new Date('2022-01-01')); + +const fakeTime = new Date('2022-01-01').getTime(); + +test('can save update then get the update details', () => { + saveLastUpdate('test'); + expect(getLastUpdate('test')).toBe(fakeTime); +}); diff --git a/homework7/project_express/node_modules/simple-update-notifier/src/cache.ts b/homework7/project_express/node_modules/simple-update-notifier/src/cache.ts new file mode 100644 index 0000000..97a73e7 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/src/cache.ts @@ -0,0 +1,41 @@ +import os from 'os'; +import path from 'path'; +import fs from 'fs'; + +const homeDirectory = os.homedir(); +const configDir = + process.env.XDG_CONFIG_HOME || + path.join(homeDirectory, '.config', 'simple-update-notifier'); + +const getConfigFile = (packageName: string) => { + return path.join(configDir, `${packageName}.json`); +}; + +export const createConfigDir = () => { + if (!fs.existsSync(configDir)) { + fs.mkdirSync(configDir, { recursive: true }); + } +}; + +export const getLastUpdate = (packageName: string) => { + const configFile = getConfigFile(packageName); + + try { + if (!fs.existsSync(configFile)) { + return undefined; + } + const file = JSON.parse(fs.readFileSync(configFile, 'utf8')); + return file.lastUpdateCheck as number; + } catch { + return undefined; + } +}; + +export const saveLastUpdate = (packageName: string) => { + const configFile = getConfigFile(packageName); + + fs.writeFileSync( + configFile, + JSON.stringify({ lastUpdateCheck: new Date().getTime() }) + ); +}; diff --git a/homework7/project_express/node_modules/simple-update-notifier/src/getDistVersion.spec.ts b/homework7/project_express/node_modules/simple-update-notifier/src/getDistVersion.spec.ts new file mode 100644 index 0000000..b78a42e --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/src/getDistVersion.spec.ts @@ -0,0 +1,35 @@ +import Stream from 'stream'; +import https from 'https'; +import getDistVersion from './getDistVersion'; + +jest.mock('https', () => ({ + get: jest.fn(), +})); + +test('Valid response returns version', async () => { + const st = new Stream(); + (https.get as jest.Mock).mockImplementation((url, cb) => { + cb(st); + + st.emit('data', '{"latest":"1.0.0"}'); + st.emit('end'); + }); + + const version = await getDistVersion('test', 'latest'); + + expect(version).toEqual('1.0.0'); +}); + +test('Invalid response throws error', async () => { + const st = new Stream(); + (https.get as jest.Mock).mockImplementation((url, cb) => { + cb(st); + + st.emit('data', 'some invalid json'); + st.emit('end'); + }); + + expect(getDistVersion('test', 'latest')).rejects.toThrow( + 'Could not parse version response' + ); +}); diff --git a/homework7/project_express/node_modules/simple-update-notifier/src/getDistVersion.ts b/homework7/project_express/node_modules/simple-update-notifier/src/getDistVersion.ts new file mode 100644 index 0000000..d474e1f --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/src/getDistVersion.ts @@ -0,0 +1,29 @@ +import https from 'https'; + +const getDistVersion = async (packageName: string, distTag: string) => { + const url = `https://registry.npmjs.org/-/package/${packageName}/dist-tags`; + + return new Promise((resolve, reject) => { + https + .get(url, (res) => { + let body = ''; + + res.on('data', (chunk) => (body += chunk)); + res.on('end', () => { + try { + const json = JSON.parse(body); + const version = json[distTag]; + if (!version) { + reject(new Error('Error getting version')); + } + resolve(version); + } catch { + reject(new Error('Could not parse version response')); + } + }); + }) + .on('error', (err) => reject(err)); + }); +}; + +export default getDistVersion; diff --git a/homework7/project_express/node_modules/simple-update-notifier/src/hasNewVersion.spec.ts b/homework7/project_express/node_modules/simple-update-notifier/src/hasNewVersion.spec.ts new file mode 100644 index 0000000..af7ab22 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/src/hasNewVersion.spec.ts @@ -0,0 +1,82 @@ +import hasNewVersion from './hasNewVersion'; +import { getLastUpdate } from './cache'; +import getDistVersion from './getDistVersion'; + +jest.mock('./getDistVersion', () => jest.fn().mockReturnValue('1.0.0')); +jest.mock('./cache', () => ({ + getLastUpdate: jest.fn().mockReturnValue(undefined), + createConfigDir: jest.fn(), + saveLastUpdate: jest.fn(), +})); + +const pkg = { name: 'test', version: '1.0.0' }; + +afterEach(() => jest.clearAllMocks()); + +const defaultArgs = { + pkg, + shouldNotifyInNpmScript: true, + alwaysRun: true, +}; + +test('it should not trigger update for same version', async () => { + const newVersion = await hasNewVersion(defaultArgs); + + expect(newVersion).toBe(false); +}); + +test('it should trigger update for patch version bump', async () => { + (getDistVersion as jest.Mock).mockReturnValue('1.0.1'); + + const newVersion = await hasNewVersion(defaultArgs); + + expect(newVersion).toBe('1.0.1'); +}); + +test('it should trigger update for minor version bump', async () => { + (getDistVersion as jest.Mock).mockReturnValue('1.1.0'); + + const newVersion = await hasNewVersion(defaultArgs); + + expect(newVersion).toBe('1.1.0'); +}); + +test('it should trigger update for major version bump', async () => { + (getDistVersion as jest.Mock).mockReturnValue('2.0.0'); + + const newVersion = await hasNewVersion(defaultArgs); + + expect(newVersion).toBe('2.0.0'); +}); + +test('it should not trigger update if version is lower', async () => { + (getDistVersion as jest.Mock).mockReturnValue('0.0.9'); + + const newVersion = await hasNewVersion(defaultArgs); + + expect(newVersion).toBe(false); +}); + +it('should trigger update check if last update older than config', async () => { + const TWO_WEEKS = new Date().getTime() - 1000 * 60 * 60 * 24 * 14; + (getLastUpdate as jest.Mock).mockReturnValue(TWO_WEEKS); + const newVersion = await hasNewVersion({ + pkg, + shouldNotifyInNpmScript: true, + }); + + expect(newVersion).toBe(false); + expect(getDistVersion).toHaveBeenCalled(); +}); + +it('should not trigger update check if last update is too recent', async () => { + const TWELVE_HOURS = new Date().getTime() - 1000 * 60 * 60 * 12; + (getLastUpdate as jest.Mock).mockReturnValue(TWELVE_HOURS); + const newVersion = await hasNewVersion({ + pkg, + shouldNotifyInNpmScript: true, + }); + + expect(newVersion).toBe(false); + expect(getDistVersion).not.toHaveBeenCalled(); +}); diff --git a/homework7/project_express/node_modules/simple-update-notifier/src/hasNewVersion.ts b/homework7/project_express/node_modules/simple-update-notifier/src/hasNewVersion.ts new file mode 100644 index 0000000..a55c747 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/src/hasNewVersion.ts @@ -0,0 +1,30 @@ +import semver from 'semver'; +import { createConfigDir, getLastUpdate, saveLastUpdate } from './cache'; +import getDistVersion from './getDistVersion'; +import { IUpdate } from './types'; + +const hasNewVersion = async ({ + pkg, + updateCheckInterval = 1000 * 60 * 60 * 24, + distTag = 'latest', + alwaysRun, +}: IUpdate) => { + createConfigDir(); + const lastUpdateCheck = getLastUpdate(pkg.name); + if ( + alwaysRun || + !lastUpdateCheck || + lastUpdateCheck < new Date().getTime() - updateCheckInterval + ) { + const latestVersion = await getDistVersion(pkg.name, distTag); + saveLastUpdate(pkg.name); + if (semver.gt(latestVersion, pkg.version)) { + return latestVersion; + } + return false; + } else { + return false; + } +}; + +export default hasNewVersion; diff --git a/homework7/project_express/node_modules/simple-update-notifier/src/index.spec.ts b/homework7/project_express/node_modules/simple-update-notifier/src/index.spec.ts new file mode 100644 index 0000000..77d5de1 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/src/index.spec.ts @@ -0,0 +1,27 @@ +import simpleUpdateNotifier from '.'; +import hasNewVersion from './hasNewVersion'; + +const consoleSpy = jest.spyOn(console, 'log'); + +jest.mock('./hasNewVersion', () => jest.fn().mockResolvedValue('2.0.0')); + +beforeEach(jest.clearAllMocks); + +test('it logs message if update is available', async () => { + await simpleUpdateNotifier({ + pkg: { name: 'test', version: '1.0.0' }, + alwaysRun: true, + }); + + expect(consoleSpy).toHaveBeenCalledTimes(1); +}); + +test('it does not log message if update is not available', async () => { + (hasNewVersion as jest.Mock).mockResolvedValue(false); + await simpleUpdateNotifier({ + pkg: { name: 'test', version: '2.0.0' }, + alwaysRun: true, + }); + + expect(consoleSpy).toHaveBeenCalledTimes(0); +}); diff --git a/homework7/project_express/node_modules/simple-update-notifier/src/index.ts b/homework7/project_express/node_modules/simple-update-notifier/src/index.ts new file mode 100644 index 0000000..69c48a2 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/src/index.ts @@ -0,0 +1,28 @@ +import isNpmOrYarn from './isNpmOrYarn'; +import hasNewVersion from './hasNewVersion'; +import { IUpdate } from './types'; +import borderedText from './borderedText'; + +const simpleUpdateNotifier = async (args: IUpdate) => { + if ( + !args.alwaysRun && + (!process.stdout.isTTY || (isNpmOrYarn && !args.shouldNotifyInNpmScript)) + ) { + return; + } + + try { + const latestVersion = await hasNewVersion(args); + if (latestVersion) { + console.log( + borderedText(`New version of ${args.pkg.name} available! +Current Version: ${args.pkg.version} +Latest Version: ${latestVersion}`) + ); + } + } catch { + // Catch any network errors or cache writing errors so module doesn't cause a crash + } +}; + +export default simpleUpdateNotifier; diff --git a/homework7/project_express/node_modules/simple-update-notifier/src/isNpmOrYarn.ts b/homework7/project_express/node_modules/simple-update-notifier/src/isNpmOrYarn.ts new file mode 100644 index 0000000..ee4c837 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/src/isNpmOrYarn.ts @@ -0,0 +1,12 @@ +import process from 'process'; + +const packageJson = process.env.npm_package_json; +const userAgent = process.env.npm_config_user_agent; +const isNpm6 = Boolean(userAgent && userAgent.startsWith('npm')); +const isNpm7 = Boolean(packageJson && packageJson.endsWith('package.json')); + +const isNpm = isNpm6 || isNpm7; +const isYarn = Boolean(userAgent && userAgent.startsWith('yarn')); +const isNpmOrYarn = isNpm || isYarn; + +export default isNpmOrYarn; diff --git a/homework7/project_express/node_modules/simple-update-notifier/src/types.ts b/homework7/project_express/node_modules/simple-update-notifier/src/types.ts new file mode 100644 index 0000000..cb94563 --- /dev/null +++ b/homework7/project_express/node_modules/simple-update-notifier/src/types.ts @@ -0,0 +1,7 @@ +export interface IUpdate { + pkg: { name: string; version: string }; + updateCheckInterval?: number; + shouldNotifyInNpmScript?: boolean; + distTag?: string; + alwaysRun?: boolean; +} diff --git a/homework7/project_express/node_modules/source-map/.npmignore b/homework7/project_express/node_modules/source-map/.npmignore new file mode 100644 index 0000000..3dddf3f --- /dev/null +++ b/homework7/project_express/node_modules/source-map/.npmignore @@ -0,0 +1,2 @@ +dist/* +node_modules/* diff --git a/homework7/project_express/node_modules/source-map/.travis.yml b/homework7/project_express/node_modules/source-map/.travis.yml new file mode 100644 index 0000000..ddc9c4f --- /dev/null +++ b/homework7/project_express/node_modules/source-map/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.8 + - "0.10" \ No newline at end of file diff --git a/homework7/project_express/node_modules/source-map/CHANGELOG.md b/homework7/project_express/node_modules/source-map/CHANGELOG.md new file mode 100644 index 0000000..2e7ca5d --- /dev/null +++ b/homework7/project_express/node_modules/source-map/CHANGELOG.md @@ -0,0 +1,194 @@ +# Change Log + +## 0.1.43 + +* Performance improvements for `SourceMapGenerator` and `SourceNode`. See issue + #148 for some discussion and issues #150, #151, and #152 for implementations. + +## 0.1.42 + +* Fix an issue where `SourceNode`s from different versions of the source-map + library couldn't be used in conjunction with each other. See issue #142. + +## 0.1.41 + +* Fix a bug with getting the source content of relative sources with a "./" + prefix. See issue #145 and [Bug 1090768](bugzil.la/1090768). + +* Add the `SourceMapConsumer.prototype.computeColumnSpans` method to compute the + column span of each mapping. + +* Add the `SourceMapConsumer.prototype.allGeneratedPositionsFor` method to find + all generated positions associated with a given original source and line. + +## 0.1.40 + +* Performance improvements for parsing source maps in SourceMapConsumer. + +## 0.1.39 + +* Fix a bug where setting a source's contents to null before any source content + had been set before threw a TypeError. See issue #131. + +## 0.1.38 + +* Fix a bug where finding relative paths from an empty path were creating + absolute paths. See issue #129. + +## 0.1.37 + +* Fix a bug where if the source root was an empty string, relative source paths + would turn into absolute source paths. Issue #124. + +## 0.1.36 + +* Allow the `names` mapping property to be an empty string. Issue #121. + +## 0.1.35 + +* A third optional parameter was added to `SourceNode.fromStringWithSourceMap` + to specify a path that relative sources in the second parameter should be + relative to. Issue #105. + +* If no file property is given to a `SourceMapGenerator`, then the resulting + source map will no longer have a `null` file property. The property will + simply not exist. Issue #104. + +* Fixed a bug where consecutive newlines were ignored in `SourceNode`s. + Issue #116. + +## 0.1.34 + +* Make `SourceNode` work with windows style ("\r\n") newlines. Issue #103. + +* Fix bug involving source contents and the + `SourceMapGenerator.prototype.applySourceMap`. Issue #100. + +## 0.1.33 + +* Fix some edge cases surrounding path joining and URL resolution. + +* Add a third parameter for relative path to + `SourceMapGenerator.prototype.applySourceMap`. + +* Fix issues with mappings and EOLs. + +## 0.1.32 + +* Fixed a bug where SourceMapConsumer couldn't handle negative relative columns + (issue 92). + +* Fixed test runner to actually report number of failed tests as its process + exit code. + +* Fixed a typo when reporting bad mappings (issue 87). + +## 0.1.31 + +* Delay parsing the mappings in SourceMapConsumer until queried for a source + location. + +* Support Sass source maps (which at the time of writing deviate from the spec + in small ways) in SourceMapConsumer. + +## 0.1.30 + +* Do not join source root with a source, when the source is a data URI. + +* Extend the test runner to allow running single specific test files at a time. + +* Performance improvements in `SourceNode.prototype.walk` and + `SourceMapConsumer.prototype.eachMapping`. + +* Source map browser builds will now work inside Workers. + +* Better error messages when attempting to add an invalid mapping to a + `SourceMapGenerator`. + +## 0.1.29 + +* Allow duplicate entries in the `names` and `sources` arrays of source maps + (usually from TypeScript) we are parsing. Fixes github issue 72. + +## 0.1.28 + +* Skip duplicate mappings when creating source maps from SourceNode; github + issue 75. + +## 0.1.27 + +* Don't throw an error when the `file` property is missing in SourceMapConsumer, + we don't use it anyway. + +## 0.1.26 + +* Fix SourceNode.fromStringWithSourceMap for empty maps. Fixes github issue 70. + +## 0.1.25 + +* Make compatible with browserify + +## 0.1.24 + +* Fix issue with absolute paths and `file://` URIs. See + https://bugzilla.mozilla.org/show_bug.cgi?id=885597 + +## 0.1.23 + +* Fix issue with absolute paths and sourcesContent, github issue 64. + +## 0.1.22 + +* Ignore duplicate mappings in SourceMapGenerator. Fixes github issue 21. + +## 0.1.21 + +* Fixed handling of sources that start with a slash so that they are relative to + the source root's host. + +## 0.1.20 + +* Fixed github issue #43: absolute URLs aren't joined with the source root + anymore. + +## 0.1.19 + +* Using Travis CI to run tests. + +## 0.1.18 + +* Fixed a bug in the handling of sourceRoot. + +## 0.1.17 + +* Added SourceNode.fromStringWithSourceMap. + +## 0.1.16 + +* Added missing documentation. + +* Fixed the generating of empty mappings in SourceNode. + +## 0.1.15 + +* Added SourceMapGenerator.applySourceMap. + +## 0.1.14 + +* The sourceRoot is now handled consistently. + +## 0.1.13 + +* Added SourceMapGenerator.fromSourceMap. + +## 0.1.12 + +* SourceNode now generates empty mappings too. + +## 0.1.11 + +* Added name support to SourceNode. + +## 0.1.10 + +* Added sourcesContent support to the customer and generator. diff --git a/homework7/project_express/node_modules/source-map/LICENSE b/homework7/project_express/node_modules/source-map/LICENSE new file mode 100644 index 0000000..ed1b7cf --- /dev/null +++ b/homework7/project_express/node_modules/source-map/LICENSE @@ -0,0 +1,28 @@ + +Copyright (c) 2009-2011, Mozilla Foundation and contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the names of the Mozilla Foundation nor the names of project + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/homework7/project_express/node_modules/source-map/Makefile.dryice.js b/homework7/project_express/node_modules/source-map/Makefile.dryice.js new file mode 100644 index 0000000..d6fc26a --- /dev/null +++ b/homework7/project_express/node_modules/source-map/Makefile.dryice.js @@ -0,0 +1,166 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +var path = require('path'); +var fs = require('fs'); +var copy = require('dryice').copy; + +function removeAmdefine(src) { + src = String(src).replace( + /if\s*\(typeof\s*define\s*!==\s*'function'\)\s*{\s*var\s*define\s*=\s*require\('amdefine'\)\(module,\s*require\);\s*}\s*/g, + ''); + src = src.replace( + /\b(define\(.*)('amdefine',?)/gm, + '$1'); + return src; +} +removeAmdefine.onRead = true; + +function makeNonRelative(src) { + return src + .replace(/require\('.\//g, 'require(\'source-map/') + .replace(/\.\.\/\.\.\/lib\//g, ''); +} +makeNonRelative.onRead = true; + +function buildBrowser() { + console.log('\nCreating dist/source-map.js'); + + var project = copy.createCommonJsProject({ + roots: [ path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/mini-require.js', + { + project: project, + require: [ 'source-map/source-map-generator', + 'source-map/source-map-consumer', + 'source-map/source-node'] + }, + 'build/suffix-browser.js' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine + ], + dest: 'dist/source-map.js' + }); +} + +function buildBrowserMin() { + console.log('\nCreating dist/source-map.min.js'); + + copy({ + source: 'dist/source-map.js', + filter: copy.filter.uglifyjs, + dest: 'dist/source-map.min.js' + }); +} + +function buildFirefox() { + console.log('\nCreating dist/SourceMap.jsm'); + + var project = copy.createCommonJsProject({ + roots: [ path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/prefix-source-map.jsm', + { + project: project, + require: [ 'source-map/source-map-consumer', + 'source-map/source-map-generator', + 'source-map/source-node' ] + }, + 'build/suffix-source-map.jsm' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine, + makeNonRelative + ], + dest: 'dist/SourceMap.jsm' + }); + + // Create dist/test/Utils.jsm + console.log('\nCreating dist/test/Utils.jsm'); + + project = copy.createCommonJsProject({ + roots: [ __dirname, path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/prefix-utils.jsm', + 'build/assert-shim.js', + { + project: project, + require: [ 'test/source-map/util' ] + }, + 'build/suffix-utils.jsm' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine, + makeNonRelative + ], + dest: 'dist/test/Utils.jsm' + }); + + function isTestFile(f) { + return /^test\-.*?\.js/.test(f); + } + + var testFiles = fs.readdirSync(path.join(__dirname, 'test', 'source-map')).filter(isTestFile); + + testFiles.forEach(function (testFile) { + console.log('\nCreating', path.join('dist', 'test', testFile.replace(/\-/g, '_'))); + + copy({ + source: [ + 'build/test-prefix.js', + path.join('test', 'source-map', testFile), + 'build/test-suffix.js' + ], + filter: [ + removeAmdefine, + makeNonRelative, + function (input, source) { + return input.replace('define(', + 'define("' + + path.join('test', 'source-map', testFile.replace(/\.js$/, '')) + + '", ["require", "exports", "module"], '); + }, + function (input, source) { + return input.replace('{THIS_MODULE}', function () { + return "test/source-map/" + testFile.replace(/\.js$/, ''); + }); + } + ], + dest: path.join('dist', 'test', testFile.replace(/\-/g, '_')) + }); + }); +} + +function ensureDir(name) { + var dirExists = false; + try { + dirExists = fs.statSync(name).isDirectory(); + } catch (err) {} + + if (!dirExists) { + fs.mkdirSync(name, 0777); + } +} + +ensureDir("dist"); +ensureDir("dist/test"); +buildFirefox(); +buildBrowser(); +buildBrowserMin(); diff --git a/homework7/project_express/node_modules/source-map/README.md b/homework7/project_express/node_modules/source-map/README.md new file mode 100644 index 0000000..59767aa --- /dev/null +++ b/homework7/project_express/node_modules/source-map/README.md @@ -0,0 +1,475 @@ +# Source Map + +This is a library to generate and consume the source map format +[described here][format]. + +This library is written in the Asynchronous Module Definition format, and works +in the following environments: + +* Modern Browsers supporting ECMAScript 5 (either after the build, or with an + AMD loader such as RequireJS) + +* Inside Firefox (as a JSM file, after the build) + +* With NodeJS versions 0.8.X and higher + +## Node + + $ npm install source-map + +## Building from Source (for everywhere else) + +Install Node and then run + + $ git clone https://fitzgen@github.com/mozilla/source-map.git + $ cd source-map + $ npm link . + +Next, run + + $ node Makefile.dryice.js + +This should spew a bunch of stuff to stdout, and create the following files: + +* `dist/source-map.js` - The unminified browser version. + +* `dist/source-map.min.js` - The minified browser version. + +* `dist/SourceMap.jsm` - The JavaScript Module for inclusion in Firefox source. + +## Examples + +### Consuming a source map + + var rawSourceMap = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourceRoot: 'http://example.com/www/js/', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + + var smc = new SourceMapConsumer(rawSourceMap); + + console.log(smc.sources); + // [ 'http://example.com/www/js/one.js', + // 'http://example.com/www/js/two.js' ] + + console.log(smc.originalPositionFor({ + line: 2, + column: 28 + })); + // { source: 'http://example.com/www/js/two.js', + // line: 2, + // column: 10, + // name: 'n' } + + console.log(smc.generatedPositionFor({ + source: 'http://example.com/www/js/two.js', + line: 2, + column: 10 + })); + // { line: 2, column: 28 } + + smc.eachMapping(function (m) { + // ... + }); + +### Generating a source map + +In depth guide: +[**Compiling to JavaScript, and Debugging with Source Maps**](https://hacks.mozilla.org/2013/05/compiling-to-javascript-and-debugging-with-source-maps/) + +#### With SourceNode (high level API) + + function compile(ast) { + switch (ast.type) { + case 'BinaryExpression': + return new SourceNode( + ast.location.line, + ast.location.column, + ast.location.source, + [compile(ast.left), " + ", compile(ast.right)] + ); + case 'Literal': + return new SourceNode( + ast.location.line, + ast.location.column, + ast.location.source, + String(ast.value) + ); + // ... + default: + throw new Error("Bad AST"); + } + } + + var ast = parse("40 + 2", "add.js"); + console.log(compile(ast).toStringWithSourceMap({ + file: 'add.js' + })); + // { code: '40 + 2', + // map: [object SourceMapGenerator] } + +#### With SourceMapGenerator (low level API) + + var map = new SourceMapGenerator({ + file: "source-mapped.js" + }); + + map.addMapping({ + generated: { + line: 10, + column: 35 + }, + source: "foo.js", + original: { + line: 33, + column: 2 + }, + name: "christopher" + }); + + console.log(map.toString()); + // '{"version":3,"file":"source-mapped.js","sources":["foo.js"],"names":["christopher"],"mappings":";;;;;;;;;mCAgCEA"}' + +## API + +Get a reference to the module: + + // NodeJS + var sourceMap = require('source-map'); + + // Browser builds + var sourceMap = window.sourceMap; + + // Inside Firefox + let sourceMap = {}; + Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap); + +### SourceMapConsumer + +A SourceMapConsumer instance represents a parsed source map which we can query +for information about the original file positions by giving it a file position +in the generated source. + +#### new SourceMapConsumer(rawSourceMap) + +The only parameter is the raw source map (either as a string which can be +`JSON.parse`'d, or an object). According to the spec, source maps have the +following attributes: + +* `version`: Which version of the source map spec this map is following. + +* `sources`: An array of URLs to the original source files. + +* `names`: An array of identifiers which can be referrenced by individual + mappings. + +* `sourceRoot`: Optional. The URL root from which all sources are relative. + +* `sourcesContent`: Optional. An array of contents of the original source files. + +* `mappings`: A string of base64 VLQs which contain the actual mappings. + +* `file`: Optional. The generated filename this source map is associated with. + +#### SourceMapConsumer.prototype.computeColumnSpans() + +Compute the last column for each generated mapping. The last column is +inclusive. + +#### SourceMapConsumer.prototype.originalPositionFor(generatedPosition) + +Returns the original source, line, and column information for the generated +source's line and column positions provided. The only argument is an object with +the following properties: + +* `line`: The line number in the generated source. + +* `column`: The column number in the generated source. + +and an object is returned with the following properties: + +* `source`: The original source file, or null if this information is not + available. + +* `line`: The line number in the original source, or null if this information is + not available. + +* `column`: The column number in the original source, or null or null if this + information is not available. + +* `name`: The original identifier, or null if this information is not available. + +#### SourceMapConsumer.prototype.generatedPositionFor(originalPosition) + +Returns the generated line and column information for the original source, +line, and column positions provided. The only argument is an object with +the following properties: + +* `source`: The filename of the original source. + +* `line`: The line number in the original source. + +* `column`: The column number in the original source. + +and an object is returned with the following properties: + +* `line`: The line number in the generated source, or null. + +* `column`: The column number in the generated source, or null. + +#### SourceMapConsumer.prototype.allGeneratedPositionsFor(originalPosition) + +Returns all generated line and column information for the original source +and line provided. The only argument is an object with the following +properties: + +* `source`: The filename of the original source. + +* `line`: The line number in the original source. + +and an array of objects is returned, each with the following properties: + +* `line`: The line number in the generated source, or null. + +* `column`: The column number in the generated source, or null. + +#### SourceMapConsumer.prototype.sourceContentFor(source) + +Returns the original source content for the source provided. The only +argument is the URL of the original source file. + +#### SourceMapConsumer.prototype.eachMapping(callback, context, order) + +Iterate over each mapping between an original source/line/column and a +generated line/column in this source map. + +* `callback`: The function that is called with each mapping. Mappings have the + form `{ source, generatedLine, generatedColumn, originalLine, originalColumn, + name }` + +* `context`: Optional. If specified, this object will be the value of `this` + every time that `callback` is called. + +* `order`: Either `SourceMapConsumer.GENERATED_ORDER` or + `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to iterate over + the mappings sorted by the generated file's line/column order or the + original's source/line/column order, respectively. Defaults to + `SourceMapConsumer.GENERATED_ORDER`. + +### SourceMapGenerator + +An instance of the SourceMapGenerator represents a source map which is being +built incrementally. + +#### new SourceMapGenerator([startOfSourceMap]) + +You may pass an object with the following properties: + +* `file`: The filename of the generated source that this source map is + associated with. + +* `sourceRoot`: A root for all relative URLs in this source map. + +* `skipValidation`: Optional. When `true`, disables validation of mappings as + they are added. This can improve performance but should be used with + discretion, as a last resort. Even then, one should avoid using this flag when + running tests, if possible. + +#### SourceMapGenerator.fromSourceMap(sourceMapConsumer) + +Creates a new SourceMapGenerator based on a SourceMapConsumer + +* `sourceMapConsumer` The SourceMap. + +#### SourceMapGenerator.prototype.addMapping(mapping) + +Add a single mapping from original source line and column to the generated +source's line and column for this source map being created. The mapping object +should have the following properties: + +* `generated`: An object with the generated line and column positions. + +* `original`: An object with the original line and column positions. + +* `source`: The original source file (relative to the sourceRoot). + +* `name`: An optional original token name for this mapping. + +#### SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent) + +Set the source content for an original source file. + +* `sourceFile` the URL of the original source file. + +* `sourceContent` the content of the source file. + +#### SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile[, sourceMapPath]]) + +Applies a SourceMap for a source file to the SourceMap. +Each mapping to the supplied source file is rewritten using the +supplied SourceMap. Note: The resolution for the resulting mappings +is the minimium of this map and the supplied map. + +* `sourceMapConsumer`: The SourceMap to be applied. + +* `sourceFile`: Optional. The filename of the source file. + If omitted, sourceMapConsumer.file will be used, if it exists. + Otherwise an error will be thrown. + +* `sourceMapPath`: Optional. The dirname of the path to the SourceMap + to be applied. If relative, it is relative to the SourceMap. + + This parameter is needed when the two SourceMaps aren't in the same + directory, and the SourceMap to be applied contains relative source + paths. If so, those relative source paths need to be rewritten + relative to the SourceMap. + + If omitted, it is assumed that both SourceMaps are in the same directory, + thus not needing any rewriting. (Supplying `'.'` has the same effect.) + +#### SourceMapGenerator.prototype.toString() + +Renders the source map being generated to a string. + +### SourceNode + +SourceNodes provide a way to abstract over interpolating and/or concatenating +snippets of generated JavaScript source code, while maintaining the line and +column information associated between those snippets and the original source +code. This is useful as the final intermediate representation a compiler might +use before outputting the generated JS and source map. + +#### new SourceNode([line, column, source[, chunk[, name]]]) + +* `line`: The original line number associated with this source node, or null if + it isn't associated with an original line. + +* `column`: The original column number associated with this source node, or null + if it isn't associated with an original column. + +* `source`: The original source's filename; null if no filename is provided. + +* `chunk`: Optional. Is immediately passed to `SourceNode.prototype.add`, see + below. + +* `name`: Optional. The original identifier. + +#### SourceNode.fromStringWithSourceMap(code, sourceMapConsumer[, relativePath]) + +Creates a SourceNode from generated code and a SourceMapConsumer. + +* `code`: The generated code + +* `sourceMapConsumer` The SourceMap for the generated code + +* `relativePath` The optional path that relative sources in `sourceMapConsumer` + should be relative to. + +#### SourceNode.prototype.add(chunk) + +Add a chunk of generated JS to this source node. + +* `chunk`: A string snippet of generated JS code, another instance of + `SourceNode`, or an array where each member is one of those things. + +#### SourceNode.prototype.prepend(chunk) + +Prepend a chunk of generated JS to this source node. + +* `chunk`: A string snippet of generated JS code, another instance of + `SourceNode`, or an array where each member is one of those things. + +#### SourceNode.prototype.setSourceContent(sourceFile, sourceContent) + +Set the source content for a source file. This will be added to the +`SourceMap` in the `sourcesContent` field. + +* `sourceFile`: The filename of the source file + +* `sourceContent`: The content of the source file + +#### SourceNode.prototype.walk(fn) + +Walk over the tree of JS snippets in this node and its children. The walking +function is called once for each snippet of JS and is passed that snippet and +the its original associated source's line/column location. + +* `fn`: The traversal function. + +#### SourceNode.prototype.walkSourceContents(fn) + +Walk over the tree of SourceNodes. The walking function is called for each +source file content and is passed the filename and source content. + +* `fn`: The traversal function. + +#### SourceNode.prototype.join(sep) + +Like `Array.prototype.join` except for SourceNodes. Inserts the separator +between each of this source node's children. + +* `sep`: The separator. + +#### SourceNode.prototype.replaceRight(pattern, replacement) + +Call `String.prototype.replace` on the very right-most source snippet. Useful +for trimming whitespace from the end of a source node, etc. + +* `pattern`: The pattern to replace. + +* `replacement`: The thing to replace the pattern with. + +#### SourceNode.prototype.toString() + +Return the string representation of this source node. Walks over the tree and +concatenates all the various snippets together to one string. + +#### SourceNode.prototype.toStringWithSourceMap([startOfSourceMap]) + +Returns the string representation of this tree of source nodes, plus a +SourceMapGenerator which contains all the mappings between the generated and +original sources. + +The arguments are the same as those to `new SourceMapGenerator`. + +## Tests + +[![Build Status](https://travis-ci.org/mozilla/source-map.png?branch=master)](https://travis-ci.org/mozilla/source-map) + +Install NodeJS version 0.8.0 or greater, then run `node test/run-tests.js`. + +To add new tests, create a new file named `test/test-.js` +and export your test functions with names that start with "test", for example + + exports["test doing the foo bar"] = function (assert, util) { + ... + }; + +The new test will be located automatically when you run the suite. + +The `util` argument is the test utility module located at `test/source-map/util`. + +The `assert` argument is a cut down version of node's assert module. You have +access to the following assertion functions: + +* `doesNotThrow` + +* `equal` + +* `ok` + +* `strictEqual` + +* `throws` + +(The reason for the restricted set of test functions is because we need the +tests to run inside Firefox's test suite as well and so the assert module is +shimmed in that environment. See `build/assert-shim.js`.) + +[format]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit +[feature]: https://wiki.mozilla.org/DevTools/Features/SourceMap +[Dryice]: https://github.com/mozilla/dryice diff --git a/homework7/project_express/node_modules/source-map/build/assert-shim.js b/homework7/project_express/node_modules/source-map/build/assert-shim.js new file mode 100644 index 0000000..daa1a62 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/build/assert-shim.js @@ -0,0 +1,56 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +define('test/source-map/assert', ['exports'], function (exports) { + + let do_throw = function (msg) { + throw new Error(msg); + }; + + exports.init = function (throw_fn) { + do_throw = throw_fn; + }; + + exports.doesNotThrow = function (fn) { + try { + fn(); + } + catch (e) { + do_throw(e.message); + } + }; + + exports.equal = function (actual, expected, msg) { + msg = msg || String(actual) + ' != ' + String(expected); + if (actual != expected) { + do_throw(msg); + } + }; + + exports.ok = function (val, msg) { + msg = msg || String(val) + ' is falsey'; + if (!Boolean(val)) { + do_throw(msg); + } + }; + + exports.strictEqual = function (actual, expected, msg) { + msg = msg || String(actual) + ' !== ' + String(expected); + if (actual !== expected) { + do_throw(msg); + } + }; + + exports.throws = function (fn) { + try { + fn(); + do_throw('Expected an error to be thrown, but it wasn\'t.'); + } + catch (e) { + } + }; + +}); diff --git a/homework7/project_express/node_modules/source-map/build/mini-require.js b/homework7/project_express/node_modules/source-map/build/mini-require.js new file mode 100644 index 0000000..0daf453 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/build/mini-require.js @@ -0,0 +1,152 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/** + * Define a module along with a payload. + * @param {string} moduleName Name for the payload + * @param {ignored} deps Ignored. For compatibility with CommonJS AMD Spec + * @param {function} payload Function with (require, exports, module) params + */ +function define(moduleName, deps, payload) { + if (typeof moduleName != "string") { + throw new TypeError('Expected string, got: ' + moduleName); + } + + if (arguments.length == 2) { + payload = deps; + } + + if (moduleName in define.modules) { + throw new Error("Module already defined: " + moduleName); + } + define.modules[moduleName] = payload; +}; + +/** + * The global store of un-instantiated modules + */ +define.modules = {}; + + +/** + * We invoke require() in the context of a Domain so we can have multiple + * sets of modules running separate from each other. + * This contrasts with JSMs which are singletons, Domains allows us to + * optionally load a CommonJS module twice with separate data each time. + * Perhaps you want 2 command lines with a different set of commands in each, + * for example. + */ +function Domain() { + this.modules = {}; + this._currentModule = null; +} + +(function () { + + /** + * Lookup module names and resolve them by calling the definition function if + * needed. + * There are 2 ways to call this, either with an array of dependencies and a + * callback to call when the dependencies are found (which can happen + * asynchronously in an in-page context) or with a single string an no callback + * where the dependency is resolved synchronously and returned. + * The API is designed to be compatible with the CommonJS AMD spec and + * RequireJS. + * @param {string[]|string} deps A name, or names for the payload + * @param {function|undefined} callback Function to call when the dependencies + * are resolved + * @return {undefined|object} The module required or undefined for + * array/callback method + */ + Domain.prototype.require = function(deps, callback) { + if (Array.isArray(deps)) { + var params = deps.map(function(dep) { + return this.lookup(dep); + }, this); + if (callback) { + callback.apply(null, params); + } + return undefined; + } + else { + return this.lookup(deps); + } + }; + + function normalize(path) { + var bits = path.split('/'); + var i = 1; + while (i < bits.length) { + if (bits[i] === '..') { + bits.splice(i-1, 1); + } else if (bits[i] === '.') { + bits.splice(i, 1); + } else { + i++; + } + } + return bits.join('/'); + } + + function join(a, b) { + a = a.trim(); + b = b.trim(); + if (/^\//.test(b)) { + return b; + } else { + return a.replace(/\/*$/, '/') + b; + } + } + + function dirname(path) { + var bits = path.split('/'); + bits.pop(); + return bits.join('/'); + } + + /** + * Lookup module names and resolve them by calling the definition function if + * needed. + * @param {string} moduleName A name for the payload to lookup + * @return {object} The module specified by aModuleName or null if not found. + */ + Domain.prototype.lookup = function(moduleName) { + if (/^\./.test(moduleName)) { + moduleName = normalize(join(dirname(this._currentModule), moduleName)); + } + + if (moduleName in this.modules) { + var module = this.modules[moduleName]; + return module; + } + + if (!(moduleName in define.modules)) { + throw new Error("Module not defined: " + moduleName); + } + + var module = define.modules[moduleName]; + + if (typeof module == "function") { + var exports = {}; + var previousModule = this._currentModule; + this._currentModule = moduleName; + module(this.require.bind(this), exports, { id: moduleName, uri: "" }); + this._currentModule = previousModule; + module = exports; + } + + // cache the resulting module object for next time + this.modules[moduleName] = module; + + return module; + }; + +}()); + +define.Domain = Domain; +define.globalDomain = new Domain(); +var require = define.globalDomain.require.bind(define.globalDomain); diff --git a/homework7/project_express/node_modules/source-map/build/prefix-source-map.jsm b/homework7/project_express/node_modules/source-map/build/prefix-source-map.jsm new file mode 100644 index 0000000..ee2539d --- /dev/null +++ b/homework7/project_express/node_modules/source-map/build/prefix-source-map.jsm @@ -0,0 +1,20 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +/////////////////////////////////////////////////////////////////////////////// + + +this.EXPORTED_SYMBOLS = [ "SourceMapConsumer", "SourceMapGenerator", "SourceNode" ]; + +Components.utils.import('resource://gre/modules/devtools/Require.jsm'); diff --git a/homework7/project_express/node_modules/source-map/build/prefix-utils.jsm b/homework7/project_express/node_modules/source-map/build/prefix-utils.jsm new file mode 100644 index 0000000..80341d4 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/build/prefix-utils.jsm @@ -0,0 +1,18 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +Components.utils.import('resource://gre/modules/devtools/Require.jsm'); +Components.utils.import('resource://gre/modules/devtools/SourceMap.jsm'); + +this.EXPORTED_SYMBOLS = [ "define", "runSourceMapTests" ]; diff --git a/homework7/project_express/node_modules/source-map/build/suffix-browser.js b/homework7/project_express/node_modules/source-map/build/suffix-browser.js new file mode 100644 index 0000000..fb29ff5 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/build/suffix-browser.js @@ -0,0 +1,8 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/////////////////////////////////////////////////////////////////////////////// + +this.sourceMap = { + SourceMapConsumer: require('source-map/source-map-consumer').SourceMapConsumer, + SourceMapGenerator: require('source-map/source-map-generator').SourceMapGenerator, + SourceNode: require('source-map/source-node').SourceNode +}; diff --git a/homework7/project_express/node_modules/source-map/build/suffix-source-map.jsm b/homework7/project_express/node_modules/source-map/build/suffix-source-map.jsm new file mode 100644 index 0000000..cf3c2d8 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/build/suffix-source-map.jsm @@ -0,0 +1,6 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/////////////////////////////////////////////////////////////////////////////// + +this.SourceMapConsumer = require('source-map/source-map-consumer').SourceMapConsumer; +this.SourceMapGenerator = require('source-map/source-map-generator').SourceMapGenerator; +this.SourceNode = require('source-map/source-node').SourceNode; diff --git a/homework7/project_express/node_modules/source-map/build/suffix-utils.jsm b/homework7/project_express/node_modules/source-map/build/suffix-utils.jsm new file mode 100644 index 0000000..b31b84c --- /dev/null +++ b/homework7/project_express/node_modules/source-map/build/suffix-utils.jsm @@ -0,0 +1,21 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +function runSourceMapTests(modName, do_throw) { + let mod = require(modName); + let assert = require('test/source-map/assert'); + let util = require('test/source-map/util'); + + assert.init(do_throw); + + for (let k in mod) { + if (/^test/.test(k)) { + mod[k](assert, util); + } + } + +} +this.runSourceMapTests = runSourceMapTests; diff --git a/homework7/project_express/node_modules/source-map/build/test-prefix.js b/homework7/project_express/node_modules/source-map/build/test-prefix.js new file mode 100644 index 0000000..1b13f30 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/build/test-prefix.js @@ -0,0 +1,8 @@ +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +Components.utils.import('resource://test/Utils.jsm'); diff --git a/homework7/project_express/node_modules/source-map/build/test-suffix.js b/homework7/project_express/node_modules/source-map/build/test-suffix.js new file mode 100644 index 0000000..bec2de3 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/build/test-suffix.js @@ -0,0 +1,3 @@ +function run_test() { + runSourceMapTests('{THIS_MODULE}', do_throw); +} diff --git a/homework7/project_express/node_modules/source-map/lib/source-map.js b/homework7/project_express/node_modules/source-map/lib/source-map.js new file mode 100644 index 0000000..121ad24 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/lib/source-map.js @@ -0,0 +1,8 @@ +/* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause + */ +exports.SourceMapGenerator = require('./source-map/source-map-generator').SourceMapGenerator; +exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer; +exports.SourceNode = require('./source-map/source-node').SourceNode; diff --git a/homework7/project_express/node_modules/source-map/lib/source-map/array-set.js b/homework7/project_express/node_modules/source-map/lib/source-map/array-set.js new file mode 100644 index 0000000..40f9a18 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/lib/source-map/array-set.js @@ -0,0 +1,97 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('./util'); + + /** + * A data structure which is a combination of an array and a set. Adding a new + * member is O(1), testing for membership is O(1), and finding the index of an + * element is O(1). Removing elements from the set is not supported. Only + * strings are supported for membership. + */ + function ArraySet() { + this._array = []; + this._set = {}; + } + + /** + * Static method for creating ArraySet instances from an existing array. + */ + ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { + var set = new ArraySet(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i], aAllowDuplicates); + } + return set; + }; + + /** + * Add the given string to this set. + * + * @param String aStr + */ + ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { + var isDuplicate = this.has(aStr); + var idx = this._array.length; + if (!isDuplicate || aAllowDuplicates) { + this._array.push(aStr); + } + if (!isDuplicate) { + this._set[util.toSetString(aStr)] = idx; + } + }; + + /** + * Is the given string a member of this set? + * + * @param String aStr + */ + ArraySet.prototype.has = function ArraySet_has(aStr) { + return Object.prototype.hasOwnProperty.call(this._set, + util.toSetString(aStr)); + }; + + /** + * What is the index of the given string in the array? + * + * @param String aStr + */ + ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { + if (this.has(aStr)) { + return this._set[util.toSetString(aStr)]; + } + throw new Error('"' + aStr + '" is not in the set.'); + }; + + /** + * What is the element at the given index? + * + * @param Number aIdx + */ + ArraySet.prototype.at = function ArraySet_at(aIdx) { + if (aIdx >= 0 && aIdx < this._array.length) { + return this._array[aIdx]; + } + throw new Error('No element indexed by ' + aIdx); + }; + + /** + * Returns the array representation of this set (which has the proper indices + * indicated by indexOf). Note that this is a copy of the internal array used + * for storing the members so that no one can mess with internal state. + */ + ArraySet.prototype.toArray = function ArraySet_toArray() { + return this._array.slice(); + }; + + exports.ArraySet = ArraySet; + +}); diff --git a/homework7/project_express/node_modules/source-map/lib/source-map/base64-vlq.js b/homework7/project_express/node_modules/source-map/lib/source-map/base64-vlq.js new file mode 100644 index 0000000..e22dcae --- /dev/null +++ b/homework7/project_express/node_modules/source-map/lib/source-map/base64-vlq.js @@ -0,0 +1,142 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + * + * Based on the Base 64 VLQ implementation in Closure Compiler: + * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java + * + * Copyright 2011 The Closure Compiler Authors. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64 = require('./base64'); + + // A single base 64 digit can contain 6 bits of data. For the base 64 variable + // length quantities we use in the source map spec, the first bit is the sign, + // the next four bits are the actual value, and the 6th bit is the + // continuation bit. The continuation bit tells us whether there are more + // digits in this value following this digit. + // + // Continuation + // | Sign + // | | + // V V + // 101011 + + var VLQ_BASE_SHIFT = 5; + + // binary: 100000 + var VLQ_BASE = 1 << VLQ_BASE_SHIFT; + + // binary: 011111 + var VLQ_BASE_MASK = VLQ_BASE - 1; + + // binary: 100000 + var VLQ_CONTINUATION_BIT = VLQ_BASE; + + /** + * Converts from a two-complement value to a value where the sign bit is + * placed in the least significant bit. For example, as decimals: + * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) + * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) + */ + function toVLQSigned(aValue) { + return aValue < 0 + ? ((-aValue) << 1) + 1 + : (aValue << 1) + 0; + } + + /** + * Converts to a two-complement value from a value where the sign bit is + * placed in the least significant bit. For example, as decimals: + * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 + * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 + */ + function fromVLQSigned(aValue) { + var isNegative = (aValue & 1) === 1; + var shifted = aValue >> 1; + return isNegative + ? -shifted + : shifted; + } + + /** + * Returns the base 64 VLQ encoded value. + */ + exports.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; + + var vlq = toVLQSigned(aValue); + + do { + digit = vlq & VLQ_BASE_MASK; + vlq >>>= VLQ_BASE_SHIFT; + if (vlq > 0) { + // There are still more digits in this value, so we must make sure the + // continuation bit is marked. + digit |= VLQ_CONTINUATION_BIT; + } + encoded += base64.encode(digit); + } while (vlq > 0); + + return encoded; + }; + + /** + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string via the out parameter. + */ + exports.decode = function base64VLQ_decode(aStr, aOutParam) { + var i = 0; + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; + + do { + if (i >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); + } + digit = base64.decode(aStr.charAt(i++)); + continuation = !!(digit & VLQ_CONTINUATION_BIT); + digit &= VLQ_BASE_MASK; + result = result + (digit << shift); + shift += VLQ_BASE_SHIFT; + } while (continuation); + + aOutParam.value = fromVLQSigned(result); + aOutParam.rest = aStr.slice(i); + }; + +}); diff --git a/homework7/project_express/node_modules/source-map/lib/source-map/base64.js b/homework7/project_express/node_modules/source-map/lib/source-map/base64.js new file mode 100644 index 0000000..863cc46 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/lib/source-map/base64.js @@ -0,0 +1,42 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var charToIntMap = {}; + var intToCharMap = {}; + + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + .split('') + .forEach(function (ch, index) { + charToIntMap[ch] = index; + intToCharMap[index] = ch; + }); + + /** + * Encode an integer in the range of 0 to 63 to a single base 64 digit. + */ + exports.encode = function base64_encode(aNumber) { + if (aNumber in intToCharMap) { + return intToCharMap[aNumber]; + } + throw new TypeError("Must be between 0 and 63: " + aNumber); + }; + + /** + * Decode a single base 64 digit to an integer. + */ + exports.decode = function base64_decode(aChar) { + if (aChar in charToIntMap) { + return charToIntMap[aChar]; + } + throw new TypeError("Not a valid base 64 digit: " + aChar); + }; + +}); diff --git a/homework7/project_express/node_modules/source-map/lib/source-map/binary-search.js b/homework7/project_express/node_modules/source-map/lib/source-map/binary-search.js new file mode 100644 index 0000000..e085f81 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/lib/source-map/binary-search.js @@ -0,0 +1,80 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + /** + * Recursive implementation of binary search. + * + * @param aLow Indices here and lower do not contain the needle. + * @param aHigh Indices here and higher do not contain the needle. + * @param aNeedle The element being searched for. + * @param aHaystack The non-empty array being searched. + * @param aCompare Function which takes two elements and returns -1, 0, or 1. + */ + function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) { + // This function terminates when one of the following is true: + // + // 1. We find the exact element we are looking for. + // + // 2. We did not find the exact element, but we can return the index of + // the next closest element that is less than that element. + // + // 3. We did not find the exact element, and there is no next-closest + // element which is less than the one we are searching for, so we + // return -1. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid], true); + if (cmp === 0) { + // Found the element we are looking for. + return mid; + } + else if (cmp > 0) { + // aHaystack[mid] is greater than our needle. + if (aHigh - mid > 1) { + // The element is in the upper half. + return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare); + } + // We did not find an exact match, return the next closest one + // (termination case 2). + return mid; + } + else { + // aHaystack[mid] is less than our needle. + if (mid - aLow > 1) { + // The element is in the lower half. + return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare); + } + // The exact needle element was not found in this haystack. Determine if + // we are in termination case (2) or (3) and return the appropriate thing. + return aLow < 0 ? -1 : aLow; + } + } + + /** + * This is an implementation of binary search which will always try and return + * the index of next lowest value checked if there is no exact hit. This is + * because mappings between original and generated line/col pairs are single + * points, and there is an implicit region between each of them, so a miss + * just means that you aren't on the very start of a region. + * + * @param aNeedle The element you are looking for. + * @param aHaystack The array that is being searched. + * @param aCompare A function which takes the needle and an element in the + * array and returns -1, 0, or 1 depending on whether the needle is less + * than, equal to, or greater than the element, respectively. + */ + exports.search = function search(aNeedle, aHaystack, aCompare) { + if (aHaystack.length === 0) { + return -1; + } + return recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare) + }; + +}); diff --git a/homework7/project_express/node_modules/source-map/lib/source-map/mapping-list.js b/homework7/project_express/node_modules/source-map/lib/source-map/mapping-list.js new file mode 100644 index 0000000..2a4eb61 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/lib/source-map/mapping-list.js @@ -0,0 +1,86 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2014 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('./util'); + + /** + * Determine whether mappingB is after mappingA with respect to generated + * position. + */ + function generatedPositionAfter(mappingA, mappingB) { + // Optimized for most common case + var lineA = mappingA.generatedLine; + var lineB = mappingB.generatedLine; + var columnA = mappingA.generatedColumn; + var columnB = mappingB.generatedColumn; + return lineB > lineA || lineB == lineA && columnB >= columnA || + util.compareByGeneratedPositions(mappingA, mappingB) <= 0; + } + + /** + * A data structure to provide a sorted view of accumulated mappings in a + * performance conscious manner. It trades a neglibable overhead in general + * case for a large speedup in case of mappings being added in order. + */ + function MappingList() { + this._array = []; + this._sorted = true; + // Serves as infimum + this._last = {generatedLine: -1, generatedColumn: 0}; + } + + /** + * Iterate through internal items. This method takes the same arguments that + * `Array.prototype.forEach` takes. + * + * NOTE: The order of the mappings is NOT guaranteed. + */ + MappingList.prototype.unsortedForEach = + function MappingList_forEach(aCallback, aThisArg) { + this._array.forEach(aCallback, aThisArg); + }; + + /** + * Add the given source mapping. + * + * @param Object aMapping + */ + MappingList.prototype.add = function MappingList_add(aMapping) { + var mapping; + if (generatedPositionAfter(this._last, aMapping)) { + this._last = aMapping; + this._array.push(aMapping); + } else { + this._sorted = false; + this._array.push(aMapping); + } + }; + + /** + * Returns the flat, sorted array of mappings. The mappings are sorted by + * generated position. + * + * WARNING: This method returns internal data without copying, for + * performance. The return value must NOT be mutated, and should be treated as + * an immutable borrow. If you want to take ownership, you must make your own + * copy. + */ + MappingList.prototype.toArray = function MappingList_toArray() { + if (!this._sorted) { + this._array.sort(util.compareByGeneratedPositions); + this._sorted = true; + } + return this._array; + }; + + exports.MappingList = MappingList; + +}); diff --git a/homework7/project_express/node_modules/source-map/lib/source-map/source-map-consumer.js b/homework7/project_express/node_modules/source-map/lib/source-map/source-map-consumer.js new file mode 100644 index 0000000..cfaa299 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/lib/source-map/source-map-consumer.js @@ -0,0 +1,575 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('./util'); + var binarySearch = require('./binary-search'); + var ArraySet = require('./array-set').ArraySet; + var base64VLQ = require('./base64-vlq'); + + /** + * A SourceMapConsumer instance represents a parsed source map which we can + * query for information about the original file positions by giving it a file + * position in the generated source. + * + * The only parameter is the raw source map (either as a JSON string, or + * already parsed to an object). According to the spec, source maps have the + * following attributes: + * + * - version: Which version of the source map spec this map is following. + * - sources: An array of URLs to the original source files. + * - names: An array of identifiers which can be referrenced by individual mappings. + * - sourceRoot: Optional. The URL root from which all sources are relative. + * - sourcesContent: Optional. An array of contents of the original source files. + * - mappings: A string of base64 VLQs which contain the actual mappings. + * - file: Optional. The generated file this source map is associated with. + * + * Here is an example source map, taken from the source map spec[0]: + * + * { + * version : 3, + * file: "out.js", + * sourceRoot : "", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AA,AB;;ABCDE;" + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# + */ + function SourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sources = util.getArg(sourceMap, 'sources'); + // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which + // requires the array) to play nice here. + var names = util.getArg(sourceMap, 'names', []); + var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); + var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); + var mappings = util.getArg(sourceMap, 'mappings'); + var file = util.getArg(sourceMap, 'file', null); + + // Once again, Sass deviates from the spec and supplies the version as a + // string rather than a number, so we use loose equality checking here. + if (version != this._version) { + throw new Error('Unsupported version: ' + version); + } + + // Some source maps produce relative source paths like "./foo.js" instead of + // "foo.js". Normalize these first so that future comparisons will succeed. + // See bugzil.la/1090768. + sources = sources.map(util.normalize); + + // Pass `true` below to allow duplicate names and sources. While source maps + // are intended to be compressed and deduplicated, the TypeScript compiler + // sometimes generates source maps with duplicates in them. See Github issue + // #72 and bugzil.la/889492. + this._names = ArraySet.fromArray(names, true); + this._sources = ArraySet.fromArray(sources, true); + + this.sourceRoot = sourceRoot; + this.sourcesContent = sourcesContent; + this._mappings = mappings; + this.file = file; + } + + /** + * Create a SourceMapConsumer from a SourceMapGenerator. + * + * @param SourceMapGenerator aSourceMap + * The source map that will be consumed. + * @returns SourceMapConsumer + */ + SourceMapConsumer.fromSourceMap = + function SourceMapConsumer_fromSourceMap(aSourceMap) { + var smc = Object.create(SourceMapConsumer.prototype); + + smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); + smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); + smc.sourceRoot = aSourceMap._sourceRoot; + smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), + smc.sourceRoot); + smc.file = aSourceMap._file; + + smc.__generatedMappings = aSourceMap._mappings.toArray().slice(); + smc.__originalMappings = aSourceMap._mappings.toArray().slice() + .sort(util.compareByOriginalPositions); + + return smc; + }; + + /** + * The version of the source mapping spec that we are consuming. + */ + SourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(SourceMapConsumer.prototype, 'sources', { + get: function () { + return this._sources.toArray().map(function (s) { + return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s; + }, this); + } + }); + + // `__generatedMappings` and `__originalMappings` are arrays that hold the + // parsed mapping coordinates from the source map's "mappings" attribute. They + // are lazily instantiated, accessed via the `_generatedMappings` and + // `_originalMappings` getters respectively, and we only parse the mappings + // and create these arrays once queried for a source location. We jump through + // these hoops because there can be many thousands of mappings, and parsing + // them is expensive, so we only want to do it if we must. + // + // Each object in the arrays is of the form: + // + // { + // generatedLine: The line number in the generated code, + // generatedColumn: The column number in the generated code, + // source: The path to the original source file that generated this + // chunk of code, + // originalLine: The line number in the original source that + // corresponds to this chunk of generated code, + // originalColumn: The column number in the original source that + // corresponds to this chunk of generated code, + // name: The name of the original symbol which generated this chunk of + // code. + // } + // + // All properties except for `generatedLine` and `generatedColumn` can be + // `null`. + // + // `_generatedMappings` is ordered by the generated positions. + // + // `_originalMappings` is ordered by the original positions. + + SourceMapConsumer.prototype.__generatedMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { + get: function () { + if (!this.__generatedMappings) { + this.__generatedMappings = []; + this.__originalMappings = []; + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__generatedMappings; + } + }); + + SourceMapConsumer.prototype.__originalMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { + get: function () { + if (!this.__originalMappings) { + this.__generatedMappings = []; + this.__originalMappings = []; + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__originalMappings; + } + }); + + SourceMapConsumer.prototype._nextCharIsMappingSeparator = + function SourceMapConsumer_nextCharIsMappingSeparator(aStr) { + var c = aStr.charAt(0); + return c === ";" || c === ","; + }; + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + SourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + var generatedLine = 1; + var previousGeneratedColumn = 0; + var previousOriginalLine = 0; + var previousOriginalColumn = 0; + var previousSource = 0; + var previousName = 0; + var str = aStr; + var temp = {}; + var mapping; + + while (str.length > 0) { + if (str.charAt(0) === ';') { + generatedLine++; + str = str.slice(1); + previousGeneratedColumn = 0; + } + else if (str.charAt(0) === ',') { + str = str.slice(1); + } + else { + mapping = {}; + mapping.generatedLine = generatedLine; + + // Generated column. + base64VLQ.decode(str, temp); + mapping.generatedColumn = previousGeneratedColumn + temp.value; + previousGeneratedColumn = mapping.generatedColumn; + str = temp.rest; + + if (str.length > 0 && !this._nextCharIsMappingSeparator(str)) { + // Original source. + base64VLQ.decode(str, temp); + mapping.source = this._sources.at(previousSource + temp.value); + previousSource += temp.value; + str = temp.rest; + if (str.length === 0 || this._nextCharIsMappingSeparator(str)) { + throw new Error('Found a source, but no line and column'); + } + + // Original line. + base64VLQ.decode(str, temp); + mapping.originalLine = previousOriginalLine + temp.value; + previousOriginalLine = mapping.originalLine; + // Lines are stored 0-based + mapping.originalLine += 1; + str = temp.rest; + if (str.length === 0 || this._nextCharIsMappingSeparator(str)) { + throw new Error('Found a source and line, but no column'); + } + + // Original column. + base64VLQ.decode(str, temp); + mapping.originalColumn = previousOriginalColumn + temp.value; + previousOriginalColumn = mapping.originalColumn; + str = temp.rest; + + if (str.length > 0 && !this._nextCharIsMappingSeparator(str)) { + // Original name. + base64VLQ.decode(str, temp); + mapping.name = this._names.at(previousName + temp.value); + previousName += temp.value; + str = temp.rest; + } + } + + this.__generatedMappings.push(mapping); + if (typeof mapping.originalLine === 'number') { + this.__originalMappings.push(mapping); + } + } + } + + this.__generatedMappings.sort(util.compareByGeneratedPositions); + this.__originalMappings.sort(util.compareByOriginalPositions); + }; + + /** + * Find the mapping that best matches the hypothetical "needle" mapping that + * we are searching for in the given "haystack" of mappings. + */ + SourceMapConsumer.prototype._findMapping = + function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, + aColumnName, aComparator) { + // To return the position we are searching for, we must first find the + // mapping for the given position and then return the opposite position it + // points to. Because the mappings are sorted, we can use binary search to + // find the best mapping. + + if (aNeedle[aLineName] <= 0) { + throw new TypeError('Line must be greater than or equal to 1, got ' + + aNeedle[aLineName]); + } + if (aNeedle[aColumnName] < 0) { + throw new TypeError('Column must be greater than or equal to 0, got ' + + aNeedle[aColumnName]); + } + + return binarySearch.search(aNeedle, aMappings, aComparator); + }; + + /** + * Compute the last column for each generated mapping. The last column is + * inclusive. + */ + SourceMapConsumer.prototype.computeColumnSpans = + function SourceMapConsumer_computeColumnSpans() { + for (var index = 0; index < this._generatedMappings.length; ++index) { + var mapping = this._generatedMappings[index]; + + // Mappings do not contain a field for the last generated columnt. We + // can come up with an optimistic estimate, however, by assuming that + // mappings are contiguous (i.e. given two consecutive mappings, the + // first mapping ends where the second one starts). + if (index + 1 < this._generatedMappings.length) { + var nextMapping = this._generatedMappings[index + 1]; + + if (mapping.generatedLine === nextMapping.generatedLine) { + mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1; + continue; + } + } + + // The last mapping for each line spans the entire line. + mapping.lastGeneratedColumn = Infinity; + } + }; + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ + SourceMapConsumer.prototype.originalPositionFor = + function SourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + var index = this._findMapping(needle, + this._generatedMappings, + "generatedLine", + "generatedColumn", + util.compareByGeneratedPositions); + + if (index >= 0) { + var mapping = this._generatedMappings[index]; + + if (mapping.generatedLine === needle.generatedLine) { + var source = util.getArg(mapping, 'source', null); + if (source != null && this.sourceRoot != null) { + source = util.join(this.sourceRoot, source); + } + return { + source: source, + line: util.getArg(mapping, 'originalLine', null), + column: util.getArg(mapping, 'originalColumn', null), + name: util.getArg(mapping, 'name', null) + }; + } + } + + return { + source: null, + line: null, + column: null, + name: null + }; + }; + + /** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * availible. + */ + SourceMapConsumer.prototype.sourceContentFor = + function SourceMapConsumer_sourceContentFor(aSource) { + if (!this.sourcesContent) { + return null; + } + + if (this.sourceRoot != null) { + aSource = util.relative(this.sourceRoot, aSource); + } + + if (this._sources.has(aSource)) { + return this.sourcesContent[this._sources.indexOf(aSource)]; + } + + var url; + if (this.sourceRoot != null + && (url = util.urlParse(this.sourceRoot))) { + // XXX: file:// URIs and absolute paths lead to unexpected behavior for + // many users. We can help them out when they expect file:// URIs to + // behave like it would if they were running a local HTTP server. See + // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. + var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); + if (url.scheme == "file" + && this._sources.has(fileUriAbsPath)) { + return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] + } + + if ((!url.path || url.path == "/") + && this._sources.has("/" + aSource)) { + return this.sourcesContent[this._sources.indexOf("/" + aSource)]; + } + } + + throw new Error('"' + aSource + '" is not in the SourceMap.'); + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + SourceMapConsumer.prototype.generatedPositionFor = + function SourceMapConsumer_generatedPositionFor(aArgs) { + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: util.getArg(aArgs, 'line'), + originalColumn: util.getArg(aArgs, 'column') + }; + + if (this.sourceRoot != null) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + + var index = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions); + + if (index >= 0) { + var mapping = this._originalMappings[index]; + + return { + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }; + } + + return { + line: null, + column: null, + lastColumn: null + }; + }; + + /** + * Returns all generated line and column information for the original source + * and line provided. The only argument is an object with the following + * properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * + * and an array of objects is returned, each with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + SourceMapConsumer.prototype.allGeneratedPositionsFor = + function SourceMapConsumer_allGeneratedPositionsFor(aArgs) { + // When there is no exact match, SourceMapConsumer.prototype._findMapping + // returns the index of the closest mapping less than the needle. By + // setting needle.originalColumn to Infinity, we thus find the last + // mapping for the given line, provided such a mapping exists. + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: util.getArg(aArgs, 'line'), + originalColumn: Infinity + }; + + if (this.sourceRoot != null) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + + var mappings = []; + + var index = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions); + if (index >= 0) { + var mapping = this._originalMappings[index]; + + while (mapping && mapping.originalLine === needle.originalLine) { + mappings.push({ + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }); + + mapping = this._originalMappings[--index]; + } + } + + return mappings.reverse(); + }; + + SourceMapConsumer.GENERATED_ORDER = 1; + SourceMapConsumer.ORIGINAL_ORDER = 2; + + /** + * Iterate over each mapping between an original source/line/column and a + * generated line/column in this source map. + * + * @param Function aCallback + * The function that is called with each mapping. + * @param Object aContext + * Optional. If specified, this object will be the value of `this` every + * time that `aCallback` is called. + * @param aOrder + * Either `SourceMapConsumer.GENERATED_ORDER` or + * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to + * iterate over the mappings sorted by the generated file's line/column + * order or the original's source/line/column order, respectively. Defaults to + * `SourceMapConsumer.GENERATED_ORDER`. + */ + SourceMapConsumer.prototype.eachMapping = + function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { + var context = aContext || null; + var order = aOrder || SourceMapConsumer.GENERATED_ORDER; + + var mappings; + switch (order) { + case SourceMapConsumer.GENERATED_ORDER: + mappings = this._generatedMappings; + break; + case SourceMapConsumer.ORIGINAL_ORDER: + mappings = this._originalMappings; + break; + default: + throw new Error("Unknown order of iteration."); + } + + var sourceRoot = this.sourceRoot; + mappings.map(function (mapping) { + var source = mapping.source; + if (source != null && sourceRoot != null) { + source = util.join(sourceRoot, source); + } + return { + source: source, + generatedLine: mapping.generatedLine, + generatedColumn: mapping.generatedColumn, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: mapping.name + }; + }).forEach(aCallback, context); + }; + + exports.SourceMapConsumer = SourceMapConsumer; + +}); diff --git a/homework7/project_express/node_modules/source-map/lib/source-map/source-map-generator.js b/homework7/project_express/node_modules/source-map/lib/source-map/source-map-generator.js new file mode 100644 index 0000000..1ab7a47 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/lib/source-map/source-map-generator.js @@ -0,0 +1,400 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64VLQ = require('./base64-vlq'); + var util = require('./util'); + var ArraySet = require('./array-set').ArraySet; + var MappingList = require('./mapping-list').MappingList; + + /** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. You may pass an object with the following + * properties: + * + * - file: The filename of the generated source. + * - sourceRoot: A root for all relative URLs in this source map. + */ + function SourceMapGenerator(aArgs) { + if (!aArgs) { + aArgs = {}; + } + this._file = util.getArg(aArgs, 'file', null); + this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); + this._skipValidation = util.getArg(aArgs, 'skipValidation', false); + this._sources = new ArraySet(); + this._names = new ArraySet(); + this._mappings = new MappingList(); + this._sourcesContents = null; + } + + SourceMapGenerator.prototype._version = 3; + + /** + * Creates a new SourceMapGenerator based on a SourceMapConsumer + * + * @param aSourceMapConsumer The SourceMap. + */ + SourceMapGenerator.fromSourceMap = + function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { + var sourceRoot = aSourceMapConsumer.sourceRoot; + var generator = new SourceMapGenerator({ + file: aSourceMapConsumer.file, + sourceRoot: sourceRoot + }); + aSourceMapConsumer.eachMapping(function (mapping) { + var newMapping = { + generated: { + line: mapping.generatedLine, + column: mapping.generatedColumn + } + }; + + if (mapping.source != null) { + newMapping.source = mapping.source; + if (sourceRoot != null) { + newMapping.source = util.relative(sourceRoot, newMapping.source); + } + + newMapping.original = { + line: mapping.originalLine, + column: mapping.originalColumn + }; + + if (mapping.name != null) { + newMapping.name = mapping.name; + } + } + + generator.addMapping(newMapping); + }); + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + generator.setSourceContent(sourceFile, content); + } + }); + return generator; + }; + + /** + * Add a single mapping from original source line and column to the generated + * source's line and column for this source map being created. The mapping + * object should have the following properties: + * + * - generated: An object with the generated line and column positions. + * - original: An object with the original line and column positions. + * - source: The original source file (relative to the sourceRoot). + * - name: An optional original token name for this mapping. + */ + SourceMapGenerator.prototype.addMapping = + function SourceMapGenerator_addMapping(aArgs) { + var generated = util.getArg(aArgs, 'generated'); + var original = util.getArg(aArgs, 'original', null); + var source = util.getArg(aArgs, 'source', null); + var name = util.getArg(aArgs, 'name', null); + + if (!this._skipValidation) { + this._validateMapping(generated, original, source, name); + } + + if (source != null && !this._sources.has(source)) { + this._sources.add(source); + } + + if (name != null && !this._names.has(name)) { + this._names.add(name); + } + + this._mappings.add({ + generatedLine: generated.line, + generatedColumn: generated.column, + originalLine: original != null && original.line, + originalColumn: original != null && original.column, + source: source, + name: name + }); + }; + + /** + * Set the source content for a source file. + */ + SourceMapGenerator.prototype.setSourceContent = + function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { + var source = aSourceFile; + if (this._sourceRoot != null) { + source = util.relative(this._sourceRoot, source); + } + + if (aSourceContent != null) { + // Add the source content to the _sourcesContents map. + // Create a new _sourcesContents map if the property is null. + if (!this._sourcesContents) { + this._sourcesContents = {}; + } + this._sourcesContents[util.toSetString(source)] = aSourceContent; + } else if (this._sourcesContents) { + // Remove the source file from the _sourcesContents map. + // If the _sourcesContents map is empty, set the property to null. + delete this._sourcesContents[util.toSetString(source)]; + if (Object.keys(this._sourcesContents).length === 0) { + this._sourcesContents = null; + } + } + }; + + /** + * Applies the mappings of a sub-source-map for a specific source file to the + * source map being generated. Each mapping to the supplied source file is + * rewritten using the supplied source map. Note: The resolution for the + * resulting mappings is the minimium of this map and the supplied map. + * + * @param aSourceMapConsumer The source map to be applied. + * @param aSourceFile Optional. The filename of the source file. + * If omitted, SourceMapConsumer's file property will be used. + * @param aSourceMapPath Optional. The dirname of the path to the source map + * to be applied. If relative, it is relative to the SourceMapConsumer. + * This parameter is needed when the two source maps aren't in the same + * directory, and the source map to be applied contains relative source + * paths. If so, those relative source paths need to be rewritten + * relative to the SourceMapGenerator. + */ + SourceMapGenerator.prototype.applySourceMap = + function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) { + var sourceFile = aSourceFile; + // If aSourceFile is omitted, we will use the file property of the SourceMap + if (aSourceFile == null) { + if (aSourceMapConsumer.file == null) { + throw new Error( + 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + + 'or the source map\'s "file" property. Both were omitted.' + ); + } + sourceFile = aSourceMapConsumer.file; + } + var sourceRoot = this._sourceRoot; + // Make "sourceFile" relative if an absolute Url is passed. + if (sourceRoot != null) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + // Applying the SourceMap can add and remove items from the sources and + // the names array. + var newSources = new ArraySet(); + var newNames = new ArraySet(); + + // Find mappings for the "sourceFile" + this._mappings.unsortedForEach(function (mapping) { + if (mapping.source === sourceFile && mapping.originalLine != null) { + // Check if it can be mapped by the source map, then update the mapping. + var original = aSourceMapConsumer.originalPositionFor({ + line: mapping.originalLine, + column: mapping.originalColumn + }); + if (original.source != null) { + // Copy mapping + mapping.source = original.source; + if (aSourceMapPath != null) { + mapping.source = util.join(aSourceMapPath, mapping.source) + } + if (sourceRoot != null) { + mapping.source = util.relative(sourceRoot, mapping.source); + } + mapping.originalLine = original.line; + mapping.originalColumn = original.column; + if (original.name != null) { + mapping.name = original.name; + } + } + } + + var source = mapping.source; + if (source != null && !newSources.has(source)) { + newSources.add(source); + } + + var name = mapping.name; + if (name != null && !newNames.has(name)) { + newNames.add(name); + } + + }, this); + this._sources = newSources; + this._names = newNames; + + // Copy sourcesContents of applied map. + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + if (aSourceMapPath != null) { + sourceFile = util.join(aSourceMapPath, sourceFile); + } + if (sourceRoot != null) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + this.setSourceContent(sourceFile, content); + } + }, this); + }; + + /** + * A mapping can have one of the three levels of data: + * + * 1. Just the generated position. + * 2. The Generated position, original position, and original source. + * 3. Generated and original position, original source, as well as a name + * token. + * + * To maintain consistency, we validate that any new mapping being added falls + * in to one of these categories. + */ + SourceMapGenerator.prototype._validateMapping = + function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, + aName) { + if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aGenerated.line > 0 && aGenerated.column >= 0 + && !aOriginal && !aSource && !aName) { + // Case 1. + return; + } + else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aOriginal && 'line' in aOriginal && 'column' in aOriginal + && aGenerated.line > 0 && aGenerated.column >= 0 + && aOriginal.line > 0 && aOriginal.column >= 0 + && aSource) { + // Cases 2 and 3. + return; + } + else { + throw new Error('Invalid mapping: ' + JSON.stringify({ + generated: aGenerated, + source: aSource, + original: aOriginal, + name: aName + })); + } + }; + + /** + * Serialize the accumulated mappings in to the stream of base 64 VLQs + * specified by the source map format. + */ + SourceMapGenerator.prototype._serializeMappings = + function SourceMapGenerator_serializeMappings() { + var previousGeneratedColumn = 0; + var previousGeneratedLine = 1; + var previousOriginalColumn = 0; + var previousOriginalLine = 0; + var previousName = 0; + var previousSource = 0; + var result = ''; + var mapping; + + var mappings = this._mappings.toArray(); + + for (var i = 0, len = mappings.length; i < len; i++) { + mapping = mappings[i]; + + if (mapping.generatedLine !== previousGeneratedLine) { + previousGeneratedColumn = 0; + while (mapping.generatedLine !== previousGeneratedLine) { + result += ';'; + previousGeneratedLine++; + } + } + else { + if (i > 0) { + if (!util.compareByGeneratedPositions(mapping, mappings[i - 1])) { + continue; + } + result += ','; + } + } + + result += base64VLQ.encode(mapping.generatedColumn + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generatedColumn; + + if (mapping.source != null) { + result += base64VLQ.encode(this._sources.indexOf(mapping.source) + - previousSource); + previousSource = this._sources.indexOf(mapping.source); + + // lines are stored 0-based in SourceMap spec version 3 + result += base64VLQ.encode(mapping.originalLine - 1 + - previousOriginalLine); + previousOriginalLine = mapping.originalLine - 1; + + result += base64VLQ.encode(mapping.originalColumn + - previousOriginalColumn); + previousOriginalColumn = mapping.originalColumn; + + if (mapping.name != null) { + result += base64VLQ.encode(this._names.indexOf(mapping.name) + - previousName); + previousName = this._names.indexOf(mapping.name); + } + } + } + + return result; + }; + + SourceMapGenerator.prototype._generateSourcesContent = + function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { + return aSources.map(function (source) { + if (!this._sourcesContents) { + return null; + } + if (aSourceRoot != null) { + source = util.relative(aSourceRoot, source); + } + var key = util.toSetString(source); + return Object.prototype.hasOwnProperty.call(this._sourcesContents, + key) + ? this._sourcesContents[key] + : null; + }, this); + }; + + /** + * Externalize the source map. + */ + SourceMapGenerator.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() + }; + if (this._file != null) { + map.file = this._file; + } + if (this._sourceRoot != null) { + map.sourceRoot = this._sourceRoot; + } + if (this._sourcesContents) { + map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); + } + + return map; + }; + + /** + * Render the source map being generated to a string. + */ + SourceMapGenerator.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this); + }; + + exports.SourceMapGenerator = SourceMapGenerator; + +}); diff --git a/homework7/project_express/node_modules/source-map/lib/source-map/source-node.js b/homework7/project_express/node_modules/source-map/lib/source-map/source-node.js new file mode 100644 index 0000000..9ee90bd --- /dev/null +++ b/homework7/project_express/node_modules/source-map/lib/source-map/source-node.js @@ -0,0 +1,414 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; + var util = require('./util'); + + // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other + // operating systems these days (capturing the result). + var REGEX_NEWLINE = /(\r?\n)/; + + // Newline character code for charCodeAt() comparisons + var NEWLINE_CODE = 10; + + // Private symbol for identifying `SourceNode`s when multiple versions of + // the source-map library are loaded. This MUST NOT CHANGE across + // versions! + var isSourceNode = "$$$isSourceNode$$$"; + + /** + * SourceNodes provide a way to abstract over interpolating/concatenating + * snippets of generated JavaScript source code while maintaining the line and + * column information associated with the original source code. + * + * @param aLine The original line number. + * @param aColumn The original column number. + * @param aSource The original source's filename. + * @param aChunks Optional. An array of strings which are snippets of + * generated JS, or other SourceNodes. + * @param aName The original identifier. + */ + function SourceNode(aLine, aColumn, aSource, aChunks, aName) { + this.children = []; + this.sourceContents = {}; + this.line = aLine == null ? null : aLine; + this.column = aColumn == null ? null : aColumn; + this.source = aSource == null ? null : aSource; + this.name = aName == null ? null : aName; + this[isSourceNode] = true; + if (aChunks != null) this.add(aChunks); + } + + /** + * Creates a SourceNode from generated code and a SourceMapConsumer. + * + * @param aGeneratedCode The generated code + * @param aSourceMapConsumer The SourceMap for the generated code + * @param aRelativePath Optional. The path that relative sources in the + * SourceMapConsumer should be relative to. + */ + SourceNode.fromStringWithSourceMap = + function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) { + // The SourceNode we want to fill with the generated code + // and the SourceMap + var node = new SourceNode(); + + // All even indices of this array are one line of the generated code, + // while all odd indices are the newlines between two adjacent lines + // (since `REGEX_NEWLINE` captures its match). + // Processed fragments are removed from this array, by calling `shiftNextLine`. + var remainingLines = aGeneratedCode.split(REGEX_NEWLINE); + var shiftNextLine = function() { + var lineContents = remainingLines.shift(); + // The last line of a file might not have a newline. + var newLine = remainingLines.shift() || ""; + return lineContents + newLine; + }; + + // We need to remember the position of "remainingLines" + var lastGeneratedLine = 1, lastGeneratedColumn = 0; + + // The generate SourceNodes we need a code range. + // To extract it current and last mapping is used. + // Here we store the last mapping. + var lastMapping = null; + + aSourceMapConsumer.eachMapping(function (mapping) { + if (lastMapping !== null) { + // We add the code from "lastMapping" to "mapping": + // First check if there is a new line in between. + if (lastGeneratedLine < mapping.generatedLine) { + var code = ""; + // Associate first line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + lastGeneratedLine++; + lastGeneratedColumn = 0; + // The remaining code is added without mapping + } else { + // There is no new line in between. + // Associate the code between "lastGeneratedColumn" and + // "mapping.generatedColumn" with "lastMapping" + var nextLine = remainingLines[0]; + var code = nextLine.substr(0, mapping.generatedColumn - + lastGeneratedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn - + lastGeneratedColumn); + lastGeneratedColumn = mapping.generatedColumn; + addMappingWithCode(lastMapping, code); + // No more remaining code, continue + lastMapping = mapping; + return; + } + } + // We add the generated code until the first mapping + // to the SourceNode without any mapping. + // Each line is added as separate string. + while (lastGeneratedLine < mapping.generatedLine) { + node.add(shiftNextLine()); + lastGeneratedLine++; + } + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + node.add(nextLine.substr(0, mapping.generatedColumn)); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + lastMapping = mapping; + }, this); + // We have processed all mappings. + if (remainingLines.length > 0) { + if (lastMapping) { + // Associate the remaining code in the current line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + } + // and add the remaining lines without any mapping + node.add(remainingLines.join("")); + } + + // Copy sourcesContent into SourceNode + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + if (aRelativePath != null) { + sourceFile = util.join(aRelativePath, sourceFile); + } + node.setSourceContent(sourceFile, content); + } + }); + + return node; + + function addMappingWithCode(mapping, code) { + if (mapping === null || mapping.source === undefined) { + node.add(code); + } else { + var source = aRelativePath + ? util.join(aRelativePath, mapping.source) + : mapping.source; + node.add(new SourceNode(mapping.originalLine, + mapping.originalColumn, + source, + code, + mapping.name)); + } + } + }; + + /** + * Add a chunk of generated JS to this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.add = function SourceNode_add(aChunk) { + if (Array.isArray(aChunk)) { + aChunk.forEach(function (chunk) { + this.add(chunk); + }, this); + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + if (aChunk) { + this.children.push(aChunk); + } + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Add a chunk of generated JS to the beginning of this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { + if (Array.isArray(aChunk)) { + for (var i = aChunk.length-1; i >= 0; i--) { + this.prepend(aChunk[i]); + } + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + this.children.unshift(aChunk); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Walk over the tree of JS snippets in this node and its children. The + * walking function is called once for each snippet of JS and is passed that + * snippet and the its original associated source's line/column location. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walk = function SourceNode_walk(aFn) { + var chunk; + for (var i = 0, len = this.children.length; i < len; i++) { + chunk = this.children[i]; + if (chunk[isSourceNode]) { + chunk.walk(aFn); + } + else { + if (chunk !== '') { + aFn(chunk, { source: this.source, + line: this.line, + column: this.column, + name: this.name }); + } + } + } + }; + + /** + * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between + * each of `this.children`. + * + * @param aSep The separator. + */ + SourceNode.prototype.join = function SourceNode_join(aSep) { + var newChildren; + var i; + var len = this.children.length; + if (len > 0) { + newChildren = []; + for (i = 0; i < len-1; i++) { + newChildren.push(this.children[i]); + newChildren.push(aSep); + } + newChildren.push(this.children[i]); + this.children = newChildren; + } + return this; + }; + + /** + * Call String.prototype.replace on the very right-most source snippet. Useful + * for trimming whitespace from the end of a source node, etc. + * + * @param aPattern The pattern to replace. + * @param aReplacement The thing to replace the pattern with. + */ + SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild[isSourceNode]) { + lastChild.replaceRight(aPattern, aReplacement); + } + else if (typeof lastChild === 'string') { + this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); + } + else { + this.children.push(''.replace(aPattern, aReplacement)); + } + return this; + }; + + /** + * Set the source content for a source file. This will be added to the SourceMapGenerator + * in the sourcesContent field. + * + * @param aSourceFile The filename of the source file + * @param aSourceContent The content of the source file + */ + SourceNode.prototype.setSourceContent = + function SourceNode_setSourceContent(aSourceFile, aSourceContent) { + this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; + }; + + /** + * Walk over the tree of SourceNodes. The walking function is called for each + * source file content and is passed the filename and source content. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walkSourceContents = + function SourceNode_walkSourceContents(aFn) { + for (var i = 0, len = this.children.length; i < len; i++) { + if (this.children[i][isSourceNode]) { + this.children[i].walkSourceContents(aFn); + } + } + + var sources = Object.keys(this.sourceContents); + for (var i = 0, len = sources.length; i < len; i++) { + aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); + } + }; + + /** + * Return the string representation of this source node. Walks over the tree + * and concatenates all the various snippets together to one string. + */ + SourceNode.prototype.toString = function SourceNode_toString() { + var str = ""; + this.walk(function (chunk) { + str += chunk; + }); + return str; + }; + + /** + * Returns the string representation of this source node along with a source + * map. + */ + SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { + var generated = { + code: "", + line: 1, + column: 0 + }; + var map = new SourceMapGenerator(aArgs); + var sourceMappingActive = false; + var lastOriginalSource = null; + var lastOriginalLine = null; + var lastOriginalColumn = null; + var lastOriginalName = null; + this.walk(function (chunk, original) { + generated.code += chunk; + if (original.source !== null + && original.line !== null + && original.column !== null) { + if(lastOriginalSource !== original.source + || lastOriginalLine !== original.line + || lastOriginalColumn !== original.column + || lastOriginalName !== original.name) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + lastOriginalSource = original.source; + lastOriginalLine = original.line; + lastOriginalColumn = original.column; + lastOriginalName = original.name; + sourceMappingActive = true; + } else if (sourceMappingActive) { + map.addMapping({ + generated: { + line: generated.line, + column: generated.column + } + }); + lastOriginalSource = null; + sourceMappingActive = false; + } + for (var idx = 0, length = chunk.length; idx < length; idx++) { + if (chunk.charCodeAt(idx) === NEWLINE_CODE) { + generated.line++; + generated.column = 0; + // Mappings end at eol + if (idx + 1 === length) { + lastOriginalSource = null; + sourceMappingActive = false; + } else if (sourceMappingActive) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + } else { + generated.column++; + } + } + }); + this.walkSourceContents(function (sourceFile, sourceContent) { + map.setSourceContent(sourceFile, sourceContent); + }); + + return { code: generated.code, map: map }; + }; + + exports.SourceNode = SourceNode; + +}); diff --git a/homework7/project_express/node_modules/source-map/lib/source-map/util.js b/homework7/project_express/node_modules/source-map/lib/source-map/util.js new file mode 100644 index 0000000..976f6ca --- /dev/null +++ b/homework7/project_express/node_modules/source-map/lib/source-map/util.js @@ -0,0 +1,319 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + /** + * This is a helper function for getting values from parameter/options + * objects. + * + * @param args The object we are extracting values from + * @param name The name of the property we are getting. + * @param defaultValue An optional value to return if the property is missing + * from the object. If this is not specified and the property is missing, an + * error will be thrown. + */ + function getArg(aArgs, aName, aDefaultValue) { + if (aName in aArgs) { + return aArgs[aName]; + } else if (arguments.length === 3) { + return aDefaultValue; + } else { + throw new Error('"' + aName + '" is a required argument.'); + } + } + exports.getArg = getArg; + + var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/; + var dataUrlRegexp = /^data:.+\,.+$/; + + function urlParse(aUrl) { + var match = aUrl.match(urlRegexp); + if (!match) { + return null; + } + return { + scheme: match[1], + auth: match[2], + host: match[3], + port: match[4], + path: match[5] + }; + } + exports.urlParse = urlParse; + + function urlGenerate(aParsedUrl) { + var url = ''; + if (aParsedUrl.scheme) { + url += aParsedUrl.scheme + ':'; + } + url += '//'; + if (aParsedUrl.auth) { + url += aParsedUrl.auth + '@'; + } + if (aParsedUrl.host) { + url += aParsedUrl.host; + } + if (aParsedUrl.port) { + url += ":" + aParsedUrl.port + } + if (aParsedUrl.path) { + url += aParsedUrl.path; + } + return url; + } + exports.urlGenerate = urlGenerate; + + /** + * Normalizes a path, or the path portion of a URL: + * + * - Replaces consequtive slashes with one slash. + * - Removes unnecessary '.' parts. + * - Removes unnecessary '/..' parts. + * + * Based on code in the Node.js 'path' core module. + * + * @param aPath The path or url to normalize. + */ + function normalize(aPath) { + var path = aPath; + var url = urlParse(aPath); + if (url) { + if (!url.path) { + return aPath; + } + path = url.path; + } + var isAbsolute = (path.charAt(0) === '/'); + + var parts = path.split(/\/+/); + for (var part, up = 0, i = parts.length - 1; i >= 0; i--) { + part = parts[i]; + if (part === '.') { + parts.splice(i, 1); + } else if (part === '..') { + up++; + } else if (up > 0) { + if (part === '') { + // The first part is blank if the path is absolute. Trying to go + // above the root is a no-op. Therefore we can remove all '..' parts + // directly after the root. + parts.splice(i + 1, up); + up = 0; + } else { + parts.splice(i, 2); + up--; + } + } + } + path = parts.join('/'); + + if (path === '') { + path = isAbsolute ? '/' : '.'; + } + + if (url) { + url.path = path; + return urlGenerate(url); + } + return path; + } + exports.normalize = normalize; + + /** + * Joins two paths/URLs. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be joined with the root. + * + * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a + * scheme-relative URL: Then the scheme of aRoot, if any, is prepended + * first. + * - Otherwise aPath is a path. If aRoot is a URL, then its path portion + * is updated with the result and aRoot is returned. Otherwise the result + * is returned. + * - If aPath is absolute, the result is aPath. + * - Otherwise the two paths are joined with a slash. + * - Joining for example 'http://' and 'www.example.com' is also supported. + */ + function join(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } + if (aPath === "") { + aPath = "."; + } + var aPathUrl = urlParse(aPath); + var aRootUrl = urlParse(aRoot); + if (aRootUrl) { + aRoot = aRootUrl.path || '/'; + } + + // `join(foo, '//www.example.org')` + if (aPathUrl && !aPathUrl.scheme) { + if (aRootUrl) { + aPathUrl.scheme = aRootUrl.scheme; + } + return urlGenerate(aPathUrl); + } + + if (aPathUrl || aPath.match(dataUrlRegexp)) { + return aPath; + } + + // `join('http://', 'www.example.com')` + if (aRootUrl && !aRootUrl.host && !aRootUrl.path) { + aRootUrl.host = aPath; + return urlGenerate(aRootUrl); + } + + var joined = aPath.charAt(0) === '/' + ? aPath + : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath); + + if (aRootUrl) { + aRootUrl.path = joined; + return urlGenerate(aRootUrl); + } + return joined; + } + exports.join = join; + + /** + * Make a path relative to a URL or another path. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be made relative to aRoot. + */ + function relative(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } + + aRoot = aRoot.replace(/\/$/, ''); + + // XXX: It is possible to remove this block, and the tests still pass! + var url = urlParse(aRoot); + if (aPath.charAt(0) == "/" && url && url.path == "/") { + return aPath.slice(1); + } + + return aPath.indexOf(aRoot + '/') === 0 + ? aPath.substr(aRoot.length + 1) + : aPath; + } + exports.relative = relative; + + /** + * Because behavior goes wacky when you set `__proto__` on objects, we + * have to prefix all the strings in our set with an arbitrary character. + * + * See https://github.com/mozilla/source-map/pull/31 and + * https://github.com/mozilla/source-map/issues/30 + * + * @param String aStr + */ + function toSetString(aStr) { + return '$' + aStr; + } + exports.toSetString = toSetString; + + function fromSetString(aStr) { + return aStr.substr(1); + } + exports.fromSetString = fromSetString; + + function strcmp(aStr1, aStr2) { + var s1 = aStr1 || ""; + var s2 = aStr2 || ""; + return (s1 > s2) - (s1 < s2); + } + + /** + * Comparator between two mappings where the original positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same original source/line/column, but different generated + * line and column the same. Useful when searching for a mapping with a + * stubbed out mapping. + */ + function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { + var cmp; + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp || onlyCompareOriginal) { + return cmp; + } + + cmp = strcmp(mappingA.name, mappingB.name); + if (cmp) { + return cmp; + } + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp) { + return cmp; + } + + return mappingA.generatedColumn - mappingB.generatedColumn; + }; + exports.compareByOriginalPositions = compareByOriginalPositions; + + /** + * Comparator between two mappings where the generated positions are + * compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same generated line and column, but different + * source/name/original line and column the same. Useful when searching for a + * mapping with a stubbed out mapping. + */ + function compareByGeneratedPositions(mappingA, mappingB, onlyCompareGenerated) { + var cmp; + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp || onlyCompareGenerated) { + return cmp; + } + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp) { + return cmp; + } + + return strcmp(mappingA.name, mappingB.name); + }; + exports.compareByGeneratedPositions = compareByGeneratedPositions; + +}); diff --git a/homework7/project_express/node_modules/source-map/package.json b/homework7/project_express/node_modules/source-map/package.json new file mode 100644 index 0000000..ba5665b --- /dev/null +++ b/homework7/project_express/node_modules/source-map/package.json @@ -0,0 +1,65 @@ +{ + "name": "source-map", + "description": "Generates and consumes source maps", + "version": "0.1.43", + "homepage": "https://github.com/mozilla/source-map", + "author": "Nick Fitzgerald ", + "contributors": [ + "Tobias Koppers ", + "Duncan Beevers ", + "Stephen Crane ", + "Ryan Seddon ", + "Miles Elam ", + "Mihai Bazon ", + "Michael Ficarra ", + "Todd Wolfson ", + "Alexander Solovyov ", + "Felix Gnass ", + "Conrad Irwin ", + "usrbincc ", + "David Glasser ", + "Chase Douglas ", + "Evan Wallace ", + "Heather Arthur ", + "Hugh Kennedy ", + "David Glasser ", + "Simon Lydell ", + "Jmeas Smith ", + "Michael Z Goddard ", + "azu ", + "John Gozde ", + "Adam Kirkton ", + "Chris Montgomery ", + "J. Ryan Stinnett ", + "Jack Herrington ", + "Chris Truter ", + "Daniel Espeset " + ], + "repository": { + "type": "git", + "url": "http://github.com/mozilla/source-map.git" + }, + "directories": { + "lib": "./lib" + }, + "main": "./lib/source-map.js", + "engines": { + "node": ">=0.8.0" + }, + "licenses": [ + { + "type": "BSD", + "url": "http://opensource.org/licenses/BSD-3-Clause" + } + ], + "dependencies": { + "amdefine": ">=0.0.4" + }, + "devDependencies": { + "dryice": ">=0.4.8" + }, + "scripts": { + "test": "node test/run-tests.js", + "build": "node Makefile.dryice.js" + } +} diff --git a/homework7/project_express/node_modules/source-map/test/run-tests.js b/homework7/project_express/node_modules/source-map/test/run-tests.js new file mode 100644 index 0000000..64a7c3a --- /dev/null +++ b/homework7/project_express/node_modules/source-map/test/run-tests.js @@ -0,0 +1,62 @@ +#!/usr/bin/env node +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +var assert = require('assert'); +var fs = require('fs'); +var path = require('path'); +var util = require('./source-map/util'); + +function run(tests) { + var total = 0; + var passed = 0; + + for (var i = 0; i < tests.length; i++) { + for (var k in tests[i].testCase) { + if (/^test/.test(k)) { + total++; + try { + tests[i].testCase[k](assert, util); + passed++; + } + catch (e) { + console.log('FAILED ' + tests[i].name + ': ' + k + '!'); + console.log(e.stack); + } + } + } + } + + console.log(''); + console.log(passed + ' / ' + total + ' tests passed.'); + console.log(''); + + return total - passed; +} + +function isTestFile(f) { + var testToRun = process.argv[2]; + return testToRun + ? path.basename(testToRun) === f + : /^test\-.*?\.js/.test(f); +} + +function toModule(f) { + return './source-map/' + f.replace(/\.js$/, ''); +} + +var requires = fs.readdirSync(path.join(__dirname, 'source-map')) + .filter(isTestFile) + .map(toModule); + +var code = run(requires.map(require).map(function (mod, i) { + return { + name: requires[i], + testCase: mod + }; +})); + +process.exit(code); diff --git a/homework7/project_express/node_modules/source-map/test/source-map/test-api.js b/homework7/project_express/node_modules/source-map/test/source-map/test-api.js new file mode 100644 index 0000000..3801233 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/test/source-map/test-api.js @@ -0,0 +1,26 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2012 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var sourceMap; + try { + sourceMap = require('../../lib/source-map'); + } catch (e) { + sourceMap = {}; + Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap); + } + + exports['test that the api is properly exposed in the top level'] = function (assert, util) { + assert.equal(typeof sourceMap.SourceMapGenerator, "function"); + assert.equal(typeof sourceMap.SourceMapConsumer, "function"); + assert.equal(typeof sourceMap.SourceNode, "function"); + }; + +}); diff --git a/homework7/project_express/node_modules/source-map/test/source-map/test-array-set.js b/homework7/project_express/node_modules/source-map/test/source-map/test-array-set.js new file mode 100644 index 0000000..b5797ed --- /dev/null +++ b/homework7/project_express/node_modules/source-map/test/source-map/test-array-set.js @@ -0,0 +1,104 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var ArraySet = require('../../lib/source-map/array-set').ArraySet; + + function makeTestSet() { + var set = new ArraySet(); + for (var i = 0; i < 100; i++) { + set.add(String(i)); + } + return set; + } + + exports['test .has() membership'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.ok(set.has(String(i))); + } + }; + + exports['test .indexOf() elements'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.strictEqual(set.indexOf(String(i)), i); + } + }; + + exports['test .at() indexing'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.strictEqual(set.at(i), String(i)); + } + }; + + exports['test creating from an array'] = function (assert, util) { + var set = ArraySet.fromArray(['foo', 'bar', 'baz', 'quux', 'hasOwnProperty']); + + assert.ok(set.has('foo')); + assert.ok(set.has('bar')); + assert.ok(set.has('baz')); + assert.ok(set.has('quux')); + assert.ok(set.has('hasOwnProperty')); + + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.indexOf('bar'), 1); + assert.strictEqual(set.indexOf('baz'), 2); + assert.strictEqual(set.indexOf('quux'), 3); + + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.at(1), 'bar'); + assert.strictEqual(set.at(2), 'baz'); + assert.strictEqual(set.at(3), 'quux'); + }; + + exports['test that you can add __proto__; see github issue #30'] = function (assert, util) { + var set = new ArraySet(); + set.add('__proto__'); + assert.ok(set.has('__proto__')); + assert.strictEqual(set.at(0), '__proto__'); + assert.strictEqual(set.indexOf('__proto__'), 0); + }; + + exports['test .fromArray() with duplicates'] = function (assert, util) { + var set = ArraySet.fromArray(['foo', 'foo']); + assert.ok(set.has('foo')); + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.toArray().length, 1); + + set = ArraySet.fromArray(['foo', 'foo'], true); + assert.ok(set.has('foo')); + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.at(1), 'foo'); + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.toArray().length, 2); + }; + + exports['test .add() with duplicates'] = function (assert, util) { + var set = new ArraySet(); + set.add('foo'); + + set.add('foo'); + assert.ok(set.has('foo')); + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.toArray().length, 1); + + set.add('foo', true); + assert.ok(set.has('foo')); + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.at(1), 'foo'); + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.toArray().length, 2); + }; + +}); diff --git a/homework7/project_express/node_modules/source-map/test/source-map/test-base64-vlq.js b/homework7/project_express/node_modules/source-map/test/source-map/test-base64-vlq.js new file mode 100644 index 0000000..6fd0d99 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/test/source-map/test-base64-vlq.js @@ -0,0 +1,23 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64VLQ = require('../../lib/source-map/base64-vlq'); + + exports['test normal encoding and decoding'] = function (assert, util) { + var result = {}; + for (var i = -255; i < 256; i++) { + base64VLQ.decode(base64VLQ.encode(i), result); + assert.equal(result.value, i); + assert.equal(result.rest, ""); + } + }; + +}); diff --git a/homework7/project_express/node_modules/source-map/test/source-map/test-base64.js b/homework7/project_express/node_modules/source-map/test/source-map/test-base64.js new file mode 100644 index 0000000..ff3a244 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/test/source-map/test-base64.js @@ -0,0 +1,35 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64 = require('../../lib/source-map/base64'); + + exports['test out of range encoding'] = function (assert, util) { + assert.throws(function () { + base64.encode(-1); + }); + assert.throws(function () { + base64.encode(64); + }); + }; + + exports['test out of range decoding'] = function (assert, util) { + assert.throws(function () { + base64.decode('='); + }); + }; + + exports['test normal encoding and decoding'] = function (assert, util) { + for (var i = 0; i < 64; i++) { + assert.equal(base64.decode(base64.encode(i)), i); + } + }; + +}); diff --git a/homework7/project_express/node_modules/source-map/test/source-map/test-binary-search.js b/homework7/project_express/node_modules/source-map/test/source-map/test-binary-search.js new file mode 100644 index 0000000..f1c9e0f --- /dev/null +++ b/homework7/project_express/node_modules/source-map/test/source-map/test-binary-search.js @@ -0,0 +1,54 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var binarySearch = require('../../lib/source-map/binary-search'); + + function numberCompare(a, b) { + return a - b; + } + + exports['test too high'] = function (assert, util) { + var needle = 30; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.doesNotThrow(function () { + binarySearch.search(needle, haystack, numberCompare); + }); + + assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare)], 20); + }; + + exports['test too low'] = function (assert, util) { + var needle = 1; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.doesNotThrow(function () { + binarySearch.search(needle, haystack, numberCompare); + }); + + assert.equal(binarySearch.search(needle, haystack, numberCompare), -1); + }; + + exports['test exact search'] = function (assert, util) { + var needle = 4; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare)], 4); + }; + + exports['test fuzzy search'] = function (assert, util) { + var needle = 19; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare)], 18); + }; + +}); diff --git a/homework7/project_express/node_modules/source-map/test/source-map/test-dog-fooding.js b/homework7/project_express/node_modules/source-map/test/source-map/test-dog-fooding.js new file mode 100644 index 0000000..26757b2 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/test/source-map/test-dog-fooding.js @@ -0,0 +1,84 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + + exports['test eating our own dog food'] = function (assert, util) { + var smg = new SourceMapGenerator({ + file: 'testing.js', + sourceRoot: '/wu/tang' + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 1, column: 0 }, + generated: { line: 2, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 2, column: 0 }, + generated: { line: 3, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 3, column: 0 }, + generated: { line: 4, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 4, column: 0 }, + generated: { line: 5, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 5, column: 10 }, + generated: { line: 6, column: 12 } + }); + + var smc = new SourceMapConsumer(smg.toString()); + + // Exact + util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 0, null, smc, assert); + util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 0, null, smc, assert); + util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 0, null, smc, assert); + util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 0, null, smc, assert); + util.assertMapping(6, 12, '/wu/tang/gza.coffee', 5, 10, null, smc, assert); + + // Fuzzy + + // Generated to original + util.assertMapping(2, 0, null, null, null, null, smc, assert, true); + util.assertMapping(2, 9, '/wu/tang/gza.coffee', 1, 0, null, smc, assert, true); + util.assertMapping(3, 0, null, null, null, null, smc, assert, true); + util.assertMapping(3, 9, '/wu/tang/gza.coffee', 2, 0, null, smc, assert, true); + util.assertMapping(4, 0, null, null, null, null, smc, assert, true); + util.assertMapping(4, 9, '/wu/tang/gza.coffee', 3, 0, null, smc, assert, true); + util.assertMapping(5, 0, null, null, null, null, smc, assert, true); + util.assertMapping(5, 9, '/wu/tang/gza.coffee', 4, 0, null, smc, assert, true); + util.assertMapping(6, 0, null, null, null, null, smc, assert, true); + util.assertMapping(6, 9, null, null, null, null, smc, assert, true); + util.assertMapping(6, 13, '/wu/tang/gza.coffee', 5, 10, null, smc, assert, true); + + // Original to generated + util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 1, null, smc, assert, null, true); + util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 3, null, smc, assert, null, true); + util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 6, null, smc, assert, null, true); + util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 9, null, smc, assert, null, true); + util.assertMapping(5, 2, '/wu/tang/gza.coffee', 5, 9, null, smc, assert, null, true); + util.assertMapping(6, 12, '/wu/tang/gza.coffee', 6, 19, null, smc, assert, null, true); + }; + +}); diff --git a/homework7/project_express/node_modules/source-map/test/source-map/test-source-map-consumer.js b/homework7/project_express/node_modules/source-map/test/source-map/test-source-map-consumer.js new file mode 100644 index 0000000..c714943 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/test/source-map/test-source-map-consumer.js @@ -0,0 +1,702 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + + exports['test that we can instantiate with a string or an object'] = function (assert, util) { + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(util.testMap); + }); + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(JSON.stringify(util.testMap)); + }); + }; + + exports['test that the `sources` field has the original sources'] = function (assert, util) { + var map; + var sources; + + map = new SourceMapConsumer(util.testMap); + sources = map.sources; + assert.equal(sources[0], '/the/root/one.js'); + assert.equal(sources[1], '/the/root/two.js'); + assert.equal(sources.length, 2); + + map = new SourceMapConsumer(util.testMapNoSourceRoot); + sources = map.sources; + assert.equal(sources[0], 'one.js'); + assert.equal(sources[1], 'two.js'); + assert.equal(sources.length, 2); + + map = new SourceMapConsumer(util.testMapEmptySourceRoot); + sources = map.sources; + assert.equal(sources[0], 'one.js'); + assert.equal(sources[1], 'two.js'); + assert.equal(sources.length, 2); + }; + + exports['test that the source root is reflected in a mapping\'s source field'] = function (assert, util) { + var map; + var mapping; + + map = new SourceMapConsumer(util.testMap); + + mapping = map.originalPositionFor({ + line: 2, + column: 1 + }); + assert.equal(mapping.source, '/the/root/two.js'); + + mapping = map.originalPositionFor({ + line: 1, + column: 1 + }); + assert.equal(mapping.source, '/the/root/one.js'); + + + map = new SourceMapConsumer(util.testMapNoSourceRoot); + + mapping = map.originalPositionFor({ + line: 2, + column: 1 + }); + assert.equal(mapping.source, 'two.js'); + + mapping = map.originalPositionFor({ + line: 1, + column: 1 + }); + assert.equal(mapping.source, 'one.js'); + + + map = new SourceMapConsumer(util.testMapEmptySourceRoot); + + mapping = map.originalPositionFor({ + line: 2, + column: 1 + }); + assert.equal(mapping.source, 'two.js'); + + mapping = map.originalPositionFor({ + line: 1, + column: 1 + }); + assert.equal(mapping.source, 'one.js'); + }; + + exports['test mapping tokens back exactly'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + + util.assertMapping(1, 1, '/the/root/one.js', 1, 1, null, map, assert); + util.assertMapping(1, 5, '/the/root/one.js', 1, 5, null, map, assert); + util.assertMapping(1, 9, '/the/root/one.js', 1, 11, null, map, assert); + util.assertMapping(1, 18, '/the/root/one.js', 1, 21, 'bar', map, assert); + util.assertMapping(1, 21, '/the/root/one.js', 2, 3, null, map, assert); + util.assertMapping(1, 28, '/the/root/one.js', 2, 10, 'baz', map, assert); + util.assertMapping(1, 32, '/the/root/one.js', 2, 14, 'bar', map, assert); + + util.assertMapping(2, 1, '/the/root/two.js', 1, 1, null, map, assert); + util.assertMapping(2, 5, '/the/root/two.js', 1, 5, null, map, assert); + util.assertMapping(2, 9, '/the/root/two.js', 1, 11, null, map, assert); + util.assertMapping(2, 18, '/the/root/two.js', 1, 21, 'n', map, assert); + util.assertMapping(2, 21, '/the/root/two.js', 2, 3, null, map, assert); + util.assertMapping(2, 28, '/the/root/two.js', 2, 10, 'n', map, assert); + }; + + exports['test mapping tokens fuzzy'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + + // Finding original positions + util.assertMapping(1, 20, '/the/root/one.js', 1, 21, 'bar', map, assert, true); + util.assertMapping(1, 30, '/the/root/one.js', 2, 10, 'baz', map, assert, true); + util.assertMapping(2, 12, '/the/root/two.js', 1, 11, null, map, assert, true); + + // Finding generated positions + util.assertMapping(1, 18, '/the/root/one.js', 1, 22, 'bar', map, assert, null, true); + util.assertMapping(1, 28, '/the/root/one.js', 2, 13, 'baz', map, assert, null, true); + util.assertMapping(2, 9, '/the/root/two.js', 1, 16, null, map, assert, null, true); + }; + + exports['test mappings and end of lines'] = function (assert, util) { + var smg = new SourceMapGenerator({ + file: 'foo.js' + }); + smg.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 1, column: 1 }, + source: 'bar.js' + }); + smg.addMapping({ + original: { line: 2, column: 2 }, + generated: { line: 2, column: 2 }, + source: 'bar.js' + }); + + var map = SourceMapConsumer.fromSourceMap(smg); + + // When finding original positions, mappings end at the end of the line. + util.assertMapping(2, 1, null, null, null, null, map, assert, true) + + // When finding generated positions, mappings do not end at the end of the line. + util.assertMapping(1, 1, 'bar.js', 2, 1, null, map, assert, null, true); + }; + + exports['test creating source map consumers with )]}\' prefix'] = function (assert, util) { + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(")]}'" + JSON.stringify(util.testMap)); + }); + }; + + exports['test eachMapping'] = function (assert, util) { + var map; + + map = new SourceMapConsumer(util.testMap); + var previousLine = -Infinity; + var previousColumn = -Infinity; + map.eachMapping(function (mapping) { + assert.ok(mapping.generatedLine >= previousLine); + + assert.ok(mapping.source === '/the/root/one.js' || mapping.source === '/the/root/two.js'); + + if (mapping.generatedLine === previousLine) { + assert.ok(mapping.generatedColumn >= previousColumn); + previousColumn = mapping.generatedColumn; + } + else { + previousLine = mapping.generatedLine; + previousColumn = -Infinity; + } + }); + + map = new SourceMapConsumer(util.testMapNoSourceRoot); + map.eachMapping(function (mapping) { + assert.ok(mapping.source === 'one.js' || mapping.source === 'two.js'); + }); + + map = new SourceMapConsumer(util.testMapEmptySourceRoot); + map.eachMapping(function (mapping) { + assert.ok(mapping.source === 'one.js' || mapping.source === 'two.js'); + }); + }; + + exports['test iterating over mappings in a different order'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var previousLine = -Infinity; + var previousColumn = -Infinity; + var previousSource = ""; + map.eachMapping(function (mapping) { + assert.ok(mapping.source >= previousSource); + + if (mapping.source === previousSource) { + assert.ok(mapping.originalLine >= previousLine); + + if (mapping.originalLine === previousLine) { + assert.ok(mapping.originalColumn >= previousColumn); + previousColumn = mapping.originalColumn; + } + else { + previousLine = mapping.originalLine; + previousColumn = -Infinity; + } + } + else { + previousSource = mapping.source; + previousLine = -Infinity; + previousColumn = -Infinity; + } + }, null, SourceMapConsumer.ORIGINAL_ORDER); + }; + + exports['test that we can set the context for `this` in eachMapping'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var context = {}; + map.eachMapping(function () { + assert.equal(this, context); + }, context); + }; + + exports['test that the `sourcesContent` field has the original sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMapWithSourcesContent); + var sourcesContent = map.sourcesContent; + + assert.equal(sourcesContent[0], ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(sourcesContent[1], ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.equal(sourcesContent.length, 2); + }; + + exports['test that we can get the original sources for the sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMapWithSourcesContent); + var sources = map.sources; + + assert.equal(map.sourceContentFor(sources[0]), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor(sources[1]), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.equal(map.sourceContentFor("one.js"), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor("two.js"), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.throws(function () { + map.sourceContentFor(""); + }, Error); + assert.throws(function () { + map.sourceContentFor("/the/root/three.js"); + }, Error); + assert.throws(function () { + map.sourceContentFor("three.js"); + }, Error); + }; + + exports['test that we can get the original source content with relative source paths'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMapRelativeSources); + var sources = map.sources; + + assert.equal(map.sourceContentFor(sources[0]), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor(sources[1]), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.equal(map.sourceContentFor("one.js"), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor("two.js"), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.throws(function () { + map.sourceContentFor(""); + }, Error); + assert.throws(function () { + map.sourceContentFor("/the/root/three.js"); + }, Error); + assert.throws(function () { + map.sourceContentFor("three.js"); + }, Error); + }; + + exports['test sourceRoot + generatedPositionFor'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'foo/bar', + file: 'baz.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bang.coffee' + }); + map.addMapping({ + original: { line: 5, column: 5 }, + generated: { line: 6, column: 6 }, + source: 'bang.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + // Should handle without sourceRoot. + var pos = map.generatedPositionFor({ + line: 1, + column: 1, + source: 'bang.coffee' + }); + + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + + // Should handle with sourceRoot. + var pos = map.generatedPositionFor({ + line: 1, + column: 1, + source: 'foo/bar/bang.coffee' + }); + + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + }; + + exports['test allGeneratedPositionsFor'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bar.coffee' + }); + map.addMapping({ + original: { line: 2, column: 1 }, + generated: { line: 3, column: 2 }, + source: 'bar.coffee' + }); + map.addMapping({ + original: { line: 2, column: 2 }, + generated: { line: 3, column: 3 }, + source: 'bar.coffee' + }); + map.addMapping({ + original: { line: 3, column: 1 }, + generated: { line: 4, column: 2 }, + source: 'bar.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + var mappings = map.allGeneratedPositionsFor({ + line: 2, + source: 'bar.coffee' + }); + + assert.equal(mappings.length, 2); + assert.equal(mappings[0].line, 3); + assert.equal(mappings[0].column, 2); + assert.equal(mappings[1].line, 3); + assert.equal(mappings[1].column, 3); + }; + + exports['test allGeneratedPositionsFor for line with no mappings'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bar.coffee' + }); + map.addMapping({ + original: { line: 3, column: 1 }, + generated: { line: 4, column: 2 }, + source: 'bar.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + var mappings = map.allGeneratedPositionsFor({ + line: 2, + source: 'bar.coffee' + }); + + assert.equal(mappings.length, 0); + }; + + exports['test allGeneratedPositionsFor source map with no mappings'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated.js' + }); + map = new SourceMapConsumer(map.toString()); + + var mappings = map.allGeneratedPositionsFor({ + line: 2, + source: 'bar.coffee' + }); + + assert.equal(mappings.length, 0); + }; + + exports['test computeColumnSpans'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 1, column: 1 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 2, column: 1 }, + generated: { line: 2, column: 1 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 2, column: 2 }, + generated: { line: 2, column: 10 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 2, column: 3 }, + generated: { line: 2, column: 20 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 3, column: 1 }, + generated: { line: 3, column: 1 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 3, column: 2 }, + generated: { line: 3, column: 2 }, + source: 'foo.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + map.computeColumnSpans(); + + var mappings = map.allGeneratedPositionsFor({ + line: 1, + source: 'foo.coffee' + }); + + assert.equal(mappings.length, 1); + assert.equal(mappings[0].lastColumn, Infinity); + + var mappings = map.allGeneratedPositionsFor({ + line: 2, + source: 'foo.coffee' + }); + + assert.equal(mappings.length, 3); + assert.equal(mappings[0].lastColumn, 9); + assert.equal(mappings[1].lastColumn, 19); + assert.equal(mappings[2].lastColumn, Infinity); + + var mappings = map.allGeneratedPositionsFor({ + line: 3, + source: 'foo.coffee' + }); + + assert.equal(mappings.length, 2); + assert.equal(mappings[0].lastColumn, 1); + assert.equal(mappings[1].lastColumn, Infinity); + }; + + exports['test sourceRoot + originalPositionFor'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'foo/bar', + file: 'baz.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bang.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + var pos = map.originalPositionFor({ + line: 2, + column: 2, + }); + + // Should always have the prepended source root + assert.equal(pos.source, 'foo/bar/bang.coffee'); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + }; + + exports['test github issue #56'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://', + file: 'www.example.com/foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'www.example.com/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1); + assert.equal(sources[0], 'http://www.example.com/original.js'); + }; + + exports['test github issue #43'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://example.com', + file: 'foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'http://cdn.example.com/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1, + 'Should only be one source.'); + assert.equal(sources[0], 'http://cdn.example.com/original.js', + 'Should not be joined with the sourceRoot.'); + }; + + exports['test absolute path, but same host sources'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://example.com/foo/bar', + file: 'foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: '/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1, + 'Should only be one source.'); + assert.equal(sources[0], 'http://example.com/original.js', + 'Source should be relative the host of the source root.'); + }; + + exports['test github issue #64'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sourceRoot": "http://example.com/", + "sources": ["/a"], + "names": [], + "mappings": "AACA", + "sourcesContent": ["foo"] + }); + + assert.equal(map.sourceContentFor("a"), "foo"); + assert.equal(map.sourceContentFor("/a"), "foo"); + }; + + exports['test bug 885597'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sourceRoot": "file:///Users/AlGore/Invented/The/Internet/", + "sources": ["/a"], + "names": [], + "mappings": "AACA", + "sourcesContent": ["foo"] + }); + + var s = map.sources[0]; + assert.equal(map.sourceContentFor(s), "foo"); + }; + + exports['test github issue #72, duplicate sources'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sources": ["source1.js", "source1.js", "source3.js"], + "names": [], + "mappings": ";EAAC;;IAEE;;MEEE", + "sourceRoot": "http://example.com" + }); + + var pos = map.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(pos.source, 'http://example.com/source1.js'); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + + var pos = map.originalPositionFor({ + line: 4, + column: 4 + }); + assert.equal(pos.source, 'http://example.com/source1.js'); + assert.equal(pos.line, 3); + assert.equal(pos.column, 3); + + var pos = map.originalPositionFor({ + line: 6, + column: 6 + }); + assert.equal(pos.source, 'http://example.com/source3.js'); + assert.equal(pos.line, 5); + assert.equal(pos.column, 5); + }; + + exports['test github issue #72, duplicate names'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sources": ["source.js"], + "names": ["name1", "name1", "name3"], + "mappings": ";EAACA;;IAEEA;;MAEEE", + "sourceRoot": "http://example.com" + }); + + var pos = map.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(pos.name, 'name1'); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + + var pos = map.originalPositionFor({ + line: 4, + column: 4 + }); + assert.equal(pos.name, 'name1'); + assert.equal(pos.line, 3); + assert.equal(pos.column, 3); + + var pos = map.originalPositionFor({ + line: 6, + column: 6 + }); + assert.equal(pos.name, 'name3'); + assert.equal(pos.line, 5); + assert.equal(pos.column, 5); + }; + + exports['test SourceMapConsumer.fromSourceMap'] = function (assert, util) { + var smg = new SourceMapGenerator({ + sourceRoot: 'http://example.com/', + file: 'foo.js' + }); + smg.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bar.js' + }); + smg.addMapping({ + original: { line: 2, column: 2 }, + generated: { line: 4, column: 4 }, + source: 'baz.js', + name: 'dirtMcGirt' + }); + smg.setSourceContent('baz.js', 'baz.js content'); + + var smc = SourceMapConsumer.fromSourceMap(smg); + assert.equal(smc.file, 'foo.js'); + assert.equal(smc.sourceRoot, 'http://example.com/'); + assert.equal(smc.sources.length, 2); + assert.equal(smc.sources[0], 'http://example.com/bar.js'); + assert.equal(smc.sources[1], 'http://example.com/baz.js'); + assert.equal(smc.sourceContentFor('baz.js'), 'baz.js content'); + + var pos = smc.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + assert.equal(pos.source, 'http://example.com/bar.js'); + assert.equal(pos.name, null); + + pos = smc.generatedPositionFor({ + line: 1, + column: 1, + source: 'http://example.com/bar.js' + }); + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + + pos = smc.originalPositionFor({ + line: 4, + column: 4 + }); + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + assert.equal(pos.source, 'http://example.com/baz.js'); + assert.equal(pos.name, 'dirtMcGirt'); + + pos = smc.generatedPositionFor({ + line: 2, + column: 2, + source: 'http://example.com/baz.js' + }); + assert.equal(pos.line, 4); + assert.equal(pos.column, 4); + }; +}); diff --git a/homework7/project_express/node_modules/source-map/test/source-map/test-source-map-generator.js b/homework7/project_express/node_modules/source-map/test/source-map/test-source-map-generator.js new file mode 100644 index 0000000..d748bb1 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/test/source-map/test-source-map-generator.js @@ -0,0 +1,679 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceNode = require('../../lib/source-map/source-node').SourceNode; + var util = require('./util'); + + exports['test some simple stuff'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'foo.js', + sourceRoot: '.' + }); + assert.ok(true); + + var map = new SourceMapGenerator().toJSON(); + assert.ok(!('file' in map)); + assert.ok(!('sourceRoot' in map)); + }; + + exports['test JSON serialization'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'foo.js', + sourceRoot: '.' + }); + assert.equal(map.toString(), JSON.stringify(map)); + }; + + exports['test adding mappings (case 1)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 } + }); + }); + }; + + exports['test adding mappings (case 2)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + source: 'bar.js', + original: { line: 1, column: 1 } + }); + }); + }; + + exports['test adding mappings (case 3)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + source: 'bar.js', + original: { line: 1, column: 1 }, + name: 'someToken' + }); + }); + }; + + exports['test adding mappings (invalid)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + // Not enough info. + assert.throws(function () { + map.addMapping({}); + }); + + // Original file position, but no source. + assert.throws(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 } + }); + }); + }; + + exports['test adding mappings with skipValidation'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.', + skipValidation: true + }); + + // Not enough info, caught by `util.getArgs` + assert.throws(function () { + map.addMapping({}); + }); + + // Original file position, but no source. Not checked. + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 } + }); + }); + }; + + exports['test that the correct mappings are being generated'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'min.js', + sourceRoot: '/the/root' + }); + + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 5 }, + original: { line: 1, column: 5 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 9 }, + original: { line: 1, column: 11 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 18 }, + original: { line: 1, column: 21 }, + source: 'one.js', + name: 'bar' + }); + map.addMapping({ + generated: { line: 1, column: 21 }, + original: { line: 2, column: 3 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 28 }, + original: { line: 2, column: 10 }, + source: 'one.js', + name: 'baz' + }); + map.addMapping({ + generated: { line: 1, column: 32 }, + original: { line: 2, column: 14 }, + source: 'one.js', + name: 'bar' + }); + + map.addMapping({ + generated: { line: 2, column: 1 }, + original: { line: 1, column: 1 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 5 }, + original: { line: 1, column: 5 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 9 }, + original: { line: 1, column: 11 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 18 }, + original: { line: 1, column: 21 }, + source: 'two.js', + name: 'n' + }); + map.addMapping({ + generated: { line: 2, column: 21 }, + original: { line: 2, column: 3 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 28 }, + original: { line: 2, column: 10 }, + source: 'two.js', + name: 'n' + }); + + map = JSON.parse(map.toString()); + + util.assertEqualMaps(assert, map, util.testMap); + }; + + exports['test that adding a mapping with an empty string name does not break generation'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + map.addMapping({ + generated: { line: 1, column: 1 }, + source: 'bar.js', + original: { line: 1, column: 1 }, + name: '' + }); + + assert.doesNotThrow(function () { + JSON.parse(map.toString()); + }); + }; + + exports['test that source content can be set'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'min.js', + sourceRoot: '/the/root' + }); + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 2, column: 1 }, + original: { line: 1, column: 1 }, + source: 'two.js' + }); + map.setSourceContent('one.js', 'one file content'); + + map = JSON.parse(map.toString()); + assert.equal(map.sources[0], 'one.js'); + assert.equal(map.sources[1], 'two.js'); + assert.equal(map.sourcesContent[0], 'one file content'); + assert.equal(map.sourcesContent[1], null); + }; + + exports['test .fromSourceMap'] = function (assert, util) { + var map = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(util.testMap)); + util.assertEqualMaps(assert, map.toJSON(), util.testMap); + }; + + exports['test .fromSourceMap with sourcesContent'] = function (assert, util) { + var map = SourceMapGenerator.fromSourceMap( + new SourceMapConsumer(util.testMapWithSourcesContent)); + util.assertEqualMaps(assert, map.toJSON(), util.testMapWithSourcesContent); + }; + + exports['test applySourceMap'] = function (assert, util) { + var node = new SourceNode(null, null, null, [ + new SourceNode(2, 0, 'fileX', 'lineX2\n'), + 'genA1\n', + new SourceNode(2, 0, 'fileY', 'lineY2\n'), + 'genA2\n', + new SourceNode(1, 0, 'fileX', 'lineX1\n'), + 'genA3\n', + new SourceNode(1, 0, 'fileY', 'lineY1\n') + ]); + var mapStep1 = node.toStringWithSourceMap({ + file: 'fileA' + }).map; + mapStep1.setSourceContent('fileX', 'lineX1\nlineX2\n'); + mapStep1 = mapStep1.toJSON(); + + node = new SourceNode(null, null, null, [ + 'gen1\n', + new SourceNode(1, 0, 'fileA', 'lineA1\n'), + new SourceNode(2, 0, 'fileA', 'lineA2\n'), + new SourceNode(3, 0, 'fileA', 'lineA3\n'), + new SourceNode(4, 0, 'fileA', 'lineA4\n'), + new SourceNode(1, 0, 'fileB', 'lineB1\n'), + new SourceNode(2, 0, 'fileB', 'lineB2\n'), + 'gen2\n' + ]); + var mapStep2 = node.toStringWithSourceMap({ + file: 'fileGen' + }).map; + mapStep2.setSourceContent('fileB', 'lineB1\nlineB2\n'); + mapStep2 = mapStep2.toJSON(); + + node = new SourceNode(null, null, null, [ + 'gen1\n', + new SourceNode(2, 0, 'fileX', 'lineA1\n'), + new SourceNode(2, 0, 'fileA', 'lineA2\n'), + new SourceNode(2, 0, 'fileY', 'lineA3\n'), + new SourceNode(4, 0, 'fileA', 'lineA4\n'), + new SourceNode(1, 0, 'fileB', 'lineB1\n'), + new SourceNode(2, 0, 'fileB', 'lineB2\n'), + 'gen2\n' + ]); + var expectedMap = node.toStringWithSourceMap({ + file: 'fileGen' + }).map; + expectedMap.setSourceContent('fileX', 'lineX1\nlineX2\n'); + expectedMap.setSourceContent('fileB', 'lineB1\nlineB2\n'); + expectedMap = expectedMap.toJSON(); + + // apply source map "mapStep1" to "mapStep2" + var generator = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(mapStep2)); + generator.applySourceMap(new SourceMapConsumer(mapStep1)); + var actualMap = generator.toJSON(); + + util.assertEqualMaps(assert, actualMap, expectedMap); + }; + + exports['test applySourceMap throws when file is missing'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'test.js' + }); + var map2 = new SourceMapGenerator(); + assert.throws(function() { + map.applySourceMap(new SourceMapConsumer(map2.toJSON())); + }); + }; + + exports['test the two additional parameters of applySourceMap'] = function (assert, util) { + // Assume the following directory structure: + // + // http://foo.org/ + // bar.coffee + // app/ + // coffee/ + // foo.coffee + // temp/ + // bundle.js + // temp_maps/ + // bundle.js.map + // public/ + // bundle.min.js + // bundle.min.js.map + // + // http://www.example.com/ + // baz.coffee + + var bundleMap = new SourceMapGenerator({ + file: 'bundle.js' + }); + bundleMap.addMapping({ + generated: { line: 3, column: 3 }, + original: { line: 2, column: 2 }, + source: '../../coffee/foo.coffee' + }); + bundleMap.setSourceContent('../../coffee/foo.coffee', 'foo coffee'); + bundleMap.addMapping({ + generated: { line: 13, column: 13 }, + original: { line: 12, column: 12 }, + source: '/bar.coffee' + }); + bundleMap.setSourceContent('/bar.coffee', 'bar coffee'); + bundleMap.addMapping({ + generated: { line: 23, column: 23 }, + original: { line: 22, column: 22 }, + source: 'http://www.example.com/baz.coffee' + }); + bundleMap.setSourceContent( + 'http://www.example.com/baz.coffee', + 'baz coffee' + ); + bundleMap = new SourceMapConsumer(bundleMap.toJSON()); + + var minifiedMap = new SourceMapGenerator({ + file: 'bundle.min.js', + sourceRoot: '..' + }); + minifiedMap.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 3, column: 3 }, + source: 'temp/bundle.js' + }); + minifiedMap.addMapping({ + generated: { line: 11, column: 11 }, + original: { line: 13, column: 13 }, + source: 'temp/bundle.js' + }); + minifiedMap.addMapping({ + generated: { line: 21, column: 21 }, + original: { line: 23, column: 23 }, + source: 'temp/bundle.js' + }); + minifiedMap = new SourceMapConsumer(minifiedMap.toJSON()); + + var expectedMap = function (sources) { + var map = new SourceMapGenerator({ + file: 'bundle.min.js', + sourceRoot: '..' + }); + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 2, column: 2 }, + source: sources[0] + }); + map.setSourceContent(sources[0], 'foo coffee'); + map.addMapping({ + generated: { line: 11, column: 11 }, + original: { line: 12, column: 12 }, + source: sources[1] + }); + map.setSourceContent(sources[1], 'bar coffee'); + map.addMapping({ + generated: { line: 21, column: 21 }, + original: { line: 22, column: 22 }, + source: sources[2] + }); + map.setSourceContent(sources[2], 'baz coffee'); + return map.toJSON(); + } + + var actualMap = function (aSourceMapPath) { + var map = SourceMapGenerator.fromSourceMap(minifiedMap); + // Note that relying on `bundleMap.file` (which is simply 'bundle.js') + // instead of supplying the second parameter wouldn't work here. + map.applySourceMap(bundleMap, '../temp/bundle.js', aSourceMapPath); + return map.toJSON(); + } + + util.assertEqualMaps(assert, actualMap('../temp/temp_maps'), expectedMap([ + 'coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); + + util.assertEqualMaps(assert, actualMap('/app/temp/temp_maps'), expectedMap([ + '/app/coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); + + util.assertEqualMaps(assert, actualMap('http://foo.org/app/temp/temp_maps'), expectedMap([ + 'http://foo.org/app/coffee/foo.coffee', + 'http://foo.org/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); + + // If the third parameter is omitted or set to the current working + // directory we get incorrect source paths: + + util.assertEqualMaps(assert, actualMap(), expectedMap([ + '../coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); + + util.assertEqualMaps(assert, actualMap(''), expectedMap([ + '../coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); + + util.assertEqualMaps(assert, actualMap('.'), expectedMap([ + '../coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); + + util.assertEqualMaps(assert, actualMap('./'), expectedMap([ + '../coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); + }; + + exports['test applySourceMap name handling'] = function (assert, util) { + // Imagine some CoffeeScript code being compiled into JavaScript and then + // minified. + + var assertName = function(coffeeName, jsName, expectedName) { + var minifiedMap = new SourceMapGenerator({ + file: 'test.js.min' + }); + minifiedMap.addMapping({ + generated: { line: 1, column: 4 }, + original: { line: 1, column: 4 }, + source: 'test.js', + name: jsName + }); + + var coffeeMap = new SourceMapGenerator({ + file: 'test.js' + }); + coffeeMap.addMapping({ + generated: { line: 1, column: 4 }, + original: { line: 1, column: 0 }, + source: 'test.coffee', + name: coffeeName + }); + + minifiedMap.applySourceMap(new SourceMapConsumer(coffeeMap.toJSON())); + + new SourceMapConsumer(minifiedMap.toJSON()).eachMapping(function(mapping) { + assert.equal(mapping.name, expectedName); + }); + }; + + // `foo = 1` -> `var foo = 1;` -> `var a=1` + // CoffeeScript doesn’t rename variables, so there’s no need for it to + // provide names in its source maps. Minifiers do rename variables and + // therefore do provide names in their source maps. So that name should be + // retained if the original map lacks names. + assertName(null, 'foo', 'foo'); + + // `foo = 1` -> `var coffee$foo = 1;` -> `var a=1` + // Imagine that CoffeeScript prefixed all variables with `coffee$`. Even + // though the minifier then also provides a name, the original name is + // what corresponds to the source. + assertName('foo', 'coffee$foo', 'foo'); + + // `foo = 1` -> `var coffee$foo = 1;` -> `var coffee$foo=1` + // Minifiers can turn off variable mangling. Then there’s no need to + // provide names in the source map, but the names from the original map are + // still needed. + assertName('foo', null, 'foo'); + + // `foo = 1` -> `var foo = 1;` -> `var foo=1` + // No renaming at all. + assertName(null, null, null); + }; + + exports['test sorting with duplicate generated mappings'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'test.js' + }); + map.addMapping({ + generated: { line: 3, column: 0 }, + original: { line: 2, column: 0 }, + source: 'a.js' + }); + map.addMapping({ + generated: { line: 2, column: 0 } + }); + map.addMapping({ + generated: { line: 2, column: 0 } + }); + map.addMapping({ + generated: { line: 1, column: 0 }, + original: { line: 1, column: 0 }, + source: 'a.js' + }); + + util.assertEqualMaps(assert, map.toJSON(), { + version: 3, + file: 'test.js', + sources: ['a.js'], + names: [], + mappings: 'AAAA;A;AACA' + }); + }; + + exports['test ignore duplicate mappings.'] = function (assert, util) { + var init = { file: 'min.js', sourceRoot: '/the/root' }; + var map1, map2; + + // null original source location + var nullMapping1 = { + generated: { line: 1, column: 0 } + }; + var nullMapping2 = { + generated: { line: 2, column: 2 } + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(nullMapping1); + map1.addMapping(nullMapping1); + + map2.addMapping(nullMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(nullMapping2); + map1.addMapping(nullMapping1); + + map2.addMapping(nullMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + // original source location + var srcMapping1 = { + generated: { line: 1, column: 0 }, + original: { line: 11, column: 0 }, + source: 'srcMapping1.js' + }; + var srcMapping2 = { + generated: { line: 2, column: 2 }, + original: { line: 11, column: 0 }, + source: 'srcMapping2.js' + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(srcMapping1); + map1.addMapping(srcMapping1); + + map2.addMapping(srcMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(srcMapping2); + map1.addMapping(srcMapping1); + + map2.addMapping(srcMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + // full original source and name information + var fullMapping1 = { + generated: { line: 1, column: 0 }, + original: { line: 11, column: 0 }, + source: 'fullMapping1.js', + name: 'fullMapping1' + }; + var fullMapping2 = { + generated: { line: 2, column: 2 }, + original: { line: 11, column: 0 }, + source: 'fullMapping2.js', + name: 'fullMapping2' + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(fullMapping1); + map1.addMapping(fullMapping1); + + map2.addMapping(fullMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(fullMapping2); + map1.addMapping(fullMapping1); + + map2.addMapping(fullMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + }; + + exports['test github issue #72, check for duplicate names or sources'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'test.js' + }); + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 2, column: 2 }, + source: 'a.js', + name: 'foo' + }); + map.addMapping({ + generated: { line: 3, column: 3 }, + original: { line: 4, column: 4 }, + source: 'a.js', + name: 'foo' + }); + util.assertEqualMaps(assert, map.toJSON(), { + version: 3, + file: 'test.js', + sources: ['a.js'], + names: ['foo'], + mappings: 'CACEA;;GAEEA' + }); + }; + + exports['test setting sourcesContent to null when already null'] = function (assert, util) { + var smg = new SourceMapGenerator({ file: "foo.js" }); + assert.doesNotThrow(function() { + smg.setSourceContent("bar.js", null); + }); + }; + +}); diff --git a/homework7/project_express/node_modules/source-map/test/source-map/test-source-node.js b/homework7/project_express/node_modules/source-map/test/source-map/test-source-node.js new file mode 100644 index 0000000..139af4e --- /dev/null +++ b/homework7/project_express/node_modules/source-map/test/source-map/test-source-node.js @@ -0,0 +1,612 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceNode = require('../../lib/source-map/source-node').SourceNode; + + function forEachNewline(fn) { + return function (assert, util) { + ['\n', '\r\n'].forEach(fn.bind(null, assert, util)); + } + } + + exports['test .add()'] = function (assert, util) { + var node = new SourceNode(null, null, null); + + // Adding a string works. + node.add('function noop() {}'); + + // Adding another source node works. + node.add(new SourceNode(null, null, null)); + + // Adding an array works. + node.add(['function foo() {', + new SourceNode(null, null, null, + 'return 10;'), + '}']); + + // Adding other stuff doesn't. + assert.throws(function () { + node.add({}); + }); + assert.throws(function () { + node.add(function () {}); + }); + }; + + exports['test .prepend()'] = function (assert, util) { + var node = new SourceNode(null, null, null); + + // Prepending a string works. + node.prepend('function noop() {}'); + assert.equal(node.children[0], 'function noop() {}'); + assert.equal(node.children.length, 1); + + // Prepending another source node works. + node.prepend(new SourceNode(null, null, null)); + assert.equal(node.children[0], ''); + assert.equal(node.children[1], 'function noop() {}'); + assert.equal(node.children.length, 2); + + // Prepending an array works. + node.prepend(['function foo() {', + new SourceNode(null, null, null, + 'return 10;'), + '}']); + assert.equal(node.children[0], 'function foo() {'); + assert.equal(node.children[1], 'return 10;'); + assert.equal(node.children[2], '}'); + assert.equal(node.children[3], ''); + assert.equal(node.children[4], 'function noop() {}'); + assert.equal(node.children.length, 5); + + // Prepending other stuff doesn't. + assert.throws(function () { + node.prepend({}); + }); + assert.throws(function () { + node.prepend(function () {}); + }); + }; + + exports['test .toString()'] = function (assert, util) { + assert.equal((new SourceNode(null, null, null, + ['function foo() {', + new SourceNode(null, null, null, 'return 10;'), + '}'])).toString(), + 'function foo() {return 10;}'); + }; + + exports['test .join()'] = function (assert, util) { + assert.equal((new SourceNode(null, null, null, + ['a', 'b', 'c', 'd'])).join(', ').toString(), + 'a, b, c, d'); + }; + + exports['test .walk()'] = function (assert, util) { + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', new SourceNode(1, 0, 'a.js', ['someCall()']), ';\n', + ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';\n', + '}());']); + var expected = [ + { str: '(function () {\n', source: null, line: null, column: null }, + { str: ' ', source: null, line: null, column: null }, + { str: 'someCall()', source: 'a.js', line: 1, column: 0 }, + { str: ';\n', source: null, line: null, column: null }, + { str: ' ', source: null, line: null, column: null }, + { str: 'if (foo) bar()', source: 'b.js', line: 2, column: 0 }, + { str: ';\n', source: null, line: null, column: null }, + { str: '}());', source: null, line: null, column: null }, + ]; + var i = 0; + node.walk(function (chunk, loc) { + assert.equal(expected[i].str, chunk); + assert.equal(expected[i].source, loc.source); + assert.equal(expected[i].line, loc.line); + assert.equal(expected[i].column, loc.column); + i++; + }); + }; + + exports['test .replaceRight'] = function (assert, util) { + var node; + + // Not nested + node = new SourceNode(null, null, null, 'hello world'); + node.replaceRight(/world/, 'universe'); + assert.equal(node.toString(), 'hello universe'); + + // Nested + node = new SourceNode(null, null, null, + [new SourceNode(null, null, null, 'hey sexy mama, '), + new SourceNode(null, null, null, 'want to kill all humans?')]); + node.replaceRight(/kill all humans/, 'watch Futurama'); + assert.equal(node.toString(), 'hey sexy mama, want to watch Futurama?'); + }; + + exports['test .toStringWithSourceMap()'] = forEachNewline(function (assert, util, nl) { + var node = new SourceNode(null, null, null, + ['(function () {' + nl, + ' ', + new SourceNode(1, 0, 'a.js', 'someCall', 'originalCall'), + new SourceNode(1, 8, 'a.js', '()'), + ';' + nl, + ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';' + nl, + '}());']); + var result = node.toStringWithSourceMap({ + file: 'foo.js' + }); + + assert.equal(result.code, [ + '(function () {', + ' someCall();', + ' if (foo) bar();', + '}());' + ].join(nl)); + + var map = result.map; + var mapWithoutOptions = node.toStringWithSourceMap().map; + + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + assert.ok(mapWithoutOptions instanceof SourceMapGenerator, 'mapWithoutOptions instanceof SourceMapGenerator'); + assert.ok(!('file' in mapWithoutOptions)); + mapWithoutOptions._file = 'foo.js'; + util.assertEqualMaps(assert, map.toJSON(), mapWithoutOptions.toJSON()); + + map = new SourceMapConsumer(map.toString()); + + var actual; + + actual = map.originalPositionFor({ + line: 1, + column: 4 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + + actual = map.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(actual.source, 'a.js'); + assert.equal(actual.line, 1); + assert.equal(actual.column, 0); + assert.equal(actual.name, 'originalCall'); + + actual = map.originalPositionFor({ + line: 3, + column: 2 + }); + assert.equal(actual.source, 'b.js'); + assert.equal(actual.line, 2); + assert.equal(actual.column, 0); + + actual = map.originalPositionFor({ + line: 3, + column: 16 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + + actual = map.originalPositionFor({ + line: 4, + column: 2 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + }); + + exports['test .fromStringWithSourceMap()'] = forEachNewline(function (assert, util, nl) { + var testCode = util.testGeneratedCode.replace(/\n/g, nl); + var node = SourceNode.fromStringWithSourceMap( + testCode, + new SourceMapConsumer(util.testMap)); + + var result = node.toStringWithSourceMap({ + file: 'min.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, testCode); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + assert.equal(map.version, util.testMap.version); + assert.equal(map.file, util.testMap.file); + assert.equal(map.mappings, util.testMap.mappings); + }); + + exports['test .fromStringWithSourceMap() empty map'] = forEachNewline(function (assert, util, nl) { + var node = SourceNode.fromStringWithSourceMap( + util.testGeneratedCode.replace(/\n/g, nl), + new SourceMapConsumer(util.emptyMap)); + var result = node.toStringWithSourceMap({ + file: 'min.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, util.testGeneratedCode.replace(/\n/g, nl)); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + assert.equal(map.version, util.emptyMap.version); + assert.equal(map.file, util.emptyMap.file); + assert.equal(map.mappings.length, util.emptyMap.mappings.length); + assert.equal(map.mappings, util.emptyMap.mappings); + }); + + exports['test .fromStringWithSourceMap() complex version'] = forEachNewline(function (assert, util, nl) { + var input = new SourceNode(null, null, null, [ + "(function() {" + nl, + " var Test = {};" + nl, + " ", new SourceNode(1, 0, "a.js", "Test.A = { value: 1234 };" + nl), + " ", new SourceNode(2, 0, "a.js", "Test.A.x = 'xyz';"), nl, + "}());" + nl, + "/* Generated Source */"]); + input = input.toStringWithSourceMap({ + file: 'foo.js' + }); + + var node = SourceNode.fromStringWithSourceMap( + input.code, + new SourceMapConsumer(input.map.toString())); + + var result = node.toStringWithSourceMap({ + file: 'foo.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, input.code); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + var inputMap = input.map.toJSON(); + util.assertEqualMaps(assert, map, inputMap); + }); + + exports['test .fromStringWithSourceMap() third argument'] = function (assert, util) { + // Assume the following directory structure: + // + // http://foo.org/ + // bar.coffee + // app/ + // coffee/ + // foo.coffee + // coffeeBundle.js # Made from {foo,bar,baz}.coffee + // maps/ + // coffeeBundle.js.map + // js/ + // foo.js + // public/ + // app.js # Made from {foo,coffeeBundle}.js + // app.js.map + // + // http://www.example.com/ + // baz.coffee + + var coffeeBundle = new SourceNode(1, 0, 'foo.coffee', 'foo(coffee);\n'); + coffeeBundle.setSourceContent('foo.coffee', 'foo coffee'); + coffeeBundle.add(new SourceNode(2, 0, '/bar.coffee', 'bar(coffee);\n')); + coffeeBundle.add(new SourceNode(3, 0, 'http://www.example.com/baz.coffee', 'baz(coffee);')); + coffeeBundle = coffeeBundle.toStringWithSourceMap({ + file: 'foo.js', + sourceRoot: '..' + }); + + var foo = new SourceNode(1, 0, 'foo.js', 'foo(js);'); + + var test = function(relativePath, expectedSources) { + var app = new SourceNode(); + app.add(SourceNode.fromStringWithSourceMap( + coffeeBundle.code, + new SourceMapConsumer(coffeeBundle.map.toString()), + relativePath)); + app.add(foo); + var i = 0; + app.walk(function (chunk, loc) { + assert.equal(loc.source, expectedSources[i]); + i++; + }); + app.walkSourceContents(function (sourceFile, sourceContent) { + assert.equal(sourceFile, expectedSources[0]); + assert.equal(sourceContent, 'foo coffee'); + }) + }; + + test('../coffee/maps', [ + '../coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee', + 'foo.js' + ]); + + // If the third parameter is omitted or set to the current working + // directory we get incorrect source paths: + + test(undefined, [ + '../foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee', + 'foo.js' + ]); + + test('', [ + '../foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee', + 'foo.js' + ]); + + test('.', [ + '../foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee', + 'foo.js' + ]); + + test('./', [ + '../foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee', + 'foo.js' + ]); + }; + + exports['test .toStringWithSourceMap() merging duplicate mappings'] = forEachNewline(function (assert, util, nl) { + var input = new SourceNode(null, null, null, [ + new SourceNode(1, 0, "a.js", "(function"), + new SourceNode(1, 0, "a.js", "() {" + nl), + " ", + new SourceNode(1, 0, "a.js", "var Test = "), + new SourceNode(1, 0, "b.js", "{};" + nl), + new SourceNode(2, 0, "b.js", "Test"), + new SourceNode(2, 0, "b.js", ".A", "A"), + new SourceNode(2, 20, "b.js", " = { value: ", "A"), + "1234", + new SourceNode(2, 40, "b.js", " };" + nl, "A"), + "}());" + nl, + "/* Generated Source */" + ]); + input = input.toStringWithSourceMap({ + file: 'foo.js' + }); + + assert.equal(input.code, [ + "(function() {", + " var Test = {};", + "Test.A = { value: 1234 };", + "}());", + "/* Generated Source */" + ].join(nl)) + + var correctMap = new SourceMapGenerator({ + file: 'foo.js' + }); + correctMap.addMapping({ + generated: { line: 1, column: 0 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + // Here is no need for a empty mapping, + // because mappings ends at eol + correctMap.addMapping({ + generated: { line: 2, column: 2 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 2, column: 13 }, + source: 'b.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 0 }, + source: 'b.js', + original: { line: 2, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 4 }, + source: 'b.js', + name: 'A', + original: { line: 2, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 6 }, + source: 'b.js', + name: 'A', + original: { line: 2, column: 20 } + }); + // This empty mapping is required, + // because there is a hole in the middle of the line + correctMap.addMapping({ + generated: { line: 3, column: 18 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 22 }, + source: 'b.js', + name: 'A', + original: { line: 2, column: 40 } + }); + // Here is no need for a empty mapping, + // because mappings ends at eol + + var inputMap = input.map.toJSON(); + correctMap = correctMap.toJSON(); + util.assertEqualMaps(assert, inputMap, correctMap); + }); + + exports['test .toStringWithSourceMap() multi-line SourceNodes'] = forEachNewline(function (assert, util, nl) { + var input = new SourceNode(null, null, null, [ + new SourceNode(1, 0, "a.js", "(function() {" + nl + "var nextLine = 1;" + nl + "anotherLine();" + nl), + new SourceNode(2, 2, "b.js", "Test.call(this, 123);" + nl), + new SourceNode(2, 2, "b.js", "this['stuff'] = 'v';" + nl), + new SourceNode(2, 2, "b.js", "anotherLine();" + nl), + "/*" + nl + "Generated" + nl + "Source" + nl + "*/" + nl, + new SourceNode(3, 4, "c.js", "anotherLine();" + nl), + "/*" + nl + "Generated" + nl + "Source" + nl + "*/" + ]); + input = input.toStringWithSourceMap({ + file: 'foo.js' + }); + + assert.equal(input.code, [ + "(function() {", + "var nextLine = 1;", + "anotherLine();", + "Test.call(this, 123);", + "this['stuff'] = 'v';", + "anotherLine();", + "/*", + "Generated", + "Source", + "*/", + "anotherLine();", + "/*", + "Generated", + "Source", + "*/" + ].join(nl)); + + var correctMap = new SourceMapGenerator({ + file: 'foo.js' + }); + correctMap.addMapping({ + generated: { line: 1, column: 0 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 2, column: 0 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 0 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 4, column: 0 }, + source: 'b.js', + original: { line: 2, column: 2 } + }); + correctMap.addMapping({ + generated: { line: 5, column: 0 }, + source: 'b.js', + original: { line: 2, column: 2 } + }); + correctMap.addMapping({ + generated: { line: 6, column: 0 }, + source: 'b.js', + original: { line: 2, column: 2 } + }); + correctMap.addMapping({ + generated: { line: 11, column: 0 }, + source: 'c.js', + original: { line: 3, column: 4 } + }); + + var inputMap = input.map.toJSON(); + correctMap = correctMap.toJSON(); + util.assertEqualMaps(assert, inputMap, correctMap); + }); + + exports['test .toStringWithSourceMap() with empty string'] = function (assert, util) { + var node = new SourceNode(1, 0, 'empty.js', ''); + var result = node.toStringWithSourceMap(); + assert.equal(result.code, ''); + }; + + exports['test .toStringWithSourceMap() with consecutive newlines'] = forEachNewline(function (assert, util, nl) { + var input = new SourceNode(null, null, null, [ + "/***/" + nl + nl, + new SourceNode(1, 0, "a.js", "'use strict';" + nl), + new SourceNode(2, 0, "a.js", "a();"), + ]); + input = input.toStringWithSourceMap({ + file: 'foo.js' + }); + + assert.equal(input.code, [ + "/***/", + "", + "'use strict';", + "a();", + ].join(nl)); + + var correctMap = new SourceMapGenerator({ + file: 'foo.js' + }); + correctMap.addMapping({ + generated: { line: 3, column: 0 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 4, column: 0 }, + source: 'a.js', + original: { line: 2, column: 0 } + }); + + var inputMap = input.map.toJSON(); + correctMap = correctMap.toJSON(); + util.assertEqualMaps(assert, inputMap, correctMap); + }); + + exports['test setSourceContent with toStringWithSourceMap'] = function (assert, util) { + var aNode = new SourceNode(1, 1, 'a.js', 'a'); + aNode.setSourceContent('a.js', 'someContent'); + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', aNode, + ' ', new SourceNode(1, 1, 'b.js', 'b'), + '}());']); + node.setSourceContent('b.js', 'otherContent'); + var map = node.toStringWithSourceMap({ + file: 'foo.js' + }).map; + + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = new SourceMapConsumer(map.toString()); + + assert.equal(map.sources.length, 2); + assert.equal(map.sources[0], 'a.js'); + assert.equal(map.sources[1], 'b.js'); + assert.equal(map.sourcesContent.length, 2); + assert.equal(map.sourcesContent[0], 'someContent'); + assert.equal(map.sourcesContent[1], 'otherContent'); + }; + + exports['test walkSourceContents'] = function (assert, util) { + var aNode = new SourceNode(1, 1, 'a.js', 'a'); + aNode.setSourceContent('a.js', 'someContent'); + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', aNode, + ' ', new SourceNode(1, 1, 'b.js', 'b'), + '}());']); + node.setSourceContent('b.js', 'otherContent'); + var results = []; + node.walkSourceContents(function (sourceFile, sourceContent) { + results.push([sourceFile, sourceContent]); + }); + assert.equal(results.length, 2); + assert.equal(results[0][0], 'a.js'); + assert.equal(results[0][1], 'someContent'); + assert.equal(results[1][0], 'b.js'); + assert.equal(results[1][1], 'otherContent'); + }; +}); diff --git a/homework7/project_express/node_modules/source-map/test/source-map/test-util.js b/homework7/project_express/node_modules/source-map/test/source-map/test-util.js new file mode 100644 index 0000000..997d1a2 --- /dev/null +++ b/homework7/project_express/node_modules/source-map/test/source-map/test-util.js @@ -0,0 +1,216 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2014 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var libUtil = require('../../lib/source-map/util'); + + exports['test urls'] = function (assert, util) { + var assertUrl = function (url) { + assert.equal(url, libUtil.urlGenerate(libUtil.urlParse(url))); + }; + assertUrl('http://'); + assertUrl('http://www.example.com'); + assertUrl('http://user:pass@www.example.com'); + assertUrl('http://www.example.com:80'); + assertUrl('http://www.example.com/'); + assertUrl('http://www.example.com/foo/bar'); + assertUrl('http://www.example.com/foo/bar/'); + assertUrl('http://user:pass@www.example.com:80/foo/bar/'); + + assertUrl('//'); + assertUrl('//www.example.com'); + assertUrl('file:///www.example.com'); + + assert.equal(libUtil.urlParse(''), null); + assert.equal(libUtil.urlParse('.'), null); + assert.equal(libUtil.urlParse('..'), null); + assert.equal(libUtil.urlParse('a'), null); + assert.equal(libUtil.urlParse('a/b'), null); + assert.equal(libUtil.urlParse('a//b'), null); + assert.equal(libUtil.urlParse('/a'), null); + assert.equal(libUtil.urlParse('data:foo,bar'), null); + }; + + exports['test normalize()'] = function (assert, util) { + assert.equal(libUtil.normalize('/..'), '/'); + assert.equal(libUtil.normalize('/../'), '/'); + assert.equal(libUtil.normalize('/../../../..'), '/'); + assert.equal(libUtil.normalize('/../../../../a/b/c'), '/a/b/c'); + assert.equal(libUtil.normalize('/a/b/c/../../../d/../../e'), '/e'); + + assert.equal(libUtil.normalize('..'), '..'); + assert.equal(libUtil.normalize('../'), '../'); + assert.equal(libUtil.normalize('../../a/'), '../../a/'); + assert.equal(libUtil.normalize('a/..'), '.'); + assert.equal(libUtil.normalize('a/../../..'), '../..'); + + assert.equal(libUtil.normalize('/.'), '/'); + assert.equal(libUtil.normalize('/./'), '/'); + assert.equal(libUtil.normalize('/./././.'), '/'); + assert.equal(libUtil.normalize('/././././a/b/c'), '/a/b/c'); + assert.equal(libUtil.normalize('/a/b/c/./././d/././e'), '/a/b/c/d/e'); + + assert.equal(libUtil.normalize(''), '.'); + assert.equal(libUtil.normalize('.'), '.'); + assert.equal(libUtil.normalize('./'), '.'); + assert.equal(libUtil.normalize('././a'), 'a'); + assert.equal(libUtil.normalize('a/./'), 'a/'); + assert.equal(libUtil.normalize('a/././.'), 'a'); + + assert.equal(libUtil.normalize('/a/b//c////d/////'), '/a/b/c/d/'); + assert.equal(libUtil.normalize('///a/b//c////d/////'), '///a/b/c/d/'); + assert.equal(libUtil.normalize('a/b//c////d'), 'a/b/c/d'); + + assert.equal(libUtil.normalize('.///.././../a/b//./..'), '../../a') + + assert.equal(libUtil.normalize('http://www.example.com'), 'http://www.example.com'); + assert.equal(libUtil.normalize('http://www.example.com/'), 'http://www.example.com/'); + assert.equal(libUtil.normalize('http://www.example.com/./..//a/b/c/.././d//'), 'http://www.example.com/a/b/d/'); + }; + + exports['test join()'] = function (assert, util) { + assert.equal(libUtil.join('a', 'b'), 'a/b'); + assert.equal(libUtil.join('a/', 'b'), 'a/b'); + assert.equal(libUtil.join('a//', 'b'), 'a/b'); + assert.equal(libUtil.join('a', 'b/'), 'a/b/'); + assert.equal(libUtil.join('a', 'b//'), 'a/b/'); + assert.equal(libUtil.join('a/', '/b'), '/b'); + assert.equal(libUtil.join('a//', '//b'), '//b'); + + assert.equal(libUtil.join('a', '..'), '.'); + assert.equal(libUtil.join('a', '../b'), 'b'); + assert.equal(libUtil.join('a/b', '../c'), 'a/c'); + + assert.equal(libUtil.join('a', '.'), 'a'); + assert.equal(libUtil.join('a', './b'), 'a/b'); + assert.equal(libUtil.join('a/b', './c'), 'a/b/c'); + + assert.equal(libUtil.join('a', 'http://www.example.com'), 'http://www.example.com'); + assert.equal(libUtil.join('a', 'data:foo,bar'), 'data:foo,bar'); + + + assert.equal(libUtil.join('', 'b'), 'b'); + assert.equal(libUtil.join('.', 'b'), 'b'); + assert.equal(libUtil.join('', 'b/'), 'b/'); + assert.equal(libUtil.join('.', 'b/'), 'b/'); + assert.equal(libUtil.join('', 'b//'), 'b/'); + assert.equal(libUtil.join('.', 'b//'), 'b/'); + + assert.equal(libUtil.join('', '..'), '..'); + assert.equal(libUtil.join('.', '..'), '..'); + assert.equal(libUtil.join('', '../b'), '../b'); + assert.equal(libUtil.join('.', '../b'), '../b'); + + assert.equal(libUtil.join('', '.'), '.'); + assert.equal(libUtil.join('.', '.'), '.'); + assert.equal(libUtil.join('', './b'), 'b'); + assert.equal(libUtil.join('.', './b'), 'b'); + + assert.equal(libUtil.join('', 'http://www.example.com'), 'http://www.example.com'); + assert.equal(libUtil.join('.', 'http://www.example.com'), 'http://www.example.com'); + assert.equal(libUtil.join('', 'data:foo,bar'), 'data:foo,bar'); + assert.equal(libUtil.join('.', 'data:foo,bar'), 'data:foo,bar'); + + + assert.equal(libUtil.join('..', 'b'), '../b'); + assert.equal(libUtil.join('..', 'b/'), '../b/'); + assert.equal(libUtil.join('..', 'b//'), '../b/'); + + assert.equal(libUtil.join('..', '..'), '../..'); + assert.equal(libUtil.join('..', '../b'), '../../b'); + + assert.equal(libUtil.join('..', '.'), '..'); + assert.equal(libUtil.join('..', './b'), '../b'); + + assert.equal(libUtil.join('..', 'http://www.example.com'), 'http://www.example.com'); + assert.equal(libUtil.join('..', 'data:foo,bar'), 'data:foo,bar'); + + + assert.equal(libUtil.join('a', ''), 'a'); + assert.equal(libUtil.join('a', '.'), 'a'); + assert.equal(libUtil.join('a/', ''), 'a'); + assert.equal(libUtil.join('a/', '.'), 'a'); + assert.equal(libUtil.join('a//', ''), 'a'); + assert.equal(libUtil.join('a//', '.'), 'a'); + assert.equal(libUtil.join('/a', ''), '/a'); + assert.equal(libUtil.join('/a', '.'), '/a'); + assert.equal(libUtil.join('', ''), '.'); + assert.equal(libUtil.join('.', ''), '.'); + assert.equal(libUtil.join('.', ''), '.'); + assert.equal(libUtil.join('.', '.'), '.'); + assert.equal(libUtil.join('..', ''), '..'); + assert.equal(libUtil.join('..', '.'), '..'); + assert.equal(libUtil.join('http://foo.org/a', ''), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org/a', '.'), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org/a/', ''), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org/a/', '.'), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org/a//', ''), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org/a//', '.'), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org', ''), 'http://foo.org/'); + assert.equal(libUtil.join('http://foo.org', '.'), 'http://foo.org/'); + assert.equal(libUtil.join('http://foo.org/', ''), 'http://foo.org/'); + assert.equal(libUtil.join('http://foo.org/', '.'), 'http://foo.org/'); + assert.equal(libUtil.join('http://foo.org//', ''), 'http://foo.org/'); + assert.equal(libUtil.join('http://foo.org//', '.'), 'http://foo.org/'); + assert.equal(libUtil.join('//www.example.com', ''), '//www.example.com/'); + assert.equal(libUtil.join('//www.example.com', '.'), '//www.example.com/'); + + + assert.equal(libUtil.join('http://foo.org/a', 'b'), 'http://foo.org/a/b'); + assert.equal(libUtil.join('http://foo.org/a/', 'b'), 'http://foo.org/a/b'); + assert.equal(libUtil.join('http://foo.org/a//', 'b'), 'http://foo.org/a/b'); + assert.equal(libUtil.join('http://foo.org/a', 'b/'), 'http://foo.org/a/b/'); + assert.equal(libUtil.join('http://foo.org/a', 'b//'), 'http://foo.org/a/b/'); + assert.equal(libUtil.join('http://foo.org/a/', '/b'), 'http://foo.org/b'); + assert.equal(libUtil.join('http://foo.org/a//', '//b'), 'http://b'); + + assert.equal(libUtil.join('http://foo.org/a', '..'), 'http://foo.org/'); + assert.equal(libUtil.join('http://foo.org/a', '../b'), 'http://foo.org/b'); + assert.equal(libUtil.join('http://foo.org/a/b', '../c'), 'http://foo.org/a/c'); + + assert.equal(libUtil.join('http://foo.org/a', '.'), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org/a', './b'), 'http://foo.org/a/b'); + assert.equal(libUtil.join('http://foo.org/a/b', './c'), 'http://foo.org/a/b/c'); + + assert.equal(libUtil.join('http://foo.org/a', 'http://www.example.com'), 'http://www.example.com'); + assert.equal(libUtil.join('http://foo.org/a', 'data:foo,bar'), 'data:foo,bar'); + + + assert.equal(libUtil.join('http://foo.org', 'a'), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org/', 'a'), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org//', 'a'), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org', '/a'), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org/', '/a'), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org//', '/a'), 'http://foo.org/a'); + + + assert.equal(libUtil.join('http://', 'www.example.com'), 'http://www.example.com'); + assert.equal(libUtil.join('file:///', 'www.example.com'), 'file:///www.example.com'); + assert.equal(libUtil.join('http://', 'ftp://example.com'), 'ftp://example.com'); + + assert.equal(libUtil.join('http://www.example.com', '//foo.org/bar'), 'http://foo.org/bar'); + assert.equal(libUtil.join('//www.example.com', '//foo.org/bar'), '//foo.org/bar'); + }; + + // TODO Issue #128: Define and test this function properly. + exports['test relative()'] = function (assert, util) { + assert.equal(libUtil.relative('/the/root', '/the/root/one.js'), 'one.js'); + assert.equal(libUtil.relative('/the/root', '/the/rootone.js'), '/the/rootone.js'); + + assert.equal(libUtil.relative('', '/the/root/one.js'), '/the/root/one.js'); + assert.equal(libUtil.relative('.', '/the/root/one.js'), '/the/root/one.js'); + assert.equal(libUtil.relative('', 'the/root/one.js'), 'the/root/one.js'); + assert.equal(libUtil.relative('.', 'the/root/one.js'), 'the/root/one.js'); + + assert.equal(libUtil.relative('/', '/the/root/one.js'), 'the/root/one.js'); + assert.equal(libUtil.relative('/', 'the/root/one.js'), 'the/root/one.js'); + }; + +}); diff --git a/homework7/project_express/node_modules/source-map/test/source-map/util.js b/homework7/project_express/node_modules/source-map/test/source-map/util.js new file mode 100644 index 0000000..56bbe2c --- /dev/null +++ b/homework7/project_express/node_modules/source-map/test/source-map/util.js @@ -0,0 +1,192 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('../../lib/source-map/util'); + + // This is a test mapping which maps functions from two different files + // (one.js and two.js) to a minified generated source. + // + // Here is one.js: + // + // ONE.foo = function (bar) { + // return baz(bar); + // }; + // + // Here is two.js: + // + // TWO.inc = function (n) { + // return n + 1; + // }; + // + // And here is the generated code (min.js): + // + // ONE.foo=function(a){return baz(a);}; + // TWO.inc=function(a){return a+1;}; + exports.testGeneratedCode = " ONE.foo=function(a){return baz(a);};\n"+ + " TWO.inc=function(a){return a+1;};"; + exports.testMap = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourceRoot: '/the/root', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + exports.testMapNoSourceRoot = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + exports.testMapEmptySourceRoot = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourceRoot: '', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + exports.testMapWithSourcesContent = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourcesContent: [ + ' ONE.foo = function (bar) {\n' + + ' return baz(bar);\n' + + ' };', + ' TWO.inc = function (n) {\n' + + ' return n + 1;\n' + + ' };' + ], + sourceRoot: '/the/root', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + exports.testMapRelativeSources = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['./one.js', './two.js'], + sourcesContent: [ + ' ONE.foo = function (bar) {\n' + + ' return baz(bar);\n' + + ' };', + ' TWO.inc = function (n) {\n' + + ' return n + 1;\n' + + ' };' + ], + sourceRoot: '/the/root', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + exports.emptyMap = { + version: 3, + file: 'min.js', + names: [], + sources: [], + mappings: '' + }; + + + function assertMapping(generatedLine, generatedColumn, originalSource, + originalLine, originalColumn, name, map, assert, + dontTestGenerated, dontTestOriginal) { + if (!dontTestOriginal) { + var origMapping = map.originalPositionFor({ + line: generatedLine, + column: generatedColumn + }); + assert.equal(origMapping.name, name, + 'Incorrect name, expected ' + JSON.stringify(name) + + ', got ' + JSON.stringify(origMapping.name)); + assert.equal(origMapping.line, originalLine, + 'Incorrect line, expected ' + JSON.stringify(originalLine) + + ', got ' + JSON.stringify(origMapping.line)); + assert.equal(origMapping.column, originalColumn, + 'Incorrect column, expected ' + JSON.stringify(originalColumn) + + ', got ' + JSON.stringify(origMapping.column)); + + var expectedSource; + + if (originalSource && map.sourceRoot && originalSource.indexOf(map.sourceRoot) === 0) { + expectedSource = originalSource; + } else if (originalSource) { + expectedSource = map.sourceRoot + ? util.join(map.sourceRoot, originalSource) + : originalSource; + } else { + expectedSource = null; + } + + assert.equal(origMapping.source, expectedSource, + 'Incorrect source, expected ' + JSON.stringify(expectedSource) + + ', got ' + JSON.stringify(origMapping.source)); + } + + if (!dontTestGenerated) { + var genMapping = map.generatedPositionFor({ + source: originalSource, + line: originalLine, + column: originalColumn + }); + assert.equal(genMapping.line, generatedLine, + 'Incorrect line, expected ' + JSON.stringify(generatedLine) + + ', got ' + JSON.stringify(genMapping.line)); + assert.equal(genMapping.column, generatedColumn, + 'Incorrect column, expected ' + JSON.stringify(generatedColumn) + + ', got ' + JSON.stringify(genMapping.column)); + } + } + exports.assertMapping = assertMapping; + + function assertEqualMaps(assert, actualMap, expectedMap) { + assert.equal(actualMap.version, expectedMap.version, "version mismatch"); + assert.equal(actualMap.file, expectedMap.file, "file mismatch"); + assert.equal(actualMap.names.length, + expectedMap.names.length, + "names length mismatch: " + + actualMap.names.join(", ") + " != " + expectedMap.names.join(", ")); + for (var i = 0; i < actualMap.names.length; i++) { + assert.equal(actualMap.names[i], + expectedMap.names[i], + "names[" + i + "] mismatch: " + + actualMap.names.join(", ") + " != " + expectedMap.names.join(", ")); + } + assert.equal(actualMap.sources.length, + expectedMap.sources.length, + "sources length mismatch: " + + actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", ")); + for (var i = 0; i < actualMap.sources.length; i++) { + assert.equal(actualMap.sources[i], + expectedMap.sources[i], + "sources[" + i + "] length mismatch: " + + actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", ")); + } + assert.equal(actualMap.sourceRoot, + expectedMap.sourceRoot, + "sourceRoot mismatch: " + + actualMap.sourceRoot + " != " + expectedMap.sourceRoot); + assert.equal(actualMap.mappings, expectedMap.mappings, + "mappings mismatch:\nActual: " + actualMap.mappings + "\nExpected: " + expectedMap.mappings); + if (actualMap.sourcesContent) { + assert.equal(actualMap.sourcesContent.length, + expectedMap.sourcesContent.length, + "sourcesContent length mismatch"); + for (var i = 0; i < actualMap.sourcesContent.length; i++) { + assert.equal(actualMap.sourcesContent[i], + expectedMap.sourcesContent[i], + "sourcesContent[" + i + "] mismatch"); + } + } + } + exports.assertEqualMaps = assertEqualMaps; + +}); diff --git a/homework7/project_express/node_modules/statuses/HISTORY.md b/homework7/project_express/node_modules/statuses/HISTORY.md new file mode 100644 index 0000000..a1977b2 --- /dev/null +++ b/homework7/project_express/node_modules/statuses/HISTORY.md @@ -0,0 +1,65 @@ +1.5.0 / 2018-03-27 +================== + + * Add `103 Early Hints` + +1.4.0 / 2017-10-20 +================== + + * Add `STATUS_CODES` export + +1.3.1 / 2016-11-11 +================== + + * Fix return type in JSDoc + +1.3.0 / 2016-05-17 +================== + + * Add `421 Misdirected Request` + * perf: enable strict mode + +1.2.1 / 2015-02-01 +================== + + * Fix message for status 451 + - `451 Unavailable For Legal Reasons` + +1.2.0 / 2014-09-28 +================== + + * Add `208 Already Repored` + * Add `226 IM Used` + * Add `306 (Unused)` + * Add `415 Unable For Legal Reasons` + * Add `508 Loop Detected` + +1.1.1 / 2014-09-24 +================== + + * Add missing 308 to `codes.json` + +1.1.0 / 2014-09-21 +================== + + * Add `codes.json` for universal support + +1.0.4 / 2014-08-20 +================== + + * Package cleanup + +1.0.3 / 2014-06-08 +================== + + * Add 308 to `.redirect` category + +1.0.2 / 2014-03-13 +================== + + * Add `.retry` category + +1.0.1 / 2014-03-12 +================== + + * Initial release diff --git a/homework7/project_express/node_modules/statuses/LICENSE b/homework7/project_express/node_modules/statuses/LICENSE new file mode 100644 index 0000000..28a3161 --- /dev/null +++ b/homework7/project_express/node_modules/statuses/LICENSE @@ -0,0 +1,23 @@ + +The MIT License (MIT) + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2016 Douglas Christopher Wilson + +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/homework7/project_express/node_modules/statuses/README.md b/homework7/project_express/node_modules/statuses/README.md new file mode 100644 index 0000000..0fe5720 --- /dev/null +++ b/homework7/project_express/node_modules/statuses/README.md @@ -0,0 +1,127 @@ +# Statuses + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +HTTP status utility for node. + +This module provides a list of status codes and messages sourced from +a few different projects: + + * The [IANA Status Code Registry](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml) + * The [Node.js project](https://nodejs.org/) + * The [NGINX project](https://www.nginx.com/) + * The [Apache HTTP Server project](https://httpd.apache.org/) + +## Installation + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```sh +$ npm install statuses +``` + +## API + + + +```js +var status = require('statuses') +``` + +### var code = status(Integer || String) + +If `Integer` or `String` is a valid HTTP code or status message, then the +appropriate `code` will be returned. Otherwise, an error will be thrown. + + + +```js +status(403) // => 403 +status('403') // => 403 +status('forbidden') // => 403 +status('Forbidden') // => 403 +status(306) // throws, as it's not supported by node.js +``` + +### status.STATUS_CODES + +Returns an object which maps status codes to status messages, in +the same format as the +[Node.js http module](https://nodejs.org/dist/latest/docs/api/http.html#http_http_status_codes). + +### status.codes + +Returns an array of all the status codes as `Integer`s. + +### var msg = status[code] + +Map of `code` to `status message`. `undefined` for invalid `code`s. + + + +```js +status[404] // => 'Not Found' +``` + +### var code = status[msg] + +Map of `status message` to `code`. `msg` can either be title-cased or +lower-cased. `undefined` for invalid `status message`s. + + + +```js +status['not found'] // => 404 +status['Not Found'] // => 404 +``` + +### status.redirect[code] + +Returns `true` if a status code is a valid redirect status. + + + +```js +status.redirect[200] // => undefined +status.redirect[301] // => true +``` + +### status.empty[code] + +Returns `true` if a status code expects an empty body. + + + +```js +status.empty[200] // => undefined +status.empty[204] // => true +status.empty[304] // => true +``` + +### status.retry[code] + +Returns `true` if you should retry the rest. + + + +```js +status.retry[501] // => undefined +status.retry[503] // => true +``` + +[npm-image]: https://img.shields.io/npm/v/statuses.svg +[npm-url]: https://npmjs.org/package/statuses +[node-version-image]: https://img.shields.io/node/v/statuses.svg +[node-version-url]: https://nodejs.org/en/download +[travis-image]: https://img.shields.io/travis/jshttp/statuses.svg +[travis-url]: https://travis-ci.org/jshttp/statuses +[coveralls-image]: https://img.shields.io/coveralls/jshttp/statuses.svg +[coveralls-url]: https://coveralls.io/r/jshttp/statuses?branch=master +[downloads-image]: https://img.shields.io/npm/dm/statuses.svg +[downloads-url]: https://npmjs.org/package/statuses diff --git a/homework7/project_express/node_modules/statuses/codes.json b/homework7/project_express/node_modules/statuses/codes.json new file mode 100644 index 0000000..a09283a --- /dev/null +++ b/homework7/project_express/node_modules/statuses/codes.json @@ -0,0 +1,66 @@ +{ + "100": "Continue", + "101": "Switching Protocols", + "102": "Processing", + "103": "Early Hints", + "200": "OK", + "201": "Created", + "202": "Accepted", + "203": "Non-Authoritative Information", + "204": "No Content", + "205": "Reset Content", + "206": "Partial Content", + "207": "Multi-Status", + "208": "Already Reported", + "226": "IM Used", + "300": "Multiple Choices", + "301": "Moved Permanently", + "302": "Found", + "303": "See Other", + "304": "Not Modified", + "305": "Use Proxy", + "306": "(Unused)", + "307": "Temporary Redirect", + "308": "Permanent Redirect", + "400": "Bad Request", + "401": "Unauthorized", + "402": "Payment Required", + "403": "Forbidden", + "404": "Not Found", + "405": "Method Not Allowed", + "406": "Not Acceptable", + "407": "Proxy Authentication Required", + "408": "Request Timeout", + "409": "Conflict", + "410": "Gone", + "411": "Length Required", + "412": "Precondition Failed", + "413": "Payload Too Large", + "414": "URI Too Long", + "415": "Unsupported Media Type", + "416": "Range Not Satisfiable", + "417": "Expectation Failed", + "418": "I'm a teapot", + "421": "Misdirected Request", + "422": "Unprocessable Entity", + "423": "Locked", + "424": "Failed Dependency", + "425": "Unordered Collection", + "426": "Upgrade Required", + "428": "Precondition Required", + "429": "Too Many Requests", + "431": "Request Header Fields Too Large", + "451": "Unavailable For Legal Reasons", + "500": "Internal Server Error", + "501": "Not Implemented", + "502": "Bad Gateway", + "503": "Service Unavailable", + "504": "Gateway Timeout", + "505": "HTTP Version Not Supported", + "506": "Variant Also Negotiates", + "507": "Insufficient Storage", + "508": "Loop Detected", + "509": "Bandwidth Limit Exceeded", + "510": "Not Extended", + "511": "Network Authentication Required" +} diff --git a/homework7/project_express/node_modules/statuses/index.js b/homework7/project_express/node_modules/statuses/index.js new file mode 100644 index 0000000..4df469a --- /dev/null +++ b/homework7/project_express/node_modules/statuses/index.js @@ -0,0 +1,113 @@ +/*! + * statuses + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2016 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var codes = require('./codes.json') + +/** + * Module exports. + * @public + */ + +module.exports = status + +// status code to message map +status.STATUS_CODES = codes + +// array of status codes +status.codes = populateStatusesMap(status, codes) + +// status codes for redirects +status.redirect = { + 300: true, + 301: true, + 302: true, + 303: true, + 305: true, + 307: true, + 308: true +} + +// status codes for empty bodies +status.empty = { + 204: true, + 205: true, + 304: true +} + +// status codes for when you should retry the request +status.retry = { + 502: true, + 503: true, + 504: true +} + +/** + * Populate the statuses map for given codes. + * @private + */ + +function populateStatusesMap (statuses, codes) { + var arr = [] + + Object.keys(codes).forEach(function forEachCode (code) { + var message = codes[code] + var status = Number(code) + + // Populate properties + statuses[status] = message + statuses[message] = status + statuses[message.toLowerCase()] = status + + // Add to array + arr.push(status) + }) + + return arr +} + +/** + * Get the status code. + * + * Given a number, this will throw if it is not a known status + * code, otherwise the code will be returned. Given a string, + * the string will be parsed for a number and return the code + * if valid, otherwise will lookup the code assuming this is + * the status message. + * + * @param {string|number} code + * @returns {number} + * @public + */ + +function status (code) { + if (typeof code === 'number') { + if (!status[code]) throw new Error('invalid status code: ' + code) + return code + } + + if (typeof code !== 'string') { + throw new TypeError('code must be a number or string') + } + + // '403' + var n = parseInt(code, 10) + if (!isNaN(n)) { + if (!status[n]) throw new Error('invalid status code: ' + n) + return n + } + + n = status[code.toLowerCase()] + if (!n) throw new Error('invalid status message: "' + code + '"') + return n +} diff --git a/homework7/project_express/node_modules/statuses/package.json b/homework7/project_express/node_modules/statuses/package.json new file mode 100644 index 0000000..6919edc --- /dev/null +++ b/homework7/project_express/node_modules/statuses/package.json @@ -0,0 +1,90 @@ +{ + "_from": "statuses@~1.5.0", + "_id": "statuses@1.5.0", + "_inBundle": false, + "_integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "_location": "/statuses", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "statuses@~1.5.0", + "name": "statuses", + "escapedName": "statuses", + "rawSpec": "~1.5.0", + "saveSpec": null, + "fetchSpec": "~1.5.0" + }, + "_requiredBy": [ + "/express", + "/finalhandler", + "/http-errors", + "/send" + ], + "_resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "_shasum": "161c7dac177659fd9811f43771fa99381478628c", + "_spec": "statuses@~1.5.0", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\express", + "bugs": { + "url": "https://github.com/jshttp/statuses/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "Jonathan Ong", + "email": "me@jongleberry.com", + "url": "http://jongleberry.com" + } + ], + "deprecated": false, + "description": "HTTP status utility", + "devDependencies": { + "csv-parse": "1.2.4", + "eslint": "4.19.1", + "eslint-config-standard": "11.0.0", + "eslint-plugin-import": "2.9.0", + "eslint-plugin-markdown": "1.0.0-beta.6", + "eslint-plugin-node": "6.0.1", + "eslint-plugin-promise": "3.7.0", + "eslint-plugin-standard": "3.0.1", + "istanbul": "0.4.5", + "mocha": "1.21.5", + "raw-body": "2.3.2", + "stream-to-array": "2.3.0" + }, + "engines": { + "node": ">= 0.6" + }, + "files": [ + "HISTORY.md", + "index.js", + "codes.json", + "LICENSE" + ], + "homepage": "https://github.com/jshttp/statuses#readme", + "keywords": [ + "http", + "status", + "code" + ], + "license": "MIT", + "name": "statuses", + "repository": { + "type": "git", + "url": "git+https://github.com/jshttp/statuses.git" + }, + "scripts": { + "build": "node scripts/build.js", + "fetch": "node scripts/fetch-apache.js && node scripts/fetch-iana.js && node scripts/fetch-nginx.js && node scripts/fetch-node.js", + "lint": "eslint --plugin markdown --ext js,md .", + "test": "mocha --reporter spec --check-leaks --bail test/", + "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "update": "npm run fetch && npm run build" + }, + "version": "1.5.0" +} diff --git a/homework7/project_express/node_modules/std/Animation.js b/homework7/project_express/node_modules/std/Animation.js new file mode 100644 index 0000000..93ef41a --- /dev/null +++ b/homework7/project_express/node_modules/std/Animation.js @@ -0,0 +1,57 @@ +var Class = require('./Class'), + extend = require('./extend') + +module.exports = Class(function() { + + var defaults = { + duration:250, + interval:40, + tween:function linearTween(delta) { return delta } + } + + this.init = function(animationFunction, opts) { + this._animationFunction = animationFunction + opts = extend(opts, defaults) + this._duration = opts.duration + this._interval = opts.interval + this._tween = opts.tween + this._onDone = opts.onDone + } + + this.start = function(reverse) { + this._playing = true + this._startT = new Date().getTime() + this._reverse = reverse + this._onInterval() + this._intervalID = setInterval(bind(this, this._onInterval), this._interval) + } + + this.stop = function() { + this._playing = false + clearInterval(this._intervalID) + } + + this.isGoing = function() { return this._playing } + + this._onInterval = function() { + var deltaT = new Date().getTime() - this._startT, + duration = this._duration + if (deltaT >= duration) { + this.stop() + this._animationFunction(this._tween(this._reverse ? 0 : 1)) + if (this._onDone) { this._onDone() } + return + } + var delta = deltaT / duration + if (this._reverse) { delta = 1 - delta } + this._animationFunction(this._tween(delta)) + } +}) + +// Easing equation function for elastic tween: http://code.google.com/p/kawanet/source/browse/lang/as3/KTween/trunk/src/net/kawa/tween/easing/Elastic.as +module.exports.elasticEaseOut = function(delta) { + var x = 1 - delta, + elasticity = 0.25 + value = 1 - Math.pow(x, 4) + x * x * Math.sin(delta * delta * Math.PI * elasticity) + return value +} diff --git a/homework7/project_express/node_modules/std/Changelog b/homework7/project_express/node_modules/std/Changelog new file mode 100644 index 0000000..bbc9f99 --- /dev/null +++ b/homework7/project_express/node_modules/std/Changelog @@ -0,0 +1,179 @@ +v0.1.39 ++ Stop using Changelog. See `git log` + +v0.1.38 ++ implement parallel ++ implement asyncEach ++ implement asyncMap ++ implement nextTick + +v0.1.37 ++ implemented waitFor ++ implemented rand ++ other improvements + +v0.1.35 ++ Better touch detection + +v0.1.34 ++ Better Promises ++ Small fix in time.js + +v0.1.33 ++ extend now uses copy instead of create + +v0.1.32 ++ implement blockFunction.addBlock + +v0.1.31 ++ Beefed up proto.js + +v0.1.30 ++ Improved throttle + +v0.1.29 ++ import base64 ++ Many other changes... + +v0.1.28 ++ implement repeat ++ implement deepEqual ++ implement proto ++ improved client detection in client.js + +v0.1.27 ++ make client a proper class, and add the beginnins to OS user-agent parsing ++ improve url.js - enable getting and setting the hash/query params ++ implement merge ++ Add client.isMobile + +v0.1.26 ++ add client.name and client.is[IPhone, IPad, IPod] + +v0.1.25 ++ fix cookie.remove ++ implement create ++ implement arrayToObject ++ implement defineGetter + +v0.1.24 ++ implement cookie ++ move dom/* into ui library ui.js ++ implement Animation ++ add json, from JSON2 https://github.com/douglascrockford/JSON-js ++ xhr improvements ++ implement url ++ implement trim ++ implement isArguments ++ use native isArray if available ++ add @kaleb to contributors + +v0.1.23 ++ rename class _init to init ++ add support for mixins ++ implement Promise ++ implement invokeWith ++ implement recall ++ implement Publisher mixin ++ implement dom ++ implement client ++ implement popup + +v0.1.22 ++ implement ui/Component#_off ++ implement ui/Component#_makeDraggable - publishes 'drag' and 'drop' events, both with a data object describing the drag ++ implement throttle ++ change implementation of delay to actually delay, rather than throttle ++ Improved ui/Component event normalization (notably mousewheel) ++ Implement browser ++ Implement math.round + +v0.1.21 ++ start implementing std/time ++ implement copy - shallow object/array copying, with a flag for deep copying ++ implement keys ++ implement flatten ++ clean up xhr code ++ fix xhr bug where callback would not get called for empty responses + + +v0.1.20 ++ ui/Component API cleanup ++ implement ui/Component display, hide and show ++ fix ui/Component addClass/hasClass/removeClass/toggleClass ++ better xhr error checking and xhr object cleanup ++ implement invoke ++ rename pick to filter. deprecate pick, but keep it around for now ++ give Logger alert email functionality ++ Fix delay ++ fix ui/Input defaultValue class name mixup + +v0.1.19 ++ Add xhr option not to encode values ++ Rename ui/Component#_dom to dom ++ Fix xhr get requests without a ? in the URL ++ fix context bug in delay + +v0.1.18 ++ implement delay ++ implement Logger ++ implement ui/Component ++ implement ui/Select ++ implement ui/Input + +v0.1.16 ++ Allow for passing in a context to each and map + +v0.1.15 ++ JSON.stringify xhr query parameters ++ Use JSON.parse rather than eval to parse responses. Much safer :) + +v0.1.14 ++ implement xhr ++ implement Publisher + +v0.1.12 ++ enable e.g. require('std/curry') + +v0.1.11 ++ add MIT license ++ implement curry + +v0.1.10 ++ implement slice + +v0.1.9 ++ implement strip, for stripping off the whitespace of strings ++ implement pick, for picking items out of an array + +v0.1.8 ++ fix stupid mistake + +v0.1.7 ++ import pack, unpack, crc32 and utf8_encode functions from phpjs ++ move function files into lib + +v0.1.6 ++ extend now returns the first argument, or a new object if first argument is null + +v0.1.5 ++ fix bind when second argument is a string + +v0.1.4 ++ implement extend + +v0.1.3 ++ call class initializer functions _init rather than initialize + +v0.1.2 ++ implement Class + +v0.1.1 ++ implement isArray ++ implement each ++ implement map + +v0.1.0 ++ Implement bind ++ Publish on npm as std + diff --git a/homework7/project_express/node_modules/std/Class.js b/homework7/project_express/node_modules/std/Class.js new file mode 100644 index 0000000..b316644 --- /dev/null +++ b/homework7/project_express/node_modules/std/Class.js @@ -0,0 +1,80 @@ +/* Example usage: + + var UIComponent = Class(function() { + this.init = function() { ... } + this.create = function() { ... this.createDOM() ... } + }) + + var PublisherMixin = { + init: function(){ ... }, + publish_: function() { ... } + } + + var Button = Class(UIComponent, PublisherMixin, function(supr) { + this.init = function(opts) { + // call UIComponents init method, with the passed in arguments + supr(this, 'init', arguments) // or, UIComponent.constructor.prototype.init.apply(this, arguments) + this.color_ = opts && opts.color + } + + // createDOM overwrites abstract method from parent class UIComponent + this.createDOM = function() { + this.getElement().onclick = bind(this, function(e) { + // this.publish_ is a method added to Button by the Publisher mixin + this.publish_('Click', e) + }) + } + }) + +*/ +module.exports = function Class(/* optParent, optMixin1, optMixin2, ..., proto */) { + var args = arguments, + numOptArgs = args.length - 1, + mixins = [] + + // the prototype function is always the last argument + var proto = args[numOptArgs] + + // if there's more than one argument, then the first argument is the parent class + if (numOptArgs) { + var parent = args[0] + if (parent) { proto.prototype = parent.prototype } + } + + for (var i=1; i < numOptArgs; i++) { mixins.push(arguments[i]) } + + // cls is the actual class function. Classes may implement this.init = function(){ ... }, + // which gets called upon instantiation + var cls = function() { + if(this.init) { this.init.apply(this, arguments) } + for (var i=0, mixin; mixin = mixins[i]; i++) { + if (mixin.init) { mixin.init.apply(this) } + } + } + + // the proto function gets called with the supr function as an argument. supr climbs the + // inheritence chain, looking for the named method + cls.prototype = new proto(function supr(context, method, args) { + var target = parent + while(target = target.prototype) { + if(target[method]) { + return target[method].apply(context, args || []) + } + } + throw new Error('supr: parent method ' + method + ' does not exist') + }) + + // add all mixins' properties to the class' prototype object + for (var i=0, mixin; mixin = mixins[i]; i++) { + for (var propertyName in mixin) { + if (!mixin.hasOwnProperty(propertyName) || propertyName == 'init') { continue } + if (cls.prototype.hasOwnProperty(propertyName)) { + throw new Error('Mixin property "'+propertyName+'" already exists on class') + } + cls.prototype[propertyName] = mixin[propertyName] + } + } + + cls.prototype.constructor = cls + return cls +} diff --git a/homework7/project_express/node_modules/std/LICENSE b/homework7/project_express/node_modules/std/LICENSE new file mode 100644 index 0000000..341bae5 --- /dev/null +++ b/homework7/project_express/node_modules/std/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2011 Marcus Westin + +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/homework7/project_express/node_modules/std/ListPromise.js b/homework7/project_express/node_modules/std/ListPromise.js new file mode 100644 index 0000000..1875bea --- /dev/null +++ b/homework7/project_express/node_modules/std/ListPromise.js @@ -0,0 +1,47 @@ +var proto = require('./proto'), + bind = require('./bind') + +module.exports = proto(null, + function(waitForNum, callback) { + this._waitingFor = waitForNum + this._callbacks = [] + this._results = [] + this._error = null + if (callback) { this.add(callback) } + }, { + add: function(callback) { + if (!this._waitingFor) { + this._notify(callback) + } else { + this._callbacks.push(callback) + } + }, + getResponder: function() { + return bind(this, function(err, res) { + if (err) { this.fail(err) } + else { this.fulfill(res) } + }) + }, + fulfill: function(result) { + if (!this._waitingFor) { throw new Error('ListPromise fulfilled too many times') } + this._results.push(result) + if (!--this._waitingFor) { + this._notifyAll() + } + }, + fail: function(error) { + this._error = error + this._notifyAll() + }, + _notifyAll: function() { + if (!this._callbacks) { return } + for (var i=0; i= 0; i--) { + if (ka[i] != kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!deepEqual(a[key], b[key] )) + return false; + } + return true; +} diff --git a/homework7/project_express/node_modules/std/asyncEach.js b/homework7/project_express/node_modules/std/asyncEach.js new file mode 100644 index 0000000..878162a --- /dev/null +++ b/homework7/project_express/node_modules/std/asyncEach.js @@ -0,0 +1,63 @@ +var nextTick = require('std/nextTick') + +module.exports = function asyncEach(items, opts) { + var finish = opts.finish + if (!items.length) { return finish(null, []) } + + var parallel = opts.parallel + if (parallel === true) { parallel = items.length } + if (!parallel) { parallel = 1 } + if (parallel > waitingFor) { parallel = waitingFor } + + var nextIndex = 0 + var result = [] + var errorResult = null + var waitingFor = items.length + var context = opts.context || this + + var iterator = module.exports.makeIterator(context, opts.iterate) + + function processNextItem() { + if (!waitingFor) { + return finish.call(context, null) + } + var iterationIndex = nextIndex + if (iterationIndex == items.length) { + // no more processing to be done - just wait for the remaining parallel requests to finish + return + } + nextIndex += 1 + nextTick(function() { + iterator(items[iterationIndex], iterationIndex, iteratorCallback) + }) + } + + function iteratorCallback(err) { + if (errorResult) { return } + if (err) { + errorResult = err + finish.call(context, err, null) + } else { + waitingFor -= 1 + processNextItem() + } + } + + // starts `parallel` number of functions processing the array + for (var parallelI=0; parallelI>> 18) + + b64chars.charAt((n >>> 12) & 63) + + b64chars.charAt((n >>> 6) & 63) + + b64chars.charAt( n & 63); +}; + +var toBase64 = function(bin){ + if (bin.match(/[^\x00-\xFF]/)) throw 'unsupported character found' ; + var padlen = 0; + while(bin.length % 3) { + bin += '\0'; + padlen++; + }; + var b64 = bin.replace(/[\x00-\xFF]{3}/g, sub_toBase64); + if (!padlen) return b64; + b64 = b64.substr(0, b64.length - padlen); + while(padlen--) b64 += '='; + return b64; +}; + +var btoa = global.btoa || toBase64; + +var sub_fromBase64 = function(m){ + var n = (b64tab[ m.charAt(0) ] << 18) + | (b64tab[ m.charAt(1) ] << 12) + | (b64tab[ m.charAt(2) ] << 6) + | (b64tab[ m.charAt(3) ]); + return String.fromCharCode( n >> 16 ) + + String.fromCharCode( (n >> 8) & 0xff ) + + String.fromCharCode( n & 0xff ); +}; + +var fromBase64 = function(b64){ + b64 = b64.replace(/[^A-Za-z0-9\+\/]/g, ''); + var padlen = 0; + while(b64.length % 4){ + b64 += 'A'; + padlen++; + } + var bin = b64.replace(/[A-Za-z0-9\+\/]{4}/g, sub_fromBase64); + if (padlen >= 2) + bin = bin.substring(0, bin.length - [0,0,2,1][padlen]); + return bin; +}; + +var atob = global.atob || fromBase64; + +var re_char_nonascii = /[^\x00-\x7F]/g; + +var sub_char_nonascii = function(m){ + var n = m.charCodeAt(0); + return n < 0x800 ? String.fromCharCode(0xc0 | (n >>> 6)) + + String.fromCharCode(0x80 | (n & 0x3f)) + : String.fromCharCode(0xe0 | ((n >>> 12) & 0x0f)) + + String.fromCharCode(0x80 | ((n >>> 6) & 0x3f)) + + String.fromCharCode(0x80 | (n & 0x3f)) + ; +}; + +var utob = function(uni){ + return uni.replace(re_char_nonascii, sub_char_nonascii); +}; + +var re_bytes_nonascii + = /[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g; + +var sub_bytes_nonascii = function(m){ + var c0 = m.charCodeAt(0); + var c1 = m.charCodeAt(1); + if(c0 < 0xe0){ + return String.fromCharCode(((c0 & 0x1f) << 6) | (c1 & 0x3f)); + }else{ + var c2 = m.charCodeAt(2); + return String.fromCharCode( + ((c0 & 0x0f) << 12) | ((c1 & 0x3f) << 6) | (c2 & 0x3f) + ); + } +}; + +var btou = function(bin){ + return bin.replace(re_bytes_nonascii, sub_bytes_nonascii); +}; + +global.exports = { + fromBase64:fromBase64, + toBase64:toBase64, + atob:atob, + btoa:btoa, + utob:utob, + btou:btou, + encode:function(u){ return btoa(utob(u)) }, + encodeURI:function(u){ + return btoa(utob(u)).replace(/[+\/]/g, function(m0){ + return m0 == '+' ? '-' : '_'; + }).replace(/=+$/, ''); + }, + decode:function(a){ + return btou(atob(a.replace(/[-_]/g, function(m0){ + return m0 == '-' ? '+' : '/'; + }))); + } +}; + +})(module); \ No newline at end of file diff --git a/homework7/project_express/node_modules/std/bind.js b/homework7/project_express/node_modules/std/bind.js new file mode 100644 index 0000000..cf15e4d --- /dev/null +++ b/homework7/project_express/node_modules/std/bind.js @@ -0,0 +1,50 @@ +/* + Example usage: + + function Client() { + this._socket = new Connection() + this._socket.open() + this._socket.on('connected', bind(this, '_log', 'connected!')) + this._socket.on('connected', bind(this, 'disconnect')) + } + + Client.prototype._log = function(message) { + console.log('client says:', message) + } + + Client.prototype.disconnect = function() { + this._socket.disconnect() + } + + Example usage: + + var Toolbar = Class(function() { + + this.init = function() { + this._buttonWasClicked = false + } + + this.addButton = function(clickHandler) { + this._button = new Button() + this._button.on('Click', bind(this, '_onButtonClick', clickHandler)) + } + + this._onButtonClick = function(clickHandler) { + this._buttonWasClicked = true + clickHandler() + } + + }) + +*/ +var slice = require('./slice') + +module.exports = function bind(context, method /* curry1, curry2, ... curryN */) { + if (typeof method == 'string') { method = context[method] } + var curryArgs = slice(arguments, 2) + return function bound() { + var invocationArgs = slice(arguments) + return method.apply(context, curryArgs.concat(invocationArgs)) + } +} + diff --git a/homework7/project_express/node_modules/std/blockFunction.js b/homework7/project_express/node_modules/std/blockFunction.js new file mode 100644 index 0000000..00250b3 --- /dev/null +++ b/homework7/project_express/node_modules/std/blockFunction.js @@ -0,0 +1,44 @@ +/* + Block a function from being called by adding and removing any number of blocks. + Excellent for waiting on parallel asynchronous operations. + A blocked function starts out with exactly one block + + Example usage: + + http.createServer(function(req, res) { + var sendResponse = blockFunction(function() { + res.writeHead(204) + res.end() + }) + var queries = parseQueries(req.url) + for (var i=0; i= 0) + } +}) + +if (typeof window != 'undefined') { module.exports = new Client(window.navigator.userAgent) } +else { module.exports = {} } + +module.exports.parse = function(userAgent) { return new Client(userAgent) } diff --git a/homework7/project_express/node_modules/std/clip.js b/homework7/project_express/node_modules/std/clip.js new file mode 100644 index 0000000..e680270 --- /dev/null +++ b/homework7/project_express/node_modules/std/clip.js @@ -0,0 +1,3 @@ +module.exports = function clip(val, min, max) { + return Math.max(Math.min(val, max), min) +} diff --git a/homework7/project_express/node_modules/std/cookie.js b/homework7/project_express/node_modules/std/cookie.js new file mode 100644 index 0000000..5f88f5b --- /dev/null +++ b/homework7/project_express/node_modules/std/cookie.js @@ -0,0 +1,33 @@ +module.exports.get = function(name) { + var regex = new RegExp( + '(^|(; ))' + // beginning of document.cookie, or "; " which signifies the beginning of a new cookie + name + + '=([^;]*)') // the value of the cookie, matched up until a ";" or the end of the string + + var match = document.cookie.match(regex), + value = match && match[3] + return value && decodeURIComponent(value) +} + +module.exports.set = function(name, value, duration) { + if (duration === undefined) { duration = (365 * 24 * 60 * 60 * 1000) } // one year + var date = (duration instanceof Date ? duration : (duration < 0 ? null : new Date(new Date().getTime() + duration))), + expires = date ? "expires=" + date.toGMTString() + '; ' : '', + cookieName = name + '=' + encodeURIComponent(value) + '; ', + domain = 'domain='+document.domain+'; ', + path = 'path=/; ' + + document.cookie = cookieName + expires + domain + path +} + +module.exports.isEnabled = function() { + var name = '__test__cookie' + new Date().getTime() + module.exports.set(name, 1) + var isEnabled = !!module.exports.get(name) + module.exports.remove(name) + return isEnabled +} + +module.exports.remove = function(name) { + module.exports.set(name, "", new Date(1)) +} diff --git a/homework7/project_express/node_modules/std/copy.js b/homework7/project_express/node_modules/std/copy.js new file mode 100644 index 0000000..bbba668 --- /dev/null +++ b/homework7/project_express/node_modules/std/copy.js @@ -0,0 +1,10 @@ +var each = require('./each'), + isArray = require('./isArray') + +module.exports = function copy(obj, deep) { + var result = isArray(obj) ? [] : {} + each(obj, function(val, key) { + result[key] = (deep && typeof val == 'object') ? copy(val, deep) : val + }) + return result +} diff --git a/homework7/project_express/node_modules/std/crc32.js b/homework7/project_express/node_modules/std/crc32.js new file mode 100644 index 0000000..5aa5d3e --- /dev/null +++ b/homework7/project_express/node_modules/std/crc32.js @@ -0,0 +1,28 @@ +// https://github.com/kvz/phpjs/raw/2ae4292a8629d6007eae26298bd19339ef97957e/functions/strings/crc32.js +// MIT License http://phpjs.org/pages/license + +var utf8_encode = require('./utf8_encode') + +module.exports = function crc32 (str) { + // http://kevin.vanzonneveld.net + // + original by: Webtoolkit.info (http://www.webtoolkit.info/) + // + improved by: T0bsn + // - depends on: utf8_encode + // * example 1: crc32('Kevin van Zonneveld'); + // * returns 1: 1249991249 + str = utf8_encode(str); + var table = "00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F 63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC 51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E 7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D 806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA 11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F 30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D"; + + var crc = 0; + var x = 0; + var y = 0; + + crc = crc ^ (-1); + for (var i = 0, iTop = str.length; i < iTop; i++) { + y = (crc ^ str.charCodeAt(i)) & 0xFF; + x = "0x" + table.substr(y * 9, 8); + crc = (crc >>> 8) ^ x; + } + + return crc ^ (-1); +} diff --git a/homework7/project_express/node_modules/std/create.js b/homework7/project_express/node_modules/std/create.js new file mode 100644 index 0000000..fa865be --- /dev/null +++ b/homework7/project_express/node_modules/std/create.js @@ -0,0 +1,22 @@ +// Thanks Douglas Crockford! http://javascript.crockford.com/prototypal.html +module.exports = function create(obj, extendWithProperties) { + function extendObject(result, props) { + for (var key in props) { + if (!props.hasOwnProperty(key)) { continue } + result[key] = props[key] + } + return result + } + if (typeof Object.create == 'function') { + module.exports = function nativeCreate(obj, extendWithProperties) { + return extendObject(Object.create(obj), extendWithProperties) + } + } else { + module.exports = function shimCreate(obj, extendWithProperties) { + function F() {} + F.prototype = obj + return extendObject(new F(), extendWithProperties) + } + } + return module.exports(obj, extendWithProperties) +} diff --git a/homework7/project_express/node_modules/std/curry.js b/homework7/project_express/node_modules/std/curry.js new file mode 100644 index 0000000..52d4a19 --- /dev/null +++ b/homework7/project_express/node_modules/std/curry.js @@ -0,0 +1,10 @@ +var slice = require('./slice') + +module.exports = function curry(fn /* arg1, arg2, ... argN */) { + var curryArgs = slice(arguments, 1) + return function curried() { + var invocationArgs = slice(arguments) + return fn.apply(this, curryArgs.concat(invocationArgs)) + } +} + diff --git a/homework7/project_express/node_modules/std/defineGetter.js b/homework7/project_express/node_modules/std/defineGetter.js new file mode 100644 index 0000000..0071e2c --- /dev/null +++ b/homework7/project_express/node_modules/std/defineGetter.js @@ -0,0 +1,29 @@ +module.exports = function(object, propertyName, getter) { + module.exports = object.defineGetter ? _w3cDefineGetter + : object.__defineGetter__ ? _interimDefineGetter + : Object.defineProperty ? _ie8DefineGetter + : function() { throw 'defineGetter not supported' } + return module.exports(object, propertyName, getter) +} + +function defineGetter(object, propertyName, getter) { + var fn = object.defineGetter ? _w3cDefineGetter + : object.__defineGetter__ ? _interimDefineGetter + : Object.defineProperty ? _ie8DefineGetter + : function() { throw new Error('defineGetter is not supported') } + + module.exports.defineGetter = fn + fn.apply(this, arguments) +} + +var _w3cDefineGetter = function(object, propertyName, getter) { + object.defineGetter(propertyName, getter) +} + +var _interimDefineGetter = function(object, propertyName, getter) { + object.__defineGetter__(propertyName, getter) +} + +var _ie8DefineGetter = function(object, propertyName, getter) { + Object.defineProperty(object, propertyName, { value:getter, enumerable:true, configurable:true }) +} diff --git a/homework7/project_express/node_modules/std/delay.js b/homework7/project_express/node_modules/std/delay.js new file mode 100644 index 0000000..2984b4b --- /dev/null +++ b/homework7/project_express/node_modules/std/delay.js @@ -0,0 +1,51 @@ +/* + Delay the execution of a function. + If the function gets called multiple times during a delay, the delayed function gets invoced only once, + with the arguments of the most recent invocation. This is useful for expensive functions that should + not be called multiple times during a short time interval, e.g. rendering + + Example usage: + + Class(UIComponent, function() { + this.render = delay(function() { + ... + }, 250) // render at most 4 times per second + }) + + // Bath messages into a single email + var EmailBatcher = Class(function() { + this.init = function() { + this._queue = [] + } + + this.send = function(email) { + this._queue.push(email) + this._scheduleDispatch() + } + + this._scheduleDispatch = delay(function() { + smtp.send(this._queue.join('\n\n')) + this._queue = [] + }, 5000) // send emails at most once every 5 seconds + }) +*/ +module.exports = function delay(fn, delayBy) { + if (typeof delayBy != 'number') { delayBy = 50 } + var timeoutName = '__delayTimeout__' + (++module.exports._unique) + var delayedFunction = function delayed() { + if (this[timeoutName]) { + clearTimeout(this[timeoutName]) + } + var args = arguments, self = this + this[timeoutName] = setTimeout(function fireDelayed() { + clearTimeout(self[timeoutName]) + delete self[timeoutName] + fn.apply(self, args) + }, delayBy) + } + delayedFunction.cancel = function() { + clearTimeout(this[timeoutName]) + } + return delayedFunction +} +module.exports._unique = 0 diff --git a/homework7/project_express/node_modules/std/delayed.js b/homework7/project_express/node_modules/std/delayed.js new file mode 100644 index 0000000..3efc6ba --- /dev/null +++ b/homework7/project_express/node_modules/std/delayed.js @@ -0,0 +1,11 @@ +module.exports = function delayed(amount, fn) { + if (!fn) { + fn = amount + amount = 0 + } + return function() { + var self = this + var args = arguments + setTimeout(function() { fn.apply(self, args) }, amount) + } +} diff --git a/homework7/project_express/node_modules/std/each.js b/homework7/project_express/node_modules/std/each.js new file mode 100644 index 0000000..5c27d32 --- /dev/null +++ b/homework7/project_express/node_modules/std/each.js @@ -0,0 +1,20 @@ +var isArray = require('./isArray'), + isArguments = require('./isArguments') + +module.exports = function(items, ctx, fn) { + if (!items) { return } + if (!fn) { + fn = ctx + ctx = this + } + if (isArray(items) || isArguments(items)) { + for (var i=0; i < items.length; i++) { + fn.call(ctx, items[i], i) + } + } else { + for (var key in items) { + if (!items.hasOwnProperty(key)) { continue } + fn.call(ctx, items[key], key) + } + } +} diff --git a/homework7/project_express/node_modules/std/extend.js b/homework7/project_express/node_modules/std/extend.js new file mode 100644 index 0000000..f65441b --- /dev/null +++ b/homework7/project_express/node_modules/std/extend.js @@ -0,0 +1,40 @@ +/* + Example usage: + + var A = Class(function() { + + var defaults = { + foo: 'cat', + bar: 'dum' + } + + this.init = function(opts) { + opts = std.extend(opts, defaults) + this._foo = opts.foo + this._bar = opts.bar + } + + this.getFoo = function() { + return this._foo + } + + this.getBar = function() { + return this._bar + } + }) + + var a = new A({ bar:'sim' }) + a.getFoo() == 'cat' + a.getBar() == 'sim' +*/ + +var copy = require('./copy') + +module.exports = function extend(target, extendWith) { + target = copy(target) + for (var key in extendWith) { + if (typeof target[key] != 'undefined') { continue } + target[key] = extendWith[key] + } + return target +} diff --git a/homework7/project_express/node_modules/std/filter.js b/homework7/project_express/node_modules/std/filter.js new file mode 100644 index 0000000..2517944 --- /dev/null +++ b/homework7/project_express/node_modules/std/filter.js @@ -0,0 +1,38 @@ +/* + Example usage: + filter([1,2,0,'',false,null,undefined]) // -> [1,2,0,'',false] + filter([1,2,3], this, function(val, index) { val == 1 }) // -> [1] +*/ +var each = require('./each') +var isArray = require('./isArray') + +module.exports = function filter(arr, ctx, fn) { + if (arguments.length == 2) { + fn = ctx + ctx = this + } + if (!fn) { + fn = falseOrTruthy + } + + var result + if (isArray(arr)) { + result = [] + each(arr, function(value, index) { + if (!fn.call(ctx, value, index)) { return } + result.push(value) + }) + } else { + result = {} + each(arr, function(value, key) { + if (!fn.call(ctx, value, key)) { return } + result[key] = value + }) + } + return result +} + +function falseOrTruthy(arg) { + return !!arg || arg === false +} + diff --git a/homework7/project_express/node_modules/std/find.js b/homework7/project_express/node_modules/std/find.js new file mode 100644 index 0000000..b51d1ec --- /dev/null +++ b/homework7/project_express/node_modules/std/find.js @@ -0,0 +1,7 @@ +module.exports = function find(items, fn) { + if (!items) { return null } + for (var i=0; i argument.length) { + throw new Error('Warning: pack() Type ' + instruction + ': not enough characters in string'); + } + for (i = 0; i < quantifier; i += 2) { + // Always get per 2 bytes... + word = argument[i]; + if (((i + 1) >= quantifier) || typeof(argument[i + 1]) === 'undefined') { + word += '0'; + } else { + word += argument[i + 1]; + } + // The fastest way to reverse? + if (instruction === 'h') { + word = word[1] + word[0]; + } + result += String.fromCharCode(parseInt(word, 16)); + } + argumentPointer++; + break; + + case 'c': + // signed char + case 'C': + // unsigned char + // c and C is the same in pack + if (quantifier === '*') { + quantifier = arguments.length - argumentPointer; + } + if (quantifier > (arguments.length - argumentPointer)) { + throw new Error('Warning: pack() Type ' + instruction + ': too few arguments'); + } + + for (i = 0; i < quantifier; i++) { + result += String.fromCharCode(arguments[argumentPointer]); + argumentPointer++; + } + break; + + case 's': + // signed short (always 16 bit, machine byte order) + case 'S': + // unsigned short (always 16 bit, machine byte order) + case 'v': + // s and S is the same in pack + if (quantifier === '*') { + quantifier = arguments.length - argumentPointer; + } + if (quantifier > (arguments.length - argumentPointer)) { + throw new Error('Warning: pack() Type ' + instruction + ': too few arguments'); + } + + for (i = 0; i < quantifier; i++) { + result += String.fromCharCode(arguments[argumentPointer] & 0xFF); + result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF); + argumentPointer++; + } + break; + + case 'n': + // unsigned short (always 16 bit, big endian byte order) + if (quantifier === '*') { + quantifier = arguments.length - argumentPointer; + } + if (quantifier > (arguments.length - argumentPointer)) { + throw new Error('Warning: pack() Type ' + instruction + ': too few arguments'); + } + + for (i = 0; i < quantifier; i++) { + result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF); + result += String.fromCharCode(arguments[argumentPointer] & 0xFF); + argumentPointer++; + } + break; + + case 'i': + // signed integer (machine dependent size and byte order) + case 'I': + // unsigned integer (machine dependent size and byte order) + case 'l': + // signed long (always 32 bit, machine byte order) + case 'L': + // unsigned long (always 32 bit, machine byte order) + case 'V': + // unsigned long (always 32 bit, little endian byte order) + if (quantifier === '*') { + quantifier = arguments.length - argumentPointer; + } + if (quantifier > (arguments.length - argumentPointer)) { + throw new Error('Warning: pack() Type ' + instruction + ': too few arguments'); + } + + for (i = 0; i < quantifier; i++) { + result += String.fromCharCode(arguments[argumentPointer] & 0xFF); + result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF); + result += String.fromCharCode(arguments[argumentPointer] >> 16 & 0xFF); + result += String.fromCharCode(arguments[argumentPointer] >> 24 & 0xFF); + argumentPointer++; + } + + break; + case 'N': + // unsigned long (always 32 bit, big endian byte order) + if (quantifier === '*') { + quantifier = arguments.length - argumentPointer; + } + if (quantifier > (arguments.length - argumentPointer)) { + throw new Error('Warning: pack() Type ' + instruction + ': too few arguments'); + } + + for (i = 0; i < quantifier; i++) { + result += String.fromCharCode(arguments[argumentPointer] >> 24 & 0xFF); + result += String.fromCharCode(arguments[argumentPointer] >> 16 & 0xFF); + result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF); + result += String.fromCharCode(arguments[argumentPointer] & 0xFF); + argumentPointer++; + } + break; + + case 'f': + // float (machine dependent size and representation) + case 'd': + // double (machine dependent size and representation) + // version based on IEEE754 + precisionBits = 23; + exponentBits = 8; + if (instruction === 'd') { + precisionBits = 52; + exponentBits = 11; + } + + if (quantifier === '*') { + quantifier = arguments.length - argumentPointer; + } + if (quantifier > (arguments.length - argumentPointer)) { + throw new Error('Warning: pack() Type ' + instruction + ': too few arguments'); + } + for (i = 0; i < quantifier; i++) { + argument = arguments[argumentPointer]; + bias = Math.pow(2, exponentBits - 1) - 1; + minExp = -bias + 1; + maxExp = bias; + minUnnormExp = minExp - precisionBits; + status = isNaN(n = parseFloat(argument)) || n === -Infinity || n === +Infinity ? n : 0; + exp = 0; + len = 2 * bias + 1 + precisionBits + 3; + bin = new Array(len); + signal = (n = status !== 0 ? 0 : n) < 0; + n = Math.abs(n); + intPart = Math.floor(n); + floatPart = n - intPart; + + for (k = len; k;) { + bin[--k] = 0; + } + for (k = bias + 2; intPart && k;) { + bin[--k] = intPart % 2; + intPart = Math.floor(intPart / 2); + } + for (k = bias + 1; floatPart > 0 && k; --floatPart) { + (bin[++k] = ((floatPart *= 2) >= 1) - 0); + } + for (k = -1; ++k < len && !bin[k];) {} + + if (bin[(lastBit = precisionBits - 1 + (k = (exp = bias + 1 - k) >= minExp && exp <= maxExp ? k + 1 : bias + 1 - (exp = minExp - 1))) + 1]) { + if (!(rounded = bin[lastBit])) { + for (j = lastBit + 2; !rounded && j < len; rounded = bin[j++]) {} + } + for (j = lastBit + 1; rounded && --j >= 0; + (bin[j] = !bin[j] - 0) && (rounded = 0)) {} + } + + for (k = k - 2 < 0 ? -1 : k - 3; ++k < len && !bin[k];) {} + + if ((exp = bias + 1 - k) >= minExp && exp <= maxExp) { + ++k; + } else { + if (exp < minExp) { + if (exp !== bias + 1 - len && exp < minUnnormExp) { /*"encodeFloat::float underflow" */ + } + k = bias + 1 - (exp = minExp - 1); + } + } + + if (intPart || status !== 0) { + exp = maxExp + 1; + k = bias + 2; + if (status === -Infinity) { + signal = 1; + } else if (isNaN(status)) { + bin[k] = 1; + } + } + + n = Math.abs(exp + bias); + tmpResult = ''; + + for (j = exponentBits + 1; --j;) { + tmpResult = (n % 2) + tmpResult; + n = n >>= 1; + } + + n = 0; + j = 0; + k = (tmpResult = (signal ? '1' : '0') + tmpResult + bin.slice(k, k + precisionBits).join('')).length; + r = []; + + for (; k;) { + n += (1 << j) * tmpResult.charAt(--k); + if (j === 7) { + r[r.length] = String.fromCharCode(n); + n = 0; + } + j = (j + 1) % 8; + } + + r[r.length] = n ? String.fromCharCode(n) : ''; + result += r.join(''); + argumentPointer++; + } + break; + + case 'x': + // NUL byte + if (quantifier === '*') { + throw new Error('Warning: pack(): Type x: \'*\' ignored'); + } + for (i = 0; i < quantifier; i++) { + result += String.fromCharCode(0); + } + break; + + case 'X': + // Back up one byte + if (quantifier === '*') { + throw new Error('Warning: pack(): Type X: \'*\' ignored'); + } + for (i = 0; i < quantifier; i++) { + if (result.length === 0) { + throw new Error('Warning: pack(): Type X:' + ' outside of string'); + } else { + result = result.substring(0, result.length - 1); + } + } + break; + + case '@': + // NUL-fill to absolute position + if (quantifier === '*') { + throw new Error('Warning: pack(): Type X: \'*\' ignored'); + } + if (quantifier > result.length) { + extraNullCount = quantifier - result.length; + for (i = 0; i < extraNullCount; i++) { + result += String.fromCharCode(0); + } + } + if (quantifier < result.length) { + result = result.substring(0, quantifier); + } + break; + + default: + throw new Error('Warning: pack() Type ' + instruction + ': unknown format code'); + } + } + if (argumentPointer < arguments.length) { + throw new Error('Warning: pack(): ' + (arguments.length - argumentPointer) + ' arguments unused'); + } + + return result; +} diff --git a/homework7/project_express/node_modules/std/package.json b/homework7/project_express/node_modules/std/package.json new file mode 100644 index 0000000..446cdff --- /dev/null +++ b/homework7/project_express/node_modules/std/package.json @@ -0,0 +1,17 @@ +{ + "name": "std", + "description": "javascript standard library", + "version": "0.1.40", + "repository": { + "type": "git", + "url": "git://github.com/marcuswestin/std.js.git" + }, + "author": "@marcuswestin", + "contributors": ["@kaleb"], + "directories": { + "lib": "lib" + }, + "engines": { + "node": "*" + } +} diff --git a/homework7/project_express/node_modules/std/parallel.js b/homework7/project_express/node_modules/std/parallel.js new file mode 100644 index 0000000..4bbfd67 --- /dev/null +++ b/homework7/project_express/node_modules/std/parallel.js @@ -0,0 +1,17 @@ +var asyncMap = require('std/asyncMap') +var slice = require('std/slice') + +module.exports = function parallel(/* fn1, fn2, ..., finishFn */) { + var parallelFunctions = slice(arguments) + var finish = parallelFunctions.pop() + asyncMap(parallelFunctions, { + parallel:parallelFunctions.length, + iterate:function(parallelFn, done) { + parallelFn(done) + }, + finish:function(err, mapResults) { + if (err) { return finish(err) } + finish.apply(this, [null].concat(mapResults)) + } + }) +} diff --git a/homework7/project_express/node_modules/std/popup.js b/homework7/project_express/node_modules/std/popup.js new file mode 100644 index 0000000..13eaf00 --- /dev/null +++ b/homework7/project_express/node_modules/std/popup.js @@ -0,0 +1,26 @@ +var extend = require('./extend'), + map = require('./map') + +module.exports = function(url, winID, opts) { + opts = extend(opts, module.exports.defaults) + if (!opts['left']) { opts['left'] = Math.round((screen.width - opts['width']) / 2) } + if (!opts['top']) { opts['top'] = Math.round((screen.height - opts['height']) / 2) } + + var popupStr = map(opts, function(val, key) { return key+'='+val }).join(',') + + return window.open(url, winID, popupStr) +} + +module.exports.defaults = { + 'width': 600, + 'height': 400, + 'left': null, + 'top': null, + 'directories': 0, + 'location': 1, + 'menubar': 0, + 'resizable': 0, + 'scrollbars': 1, + 'titlebar': 0, + 'toolbar': 0 +} diff --git a/homework7/project_express/node_modules/std/proto.js b/homework7/project_express/node_modules/std/proto.js new file mode 100644 index 0000000..132750a --- /dev/null +++ b/homework7/project_express/node_modules/std/proto.js @@ -0,0 +1,39 @@ +/* + // Usage: proto(prototypeObj, intantiatingFn, properties) + + var base = { + say:function(arg) { alert(arg) } + } + + var person = proto(base, + function(name) { + this.name = name + }, { + greet:function(other) { + this.say("hello "+other.name+", I'm "+this.name) + } + } + ) + + var marcus = person("marcus"), + john = person("john") + + marcus.greet(john) +*/ + +var create = require('./create') + +var proto = module.exports = function proto(prototypeObject, instantiationFunction, propertiesToAdd) { + // F is the function that is required in order to implement JS prototypical inheritence + function F(args) { + // When a new object is created, call the instantiation function + return instantiationFunction.apply(this, args) + } + // The prototype object itself points to the passed-in prototypeObject, + // but also has all the properties enumerated in propertiesToAdd + F.prototype = prototypeObject ? create(prototypeObject, propertiesToAdd) : propertiesToAdd + + return function() { + return new F(arguments) + } +} diff --git a/homework7/project_express/node_modules/std/rand.js b/homework7/project_express/node_modules/std/rand.js new file mode 100644 index 0000000..1add156 --- /dev/null +++ b/homework7/project_express/node_modules/std/rand.js @@ -0,0 +1,3 @@ +module.exports = function rand(floor, ceil) { + return Math.floor(Math.random() * (ceil - floor + 1)) + floor +} \ No newline at end of file diff --git a/homework7/project_express/node_modules/std/recall.js b/homework7/project_express/node_modules/std/recall.js new file mode 100644 index 0000000..6238023 --- /dev/null +++ b/homework7/project_express/node_modules/std/recall.js @@ -0,0 +1,4 @@ +module.exports = function recall(context, args) { + var fn = args.callee + return function() { return fn.apply(context, args); } +} diff --git a/homework7/project_express/node_modules/std/remove.js b/homework7/project_express/node_modules/std/remove.js new file mode 100644 index 0000000..19e251c --- /dev/null +++ b/homework7/project_express/node_modules/std/remove.js @@ -0,0 +1,8 @@ +module.exports = function remove(arr, item) { + if (!arr) { return } + for (var i=0; i 0)) { // (undefined < 0) == false, but (!(undefined > 0)) == true + return Math.round(value) + } + var granularity = Math.pow(10, decimalPoints) + return Math.round(value * granularity) / granularity +} diff --git a/homework7/project_express/node_modules/std/router.js b/homework7/project_express/node_modules/std/router.js new file mode 100644 index 0000000..278a99c --- /dev/null +++ b/homework7/project_express/node_modules/std/router.js @@ -0,0 +1,71 @@ +var create = require('./create'), + options = require('./options'), + parseUrl = require('./url').parse + +module.exports = function(opts) { + opts = options(opts, { prefix:'/', default:'/' }) + opts.prefix = new RegExp('^'+opts.prefix) + return create(router, { + routes:{}, + errorHandlers:[], + opts:opts + }) +} + +var router = { + add:function(routeName, handler) { + var route = this.routes + var parts = routeName.split('/') + if (parts[0] != '') { throw new Error('Route much start with "/": '+ routeName) } + parts.shift() + for (var i=0; i steps[i]) { continue } + var result = _getStepResult(millisecondsAgo, steps, i) + if (yield) { + yield(result.payload) + if (result.smallestGranularity) { + var timeoutIn = Math.min(result.smallestGranularity - (millisecondsAgo % result.smallestGranularity), MAX_TIMEOUT_VALUE) + setTimeout(curry(stepFn, unbasedTimestamp, yield), timeoutIn * base) + } + } + return result.payload + } + return _getStepResult(millisecondsAgo, steps, i - 3).payload // the last one + } + return stepFn + } + + function _getStepResult(millisecondsAgo, steps, i) { + var stepSize = steps[i] + var stepPayload = steps[i+1] + var stepGranularities = steps[i+2] + var smallestGranularity = stepSize + var untakenTime = millisecondsAgo + each(stepGranularities, function(granularity) { + var granAmount = Math.floor(untakenTime / granularity) + untakenTime -= granAmount * granularity + stepPayload = stepPayload.replace('%N', granAmount) + if (granularity < smallestGranularity) { + smallestGranularity = granularity + } + }) + return { payload:stepPayload, smallestGranularity:smallestGranularity } + } + + return time +} diff --git a/homework7/project_express/node_modules/std/trim.js b/homework7/project_express/node_modules/std/trim.js new file mode 100644 index 0000000..d0458cf --- /dev/null +++ b/homework7/project_express/node_modules/std/trim.js @@ -0,0 +1,4 @@ +// Thanks goog! http://code.google.com/p/closure-library/source/browse/trunk/closure/goog/string/string.js?r=2 +module.exports = function(str) { + return str ? str.replace(/^[\s\xa0]+|[\s\xa0]+$/g, '') : '' +} diff --git a/homework7/project_express/node_modules/std/unique.js b/homework7/project_express/node_modules/std/unique.js new file mode 100644 index 0000000..936d603 --- /dev/null +++ b/homework7/project_express/node_modules/std/unique.js @@ -0,0 +1,22 @@ +var identity = function(item) { return item } +var itemId = function(item) { return item.id } + +/* + * Filters a list to unique items + */ +module.exports = function(list, getId) { + if (!list || !list.length) { return [] } + if (!getId) { + getId = (list[0].id ? itemId : identity) + } + var seen = {} + var result = [] + for (var i=0; i> 3) - 1; + lastByte = byteArray.length + (-(start + length) >> 3); + diff = curByte - lastByte; + sum = ( + (byteArray[ curByte ] >> offsetRight) & + ((1 << (diff ? 8 - offsetRight : length)) - 1) + ) + ( + diff && (offsetLeft = (start + length) % 8) ? + (byteArray[ lastByte++ ] & ((1 << offsetLeft) - 1)) << + (diff-- << 3) - offsetRight : + 0 + ); + + for(; diff;) { + sum += shl(byteArray[ lastByte++ ], (diff-- << 3) - offsetRight); + } + return sum; + }; + + while (formatPointer < format.length) { + instruction = format[formatPointer]; + + // Start reading 'quantifier' + quantifier = ''; + formatPointer++; + while ((formatPointer < format.length) && + (format[formatPointer].match(/[\d\*]/) !== null)) { + quantifier += format[formatPointer]; + formatPointer++; + } + if (quantifier === '') { + quantifier = '1'; + } + + + // Start reading label + label = ''; + while ((formatPointer < format.length) && + (format[formatPointer] !== '/')) { + label += format[formatPointer]; + formatPointer++; + } + if (format[formatPointer] === '/') { + formatPointer++; + } + + // Process given instruction + switch (instruction) { + case 'a': // NUL-padded string + case 'A': // SPACE-padded string + if (quantifier === '*') { + quantifier = data.length - dataPointer; + } else { + quantifier = parseInt(quantifier, 10); + } + currentData = data.substr(dataPointer, quantifier); + dataPointer += quantifier; + + if (instruction === 'a') { + currentResult = currentData.replace(/\0+$/, ''); + } else { + currentResult = currentData.replace(/ +$/, ''); + } + result[label] = currentResult; + break; + + case 'h': // Hex string, low nibble first + case 'H': // Hex string, high nibble first + if (quantifier === '*') { + quantifier = data.length - dataPointer; + } else { + quantifier = parseInt(quantifier, 10); + } + currentData = data.substr(dataPointer, quantifier); + dataPointer += quantifier; + + if (quantifier>currentData.length) { + throw new Error('Warning: unpack(): Type ' + instruction + + ': not enough input, need ' + quantifier); + } + + currentResult = ''; + for(i=0;i= 128)) { + currentResult -= 256; + } + result[label+(quantifier>1? + (i+1): + '')] = currentResult; + } + break; + + case 'S': // unsigned short (always 16 bit, machine byte order) + case 's': // signed short (always 16 bit, machine byte order) + case 'v': // unsigned short (always 16 bit, little endian byte order) + if (quantifier === '*') { + quantifier = (data.length - dataPointer) / 2; + } else { + quantifier = parseInt(quantifier, 10); + } + + currentData = data.substr(dataPointer, quantifier * 2); + dataPointer += quantifier * 2; + + for (i=0;i= 32768)) { + currentResult -= 65536; + } + result[label+(quantifier>1? + ((i/2)+1): + '')] = currentResult; + } + break; + + case 'n': // unsigned short (always 16 bit, big endian byte order) + if (quantifier === '*') { + quantifier = (data.length - dataPointer) / 2; + } else { + quantifier = parseInt(quantifier, 10); + } + + currentData = data.substr(dataPointer, quantifier * 2); + dataPointer += quantifier * 2; + + for (i=0;i1? + ((i/2)+1): + '')] = currentResult; + } + break; + + case 'i': // signed integer (machine dependent size and byte order) + case 'I': // unsigned integer (machine dependent size & byte order) + case 'l': // signed long (always 32 bit, machine byte order) + case 'L': // unsigned long (always 32 bit, machine byte order) + case 'V': // unsigned long (always 32 bit, little endian byte order) + if (quantifier === '*') { + quantifier = (data.length - dataPointer) / 4; + } else { + quantifier = parseInt(quantifier, 10); + } + + currentData = data.substr(dataPointer, quantifier * 4); + dataPointer += quantifier * 4; + + for (i=0;i1? + ((i/4)+1): + '')] = currentResult; + } + + break; + + case 'N': // unsigned long (always 32 bit, little endian byte order) + if (quantifier === '*') { + quantifier = (data.length - dataPointer) / 4; + } else { + quantifier = parseInt(quantifier, 10); + } + + currentData = data.substr(dataPointer, quantifier * 4); + dataPointer += quantifier * 4; + + for (i=0;i1? + ((i/4)+1): + '')] = currentResult; + } + + break; + + case 'f': + case 'd': + exponentBits = 8; + dataByteLength = 4; + if (instruction === 'd') { + exponentBits = 11; + dataByteLength = 8; + } + + if (quantifier === '*') { + quantifier = (data.length - dataPointer) / dataByteLength; + } else { + quantifier = parseInt(quantifier, 10); + } + + currentData = data.substr(dataPointer, + quantifier * dataByteLength); + dataPointer += quantifier * dataByteLength; + + for (i=0;i= 0 ; --j) { + b.push(data.charCodeAt(j)); + } + + precisionBits = (instruction === 'f')?23:52; + + bias = Math.pow(2, exponentBits - 1) - 1; + signal = readBits(precisionBits + exponentBits, 1, b); + exponent = readBits(precisionBits, exponentBits, b); + significand = 0; + divisor = 2; + curByte = b.length + (-precisionBits >> 3) - 1; + startBit = 0; + + do { + byteValue = b[ ++curByte ]; + startBit = precisionBits % 8 || 8; + mask = 1 << startBit; + for(; (mask >>= 1);) { + if (byteValue & mask) { + significand += 1 / divisor; + } + divisor *= 2; + } + } while ((precisionBits -= startBit)); + + if (exponent === (bias << 1) + 1) { + if (significand) { + currentResult = NaN; + } else { + if (signal) { + currentResult = -Infinity; + } else { + currentResult = +Infinity; + } + } + } else { + if ((1 + signal * -2) * (exponent || significand)) { + if (!exponent) { + currentResult = Math.pow(2, -bias + 1) * + significand; + } else { + currentResult = Math.pow(2, + exponent - bias) * + (1 + significand); + } + } else { + currentResult = 0; + } + } + result[label+(quantifier>1? + ((i/4)+1): + '')] = currentResult; + } + + break; + + case 'x': // NUL byte + case 'X': // Back up one byte + case '@': // NUL byte + if (quantifier === '*') { + quantifier = data.length - dataPointer; + } else { + quantifier = parseInt(quantifier, 10); + } + + if (quantifier > 0) { + if (instruction === 'X') { + dataPointer -= quantifier; + } else { + if (instruction === 'x') { + dataPointer += quantifier; + } else { + dataPointer = quantifier; + } + } + } + break; + + default: + throw new Error('Warning: unpack() Type ' + instruction + + ': unknown format code'); + } + } + return result; +} diff --git a/homework7/project_express/node_modules/std/url.js b/homework7/project_express/node_modules/std/url.js new file mode 100644 index 0000000..881e43c --- /dev/null +++ b/homework7/project_express/node_modules/std/url.js @@ -0,0 +1,112 @@ +var Class = require('./Class') +var map = require('./map') +var isArray = require('std/isArray') + +var URL = Class(function() { + + this._extractionRegex = new RegExp([ + '^', // start at the beginning of the string + '((\\w+:)?//)?', // match a possible protocol, like http://, ftp://, or // for a relative url + '(\\w[\\w\\.\\-]+)?', // match a possible domain + '(:\\d+)?', // match a possible port + '(\\/[^\\?#]+)?', // match a possible path + '(\\?[^#]+)?', // match possible GET parameters + '(#.*)?' // match the rest of the URL as the hash + ].join(''), 'i') + + this.init = function(url) { + var match = (url || '').toString().match(this._extractionRegex) || [] + this.protocol = match[2] || '' + this.hostname = match[3] || '' + this.port = (match[4] || '').substr(1) + this.host = (this.hostname ? this.hostname : '') + (this.port ? ':' + this.port : '') + this.pathname = match[5] || '' + this.search = (match[6]||'').substr(1) + this.hash = (match[7]||'').substr(1) + } + + this.setProtocol = function(protocol) { + this.protocol = protocol + return this + } + + this.toString = function() { + return [ + this.protocol || '//', + this.host, + this.pathname, + this.getSearch(), + this.getHash() + ].join('') + } + + this.toJSON = this.toString + + this.getTopLevelDomain = function() { + if (!this.host) { return '' } + var parts = this.host.split('.') + return parts.slice(parts.length - 2).join('.') + } + + this.getSearchParams = function() { + if (this._searchParams) { return this._searchParams } + return this._searchParams = url.query.parse(this.search) || {} + } + + this.getHashParams = function() { + if (this._hashParams) { return this._hashParams } + return this._hashParams = url.query.parse(this.hash) || {} + } + + this.addToSearch = function(key, val) { this.getSearchParams()[key] = val; return this } + this.addToHash = function(key, val) { this.getHashParams()[key] = val; return this } + this.removeFromSearch = function(key) { delete this.getSearchParams()[key]; return this } + this.removeFromHash = function(key) { delete this.getHashParams()[key]; return this } + + this.getSearch = function() { + return ( + this._searchParams ? '?' + url.query.string(this._searchParams) + : this.search ? '?' + this.search + : '') + } + + this.getHash = function() { + return ( + this._hashParams ? '#' + url.query.string(this._hashParams) + : this.hash ? '?' + this.hash + : '') + } + + this.getSearchParam = function(key) { return this.getSearchParams()[key] } + this.getHashParam = function(key) { return this.getHashParams()[key] } +}) + +var url = module.exports = function url(url) { return new URL(url) } +url.parse = url + +url.query = { + parse:function(paramString) { + var parts = paramString.split('&'), + params = {} + for (var i=0; i 127 && c1 < 2048) { + enc = String.fromCharCode((c1 >> 6) | 192) + String.fromCharCode((c1 & 63) | 128); + } else { + enc = String.fromCharCode((c1 >> 12) | 224) + String.fromCharCode(((c1 >> 6) & 63) | 128) + String.fromCharCode((c1 & 63) | 128); + } + if (enc !== null) { + if (end > start) { + utftext += string.slice(start, end); + } + utftext += enc; + start = end = n + 1; + } + } + + if (end > start) { + utftext += string.slice(start, stringl); + } + + return utftext; +} diff --git a/homework7/project_express/node_modules/std/waitFor.js b/homework7/project_express/node_modules/std/waitFor.js new file mode 100644 index 0000000..df8a1b2 --- /dev/null +++ b/homework7/project_express/node_modules/std/waitFor.js @@ -0,0 +1,13 @@ +module.exports = function waitFor(num, callback) { + var seenError + return function(err, res) { + if (num == 0) { return log.warn("waitFor was called more than the expected number of times") } + if (seenError) { return } + if (err) { + seenError = true + return callback(err) + } + num -= 1 + if (num == 0) { callback(null) } + } +} diff --git a/homework7/project_express/node_modules/std/xhr.js b/homework7/project_express/node_modules/std/xhr.js new file mode 100644 index 0000000..21f2aec --- /dev/null +++ b/homework7/project_express/node_modules/std/xhr.js @@ -0,0 +1,89 @@ +var curry = require('./curry'), + map = require('./map'), + each = require('./each'), + json = require('./json') + +module.exports = { + request: request, + get: curry(request, 'get'), + post: curry(request, 'post'), + jsonGet: curry(sendJSON, 'get'), + jsonPost: curry(sendJSON, 'post') +} + +var XHR = window.XMLHttpRequest || function() { return new ActiveXObject("Msxml2.XMLHTTP"); } + +var onBeforeUnloadFired = false +function onBeforeUnload() { + onBeforeUnloadFired = true + setTimeout(function(){ onBeforeUnloadFired = false }, 100) +} + +if (window.addEventListener) { window.addEventListener('beforeunload', onBeforeUnload, false) } +else { window.attachEvent('onbeforeunload', onBeforeUnload) } + +function request(method, url, params, callback, headers, opts) { + var xhr = new XHR() + method = method.toUpperCase() + headers = headers || {} + opts = opts || {} + xhr.onreadystatechange = function() { + var err, result + try { + if (xhr.readyState != 4) { return } + if (onBeforeUnloadFired) { return } + var text = xhr.responseText, + isJson = xhr.getResponseHeader('Content-Type') == 'application/json' + if (xhr.status == 200 || xhr.status == 204) { + result = isJson ? json.parse(text) : text + } else { + try { err = isJson ? json.parse(text) : new Error(text) } + catch (e) { err = new Error(text) } + } + } catch(e) { + err = e + } + if (err || typeof result != undefined) { + _abortXHR(xhr) + callback(err, result) + } + } + + var uriEncode = (opts.encode === false + ? function(params) { return map(params, function(val, key) { return key+'='+val }).join('&') } + : function(params) { return map(params, function(val, key) { return encodeURIComponent(key)+'='+encodeURIComponent(val) }).join('&') }) + + var data = '' + if (method == 'GET') { + var queryParams = uriEncode(params) + url += (url.indexOf('?') == -1 && queryParams ? '?' : '') + queryParams + } else if (method == 'POST') { + var contentType = headers['Content-Type'] + if (!contentType) { + contentType = headers['Content-Type'] = 'application/x-www-form-urlencoded' + } + if (contentType == 'application/x-www-form-urlencoded') { + data = uriEncode(params) + } else if (contentType == 'application/json') { + data = json.stringify(params) + } + } + xhr.open(method, url, true) + each(headers, function(val, key) { xhr.setRequestHeader(key, val) }) + xhr.send(data) +} + +function sendJSON(method, url, params, callback) { + return request(method, url, params, callback, { 'Content-Type':'application/json' }) +} + +function _abortXHR(xhr) { + try { + if('onload' in xhr) { + xhr.onload = xhr.onerror = xhr.ontimeout = null; + } else if('onreadystatechange' in xhr) { + xhr.onreadystatechange = null; + } + if(xhr.abort) { xhr.abort(); } + } catch(e) {} +} diff --git a/homework7/project_express/node_modules/supports-color/browser.js b/homework7/project_express/node_modules/supports-color/browser.js new file mode 100644 index 0000000..62afa3a --- /dev/null +++ b/homework7/project_express/node_modules/supports-color/browser.js @@ -0,0 +1,5 @@ +'use strict'; +module.exports = { + stdout: false, + stderr: false +}; diff --git a/homework7/project_express/node_modules/supports-color/index.js b/homework7/project_express/node_modules/supports-color/index.js new file mode 100644 index 0000000..1704131 --- /dev/null +++ b/homework7/project_express/node_modules/supports-color/index.js @@ -0,0 +1,131 @@ +'use strict'; +const os = require('os'); +const hasFlag = require('has-flag'); + +const env = process.env; + +let forceColor; +if (hasFlag('no-color') || + hasFlag('no-colors') || + hasFlag('color=false')) { + forceColor = false; +} else if (hasFlag('color') || + hasFlag('colors') || + hasFlag('color=true') || + hasFlag('color=always')) { + forceColor = true; +} +if ('FORCE_COLOR' in env) { + forceColor = env.FORCE_COLOR.length === 0 || parseInt(env.FORCE_COLOR, 10) !== 0; +} + +function translateLevel(level) { + if (level === 0) { + return false; + } + + return { + level, + hasBasic: true, + has256: level >= 2, + has16m: level >= 3 + }; +} + +function supportsColor(stream) { + if (forceColor === false) { + return 0; + } + + if (hasFlag('color=16m') || + hasFlag('color=full') || + hasFlag('color=truecolor')) { + return 3; + } + + if (hasFlag('color=256')) { + return 2; + } + + if (stream && !stream.isTTY && forceColor !== true) { + return 0; + } + + const min = forceColor ? 1 : 0; + + if (process.platform === 'win32') { + // Node.js 7.5.0 is the first version of Node.js to include a patch to + // libuv that enables 256 color output on Windows. Anything earlier and it + // won't work. However, here we target Node.js 8 at minimum as it is an LTS + // release, and Node.js 7 is not. Windows 10 build 10586 is the first Windows + // release that supports 256 colors. Windows 10 build 14931 is the first release + // that supports 16m/TrueColor. + const osRelease = os.release().split('.'); + if ( + Number(process.versions.node.split('.')[0]) >= 8 && + Number(osRelease[0]) >= 10 && + Number(osRelease[2]) >= 10586 + ) { + return Number(osRelease[2]) >= 14931 ? 3 : 2; + } + + return 1; + } + + if ('CI' in env) { + if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env) || env.CI_NAME === 'codeship') { + return 1; + } + + return min; + } + + if ('TEAMCITY_VERSION' in env) { + return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0; + } + + if (env.COLORTERM === 'truecolor') { + return 3; + } + + if ('TERM_PROGRAM' in env) { + const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10); + + switch (env.TERM_PROGRAM) { + case 'iTerm.app': + return version >= 3 ? 3 : 2; + case 'Apple_Terminal': + return 2; + // No default + } + } + + if (/-256(color)?$/i.test(env.TERM)) { + return 2; + } + + if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) { + return 1; + } + + if ('COLORTERM' in env) { + return 1; + } + + if (env.TERM === 'dumb') { + return min; + } + + return min; +} + +function getSupportLevel(stream) { + const level = supportsColor(stream); + return translateLevel(level); +} + +module.exports = { + supportsColor: getSupportLevel, + stdout: getSupportLevel(process.stdout), + stderr: getSupportLevel(process.stderr) +}; diff --git a/homework7/project_express/node_modules/supports-color/license b/homework7/project_express/node_modules/supports-color/license new file mode 100644 index 0000000..e7af2f7 --- /dev/null +++ b/homework7/project_express/node_modules/supports-color/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +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/homework7/project_express/node_modules/supports-color/package.json b/homework7/project_express/node_modules/supports-color/package.json new file mode 100644 index 0000000..ad199f5 --- /dev/null +++ b/homework7/project_express/node_modules/supports-color/package.json @@ -0,0 +1,53 @@ +{ + "name": "supports-color", + "version": "5.5.0", + "description": "Detect whether a terminal supports color", + "license": "MIT", + "repository": "chalk/supports-color", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=4" + }, + "scripts": { + "test": "xo && ava" + }, + "files": [ + "index.js", + "browser.js" + ], + "keywords": [ + "color", + "colour", + "colors", + "terminal", + "console", + "cli", + "ansi", + "styles", + "tty", + "rgb", + "256", + "shell", + "xterm", + "command-line", + "support", + "supports", + "capability", + "detect", + "truecolor", + "16m" + ], + "dependencies": { + "has-flag": "^3.0.0" + }, + "devDependencies": { + "ava": "^0.25.0", + "import-fresh": "^2.0.0", + "xo": "^0.20.0" + }, + "browser": "browser.js" +} diff --git a/homework7/project_express/node_modules/supports-color/readme.md b/homework7/project_express/node_modules/supports-color/readme.md new file mode 100644 index 0000000..f6e4019 --- /dev/null +++ b/homework7/project_express/node_modules/supports-color/readme.md @@ -0,0 +1,66 @@ +# supports-color [![Build Status](https://travis-ci.org/chalk/supports-color.svg?branch=master)](https://travis-ci.org/chalk/supports-color) + +> Detect whether a terminal supports color + + +## Install + +``` +$ npm install supports-color +``` + + +## Usage + +```js +const supportsColor = require('supports-color'); + +if (supportsColor.stdout) { + console.log('Terminal stdout supports color'); +} + +if (supportsColor.stdout.has256) { + console.log('Terminal stdout supports 256 colors'); +} + +if (supportsColor.stderr.has16m) { + console.log('Terminal stderr supports 16 million colors (truecolor)'); +} +``` + + +## API + +Returns an `Object` with a `stdout` and `stderr` property for testing either streams. Each property is an `Object`, or `false` if color is not supported. + +The `stdout`/`stderr` objects specifies a level of support for color through a `.level` property and a corresponding flag: + +- `.level = 1` and `.hasBasic = true`: Basic color support (16 colors) +- `.level = 2` and `.has256 = true`: 256 color support +- `.level = 3` and `.has16m = true`: Truecolor support (16 million colors) + + +## Info + +It obeys the `--color` and `--no-color` CLI flags. + +Can be overridden by the user with the flags `--color` and `--no-color`. For situations where using `--color` is not possible, add the environment variable `FORCE_COLOR=1` to forcefully enable color or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks. + +Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively. + + +## Related + +- [supports-color-cli](https://github.com/chalk/supports-color-cli) - CLI for this module +- [chalk](https://github.com/chalk/chalk) - Terminal string styling done right + + +## Maintainers + +- [Sindre Sorhus](https://github.com/sindresorhus) +- [Josh Junon](https://github.com/qix-) + + +## License + +MIT diff --git a/homework7/project_express/node_modules/to-regex-range/LICENSE b/homework7/project_express/node_modules/to-regex-range/LICENSE new file mode 100644 index 0000000..7cccaf9 --- /dev/null +++ b/homework7/project_express/node_modules/to-regex-range/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015-present, Jon Schlinkert. + +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/homework7/project_express/node_modules/to-regex-range/README.md b/homework7/project_express/node_modules/to-regex-range/README.md new file mode 100644 index 0000000..38887da --- /dev/null +++ b/homework7/project_express/node_modules/to-regex-range/README.md @@ -0,0 +1,305 @@ +# to-regex-range [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=W8YFZ425KND68) [![NPM version](https://img.shields.io/npm/v/to-regex-range.svg?style=flat)](https://www.npmjs.com/package/to-regex-range) [![NPM monthly downloads](https://img.shields.io/npm/dm/to-regex-range.svg?style=flat)](https://npmjs.org/package/to-regex-range) [![NPM total downloads](https://img.shields.io/npm/dt/to-regex-range.svg?style=flat)](https://npmjs.org/package/to-regex-range) [![Linux Build Status](https://img.shields.io/travis/micromatch/to-regex-range.svg?style=flat&label=Travis)](https://travis-ci.org/micromatch/to-regex-range) + +> Pass two numbers, get a regex-compatible source string for matching ranges. Validated against more than 2.78 million test assertions. + +Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install --save to-regex-range +``` + +
+What does this do? + +
+ +This libary generates the `source` string to be passed to `new RegExp()` for matching a range of numbers. + +**Example** + +```js +const toRegexRange = require('to-regex-range'); +const regex = new RegExp(toRegexRange('15', '95')); +``` + +A string is returned so that you can do whatever you need with it before passing it to `new RegExp()` (like adding `^` or `$` boundaries, defining flags, or combining it another string). + +
+ +
+ +
+Why use this library? + +
+ +### Convenience + +Creating regular expressions for matching numbers gets deceptively complicated pretty fast. + +For example, let's say you need a validation regex for matching part of a user-id, postal code, social security number, tax id, etc: + +* regex for matching `1` => `/1/` (easy enough) +* regex for matching `1` through `5` => `/[1-5]/` (not bad...) +* regex for matching `1` or `5` => `/(1|5)/` (still easy...) +* regex for matching `1` through `50` => `/([1-9]|[1-4][0-9]|50)/` (uh-oh...) +* regex for matching `1` through `55` => `/([1-9]|[1-4][0-9]|5[0-5])/` (no prob, I can do this...) +* regex for matching `1` through `555` => `/([1-9]|[1-9][0-9]|[1-4][0-9]{2}|5[0-4][0-9]|55[0-5])/` (maybe not...) +* regex for matching `0001` through `5555` => `/(0{3}[1-9]|0{2}[1-9][0-9]|0[1-9][0-9]{2}|[1-4][0-9]{3}|5[0-4][0-9]{2}|55[0-4][0-9]|555[0-5])/` (okay, I get the point!) + +The numbers are contrived, but they're also really basic. In the real world you might need to generate a regex on-the-fly for validation. + +**Learn more** + +If you're interested in learning more about [character classes](http://www.regular-expressions.info/charclass.html) and other regex features, I personally have always found [regular-expressions.info](http://www.regular-expressions.info/charclass.html) to be pretty useful. + +### Heavily tested + +As of April 07, 2019, this library runs [>1m test assertions](./test/test.js) against generated regex-ranges to provide brute-force verification that results are correct. + +Tests run in ~280ms on my MacBook Pro, 2.5 GHz Intel Core i7. + +### Optimized + +Generated regular expressions are optimized: + +* duplicate sequences and character classes are reduced using quantifiers +* smart enough to use `?` conditionals when number(s) or range(s) can be positive or negative +* uses fragment caching to avoid processing the same exact string more than once + +
+ +
+ +## Usage + +Add this library to your javascript application with the following line of code + +```js +const toRegexRange = require('to-regex-range'); +``` + +The main export is a function that takes two integers: the `min` value and `max` value (formatted as strings or numbers). + +```js +const source = toRegexRange('15', '95'); +//=> 1[5-9]|[2-8][0-9]|9[0-5] + +const regex = new RegExp(`^${source}$`); +console.log(regex.test('14')); //=> false +console.log(regex.test('50')); //=> true +console.log(regex.test('94')); //=> true +console.log(regex.test('96')); //=> false +``` + +## Options + +### options.capture + +**Type**: `boolean` + +**Deafault**: `undefined` + +Wrap the returned value in parentheses when there is more than one regex condition. Useful when you're dynamically generating ranges. + +```js +console.log(toRegexRange('-10', '10')); +//=> -[1-9]|-?10|[0-9] + +console.log(toRegexRange('-10', '10', { capture: true })); +//=> (-[1-9]|-?10|[0-9]) +``` + +### options.shorthand + +**Type**: `boolean` + +**Deafault**: `undefined` + +Use the regex shorthand for `[0-9]`: + +```js +console.log(toRegexRange('0', '999999')); +//=> [0-9]|[1-9][0-9]{1,5} + +console.log(toRegexRange('0', '999999', { shorthand: true })); +//=> \d|[1-9]\d{1,5} +``` + +### options.relaxZeros + +**Type**: `boolean` + +**Default**: `true` + +This option relaxes matching for leading zeros when when ranges are zero-padded. + +```js +const source = toRegexRange('-0010', '0010'); +const regex = new RegExp(`^${source}$`); +console.log(regex.test('-10')); //=> true +console.log(regex.test('-010')); //=> true +console.log(regex.test('-0010')); //=> true +console.log(regex.test('10')); //=> true +console.log(regex.test('010')); //=> true +console.log(regex.test('0010')); //=> true +``` + +When `relaxZeros` is false, matching is strict: + +```js +const source = toRegexRange('-0010', '0010', { relaxZeros: false }); +const regex = new RegExp(`^${source}$`); +console.log(regex.test('-10')); //=> false +console.log(regex.test('-010')); //=> false +console.log(regex.test('-0010')); //=> true +console.log(regex.test('10')); //=> false +console.log(regex.test('010')); //=> false +console.log(regex.test('0010')); //=> true +``` + +## Examples + +| **Range** | **Result** | **Compile time** | +| --- | --- | --- | +| `toRegexRange(-10, 10)` | `-[1-9]\|-?10\|[0-9]` | _132μs_ | +| `toRegexRange(-100, -10)` | `-1[0-9]\|-[2-9][0-9]\|-100` | _50μs_ | +| `toRegexRange(-100, 100)` | `-[1-9]\|-?[1-9][0-9]\|-?100\|[0-9]` | _42μs_ | +| `toRegexRange(001, 100)` | `0{0,2}[1-9]\|0?[1-9][0-9]\|100` | _109μs_ | +| `toRegexRange(001, 555)` | `0{0,2}[1-9]\|0?[1-9][0-9]\|[1-4][0-9]{2}\|5[0-4][0-9]\|55[0-5]` | _51μs_ | +| `toRegexRange(0010, 1000)` | `0{0,2}1[0-9]\|0{0,2}[2-9][0-9]\|0?[1-9][0-9]{2}\|1000` | _31μs_ | +| `toRegexRange(1, 50)` | `[1-9]\|[1-4][0-9]\|50` | _24μs_ | +| `toRegexRange(1, 55)` | `[1-9]\|[1-4][0-9]\|5[0-5]` | _23μs_ | +| `toRegexRange(1, 555)` | `[1-9]\|[1-9][0-9]\|[1-4][0-9]{2}\|5[0-4][0-9]\|55[0-5]` | _30μs_ | +| `toRegexRange(1, 5555)` | `[1-9]\|[1-9][0-9]{1,2}\|[1-4][0-9]{3}\|5[0-4][0-9]{2}\|55[0-4][0-9]\|555[0-5]` | _43μs_ | +| `toRegexRange(111, 555)` | `11[1-9]\|1[2-9][0-9]\|[2-4][0-9]{2}\|5[0-4][0-9]\|55[0-5]` | _38μs_ | +| `toRegexRange(29, 51)` | `29\|[34][0-9]\|5[01]` | _24μs_ | +| `toRegexRange(31, 877)` | `3[1-9]\|[4-9][0-9]\|[1-7][0-9]{2}\|8[0-6][0-9]\|87[0-7]` | _32μs_ | +| `toRegexRange(5, 5)` | `5` | _8μs_ | +| `toRegexRange(5, 6)` | `5\|6` | _11μs_ | +| `toRegexRange(1, 2)` | `1\|2` | _6μs_ | +| `toRegexRange(1, 5)` | `[1-5]` | _15μs_ | +| `toRegexRange(1, 10)` | `[1-9]\|10` | _22μs_ | +| `toRegexRange(1, 100)` | `[1-9]\|[1-9][0-9]\|100` | _25μs_ | +| `toRegexRange(1, 1000)` | `[1-9]\|[1-9][0-9]{1,2}\|1000` | _31μs_ | +| `toRegexRange(1, 10000)` | `[1-9]\|[1-9][0-9]{1,3}\|10000` | _34μs_ | +| `toRegexRange(1, 100000)` | `[1-9]\|[1-9][0-9]{1,4}\|100000` | _36μs_ | +| `toRegexRange(1, 1000000)` | `[1-9]\|[1-9][0-9]{1,5}\|1000000` | _42μs_ | +| `toRegexRange(1, 10000000)` | `[1-9]\|[1-9][0-9]{1,6}\|10000000` | _42μs_ | + +## Heads up! + +**Order of arguments** + +When the `min` is larger than the `max`, values will be flipped to create a valid range: + +```js +toRegexRange('51', '29'); +``` + +Is effectively flipped to: + +```js +toRegexRange('29', '51'); +//=> 29|[3-4][0-9]|5[0-1] +``` + +**Steps / increments** + +This library does not support steps (increments). A pr to add support would be welcome. + +## History + +### v2.0.0 - 2017-04-21 + +**New features** + +Adds support for zero-padding! + +### v1.0.0 + +**Optimizations** + +Repeating ranges are now grouped using quantifiers. rocessing time is roughly the same, but the generated regex is much smaller, which should result in faster matching. + +## Attribution + +Inspired by the python library [range-regex](https://github.com/dimka665/range-regex). + +## About + +
+Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). + +
+ +
+Running Tests + +Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: + +```sh +$ npm install && npm test +``` + +
+ +
+Building docs + +_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ + +To generate the readme, run the following command: + +```sh +$ npm install -g verbose/verb#dev verb-generate-readme && verb +``` + +
+ +### Related projects + +You might also be interested in these projects: + +* [expand-range](https://www.npmjs.com/package/expand-range): Fast, bash-like range expansion. Expand a range of numbers or letters, uppercase or lowercase. Used… [more](https://github.com/jonschlinkert/expand-range) | [homepage](https://github.com/jonschlinkert/expand-range "Fast, bash-like range expansion. Expand a range of numbers or letters, uppercase or lowercase. Used by micromatch.") +* [fill-range](https://www.npmjs.com/package/fill-range): Fill in a range of numbers or letters, optionally passing an increment or `step` to… [more](https://github.com/jonschlinkert/fill-range) | [homepage](https://github.com/jonschlinkert/fill-range "Fill in a range of numbers or letters, optionally passing an increment or `step` to use, or create a regex-compatible range with `options.toRegex`") +* [micromatch](https://www.npmjs.com/package/micromatch): Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch. | [homepage](https://github.com/micromatch/micromatch "Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch.") +* [repeat-element](https://www.npmjs.com/package/repeat-element): Create an array by repeating the given value n times. | [homepage](https://github.com/jonschlinkert/repeat-element "Create an array by repeating the given value n times.") +* [repeat-string](https://www.npmjs.com/package/repeat-string): Repeat the given string n times. Fastest implementation for repeating a string. | [homepage](https://github.com/jonschlinkert/repeat-string "Repeat the given string n times. Fastest implementation for repeating a string.") + +### Contributors + +| **Commits** | **Contributor** | +| --- | --- | +| 63 | [jonschlinkert](https://github.com/jonschlinkert) | +| 3 | [doowb](https://github.com/doowb) | +| 2 | [realityking](https://github.com/realityking) | + +### Author + +**Jon Schlinkert** + +* [GitHub Profile](https://github.com/jonschlinkert) +* [Twitter Profile](https://twitter.com/jonschlinkert) +* [LinkedIn Profile](https://linkedin.com/in/jonschlinkert) + +Please consider supporting me on Patreon, or [start your own Patreon page](https://patreon.com/invite/bxpbvm)! + + + + + +### License + +Copyright © 2019, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT License](LICENSE). + +*** + +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.8.0, on April 07, 2019._ \ No newline at end of file diff --git a/homework7/project_express/node_modules/to-regex-range/index.js b/homework7/project_express/node_modules/to-regex-range/index.js new file mode 100644 index 0000000..77fbace --- /dev/null +++ b/homework7/project_express/node_modules/to-regex-range/index.js @@ -0,0 +1,288 @@ +/*! + * to-regex-range + * + * Copyright (c) 2015-present, Jon Schlinkert. + * Released under the MIT License. + */ + +'use strict'; + +const isNumber = require('is-number'); + +const toRegexRange = (min, max, options) => { + if (isNumber(min) === false) { + throw new TypeError('toRegexRange: expected the first argument to be a number'); + } + + if (max === void 0 || min === max) { + return String(min); + } + + if (isNumber(max) === false) { + throw new TypeError('toRegexRange: expected the second argument to be a number.'); + } + + let opts = { relaxZeros: true, ...options }; + if (typeof opts.strictZeros === 'boolean') { + opts.relaxZeros = opts.strictZeros === false; + } + + let relax = String(opts.relaxZeros); + let shorthand = String(opts.shorthand); + let capture = String(opts.capture); + let wrap = String(opts.wrap); + let cacheKey = min + ':' + max + '=' + relax + shorthand + capture + wrap; + + if (toRegexRange.cache.hasOwnProperty(cacheKey)) { + return toRegexRange.cache[cacheKey].result; + } + + let a = Math.min(min, max); + let b = Math.max(min, max); + + if (Math.abs(a - b) === 1) { + let result = min + '|' + max; + if (opts.capture) { + return `(${result})`; + } + if (opts.wrap === false) { + return result; + } + return `(?:${result})`; + } + + let isPadded = hasPadding(min) || hasPadding(max); + let state = { min, max, a, b }; + let positives = []; + let negatives = []; + + if (isPadded) { + state.isPadded = isPadded; + state.maxLen = String(state.max).length; + } + + if (a < 0) { + let newMin = b < 0 ? Math.abs(b) : 1; + negatives = splitToPatterns(newMin, Math.abs(a), state, opts); + a = state.a = 0; + } + + if (b >= 0) { + positives = splitToPatterns(a, b, state, opts); + } + + state.negatives = negatives; + state.positives = positives; + state.result = collatePatterns(negatives, positives, opts); + + if (opts.capture === true) { + state.result = `(${state.result})`; + } else if (opts.wrap !== false && (positives.length + negatives.length) > 1) { + state.result = `(?:${state.result})`; + } + + toRegexRange.cache[cacheKey] = state; + return state.result; +}; + +function collatePatterns(neg, pos, options) { + let onlyNegative = filterPatterns(neg, pos, '-', false, options) || []; + let onlyPositive = filterPatterns(pos, neg, '', false, options) || []; + let intersected = filterPatterns(neg, pos, '-?', true, options) || []; + let subpatterns = onlyNegative.concat(intersected).concat(onlyPositive); + return subpatterns.join('|'); +} + +function splitToRanges(min, max) { + let nines = 1; + let zeros = 1; + + let stop = countNines(min, nines); + let stops = new Set([max]); + + while (min <= stop && stop <= max) { + stops.add(stop); + nines += 1; + stop = countNines(min, nines); + } + + stop = countZeros(max + 1, zeros) - 1; + + while (min < stop && stop <= max) { + stops.add(stop); + zeros += 1; + stop = countZeros(max + 1, zeros) - 1; + } + + stops = [...stops]; + stops.sort(compare); + return stops; +} + +/** + * Convert a range to a regex pattern + * @param {Number} `start` + * @param {Number} `stop` + * @return {String} + */ + +function rangeToPattern(start, stop, options) { + if (start === stop) { + return { pattern: start, count: [], digits: 0 }; + } + + let zipped = zip(start, stop); + let digits = zipped.length; + let pattern = ''; + let count = 0; + + for (let i = 0; i < digits; i++) { + let [startDigit, stopDigit] = zipped[i]; + + if (startDigit === stopDigit) { + pattern += startDigit; + + } else if (startDigit !== '0' || stopDigit !== '9') { + pattern += toCharacterClass(startDigit, stopDigit, options); + + } else { + count++; + } + } + + if (count) { + pattern += options.shorthand === true ? '\\d' : '[0-9]'; + } + + return { pattern, count: [count], digits }; +} + +function splitToPatterns(min, max, tok, options) { + let ranges = splitToRanges(min, max); + let tokens = []; + let start = min; + let prev; + + for (let i = 0; i < ranges.length; i++) { + let max = ranges[i]; + let obj = rangeToPattern(String(start), String(max), options); + let zeros = ''; + + if (!tok.isPadded && prev && prev.pattern === obj.pattern) { + if (prev.count.length > 1) { + prev.count.pop(); + } + + prev.count.push(obj.count[0]); + prev.string = prev.pattern + toQuantifier(prev.count); + start = max + 1; + continue; + } + + if (tok.isPadded) { + zeros = padZeros(max, tok, options); + } + + obj.string = zeros + obj.pattern + toQuantifier(obj.count); + tokens.push(obj); + start = max + 1; + prev = obj; + } + + return tokens; +} + +function filterPatterns(arr, comparison, prefix, intersection, options) { + let result = []; + + for (let ele of arr) { + let { string } = ele; + + // only push if _both_ are negative... + if (!intersection && !contains(comparison, 'string', string)) { + result.push(prefix + string); + } + + // or _both_ are positive + if (intersection && contains(comparison, 'string', string)) { + result.push(prefix + string); + } + } + return result; +} + +/** + * Zip strings + */ + +function zip(a, b) { + let arr = []; + for (let i = 0; i < a.length; i++) arr.push([a[i], b[i]]); + return arr; +} + +function compare(a, b) { + return a > b ? 1 : b > a ? -1 : 0; +} + +function contains(arr, key, val) { + return arr.some(ele => ele[key] === val); +} + +function countNines(min, len) { + return Number(String(min).slice(0, -len) + '9'.repeat(len)); +} + +function countZeros(integer, zeros) { + return integer - (integer % Math.pow(10, zeros)); +} + +function toQuantifier(digits) { + let [start = 0, stop = ''] = digits; + if (stop || start > 1) { + return `{${start + (stop ? ',' + stop : '')}}`; + } + return ''; +} + +function toCharacterClass(a, b, options) { + return `[${a}${(b - a === 1) ? '' : '-'}${b}]`; +} + +function hasPadding(str) { + return /^-?(0+)\d/.test(str); +} + +function padZeros(value, tok, options) { + if (!tok.isPadded) { + return value; + } + + let diff = Math.abs(tok.maxLen - String(value).length); + let relax = options.relaxZeros !== false; + + switch (diff) { + case 0: + return ''; + case 1: + return relax ? '0?' : '0'; + case 2: + return relax ? '0{0,2}' : '00'; + default: { + return relax ? `0{0,${diff}}` : `0{${diff}}`; + } + } +} + +/** + * Cache + */ + +toRegexRange.cache = {}; +toRegexRange.clearCache = () => (toRegexRange.cache = {}); + +/** + * Expose `toRegexRange` + */ + +module.exports = toRegexRange; diff --git a/homework7/project_express/node_modules/to-regex-range/package.json b/homework7/project_express/node_modules/to-regex-range/package.json new file mode 100644 index 0000000..4ef194f --- /dev/null +++ b/homework7/project_express/node_modules/to-regex-range/package.json @@ -0,0 +1,88 @@ +{ + "name": "to-regex-range", + "description": "Pass two numbers, get a regex-compatible source string for matching ranges. Validated against more than 2.78 million test assertions.", + "version": "5.0.1", + "homepage": "https://github.com/micromatch/to-regex-range", + "author": "Jon Schlinkert (https://github.com/jonschlinkert)", + "contributors": [ + "Jon Schlinkert (http://twitter.com/jonschlinkert)", + "Rouven Weßling (www.rouvenwessling.de)" + ], + "repository": "micromatch/to-regex-range", + "bugs": { + "url": "https://github.com/micromatch/to-regex-range/issues" + }, + "license": "MIT", + "files": [ + "index.js" + ], + "main": "index.js", + "engines": { + "node": ">=8.0" + }, + "scripts": { + "test": "mocha" + }, + "dependencies": { + "is-number": "^7.0.0" + }, + "devDependencies": { + "fill-range": "^6.0.0", + "gulp-format-md": "^2.0.0", + "mocha": "^6.0.2", + "text-table": "^0.2.0", + "time-diff": "^0.3.1" + }, + "keywords": [ + "bash", + "date", + "expand", + "expansion", + "expression", + "glob", + "match", + "match date", + "match number", + "match numbers", + "match year", + "matches", + "matching", + "number", + "numbers", + "numerical", + "range", + "ranges", + "regex", + "regexp", + "regular", + "regular expression", + "sequence" + ], + "verb": { + "layout": "default", + "toc": false, + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "lint": { + "reflinks": true + }, + "helpers": { + "examples": { + "displayName": "examples" + } + }, + "related": { + "list": [ + "expand-range", + "fill-range", + "micromatch", + "repeat-element", + "repeat-string" + ] + } + } +} diff --git a/homework7/project_express/node_modules/toidentifier/LICENSE b/homework7/project_express/node_modules/toidentifier/LICENSE new file mode 100644 index 0000000..de22d15 --- /dev/null +++ b/homework7/project_express/node_modules/toidentifier/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Douglas Christopher Wilson + +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/homework7/project_express/node_modules/toidentifier/README.md b/homework7/project_express/node_modules/toidentifier/README.md new file mode 100644 index 0000000..7c8794e --- /dev/null +++ b/homework7/project_express/node_modules/toidentifier/README.md @@ -0,0 +1,61 @@ +# toidentifier + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][codecov-image]][codecov-url] + +> Convert a string of words to a JavaScript identifier + +## Install + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```bash +$ npm install toidentifier +``` + +## Example + +```js +var toIdentifier = require('toidentifier') + +console.log(toIdentifier('Bad Request')) +// => "BadRequest" +``` + +## API + +This CommonJS module exports a single default function: `toIdentifier`. + +### toIdentifier(string) + +Given a string as the argument, it will be transformed according to +the following rules and the new string will be returned: + +1. Split into words separated by space characters (`0x20`). +2. Upper case the first character of each word. +3. Join the words together with no separator. +4. Remove all non-word (`[0-9a-z_]`) characters. + +## License + +[MIT](LICENSE) + +[codecov-image]: https://img.shields.io/codecov/c/github/component/toidentifier.svg +[codecov-url]: https://codecov.io/gh/component/toidentifier +[downloads-image]: https://img.shields.io/npm/dm/toidentifier.svg +[downloads-url]: https://npmjs.org/package/toidentifier +[npm-image]: https://img.shields.io/npm/v/toidentifier.svg +[npm-url]: https://npmjs.org/package/toidentifier +[travis-image]: https://img.shields.io/travis/component/toidentifier/master.svg +[travis-url]: https://travis-ci.org/component/toidentifier + + +## + +[npm]: https://www.npmjs.com/ + +[yarn]: https://yarnpkg.com/ diff --git a/homework7/project_express/node_modules/toidentifier/index.js b/homework7/project_express/node_modules/toidentifier/index.js new file mode 100644 index 0000000..bba5411 --- /dev/null +++ b/homework7/project_express/node_modules/toidentifier/index.js @@ -0,0 +1,30 @@ +/*! + * toidentifier + * Copyright(c) 2016 Douglas Christopher Wilson + * MIT Licensed + */ + +/** + * Module exports. + * @public + */ + +module.exports = toIdentifier + +/** + * Trasform the given string into a JavaScript identifier + * + * @param {string} str + * @returns {string} + * @public + */ + +function toIdentifier (str) { + return str + .split(' ') + .map(function (token) { + return token.slice(0, 1).toUpperCase() + token.slice(1) + }) + .join('') + .replace(/[^ _0-9a-z]/gi, '') +} diff --git a/homework7/project_express/node_modules/toidentifier/package.json b/homework7/project_express/node_modules/toidentifier/package.json new file mode 100644 index 0000000..9b5b6b1 --- /dev/null +++ b/homework7/project_express/node_modules/toidentifier/package.json @@ -0,0 +1,76 @@ +{ + "_from": "toidentifier@1.0.0", + "_id": "toidentifier@1.0.0", + "_inBundle": false, + "_integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "_location": "/toidentifier", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "toidentifier@1.0.0", + "name": "toidentifier", + "escapedName": "toidentifier", + "rawSpec": "1.0.0", + "saveSpec": null, + "fetchSpec": "1.0.0" + }, + "_requiredBy": [ + "/http-errors" + ], + "_resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "_shasum": "7e1be3470f1e77948bc43d94a3c8f4d7752ba553", + "_spec": "toidentifier@1.0.0", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\http-errors", + "author": { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + "bugs": { + "url": "https://github.com/component/toidentifier/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "Nick Baugh", + "email": "niftylettuce@gmail.com", + "url": "http://niftylettuce.com/" + } + ], + "deprecated": false, + "description": "Convert a string of words to a JavaScript identifier", + "devDependencies": { + "eslint": "4.19.1", + "eslint-config-standard": "11.0.0", + "eslint-plugin-import": "2.11.0", + "eslint-plugin-markdown": "1.0.0-beta.6", + "eslint-plugin-node": "6.0.1", + "eslint-plugin-promise": "3.7.0", + "eslint-plugin-standard": "3.1.0", + "mocha": "1.21.5", + "nyc": "11.8.0" + }, + "engines": { + "node": ">=0.6" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/component/toidentifier#readme", + "license": "MIT", + "name": "toidentifier", + "repository": { + "type": "git", + "url": "git+https://github.com/component/toidentifier.git" + }, + "scripts": { + "lint": "eslint --plugin markdown --ext js,md .", + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "nyc --reporter=html --reporter=text npm test" + }, + "version": "1.0.0" +} diff --git a/homework7/project_express/node_modules/touch/LICENSE b/homework7/project_express/node_modules/touch/LICENSE new file mode 100644 index 0000000..05eeeb8 --- /dev/null +++ b/homework7/project_express/node_modules/touch/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/homework7/project_express/node_modules/touch/README.md b/homework7/project_express/node_modules/touch/README.md new file mode 100644 index 0000000..b5a361e --- /dev/null +++ b/homework7/project_express/node_modules/touch/README.md @@ -0,0 +1,52 @@ +# node-touch + +For all your node touching needs. + +## Installing + +```bash +npm install touch +``` + +## CLI Usage: + +See `man touch` + +This package exports a binary called `nodetouch` that works mostly +like the unix builtin `touch(1)`. + +## API Usage: + +```javascript +var touch = require("touch") +``` + +Gives you the following functions: + +* `touch(filename, options, cb)` +* `touch.sync(filename, options)` +* `touch.ftouch(fd, options, cb)` +* `touch.ftouchSync(fd, options)` + +All the `options` objects are optional. + +All the async functions return a Promise. If a callback function is +provided, then it's attached to the Promise. + +## Options + +* `force` like `touch -f` Boolean +* `time` like `touch -t ` Can be a Date object, or any parseable + Date string, or epoch ms number. +* `atime` like `touch -a` Can be either a Boolean, or a Date. +* `mtime` like `touch -m` Can be either a Boolean, or a Date. +* `ref` like `touch -r ` Must be path to a file. +* `nocreate` like `touch -c` Boolean + +If neither `atime` nor `mtime` are set, then both values are set. If +one of them is set, then the other is not. + +## cli + +This package creates a `nodetouch` command line executable that works +very much like the unix builtin `touch(1)` diff --git a/homework7/project_express/node_modules/touch/bin/nodetouch.js b/homework7/project_express/node_modules/touch/bin/nodetouch.js new file mode 100644 index 0000000..f78f082 --- /dev/null +++ b/homework7/project_express/node_modules/touch/bin/nodetouch.js @@ -0,0 +1,112 @@ +#!/usr/bin/env node +const touch = require("../index.js") + +const usage = code => { + console[code ? 'error' : 'log']( + 'usage:\n' + + 'touch [-acfm] [-r file] [-t [[CC]YY]MMDDhhmm[.SS]] file ...' + ) + process.exit(code) +} + +const singleFlags = { + a: 'atime', + m: 'mtime', + c: 'nocreate', + f: 'force' +} + +const singleOpts = { + r: 'ref', + t: 'time' +} + +const files = [] +const args = process.argv.slice(2) +const options = {} +for (let i = 0; i < args.length; i++) { + const arg = args[i] + if (!arg.match(/^-/)) { + files.push(arg) + continue + } + + // expand shorthands + if (arg.charAt(1) !== '-') { + const expand = [] + for (let f = 1; f < arg.length; f++) { + const fc = arg.charAt(f) + const sf = singleFlags[fc] + const so = singleOpts[fc] + if (sf) + expand.push('--' + sf) + else if (so) { + const soslice = arg.slice(f + 1) + const soval = soslice.charAt(0) === '=' ? soslice : '=' + soslice + expand.push('--' + so + soval) + f = arg.length + } else if (arg !== '-' + fc) + expand.push('-' + fc) + } + if (expand.length) { + args.splice.apply(args, [i, 1].concat(expand)) + i-- + continue + } + } + + const argsplit = arg.split('=') + const key = argsplit.shift().replace(/^\-\-/, '') + const val = argsplit.length ? argsplit.join('=') : null + + switch (key) { + case 'time': + const timestr = val || args[++i] + // [-t [[CC]YY]MMDDhhmm[.SS]] + const parsedtime = timestr.match( + /^(([0-9]{2})?([0-9]{2}))?([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})(\.([0-9]{2}))?$/ + ) + if (!parsedtime) { + console.error('touch: out of range or illegal ' + + 'time specification: ' + + '[[CC]YY]MMDDhhmm[.SS]') + process.exit(1) + } else { + const y = +parsedtime[1] + const year = parsedtime[2] ? y + : y <= 68 ? 2000 + y + : 1900 + y + + const MM = +parsedtime[4] - 1 + const dd = +parsedtime[5] + const hh = +parsedtime[6] + const mm = +parsedtime[7] + const ss = +parsedtime[8] + + options.time = new Date(Date.UTC(year, MM, dd, hh, mm, ss)) + } + continue + + case 'ref': + options.ref = val || args[++i] + continue + + case 'mtime': + case 'nocreate': + case 'atime': + case 'force': + options[key] = true + continue + + default: + console.error('touch: illegal option -- ' + arg) + usage(1) + } +} + +if (!files.length) + usage() + +process.exitCode = 0 +Promise.all(files.map(f => touch(f, options))) + .catch(er => process.exitCode = 1) diff --git a/homework7/project_express/node_modules/touch/index.js b/homework7/project_express/node_modules/touch/index.js new file mode 100644 index 0000000..f942e42 --- /dev/null +++ b/homework7/project_express/node_modules/touch/index.js @@ -0,0 +1,224 @@ +'use strict' + +const EE = require('events').EventEmitter +const cons = require('constants') +const fs = require('fs') + +module.exports = (f, options, cb) => { + if (typeof options === 'function') + cb = options, options = {} + + const p = new Promise((res, rej) => { + new Touch(validOpts(options, f, null)) + .on('done', res).on('error', rej) + }) + + return cb ? p.then(res => cb(null, res), cb) : p +} + +module.exports.sync = module.exports.touchSync = (f, options) => + (new TouchSync(validOpts(options, f, null)), undefined) + +module.exports.ftouch = (fd, options, cb) => { + if (typeof options === 'function') + cb = options, options = {} + + const p = new Promise((res, rej) => { + new Touch(validOpts(options, null, fd)) + .on('done', res).on('error', rej) + }) + + return cb ? p.then(res => cb(null, res), cb) : p +} + +module.exports.ftouchSync = (fd, opt) => + (new TouchSync(validOpts(opt, null, fd)), undefined) + +const validOpts = (options, path, fd) => { + options = Object.create(options || {}) + options.fd = fd + options.path = path + + // {mtime: true}, {ctime: true} + // If set to something else, then treat as epoch ms value + const now = parseInt(new Date(options.time || Date.now()).getTime() / 1000) + if (!options.atime && !options.mtime) + options.atime = options.mtime = now + else { + if (true === options.atime) + options.atime = now + + if (true === options.mtime) + options.mtime = now + } + + let oflags = 0 + if (!options.force) + oflags = oflags | cons.O_RDWR + + if (!options.nocreate) + oflags = oflags | cons.O_CREAT + + options.oflags = oflags + return options +} + +class Touch extends EE { + constructor (options) { + super(options) + this.fd = options.fd + this.path = options.path + this.atime = options.atime + this.mtime = options.mtime + this.ref = options.ref + this.nocreate = !!options.nocreate + this.force = !!options.force + this.closeAfter = options.closeAfter + this.oflags = options.oflags + this.options = options + + if (typeof this.fd !== 'number') { + this.closeAfter = true + this.open() + } else + this.onopen(null, this.fd) + } + + emit (ev, data) { + // we only emit when either done or erroring + // in both cases, need to close + this.close() + return super.emit(ev, data) + } + + close () { + if (typeof this.fd === 'number' && this.closeAfter) + fs.close(this.fd, () => {}) + } + + open () { + fs.open(this.path, this.oflags, (er, fd) => this.onopen(er, fd)) + } + + onopen (er, fd) { + if (er) { + if (er.code === 'EISDIR') + this.onopen(null, null) + else if (er.code === 'ENOENT' && this.nocreate) + this.emit('done') + else + this.emit('error', er) + } else { + this.fd = fd + if (this.ref) + this.statref() + else if (!this.atime || !this.mtime) + this.fstat() + else + this.futimes() + } + } + + statref () { + fs.stat(this.ref, (er, st) => { + if (er) + this.emit('error', er) + else + this.onstatref(st) + }) + } + + onstatref (st) { + this.atime = this.atime && parseInt(st.atime.getTime()/1000, 10) + this.mtime = this.mtime && parseInt(st.mtime.getTime()/1000, 10) + if (!this.atime || !this.mtime) + this.fstat() + else + this.futimes() + } + + fstat () { + const stat = this.fd ? 'fstat' : 'stat' + const target = this.fd || this.path + fs[stat](target, (er, st) => { + if (er) + this.emit('error', er) + else + this.onfstat(st) + }) + } + + onfstat (st) { + if (typeof this.atime !== 'number') + this.atime = parseInt(st.atime.getTime()/1000, 10) + + if (typeof this.mtime !== 'number') + this.mtime = parseInt(st.mtime.getTime()/1000, 10) + + this.futimes() + } + + futimes () { + const utimes = this.fd ? 'futimes' : 'utimes' + const target = this.fd || this.path + fs[utimes](target, ''+this.atime, ''+this.mtime, er => { + if (er) + this.emit('error', er) + else + this.emit('done') + }) + } +} + +class TouchSync extends Touch { + open () { + try { + this.onopen(null, fs.openSync(this.path, this.oflags)) + } catch (er) { + this.onopen(er) + } + } + + statref () { + let threw = true + try { + this.onstatref(fs.statSync(this.ref)) + threw = false + } finally { + if (threw) + this.close() + } + } + + fstat () { + let threw = true + const stat = this.fd ? 'fstatSync' : 'statSync' + const target = this.fd || this.path + try { + this.onfstat(fs[stat](target)) + threw = false + } finally { + if (threw) + this.close() + } + } + + futimes () { + let threw = true + const utimes = this.fd ? 'futimesSync' : 'utimesSync' + const target = this.fd || this.path + try { + fs[utimes](target, this.atime, this.mtime) + threw = false + } finally { + if (threw) + this.close() + } + this.emit('done') + } + + close () { + if (typeof this.fd === 'number' && this.closeAfter) + try { fs.closeSync(this.fd) } catch (er) {} + } +} diff --git a/homework7/project_express/node_modules/touch/package.json b/homework7/project_express/node_modules/touch/package.json new file mode 100644 index 0000000..05608de --- /dev/null +++ b/homework7/project_express/node_modules/touch/package.json @@ -0,0 +1,28 @@ +{ + "author": "Isaac Z. Schlueter (http://blog.izs.me/)", + "name": "touch", + "description": "like touch(1) in node", + "version": "3.1.0", + "repository": "git://github.com/isaacs/node-touch.git", + "bin": { + "nodetouch": "./bin/nodetouch.js" + }, + "dependencies": { + "nopt": "~1.0.10" + }, + "license": "ISC", + "scripts": { + "test": "tap test/*.js --100 -J", + "preversion": "npm test", + "postversion": "npm publish", + "postpublish": "git push origin --all; git push origin --tags" + }, + "devDependencies": { + "mutate-fs": "^1.1.0", + "tap": "^10.7.0" + }, + "files": [ + "index.js", + "bin/nodetouch.js" + ] +} diff --git a/homework7/project_express/node_modules/type-is/HISTORY.md b/homework7/project_express/node_modules/type-is/HISTORY.md new file mode 100644 index 0000000..8de21f7 --- /dev/null +++ b/homework7/project_express/node_modules/type-is/HISTORY.md @@ -0,0 +1,259 @@ +1.6.18 / 2019-04-26 +=================== + + * Fix regression passing request object to `typeis.is` + +1.6.17 / 2019-04-25 +=================== + + * deps: mime-types@~2.1.24 + - Add Apple file extensions from IANA + - Add extension `.csl` to `application/vnd.citationstyles.style+xml` + - Add extension `.es` to `application/ecmascript` + - Add extension `.nq` to `application/n-quads` + - Add extension `.nt` to `application/n-triples` + - Add extension `.owl` to `application/rdf+xml` + - Add extensions `.siv` and `.sieve` to `application/sieve` + - Add extensions from IANA for `image/*` types + - Add extensions from IANA for `model/*` types + - Add extensions to HEIC image types + - Add new mime types + - Add `text/mdx` with extension `.mdx` + * perf: prevent internal `throw` on invalid type + +1.6.16 / 2018-02-16 +=================== + + * deps: mime-types@~2.1.18 + - Add `application/raml+yaml` with extension `.raml` + - Add `application/wasm` with extension `.wasm` + - Add `text/shex` with extension `.shex` + - Add extensions for JPEG-2000 images + - Add extensions from IANA for `message/*` types + - Add extension `.mjs` to `application/javascript` + - Add extension `.wadl` to `application/vnd.sun.wadl+xml` + - Add extension `.gz` to `application/gzip` + - Add glTF types and extensions + - Add new mime types + - Update extensions `.md` and `.markdown` to be `text/markdown` + - Update font MIME types + - Update `text/hjson` to registered `application/hjson` + +1.6.15 / 2017-03-31 +=================== + + * deps: mime-types@~2.1.15 + - Add new mime types + +1.6.14 / 2016-11-18 +=================== + + * deps: mime-types@~2.1.13 + - Add new mime types + +1.6.13 / 2016-05-18 +=================== + + * deps: mime-types@~2.1.11 + - Add new mime types + +1.6.12 / 2016-02-28 +=================== + + * deps: mime-types@~2.1.10 + - Add new mime types + - Fix extension of `application/dash+xml` + - Update primary extension for `audio/mp4` + +1.6.11 / 2016-01-29 +=================== + + * deps: mime-types@~2.1.9 + - Add new mime types + +1.6.10 / 2015-12-01 +=================== + + * deps: mime-types@~2.1.8 + - Add new mime types + +1.6.9 / 2015-09-27 +================== + + * deps: mime-types@~2.1.7 + - Add new mime types + +1.6.8 / 2015-09-04 +================== + + * deps: mime-types@~2.1.6 + - Add new mime types + +1.6.7 / 2015-08-20 +================== + + * Fix type error when given invalid type to match against + * deps: mime-types@~2.1.5 + - Add new mime types + +1.6.6 / 2015-07-31 +================== + + * deps: mime-types@~2.1.4 + - Add new mime types + +1.6.5 / 2015-07-16 +================== + + * deps: mime-types@~2.1.3 + - Add new mime types + +1.6.4 / 2015-07-01 +================== + + * deps: mime-types@~2.1.2 + - Add new mime types + * perf: enable strict mode + * perf: remove argument reassignment + +1.6.3 / 2015-06-08 +================== + + * deps: mime-types@~2.1.1 + - Add new mime types + * perf: reduce try block size + * perf: remove bitwise operations + +1.6.2 / 2015-05-10 +================== + + * deps: mime-types@~2.0.11 + - Add new mime types + +1.6.1 / 2015-03-13 +================== + + * deps: mime-types@~2.0.10 + - Add new mime types + +1.6.0 / 2015-02-12 +================== + + * fix false-positives in `hasBody` `Transfer-Encoding` check + * support wildcard for both type and subtype (`*/*`) + +1.5.7 / 2015-02-09 +================== + + * fix argument reassignment + * deps: mime-types@~2.0.9 + - Add new mime types + +1.5.6 / 2015-01-29 +================== + + * deps: mime-types@~2.0.8 + - Add new mime types + +1.5.5 / 2014-12-30 +================== + + * deps: mime-types@~2.0.7 + - Add new mime types + - Fix missing extensions + - Fix various invalid MIME type entries + - Remove example template MIME types + - deps: mime-db@~1.5.0 + +1.5.4 / 2014-12-10 +================== + + * deps: mime-types@~2.0.4 + - Add new mime types + - deps: mime-db@~1.3.0 + +1.5.3 / 2014-11-09 +================== + + * deps: mime-types@~2.0.3 + - Add new mime types + - deps: mime-db@~1.2.0 + +1.5.2 / 2014-09-28 +================== + + * deps: mime-types@~2.0.2 + - Add new mime types + - deps: mime-db@~1.1.0 + +1.5.1 / 2014-09-07 +================== + + * Support Node.js 0.6 + * deps: media-typer@0.3.0 + * deps: mime-types@~2.0.1 + - Support Node.js 0.6 + +1.5.0 / 2014-09-05 +================== + + * fix `hasbody` to be true for `content-length: 0` + +1.4.0 / 2014-09-02 +================== + + * update mime-types + +1.3.2 / 2014-06-24 +================== + + * use `~` range on mime-types + +1.3.1 / 2014-06-19 +================== + + * fix global variable leak + +1.3.0 / 2014-06-19 +================== + + * improve type parsing + + - invalid media type never matches + - media type not case-sensitive + - extra LWS does not affect results + +1.2.2 / 2014-06-19 +================== + + * fix behavior on unknown type argument + +1.2.1 / 2014-06-03 +================== + + * switch dependency from `mime` to `mime-types@1.0.0` + +1.2.0 / 2014-05-11 +================== + + * support suffix matching: + + - `+json` matches `application/vnd+json` + - `*/vnd+json` matches `application/vnd+json` + - `application/*+json` matches `application/vnd+json` + +1.1.0 / 2014-04-12 +================== + + * add non-array values support + * expose internal utilities: + + - `.is()` + - `.hasBody()` + - `.normalize()` + - `.match()` + +1.0.1 / 2014-03-30 +================== + + * add `multipart` as a shorthand diff --git a/homework7/project_express/node_modules/type-is/LICENSE b/homework7/project_express/node_modules/type-is/LICENSE new file mode 100644 index 0000000..386b7b6 --- /dev/null +++ b/homework7/project_express/node_modules/type-is/LICENSE @@ -0,0 +1,23 @@ +(The MIT License) + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2014-2015 Douglas Christopher Wilson + +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/homework7/project_express/node_modules/type-is/README.md b/homework7/project_express/node_modules/type-is/README.md new file mode 100644 index 0000000..b85ef8f --- /dev/null +++ b/homework7/project_express/node_modules/type-is/README.md @@ -0,0 +1,170 @@ +# type-is + +[![NPM Version][npm-version-image]][npm-url] +[![NPM Downloads][npm-downloads-image]][npm-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Infer the content-type of a request. + +### Install + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```sh +$ npm install type-is +``` + +## API + +```js +var http = require('http') +var typeis = require('type-is') + +http.createServer(function (req, res) { + var istext = typeis(req, ['text/*']) + res.end('you ' + (istext ? 'sent' : 'did not send') + ' me text') +}) +``` + +### typeis(request, types) + +Checks if the `request` is one of the `types`. If the request has no body, +even if there is a `Content-Type` header, then `null` is returned. If the +`Content-Type` header is invalid or does not matches any of the `types`, then +`false` is returned. Otherwise, a string of the type that matched is returned. + +The `request` argument is expected to be a Node.js HTTP request. The `types` +argument is an array of type strings. + +Each type in the `types` array can be one of the following: + +- A file extension name such as `json`. This name will be returned if matched. +- A mime type such as `application/json`. +- A mime type with a wildcard such as `*/*` or `*/json` or `application/*`. + The full mime type will be returned if matched. +- A suffix such as `+json`. This can be combined with a wildcard such as + `*/vnd+json` or `application/*+json`. The full mime type will be returned + if matched. + +Some examples to illustrate the inputs and returned value: + + + +```js +// req.headers.content-type = 'application/json' + +typeis(req, ['json']) // => 'json' +typeis(req, ['html', 'json']) // => 'json' +typeis(req, ['application/*']) // => 'application/json' +typeis(req, ['application/json']) // => 'application/json' + +typeis(req, ['html']) // => false +``` + +### typeis.hasBody(request) + +Returns a Boolean if the given `request` has a body, regardless of the +`Content-Type` header. + +Having a body has no relation to how large the body is (it may be 0 bytes). +This is similar to how file existence works. If a body does exist, then this +indicates that there is data to read from the Node.js request stream. + + + +```js +if (typeis.hasBody(req)) { + // read the body, since there is one + + req.on('data', function (chunk) { + // ... + }) +} +``` + +### typeis.is(mediaType, types) + +Checks if the `mediaType` is one of the `types`. If the `mediaType` is invalid +or does not matches any of the `types`, then `false` is returned. Otherwise, a +string of the type that matched is returned. + +The `mediaType` argument is expected to be a +[media type](https://tools.ietf.org/html/rfc6838) string. The `types` argument +is an array of type strings. + +Each type in the `types` array can be one of the following: + +- A file extension name such as `json`. This name will be returned if matched. +- A mime type such as `application/json`. +- A mime type with a wildcard such as `*/*` or `*/json` or `application/*`. + The full mime type will be returned if matched. +- A suffix such as `+json`. This can be combined with a wildcard such as + `*/vnd+json` or `application/*+json`. The full mime type will be returned + if matched. + +Some examples to illustrate the inputs and returned value: + + + +```js +var mediaType = 'application/json' + +typeis.is(mediaType, ['json']) // => 'json' +typeis.is(mediaType, ['html', 'json']) // => 'json' +typeis.is(mediaType, ['application/*']) // => 'application/json' +typeis.is(mediaType, ['application/json']) // => 'application/json' + +typeis.is(mediaType, ['html']) // => false +``` + +## Examples + +### Example body parser + +```js +var express = require('express') +var typeis = require('type-is') + +var app = express() + +app.use(function bodyParser (req, res, next) { + if (!typeis.hasBody(req)) { + return next() + } + + switch (typeis(req, ['urlencoded', 'json', 'multipart'])) { + case 'urlencoded': + // parse urlencoded body + throw new Error('implement urlencoded body parsing') + case 'json': + // parse json body + throw new Error('implement json body parsing') + case 'multipart': + // parse multipart body + throw new Error('implement multipart body parsing') + default: + // 415 error code + res.statusCode = 415 + res.end() + break + } +}) +``` + +## License + +[MIT](LICENSE) + +[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/type-is/master +[coveralls-url]: https://coveralls.io/r/jshttp/type-is?branch=master +[node-version-image]: https://badgen.net/npm/node/type-is +[node-version-url]: https://nodejs.org/en/download +[npm-downloads-image]: https://badgen.net/npm/dm/type-is +[npm-url]: https://npmjs.org/package/type-is +[npm-version-image]: https://badgen.net/npm/v/type-is +[travis-image]: https://badgen.net/travis/jshttp/type-is/master +[travis-url]: https://travis-ci.org/jshttp/type-is diff --git a/homework7/project_express/node_modules/type-is/index.js b/homework7/project_express/node_modules/type-is/index.js new file mode 100644 index 0000000..890ad76 --- /dev/null +++ b/homework7/project_express/node_modules/type-is/index.js @@ -0,0 +1,266 @@ +/*! + * type-is + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var typer = require('media-typer') +var mime = require('mime-types') + +/** + * Module exports. + * @public + */ + +module.exports = typeofrequest +module.exports.is = typeis +module.exports.hasBody = hasbody +module.exports.normalize = normalize +module.exports.match = mimeMatch + +/** + * Compare a `value` content-type with `types`. + * Each `type` can be an extension like `html`, + * a special shortcut like `multipart` or `urlencoded`, + * or a mime type. + * + * If no types match, `false` is returned. + * Otherwise, the first `type` that matches is returned. + * + * @param {String} value + * @param {Array} types + * @public + */ + +function typeis (value, types_) { + var i + var types = types_ + + // remove parameters and normalize + var val = tryNormalizeType(value) + + // no type or invalid + if (!val) { + return false + } + + // support flattened arguments + if (types && !Array.isArray(types)) { + types = new Array(arguments.length - 1) + for (i = 0; i < types.length; i++) { + types[i] = arguments[i + 1] + } + } + + // no types, return the content type + if (!types || !types.length) { + return val + } + + var type + for (i = 0; i < types.length; i++) { + if (mimeMatch(normalize(type = types[i]), val)) { + return type[0] === '+' || type.indexOf('*') !== -1 + ? val + : type + } + } + + // no matches + return false +} + +/** + * Check if a request has a request body. + * A request with a body __must__ either have `transfer-encoding` + * or `content-length` headers set. + * http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3 + * + * @param {Object} request + * @return {Boolean} + * @public + */ + +function hasbody (req) { + return req.headers['transfer-encoding'] !== undefined || + !isNaN(req.headers['content-length']) +} + +/** + * Check if the incoming request contains the "Content-Type" + * header field, and it contains any of the give mime `type`s. + * If there is no request body, `null` is returned. + * If there is no content type, `false` is returned. + * Otherwise, it returns the first `type` that matches. + * + * Examples: + * + * // With Content-Type: text/html; charset=utf-8 + * this.is('html'); // => 'html' + * this.is('text/html'); // => 'text/html' + * this.is('text/*', 'application/json'); // => 'text/html' + * + * // When Content-Type is application/json + * this.is('json', 'urlencoded'); // => 'json' + * this.is('application/json'); // => 'application/json' + * this.is('html', 'application/*'); // => 'application/json' + * + * this.is('html'); // => false + * + * @param {String|Array} types... + * @return {String|false|null} + * @public + */ + +function typeofrequest (req, types_) { + var types = types_ + + // no body + if (!hasbody(req)) { + return null + } + + // support flattened arguments + if (arguments.length > 2) { + types = new Array(arguments.length - 1) + for (var i = 0; i < types.length; i++) { + types[i] = arguments[i + 1] + } + } + + // request content type + var value = req.headers['content-type'] + + return typeis(value, types) +} + +/** + * Normalize a mime type. + * If it's a shorthand, expand it to a valid mime type. + * + * In general, you probably want: + * + * var type = is(req, ['urlencoded', 'json', 'multipart']); + * + * Then use the appropriate body parsers. + * These three are the most common request body types + * and are thus ensured to work. + * + * @param {String} type + * @private + */ + +function normalize (type) { + if (typeof type !== 'string') { + // invalid type + return false + } + + switch (type) { + case 'urlencoded': + return 'application/x-www-form-urlencoded' + case 'multipart': + return 'multipart/*' + } + + if (type[0] === '+') { + // "+json" -> "*/*+json" expando + return '*/*' + type + } + + return type.indexOf('/') === -1 + ? mime.lookup(type) + : type +} + +/** + * Check if `expected` mime type + * matches `actual` mime type with + * wildcard and +suffix support. + * + * @param {String} expected + * @param {String} actual + * @return {Boolean} + * @private + */ + +function mimeMatch (expected, actual) { + // invalid type + if (expected === false) { + return false + } + + // split types + var actualParts = actual.split('/') + var expectedParts = expected.split('/') + + // invalid format + if (actualParts.length !== 2 || expectedParts.length !== 2) { + return false + } + + // validate type + if (expectedParts[0] !== '*' && expectedParts[0] !== actualParts[0]) { + return false + } + + // validate suffix wildcard + if (expectedParts[1].substr(0, 2) === '*+') { + return expectedParts[1].length <= actualParts[1].length + 1 && + expectedParts[1].substr(1) === actualParts[1].substr(1 - expectedParts[1].length) + } + + // validate subtype + if (expectedParts[1] !== '*' && expectedParts[1] !== actualParts[1]) { + return false + } + + return true +} + +/** + * Normalize a type and remove parameters. + * + * @param {string} value + * @return {string} + * @private + */ + +function normalizeType (value) { + // parse the type + var type = typer.parse(value) + + // remove the parameters + type.parameters = undefined + + // reformat it + return typer.format(type) +} + +/** + * Try to normalize a type and remove parameters. + * + * @param {string} value + * @return {string} + * @private + */ + +function tryNormalizeType (value) { + if (!value) { + return null + } + + try { + return normalizeType(value) + } catch (err) { + return null + } +} diff --git a/homework7/project_express/node_modules/type-is/package.json b/homework7/project_express/node_modules/type-is/package.json new file mode 100644 index 0000000..d3b2897 --- /dev/null +++ b/homework7/project_express/node_modules/type-is/package.json @@ -0,0 +1,85 @@ +{ + "_from": "type-is@~1.6.18", + "_id": "type-is@1.6.18", + "_inBundle": false, + "_integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "_location": "/type-is", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "type-is@~1.6.18", + "name": "type-is", + "escapedName": "type-is", + "rawSpec": "~1.6.18", + "saveSpec": null, + "fetchSpec": "~1.6.18" + }, + "_requiredBy": [ + "/body-parser", + "/express" + ], + "_resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "_shasum": "4e552cd05df09467dcbc4ef739de89f2cf37c131", + "_spec": "type-is@~1.6.18", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\express", + "bugs": { + "url": "https://github.com/jshttp/type-is/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "Jonathan Ong", + "email": "me@jongleberry.com", + "url": "http://jongleberry.com" + } + ], + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "deprecated": false, + "description": "Infer the content-type of a request.", + "devDependencies": { + "eslint": "5.16.0", + "eslint-config-standard": "12.0.0", + "eslint-plugin-import": "2.17.2", + "eslint-plugin-markdown": "1.0.0", + "eslint-plugin-node": "8.0.1", + "eslint-plugin-promise": "4.1.1", + "eslint-plugin-standard": "4.0.0", + "mocha": "6.1.4", + "nyc": "14.0.0" + }, + "engines": { + "node": ">= 0.6" + }, + "files": [ + "LICENSE", + "HISTORY.md", + "index.js" + ], + "homepage": "https://github.com/jshttp/type-is#readme", + "keywords": [ + "content", + "type", + "checking" + ], + "license": "MIT", + "name": "type-is", + "repository": { + "type": "git", + "url": "git+https://github.com/jshttp/type-is.git" + }, + "scripts": { + "lint": "eslint --plugin markdown --ext js,md .", + "test": "mocha --reporter spec --check-leaks --bail test/", + "test-cov": "nyc --reporter=html --reporter=text npm test", + "test-travis": "nyc --reporter=text npm test" + }, + "version": "1.6.18" +} diff --git a/homework7/project_express/node_modules/uglify-js/.npmignore b/homework7/project_express/node_modules/uglify-js/.npmignore new file mode 100644 index 0000000..94fceeb --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/.npmignore @@ -0,0 +1,2 @@ +tmp/ +node_modules/ diff --git a/homework7/project_express/node_modules/uglify-js/LICENSE b/homework7/project_express/node_modules/uglify-js/LICENSE new file mode 100644 index 0000000..dd7706f --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/LICENSE @@ -0,0 +1,29 @@ +UglifyJS is released under the BSD license: + +Copyright 2012-2013 (c) Mihai Bazon + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. diff --git a/homework7/project_express/node_modules/uglify-js/README.md b/homework7/project_express/node_modules/uglify-js/README.md new file mode 100644 index 0000000..ce55dc3 --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/README.md @@ -0,0 +1,567 @@ +UglifyJS 2 +========== + +UglifyJS is a JavaScript parser, minifier, compressor or beautifier toolkit. + +This page documents the command line utility. For +[API and internals documentation see my website](http://lisperator.net/uglifyjs/). +There's also an +[in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox, +Chrome and probably Safari). + +Install +------- + +First make sure you have installed the latest version of [node.js](http://nodejs.org/) +(You may need to restart your computer after this step). + +From NPM for use as a command line app: + + npm install uglify-js -g + +From NPM for programmatic use: + + npm install uglify-js + +From Git: + + git clone git://github.com/mishoo/UglifyJS2.git + cd UglifyJS2 + npm link . + +Usage +----- + + uglifyjs [input files] [options] + +UglifyJS2 can take multiple input files. It's recommended that you pass the +input files first, then pass the options. UglifyJS will parse input files +in sequence and apply any compression options. The files are parsed in the +same global scope, that is, a reference from a file to some +variable/function declared in another file will be matched properly. + +If you want to read from STDIN instead, pass a single dash instead of input +files. + +The available options are: + + --source-map Specify an output file where to generate source map. + [string] + --source-map-root The path to the original source to be included in the + source map. [string] + --source-map-url The path to the source map to be added in //@ + sourceMappingURL. Defaults to the value passed with + --source-map. [string] + --in-source-map Input source map, useful if you're compressing JS that was + generated from some other original code. + --screw-ie8 Pass this flag if you don't care about full compliance with + Internet Explorer 6-8 quirks (by default UglifyJS will try + to be IE-proof). + -p, --prefix Skip prefix for original filenames that appear in source + maps. For example -p 3 will drop 3 directories from file + names and ensure they are relative paths. + -o, --output Output file (default STDOUT). + -b, --beautify Beautify output/specify output options. [string] + -m, --mangle Mangle names/pass mangler options. [string] + -r, --reserved Reserved names to exclude from mangling. + -c, --compress Enable compressor/pass compressor options. Pass options + like -c hoist_vars=false,if_return=false. Use -c with no + argument to use the default compression options. [string] + -d, --define Global definitions [string] + --comments Preserve copyright comments in the output. By default this + works like Google Closure, keeping JSDoc-style comments + that contain "@license" or "@preserve". You can optionally + pass one of the following arguments to this flag: + - "all" to keep all comments + - a valid JS regexp (needs to start with a slash) to keep + only comments that match. + Note that currently not *all* comments can be kept when + compression is on, because of dead code removal or + cascading statements into sequences. [string] + --stats Display operations run time on STDERR. [boolean] + --acorn Use Acorn for parsing. [boolean] + --spidermonkey Assume input fles are SpiderMonkey AST format (as JSON). + [boolean] + --self Build itself (UglifyJS2) as a library (implies + --wrap=UglifyJS --export-all) [boolean] + --wrap Embed everything in a big function, making the “exports” + and “global” variables available. You need to pass an + argument to this option to specify the name that your + module will take when included in, say, a browser. + [string] + --export-all Only used when --wrap, this tells UglifyJS to add code to + automatically export all globals. [boolean] + --lint Display some scope warnings [boolean] + -v, --verbose Verbose [boolean] + -V, --version Print version number and exit. [boolean] + +Specify `--output` (`-o`) to declare the output file. Otherwise the output +goes to STDOUT. + +## Source map options + +UglifyJS2 can generate a source map file, which is highly useful for +debugging your compressed JavaScript. To get a source map, pass +`--source-map output.js.map` (full path to the file where you want the +source map dumped). + +Additionally you might need `--source-map-root` to pass the URL where the +original files can be found. In case you are passing full paths to input +files to UglifyJS, you can use `--prefix` (`-p`) to specify the number of +directories to drop from the path prefix when declaring files in the source +map. + +For example: + + uglifyjs /home/doe/work/foo/src/js/file1.js \ + /home/doe/work/foo/src/js/file2.js \ + -o foo.min.js \ + --source-map foo.min.js.map \ + --source-map-root http://foo.com/src \ + -p 5 -c -m + +The above will compress and mangle `file1.js` and `file2.js`, will drop the +output in `foo.min.js` and the source map in `foo.min.js.map`. The source +mapping will refer to `http://foo.com/src/js/file1.js` and +`http://foo.com/src/js/file2.js` (in fact it will list `http://foo.com/src` +as the source map root, and the original files as `js/file1.js` and +`js/file2.js`). + +### Composed source map + +When you're compressing JS code that was output by a compiler such as +CoffeeScript, mapping to the JS code won't be too helpful. Instead, you'd +like to map back to the original code (i.e. CoffeeScript). UglifyJS has an +option to take an input source map. Assuming you have a mapping from +CoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript → +compressed JS by mapping every token in the compiled JS to its original +location. + +To use this feature you need to pass `--in-source-map +/path/to/input/source.map`. Normally the input source map should also point +to the file containing the generated JS, so if that's correct you can omit +input files from the command line. + +## Mangler options + +To enable the mangler you need to pass `--mangle` (`-m`). The following +(comma-separated) options are supported: + +- `sort` — to assign shorter names to most frequently used variables. This + saves a few hundred bytes on jQuery before gzip, but the output is + _bigger_ after gzip (and seems to happen for other libraries I tried it + on) therefore it's not enabled by default. + +- `toplevel` — mangle names declared in the toplevel scope (disabled by + default). + +- `eval` — mangle names visible in scopes where `eval` or `when` are used + (disabled by default). + +When mangling is enabled but you want to prevent certain names from being +mangled, you can declare those names with `--reserved` (`-r`) — pass a +comma-separated list of names. For example: + + uglifyjs ... -m -r '$,require,exports' + +to prevent the `require`, `exports` and `$` names from being changed. + +## Compressor options + +You need to pass `--compress` (`-c`) to enable the compressor. Optionally +you can pass a comma-separated list of options. Options are in the form +`foo=bar`, or just `foo` (the latter implies a boolean option that you want +to set `true`; it's effectively a shortcut for `foo=true`). + +- `sequences` -- join consecutive simple statements using the comma operator +- `properties` -- rewrite property access using the dot notation, for + example `foo["bar"] → foo.bar` +- `dead_code` -- remove unreachable code +- `drop_debugger` -- remove `debugger;` statements +- `unsafe` (default: false) -- apply "unsafe" transformations (discussion below) +- `conditionals` -- apply optimizations for `if`-s and conditional + expressions +- `comparisons` -- apply certain optimizations to binary nodes, for example: + `!(a <= b) → a > b` (only when `unsafe`), attempts to negate binary nodes, + e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc. +- `evaluate` -- attempt to evaluate constant expressions +- `booleans` -- various optimizations for boolean context, for example `!!a + ? b : c → a ? b : c` +- `loops` -- optimizations for `do`, `while` and `for` loops when we can + statically determine the condition +- `unused` -- drop unreferenced functions and variables +- `hoist_funs` -- hoist function declarations +- `hoist_vars` (default: false) -- hoist `var` declarations (this is `false` + by default because it seems to increase the size of the output in general) +- `if_return` -- optimizations for if/return and if/continue +- `join_vars` -- join consecutive `var` statements +- `cascade` -- small optimization for sequences, transform `x, x` into `x` + and `x = something(), x` into `x = something()` +- `warnings` -- display warnings when dropping unreachable code or unused + declarations etc. + +### The `unsafe` option + +It enables some transformations that *might* break code logic in certain +contrived cases, but should be fine for most code. You might want to try it +on your own code, it should reduce the minified size. Here's what happens +when this flag is on: + +- `new Array(1, 2, 3)` or `Array(1, 2, 3)` → `[1, 2, 3 ]` +- `new Object()` → `{}` +- `String(exp)` or `exp.toString()` → `"" + exp` +- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new` +- `typeof foo == "undefined"` → `foo === void 0` +- `void 0` → `"undefined"` (if there is a variable named "undefined" in + scope; we do it because the variable name will be mangled, typically + reduced to a single character). + +### Conditional compilation + +You can use the `--define` (`-d`) switch in order to declare global +variables that UglifyJS will assume to be constants (unless defined in +scope). For example if you pass `--define DEBUG=false` then, coupled with +dead code removal UglifyJS will discard the following from the output: + + if (DEBUG) { + console.log("debug stuff"); + } + +UglifyJS will warn about the condition being always false and about dropping +unreachable code; for now there is no option to turn off only this specific +warning, you can pass `warnings=false` to turn off *all* warnings. + +Another way of doing that is to declare your globals as constants in a +separate file and include it into the build. For example you can have a +`build/defines.js` file with the following: + + const DEBUG = false; + const PRODUCTION = true; + // etc. + +and build your code like this: + + uglifyjs build/defines.js js/foo.js js/bar.js... -c + +UglifyJS will notice the constants and, since they cannot be altered, it +will evaluate references to them to the value itself and drop unreachable +code as usual. The possible downside of this approach is that the build +will contain the `const` declarations. + + +## Beautifier options + +The code generator tries to output shortest code possible by default. In +case you want beautified output, pass `--beautify` (`-b`). Optionally you +can pass additional arguments that control the code output: + +- `beautify` (default `true`) -- whether to actually beautify the output. + Passing `-b` will set this to true, but you might need to pass `-b` even + when you want to generate minified code, in order to specify additional + arguments, so you can use `-b beautify=false` to override it. +- `indent-level` (default 4) +- `indent-start` (default 0) -- prefix all lines by that many spaces +- `quote-keys` (default `false`) -- pass `true` to quote all keys in literal + objects +- `space-colon` (default `true`) -- insert a space after the colon signs +- `ascii-only` (default `false`) -- escape Unicode characters in strings and + regexps +- `inline-script` (default `false`) -- escape the slash in occurrences of + ` 0) { + sys.error("WARN: Ignoring input files since --self was passed"); + } + files = UglifyJS.FILES; + if (!ARGS.wrap) ARGS.wrap = "UglifyJS"; + ARGS.export_all = true; +} + +var ORIG_MAP = ARGS.in_source_map; + +if (ORIG_MAP) { + ORIG_MAP = JSON.parse(fs.readFileSync(ORIG_MAP)); + if (files.length == 0) { + sys.error("INFO: Using file from the input source map: " + ORIG_MAP.file); + files = [ ORIG_MAP.file ]; + } + if (ARGS.source_map_root == null) { + ARGS.source_map_root = ORIG_MAP.sourceRoot; + } +} + +if (files.length == 0) { + files = [ "-" ]; +} + +if (files.indexOf("-") >= 0 && ARGS.source_map) { + sys.error("ERROR: Source map doesn't work with input from STDIN"); + process.exit(1); +} + +if (files.filter(function(el){ return el == "-" }).length > 1) { + sys.error("ERROR: Can read a single file from STDIN (two or more dashes specified)"); + process.exit(1); +} + +var STATS = {}; +var OUTPUT_FILE = ARGS.o; +var TOPLEVEL = null; + +var SOURCE_MAP = ARGS.source_map ? UglifyJS.SourceMap({ + file: OUTPUT_FILE, + root: ARGS.source_map_root, + orig: ORIG_MAP, +}) : null; + +OUTPUT_OPTIONS.source_map = SOURCE_MAP; + +try { + var output = UglifyJS.OutputStream(OUTPUT_OPTIONS); + var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS); +} catch(ex) { + if (ex instanceof UglifyJS.DefaultsError) { + sys.error(ex.msg); + sys.error("Supported options:"); + sys.error(sys.inspect(ex.defs)); + process.exit(1); + } +} + +async.eachLimit(files, 1, function (file, cb) { + read_whole_file(file, function (err, code) { + if (err) { + sys.error("ERROR: can't read file: " + filename); + process.exit(1); + } + if (ARGS.p != null) { + file = file.replace(/^\/+/, "").split(/\/+/).slice(ARGS.p).join("/"); + } + time_it("parse", function(){ + if (ARGS.spidermonkey) { + var program = JSON.parse(code); + if (!TOPLEVEL) TOPLEVEL = program; + else TOPLEVEL.body = TOPLEVEL.body.concat(program.body); + } + else if (ARGS.acorn) { + TOPLEVEL = acorn.parse(code, { + locations : true, + trackComments : true, + sourceFile : file, + program : TOPLEVEL + }); + } + else { + TOPLEVEL = UglifyJS.parse(code, { + filename: file, + toplevel: TOPLEVEL + }); + }; + }); + cb(); + }); +}, function () { + if (ARGS.acorn || ARGS.spidermonkey) time_it("convert_ast", function(){ + TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL); + }); + + if (ARGS.wrap) { + TOPLEVEL = TOPLEVEL.wrap_commonjs(ARGS.wrap, ARGS.export_all); + } + + if (ARGS.enclose) { + var arg_parameter_list = ARGS.enclose; + + if (!(arg_parameter_list instanceof Array)) { + arg_parameter_list = [arg_parameter_list]; + } + + TOPLEVEL = TOPLEVEL.wrap_enclose(arg_parameter_list); + } + + var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint; + + if (SCOPE_IS_NEEDED) { + time_it("scope", function(){ + TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8 }); + if (ARGS.lint) { + TOPLEVEL.scope_warnings(); + } + }); + } + + if (COMPRESS) { + time_it("squeeze", function(){ + TOPLEVEL = TOPLEVEL.transform(compressor); + }); + } + + if (SCOPE_IS_NEEDED) { + time_it("scope", function(){ + TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8 }); + if (MANGLE) { + TOPLEVEL.compute_char_frequency(MANGLE); + } + }); + } + + if (MANGLE) time_it("mangle", function(){ + TOPLEVEL.mangle_names(MANGLE); + }); + time_it("generate", function(){ + TOPLEVEL.print(output); + }); + + output = output.get(); + + if (SOURCE_MAP) { + fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8"); + output += "\n/*\n//@ sourceMappingURL=" + (ARGS.source_map_url || ARGS.source_map) + "\n*/"; + } + + if (OUTPUT_FILE) { + fs.writeFileSync(OUTPUT_FILE, output, "utf8"); + } else { + sys.print(output); + sys.error("\n"); + } + + if (ARGS.stats) { + sys.error(UglifyJS.string_template("Timing information (compressed {count} files):", { + count: files.length + })); + for (var i in STATS) if (STATS.hasOwnProperty(i)) { + sys.error(UglifyJS.string_template("- {name}: {time}s", { + name: i, + time: (STATS[i] / 1000).toFixed(3) + })); + } + } +}); + +/* -----[ functions ]----- */ + +function normalize(o) { + for (var i in o) if (o.hasOwnProperty(i) && /-/.test(i)) { + o[i.replace(/-/g, "_")] = o[i]; + delete o[i]; + } +} + +function getOptions(x, constants) { + x = ARGS[x]; + if (!x) return null; + var ret = {}; + if (x !== true) { + var ast; + try { + ast = UglifyJS.parse(x); + } catch(ex) { + if (ex instanceof UglifyJS.JS_Parse_Error) { + sys.error("Error parsing arguments in: " + x); + process.exit(1); + } + } + ast.walk(new UglifyJS.TreeWalker(function(node){ + if (node instanceof UglifyJS.AST_Toplevel) return; // descend + if (node instanceof UglifyJS.AST_SimpleStatement) return; // descend + if (node instanceof UglifyJS.AST_Seq) return; // descend + if (node instanceof UglifyJS.AST_Assign) { + var name = node.left.print_to_string({ beautify: false }).replace(/-/g, "_"); + var value = node.right; + if (constants) + value = new Function("return (" + value.print_to_string() + ")")(); + ret[name] = value; + return true; // no descend + } + sys.error(node.TYPE) + sys.error("Error parsing arguments in: " + x); + process.exit(1); + })); + } + return ret; +} + +function read_whole_file(filename, cb) { + if (filename == "-") { + var chunks = []; + process.stdin.setEncoding('utf-8'); + process.stdin.on('data', function (chunk) { + chunks.push(chunk); + }).on('end', function () { + cb(null, chunks.join("")); + }); + process.openStdin(); + } else { + fs.readFile(filename, "utf-8", cb); + } +} + +function time_it(name, cont) { + var t1 = new Date().getTime(); + var ret = cont(); + if (ARGS.stats) { + var spent = new Date().getTime() - t1; + if (STATS[name]) STATS[name] += spent; + else STATS[name] = spent; + } + return ret; +} diff --git a/homework7/project_express/node_modules/uglify-js/lib/ast.js b/homework7/project_express/node_modules/uglify-js/lib/ast.js new file mode 100644 index 0000000..a1301da --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/lib/ast.js @@ -0,0 +1,985 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function DEFNODE(type, props, methods, base) { + if (arguments.length < 4) base = AST_Node; + if (!props) props = []; + else props = props.split(/\s+/); + var self_props = props; + if (base && base.PROPS) + props = props.concat(base.PROPS); + var code = "return function AST_" + type + "(props){ if (props) { "; + for (var i = props.length; --i >= 0;) { + code += "this." + props[i] + " = props." + props[i] + ";"; + } + var proto = base && new base; + if (proto && proto.initialize || (methods && methods.initialize)) + code += "this.initialize();"; + code += "}}"; + var ctor = new Function(code)(); + if (proto) { + ctor.prototype = proto; + ctor.BASE = base; + } + if (base) base.SUBCLASSES.push(ctor); + ctor.prototype.CTOR = ctor; + ctor.PROPS = props || null; + ctor.SELF_PROPS = self_props; + ctor.SUBCLASSES = []; + if (type) { + ctor.prototype.TYPE = ctor.TYPE = type; + } + if (methods) for (i in methods) if (methods.hasOwnProperty(i)) { + if (/^\$/.test(i)) { + ctor[i.substr(1)] = methods[i]; + } else { + ctor.prototype[i] = methods[i]; + } + } + ctor.DEFMETHOD = function(name, method) { + this.prototype[name] = method; + }; + return ctor; +}; + +var AST_Token = DEFNODE("Token", "type value line col pos endpos nlb comments_before file", { +}, null); + +var AST_Node = DEFNODE("Node", "start end", { + clone: function() { + return new this.CTOR(this); + }, + $documentation: "Base class of all AST nodes", + $propdoc: { + start: "[AST_Token] The first token of this node", + end: "[AST_Token] The last token of this node" + }, + _walk: function(visitor) { + return visitor._visit(this); + }, + walk: function(visitor) { + return this._walk(visitor); // not sure the indirection will be any help + } +}, null); + +AST_Node.warn_function = null; +AST_Node.warn = function(txt, props) { + if (AST_Node.warn_function) + AST_Node.warn_function(string_template(txt, props)); +}; + +/* -----[ statements ]----- */ + +var AST_Statement = DEFNODE("Statement", null, { + $documentation: "Base class of all statements", +}); + +var AST_Debugger = DEFNODE("Debugger", null, { + $documentation: "Represents a debugger statement", +}, AST_Statement); + +var AST_Directive = DEFNODE("Directive", "value scope", { + $documentation: "Represents a directive, like \"use strict\";", + $propdoc: { + value: "[string] The value of this directive as a plain string (it's not an AST_String!)", + scope: "[AST_Scope/S] The scope that this directive affects" + }, +}, AST_Statement); + +var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", { + $documentation: "A statement consisting of an expression, i.e. a = 1 + 2", + $propdoc: { + body: "[AST_Node] an expression node (should not be instanceof AST_Statement)" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.body._walk(visitor); + }); + } +}, AST_Statement); + +function walk_body(node, visitor) { + if (node.body instanceof AST_Statement) { + node.body._walk(visitor); + } + else node.body.forEach(function(stat){ + stat._walk(visitor); + }); +}; + +var AST_Block = DEFNODE("Block", "body", { + $documentation: "A body of statements (usually bracketed)", + $propdoc: { + body: "[AST_Statement*] an array of statements" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + walk_body(this, visitor); + }); + } +}, AST_Statement); + +var AST_BlockStatement = DEFNODE("BlockStatement", null, { + $documentation: "A block statement", +}, AST_Block); + +var AST_EmptyStatement = DEFNODE("EmptyStatement", null, { + $documentation: "The empty statement (empty block or simply a semicolon)", + _walk: function(visitor) { + return visitor._visit(this); + } +}, AST_Statement); + +var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", { + $documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`", + $propdoc: { + body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.body._walk(visitor); + }); + } +}, AST_Statement); + +var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", { + $documentation: "Statement with a label", + $propdoc: { + label: "[AST_Label] a label definition" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.label._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_DWLoop = DEFNODE("DWLoop", "condition", { + $documentation: "Base class for do/while statements", + $propdoc: { + condition: "[AST_Node] the loop condition. Should not be instanceof AST_Statement" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.condition._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_Do = DEFNODE("Do", null, { + $documentation: "A `do` statement", +}, AST_DWLoop); + +var AST_While = DEFNODE("While", null, { + $documentation: "A `while` statement", +}, AST_DWLoop); + +var AST_For = DEFNODE("For", "init condition step", { + $documentation: "A `for` statement", + $propdoc: { + init: "[AST_Node?] the `for` initialization code, or null if empty", + condition: "[AST_Node?] the `for` termination clause, or null if empty", + step: "[AST_Node?] the `for` update clause, or null if empty" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + if (this.init) this.init._walk(visitor); + if (this.condition) this.condition._walk(visitor); + if (this.step) this.step._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_ForIn = DEFNODE("ForIn", "init name object", { + $documentation: "A `for ... in` statement", + $propdoc: { + init: "[AST_Node] the `for/in` initialization code", + name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var", + object: "[AST_Node] the object that we're looping through" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.init._walk(visitor); + this.object._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_With = DEFNODE("With", "expression", { + $documentation: "A `with` statement", + $propdoc: { + expression: "[AST_Node] the `with` expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +/* -----[ scope and functions ]----- */ + +var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", { + $documentation: "Base class for all statements introducing a lexical scope", + $propdoc: { + directives: "[string*/S] an array of directives declared in this scope", + variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope", + functions: "[Object/S] like `variables`, but only lists function declarations", + uses_with: "[boolean/S] tells whether this scope uses the `with` statement", + uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`", + parent_scope: "[AST_Scope?/S] link to the parent scope", + enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes", + cname: "[integer/S] current index for mangling variables (used internally by the mangler)", + }, +}, AST_Block); + +var AST_Toplevel = DEFNODE("Toplevel", "globals", { + $documentation: "The toplevel scope", + $propdoc: { + globals: "[Object/S] a map of name -> SymbolDef for all undeclared names", + }, + wrap_enclose: function(arg_parameter_pairs) { + var self = this; + var args = []; + var parameters = []; + + arg_parameter_pairs.forEach(function(pair) { + var split = pair.split(":"); + + args.push(split[0]); + parameters.push(split[1]); + }); + + var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")"; + wrapped_tl = parse(wrapped_tl); + wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){ + if (node instanceof AST_Directive && node.value == "$ORIG") { + return MAP.splice(self.body); + } + })); + return wrapped_tl; + }, + wrap_commonjs: function(name, export_all) { + var self = this; + var to_export = []; + if (export_all) { + self.figure_out_scope(); + self.walk(new TreeWalker(function(node){ + if (node instanceof AST_SymbolDeclaration && node.definition().global) { + if (!find_if(function(n){ return n.name == node.name }, to_export)) + to_export.push(node); + } + })); + } + var wrapped_tl = "(function(exports, global){ global['" + name + "'] = exports; '$ORIG'; '$EXPORTS'; }({}, (function(){return this}())))"; + wrapped_tl = parse(wrapped_tl); + wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){ + if (node instanceof AST_SimpleStatement) { + node = node.body; + if (node instanceof AST_String) switch (node.getValue()) { + case "$ORIG": + return MAP.splice(self.body); + case "$EXPORTS": + var body = []; + to_export.forEach(function(sym){ + body.push(new AST_SimpleStatement({ + body: new AST_Assign({ + left: new AST_Sub({ + expression: new AST_SymbolRef({ name: "exports" }), + property: new AST_String({ value: sym.name }), + }), + operator: "=", + right: new AST_SymbolRef(sym), + }), + })); + }); + return MAP.splice(body); + } + } + })); + return wrapped_tl; + } +}, AST_Scope); + +var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", { + $documentation: "Base class for functions", + $propdoc: { + name: "[AST_SymbolDeclaration?] the name of this function", + argnames: "[AST_SymbolFunarg*] array of function arguments", + uses_arguments: "[boolean/S] tells whether this function accesses the arguments array" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + if (this.name) this.name._walk(visitor); + this.argnames.forEach(function(arg){ + arg._walk(visitor); + }); + walk_body(this, visitor); + }); + } +}, AST_Scope); + +var AST_Accessor = DEFNODE("Accessor", null, { + $documentation: "A setter/getter function" +}, AST_Lambda); + +var AST_Function = DEFNODE("Function", null, { + $documentation: "A function expression" +}, AST_Lambda); + +var AST_Defun = DEFNODE("Defun", null, { + $documentation: "A function definition" +}, AST_Lambda); + +/* -----[ JUMPS ]----- */ + +var AST_Jump = DEFNODE("Jump", null, { + $documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)" +}, AST_Statement); + +var AST_Exit = DEFNODE("Exit", "value", { + $documentation: "Base class for “exits” (`return` and `throw`)", + $propdoc: { + value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return" + }, + _walk: function(visitor) { + return visitor._visit(this, this.value && function(){ + this.value._walk(visitor); + }); + } +}, AST_Jump); + +var AST_Return = DEFNODE("Return", null, { + $documentation: "A `return` statement" +}, AST_Exit); + +var AST_Throw = DEFNODE("Throw", null, { + $documentation: "A `throw` statement" +}, AST_Exit); + +var AST_LoopControl = DEFNODE("LoopControl", "label", { + $documentation: "Base class for loop control statements (`break` and `continue`)", + $propdoc: { + label: "[AST_LabelRef?] the label, or null if none", + }, + _walk: function(visitor) { + return visitor._visit(this, this.label && function(){ + this.label._walk(visitor); + }); + } +}, AST_Jump); + +var AST_Break = DEFNODE("Break", null, { + $documentation: "A `break` statement" +}, AST_LoopControl); + +var AST_Continue = DEFNODE("Continue", null, { + $documentation: "A `continue` statement" +}, AST_LoopControl); + +/* -----[ IF ]----- */ + +var AST_If = DEFNODE("If", "condition alternative", { + $documentation: "A `if` statement", + $propdoc: { + condition: "[AST_Node] the `if` condition", + alternative: "[AST_Statement?] the `else` part, or null if not present" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.condition._walk(visitor); + this.body._walk(visitor); + if (this.alternative) this.alternative._walk(visitor); + }); + } +}, AST_StatementWithBody); + +/* -----[ SWITCH ]----- */ + +var AST_Switch = DEFNODE("Switch", "expression", { + $documentation: "A `switch` statement", + $propdoc: { + expression: "[AST_Node] the `switch` “discriminant”" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + walk_body(this, visitor); + }); + } +}, AST_Block); + +var AST_SwitchBranch = DEFNODE("SwitchBranch", null, { + $documentation: "Base class for `switch` branches", +}, AST_Block); + +var AST_Default = DEFNODE("Default", null, { + $documentation: "A `default` switch branch", +}, AST_SwitchBranch); + +var AST_Case = DEFNODE("Case", "expression", { + $documentation: "A `case` switch branch", + $propdoc: { + expression: "[AST_Node] the `case` expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + walk_body(this, visitor); + }); + } +}, AST_SwitchBranch); + +/* -----[ EXCEPTIONS ]----- */ + +var AST_Try = DEFNODE("Try", "bcatch bfinally", { + $documentation: "A `try` statement", + $propdoc: { + bcatch: "[AST_Catch?] the catch block, or null if not present", + bfinally: "[AST_Finally?] the finally block, or null if not present" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + walk_body(this, visitor); + if (this.bcatch) this.bcatch._walk(visitor); + if (this.bfinally) this.bfinally._walk(visitor); + }); + } +}, AST_Block); + +// XXX: this is wrong according to ECMA-262 (12.4). the catch block +// should introduce another scope, as the argname should be visible +// only inside the catch block. However, doing it this way because of +// IE which simply introduces the name in the surrounding scope. If +// we ever want to fix this then AST_Catch should inherit from +// AST_Scope. +var AST_Catch = DEFNODE("Catch", "argname", { + $documentation: "A `catch` node; only makes sense as part of a `try` statement", + $propdoc: { + argname: "[AST_SymbolCatch] symbol for the exception" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.argname._walk(visitor); + walk_body(this, visitor); + }); + } +}, AST_Block); + +var AST_Finally = DEFNODE("Finally", null, { + $documentation: "A `finally` node; only makes sense as part of a `try` statement" +}, AST_Block); + +/* -----[ VAR/CONST ]----- */ + +var AST_Definitions = DEFNODE("Definitions", "definitions", { + $documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)", + $propdoc: { + definitions: "[AST_VarDef*] array of variable definitions" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.definitions.forEach(function(def){ + def._walk(visitor); + }); + }); + } +}, AST_Statement); + +var AST_Var = DEFNODE("Var", null, { + $documentation: "A `var` statement" +}, AST_Definitions); + +var AST_Const = DEFNODE("Const", null, { + $documentation: "A `const` statement" +}, AST_Definitions); + +var AST_VarDef = DEFNODE("VarDef", "name value", { + $documentation: "A variable declaration; only appears in a AST_Definitions node", + $propdoc: { + name: "[AST_SymbolVar|AST_SymbolConst] name of the variable", + value: "[AST_Node?] initializer, or null of there's no initializer" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.name._walk(visitor); + if (this.value) this.value._walk(visitor); + }); + } +}); + +/* -----[ OTHER ]----- */ + +var AST_Call = DEFNODE("Call", "expression args", { + $documentation: "A function call expression", + $propdoc: { + expression: "[AST_Node] expression to invoke as function", + args: "[AST_Node*] array of arguments" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + this.args.forEach(function(arg){ + arg._walk(visitor); + }); + }); + } +}); + +var AST_New = DEFNODE("New", null, { + $documentation: "An object instantiation. Derives from a function call since it has exactly the same properties" +}, AST_Call); + +var AST_Seq = DEFNODE("Seq", "car cdr", { + $documentation: "A sequence expression (two comma-separated expressions)", + $propdoc: { + car: "[AST_Node] first element in sequence", + cdr: "[AST_Node] second element in sequence" + }, + $cons: function(x, y) { + var seq = new AST_Seq(x); + seq.car = x; + seq.cdr = y; + return seq; + }, + $from_array: function(array) { + if (array.length == 0) return null; + if (array.length == 1) return array[0].clone(); + var list = null; + for (var i = array.length; --i >= 0;) { + list = AST_Seq.cons(array[i], list); + } + var p = list; + while (p) { + if (p.cdr && !p.cdr.cdr) { + p.cdr = p.cdr.car; + break; + } + p = p.cdr; + } + return list; + }, + to_array: function() { + var p = this, a = []; + while (p) { + a.push(p.car); + if (p.cdr && !(p.cdr instanceof AST_Seq)) { + a.push(p.cdr); + break; + } + p = p.cdr; + } + return a; + }, + add: function(node) { + var p = this; + while (p) { + if (!(p.cdr instanceof AST_Seq)) { + var cell = AST_Seq.cons(p.cdr, node); + return p.cdr = cell; + } + p = p.cdr; + } + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.car._walk(visitor); + if (this.cdr) this.cdr._walk(visitor); + }); + } +}); + +var AST_PropAccess = DEFNODE("PropAccess", "expression property", { + $documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`", + $propdoc: { + expression: "[AST_Node] the “container” expression", + property: "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node" + } +}); + +var AST_Dot = DEFNODE("Dot", null, { + $documentation: "A dotted property access expression", + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + }); + } +}, AST_PropAccess); + +var AST_Sub = DEFNODE("Sub", null, { + $documentation: "Index-style property access, i.e. `a[\"foo\"]`", + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + this.property._walk(visitor); + }); + } +}, AST_PropAccess); + +var AST_Unary = DEFNODE("Unary", "operator expression", { + $documentation: "Base class for unary expressions", + $propdoc: { + operator: "[string] the operator", + expression: "[AST_Node] expression that this unary operator applies to" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + }); + } +}); + +var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, { + $documentation: "Unary prefix expression, i.e. `typeof i` or `++i`" +}, AST_Unary); + +var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, { + $documentation: "Unary postfix expression, i.e. `i++`" +}, AST_Unary); + +var AST_Binary = DEFNODE("Binary", "left operator right", { + $documentation: "Binary expression, i.e. `a + b`", + $propdoc: { + left: "[AST_Node] left-hand side expression", + operator: "[string] the operator", + right: "[AST_Node] right-hand side expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.left._walk(visitor); + this.right._walk(visitor); + }); + } +}); + +var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", { + $documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`", + $propdoc: { + condition: "[AST_Node]", + consequent: "[AST_Node]", + alternative: "[AST_Node]" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.condition._walk(visitor); + this.consequent._walk(visitor); + this.alternative._walk(visitor); + }); + } +}); + +var AST_Assign = DEFNODE("Assign", null, { + $documentation: "An assignment expression — `a = b + 5`", +}, AST_Binary); + +/* -----[ LITERALS ]----- */ + +var AST_Array = DEFNODE("Array", "elements", { + $documentation: "An array literal", + $propdoc: { + elements: "[AST_Node*] array of elements" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.elements.forEach(function(el){ + el._walk(visitor); + }); + }); + } +}); + +var AST_Object = DEFNODE("Object", "properties", { + $documentation: "An object literal", + $propdoc: { + properties: "[AST_ObjectProperty*] array of properties" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.properties.forEach(function(prop){ + prop._walk(visitor); + }); + }); + } +}); + +var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", { + $documentation: "Base class for literal object properties", + $propdoc: { + key: "[string] the property name; it's always a plain string in our AST, no matter if it was a string, number or identifier in original code", + value: "[AST_Node] property value. For setters and getters this is an AST_Function." + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.value._walk(visitor); + }); + } +}); + +var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", null, { + $documentation: "A key: value object property", +}, AST_ObjectProperty); + +var AST_ObjectSetter = DEFNODE("ObjectSetter", null, { + $documentation: "An object setter property", +}, AST_ObjectProperty); + +var AST_ObjectGetter = DEFNODE("ObjectGetter", null, { + $documentation: "An object getter property", +}, AST_ObjectProperty); + +var AST_Symbol = DEFNODE("Symbol", "scope name thedef", { + $propdoc: { + name: "[string] name of this symbol", + scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)", + thedef: "[SymbolDef/S] the definition of this symbol" + }, + $documentation: "Base class for all symbols", +}); + +var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, { + $documentation: "The name of a property accessor (setter/getter function)" +}, AST_Symbol); + +var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", { + $documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)", + $propdoc: { + init: "[AST_Node*/S] array of initializers for this declaration." + } +}, AST_Symbol); + +var AST_SymbolVar = DEFNODE("SymbolVar", null, { + $documentation: "Symbol defining a variable", +}, AST_SymbolDeclaration); + +var AST_SymbolConst = DEFNODE("SymbolConst", null, { + $documentation: "A constant declaration" +}, AST_SymbolDeclaration); + +var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, { + $documentation: "Symbol naming a function argument", +}, AST_SymbolVar); + +var AST_SymbolDefun = DEFNODE("SymbolDefun", null, { + $documentation: "Symbol defining a function", +}, AST_SymbolDeclaration); + +var AST_SymbolLambda = DEFNODE("SymbolLambda", null, { + $documentation: "Symbol naming a function expression", +}, AST_SymbolDeclaration); + +var AST_SymbolCatch = DEFNODE("SymbolCatch", null, { + $documentation: "Symbol naming the exception in catch", +}, AST_SymbolDeclaration); + +var AST_Label = DEFNODE("Label", "references", { + $documentation: "Symbol naming a label (declaration)", + $propdoc: { + references: "[AST_LabelRef*] a list of nodes referring to this label" + } +}, AST_Symbol); + +var AST_SymbolRef = DEFNODE("SymbolRef", null, { + $documentation: "Reference to some symbol (not definition/declaration)", +}, AST_Symbol); + +var AST_LabelRef = DEFNODE("LabelRef", null, { + $documentation: "Reference to a label symbol", +}, AST_Symbol); + +var AST_This = DEFNODE("This", null, { + $documentation: "The `this` symbol", +}, AST_Symbol); + +var AST_Constant = DEFNODE("Constant", null, { + $documentation: "Base class for all constants", + getValue: function() { + return this.value; + } +}); + +var AST_String = DEFNODE("String", "value", { + $documentation: "A string literal", + $propdoc: { + value: "[string] the contents of this string" + } +}, AST_Constant); + +var AST_Number = DEFNODE("Number", "value", { + $documentation: "A number literal", + $propdoc: { + value: "[number] the numeric value" + } +}, AST_Constant); + +var AST_RegExp = DEFNODE("RegExp", "value", { + $documentation: "A regexp literal", + $propdoc: { + value: "[RegExp] the actual regexp" + } +}, AST_Constant); + +var AST_Atom = DEFNODE("Atom", null, { + $documentation: "Base class for atoms", +}, AST_Constant); + +var AST_Null = DEFNODE("Null", null, { + $documentation: "The `null` atom", + value: null +}, AST_Atom); + +var AST_NaN = DEFNODE("NaN", null, { + $documentation: "The impossible value", + value: 0/0 +}, AST_Atom); + +var AST_Undefined = DEFNODE("Undefined", null, { + $documentation: "The `undefined` value", + value: (function(){}()) +}, AST_Atom); + +var AST_Hole = DEFNODE("Hole", null, { + $documentation: "A hole in an array", + value: (function(){}()) +}, AST_Atom); + +var AST_Infinity = DEFNODE("Infinity", null, { + $documentation: "The `Infinity` value", + value: 1/0 +}, AST_Atom); + +var AST_Boolean = DEFNODE("Boolean", null, { + $documentation: "Base class for booleans", +}, AST_Atom); + +var AST_False = DEFNODE("False", null, { + $documentation: "The `false` atom", + value: false +}, AST_Boolean); + +var AST_True = DEFNODE("True", null, { + $documentation: "The `true` atom", + value: true +}, AST_Boolean); + +/* -----[ TreeWalker ]----- */ + +function TreeWalker(callback) { + this.visit = callback; + this.stack = []; +}; +TreeWalker.prototype = { + _visit: function(node, descend) { + this.stack.push(node); + var ret = this.visit(node, descend ? function(){ + descend.call(node); + } : noop); + if (!ret && descend) { + descend.call(node); + } + this.stack.pop(); + return ret; + }, + parent: function(n) { + return this.stack[this.stack.length - 2 - (n || 0)]; + }, + push: function (node) { + this.stack.push(node); + }, + pop: function() { + return this.stack.pop(); + }, + self: function() { + return this.stack[this.stack.length - 1]; + }, + find_parent: function(type) { + var stack = this.stack; + for (var i = stack.length; --i >= 0;) { + var x = stack[i]; + if (x instanceof type) return x; + } + }, + in_boolean_context: function() { + var stack = this.stack; + var i = stack.length, self = stack[--i]; + while (i > 0) { + var p = stack[--i]; + if ((p instanceof AST_If && p.condition === self) || + (p instanceof AST_Conditional && p.condition === self) || + (p instanceof AST_DWLoop && p.condition === self) || + (p instanceof AST_For && p.condition === self) || + (p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self)) + { + return true; + } + if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||"))) + return false; + self = p; + } + }, + loopcontrol_target: function(label) { + var stack = this.stack; + if (label) { + for (var i = stack.length; --i >= 0;) { + var x = stack[i]; + if (x instanceof AST_LabeledStatement && x.label.name == label.name) { + return x.body; + } + } + } else { + for (var i = stack.length; --i >= 0;) { + var x = stack[i]; + if (x instanceof AST_Switch + || x instanceof AST_For + || x instanceof AST_ForIn + || x instanceof AST_DWLoop) return x; + } + } + } +}; diff --git a/homework7/project_express/node_modules/uglify-js/lib/compress.js b/homework7/project_express/node_modules/uglify-js/lib/compress.js new file mode 100644 index 0000000..ebd3dd7 --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/lib/compress.js @@ -0,0 +1,1985 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function Compressor(options, false_by_default) { + if (!(this instanceof Compressor)) + return new Compressor(options, false_by_default); + TreeTransformer.call(this, this.before, this.after); + this.options = defaults(options, { + sequences : !false_by_default, + properties : !false_by_default, + dead_code : !false_by_default, + drop_debugger : !false_by_default, + unsafe : false, + unsafe_comps : false, + conditionals : !false_by_default, + comparisons : !false_by_default, + evaluate : !false_by_default, + booleans : !false_by_default, + loops : !false_by_default, + unused : !false_by_default, + hoist_funs : !false_by_default, + hoist_vars : false, + if_return : !false_by_default, + join_vars : !false_by_default, + cascade : !false_by_default, + side_effects : !false_by_default, + screw_ie8 : false, + + warnings : true, + global_defs : {} + }, true); +}; + +Compressor.prototype = new TreeTransformer; +merge(Compressor.prototype, { + option: function(key) { return this.options[key] }, + warn: function() { + if (this.options.warnings) + AST_Node.warn.apply(AST_Node, arguments); + }, + before: function(node, descend, in_list) { + if (node._squeezed) return node; + if (node instanceof AST_Scope) { + node.drop_unused(this); + node = node.hoist_declarations(this); + } + descend(node, this); + node = node.optimize(this); + if (node instanceof AST_Scope) { + // dead code removal might leave further unused declarations. + // this'll usually save very few bytes, but the performance + // hit seems negligible so I'll just drop it here. + + // no point to repeat warnings. + var save_warnings = this.options.warnings; + this.options.warnings = false; + node.drop_unused(this); + this.options.warnings = save_warnings; + } + node._squeezed = true; + return node; + } +}); + +(function(){ + + function OPT(node, optimizer) { + node.DEFMETHOD("optimize", function(compressor){ + var self = this; + if (self._optimized) return self; + var opt = optimizer(self, compressor); + opt._optimized = true; + if (opt === self) return opt; + return opt.transform(compressor); + }); + }; + + OPT(AST_Node, function(self, compressor){ + return self; + }); + + AST_Node.DEFMETHOD("equivalent_to", function(node){ + // XXX: this is a rather expensive way to test two node's equivalence: + return this.print_to_string() == node.print_to_string(); + }); + + function make_node(ctor, orig, props) { + if (!props) props = {}; + if (orig) { + if (!props.start) props.start = orig.start; + if (!props.end) props.end = orig.end; + } + return new ctor(props); + }; + + function make_node_from_constant(compressor, val, orig) { + // XXX: WIP. + // if (val instanceof AST_Node) return val.transform(new TreeTransformer(null, function(node){ + // if (node instanceof AST_SymbolRef) { + // var scope = compressor.find_parent(AST_Scope); + // var def = scope.find_variable(node); + // node.thedef = def; + // return node; + // } + // })).transform(compressor); + + if (val instanceof AST_Node) return val.transform(compressor); + switch (typeof val) { + case "string": + return make_node(AST_String, orig, { + value: val + }).optimize(compressor); + case "number": + return make_node(isNaN(val) ? AST_NaN : AST_Number, orig, { + value: val + }).optimize(compressor); + case "boolean": + return make_node(val ? AST_True : AST_False, orig).optimize(compressor); + case "undefined": + return make_node(AST_Undefined, orig).optimize(compressor); + default: + if (val === null) { + return make_node(AST_Null, orig).optimize(compressor); + } + if (val instanceof RegExp) { + return make_node(AST_RegExp, orig).optimize(compressor); + } + throw new Error(string_template("Can't handle constant of type: {type}", { + type: typeof val + })); + } + }; + + function as_statement_array(thing) { + if (thing === null) return []; + if (thing instanceof AST_BlockStatement) return thing.body; + if (thing instanceof AST_EmptyStatement) return []; + if (thing instanceof AST_Statement) return [ thing ]; + throw new Error("Can't convert thing to statement array"); + }; + + function is_empty(thing) { + if (thing === null) return true; + if (thing instanceof AST_EmptyStatement) return true; + if (thing instanceof AST_BlockStatement) return thing.body.length == 0; + return false; + }; + + function loop_body(x) { + if (x instanceof AST_Switch) return x; + if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) { + return (x.body instanceof AST_BlockStatement ? x.body : x); + } + return x; + }; + + function tighten_body(statements, compressor) { + var CHANGED; + do { + CHANGED = false; + statements = eliminate_spurious_blocks(statements); + if (compressor.option("dead_code")) { + statements = eliminate_dead_code(statements, compressor); + } + if (compressor.option("if_return")) { + statements = handle_if_return(statements, compressor); + } + if (compressor.option("sequences")) { + statements = sequencesize(statements, compressor); + } + if (compressor.option("join_vars")) { + statements = join_consecutive_vars(statements, compressor); + } + } while (CHANGED); + return statements; + + function eliminate_spurious_blocks(statements) { + var seen_dirs = []; + return statements.reduce(function(a, stat){ + if (stat instanceof AST_BlockStatement) { + CHANGED = true; + a.push.apply(a, eliminate_spurious_blocks(stat.body)); + } else if (stat instanceof AST_EmptyStatement) { + CHANGED = true; + } else if (stat instanceof AST_Directive) { + if (seen_dirs.indexOf(stat.value) < 0) { + a.push(stat); + seen_dirs.push(stat.value); + } else { + CHANGED = true; + } + } else { + a.push(stat); + } + return a; + }, []); + }; + + function handle_if_return(statements, compressor) { + var self = compressor.self(); + var in_lambda = self instanceof AST_Lambda; + var ret = []; + loop: for (var i = statements.length; --i >= 0;) { + var stat = statements[i]; + switch (true) { + case (in_lambda && stat instanceof AST_Return && !stat.value && ret.length == 0): + CHANGED = true; + // note, ret.length is probably always zero + // because we drop unreachable code before this + // step. nevertheless, it's good to check. + continue loop; + case stat instanceof AST_If: + if (stat.body instanceof AST_Return) { + //--- + // pretty silly case, but: + // if (foo()) return; return; ==> foo(); return; + if (((in_lambda && ret.length == 0) + || (ret[0] instanceof AST_Return && !ret[0].value)) + && !stat.body.value && !stat.alternative) { + CHANGED = true; + var cond = make_node(AST_SimpleStatement, stat.condition, { + body: stat.condition + }); + ret.unshift(cond); + continue loop; + } + //--- + // if (foo()) return x; return y; ==> return foo() ? x : y; + if (ret[0] instanceof AST_Return && stat.body.value && ret[0].value && !stat.alternative) { + CHANGED = true; + stat = stat.clone(); + stat.alternative = ret[0]; + ret[0] = stat.transform(compressor); + continue loop; + } + //--- + // if (foo()) return x; [ return ; ] ==> return foo() ? x : undefined; + if ((ret.length == 0 || ret[0] instanceof AST_Return) && stat.body.value && !stat.alternative && in_lambda) { + CHANGED = true; + stat = stat.clone(); + stat.alternative = ret[0] || make_node(AST_Return, stat, { + value: make_node(AST_Undefined, stat) + }); + ret[0] = stat.transform(compressor); + continue loop; + } + //--- + // if (foo()) return; [ else x... ]; y... ==> if (!foo()) { x...; y... } + if (!stat.body.value && in_lambda) { + CHANGED = true; + stat = stat.clone(); + stat.condition = stat.condition.negate(compressor); + stat.body = make_node(AST_BlockStatement, stat, { + body: as_statement_array(stat.alternative).concat(ret) + }); + stat.alternative = null; + ret = [ stat.transform(compressor) ]; + continue loop; + } + //--- + if (ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement + && (!stat.alternative || stat.alternative instanceof AST_SimpleStatement)) { + CHANGED = true; + ret.push(make_node(AST_Return, ret[0], { + value: make_node(AST_Undefined, ret[0]) + }).transform(compressor)); + ret = as_statement_array(stat.alternative).concat(ret); + ret.unshift(stat); + continue loop; + } + } + + var ab = aborts(stat.body); + var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null; + if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda) + || (ab instanceof AST_Continue && self === loop_body(lct)) + || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) { + if (ab.label) { + remove(ab.label.thedef.references, ab.label); + } + CHANGED = true; + var body = as_statement_array(stat.body).slice(0, -1); + stat = stat.clone(); + stat.condition = stat.condition.negate(compressor); + stat.body = make_node(AST_BlockStatement, stat, { + body: ret + }); + stat.alternative = make_node(AST_BlockStatement, stat, { + body: body + }); + ret = [ stat.transform(compressor) ]; + continue loop; + } + + var ab = aborts(stat.alternative); + var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null; + if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda) + || (ab instanceof AST_Continue && self === loop_body(lct)) + || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) { + if (ab.label) { + remove(ab.label.thedef.references, ab.label); + } + CHANGED = true; + stat = stat.clone(); + stat.body = make_node(AST_BlockStatement, stat.body, { + body: as_statement_array(stat.body).concat(ret) + }); + stat.alternative = make_node(AST_BlockStatement, stat.alternative, { + body: as_statement_array(stat.alternative).slice(0, -1) + }); + ret = [ stat.transform(compressor) ]; + continue loop; + } + + ret.unshift(stat); + break; + default: + ret.unshift(stat); + break; + } + } + return ret; + }; + + function eliminate_dead_code(statements, compressor) { + var has_quit = false; + var orig = statements.length; + var self = compressor.self(); + statements = statements.reduce(function(a, stat){ + if (has_quit) { + extract_declarations_from_unreachable_code(compressor, stat, a); + } else { + if (stat instanceof AST_LoopControl) { + var lct = compressor.loopcontrol_target(stat.label); + if ((stat instanceof AST_Break + && lct instanceof AST_BlockStatement + && loop_body(lct) === self) || (stat instanceof AST_Continue + && loop_body(lct) === self)) { + if (stat.label) { + remove(stat.label.thedef.references, stat.label); + } + } else { + a.push(stat); + } + } else { + a.push(stat); + } + if (aborts(stat)) has_quit = true; + } + return a; + }, []); + CHANGED = statements.length != orig; + return statements; + }; + + function sequencesize(statements, compressor) { + if (statements.length < 2) return statements; + var seq = [], ret = []; + function push_seq() { + seq = AST_Seq.from_array(seq); + if (seq) ret.push(make_node(AST_SimpleStatement, seq, { + body: seq + })); + seq = []; + }; + statements.forEach(function(stat){ + if (stat instanceof AST_SimpleStatement) seq.push(stat.body); + else push_seq(), ret.push(stat); + }); + push_seq(); + ret = sequencesize_2(ret, compressor); + CHANGED = ret.length != statements.length; + return ret; + }; + + function sequencesize_2(statements, compressor) { + function cons_seq(right) { + ret.pop(); + var left = prev.body; + if (left instanceof AST_Seq) { + left.add(right); + } else { + left = AST_Seq.cons(left, right); + } + return left.transform(compressor); + }; + var ret = [], prev = null; + statements.forEach(function(stat){ + if (prev) { + if (stat instanceof AST_For) { + var opera = {}; + try { + prev.body.walk(new TreeWalker(function(node){ + if (node instanceof AST_Binary && node.operator == "in") + throw opera; + })); + if (stat.init && !(stat.init instanceof AST_Definitions)) { + stat.init = cons_seq(stat.init); + } + else if (!stat.init) { + stat.init = prev.body; + ret.pop(); + } + } catch(ex) { + if (ex !== opera) throw ex; + } + } + else if (stat instanceof AST_If) { + stat.condition = cons_seq(stat.condition); + } + else if (stat instanceof AST_With) { + stat.expression = cons_seq(stat.expression); + } + else if (stat instanceof AST_Exit && stat.value) { + stat.value = cons_seq(stat.value); + } + else if (stat instanceof AST_Exit) { + stat.value = cons_seq(make_node(AST_Undefined, stat)); + } + else if (stat instanceof AST_Switch) { + stat.expression = cons_seq(stat.expression); + } + } + ret.push(stat); + prev = stat instanceof AST_SimpleStatement ? stat : null; + }); + return ret; + }; + + function join_consecutive_vars(statements, compressor) { + var prev = null; + return statements.reduce(function(a, stat){ + if (stat instanceof AST_Definitions && prev && prev.TYPE == stat.TYPE) { + prev.definitions = prev.definitions.concat(stat.definitions); + CHANGED = true; + } + else if (stat instanceof AST_For + && prev instanceof AST_Definitions + && (!stat.init || stat.init.TYPE == prev.TYPE)) { + CHANGED = true; + a.pop(); + if (stat.init) { + stat.init.definitions = prev.definitions.concat(stat.init.definitions); + } else { + stat.init = prev; + } + a.push(stat); + prev = stat; + } + else { + prev = stat; + a.push(stat); + } + return a; + }, []); + }; + + }; + + function extract_declarations_from_unreachable_code(compressor, stat, target) { + compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start); + stat.walk(new TreeWalker(function(node){ + if (node instanceof AST_Definitions) { + compressor.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start); + node.remove_initializers(); + target.push(node); + return true; + } + if (node instanceof AST_Defun) { + target.push(node); + return true; + } + if (node instanceof AST_Scope) { + return true; + } + })); + }; + + /* -----[ boolean/negation helpers ]----- */ + + // methods to determine whether an expression has a boolean result type + (function (def){ + var unary_bool = [ "!", "delete" ]; + var binary_bool = [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ]; + def(AST_Node, function(){ return false }); + def(AST_UnaryPrefix, function(){ + return member(this.operator, unary_bool); + }); + def(AST_Binary, function(){ + return member(this.operator, binary_bool) || + ( (this.operator == "&&" || this.operator == "||") && + this.left.is_boolean() && this.right.is_boolean() ); + }); + def(AST_Conditional, function(){ + return this.consequent.is_boolean() && this.alternative.is_boolean(); + }); + def(AST_Assign, function(){ + return this.operator == "=" && this.right.is_boolean(); + }); + def(AST_Seq, function(){ + return this.cdr.is_boolean(); + }); + def(AST_True, function(){ return true }); + def(AST_False, function(){ return true }); + })(function(node, func){ + node.DEFMETHOD("is_boolean", func); + }); + + // methods to determine if an expression has a string result type + (function (def){ + def(AST_Node, function(){ return false }); + def(AST_String, function(){ return true }); + def(AST_UnaryPrefix, function(){ + return this.operator == "typeof"; + }); + def(AST_Binary, function(compressor){ + return this.operator == "+" && + (this.left.is_string(compressor) || this.right.is_string(compressor)); + }); + def(AST_Assign, function(compressor){ + return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor); + }); + def(AST_Seq, function(compressor){ + return this.cdr.is_string(compressor); + }); + def(AST_Conditional, function(compressor){ + return this.consequent.is_string(compressor) && this.alternative.is_string(compressor); + }); + def(AST_Call, function(compressor){ + return compressor.option("unsafe") + && this.expression instanceof AST_SymbolRef + && this.expression.name == "String" + && this.expression.undeclared(); + }); + })(function(node, func){ + node.DEFMETHOD("is_string", func); + }); + + function best_of(ast1, ast2) { + return ast1.print_to_string().length > + ast2.print_to_string().length + ? ast2 : ast1; + }; + + // methods to evaluate a constant expression + (function (def){ + // The evaluate method returns an array with one or two + // elements. If the node has been successfully reduced to a + // constant, then the second element tells us the value; + // otherwise the second element is missing. The first element + // of the array is always an AST_Node descendant; when + // evaluation was successful it's a node that represents the + // constant; otherwise it's the original node. + AST_Node.DEFMETHOD("evaluate", function(compressor){ + if (!compressor.option("evaluate")) return [ this ]; + try { + var val = this._eval(), ast = make_node_from_constant(compressor, val, this); + return [ best_of(ast, this), val ]; + } catch(ex) { + if (ex !== def) throw ex; + return [ this ]; + } + }); + def(AST_Statement, function(){ + throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start)); + }); + def(AST_Function, function(){ + // XXX: AST_Function inherits from AST_Scope, which itself + // inherits from AST_Statement; however, an AST_Function + // isn't really a statement. This could byte in other + // places too. :-( Wish JS had multiple inheritance. + return [ this ]; + }); + function ev(node) { + return node._eval(); + }; + def(AST_Node, function(){ + throw def; // not constant + }); + def(AST_Constant, function(){ + return this.getValue(); + }); + def(AST_UnaryPrefix, function(){ + var e = this.expression; + switch (this.operator) { + case "!": return !ev(e); + case "typeof": + // Function would be evaluated to an array and so typeof would + // incorrectly return 'object'. Hence making is a special case. + if (e instanceof AST_Function) return typeof function(){}; + + e = ev(e); + + // typeof returns "object" or "function" on different platforms + // so cannot evaluate reliably + if (e instanceof RegExp) throw def; + + return typeof e; + case "void": return void ev(e); + case "~": return ~ev(e); + case "-": + e = ev(e); + if (e === 0) throw def; + return -e; + case "+": return +ev(e); + } + throw def; + }); + def(AST_Binary, function(){ + var left = this.left, right = this.right; + switch (this.operator) { + case "&&" : return ev(left) && ev(right); + case "||" : return ev(left) || ev(right); + case "|" : return ev(left) | ev(right); + case "&" : return ev(left) & ev(right); + case "^" : return ev(left) ^ ev(right); + case "+" : return ev(left) + ev(right); + case "*" : return ev(left) * ev(right); + case "/" : return ev(left) / ev(right); + case "%" : return ev(left) % ev(right); + case "-" : return ev(left) - ev(right); + case "<<" : return ev(left) << ev(right); + case ">>" : return ev(left) >> ev(right); + case ">>>" : return ev(left) >>> ev(right); + case "==" : return ev(left) == ev(right); + case "===" : return ev(left) === ev(right); + case "!=" : return ev(left) != ev(right); + case "!==" : return ev(left) !== ev(right); + case "<" : return ev(left) < ev(right); + case "<=" : return ev(left) <= ev(right); + case ">" : return ev(left) > ev(right); + case ">=" : return ev(left) >= ev(right); + case "in" : return ev(left) in ev(right); + case "instanceof" : return ev(left) instanceof ev(right); + } + throw def; + }); + def(AST_Conditional, function(){ + return ev(this.condition) + ? ev(this.consequent) + : ev(this.alternative); + }); + def(AST_SymbolRef, function(){ + var d = this.definition(); + if (d && d.constant && d.init) return ev(d.init); + throw def; + }); + })(function(node, func){ + node.DEFMETHOD("_eval", func); + }); + + // method to negate an expression + (function(def){ + function basic_negation(exp) { + return make_node(AST_UnaryPrefix, exp, { + operator: "!", + expression: exp + }); + }; + def(AST_Node, function(){ + return basic_negation(this); + }); + def(AST_Statement, function(){ + throw new Error("Cannot negate a statement"); + }); + def(AST_Function, function(){ + return basic_negation(this); + }); + def(AST_UnaryPrefix, function(){ + if (this.operator == "!") + return this.expression; + return basic_negation(this); + }); + def(AST_Seq, function(compressor){ + var self = this.clone(); + self.cdr = self.cdr.negate(compressor); + return self; + }); + def(AST_Conditional, function(compressor){ + var self = this.clone(); + self.consequent = self.consequent.negate(compressor); + self.alternative = self.alternative.negate(compressor); + return best_of(basic_negation(this), self); + }); + def(AST_Binary, function(compressor){ + var self = this.clone(), op = this.operator; + if (compressor.option("unsafe_comps")) { + switch (op) { + case "<=" : self.operator = ">" ; return self; + case "<" : self.operator = ">=" ; return self; + case ">=" : self.operator = "<" ; return self; + case ">" : self.operator = "<=" ; return self; + } + } + switch (op) { + case "==" : self.operator = "!="; return self; + case "!=" : self.operator = "=="; return self; + case "===": self.operator = "!=="; return self; + case "!==": self.operator = "==="; return self; + case "&&": + self.operator = "||"; + self.left = self.left.negate(compressor); + self.right = self.right.negate(compressor); + return best_of(basic_negation(this), self); + case "||": + self.operator = "&&"; + self.left = self.left.negate(compressor); + self.right = self.right.negate(compressor); + return best_of(basic_negation(this), self); + } + return basic_negation(this); + }); + })(function(node, func){ + node.DEFMETHOD("negate", function(compressor){ + return func.call(this, compressor); + }); + }); + + // determine if expression has side effects + (function(def){ + def(AST_Node, function(){ return true }); + + def(AST_EmptyStatement, function(){ return false }); + def(AST_Constant, function(){ return false }); + def(AST_This, function(){ return false }); + + def(AST_Block, function(){ + for (var i = this.body.length; --i >= 0;) { + if (this.body[i].has_side_effects()) + return true; + } + return false; + }); + + def(AST_SimpleStatement, function(){ + return this.body.has_side_effects(); + }); + def(AST_Defun, function(){ return true }); + def(AST_Function, function(){ return false }); + def(AST_Binary, function(){ + return this.left.has_side_effects() + || this.right.has_side_effects(); + }); + def(AST_Assign, function(){ return true }); + def(AST_Conditional, function(){ + return this.condition.has_side_effects() + || this.consequent.has_side_effects() + || this.alternative.has_side_effects(); + }); + def(AST_Unary, function(){ + return this.operator == "delete" + || this.operator == "++" + || this.operator == "--" + || this.expression.has_side_effects(); + }); + def(AST_SymbolRef, function(){ return false }); + def(AST_Object, function(){ + for (var i = this.properties.length; --i >= 0;) + if (this.properties[i].has_side_effects()) + return true; + return false; + }); + def(AST_ObjectProperty, function(){ + return this.value.has_side_effects(); + }); + def(AST_Array, function(){ + for (var i = this.elements.length; --i >= 0;) + if (this.elements[i].has_side_effects()) + return true; + return false; + }); + // def(AST_Dot, function(){ + // return this.expression.has_side_effects(); + // }); + // def(AST_Sub, function(){ + // return this.expression.has_side_effects() + // || this.property.has_side_effects(); + // }); + def(AST_PropAccess, function(){ + return true; + }); + def(AST_Seq, function(){ + return this.car.has_side_effects() + || this.cdr.has_side_effects(); + }); + })(function(node, func){ + node.DEFMETHOD("has_side_effects", func); + }); + + // tell me if a statement aborts + function aborts(thing) { + return thing && thing.aborts(); + }; + (function(def){ + def(AST_Statement, function(){ return null }); + def(AST_Jump, function(){ return this }); + function block_aborts(){ + var n = this.body.length; + return n > 0 && aborts(this.body[n - 1]); + }; + def(AST_BlockStatement, block_aborts); + def(AST_SwitchBranch, block_aborts); + def(AST_If, function(){ + return this.alternative && aborts(this.body) && aborts(this.alternative); + }); + })(function(node, func){ + node.DEFMETHOD("aborts", func); + }); + + /* -----[ optimizers ]----- */ + + OPT(AST_Directive, function(self, compressor){ + if (self.scope.has_directive(self.value) !== self.scope) { + return make_node(AST_EmptyStatement, self); + } + return self; + }); + + OPT(AST_Debugger, function(self, compressor){ + if (compressor.option("drop_debugger")) + return make_node(AST_EmptyStatement, self); + return self; + }); + + OPT(AST_LabeledStatement, function(self, compressor){ + if (self.body instanceof AST_Break + && compressor.loopcontrol_target(self.body.label) === self.body) { + return make_node(AST_EmptyStatement, self); + } + return self.label.references.length == 0 ? self.body : self; + }); + + OPT(AST_Block, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + return self; + }); + + OPT(AST_BlockStatement, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + switch (self.body.length) { + case 1: return self.body[0]; + case 0: return make_node(AST_EmptyStatement, self); + } + return self; + }); + + AST_Scope.DEFMETHOD("drop_unused", function(compressor){ + var self = this; + if (compressor.option("unused") + && !(self instanceof AST_Toplevel) + && !self.uses_eval + ) { + var in_use = []; + var initializations = new Dictionary(); + // pass 1: find out which symbols are directly used in + // this scope (not in nested scopes). + var scope = this; + var tw = new TreeWalker(function(node, descend){ + if (node !== self) { + if (node instanceof AST_Defun) { + initializations.add(node.name.name, node); + return true; // don't go in nested scopes + } + if (node instanceof AST_Definitions && scope === self) { + node.definitions.forEach(function(def){ + if (def.value) { + initializations.add(def.name.name, def.value); + if (def.value.has_side_effects()) { + def.value.walk(tw); + } + } + }); + return true; + } + if (node instanceof AST_SymbolRef) { + push_uniq(in_use, node.definition()); + return true; + } + if (node instanceof AST_Scope) { + var save_scope = scope; + scope = node; + descend(); + scope = save_scope; + return true; + } + } + }); + self.walk(tw); + // pass 2: for every used symbol we need to walk its + // initialization code to figure out if it uses other + // symbols (that may not be in_use). + for (var i = 0; i < in_use.length; ++i) { + in_use[i].orig.forEach(function(decl){ + // undeclared globals will be instanceof AST_SymbolRef + var init = initializations.get(decl.name); + if (init) init.forEach(function(init){ + var tw = new TreeWalker(function(node){ + if (node instanceof AST_SymbolRef) { + push_uniq(in_use, node.definition()); + } + }); + init.walk(tw); + }); + }); + } + // pass 3: we should drop declarations not in_use + var tt = new TreeTransformer( + function before(node, descend, in_list) { + if (node instanceof AST_Lambda) { + for (var a = node.argnames, i = a.length; --i >= 0;) { + var sym = a[i]; + if (sym.unreferenced()) { + a.pop(); + compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", { + name : sym.name, + file : sym.start.file, + line : sym.start.line, + col : sym.start.col + }); + } + else break; + } + } + if (node instanceof AST_Defun && node !== self) { + if (!member(node.name.definition(), in_use)) { + compressor.warn("Dropping unused function {name} [{file}:{line},{col}]", { + name : node.name.name, + file : node.name.start.file, + line : node.name.start.line, + col : node.name.start.col + }); + return make_node(AST_EmptyStatement, node); + } + return node; + } + if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) { + var def = node.definitions.filter(function(def){ + if (member(def.name.definition(), in_use)) return true; + var w = { + name : def.name.name, + file : def.name.start.file, + line : def.name.start.line, + col : def.name.start.col + }; + if (def.value && def.value.has_side_effects()) { + def._unused_side_effects = true; + compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", w); + return true; + } + compressor.warn("Dropping unused variable {name} [{file}:{line},{col}]", w); + return false; + }); + // place uninitialized names at the start + def = mergeSort(def, function(a, b){ + if (!a.value && b.value) return -1; + if (!b.value && a.value) return 1; + return 0; + }); + // for unused names whose initialization has + // side effects, we can cascade the init. code + // into the next one, or next statement. + var side_effects = []; + for (var i = 0; i < def.length;) { + var x = def[i]; + if (x._unused_side_effects) { + side_effects.push(x.value); + def.splice(i, 1); + } else { + if (side_effects.length > 0) { + side_effects.push(x.value); + x.value = AST_Seq.from_array(side_effects); + side_effects = []; + } + ++i; + } + } + if (side_effects.length > 0) { + side_effects = make_node(AST_BlockStatement, node, { + body: [ make_node(AST_SimpleStatement, node, { + body: AST_Seq.from_array(side_effects) + }) ] + }); + } else { + side_effects = null; + } + if (def.length == 0 && !side_effects) { + return make_node(AST_EmptyStatement, node); + } + if (def.length == 0) { + return side_effects; + } + node.definitions = def; + if (side_effects) { + side_effects.body.unshift(node); + node = side_effects; + } + return node; + } + if (node instanceof AST_For && node.init instanceof AST_BlockStatement) { + descend(node, this); + // certain combination of unused name + side effect leads to: + // https://github.com/mishoo/UglifyJS2/issues/44 + // that's an invalid AST. + // We fix it at this stage by moving the `var` outside the `for`. + var body = node.init.body.slice(0, -1); + node.init = node.init.body.slice(-1)[0].body; + body.push(node); + return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, { + body: body + }); + } + if (node instanceof AST_Scope && node !== self) + return node; + } + ); + self.transform(tt); + } + }); + + AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){ + var hoist_funs = compressor.option("hoist_funs"); + var hoist_vars = compressor.option("hoist_vars"); + var self = this; + if (hoist_funs || hoist_vars) { + var dirs = []; + var hoisted = []; + var vars = new Dictionary(), vars_found = 0, var_decl = 0; + // let's count var_decl first, we seem to waste a lot of + // space if we hoist `var` when there's only one. + self.walk(new TreeWalker(function(node){ + if (node instanceof AST_Scope && node !== self) + return true; + if (node instanceof AST_Var) { + ++var_decl; + return true; + } + })); + hoist_vars = hoist_vars && var_decl > 1; + var tt = new TreeTransformer( + function before(node) { + if (node !== self) { + if (node instanceof AST_Directive) { + dirs.push(node); + return make_node(AST_EmptyStatement, node); + } + if (node instanceof AST_Defun && hoist_funs) { + hoisted.push(node); + return make_node(AST_EmptyStatement, node); + } + if (node instanceof AST_Var && hoist_vars) { + node.definitions.forEach(function(def){ + vars.set(def.name.name, def); + ++vars_found; + }); + var seq = node.to_assignments(); + var p = tt.parent(); + if (p instanceof AST_ForIn && p.init === node) { + if (seq == null) return node.definitions[0].name; + return seq; + } + if (p instanceof AST_For && p.init === node) { + return seq; + } + if (!seq) return make_node(AST_EmptyStatement, node); + return make_node(AST_SimpleStatement, node, { + body: seq + }); + } + if (node instanceof AST_Scope) + return node; // to avoid descending in nested scopes + } + } + ); + self = self.transform(tt); + if (vars_found > 0) { + // collect only vars which don't show up in self's arguments list + var defs = []; + vars.each(function(def, name){ + if (self instanceof AST_Lambda + && find_if(function(x){ return x.name == def.name.name }, + self.argnames)) { + vars.del(name); + } else { + def = def.clone(); + def.value = null; + defs.push(def); + vars.set(name, def); + } + }); + if (defs.length > 0) { + // try to merge in assignments + for (var i = 0; i < self.body.length;) { + if (self.body[i] instanceof AST_SimpleStatement) { + var expr = self.body[i].body, sym, assign; + if (expr instanceof AST_Assign + && expr.operator == "=" + && (sym = expr.left) instanceof AST_Symbol + && vars.has(sym.name)) + { + var def = vars.get(sym.name); + if (def.value) break; + def.value = expr.right; + remove(defs, def); + defs.push(def); + self.body.splice(i, 1); + continue; + } + if (expr instanceof AST_Seq + && (assign = expr.car) instanceof AST_Assign + && assign.operator == "=" + && (sym = assign.left) instanceof AST_Symbol + && vars.has(sym.name)) + { + var def = vars.get(sym.name); + if (def.value) break; + def.value = assign.right; + remove(defs, def); + defs.push(def); + self.body[i].body = expr.cdr; + continue; + } + } + if (self.body[i] instanceof AST_EmptyStatement) { + self.body.splice(i, 1); + continue; + } + if (self.body[i] instanceof AST_BlockStatement) { + var tmp = [ i, 1 ].concat(self.body[i].body); + self.body.splice.apply(self.body, tmp); + continue; + } + break; + } + defs = make_node(AST_Var, self, { + definitions: defs + }); + hoisted.push(defs); + }; + } + self.body = dirs.concat(hoisted, self.body); + } + return self; + }); + + OPT(AST_SimpleStatement, function(self, compressor){ + if (compressor.option("side_effects")) { + if (!self.body.has_side_effects()) { + compressor.warn("Dropping side-effect-free statement [{file}:{line},{col}]", self.start); + return make_node(AST_EmptyStatement, self); + } + } + return self; + }); + + OPT(AST_DWLoop, function(self, compressor){ + var cond = self.condition.evaluate(compressor); + self.condition = cond[0]; + if (!compressor.option("loops")) return self; + if (cond.length > 1) { + if (cond[1]) { + return make_node(AST_For, self, { + body: self.body + }); + } else if (self instanceof AST_While) { + if (compressor.option("dead_code")) { + var a = []; + extract_declarations_from_unreachable_code(compressor, self.body, a); + return make_node(AST_BlockStatement, self, { body: a }); + } + } + } + return self; + }); + + function if_break_in_loop(self, compressor) { + function drop_it(rest) { + rest = as_statement_array(rest); + if (self.body instanceof AST_BlockStatement) { + self.body = self.body.clone(); + self.body.body = rest.concat(self.body.body.slice(1)); + self.body = self.body.transform(compressor); + } else { + self.body = make_node(AST_BlockStatement, self.body, { + body: rest + }).transform(compressor); + } + if_break_in_loop(self, compressor); + } + var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body; + if (first instanceof AST_If) { + if (first.body instanceof AST_Break + && compressor.loopcontrol_target(first.body.label) === self) { + if (self.condition) { + self.condition = make_node(AST_Binary, self.condition, { + left: self.condition, + operator: "&&", + right: first.condition.negate(compressor), + }); + } else { + self.condition = first.condition.negate(compressor); + } + drop_it(first.alternative); + } + else if (first.alternative instanceof AST_Break + && compressor.loopcontrol_target(first.alternative.label) === self) { + if (self.condition) { + self.condition = make_node(AST_Binary, self.condition, { + left: self.condition, + operator: "&&", + right: first.condition, + }); + } else { + self.condition = first.condition; + } + drop_it(first.body); + } + } + }; + + OPT(AST_While, function(self, compressor) { + if (!compressor.option("loops")) return self; + self = AST_DWLoop.prototype.optimize.call(self, compressor); + if (self instanceof AST_While) { + if_break_in_loop(self, compressor); + self = make_node(AST_For, self, self).transform(compressor); + } + return self; + }); + + OPT(AST_For, function(self, compressor){ + var cond = self.condition; + if (cond) { + cond = cond.evaluate(compressor); + self.condition = cond[0]; + } + if (!compressor.option("loops")) return self; + if (cond) { + if (cond.length > 1 && !cond[1]) { + if (compressor.option("dead_code")) { + var a = []; + if (self.init instanceof AST_Statement) { + a.push(self.init); + } + else if (self.init) { + a.push(make_node(AST_SimpleStatement, self.init, { + body: self.init + })); + } + extract_declarations_from_unreachable_code(compressor, self.body, a); + return make_node(AST_BlockStatement, self, { body: a }); + } + } + } + if_break_in_loop(self, compressor); + return self; + }); + + OPT(AST_If, function(self, compressor){ + if (!compressor.option("conditionals")) return self; + // if condition can be statically determined, warn and drop + // one of the blocks. note, statically determined implies + // “has no side effects”; also it doesn't work for cases like + // `x && true`, though it probably should. + var cond = self.condition.evaluate(compressor); + self.condition = cond[0]; + if (cond.length > 1) { + if (cond[1]) { + compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start); + if (compressor.option("dead_code")) { + var a = []; + if (self.alternative) { + extract_declarations_from_unreachable_code(compressor, self.alternative, a); + } + a.push(self.body); + return make_node(AST_BlockStatement, self, { body: a }).transform(compressor); + } + } else { + compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start); + if (compressor.option("dead_code")) { + var a = []; + extract_declarations_from_unreachable_code(compressor, self.body, a); + if (self.alternative) a.push(self.alternative); + return make_node(AST_BlockStatement, self, { body: a }).transform(compressor); + } + } + } + if (is_empty(self.alternative)) self.alternative = null; + var negated = self.condition.negate(compressor); + var negated_is_best = best_of(self.condition, negated) === negated; + if (self.alternative && negated_is_best) { + negated_is_best = false; // because we already do the switch here. + self.condition = negated; + var tmp = self.body; + self.body = self.alternative || make_node(AST_EmptyStatement); + self.alternative = tmp; + } + if (is_empty(self.body) && is_empty(self.alternative)) { + return make_node(AST_SimpleStatement, self.condition, { + body: self.condition + }).transform(compressor); + } + if (self.body instanceof AST_SimpleStatement + && self.alternative instanceof AST_SimpleStatement) { + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Conditional, self, { + condition : self.condition, + consequent : self.body.body, + alternative : self.alternative.body + }) + }).transform(compressor); + } + if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) { + if (negated_is_best) return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator : "||", + left : negated, + right : self.body.body + }) + }).transform(compressor); + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator : "&&", + left : self.condition, + right : self.body.body + }) + }).transform(compressor); + } + if (self.body instanceof AST_EmptyStatement + && self.alternative + && self.alternative instanceof AST_SimpleStatement) { + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator : "||", + left : self.condition, + right : self.alternative.body + }) + }).transform(compressor); + } + if (self.body instanceof AST_Exit + && self.alternative instanceof AST_Exit + && self.body.TYPE == self.alternative.TYPE) { + return make_node(self.body.CTOR, self, { + value: make_node(AST_Conditional, self, { + condition : self.condition, + consequent : self.body.value || make_node(AST_Undefined, self.body).optimize(compressor), + alternative : self.alternative.value || make_node(AST_Undefined, self.alternative).optimize(compressor) + }) + }).transform(compressor); + } + if (self.body instanceof AST_If + && !self.body.alternative + && !self.alternative) { + self.condition = make_node(AST_Binary, self.condition, { + operator: "&&", + left: self.condition, + right: self.body.condition + }).transform(compressor); + self.body = self.body.body; + } + if (aborts(self.body)) { + if (self.alternative) { + var alt = self.alternative; + self.alternative = null; + return make_node(AST_BlockStatement, self, { + body: [ self, alt ] + }).transform(compressor); + } + } + if (aborts(self.alternative)) { + var body = self.body; + self.body = self.alternative; + self.condition = negated_is_best ? negated : self.condition.negate(compressor); + self.alternative = null; + return make_node(AST_BlockStatement, self, { + body: [ self, body ] + }).transform(compressor); + } + return self; + }); + + OPT(AST_Switch, function(self, compressor){ + if (self.body.length == 0 && compressor.option("conditionals")) { + return make_node(AST_SimpleStatement, self, { + body: self.expression + }).transform(compressor); + } + for(;;) { + var last_branch = self.body[self.body.length - 1]; + if (last_branch) { + var stat = last_branch.body[last_branch.body.length - 1]; // last statement + if (stat instanceof AST_Break && loop_body(compressor.loopcontrol_target(stat.label)) === self) + last_branch.body.pop(); + if (last_branch instanceof AST_Default && last_branch.body.length == 0) { + self.body.pop(); + continue; + } + } + break; + } + var exp = self.expression.evaluate(compressor); + out: if (exp.length == 2) try { + // constant expression + self.expression = exp[0]; + if (!compressor.option("dead_code")) break out; + var value = exp[1]; + var in_if = false; + var in_block = false; + var started = false; + var stopped = false; + var ruined = false; + var tt = new TreeTransformer(function(node, descend, in_list){ + if (node instanceof AST_Lambda || node instanceof AST_SimpleStatement) { + // no need to descend these node types + return node; + } + else if (node instanceof AST_Switch && node === self) { + node = node.clone(); + descend(node, this); + return ruined ? node : make_node(AST_BlockStatement, node, { + body: node.body.reduce(function(a, branch){ + return a.concat(branch.body); + }, []) + }).transform(compressor); + } + else if (node instanceof AST_If || node instanceof AST_Try) { + var save = in_if; + in_if = !in_block; + descend(node, this); + in_if = save; + return node; + } + else if (node instanceof AST_StatementWithBody || node instanceof AST_Switch) { + var save = in_block; + in_block = true; + descend(node, this); + in_block = save; + return node; + } + else if (node instanceof AST_Break && this.loopcontrol_target(node.label) === self) { + if (in_if) { + ruined = true; + return node; + } + if (in_block) return node; + stopped = true; + return in_list ? MAP.skip : make_node(AST_EmptyStatement, node); + } + else if (node instanceof AST_SwitchBranch && this.parent() === self) { + if (stopped) return MAP.skip; + if (node instanceof AST_Case) { + var exp = node.expression.evaluate(compressor); + if (exp.length < 2) { + // got a case with non-constant expression, baling out + throw self; + } + if (exp[1] === value || started) { + started = true; + if (aborts(node)) stopped = true; + descend(node, this); + return node; + } + return MAP.skip; + } + descend(node, this); + return node; + } + }); + tt.stack = compressor.stack.slice(); // so that's able to see parent nodes + self = self.transform(tt); + } catch(ex) { + if (ex !== self) throw ex; + } + return self; + }); + + OPT(AST_Case, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + return self; + }); + + OPT(AST_Try, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + return self; + }); + + AST_Definitions.DEFMETHOD("remove_initializers", function(){ + this.definitions.forEach(function(def){ def.value = null }); + }); + + AST_Definitions.DEFMETHOD("to_assignments", function(){ + var assignments = this.definitions.reduce(function(a, def){ + if (def.value) { + var name = make_node(AST_SymbolRef, def.name, def.name); + a.push(make_node(AST_Assign, def, { + operator : "=", + left : name, + right : def.value + })); + } + return a; + }, []); + if (assignments.length == 0) return null; + return AST_Seq.from_array(assignments); + }); + + OPT(AST_Definitions, function(self, compressor){ + if (self.definitions.length == 0) + return make_node(AST_EmptyStatement, self); + return self; + }); + + OPT(AST_Function, function(self, compressor){ + self = AST_Lambda.prototype.optimize.call(self, compressor); + if (compressor.option("unused")) { + if (self.name && self.name.unreferenced()) { + self.name = null; + } + } + return self; + }); + + OPT(AST_Call, function(self, compressor){ + if (compressor.option("unsafe")) { + var exp = self.expression; + if (exp instanceof AST_SymbolRef && exp.undeclared()) { + switch (exp.name) { + case "Array": + if (self.args.length != 1) { + return make_node(AST_Array, self, { + elements: self.args + }); + } + break; + case "Object": + if (self.args.length == 0) { + return make_node(AST_Object, self, { + properties: [] + }); + } + break; + case "String": + if (self.args.length == 0) return make_node(AST_String, self, { + value: "" + }); + return make_node(AST_Binary, self, { + left: self.args[0], + operator: "+", + right: make_node(AST_String, self, { value: "" }) + }); + } + } + else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) { + return make_node(AST_Binary, self, { + left: make_node(AST_String, self, { value: "" }), + operator: "+", + right: exp.expression + }).transform(compressor); + } + } + if (compressor.option("side_effects")) { + if (self.expression instanceof AST_Function + && self.args.length == 0 + && !AST_Block.prototype.has_side_effects.call(self.expression)) { + return make_node(AST_Undefined, self).transform(compressor); + } + } + return self; + }); + + OPT(AST_New, function(self, compressor){ + if (compressor.option("unsafe")) { + var exp = self.expression; + if (exp instanceof AST_SymbolRef && exp.undeclared()) { + switch (exp.name) { + case "Object": + case "RegExp": + case "Function": + case "Error": + case "Array": + return make_node(AST_Call, self, self).transform(compressor); + } + } + } + return self; + }); + + OPT(AST_Seq, function(self, compressor){ + if (!compressor.option("side_effects")) + return self; + if (!self.car.has_side_effects()) { + // we shouldn't compress (1,eval)(something) to + // eval(something) because that changes the meaning of + // eval (becomes lexical instead of global). + var p; + if (!(self.cdr instanceof AST_SymbolRef + && self.cdr.name == "eval" + && self.cdr.undeclared() + && (p = compressor.parent()) instanceof AST_Call + && p.expression === self)) { + return self.cdr; + } + } + if (compressor.option("cascade")) { + if (self.car instanceof AST_Assign + && !self.car.left.has_side_effects() + && self.car.left.equivalent_to(self.cdr)) { + return self.car; + } + if (!self.car.has_side_effects() + && !self.cdr.has_side_effects() + && self.car.equivalent_to(self.cdr)) { + return self.car; + } + } + return self; + }); + + AST_Unary.DEFMETHOD("lift_sequences", function(compressor){ + if (compressor.option("sequences")) { + if (this.expression instanceof AST_Seq) { + var seq = this.expression; + var x = seq.to_array(); + this.expression = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + } + return this; + }); + + OPT(AST_UnaryPostfix, function(self, compressor){ + return self.lift_sequences(compressor); + }); + + OPT(AST_UnaryPrefix, function(self, compressor){ + self = self.lift_sequences(compressor); + var e = self.expression; + if (compressor.option("booleans") && compressor.in_boolean_context()) { + switch (self.operator) { + case "!": + if (e instanceof AST_UnaryPrefix && e.operator == "!") { + // !!foo ==> foo, if we're in boolean context + return e.expression; + } + break; + case "typeof": + // typeof always returns a non-empty string, thus it's + // always true in booleans + compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + if (e instanceof AST_Binary && self.operator == "!") { + self = best_of(self, e.negate(compressor)); + } + } + return self.evaluate(compressor)[0]; + }); + + AST_Binary.DEFMETHOD("lift_sequences", function(compressor){ + if (compressor.option("sequences")) { + if (this.left instanceof AST_Seq) { + var seq = this.left; + var x = seq.to_array(); + this.left = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + if (this.right instanceof AST_Seq + && !(this.operator == "||" || this.operator == "&&") + && !this.left.has_side_effects()) { + var seq = this.right; + var x = seq.to_array(); + this.right = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + } + return this; + }); + + var commutativeOperators = makePredicate("== === != !== * & | ^"); + + OPT(AST_Binary, function(self, compressor){ + function reverse(op) { + if (!(self.left.has_side_effects() || self.right.has_side_effects())) { + if (op) self.operator = op; + var tmp = self.left; + self.left = self.right; + self.right = tmp; + } + }; + if (commutativeOperators(self.operator)) { + if (self.right instanceof AST_Constant + && !(self.left instanceof AST_Constant)) { + reverse(); + } + } + self = self.lift_sequences(compressor); + if (compressor.option("comparisons")) switch (self.operator) { + case "===": + case "!==": + if ((self.left.is_string(compressor) && self.right.is_string(compressor)) || + (self.left.is_boolean() && self.right.is_boolean())) { + self.operator = self.operator.substr(0, 2); + } + // XXX: intentionally falling down to the next case + case "==": + case "!=": + if (self.left instanceof AST_String + && self.left.value == "undefined" + && self.right instanceof AST_UnaryPrefix + && self.right.operator == "typeof" + && compressor.option("unsafe")) { + if (!(self.right.expression instanceof AST_SymbolRef) + || !self.right.expression.undeclared()) { + self.left = self.right.expression; + self.right = make_node(AST_Undefined, self.left).optimize(compressor); + if (self.operator.length == 2) self.operator += "="; + } + } + break; + } + if (compressor.option("booleans") && compressor.in_boolean_context()) switch (self.operator) { + case "&&": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if ((ll.length > 1 && !ll[1]) || (rr.length > 1 && !rr[1])) { + compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start); + return make_node(AST_False, self); + } + if (ll.length > 1 && ll[1]) { + return rr[0]; + } + if (rr.length > 1 && rr[1]) { + return ll[0]; + } + break; + case "||": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if ((ll.length > 1 && ll[1]) || (rr.length > 1 && rr[1])) { + compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + if (ll.length > 1 && !ll[1]) { + return rr[0]; + } + if (rr.length > 1 && !rr[1]) { + return ll[0]; + } + break; + case "+": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if ((ll.length > 1 && ll[0] instanceof AST_String && ll[1]) || + (rr.length > 1 && rr[0] instanceof AST_String && rr[1])) { + compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + break; + } + var exp = self.evaluate(compressor); + if (exp.length > 1) { + if (best_of(exp[0], self) !== self) + return exp[0]; + } + if (compressor.option("comparisons")) { + if (!(compressor.parent() instanceof AST_Binary) + || compressor.parent() instanceof AST_Assign) { + var negated = make_node(AST_UnaryPrefix, self, { + operator: "!", + expression: self.negate(compressor) + }); + self = best_of(self, negated); + } + switch (self.operator) { + case "<": reverse(">"); break; + case "<=": reverse(">="); break; + } + } + if (self.operator == "+" && self.right instanceof AST_String + && self.right.getValue() === "" && self.left instanceof AST_Binary + && self.left.operator == "+" && self.left.is_string(compressor)) { + return self.left; + } + return self; + }); + + OPT(AST_SymbolRef, function(self, compressor){ + if (self.undeclared()) { + var defines = compressor.option("global_defs"); + if (defines && defines.hasOwnProperty(self.name)) { + return make_node_from_constant(compressor, defines[self.name], self); + } + switch (self.name) { + case "undefined": + return make_node(AST_Undefined, self); + case "NaN": + return make_node(AST_NaN, self); + case "Infinity": + return make_node(AST_Infinity, self); + } + } + return self; + }); + + OPT(AST_Undefined, function(self, compressor){ + if (compressor.option("unsafe")) { + var scope = compressor.find_parent(AST_Scope); + var undef = scope.find_variable("undefined"); + if (undef) { + var ref = make_node(AST_SymbolRef, self, { + name : "undefined", + scope : scope, + thedef : undef + }); + ref.reference(); + return ref; + } + } + return self; + }); + + var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ]; + OPT(AST_Assign, function(self, compressor){ + self = self.lift_sequences(compressor); + if (self.operator == "=" + && self.left instanceof AST_SymbolRef + && self.right instanceof AST_Binary + && self.right.left instanceof AST_SymbolRef + && self.right.left.name == self.left.name + && member(self.right.operator, ASSIGN_OPS)) { + self.operator = self.right.operator + "="; + self.right = self.right.right; + } + return self; + }); + + OPT(AST_Conditional, function(self, compressor){ + if (!compressor.option("conditionals")) return self; + if (self.condition instanceof AST_Seq) { + var car = self.condition.car; + self.condition = self.condition.cdr; + return AST_Seq.cons(car, self); + } + var cond = self.condition.evaluate(compressor); + if (cond.length > 1) { + if (cond[1]) { + compressor.warn("Condition always true [{file}:{line},{col}]", self.start); + return self.consequent; + } else { + compressor.warn("Condition always false [{file}:{line},{col}]", self.start); + return self.alternative; + } + } + var negated = cond[0].negate(compressor); + if (best_of(cond[0], negated) === negated) { + self = make_node(AST_Conditional, self, { + condition: negated, + consequent: self.alternative, + alternative: self.consequent + }); + } + var consequent = self.consequent; + var alternative = self.alternative; + if (consequent instanceof AST_Assign + && alternative instanceof AST_Assign + && consequent.operator == alternative.operator + && consequent.left.equivalent_to(alternative.left) + ) { + /* + * Stuff like this: + * if (foo) exp = something; else exp = something_else; + * ==> + * exp = foo ? something : something_else; + */ + self = make_node(AST_Assign, self, { + operator: consequent.operator, + left: consequent.left, + right: make_node(AST_Conditional, self, { + condition: self.condition, + consequent: consequent.right, + alternative: alternative.right + }) + }); + } + return self; + }); + + OPT(AST_Boolean, function(self, compressor){ + if (compressor.option("booleans")) { + var p = compressor.parent(); + if (p instanceof AST_Binary && (p.operator == "==" + || p.operator == "!=")) { + compressor.warn("Non-strict equality against boolean: {operator} {value} [{file}:{line},{col}]", { + operator : p.operator, + value : self.value, + file : p.start.file, + line : p.start.line, + col : p.start.col, + }); + return make_node(AST_Number, self, { + value: +self.value + }); + } + return make_node(AST_UnaryPrefix, self, { + operator: "!", + expression: make_node(AST_Number, self, { + value: 1 - self.value + }) + }); + } + return self; + }); + + OPT(AST_Sub, function(self, compressor){ + var prop = self.property; + if (prop instanceof AST_String && compressor.option("properties")) { + prop = prop.getValue(); + if (is_identifier(prop) || compressor.option("screw_ie8")) { + return make_node(AST_Dot, self, { + expression : self.expression, + property : prop + }); + } + } + return self; + }); + + function literals_in_boolean_context(self, compressor) { + if (compressor.option("booleans") && compressor.in_boolean_context()) { + return make_node(AST_True, self); + } + return self; + }; + OPT(AST_Array, literals_in_boolean_context); + OPT(AST_Object, literals_in_boolean_context); + OPT(AST_RegExp, literals_in_boolean_context); + +})(); diff --git a/homework7/project_express/node_modules/uglify-js/lib/mozilla-ast.js b/homework7/project_express/node_modules/uglify-js/lib/mozilla-ast.js new file mode 100644 index 0000000..d795094 --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/lib/mozilla-ast.js @@ -0,0 +1,267 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +(function(){ + + var MOZ_TO_ME = { + TryStatement : function(M) { + return new AST_Try({ + start : my_start_token(M), + end : my_end_token(M), + body : from_moz(M.block).body, + bcatch : from_moz(M.handlers[0]), + bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null + }); + }, + CatchClause : function(M) { + return new AST_Catch({ + start : my_start_token(M), + end : my_end_token(M), + argname : from_moz(M.param), + body : from_moz(M.body).body + }); + }, + ObjectExpression : function(M) { + return new AST_Object({ + start : my_start_token(M), + end : my_end_token(M), + properties : M.properties.map(function(prop){ + var key = prop.key; + var name = key.type == "Identifier" ? key.name : key.value; + var args = { + start : my_start_token(key), + end : my_end_token(prop.value), + key : name, + value : from_moz(prop.value) + }; + switch (prop.kind) { + case "init": + return new AST_ObjectKeyVal(args); + case "set": + args.value.name = from_moz(key); + return new AST_ObjectSetter(args); + case "get": + args.value.name = from_moz(key); + return new AST_ObjectGetter(args); + } + }) + }); + }, + SequenceExpression : function(M) { + return AST_Seq.from_array(M.expressions.map(from_moz)); + }, + MemberExpression : function(M) { + return new (M.computed ? AST_Sub : AST_Dot)({ + start : my_start_token(M), + end : my_end_token(M), + property : M.computed ? from_moz(M.property) : M.property.name, + expression : from_moz(M.object) + }); + }, + SwitchCase : function(M) { + return new (M.test ? AST_Case : AST_Default)({ + start : my_start_token(M), + end : my_end_token(M), + expression : from_moz(M.test), + body : M.consequent.map(from_moz) + }); + }, + Literal : function(M) { + var val = M.value, args = { + start : my_start_token(M), + end : my_end_token(M) + }; + if (val === null) return new AST_Null(args); + switch (typeof val) { + case "string": + args.value = val; + return new AST_String(args); + case "number": + args.value = val; + return new AST_Number(args); + case "boolean": + return new (val ? AST_True : AST_False)(args); + default: + args.value = val; + return new AST_RegExp(args); + } + }, + UnaryExpression: From_Moz_Unary, + UpdateExpression: From_Moz_Unary, + Identifier: function(M) { + var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2]; + return new (M.name == "this" ? AST_This + : p.type == "LabeledStatement" ? AST_Label + : p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar) + : p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg) + : p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg) + : p.type == "CatchClause" ? AST_SymbolCatch + : p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef + : AST_SymbolRef)({ + start : my_start_token(M), + end : my_end_token(M), + name : M.name + }); + } + }; + + function From_Moz_Unary(M) { + var prefix = "prefix" in M ? M.prefix + : M.type == "UnaryExpression" ? true : false; + return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({ + start : my_start_token(M), + end : my_end_token(M), + operator : M.operator, + expression : from_moz(M.argument) + }); + }; + + var ME_TO_MOZ = {}; + + map("Node", AST_Node); + map("Program", AST_Toplevel, "body@body"); + map("Function", AST_Function, "id>name, params@argnames, body%body"); + map("EmptyStatement", AST_EmptyStatement); + map("BlockStatement", AST_BlockStatement, "body@body"); + map("ExpressionStatement", AST_SimpleStatement, "expression>body"); + map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative"); + map("LabeledStatement", AST_LabeledStatement, "label>label, body>body"); + map("BreakStatement", AST_Break, "label>label"); + map("ContinueStatement", AST_Continue, "label>label"); + map("WithStatement", AST_With, "object>expression, body>body"); + map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body"); + map("ReturnStatement", AST_Return, "argument>value"); + map("ThrowStatement", AST_Throw, "argument>value"); + map("WhileStatement", AST_While, "test>condition, body>body"); + map("DoWhileStatement", AST_Do, "test>condition, body>body"); + map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body"); + map("ForInStatement", AST_ForIn, "left>init, right>object, body>body"); + map("DebuggerStatement", AST_Debugger); + map("FunctionDeclaration", AST_Defun, "id>name, params@argnames, body%body"); + map("VariableDeclaration", AST_Var, "declarations@definitions"); + map("VariableDeclarator", AST_VarDef, "id>name, init>value"); + + map("ThisExpression", AST_This); + map("ArrayExpression", AST_Array, "elements@elements"); + map("FunctionExpression", AST_Function, "id>name, params@argnames, body%body"); + map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right"); + map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right"); + map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right"); + map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative"); + map("NewExpression", AST_New, "callee>expression, arguments@args"); + map("CallExpression", AST_Call, "callee>expression, arguments@args"); + + /* -----[ tools ]----- */ + + function my_start_token(moznode) { + return new AST_Token({ + file : moznode.loc && moznode.loc.source, + line : moznode.loc && moznode.loc.start.line, + col : moznode.loc && moznode.loc.start.column, + pos : moznode.start, + endpos : moznode.start + }); + }; + + function my_end_token(moznode) { + return new AST_Token({ + file : moznode.loc && moznode.loc.source, + line : moznode.loc && moznode.loc.end.line, + col : moznode.loc && moznode.loc.end.column, + pos : moznode.end, + endpos : moznode.end + }); + }; + + function map(moztype, mytype, propmap) { + var moz_to_me = "function From_Moz_" + moztype + "(M){\n"; + moz_to_me += "return new mytype({\n" + + "start: my_start_token(M),\n" + + "end: my_end_token(M)"; + + if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop){ + var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop); + if (!m) throw new Error("Can't understand property map: " + prop); + var moz = "M." + m[1], how = m[2], my = m[3]; + moz_to_me += ",\n" + my + ": "; + if (how == "@") { + moz_to_me += moz + ".map(from_moz)"; + } else if (how == ">") { + moz_to_me += "from_moz(" + moz + ")"; + } else if (how == "=") { + moz_to_me += moz; + } else if (how == "%") { + moz_to_me += "from_moz(" + moz + ").body"; + } else throw new Error("Can't understand operator in propmap: " + prop); + }); + moz_to_me += "\n})}"; + + // moz_to_me = parse(moz_to_me).print_to_string({ beautify: true }); + // console.log(moz_to_me); + + moz_to_me = new Function("mytype", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")( + mytype, my_start_token, my_end_token, from_moz + ); + return MOZ_TO_ME[moztype] = moz_to_me; + }; + + var FROM_MOZ_STACK = null; + + function from_moz(node) { + FROM_MOZ_STACK.push(node); + var ret = node != null ? MOZ_TO_ME[node.type](node) : null; + FROM_MOZ_STACK.pop(); + return ret; + }; + + AST_Node.from_mozilla_ast = function(node){ + var save_stack = FROM_MOZ_STACK; + FROM_MOZ_STACK = []; + var ast = from_moz(node); + FROM_MOZ_STACK = save_stack; + return ast; + }; + +})(); diff --git a/homework7/project_express/node_modules/uglify-js/lib/output.js b/homework7/project_express/node_modules/uglify-js/lib/output.js new file mode 100644 index 0000000..defd021 --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/lib/output.js @@ -0,0 +1,1225 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function OutputStream(options) { + + options = defaults(options, { + indent_start : 0, + indent_level : 4, + quote_keys : false, + space_colon : true, + ascii_only : false, + inline_script : false, + width : 80, + max_line_len : 32000, + ie_proof : true, + beautify : false, + source_map : null, + bracketize : false, + semicolons : true, + comments : false, + preserve_line : false + }, true); + + var indentation = 0; + var current_col = 0; + var current_line = 1; + var current_pos = 0; + var OUTPUT = ""; + + function to_ascii(str, identifier) { + return str.replace(/[\u0080-\uffff]/g, function(ch) { + var code = ch.charCodeAt(0).toString(16); + if (code.length <= 2 && !identifier) { + while (code.length < 2) code = "0" + code; + return "\\x" + code; + } else { + while (code.length < 4) code = "0" + code; + return "\\u" + code; + } + }); + }; + + function make_string(str) { + var dq = 0, sq = 0; + str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s){ + switch (s) { + case "\\": return "\\\\"; + case "\b": return "\\b"; + case "\f": return "\\f"; + case "\n": return "\\n"; + case "\r": return "\\r"; + case "\u2028": return "\\u2028"; + case "\u2029": return "\\u2029"; + case '"': ++dq; return '"'; + case "'": ++sq; return "'"; + case "\0": return "\\0"; + } + return s; + }); + if (options.ascii_only) str = to_ascii(str); + if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'"; + else return '"' + str.replace(/\x22/g, '\\"') + '"'; + }; + + function encode_string(str) { + var ret = make_string(str); + if (options.inline_script) + ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1"); + return ret; + }; + + function make_name(name) { + name = name.toString(); + if (options.ascii_only) + name = to_ascii(name, true); + return name; + }; + + function make_indent(back) { + return repeat_string(" ", options.indent_start + indentation - back * options.indent_level); + }; + + /* -----[ beautification/minification ]----- */ + + var might_need_space = false; + var might_need_semicolon = false; + var last = null; + + function last_char() { + return last.charAt(last.length - 1); + }; + + function maybe_newline() { + if (options.max_line_len && current_col > options.max_line_len) + print("\n"); + }; + + var requireSemicolonChars = makePredicate("( [ + * / - , ."); + + function print(str) { + str = String(str); + var ch = str.charAt(0); + if (might_need_semicolon) { + if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) { + if (options.semicolons || requireSemicolonChars(ch)) { + OUTPUT += ";"; + current_col++; + current_pos++; + } else { + OUTPUT += "\n"; + current_pos++; + current_line++; + current_col = 0; + } + if (!options.beautify) + might_need_space = false; + } + might_need_semicolon = false; + maybe_newline(); + } + + if (!options.beautify && options.preserve_line && stack[stack.length - 1]) { + var target_line = stack[stack.length - 1].start.line; + while (current_line < target_line) { + OUTPUT += "\n"; + current_pos++; + current_line++; + current_col = 0; + might_need_space = false; + } + } + + if (might_need_space) { + var prev = last_char(); + if ((is_identifier_char(prev) + && (is_identifier_char(ch) || ch == "\\")) + || (/^[\+\-\/]$/.test(ch) && ch == prev)) + { + OUTPUT += " "; + current_col++; + current_pos++; + } + might_need_space = false; + } + var a = str.split(/\r?\n/), n = a.length - 1; + current_line += n; + if (n == 0) { + current_col += a[n].length; + } else { + current_col = a[n].length; + } + current_pos += str.length; + last = str; + OUTPUT += str; + }; + + var space = options.beautify ? function() { + print(" "); + } : function() { + might_need_space = true; + }; + + var indent = options.beautify ? function(half) { + if (options.beautify) { + print(make_indent(half ? 0.5 : 0)); + } + } : noop; + + var with_indent = options.beautify ? function(col, cont) { + if (col === true) col = next_indent(); + var save_indentation = indentation; + indentation = col; + var ret = cont(); + indentation = save_indentation; + return ret; + } : function(col, cont) { return cont() }; + + var newline = options.beautify ? function() { + print("\n"); + } : noop; + + var semicolon = options.beautify ? function() { + print(";"); + } : function() { + might_need_semicolon = true; + }; + + function force_semicolon() { + might_need_semicolon = false; + print(";"); + }; + + function next_indent() { + return indentation + options.indent_level; + }; + + function with_block(cont) { + var ret; + print("{"); + newline(); + with_indent(next_indent(), function(){ + ret = cont(); + }); + indent(); + print("}"); + return ret; + }; + + function with_parens(cont) { + print("("); + //XXX: still nice to have that for argument lists + //var ret = with_indent(current_col, cont); + var ret = cont(); + print(")"); + return ret; + }; + + function with_square(cont) { + print("["); + //var ret = with_indent(current_col, cont); + var ret = cont(); + print("]"); + return ret; + }; + + function comma() { + print(","); + space(); + }; + + function colon() { + print(":"); + if (options.space_colon) space(); + }; + + var add_mapping = options.source_map ? function(token, name) { + try { + if (token) options.source_map.add( + token.file || "?", + current_line, current_col, + token.line, token.col, + (!name && token.type == "name") ? token.value : name + ); + } catch(ex) { + AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", { + file: token.file, + line: token.line, + col: token.col, + cline: current_line, + ccol: current_col, + name: name || "" + }) + } + } : noop; + + function get() { + return OUTPUT; + }; + + var stack = []; + return { + get : get, + toString : get, + indent : indent, + indentation : function() { return indentation }, + current_width : function() { return current_col - indentation }, + should_break : function() { return options.width && this.current_width() >= options.width }, + newline : newline, + print : print, + space : space, + comma : comma, + colon : colon, + last : function() { return last }, + semicolon : semicolon, + force_semicolon : force_semicolon, + to_ascii : to_ascii, + print_name : function(name) { print(make_name(name)) }, + print_string : function(str) { print(encode_string(str)) }, + next_indent : next_indent, + with_indent : with_indent, + with_block : with_block, + with_parens : with_parens, + with_square : with_square, + add_mapping : add_mapping, + option : function(opt) { return options[opt] }, + line : function() { return current_line }, + col : function() { return current_col }, + pos : function() { return current_pos }, + push_node : function(node) { stack.push(node) }, + pop_node : function() { return stack.pop() }, + stack : function() { return stack }, + parent : function(n) { + return stack[stack.length - 2 - (n || 0)]; + } + }; + +}; + +/* -----[ code generators ]----- */ + +(function(){ + + /* -----[ utils ]----- */ + + function DEFPRINT(nodetype, generator) { + nodetype.DEFMETHOD("_codegen", generator); + }; + + AST_Node.DEFMETHOD("print", function(stream, force_parens){ + var self = this, generator = self._codegen; + stream.push_node(self); + if (force_parens || self.needs_parens(stream)) { + stream.with_parens(function(){ + self.add_comments(stream); + self.add_source_map(stream); + generator(self, stream); + }); + } else { + self.add_comments(stream); + self.add_source_map(stream); + generator(self, stream); + } + stream.pop_node(); + }); + + AST_Node.DEFMETHOD("print_to_string", function(options){ + var s = OutputStream(options); + this.print(s); + return s.get(); + }); + + /* -----[ comments ]----- */ + + AST_Node.DEFMETHOD("add_comments", function(output){ + var c = output.option("comments"), self = this; + if (c) { + var start = self.start; + if (start && !start._comments_dumped) { + start._comments_dumped = true; + var comments = start.comments_before; + + // XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112 + // if this node is `return` or `throw`, we cannot allow comments before + // the returned or thrown value. + if (self instanceof AST_Exit && + self.value && self.value.start.comments_before.length > 0) { + comments = (comments || []).concat(self.value.start.comments_before); + self.value.start.comments_before = []; + } + + if (c.test) { + comments = comments.filter(function(comment){ + return c.test(comment.value); + }); + } else if (typeof c == "function") { + comments = comments.filter(function(comment){ + return c(self, comment); + }); + } + comments.forEach(function(c){ + if (c.type == "comment1") { + output.print("//" + c.value + "\n"); + output.indent(); + } + else if (c.type == "comment2") { + output.print("/*" + c.value + "*/"); + if (start.nlb) { + output.print("\n"); + output.indent(); + } else { + output.space(); + } + } + }); + } + } + }); + + /* -----[ PARENTHESES ]----- */ + + function PARENS(nodetype, func) { + nodetype.DEFMETHOD("needs_parens", func); + }; + + PARENS(AST_Node, function(){ + return false; + }); + + // a function expression needs parens around it when it's provably + // the first token to appear in a statement. + PARENS(AST_Function, function(output){ + return first_in_statement(output); + }); + + // same goes for an object literal, because otherwise it would be + // interpreted as a block of code. + PARENS(AST_Object, function(output){ + return first_in_statement(output); + }); + + PARENS(AST_Unary, function(output){ + var p = output.parent(); + return p instanceof AST_PropAccess && p.expression === this; + }); + + PARENS(AST_Seq, function(output){ + var p = output.parent(); + return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4) + || p instanceof AST_Unary // !(foo, bar, baz) + || p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8 + || p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4 + || p instanceof AST_Dot // (1, {foo:2}).foo ==> 2 + || p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ] + || p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2 + || p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30) + * ==> 20 (side effect, set a := 10 and b := 20) */ + ; + }); + + PARENS(AST_Binary, function(output){ + var p = output.parent(); + // (foo && bar)() + if (p instanceof AST_Call && p.expression === this) + return true; + // typeof (foo && bar) + if (p instanceof AST_Unary) + return true; + // (foo && bar)["prop"], (foo && bar).prop + if (p instanceof AST_PropAccess && p.expression === this) + return true; + // this deals with precedence: 3 * (2 + 1) + if (p instanceof AST_Binary) { + var po = p.operator, pp = PRECEDENCE[po]; + var so = this.operator, sp = PRECEDENCE[so]; + if (pp > sp + || (pp == sp + && this === p.right + && !(so == po && + (so == "*" || + so == "&&" || + so == "||")))) { + return true; + } + } + }); + + PARENS(AST_PropAccess, function(output){ + var p = output.parent(); + if (p instanceof AST_New && p.expression === this) { + // i.e. new (foo.bar().baz) + // + // if there's one call into this subtree, then we need + // parens around it too, otherwise the call will be + // interpreted as passing the arguments to the upper New + // expression. + try { + this.walk(new TreeWalker(function(node){ + if (node instanceof AST_Call) throw p; + })); + } catch(ex) { + if (ex !== p) throw ex; + return true; + } + } + }); + + PARENS(AST_Call, function(output){ + var p = output.parent(); + return p instanceof AST_New && p.expression === this; + }); + + PARENS(AST_New, function(output){ + var p = output.parent(); + if (no_constructor_parens(this, output) + && (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]() + || p instanceof AST_Call && p.expression === this)) // (new foo)(bar) + return true; + }); + + PARENS(AST_Number, function(output){ + var p = output.parent(); + if (this.getValue() < 0 && p instanceof AST_PropAccess && p.expression === this) + return true; + }); + + PARENS(AST_NaN, function(output){ + var p = output.parent(); + if (p instanceof AST_PropAccess && p.expression === this) + return true; + }); + + function assign_and_conditional_paren_rules(output) { + var p = output.parent(); + // !(a = false) → true + if (p instanceof AST_Unary) + return true; + // 1 + (a = 2) + 3 → 6, side effect setting a = 2 + if (p instanceof AST_Binary && !(p instanceof AST_Assign)) + return true; + // (a = func)() —or— new (a = Object)() + if (p instanceof AST_Call && p.expression === this) + return true; + // (a = foo) ? bar : baz + if (p instanceof AST_Conditional && p.condition === this) + return true; + // (a = foo)["prop"] —or— (a = foo).prop + if (p instanceof AST_PropAccess && p.expression === this) + return true; + }; + + PARENS(AST_Assign, assign_and_conditional_paren_rules); + PARENS(AST_Conditional, assign_and_conditional_paren_rules); + + /* -----[ PRINTERS ]----- */ + + DEFPRINT(AST_Directive, function(self, output){ + output.print_string(self.value); + output.semicolon(); + }); + DEFPRINT(AST_Debugger, function(self, output){ + output.print("debugger"); + output.semicolon(); + }); + + /* -----[ statements ]----- */ + + function display_body(body, is_toplevel, output) { + var last = body.length - 1; + body.forEach(function(stmt, i){ + if (!(stmt instanceof AST_EmptyStatement)) { + output.indent(); + stmt.print(output); + if (!(i == last && is_toplevel)) { + output.newline(); + if (is_toplevel) output.newline(); + } + } + }); + }; + + AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output){ + force_statement(this.body, output); + }); + + DEFPRINT(AST_Statement, function(self, output){ + self.body.print(output); + output.semicolon(); + }); + DEFPRINT(AST_Toplevel, function(self, output){ + display_body(self.body, true, output); + output.print(""); + }); + DEFPRINT(AST_LabeledStatement, function(self, output){ + self.label.print(output); + output.colon(); + self.body.print(output); + }); + DEFPRINT(AST_SimpleStatement, function(self, output){ + self.body.print(output); + output.semicolon(); + }); + function print_bracketed(body, output) { + if (body.length > 0) output.with_block(function(){ + display_body(body, false, output); + }); + else output.print("{}"); + }; + DEFPRINT(AST_BlockStatement, function(self, output){ + print_bracketed(self.body, output); + }); + DEFPRINT(AST_EmptyStatement, function(self, output){ + output.semicolon(); + }); + DEFPRINT(AST_Do, function(self, output){ + output.print("do"); + output.space(); + self._do_print_body(output); + output.space(); + output.print("while"); + output.space(); + output.with_parens(function(){ + self.condition.print(output); + }); + output.semicolon(); + }); + DEFPRINT(AST_While, function(self, output){ + output.print("while"); + output.space(); + output.with_parens(function(){ + self.condition.print(output); + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_For, function(self, output){ + output.print("for"); + output.space(); + output.with_parens(function(){ + if (self.init) { + if (self.init instanceof AST_Definitions) { + self.init.print(output); + } else { + parenthesize_for_noin(self.init, output, true); + } + output.print(";"); + output.space(); + } else { + output.print(";"); + } + if (self.condition) { + self.condition.print(output); + output.print(";"); + output.space(); + } else { + output.print(";"); + } + if (self.step) { + self.step.print(output); + } + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_ForIn, function(self, output){ + output.print("for"); + output.space(); + output.with_parens(function(){ + self.init.print(output); + output.space(); + output.print("in"); + output.space(); + self.object.print(output); + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_With, function(self, output){ + output.print("with"); + output.space(); + output.with_parens(function(){ + self.expression.print(output); + }); + output.space(); + self._do_print_body(output); + }); + + /* -----[ functions ]----- */ + AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){ + var self = this; + if (!nokeyword) { + output.print("function"); + } + if (self.name) { + output.space(); + self.name.print(output); + } + output.with_parens(function(){ + self.argnames.forEach(function(arg, i){ + if (i) output.comma(); + arg.print(output); + }); + }); + output.space(); + print_bracketed(self.body, output); + }); + DEFPRINT(AST_Lambda, function(self, output){ + self._do_print(output); + }); + + /* -----[ exits ]----- */ + AST_Exit.DEFMETHOD("_do_print", function(output, kind){ + output.print(kind); + if (this.value) { + output.space(); + this.value.print(output); + } + output.semicolon(); + }); + DEFPRINT(AST_Return, function(self, output){ + self._do_print(output, "return"); + }); + DEFPRINT(AST_Throw, function(self, output){ + self._do_print(output, "throw"); + }); + + /* -----[ loop control ]----- */ + AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){ + output.print(kind); + if (this.label) { + output.space(); + this.label.print(output); + } + output.semicolon(); + }); + DEFPRINT(AST_Break, function(self, output){ + self._do_print(output, "break"); + }); + DEFPRINT(AST_Continue, function(self, output){ + self._do_print(output, "continue"); + }); + + /* -----[ if ]----- */ + function make_then(self, output) { + if (output.option("bracketize")) { + make_block(self.body, output); + return; + } + // The squeezer replaces "block"-s that contain only a single + // statement with the statement itself; technically, the AST + // is correct, but this can create problems when we output an + // IF having an ELSE clause where the THEN clause ends in an + // IF *without* an ELSE block (then the outer ELSE would refer + // to the inner IF). This function checks for this case and + // adds the block brackets if needed. + if (!self.body) + return output.force_semicolon(); + if (self.body instanceof AST_Do + && output.option("ie_proof")) { + // https://github.com/mishoo/UglifyJS/issues/#issue/57 IE + // croaks with "syntax error" on code like this: if (foo) + // do ... while(cond); else ... we need block brackets + // around do/while + make_block(self.body, output); + return; + } + var b = self.body; + while (true) { + if (b instanceof AST_If) { + if (!b.alternative) { + make_block(self.body, output); + return; + } + b = b.alternative; + } + else if (b instanceof AST_StatementWithBody) { + b = b.body; + } + else break; + } + force_statement(self.body, output); + }; + DEFPRINT(AST_If, function(self, output){ + output.print("if"); + output.space(); + output.with_parens(function(){ + self.condition.print(output); + }); + output.space(); + if (self.alternative) { + make_then(self, output); + output.space(); + output.print("else"); + output.space(); + force_statement(self.alternative, output); + } else { + self._do_print_body(output); + } + }); + + /* -----[ switch ]----- */ + DEFPRINT(AST_Switch, function(self, output){ + output.print("switch"); + output.space(); + output.with_parens(function(){ + self.expression.print(output); + }); + output.space(); + if (self.body.length > 0) output.with_block(function(){ + self.body.forEach(function(stmt, i){ + if (i) output.newline(); + output.indent(true); + stmt.print(output); + }); + }); + else output.print("{}"); + }); + AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output){ + if (this.body.length > 0) { + output.newline(); + this.body.forEach(function(stmt){ + output.indent(); + stmt.print(output); + output.newline(); + }); + } + }); + DEFPRINT(AST_Default, function(self, output){ + output.print("default:"); + self._do_print_body(output); + }); + DEFPRINT(AST_Case, function(self, output){ + output.print("case"); + output.space(); + self.expression.print(output); + output.print(":"); + self._do_print_body(output); + }); + + /* -----[ exceptions ]----- */ + DEFPRINT(AST_Try, function(self, output){ + output.print("try"); + output.space(); + print_bracketed(self.body, output); + if (self.bcatch) { + output.space(); + self.bcatch.print(output); + } + if (self.bfinally) { + output.space(); + self.bfinally.print(output); + } + }); + DEFPRINT(AST_Catch, function(self, output){ + output.print("catch"); + output.space(); + output.with_parens(function(){ + self.argname.print(output); + }); + output.space(); + print_bracketed(self.body, output); + }); + DEFPRINT(AST_Finally, function(self, output){ + output.print("finally"); + output.space(); + print_bracketed(self.body, output); + }); + + /* -----[ var/const ]----- */ + AST_Definitions.DEFMETHOD("_do_print", function(output, kind){ + output.print(kind); + output.space(); + this.definitions.forEach(function(def, i){ + if (i) output.comma(); + def.print(output); + }); + var p = output.parent(); + var in_for = p instanceof AST_For || p instanceof AST_ForIn; + var avoid_semicolon = in_for && p.init === this; + if (!avoid_semicolon) + output.semicolon(); + }); + DEFPRINT(AST_Var, function(self, output){ + self._do_print(output, "var"); + }); + DEFPRINT(AST_Const, function(self, output){ + self._do_print(output, "const"); + }); + + function parenthesize_for_noin(node, output, noin) { + if (!noin) node.print(output); + else try { + // need to take some precautions here: + // https://github.com/mishoo/UglifyJS2/issues/60 + node.walk(new TreeWalker(function(node){ + if (node instanceof AST_Binary && node.operator == "in") + throw output; + })); + node.print(output); + } catch(ex) { + if (ex !== output) throw ex; + node.print(output, true); + } + }; + + DEFPRINT(AST_VarDef, function(self, output){ + self.name.print(output); + if (self.value) { + output.space(); + output.print("="); + output.space(); + var p = output.parent(1); + var noin = p instanceof AST_For || p instanceof AST_ForIn; + parenthesize_for_noin(self.value, output, noin); + } + }); + + /* -----[ other expressions ]----- */ + DEFPRINT(AST_Call, function(self, output){ + self.expression.print(output); + if (self instanceof AST_New && no_constructor_parens(self, output)) + return; + output.with_parens(function(){ + self.args.forEach(function(expr, i){ + if (i) output.comma(); + expr.print(output); + }); + }); + }); + DEFPRINT(AST_New, function(self, output){ + output.print("new"); + output.space(); + AST_Call.prototype._codegen(self, output); + }); + + AST_Seq.DEFMETHOD("_do_print", function(output){ + this.car.print(output); + if (this.cdr) { + output.comma(); + if (output.should_break()) { + output.newline(); + output.indent(); + } + this.cdr.print(output); + } + }); + DEFPRINT(AST_Seq, function(self, output){ + self._do_print(output); + // var p = output.parent(); + // if (p instanceof AST_Statement) { + // output.with_indent(output.next_indent(), function(){ + // self._do_print(output); + // }); + // } else { + // self._do_print(output); + // } + }); + DEFPRINT(AST_Dot, function(self, output){ + var expr = self.expression; + expr.print(output); + if (expr instanceof AST_Number && expr.getValue() >= 0) { + if (!/[xa-f.]/i.test(output.last())) { + output.print("."); + } + } + output.print("."); + // the name after dot would be mapped about here. + output.add_mapping(self.end); + output.print_name(self.property); + }); + DEFPRINT(AST_Sub, function(self, output){ + self.expression.print(output); + output.print("["); + self.property.print(output); + output.print("]"); + }); + DEFPRINT(AST_UnaryPrefix, function(self, output){ + var op = self.operator; + output.print(op); + if (/^[a-z]/i.test(op)) + output.space(); + self.expression.print(output); + }); + DEFPRINT(AST_UnaryPostfix, function(self, output){ + self.expression.print(output); + output.print(self.operator); + }); + DEFPRINT(AST_Binary, function(self, output){ + self.left.print(output); + output.space(); + output.print(self.operator); + output.space(); + self.right.print(output); + }); + DEFPRINT(AST_Conditional, function(self, output){ + self.condition.print(output); + output.space(); + output.print("?"); + output.space(); + self.consequent.print(output); + output.space(); + output.colon(); + self.alternative.print(output); + }); + + /* -----[ literals ]----- */ + DEFPRINT(AST_Array, function(self, output){ + output.with_square(function(){ + var a = self.elements, len = a.length; + if (len > 0) output.space(); + a.forEach(function(exp, i){ + if (i) output.comma(); + exp.print(output); + }); + if (len > 0) output.space(); + }); + }); + DEFPRINT(AST_Object, function(self, output){ + if (self.properties.length > 0) output.with_block(function(){ + self.properties.forEach(function(prop, i){ + if (i) { + output.print(","); + output.newline(); + } + output.indent(); + prop.print(output); + }); + output.newline(); + }); + else output.print("{}"); + }); + DEFPRINT(AST_ObjectKeyVal, function(self, output){ + var key = self.key; + if (output.option("quote_keys")) { + output.print_string(key + ""); + } else if ((typeof key == "number" + || !output.option("beautify") + && +key + "" == key) + && parseFloat(key) >= 0) { + output.print(make_num(key)); + } else if (!is_identifier(key)) { + output.print_string(key); + } else { + output.print_name(key); + } + output.colon(); + self.value.print(output); + }); + DEFPRINT(AST_ObjectSetter, function(self, output){ + output.print("set"); + self.value._do_print(output, true); + }); + DEFPRINT(AST_ObjectGetter, function(self, output){ + output.print("get"); + self.value._do_print(output, true); + }); + DEFPRINT(AST_Symbol, function(self, output){ + var def = self.definition(); + output.print_name(def ? def.mangled_name || def.name : self.name); + }); + DEFPRINT(AST_Undefined, function(self, output){ + output.print("void 0"); + }); + DEFPRINT(AST_Hole, noop); + DEFPRINT(AST_Infinity, function(self, output){ + output.print("1/0"); + }); + DEFPRINT(AST_NaN, function(self, output){ + output.print("0/0"); + }); + DEFPRINT(AST_This, function(self, output){ + output.print("this"); + }); + DEFPRINT(AST_Constant, function(self, output){ + output.print(self.getValue()); + }); + DEFPRINT(AST_String, function(self, output){ + output.print_string(self.getValue()); + }); + DEFPRINT(AST_Number, function(self, output){ + output.print(make_num(self.getValue())); + }); + DEFPRINT(AST_RegExp, function(self, output){ + var str = self.getValue().toString(); + if (output.option("ascii_only")) + str = output.to_ascii(str); + output.print(str); + var p = output.parent(); + if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self) + output.print(" "); + }); + + function force_statement(stat, output) { + if (output.option("bracketize")) { + if (!stat || stat instanceof AST_EmptyStatement) + output.print("{}"); + else if (stat instanceof AST_BlockStatement) + stat.print(output); + else output.with_block(function(){ + output.indent(); + stat.print(output); + output.newline(); + }); + } else { + if (!stat || stat instanceof AST_EmptyStatement) + output.force_semicolon(); + else + stat.print(output); + } + }; + + // return true if the node at the top of the stack (that means the + // innermost node in the current output) is lexically the first in + // a statement. + function first_in_statement(output) { + var a = output.stack(), i = a.length, node = a[--i], p = a[--i]; + while (i > 0) { + if (p instanceof AST_Statement && p.body === node) + return true; + if ((p instanceof AST_Seq && p.car === node ) || + (p instanceof AST_Call && p.expression === node ) || + (p instanceof AST_Dot && p.expression === node ) || + (p instanceof AST_Sub && p.expression === node ) || + (p instanceof AST_Conditional && p.condition === node ) || + (p instanceof AST_Binary && p.left === node ) || + (p instanceof AST_UnaryPostfix && p.expression === node )) + { + node = p; + p = a[--i]; + } else { + return false; + } + } + }; + + // self should be AST_New. decide if we want to show parens or not. + function no_constructor_parens(self, output) { + return self.args.length == 0 && !output.option("beautify"); + }; + + function best_of(a) { + var best = a[0], len = best.length; + for (var i = 1; i < a.length; ++i) { + if (a[i].length < len) { + best = a[i]; + len = best.length; + } + } + return best; + }; + + function make_num(num) { + var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m; + if (Math.floor(num) === num) { + if (num >= 0) { + a.push("0x" + num.toString(16).toLowerCase(), // probably pointless + "0" + num.toString(8)); // same. + } else { + a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless + "-0" + (-num).toString(8)); // same. + } + if ((m = /^(.*?)(0+)$/.exec(num))) { + a.push(m[1] + "e" + m[2].length); + } + } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) { + a.push(m[2] + "e-" + (m[1].length + m[2].length), + str.substr(str.indexOf("."))); + } + return best_of(a); + }; + + function make_block(stmt, output) { + if (stmt instanceof AST_BlockStatement) { + stmt.print(output); + return; + } + output.with_block(function(){ + output.indent(); + stmt.print(output); + output.newline(); + }); + }; + + /* -----[ source map generators ]----- */ + + function DEFMAP(nodetype, generator) { + nodetype.DEFMETHOD("add_source_map", function(stream){ + generator(this, stream); + }); + }; + + // We could easily add info for ALL nodes, but it seems to me that + // would be quite wasteful, hence this noop in the base class. + DEFMAP(AST_Node, noop); + + function basic_sourcemap_gen(self, output) { + output.add_mapping(self.start); + }; + + // XXX: I'm not exactly sure if we need it for all of these nodes, + // or if we should add even more. + + DEFMAP(AST_Directive, basic_sourcemap_gen); + DEFMAP(AST_Debugger, basic_sourcemap_gen); + DEFMAP(AST_Symbol, basic_sourcemap_gen); + DEFMAP(AST_Jump, basic_sourcemap_gen); + DEFMAP(AST_StatementWithBody, basic_sourcemap_gen); + DEFMAP(AST_LabeledStatement, noop); // since the label symbol will mark it + DEFMAP(AST_Lambda, basic_sourcemap_gen); + DEFMAP(AST_Switch, basic_sourcemap_gen); + DEFMAP(AST_SwitchBranch, basic_sourcemap_gen); + DEFMAP(AST_BlockStatement, basic_sourcemap_gen); + DEFMAP(AST_Toplevel, noop); + DEFMAP(AST_New, basic_sourcemap_gen); + DEFMAP(AST_Try, basic_sourcemap_gen); + DEFMAP(AST_Catch, basic_sourcemap_gen); + DEFMAP(AST_Finally, basic_sourcemap_gen); + DEFMAP(AST_Definitions, basic_sourcemap_gen); + DEFMAP(AST_Constant, basic_sourcemap_gen); + DEFMAP(AST_ObjectProperty, function(self, output){ + output.add_mapping(self.start, self.key); + }); + +})(); diff --git a/homework7/project_express/node_modules/uglify-js/lib/parse.js b/homework7/project_express/node_modules/uglify-js/lib/parse.js new file mode 100644 index 0000000..da39b5b --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/lib/parse.js @@ -0,0 +1,1401 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + Parser based on parse-js (http://marijn.haverbeke.nl/parse-js/). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +var KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with'; +var KEYWORDS_ATOM = 'false null true'; +var RESERVED_WORDS = '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 this throws transient volatile' + + " " + KEYWORDS_ATOM + " " + KEYWORDS; +var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case'; + +KEYWORDS = makePredicate(KEYWORDS); +RESERVED_WORDS = makePredicate(RESERVED_WORDS); +KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION); +KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM); + +var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^")); + +var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i; +var RE_OCT_NUMBER = /^0[0-7]+$/; +var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i; + +var OPERATORS = makePredicate([ + "in", + "instanceof", + "typeof", + "new", + "void", + "delete", + "++", + "--", + "+", + "-", + "!", + "~", + "&", + "|", + "^", + "*", + "/", + "%", + ">>", + "<<", + ">>>", + "<", + ">", + "<=", + ">=", + "==", + "===", + "!=", + "!==", + "?", + "=", + "+=", + "-=", + "/=", + "*=", + "%=", + ">>=", + "<<=", + ">>>=", + "|=", + "^=", + "&=", + "&&", + "||" +]); + +var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000")); + +var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:")); + +var PUNC_CHARS = makePredicate(characters("[]{}(),;:")); + +var REGEXP_MODIFIERS = makePredicate(characters("gmsiy")); + +/* -----[ Tokenizer ]----- */ + +// regexps adapted from http://xregexp.com/plugins/#unicode +var UNICODE = { + letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0523\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0621-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971\\u0972\\u097B-\\u097F\\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-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D28\\u0D2A-\\u0D39\\u0D3D\\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\\u0EDD\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8B\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10D0-\\u10FA\\u10FC\\u1100-\\u1159\\u115F-\\u11A2\\u11A8-\\u11F9\\u1200-\\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-\\u1676\\u1681-\\u169A\\u16A0-\\u16EA\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19A9\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\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-\\u2094\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2C6F\\u2C71-\\u2C7D\\u2C80-\\u2CE4\\u2D00-\\u2D25\\u2D30-\\u2D65\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31B7\\u31F0-\\u31FF\\u3400\\u4DB5\\u4E00\\u9FC3\\uA000-\\uA48C\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA65F\\uA662-\\uA66E\\uA67F-\\uA697\\uA717-\\uA71F\\uA722-\\uA788\\uA78B\\uA78C\\uA7FB-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA90A-\\uA925\\uA930-\\uA946\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAC00\\uD7A3\\uF900-\\uFA2D\\uFA30-\\uFA6A\\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]"), + non_spacing_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065E\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0900-\\u0902\\u093C\\u0941-\\u0948\\u094D\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09BC\\u09C1-\\u09C4\\u09CD\\u09E2\\u09E3\\u0A01\\u0A02\\u0A3C\\u0A41\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81\\u0A82\\u0ABC\\u0AC1-\\u0AC5\\u0AC7\\u0AC8\\u0ACD\\u0AE2\\u0AE3\\u0B01\\u0B3C\\u0B3F\\u0B41-\\u0B44\\u0B4D\\u0B56\\u0B62\\u0B63\\u0B82\\u0BC0\\u0BCD\\u0C3E-\\u0C40\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0CBC\\u0CBF\\u0CC6\\u0CCC\\u0CCD\\u0CE2\\u0CE3\\u0D41-\\u0D44\\u0D4D\\u0D62\\u0D63\\u0DCA\\u0DD2-\\u0DD4\\u0DD6\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F71-\\u0F7E\\u0F80-\\u0F84\\u0F86\\u0F87\\u0F90-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102D-\\u1030\\u1032-\\u1037\\u1039\\u103A\\u103D\\u103E\\u1058\\u1059\\u105E-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108D\\u109D\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B7-\\u17BD\\u17C6\\u17C9-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193B\\u1A17\\u1A18\\u1A56\\u1A58-\\u1A5E\\u1A60\\u1A62\\u1A65-\\u1A6C\\u1A73-\\u1A7C\\u1A7F\\u1B00-\\u1B03\\u1B34\\u1B36-\\u1B3A\\u1B3C\\u1B42\\u1B6B-\\u1B73\\u1B80\\u1B81\\u1BA2-\\u1BA5\\u1BA8\\u1BA9\\u1C2C-\\u1C33\\u1C36\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE0\\u1CE2-\\u1CE8\\u1CED\\u1DC0-\\u1DE6\\u1DFD-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA67C\\uA67D\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA825\\uA826\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA951\\uA980-\\uA982\\uA9B3\\uA9B6-\\uA9B9\\uA9BC\\uAA29-\\uAA2E\\uAA31\\uAA32\\uAA35\\uAA36\\uAA43\\uAA4C\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uABE5\\uABE8\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"), + space_combining_mark: new RegExp("[\\u0903\\u093E-\\u0940\\u0949-\\u094C\\u094E\\u0982\\u0983\\u09BE-\\u09C0\\u09C7\\u09C8\\u09CB\\u09CC\\u09D7\\u0A03\\u0A3E-\\u0A40\\u0A83\\u0ABE-\\u0AC0\\u0AC9\\u0ACB\\u0ACC\\u0B02\\u0B03\\u0B3E\\u0B40\\u0B47\\u0B48\\u0B4B\\u0B4C\\u0B57\\u0BBE\\u0BBF\\u0BC1\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCC\\u0BD7\\u0C01-\\u0C03\\u0C41-\\u0C44\\u0C82\\u0C83\\u0CBE\\u0CC0-\\u0CC4\\u0CC7\\u0CC8\\u0CCA\\u0CCB\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D40\\u0D46-\\u0D48\\u0D4A-\\u0D4C\\u0D57\\u0D82\\u0D83\\u0DCF-\\u0DD1\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0F3E\\u0F3F\\u0F7F\\u102B\\u102C\\u1031\\u1038\\u103B\\u103C\\u1056\\u1057\\u1062-\\u1064\\u1067-\\u106D\\u1083\\u1084\\u1087-\\u108C\\u108F\\u109A-\\u109C\\u17B6\\u17BE-\\u17C5\\u17C7\\u17C8\\u1923-\\u1926\\u1929-\\u192B\\u1930\\u1931\\u1933-\\u1938\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A19-\\u1A1B\\u1A55\\u1A57\\u1A61\\u1A63\\u1A64\\u1A6D-\\u1A72\\u1B04\\u1B35\\u1B3B\\u1B3D-\\u1B41\\u1B43\\u1B44\\u1B82\\u1BA1\\u1BA6\\u1BA7\\u1BAA\\u1C24-\\u1C2B\\u1C34\\u1C35\\u1CE1\\u1CF2\\uA823\\uA824\\uA827\\uA880\\uA881\\uA8B4-\\uA8C3\\uA952\\uA953\\uA983\\uA9B4\\uA9B5\\uA9BA\\uA9BB\\uA9BD-\\uA9C0\\uAA2F\\uAA30\\uAA33\\uAA34\\uAA4D\\uAA7B\\uABE3\\uABE4\\uABE6\\uABE7\\uABE9\\uABEA\\uABEC]"), + connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]") +}; + +function is_letter(code) { + return (code >= 97 && code <= 122) + || (code >= 65 && code <= 90) + || (code >= 0xaa && UNICODE.letter.test(String.fromCharCode(code))); +}; + +function is_digit(code) { + return code >= 48 && code <= 57; //XXX: find out if "UnicodeDigit" means something else than 0..9 +}; + +function is_alphanumeric_char(code) { + return is_digit(code) || is_letter(code); +}; + +function is_unicode_combining_mark(ch) { + return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch); +}; + +function is_unicode_connector_punctuation(ch) { + return UNICODE.connector_punctuation.test(ch); +}; + +function is_identifier(name) { + return !RESERVED_WORDS(name) && /^[a-z_$][a-z0-9_$]*$/i.test(name); +}; + +function is_identifier_start(code) { + return code == 36 || code == 95 || is_letter(code); +}; + +function is_identifier_char(ch) { + var code = ch.charCodeAt(0); + return is_identifier_start(code) + || is_digit(code) + || code == 8204 // \u200c: zero-width non-joiner + || code == 8205 // \u200d: zero-width joiner (in my ECMA-262 PDF, this is also 200c) + || is_unicode_combining_mark(ch) + || is_unicode_connector_punctuation(ch) + ; +}; + +function parse_js_number(num) { + if (RE_HEX_NUMBER.test(num)) { + return parseInt(num.substr(2), 16); + } else if (RE_OCT_NUMBER.test(num)) { + return parseInt(num.substr(1), 8); + } else if (RE_DEC_NUMBER.test(num)) { + return parseFloat(num); + } +}; + +function JS_Parse_Error(message, line, col, pos) { + this.message = message; + this.line = line; + this.col = col; + this.pos = pos; + this.stack = new Error().stack; +}; + +JS_Parse_Error.prototype.toString = function() { + return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack; +}; + +function js_error(message, filename, line, col, pos) { + throw new JS_Parse_Error(message, line, col, pos); +}; + +function is_token(token, type, val) { + return token.type == type && (val == null || token.value == val); +}; + +var EX_EOF = {}; + +function tokenizer($TEXT, filename) { + + var S = { + text : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/\uFEFF/g, ''), + filename : filename, + pos : 0, + tokpos : 0, + line : 1, + tokline : 0, + col : 0, + tokcol : 0, + newline_before : false, + regex_allowed : false, + comments_before : [] + }; + + function peek() { return S.text.charAt(S.pos); }; + + function next(signal_eof, in_string) { + var ch = S.text.charAt(S.pos++); + if (signal_eof && !ch) + throw EX_EOF; + if (ch == "\n") { + S.newline_before = S.newline_before || !in_string; + ++S.line; + S.col = 0; + } else { + ++S.col; + } + return ch; + }; + + function find(what, signal_eof) { + var pos = S.text.indexOf(what, S.pos); + if (signal_eof && pos == -1) throw EX_EOF; + return pos; + }; + + function start_token() { + S.tokline = S.line; + S.tokcol = S.col; + S.tokpos = S.pos; + }; + + function token(type, value, is_comment) { + S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX[value]) || + (type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value)) || + (type == "punc" && PUNC_BEFORE_EXPRESSION(value))); + var ret = { + type : type, + value : value, + line : S.tokline, + col : S.tokcol, + pos : S.tokpos, + endpos : S.pos, + nlb : S.newline_before, + file : filename + }; + if (!is_comment) { + ret.comments_before = S.comments_before; + S.comments_before = []; + // make note of any newlines in the comments that came before + for (var i = 0, len = ret.comments_before.length; i < len; i++) { + ret.nlb = ret.nlb || ret.comments_before[i].nlb; + } + } + S.newline_before = false; + return new AST_Token(ret); + }; + + function skip_whitespace() { + while (WHITESPACE_CHARS(peek())) + next(); + }; + + function read_while(pred) { + var ret = "", ch, i = 0; + while ((ch = peek()) && pred(ch, i++)) + ret += next(); + return ret; + }; + + function parse_error(err) { + js_error(err, filename, S.tokline, S.tokcol, S.tokpos); + }; + + function read_num(prefix) { + var has_e = false, after_e = false, has_x = false, has_dot = prefix == "."; + var num = read_while(function(ch, i){ + var code = ch.charCodeAt(0); + switch (code) { + case 120: case 88: // xX + return has_x ? false : (has_x = true); + case 101: case 69: // eE + return has_x ? true : has_e ? false : (has_e = after_e = true); + case 45: // - + return after_e || (i == 0 && !prefix); + case 43: // + + return after_e; + case (after_e = false, 46): // . + return (!has_dot && !has_x && !has_e) ? (has_dot = true) : false; + } + return is_alphanumeric_char(code); + }); + if (prefix) num = prefix + num; + var valid = parse_js_number(num); + if (!isNaN(valid)) { + return token("num", valid); + } else { + parse_error("Invalid syntax: " + num); + } + }; + + function read_escaped_char(in_string) { + var ch = next(true, in_string); + switch (ch.charCodeAt(0)) { + case 110 : return "\n"; + case 114 : return "\r"; + case 116 : return "\t"; + case 98 : return "\b"; + case 118 : return "\u000b"; // \v + case 102 : return "\f"; + case 48 : return "\0"; + case 120 : return String.fromCharCode(hex_bytes(2)); // \x + case 117 : return String.fromCharCode(hex_bytes(4)); // \u + case 10 : return ""; // newline + default : return ch; + } + }; + + function hex_bytes(n) { + var num = 0; + for (; n > 0; --n) { + var digit = parseInt(next(true), 16); + if (isNaN(digit)) + parse_error("Invalid hex-character pattern in string"); + num = (num << 4) | digit; + } + return num; + }; + + var read_string = with_eof_error("Unterminated string constant", function(){ + var quote = next(), ret = ""; + for (;;) { + var ch = next(true); + if (ch == "\\") { + // read OctalEscapeSequence (XXX: deprecated if "strict mode") + // https://github.com/mishoo/UglifyJS/issues/178 + var octal_len = 0, first = null; + ch = read_while(function(ch){ + if (ch >= "0" && ch <= "7") { + if (!first) { + first = ch; + return ++octal_len; + } + else if (first <= "3" && octal_len <= 2) return ++octal_len; + else if (first >= "4" && octal_len <= 1) return ++octal_len; + } + return false; + }); + if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8)); + else ch = read_escaped_char(true); + } + else if (ch == quote) break; + ret += ch; + } + return token("string", ret); + }); + + function read_line_comment() { + next(); + var i = find("\n"), ret; + if (i == -1) { + ret = S.text.substr(S.pos); + S.pos = S.text.length; + } else { + ret = S.text.substring(S.pos, i); + S.pos = i; + } + return token("comment1", ret, true); + }; + + var read_multiline_comment = with_eof_error("Unterminated multiline comment", function(){ + next(); + var i = find("*/", true); + var text = S.text.substring(S.pos, i); + var a = text.split("\n"), n = a.length; + // update stream position + S.pos = i + 2; + S.line += n - 1; + if (n > 1) S.col = a[n - 1].length; + else S.col += a[n - 1].length; + S.col += 2; + S.newline_before = S.newline_before || text.indexOf("\n") >= 0; + return token("comment2", text, true); + }); + + function read_name() { + var backslash = false, name = "", ch, escaped = false, hex; + while ((ch = peek()) != null) { + if (!backslash) { + if (ch == "\\") escaped = backslash = true, next(); + else if (is_identifier_char(ch)) name += next(); + else break; + } + else { + if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX"); + ch = read_escaped_char(); + if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier"); + name += ch; + backslash = false; + } + } + if (KEYWORDS(name) && escaped) { + hex = name.charCodeAt(0).toString(16).toUpperCase(); + name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1); + } + return name; + }; + + var read_regexp = with_eof_error("Unterminated regular expression", function(regexp){ + var prev_backslash = false, ch, in_class = false; + while ((ch = next(true))) if (prev_backslash) { + regexp += "\\" + ch; + prev_backslash = false; + } else if (ch == "[") { + in_class = true; + regexp += ch; + } else if (ch == "]" && in_class) { + in_class = false; + regexp += ch; + } else if (ch == "/" && !in_class) { + break; + } else if (ch == "\\") { + prev_backslash = true; + } else { + regexp += ch; + } + var mods = read_name(); + return token("regexp", new RegExp(regexp, mods)); + }); + + function read_operator(prefix) { + function grow(op) { + if (!peek()) return op; + var bigger = op + peek(); + if (OPERATORS(bigger)) { + next(); + return grow(bigger); + } else { + return op; + } + }; + return token("operator", grow(prefix || next())); + }; + + function handle_slash() { + next(); + var regex_allowed = S.regex_allowed; + switch (peek()) { + case "/": + S.comments_before.push(read_line_comment()); + S.regex_allowed = regex_allowed; + return next_token(); + case "*": + S.comments_before.push(read_multiline_comment()); + S.regex_allowed = regex_allowed; + return next_token(); + } + return S.regex_allowed ? read_regexp("") : read_operator("/"); + }; + + function handle_dot() { + next(); + return is_digit(peek().charCodeAt(0)) + ? read_num(".") + : token("punc", "."); + }; + + function read_word() { + var word = read_name(); + return KEYWORDS_ATOM(word) ? token("atom", word) + : !KEYWORDS(word) ? token("name", word) + : OPERATORS(word) ? token("operator", word) + : token("keyword", word); + }; + + function with_eof_error(eof_error, cont) { + return function(x) { + try { + return cont(x); + } catch(ex) { + if (ex === EX_EOF) parse_error(eof_error); + else throw ex; + } + }; + }; + + function next_token(force_regexp) { + if (force_regexp != null) + return read_regexp(force_regexp); + skip_whitespace(); + start_token(); + var ch = peek(); + if (!ch) return token("eof"); + var code = ch.charCodeAt(0); + switch (code) { + case 34: case 39: return read_string(); + case 46: return handle_dot(); + case 47: return handle_slash(); + } + if (is_digit(code)) return read_num(); + if (PUNC_CHARS(ch)) return token("punc", next()); + if (OPERATOR_CHARS(ch)) return read_operator(); + if (code == 92 || is_identifier_start(code)) return read_word(); + parse_error("Unexpected character '" + ch + "'"); + }; + + next_token.context = function(nc) { + if (nc) S = nc; + return S; + }; + + return next_token; + +}; + +/* -----[ Parser (constants) ]----- */ + +var UNARY_PREFIX = makePredicate([ + "typeof", + "void", + "delete", + "--", + "++", + "!", + "~", + "-", + "+" +]); + +var UNARY_POSTFIX = makePredicate([ "--", "++" ]); + +var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]); + +var PRECEDENCE = (function(a, ret){ + for (var i = 0, n = 1; i < a.length; ++i, ++n) { + var b = a[i]; + for (var j = 0; j < b.length; ++j) { + ret[b[j]] = n; + } + } + return ret; +})( + [ + ["||"], + ["&&"], + ["|"], + ["^"], + ["&"], + ["==", "===", "!=", "!=="], + ["<", ">", "<=", ">=", "in", "instanceof"], + [">>", "<<", ">>>"], + ["+", "-"], + ["*", "/", "%"] + ], + {} +); + +var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]); + +var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]); + +/* -----[ Parser ]----- */ + +function parse($TEXT, options) { + + options = defaults(options, { + strict : false, + filename : null, + toplevel : null + }); + + var S = { + input : typeof $TEXT == "string" ? tokenizer($TEXT, options.filename) : $TEXT, + token : null, + prev : null, + peeked : null, + in_function : 0, + in_directives : true, + in_loop : 0, + labels : [] + }; + + S.token = next(); + + function is(type, value) { + return is_token(S.token, type, value); + }; + + function peek() { return S.peeked || (S.peeked = S.input()); }; + + function next() { + S.prev = S.token; + if (S.peeked) { + S.token = S.peeked; + S.peeked = null; + } else { + S.token = S.input(); + } + S.in_directives = S.in_directives && ( + S.token.type == "string" || is("punc", ";") + ); + return S.token; + }; + + function prev() { + return S.prev; + }; + + function croak(msg, line, col, pos) { + var ctx = S.input.context(); + js_error(msg, + ctx.filename, + line != null ? line : ctx.tokline, + col != null ? col : ctx.tokcol, + pos != null ? pos : ctx.tokpos); + }; + + function token_error(token, msg) { + croak(msg, token.line, token.col); + }; + + function unexpected(token) { + if (token == null) + token = S.token; + token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")"); + }; + + function expect_token(type, val) { + if (is(type, val)) { + return next(); + } + token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»"); + }; + + function expect(punc) { return expect_token("punc", punc); }; + + function can_insert_semicolon() { + return !options.strict && ( + S.token.nlb || is("eof") || is("punc", "}") + ); + }; + + function semicolon() { + if (is("punc", ";")) next(); + else if (!can_insert_semicolon()) unexpected(); + }; + + function parenthesised() { + expect("("); + var exp = expression(true); + expect(")"); + return exp; + }; + + function embed_tokens(parser) { + return function() { + var start = S.token; + var expr = parser(); + var end = prev(); + expr.start = start; + expr.end = end; + return expr; + }; + }; + + var statement = embed_tokens(function() { + var tmp; + if (is("operator", "/") || is("operator", "/=")) { + S.peeked = null; + S.token = S.input(S.token.value.substr(1)); // force regexp + } + switch (S.token.type) { + case "string": + var dir = S.in_directives, stat = simple_statement(); + // XXXv2: decide how to fix directives + if (dir && stat.body instanceof AST_String && !is("punc", ",")) + return new AST_Directive({ value: stat.body.value }); + return stat; + case "num": + case "regexp": + case "operator": + case "atom": + return simple_statement(); + + case "name": + return is_token(peek(), "punc", ":") + ? labeled_statement() + : simple_statement(); + + case "punc": + switch (S.token.value) { + case "{": + return new AST_BlockStatement({ + start : S.token, + body : block_(), + end : prev() + }); + case "[": + case "(": + return simple_statement(); + case ";": + next(); + return new AST_EmptyStatement(); + default: + unexpected(); + } + + case "keyword": + switch (tmp = S.token.value, next(), tmp) { + case "break": + return break_cont(AST_Break); + + case "continue": + return break_cont(AST_Continue); + + case "debugger": + semicolon(); + return new AST_Debugger(); + + case "do": + return new AST_Do({ + body : in_loop(statement), + condition : (expect_token("keyword", "while"), tmp = parenthesised(), semicolon(), tmp) + }); + + case "while": + return new AST_While({ + condition : parenthesised(), + body : in_loop(statement) + }); + + case "for": + return for_(); + + case "function": + return function_(true); + + case "if": + return if_(); + + case "return": + if (S.in_function == 0) + croak("'return' outside of function"); + return new AST_Return({ + value: ( is("punc", ";") + ? (next(), null) + : can_insert_semicolon() + ? null + : (tmp = expression(true), semicolon(), tmp) ) + }); + + case "switch": + return new AST_Switch({ + expression : parenthesised(), + body : in_loop(switch_body_) + }); + + case "throw": + if (S.token.nlb) + croak("Illegal newline after 'throw'"); + return new AST_Throw({ + value: (tmp = expression(true), semicolon(), tmp) + }); + + case "try": + return try_(); + + case "var": + return tmp = var_(), semicolon(), tmp; + + case "const": + return tmp = const_(), semicolon(), tmp; + + case "with": + return new AST_With({ + expression : parenthesised(), + body : statement() + }); + + default: + unexpected(); + } + } + }); + + function labeled_statement() { + var label = as_symbol(AST_Label); + if (find_if(function(l){ return l.name == label.name }, S.labels)) { + // ECMA-262, 12.12: An ECMAScript program is considered + // syntactically incorrect if it contains a + // LabelledStatement that is enclosed by a + // LabelledStatement with the same Identifier as label. + croak("Label " + label.name + " defined twice"); + } + expect(":"); + S.labels.push(label); + var stat = statement(); + S.labels.pop(); + return new AST_LabeledStatement({ body: stat, label: label }); + }; + + function simple_statement(tmp) { + return new AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) }); + }; + + function break_cont(type) { + var label = null; + if (!can_insert_semicolon()) { + label = as_symbol(AST_LabelRef, true); + } + if (label != null) { + if (!find_if(function(l){ return l.name == label.name }, S.labels)) + croak("Undefined label " + label.name); + } + else if (S.in_loop == 0) + croak(type.TYPE + " not inside a loop or switch"); + semicolon(); + return new type({ label: label }); + }; + + function for_() { + expect("("); + var init = null; + if (!is("punc", ";")) { + init = is("keyword", "var") + ? (next(), var_(true)) + : expression(true, true); + if (is("operator", "in")) { + if (init instanceof AST_Var && init.definitions.length > 1) + croak("Only one variable declaration allowed in for..in loop"); + next(); + return for_in(init); + } + } + return regular_for(init); + }; + + function regular_for(init) { + expect(";"); + var test = is("punc", ";") ? null : expression(true); + expect(";"); + var step = is("punc", ")") ? null : expression(true); + expect(")"); + return new AST_For({ + init : init, + condition : test, + step : step, + body : in_loop(statement) + }); + }; + + function for_in(init) { + var lhs = init instanceof AST_Var ? init.definitions[0].name : null; + var obj = expression(true); + expect(")"); + return new AST_ForIn({ + init : init, + name : lhs, + object : obj, + body : in_loop(statement) + }); + }; + + var function_ = function(in_statement, ctor) { + var is_accessor = ctor === AST_Accessor; + var name = (is("name") ? as_symbol(in_statement + ? AST_SymbolDefun + : is_accessor + ? AST_SymbolAccessor + : AST_SymbolLambda) + : is_accessor && (is("string") || is("num")) ? as_atom_node() + : null); + if (in_statement && !name) + unexpected(); + expect("("); + if (!ctor) ctor = in_statement ? AST_Defun : AST_Function; + return new ctor({ + name: name, + argnames: (function(first, a){ + while (!is("punc", ")")) { + if (first) first = false; else expect(","); + a.push(as_symbol(AST_SymbolFunarg)); + } + next(); + return a; + })(true, []), + body: (function(loop, labels){ + ++S.in_function; + S.in_directives = true; + S.in_loop = 0; + S.labels = []; + var a = block_(); + --S.in_function; + S.in_loop = loop; + S.labels = labels; + return a; + })(S.in_loop, S.labels) + }); + }; + + function if_() { + var cond = parenthesised(), body = statement(), belse = null; + if (is("keyword", "else")) { + next(); + belse = statement(); + } + return new AST_If({ + condition : cond, + body : body, + alternative : belse + }); + }; + + function block_() { + expect("{"); + var a = []; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + a.push(statement()); + } + next(); + return a; + }; + + function switch_body_() { + expect("{"); + var a = [], cur = null, branch = null, tmp; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + if (is("keyword", "case")) { + if (branch) branch.end = prev(); + cur = []; + branch = new AST_Case({ + start : (tmp = S.token, next(), tmp), + expression : expression(true), + body : cur + }); + a.push(branch); + expect(":"); + } + else if (is("keyword", "default")) { + if (branch) branch.end = prev(); + cur = []; + branch = new AST_Default({ + start : (tmp = S.token, next(), expect(":"), tmp), + body : cur + }); + a.push(branch); + } + else { + if (!cur) unexpected(); + cur.push(statement()); + } + } + if (branch) branch.end = prev(); + next(); + return a; + }; + + function try_() { + var body = block_(), bcatch = null, bfinally = null; + if (is("keyword", "catch")) { + var start = S.token; + next(); + expect("("); + var name = as_symbol(AST_SymbolCatch); + expect(")"); + bcatch = new AST_Catch({ + start : start, + argname : name, + body : block_(), + end : prev() + }); + } + if (is("keyword", "finally")) { + var start = S.token; + next(); + bfinally = new AST_Finally({ + start : start, + body : block_(), + end : prev() + }); + } + if (!bcatch && !bfinally) + croak("Missing catch/finally blocks"); + return new AST_Try({ + body : body, + bcatch : bcatch, + bfinally : bfinally + }); + }; + + function vardefs(no_in, in_const) { + var a = []; + for (;;) { + a.push(new AST_VarDef({ + start : S.token, + name : as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar), + value : is("operator", "=") ? (next(), expression(false, no_in)) : null, + end : prev() + })); + if (!is("punc", ",")) + break; + next(); + } + return a; + }; + + var var_ = function(no_in) { + return new AST_Var({ + start : prev(), + definitions : vardefs(no_in, false), + end : prev() + }); + }; + + var const_ = function() { + return new AST_Const({ + start : prev(), + definitions : vardefs(false, true), + end : prev() + }); + }; + + var new_ = function() { + var start = S.token; + expect_token("operator", "new"); + var newexp = expr_atom(false), args; + if (is("punc", "(")) { + next(); + args = expr_list(")"); + } else { + args = []; + } + return subscripts(new AST_New({ + start : start, + expression : newexp, + args : args, + end : prev() + }), true); + }; + + function as_atom_node() { + var tok = S.token, ret; + switch (tok.type) { + case "name": + return as_symbol(AST_SymbolRef); + case "num": + ret = new AST_Number({ start: tok, end: tok, value: tok.value }); + break; + case "string": + ret = new AST_String({ start: tok, end: tok, value: tok.value }); + break; + case "regexp": + ret = new AST_RegExp({ start: tok, end: tok, value: tok.value }); + break; + case "atom": + switch (tok.value) { + case "false": + ret = new AST_False({ start: tok, end: tok }); + break; + case "true": + ret = new AST_True({ start: tok, end: tok }); + break; + case "null": + ret = new AST_Null({ start: tok, end: tok }); + break; + } + break; + } + next(); + return ret; + }; + + var expr_atom = function(allow_calls) { + if (is("operator", "new")) { + return new_(); + } + var start = S.token; + if (is("punc")) { + switch (start.value) { + case "(": + next(); + var ex = expression(true); + ex.start = start; + ex.end = S.token; + expect(")"); + return subscripts(ex, allow_calls); + case "[": + return subscripts(array_(), allow_calls); + case "{": + return subscripts(object_(), allow_calls); + } + unexpected(); + } + if (is("keyword", "function")) { + next(); + var func = function_(false); + func.start = start; + func.end = prev(); + return subscripts(func, allow_calls); + } + if (ATOMIC_START_TOKEN[S.token.type]) { + return subscripts(as_atom_node(), allow_calls); + } + unexpected(); + }; + + function expr_list(closing, allow_trailing_comma, allow_empty) { + var first = true, a = []; + while (!is("punc", closing)) { + if (first) first = false; else expect(","); + if (allow_trailing_comma && is("punc", closing)) break; + if (is("punc", ",") && allow_empty) { + a.push(new AST_Hole({ start: S.token, end: S.token })); + } else { + a.push(expression(false)); + } + } + next(); + return a; + }; + + var array_ = embed_tokens(function() { + expect("["); + return new AST_Array({ + elements: expr_list("]", !options.strict, true) + }); + }); + + var object_ = embed_tokens(function() { + expect("{"); + var first = true, a = []; + while (!is("punc", "}")) { + if (first) first = false; else expect(","); + if (!options.strict && is("punc", "}")) + // allow trailing comma + break; + var start = S.token; + var type = start.type; + var name = as_property_name(); + if (type == "name" && !is("punc", ":")) { + if (name == "get") { + a.push(new AST_ObjectGetter({ + start : start, + key : name, + value : function_(false, AST_Accessor), + end : prev() + })); + continue; + } + if (name == "set") { + a.push(new AST_ObjectSetter({ + start : start, + key : name, + value : function_(false, AST_Accessor), + end : prev() + })); + continue; + } + } + expect(":"); + a.push(new AST_ObjectKeyVal({ + start : start, + key : name, + value : expression(false), + end : prev() + })); + } + next(); + return new AST_Object({ properties: a }); + }); + + function as_property_name() { + var tmp = S.token; + next(); + switch (tmp.type) { + case "num": + case "string": + case "name": + case "operator": + case "keyword": + case "atom": + return tmp.value; + default: + unexpected(); + } + }; + + function as_name() { + var tmp = S.token; + next(); + switch (tmp.type) { + case "name": + case "operator": + case "keyword": + case "atom": + return tmp.value; + default: + unexpected(); + } + }; + + function as_symbol(type, noerror) { + if (!is("name")) { + if (!noerror) croak("Name expected"); + return null; + } + var name = S.token.value; + var sym = new (name == "this" ? AST_This : type)({ + name : String(S.token.value), + start : S.token, + end : S.token + }); + next(); + return sym; + }; + + var subscripts = function(expr, allow_calls) { + var start = expr.start; + if (is("punc", ".")) { + next(); + return subscripts(new AST_Dot({ + start : start, + expression : expr, + property : as_name(), + end : prev() + }), allow_calls); + } + if (is("punc", "[")) { + next(); + var prop = expression(true); + expect("]"); + return subscripts(new AST_Sub({ + start : start, + expression : expr, + property : prop, + end : prev() + }), allow_calls); + } + if (allow_calls && is("punc", "(")) { + next(); + return subscripts(new AST_Call({ + start : start, + expression : expr, + args : expr_list(")"), + end : prev() + }), true); + } + return expr; + }; + + var maybe_unary = function(allow_calls) { + var start = S.token; + if (is("operator") && UNARY_PREFIX(start.value)) { + next(); + var ex = make_unary(AST_UnaryPrefix, start.value, maybe_unary(allow_calls)); + ex.start = start; + ex.end = prev(); + return ex; + } + var val = expr_atom(allow_calls); + while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) { + val = make_unary(AST_UnaryPostfix, S.token.value, val); + val.start = start; + val.end = S.token; + next(); + } + return val; + }; + + function make_unary(ctor, op, expr) { + if ((op == "++" || op == "--") && !is_assignable(expr)) + croak("Invalid use of " + op + " operator"); + return new ctor({ operator: op, expression: expr }); + }; + + var expr_op = function(left, min_prec, no_in) { + var op = is("operator") ? S.token.value : null; + if (op == "in" && no_in) op = null; + var prec = op != null ? PRECEDENCE[op] : null; + if (prec != null && prec > min_prec) { + next(); + var right = expr_op(maybe_unary(true), prec, no_in); + return expr_op(new AST_Binary({ + start : left.start, + left : left, + operator : op, + right : right, + end : right.end + }), min_prec, no_in); + } + return left; + }; + + function expr_ops(no_in) { + return expr_op(maybe_unary(true), 0, no_in); + }; + + var maybe_conditional = function(no_in) { + var start = S.token; + var expr = expr_ops(no_in); + if (is("operator", "?")) { + next(); + var yes = expression(false); + expect(":"); + return new AST_Conditional({ + start : start, + condition : expr, + consequent : yes, + alternative : expression(false, no_in), + end : peek() + }); + } + return expr; + }; + + function is_assignable(expr) { + if (!options.strict) return true; + switch (expr[0]+"") { + case "dot": + case "sub": + case "new": + case "call": + return true; + case "name": + return expr[1] != "this"; + } + }; + + var maybe_assign = function(no_in) { + var start = S.token; + var left = maybe_conditional(no_in), val = S.token.value; + if (is("operator") && ASSIGNMENT(val)) { + if (is_assignable(left)) { + next(); + return new AST_Assign({ + start : start, + left : left, + operator : val, + right : maybe_assign(no_in), + end : prev() + }); + } + croak("Invalid assignment"); + } + return left; + }; + + var expression = function(commas, no_in) { + var start = S.token; + var expr = maybe_assign(no_in); + if (commas && is("punc", ",")) { + next(); + return new AST_Seq({ + start : start, + car : expr, + cdr : expression(true, no_in), + end : peek() + }); + } + return expr; + }; + + function in_loop(cont) { + ++S.in_loop; + var ret = cont(); + --S.in_loop; + return ret; + }; + + return (function(){ + var start = S.token; + var body = []; + while (!is("eof")) + body.push(statement()); + var end = prev(); + var toplevel = options.toplevel; + if (toplevel) { + toplevel.body = toplevel.body.concat(body); + toplevel.end = end; + } else { + toplevel = new AST_Toplevel({ start: start, body: body, end: end }); + } + return toplevel; + })(); + +}; diff --git a/homework7/project_express/node_modules/uglify-js/lib/scope.js b/homework7/project_express/node_modules/uglify-js/lib/scope.js new file mode 100644 index 0000000..ea27163 --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/lib/scope.js @@ -0,0 +1,580 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function SymbolDef(scope, index, orig) { + this.name = orig.name; + this.orig = [ orig ]; + this.scope = scope; + this.references = []; + this.global = false; + this.mangled_name = null; + this.undeclared = false; + this.constant = false; + this.index = index; +}; + +SymbolDef.prototype = { + unmangleable: function(options) { + return (this.global && !(options && options.toplevel)) + || this.undeclared + || (!(options && options.eval) && (this.scope.uses_eval || this.scope.uses_with)); + }, + mangle: function(options) { + if (!this.mangled_name && !this.unmangleable(options)) { + var s = this.scope; + if (this.orig[0] instanceof AST_SymbolLambda && !options.screw_ie8) + s = s.parent_scope; + this.mangled_name = s.next_mangled(options); + } + } +}; + +AST_Toplevel.DEFMETHOD("figure_out_scope", function(){ + // This does what ast_add_scope did in UglifyJS v1. + // + // Part of it could be done at parse time, but it would complicate + // the parser (and it's already kinda complex). It's also worth + // having it separated because we might need to call it multiple + // times on the same tree. + + // pass 1: setup scope chaining and handle definitions + var self = this; + var scope = self.parent_scope = null; + var labels = new Dictionary(); + var nesting = 0; + var tw = new TreeWalker(function(node, descend){ + if (node instanceof AST_Scope) { + node.init_scope_vars(nesting); + var save_scope = node.parent_scope = scope; + var save_labels = labels; + ++nesting; + scope = node; + labels = new Dictionary(); + descend(); + labels = save_labels; + scope = save_scope; + --nesting; + return true; // don't descend again in TreeWalker + } + if (node instanceof AST_Directive) { + node.scope = scope; + push_uniq(scope.directives, node.value); + return true; + } + if (node instanceof AST_With) { + for (var s = scope; s; s = s.parent_scope) + s.uses_with = true; + return; + } + if (node instanceof AST_LabeledStatement) { + var l = node.label; + if (labels.has(l.name)) + throw new Error(string_template("Label {name} defined twice", l)); + labels.set(l.name, l); + descend(); + labels.del(l.name); + return true; // no descend again + } + if (node instanceof AST_Symbol) { + node.scope = scope; + } + if (node instanceof AST_Label) { + node.thedef = node; + node.init_scope_vars(); + } + if (node instanceof AST_SymbolLambda) { + scope.def_function(node); + } + else if (node instanceof AST_SymbolDefun) { + // Careful here, the scope where this should be defined is + // the parent scope. The reason is that we enter a new + // scope when we encounter the AST_Defun node (which is + // instanceof AST_Scope) but we get to the symbol a bit + // later. + (node.scope = scope.parent_scope).def_function(node); + } + else if (node instanceof AST_SymbolVar + || node instanceof AST_SymbolConst) { + var def = scope.def_variable(node); + def.constant = node instanceof AST_SymbolConst; + def.init = tw.parent().value; + } + else if (node instanceof AST_SymbolCatch) { + // XXX: this is wrong according to ECMA-262 (12.4). the + // `catch` argument name should be visible only inside the + // catch block. For a quick fix AST_Catch should inherit + // from AST_Scope. Keeping it this way because of IE, + // which doesn't obey the standard. (it introduces the + // identifier in the enclosing scope) + scope.def_variable(node); + } + if (node instanceof AST_LabelRef) { + var sym = labels.get(node.name); + if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", { + name: node.name, + line: node.start.line, + col: node.start.col + })); + node.thedef = sym; + } + }); + self.walk(tw); + + // pass 2: find back references and eval + var func = null; + var globals = self.globals = new Dictionary(); + var tw = new TreeWalker(function(node, descend){ + if (node instanceof AST_Lambda) { + var prev_func = func; + func = node; + descend(); + func = prev_func; + return true; + } + if (node instanceof AST_LabelRef) { + node.reference(); + return true; + } + if (node instanceof AST_SymbolRef) { + var name = node.name; + var sym = node.scope.find_variable(name); + if (!sym) { + var g; + if (globals.has(name)) { + g = globals.get(name); + } else { + g = new SymbolDef(self, globals.size(), node); + g.undeclared = true; + globals.set(name, g); + } + node.thedef = g; + if (name == "eval" && tw.parent() instanceof AST_Call) { + for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) + s.uses_eval = true; + } + if (name == "arguments") { + func.uses_arguments = true; + } + } else { + node.thedef = sym; + } + node.reference(); + return true; + } + }); + self.walk(tw); +}); + +AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){ + this.directives = []; // contains the directives defined in this scope, i.e. "use strict" + this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions) + this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope) + this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement + this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval` + this.parent_scope = null; // the parent scope + this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes + this.cname = -1; // the current index for mangling functions/variables + this.nesting = nesting; // the nesting level of this scope (0 means toplevel) +}); + +AST_Scope.DEFMETHOD("strict", function(){ + return this.has_directive("use strict"); +}); + +AST_Lambda.DEFMETHOD("init_scope_vars", function(){ + AST_Scope.prototype.init_scope_vars.apply(this, arguments); + this.uses_arguments = false; +}); + +AST_SymbolRef.DEFMETHOD("reference", function() { + var def = this.definition(); + def.references.push(this); + var s = this.scope; + while (s) { + push_uniq(s.enclosed, def); + if (s === def.scope) break; + s = s.parent_scope; + } + this.frame = this.scope.nesting - def.scope.nesting; +}); + +AST_Label.DEFMETHOD("init_scope_vars", function(){ + this.references = []; +}); + +AST_LabelRef.DEFMETHOD("reference", function(){ + this.thedef.references.push(this); +}); + +AST_Scope.DEFMETHOD("find_variable", function(name){ + if (name instanceof AST_Symbol) name = name.name; + return this.variables.get(name) + || (this.parent_scope && this.parent_scope.find_variable(name)); +}); + +AST_Scope.DEFMETHOD("has_directive", function(value){ + return this.parent_scope && this.parent_scope.has_directive(value) + || (this.directives.indexOf(value) >= 0 ? this : null); +}); + +AST_Scope.DEFMETHOD("def_function", function(symbol){ + this.functions.set(symbol.name, this.def_variable(symbol)); +}); + +AST_Scope.DEFMETHOD("def_variable", function(symbol){ + var def; + if (!this.variables.has(symbol.name)) { + def = new SymbolDef(this, this.variables.size(), symbol); + this.variables.set(symbol.name, def); + def.global = !this.parent_scope; + } else { + def = this.variables.get(symbol.name); + def.orig.push(symbol); + } + return symbol.thedef = def; +}); + +AST_Scope.DEFMETHOD("next_mangled", function(options){ + var ext = this.enclosed; + out: while (true) { + var m = base54(++this.cname); + if (!is_identifier(m)) continue; // skip over "do" + // we must ensure that the mangled name does not shadow a name + // from some parent scope that is referenced in this or in + // inner scopes. + for (var i = ext.length; --i >= 0;) { + var sym = ext[i]; + var name = sym.mangled_name || (sym.unmangleable(options) && sym.name); + if (m == name) continue out; + } + return m; + } +}); + +AST_Scope.DEFMETHOD("references", function(sym){ + if (sym instanceof AST_Symbol) sym = sym.definition(); + return this.enclosed.indexOf(sym) < 0 ? null : sym; +}); + +AST_Symbol.DEFMETHOD("unmangleable", function(options){ + return this.definition().unmangleable(options); +}); + +// property accessors are not mangleable +AST_SymbolAccessor.DEFMETHOD("unmangleable", function(){ + return true; +}); + +// labels are always mangleable +AST_Label.DEFMETHOD("unmangleable", function(){ + return false; +}); + +AST_Symbol.DEFMETHOD("unreferenced", function(){ + return this.definition().references.length == 0 + && !(this.scope.uses_eval || this.scope.uses_with); +}); + +AST_Symbol.DEFMETHOD("undeclared", function(){ + return this.definition().undeclared; +}); + +AST_LabelRef.DEFMETHOD("undeclared", function(){ + return false; +}); + +AST_Label.DEFMETHOD("undeclared", function(){ + return false; +}); + +AST_Symbol.DEFMETHOD("definition", function(){ + return this.thedef; +}); + +AST_Symbol.DEFMETHOD("global", function(){ + return this.definition().global; +}); + +AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){ + return defaults(options, { + except : [], + eval : false, + sort : false, + toplevel : false, + screw_ie8 : false + }); +}); + +AST_Toplevel.DEFMETHOD("mangle_names", function(options){ + options = this._default_mangler_options(options); + // We only need to mangle declaration nodes. Special logic wired + // into the code generator will display the mangled name if it's + // present (and for AST_SymbolRef-s it'll use the mangled name of + // the AST_SymbolDeclaration that it points to). + var lname = -1; + var to_mangle = []; + var tw = new TreeWalker(function(node, descend){ + if (node instanceof AST_LabeledStatement) { + // lname is incremented when we get to the AST_Label + var save_nesting = lname; + descend(); + lname = save_nesting; + return true; // don't descend again in TreeWalker + } + if (node instanceof AST_Scope) { + var p = tw.parent(), a = []; + node.variables.each(function(symbol){ + if (options.except.indexOf(symbol.name) < 0) { + a.push(symbol); + } + }); + if (options.sort) a.sort(function(a, b){ + return b.references.length - a.references.length; + }); + to_mangle.push.apply(to_mangle, a); + return; + } + if (node instanceof AST_Label) { + var name; + do name = base54(++lname); while (!is_identifier(name)); + node.mangled_name = name; + return true; + } + }); + this.walk(tw); + to_mangle.forEach(function(def){ def.mangle(options) }); +}); + +AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){ + options = this._default_mangler_options(options); + var tw = new TreeWalker(function(node){ + if (node instanceof AST_Constant) + base54.consider(node.print_to_string()); + else if (node instanceof AST_Return) + base54.consider("return"); + else if (node instanceof AST_Throw) + base54.consider("throw"); + else if (node instanceof AST_Continue) + base54.consider("continue"); + else if (node instanceof AST_Break) + base54.consider("break"); + else if (node instanceof AST_Debugger) + base54.consider("debugger"); + else if (node instanceof AST_Directive) + base54.consider(node.value); + else if (node instanceof AST_While) + base54.consider("while"); + else if (node instanceof AST_Do) + base54.consider("do while"); + else if (node instanceof AST_If) { + base54.consider("if"); + if (node.alternative) base54.consider("else"); + } + else if (node instanceof AST_Var) + base54.consider("var"); + else if (node instanceof AST_Const) + base54.consider("const"); + else if (node instanceof AST_Lambda) + base54.consider("function"); + else if (node instanceof AST_For) + base54.consider("for"); + else if (node instanceof AST_ForIn) + base54.consider("for in"); + else if (node instanceof AST_Switch) + base54.consider("switch"); + else if (node instanceof AST_Case) + base54.consider("case"); + else if (node instanceof AST_Default) + base54.consider("default"); + else if (node instanceof AST_With) + base54.consider("with"); + else if (node instanceof AST_ObjectSetter) + base54.consider("set" + node.key); + else if (node instanceof AST_ObjectGetter) + base54.consider("get" + node.key); + else if (node instanceof AST_ObjectKeyVal) + base54.consider(node.key); + else if (node instanceof AST_New) + base54.consider("new"); + else if (node instanceof AST_This) + base54.consider("this"); + else if (node instanceof AST_Try) + base54.consider("try"); + else if (node instanceof AST_Catch) + base54.consider("catch"); + else if (node instanceof AST_Finally) + base54.consider("finally"); + else if (node instanceof AST_Symbol && node.unmangleable(options)) + base54.consider(node.name); + else if (node instanceof AST_Unary || node instanceof AST_Binary) + base54.consider(node.operator); + else if (node instanceof AST_Dot) + base54.consider(node.property); + }); + this.walk(tw); + base54.sort(); +}); + +var base54 = (function() { + var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789"; + var chars, frequency; + function reset() { + frequency = Object.create(null); + chars = string.split("").map(function(ch){ return ch.charCodeAt(0) }); + chars.forEach(function(ch){ frequency[ch] = 0 }); + } + base54.consider = function(str){ + for (var i = str.length; --i >= 0;) { + var code = str.charCodeAt(i); + if (code in frequency) ++frequency[code]; + } + }; + base54.sort = function() { + chars = mergeSort(chars, function(a, b){ + if (is_digit(a) && !is_digit(b)) return 1; + if (is_digit(b) && !is_digit(a)) return -1; + return frequency[b] - frequency[a]; + }); + }; + base54.reset = reset; + reset(); + base54.get = function(){ return chars }; + base54.freq = function(){ return frequency }; + function base54(num) { + var ret = "", base = 54; + do { + ret += String.fromCharCode(chars[num % base]); + num = Math.floor(num / base); + base = 64; + } while (num > 0); + return ret; + }; + return base54; +})(); + +AST_Toplevel.DEFMETHOD("scope_warnings", function(options){ + options = defaults(options, { + undeclared : false, // this makes a lot of noise + unreferenced : true, + assign_to_global : true, + func_arguments : true, + nested_defuns : true, + eval : true + }); + var tw = new TreeWalker(function(node){ + if (options.undeclared + && node instanceof AST_SymbolRef + && node.undeclared()) + { + // XXX: this also warns about JS standard names, + // i.e. Object, Array, parseInt etc. Should add a list of + // exceptions. + AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", { + name: node.name, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.assign_to_global) + { + var sym = null; + if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) + sym = node.left; + else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef) + sym = node.init; + if (sym + && (sym.undeclared() + || (sym.global() && sym.scope !== sym.definition().scope))) { + AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", { + msg: sym.undeclared() ? "Accidental global?" : "Assignment to global", + name: sym.name, + file: sym.start.file, + line: sym.start.line, + col: sym.start.col + }); + } + } + if (options.eval + && node instanceof AST_SymbolRef + && node.undeclared() + && node.name == "eval") { + AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start); + } + if (options.unreferenced + && (node instanceof AST_SymbolDeclaration || node instanceof AST_Label) + && node.unreferenced()) { + AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", { + type: node instanceof AST_Label ? "Label" : "Symbol", + name: node.name, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.func_arguments + && node instanceof AST_Lambda + && node.uses_arguments) { + AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", { + name: node.name ? node.name.name : "anonymous", + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.nested_defuns + && node instanceof AST_Defun + && !(tw.parent() instanceof AST_Scope)) { + AST_Node.warn("Function {name} declared in nested statement \"{type}\" [{file}:{line},{col}]", { + name: node.name.name, + type: tw.parent().TYPE, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + }); + this.walk(tw); +}); diff --git a/homework7/project_express/node_modules/uglify-js/lib/sourcemap.js b/homework7/project_express/node_modules/uglify-js/lib/sourcemap.js new file mode 100644 index 0000000..3429908 --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/lib/sourcemap.js @@ -0,0 +1,81 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +// a small wrapper around fitzgen's source-map library +function SourceMap(options) { + options = defaults(options, { + file : null, + root : null, + orig : null, + }); + var generator = new MOZ_SourceMap.SourceMapGenerator({ + file : options.file, + sourceRoot : options.root + }); + var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig); + function add(source, gen_line, gen_col, orig_line, orig_col, name) { + if (orig_map) { + var info = orig_map.originalPositionFor({ + line: orig_line, + column: orig_col + }); + source = info.source; + orig_line = info.line; + orig_col = info.column; + name = info.name; + } + generator.addMapping({ + generated : { line: gen_line, column: gen_col }, + original : { line: orig_line, column: orig_col }, + source : source, + name : name + }); + }; + return { + add : add, + get : function() { return generator }, + toString : function() { return generator.toString() } + }; +}; diff --git a/homework7/project_express/node_modules/uglify-js/lib/transform.js b/homework7/project_express/node_modules/uglify-js/lib/transform.js new file mode 100644 index 0000000..8b4fd9f --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/lib/transform.js @@ -0,0 +1,218 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +// Tree transformer helpers. +// XXX: eventually I should refactor the compressor to use this infrastructure. + +function TreeTransformer(before, after) { + TreeWalker.call(this); + this.before = before; + this.after = after; +} +TreeTransformer.prototype = new TreeWalker; + +(function(undefined){ + + function _(node, descend) { + node.DEFMETHOD("transform", function(tw, in_list){ + var x, y; + tw.push(this); + if (tw.before) x = tw.before(this, descend, in_list); + if (x === undefined) { + if (!tw.after) { + x = this; + descend(x, tw); + } else { + tw.stack[tw.stack.length - 1] = x = this.clone(); + descend(x, tw); + y = tw.after(x, in_list); + if (y !== undefined) x = y; + } + } + tw.pop(); + return x; + }); + }; + + function do_list(list, tw) { + return MAP(list, function(node){ + return node.transform(tw, true); + }); + }; + + _(AST_Node, noop); + + _(AST_LabeledStatement, function(self, tw){ + self.label = self.label.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_SimpleStatement, function(self, tw){ + self.body = self.body.transform(tw); + }); + + _(AST_Block, function(self, tw){ + self.body = do_list(self.body, tw); + }); + + _(AST_DWLoop, function(self, tw){ + self.condition = self.condition.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_For, function(self, tw){ + if (self.init) self.init = self.init.transform(tw); + if (self.condition) self.condition = self.condition.transform(tw); + if (self.step) self.step = self.step.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_ForIn, function(self, tw){ + self.init = self.init.transform(tw); + self.object = self.object.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_With, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_Exit, function(self, tw){ + if (self.value) self.value = self.value.transform(tw); + }); + + _(AST_LoopControl, function(self, tw){ + if (self.label) self.label = self.label.transform(tw); + }); + + _(AST_If, function(self, tw){ + self.condition = self.condition.transform(tw); + self.body = self.body.transform(tw); + if (self.alternative) self.alternative = self.alternative.transform(tw); + }); + + _(AST_Switch, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Case, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Try, function(self, tw){ + self.body = do_list(self.body, tw); + if (self.bcatch) self.bcatch = self.bcatch.transform(tw); + if (self.bfinally) self.bfinally = self.bfinally.transform(tw); + }); + + _(AST_Catch, function(self, tw){ + self.argname = self.argname.transform(tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Definitions, function(self, tw){ + self.definitions = do_list(self.definitions, tw); + }); + + _(AST_VarDef, function(self, tw){ + if (self.value) self.value = self.value.transform(tw); + }); + + _(AST_Lambda, function(self, tw){ + if (self.name) self.name = self.name.transform(tw); + self.argnames = do_list(self.argnames, tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Call, function(self, tw){ + self.expression = self.expression.transform(tw); + self.args = do_list(self.args, tw); + }); + + _(AST_Seq, function(self, tw){ + self.car = self.car.transform(tw); + self.cdr = self.cdr.transform(tw); + }); + + _(AST_Dot, function(self, tw){ + self.expression = self.expression.transform(tw); + }); + + _(AST_Sub, function(self, tw){ + self.expression = self.expression.transform(tw); + self.property = self.property.transform(tw); + }); + + _(AST_Unary, function(self, tw){ + self.expression = self.expression.transform(tw); + }); + + _(AST_Binary, function(self, tw){ + self.left = self.left.transform(tw); + self.right = self.right.transform(tw); + }); + + _(AST_Conditional, function(self, tw){ + self.condition = self.condition.transform(tw); + self.consequent = self.consequent.transform(tw); + self.alternative = self.alternative.transform(tw); + }); + + _(AST_Array, function(self, tw){ + self.elements = do_list(self.elements, tw); + }); + + _(AST_Object, function(self, tw){ + self.properties = do_list(self.properties, tw); + }); + + _(AST_ObjectProperty, function(self, tw){ + self.value = self.value.transform(tw); + }); + +})(); diff --git a/homework7/project_express/node_modules/uglify-js/lib/utils.js b/homework7/project_express/node_modules/uglify-js/lib/utils.js new file mode 100644 index 0000000..c95b982 --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/lib/utils.js @@ -0,0 +1,288 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function array_to_hash(a) { + var ret = Object.create(null); + for (var i = 0; i < a.length; ++i) + ret[a[i]] = true; + return ret; +}; + +function slice(a, start) { + return Array.prototype.slice.call(a, start || 0); +}; + +function characters(str) { + return str.split(""); +}; + +function member(name, array) { + for (var i = array.length; --i >= 0;) + if (array[i] == name) + return true; + return false; +}; + +function find_if(func, array) { + for (var i = 0, n = array.length; i < n; ++i) { + if (func(array[i])) + return array[i]; + } +}; + +function repeat_string(str, i) { + if (i <= 0) return ""; + if (i == 1) return str; + var d = repeat_string(str, i >> 1); + d += d; + if (i & 1) d += str; + return d; +}; + +function DefaultsError(msg, defs) { + this.msg = msg; + this.defs = defs; +}; + +function defaults(args, defs, croak) { + if (args === true) + args = {}; + var ret = args || {}; + if (croak) for (var i in ret) if (ret.hasOwnProperty(i) && !defs.hasOwnProperty(i)) + throw new DefaultsError("`" + i + "` is not a supported option", defs); + for (var i in defs) if (defs.hasOwnProperty(i)) { + ret[i] = (args && args.hasOwnProperty(i)) ? args[i] : defs[i]; + } + return ret; +}; + +function merge(obj, ext) { + for (var i in ext) if (ext.hasOwnProperty(i)) { + obj[i] = ext[i]; + } + return obj; +}; + +function noop() {}; + +var MAP = (function(){ + function MAP(a, f, backwards) { + var ret = [], top = [], i; + function doit() { + var val = f(a[i], i); + var is_last = val instanceof Last; + if (is_last) val = val.v; + if (val instanceof AtTop) { + val = val.v; + if (val instanceof Splice) { + top.push.apply(top, backwards ? val.v.slice().reverse() : val.v); + } else { + top.push(val); + } + } + else if (val !== skip) { + if (val instanceof Splice) { + ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v); + } else { + ret.push(val); + } + } + return is_last; + }; + if (a instanceof Array) { + if (backwards) { + for (i = a.length; --i >= 0;) if (doit()) break; + ret.reverse(); + top.reverse(); + } else { + for (i = 0; i < a.length; ++i) if (doit()) break; + } + } + else { + for (i in a) if (a.hasOwnProperty(i)) if (doit()) break; + } + return top.concat(ret); + }; + MAP.at_top = function(val) { return new AtTop(val) }; + MAP.splice = function(val) { return new Splice(val) }; + MAP.last = function(val) { return new Last(val) }; + var skip = MAP.skip = {}; + function AtTop(val) { this.v = val }; + function Splice(val) { this.v = val }; + function Last(val) { this.v = val }; + return MAP; +})(); + +function push_uniq(array, el) { + if (array.indexOf(el) < 0) + array.push(el); +}; + +function string_template(text, props) { + return text.replace(/\{(.+?)\}/g, function(str, p){ + return props[p]; + }); +}; + +function remove(array, el) { + for (var i = array.length; --i >= 0;) { + if (array[i] === el) array.splice(i, 1); + } +}; + +function mergeSort(array, cmp) { + if (array.length < 2) return array.slice(); + function merge(a, b) { + var r = [], ai = 0, bi = 0, i = 0; + while (ai < a.length && bi < b.length) { + cmp(a[ai], b[bi]) <= 0 + ? r[i++] = a[ai++] + : r[i++] = b[bi++]; + } + if (ai < a.length) r.push.apply(r, a.slice(ai)); + if (bi < b.length) r.push.apply(r, b.slice(bi)); + return r; + }; + function _ms(a) { + if (a.length <= 1) + return a; + var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m); + left = _ms(left); + right = _ms(right); + return merge(left, right); + }; + return _ms(array); +}; + +function set_difference(a, b) { + return a.filter(function(el){ + return b.indexOf(el) < 0; + }); +}; + +function set_intersection(a, b) { + return a.filter(function(el){ + return b.indexOf(el) >= 0; + }); +}; + +// this function is taken from Acorn [1], written by Marijn Haverbeke +// [1] https://github.com/marijnh/acorn +function makePredicate(words) { + if (!(words instanceof Array)) words = words.split(" "); + var f = "", cats = []; + out: for (var i = 0; i < words.length; ++i) { + for (var j = 0; j < cats.length; ++j) + if (cats[j][0].length == words[i].length) { + cats[j].push(words[i]); + continue out; + } + cats.push([words[i]]); + } + function compareTo(arr) { + if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";"; + f += "switch(str){"; + for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":"; + f += "return true}return false;"; + } + // When there are more than three length categories, an outer + // switch first dispatches on the lengths, to save on comparisons. + if (cats.length > 3) { + cats.sort(function(a, b) {return b.length - a.length;}); + f += "switch(str.length){"; + for (var i = 0; i < cats.length; ++i) { + var cat = cats[i]; + f += "case " + cat[0].length + ":"; + compareTo(cat); + } + f += "}"; + // Otherwise, simply generate a flat `switch` statement. + } else { + compareTo(words); + } + return new Function("str", f); +}; + +function Dictionary() { + this._values = Object.create(null); + this._size = 0; +}; +Dictionary.prototype = { + set: function(key, val) { + if (!this.has(key)) ++this._size; + this._values["$" + key] = val; + return this; + }, + add: function(key, val) { + if (this.has(key)) { + this.get(key).push(val); + } else { + this.set(key, [ val ]); + } + return this; + }, + get: function(key) { return this._values["$" + key] }, + del: function(key) { + if (this.has(key)) { + --this._size; + delete this._values["$" + key]; + } + return this; + }, + has: function(key) { return ("$" + key) in this._values }, + each: function(f) { + for (var i in this._values) + f(this._values[i], i.substr(1)); + }, + size: function() { + return this._size; + }, + map: function(f) { + var ret = []; + for (var i in this._values) + ret.push(f(this._values[i], i.substr(1))); + return ret; + } +}; diff --git a/homework7/project_express/node_modules/uglify-js/package.json b/homework7/project_express/node_modules/uglify-js/package.json new file mode 100644 index 0000000..e30b268 --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/package.json @@ -0,0 +1,26 @@ +{ + "name": "uglify-js", + "description": "JavaScript parser, mangler/compressor and beautifier toolkit", + "homepage": "http://lisperator.net/uglifyjs", + "main": "tools/node.js", + "version": "2.3.0", + "engines": { "node" : ">=0.4.0" }, + "maintainers": [{ + "name": "Mihai Bazon", + "email": "mihai.bazon@gmail.com", + "web": "http://lisperator.net/" + }], + "repositories": [{ + "type": "git", + "url": "https://github.com/mishoo/UglifyJS2.git" + }], + "dependencies": { + "async" : "~0.2.6", + "source-map" : "~0.1.7", + "optimist" : "~0.3.5" + }, + "bin": { + "uglifyjs" : "bin/uglifyjs" + }, + "scripts": {"test": "node test/run-tests.js"} +} diff --git a/homework7/project_express/node_modules/uglify-js/test/compress/arrays.js b/homework7/project_express/node_modules/uglify-js/test/compress/arrays.js new file mode 100644 index 0000000..10fe6eb --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/test/compress/arrays.js @@ -0,0 +1,12 @@ +holes_and_undefined: { + input: { + x = [1, 2, undefined]; + y = [1, , 2, ]; + z = [1, undefined, 3]; + } + expect: { + x=[1,2,void 0]; + y=[1,,2]; + z=[1,void 0,3]; + } +} diff --git a/homework7/project_express/node_modules/uglify-js/test/compress/blocks.js b/homework7/project_express/node_modules/uglify-js/test/compress/blocks.js new file mode 100644 index 0000000..8372adf --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/test/compress/blocks.js @@ -0,0 +1,49 @@ +remove_blocks: { + input: { + {;} + foo(); + {}; + { + {}; + }; + bar(); + {} + } + expect: { + foo(); + bar(); + } +} + +keep_some_blocks: { + input: { + // 1. + if (foo) { + {{{}}} + if (bar) { baz(); } + {{}} + } else { + stuff(); + } + + // 2. + if (foo) { + for (var i = 0; i < 5; ++i) + if (bar) baz(); + } else { + stuff(); + } + } + expect: { + // 1. + if (foo) { + if (bar) baz(); + } else stuff(); + + // 2. + if (foo) { + for (var i = 0; i < 5; ++i) + if (bar) baz(); + } else stuff(); + } +} diff --git a/homework7/project_express/node_modules/uglify-js/test/compress/conditionals.js b/homework7/project_express/node_modules/uglify-js/test/compress/conditionals.js new file mode 100644 index 0000000..dc2bb67 --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/test/compress/conditionals.js @@ -0,0 +1,143 @@ +ifs_1: { + options = { + conditionals: true + }; + input: { + if (foo) bar(); + if (!foo); else bar(); + if (foo); else bar(); + if (foo); else; + } + expect: { + foo&&bar(); + foo&&bar(); + foo||bar(); + foo; + } +} + +ifs_2: { + options = { + conditionals: true + }; + input: { + if (foo) { + x(); + } else if (bar) { + y(); + } else if (baz) { + z(); + } + + if (foo) { + x(); + } else if (bar) { + y(); + } else if (baz) { + z(); + } else { + t(); + } + } + expect: { + foo ? x() : bar ? y() : baz && z(); + foo ? x() : bar ? y() : baz ? z() : t(); + } +} + +ifs_3_should_warn: { + options = { + conditionals : true, + dead_code : true, + evaluate : true, + booleans : true + }; + input: { + if (x && !(x + "1") && y) { // 1 + var qq; + foo(); + } else { + bar(); + } + + if (x || !!(x + "1") || y) { // 2 + foo(); + } else { + var jj; + bar(); + } + } + expect: { + var qq; bar(); // 1 + var jj; foo(); // 2 + } +} + +ifs_4: { + options = { + conditionals: true + }; + input: { + if (foo && bar) { + x(foo)[10].bar.baz = something(); + } else + x(foo)[10].bar.baz = something_else(); + } + expect: { + x(foo)[10].bar.baz = (foo && bar) ? something() : something_else(); + } +} + +ifs_5: { + options = { + if_return: true, + conditionals: true, + comparisons: true, + }; + input: { + function f() { + if (foo) return; + bar(); + baz(); + } + function g() { + if (foo) return; + if (bar) return; + if (baz) return; + if (baa) return; + a(); + b(); + } + } + expect: { + function f() { + if (!foo) { + bar(); + baz(); + } + } + function g() { + if (!(foo || bar || baz || baa)) { + a(); + b(); + } + } + } +} + +ifs_6: { + options = { + conditionals: true, + comparisons: true + }; + input: { + if (!foo && !bar && !baz && !boo) { + x = 10; + } else { + x = 20; + } + } + expect: { + x = foo || bar || baz || boo ? 20 : 10; + } +} diff --git a/homework7/project_express/node_modules/uglify-js/test/compress/dead-code.js b/homework7/project_express/node_modules/uglify-js/test/compress/dead-code.js new file mode 100644 index 0000000..0fd066e --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/test/compress/dead-code.js @@ -0,0 +1,89 @@ +dead_code_1: { + options = { + dead_code: true + }; + input: { + function f() { + a(); + b(); + x = 10; + return; + if (x) { + y(); + } + } + } + expect: { + function f() { + a(); + b(); + x = 10; + return; + } + } +} + +dead_code_2_should_warn: { + options = { + dead_code: true + }; + input: { + function f() { + g(); + x = 10; + throw "foo"; + // completely discarding the `if` would introduce some + // bugs. UglifyJS v1 doesn't deal with this issue; in v2 + // we copy any declarations to the upper scope. + if (x) { + y(); + var x; + function g(){}; + // but nested declarations should not be kept. + (function(){ + var q; + function y(){}; + })(); + } + } + } + expect: { + function f() { + g(); + x = 10; + throw "foo"; + var x; + function g(){}; + } + } +} + +dead_code_constant_boolean_should_warn_more: { + options = { + dead_code : true, + loops : true, + booleans : true, + conditionals : true, + evaluate : true + }; + input: { + while (!((foo && bar) || (x + "0"))) { + console.log("unreachable"); + var foo; + function bar() {} + } + for (var x = 10; x && (y || x) && (!typeof x); ++x) { + asdf(); + foo(); + var moo; + } + } + expect: { + var foo; + function bar() {} + // nothing for the while + // as for the for, it should keep: + var x = 10; + var moo; + } +} diff --git a/homework7/project_express/node_modules/uglify-js/test/compress/debugger.js b/homework7/project_express/node_modules/uglify-js/test/compress/debugger.js new file mode 100644 index 0000000..7c27073 --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/test/compress/debugger.js @@ -0,0 +1,24 @@ +keep_debugger: { + options = { + drop_debugger: false + }; + input: { + debugger; + } + expect: { + debugger; + } +} + +drop_debugger: { + options = { + drop_debugger: true + }; + input: { + debugger; + if (foo) debugger; + } + expect: { + if (foo); + } +} diff --git a/homework7/project_express/node_modules/uglify-js/test/compress/drop-unused.js b/homework7/project_express/node_modules/uglify-js/test/compress/drop-unused.js new file mode 100644 index 0000000..bf5cd29 --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/test/compress/drop-unused.js @@ -0,0 +1,97 @@ +unused_funarg_1: { + options = { unused: true }; + input: { + function f(a, b, c, d, e) { + return a + b; + } + } + expect: { + function f(a, b) { + return a + b; + } + } +} + +unused_funarg_2: { + options = { unused: true }; + input: { + function f(a, b, c, d, e) { + return a + c; + } + } + expect: { + function f(a, b, c) { + return a + c; + } + } +} + +unused_nested_function: { + options = { unused: true }; + input: { + function f(x, y) { + function g() { + something(); + } + return x + y; + } + }; + expect: { + function f(x, y) { + return x + y; + } + } +} + +unused_circular_references_1: { + options = { unused: true }; + input: { + function f(x, y) { + // circular reference + function g() { + return h(); + } + function h() { + return g(); + } + return x + y; + } + }; + expect: { + function f(x, y) { + return x + y; + } + } +} + +unused_circular_references_2: { + options = { unused: true }; + input: { + function f(x, y) { + var foo = 1, bar = baz, baz = foo + bar, qwe = moo(); + return x + y; + } + }; + expect: { + function f(x, y) { + moo(); // keeps side effect + return x + y; + } + } +} + +unused_circular_references_3: { + options = { unused: true }; + input: { + function f(x, y) { + var g = function() { return h() }; + var h = function() { return g() }; + return x + y; + } + }; + expect: { + function f(x, y) { + return x + y; + } + } +} diff --git a/homework7/project_express/node_modules/uglify-js/test/compress/issue-105.js b/homework7/project_express/node_modules/uglify-js/test/compress/issue-105.js new file mode 100644 index 0000000..349d732 --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/test/compress/issue-105.js @@ -0,0 +1,17 @@ +typeof_eq_undefined: { + options = { + comparisons: true, + unsafe: false + }; + input: { a = typeof b.c != "undefined" } + expect: { a = "undefined" != typeof b.c } +} + +typeof_eq_undefined_unsafe: { + options = { + comparisons: true, + unsafe: true + }; + input: { a = typeof b.c != "undefined" } + expect: { a = b.c !== void 0 } +} diff --git a/homework7/project_express/node_modules/uglify-js/test/compress/issue-12.js b/homework7/project_express/node_modules/uglify-js/test/compress/issue-12.js new file mode 100644 index 0000000..bf87d5c --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/test/compress/issue-12.js @@ -0,0 +1,11 @@ +keep_name_of_getter: { + options = { unused: true }; + input: { a = { get foo () {} } } + expect: { a = { get foo () {} } } +} + +keep_name_of_setter: { + options = { unused: true }; + input: { a = { set foo () {} } } + expect: { a = { set foo () {} } } +} diff --git a/homework7/project_express/node_modules/uglify-js/test/compress/issue-22.js b/homework7/project_express/node_modules/uglify-js/test/compress/issue-22.js new file mode 100644 index 0000000..a8b7bc6 --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/test/compress/issue-22.js @@ -0,0 +1,17 @@ +return_with_no_value_in_if_body: { + options = { conditionals: true }; + input: { + function foo(bar) { + if (bar) { + return; + } else { + return 1; + } + } + } + expect: { + function foo (bar) { + return bar ? void 0 : 1; + } + } +} diff --git a/homework7/project_express/node_modules/uglify-js/test/compress/issue-44.js b/homework7/project_express/node_modules/uglify-js/test/compress/issue-44.js new file mode 100644 index 0000000..7a972f9 --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/test/compress/issue-44.js @@ -0,0 +1,31 @@ +issue_44_valid_ast_1: { + options = { unused: true }; + input: { + function a(b) { + for (var i = 0, e = b.qoo(); ; i++) {} + } + } + expect: { + function a(b) { + var i = 0; + for (b.qoo(); ; i++); + } + } +} + +issue_44_valid_ast_2: { + options = { unused: true }; + input: { + function a(b) { + if (foo) for (var i = 0, e = b.qoo(); ; i++) {} + } + } + expect: { + function a(b) { + if (foo) { + var i = 0; + for (b.qoo(); ; i++); + } + } + } +} diff --git a/homework7/project_express/node_modules/uglify-js/test/compress/issue-59.js b/homework7/project_express/node_modules/uglify-js/test/compress/issue-59.js new file mode 100644 index 0000000..82b3880 --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/test/compress/issue-59.js @@ -0,0 +1,30 @@ +keep_continue: { + options = { + dead_code: true, + evaluate: true + }; + input: { + while (a) { + if (b) { + switch (true) { + case c(): + d(); + } + continue; + } + f(); + } + } + expect: { + while (a) { + if (b) { + switch (true) { + case c(): + d(); + } + continue; + } + f(); + } + } +} diff --git a/homework7/project_express/node_modules/uglify-js/test/compress/labels.js b/homework7/project_express/node_modules/uglify-js/test/compress/labels.js new file mode 100644 index 0000000..044b7a7 --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/test/compress/labels.js @@ -0,0 +1,163 @@ +labels_1: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: { + if (foo) break out; + console.log("bar"); + } + }; + expect: { + foo || console.log("bar"); + } +} + +labels_2: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: { + if (foo) print("stuff"); + else break out; + console.log("here"); + } + }; + expect: { + if (foo) { + print("stuff"); + console.log("here"); + } + } +} + +labels_3: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + for (var i = 0; i < 5; ++i) { + if (i < 3) continue; + console.log(i); + } + }; + expect: { + for (var i = 0; i < 5; ++i) + i < 3 || console.log(i); + } +} + +labels_4: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: for (var i = 0; i < 5; ++i) { + if (i < 3) continue out; + console.log(i); + } + }; + expect: { + for (var i = 0; i < 5; ++i) + i < 3 || console.log(i); + } +} + +labels_5: { + options = { if_return: true, conditionals: true, dead_code: true }; + // should keep the break-s in the following + input: { + while (foo) { + if (bar) break; + console.log("foo"); + } + out: while (foo) { + if (bar) break out; + console.log("foo"); + } + }; + expect: { + while (foo) { + if (bar) break; + console.log("foo"); + } + out: while (foo) { + if (bar) break out; + console.log("foo"); + } + } +} + +labels_6: { + input: { + out: break out; + }; + expect: {} +} + +labels_7: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + while (foo) { + x(); + y(); + continue; + } + }; + expect: { + while (foo) { + x(); + y(); + } + } +} + +labels_8: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + while (foo) { + x(); + y(); + break; + } + }; + expect: { + while (foo) { + x(); + y(); + break; + } + } +} + +labels_9: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: while (foo) { + x(); + y(); + continue out; + z(); + k(); + } + }; + expect: { + while (foo) { + x(); + y(); + } + } +} + +labels_10: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: while (foo) { + x(); + y(); + break out; + z(); + k(); + } + }; + expect: { + out: while (foo) { + x(); + y(); + break out; + } + } +} diff --git a/homework7/project_express/node_modules/uglify-js/test/compress/loops.js b/homework7/project_express/node_modules/uglify-js/test/compress/loops.js new file mode 100644 index 0000000..cdf1f04 --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/test/compress/loops.js @@ -0,0 +1,123 @@ +while_becomes_for: { + options = { loops: true }; + input: { + while (foo()) bar(); + } + expect: { + for (; foo(); ) bar(); + } +} + +drop_if_break_1: { + options = { loops: true }; + input: { + for (;;) + if (foo()) break; + } + expect: { + for (; !foo();); + } +} + +drop_if_break_2: { + options = { loops: true }; + input: { + for (;bar();) + if (foo()) break; + } + expect: { + for (; bar() && !foo();); + } +} + +drop_if_break_3: { + options = { loops: true }; + input: { + for (;bar();) { + if (foo()) break; + stuff1(); + stuff2(); + } + } + expect: { + for (; bar() && !foo();) { + stuff1(); + stuff2(); + } + } +} + +drop_if_break_4: { + options = { loops: true, sequences: true }; + input: { + for (;bar();) { + x(); + y(); + if (foo()) break; + z(); + k(); + } + } + expect: { + for (; bar() && (x(), y(), !foo());) z(), k(); + } +} + +drop_if_else_break_1: { + options = { loops: true }; + input: { + for (;;) if (foo()) bar(); else break; + } + expect: { + for (; foo(); ) bar(); + } +} + +drop_if_else_break_2: { + options = { loops: true }; + input: { + for (;bar();) { + if (foo()) baz(); + else break; + } + } + expect: { + for (; bar() && foo();) baz(); + } +} + +drop_if_else_break_3: { + options = { loops: true }; + input: { + for (;bar();) { + if (foo()) baz(); + else break; + stuff1(); + stuff2(); + } + } + expect: { + for (; bar() && foo();) { + baz(); + stuff1(); + stuff2(); + } + } +} + +drop_if_else_break_4: { + options = { loops: true, sequences: true }; + input: { + for (;bar();) { + x(); + y(); + if (foo()) baz(); + else break; + z(); + k(); + } + } + expect: { + for (; bar() && (x(), y(), foo());) baz(), z(), k(); + } +} diff --git a/homework7/project_express/node_modules/uglify-js/test/compress/properties.js b/homework7/project_express/node_modules/uglify-js/test/compress/properties.js new file mode 100644 index 0000000..9b066ec --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/test/compress/properties.js @@ -0,0 +1,40 @@ +keep_properties: { + options = { + properties: false + }; + input: { + a["foo"] = "bar"; + } + expect: { + a["foo"] = "bar"; + } +} + +dot_properties: { + options = { + properties: true + }; + input: { + a["foo"] = "bar"; + a["if"] = "if"; + } + expect: { + a.foo = "bar"; + a["if"] = "if"; + } +} + +dot_properties_es5: { + options = { + properties: true, + screw_ie8: true + }; + input: { + a["foo"] = "bar"; + a["if"] = "if"; + } + expect: { + a.foo = "bar"; + a.if = "if"; + } +} diff --git a/homework7/project_express/node_modules/uglify-js/test/compress/sequences.js b/homework7/project_express/node_modules/uglify-js/test/compress/sequences.js new file mode 100644 index 0000000..6f63ace --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/test/compress/sequences.js @@ -0,0 +1,161 @@ +make_sequences_1: { + options = { + sequences: true + }; + input: { + foo(); + bar(); + baz(); + } + expect: { + foo(),bar(),baz(); + } +} + +make_sequences_2: { + options = { + sequences: true + }; + input: { + if (boo) { + foo(); + bar(); + baz(); + } else { + x(); + y(); + z(); + } + } + expect: { + if (boo) foo(),bar(),baz(); + else x(),y(),z(); + } +} + +make_sequences_3: { + options = { + sequences: true + }; + input: { + function f() { + foo(); + bar(); + return baz(); + } + function g() { + foo(); + bar(); + throw new Error(); + } + } + expect: { + function f() { + return foo(), bar(), baz(); + } + function g() { + throw foo(), bar(), new Error(); + } + } +} + +make_sequences_4: { + options = { + sequences: true + }; + input: { + x = 5; + if (y) z(); + + x = 5; + for (i = 0; i < 5; i++) console.log(i); + + x = 5; + for (; i < 5; i++) console.log(i); + + x = 5; + switch (y) {} + + x = 5; + with (obj) {} + } + expect: { + if (x = 5, y) z(); + for (x = 5, i = 0; i < 5; i++) console.log(i); + for (x = 5; i < 5; i++) console.log(i); + switch (x = 5, y) {} + with (x = 5, obj); + } +} + +lift_sequences_1: { + options = { sequences: true }; + input: { + foo = !(x(), y(), bar()); + } + expect: { + x(), y(), foo = !bar(); + } +} + +lift_sequences_2: { + options = { sequences: true, evaluate: true }; + input: { + q = 1 + (foo(), bar(), 5) + 7 * (5 / (3 - (a(), (QW=ER), c(), 2))) - (x(), y(), 5); + } + expect: { + foo(), bar(), a(), QW = ER, c(), x(), y(), q = 36 + } +} + +lift_sequences_3: { + options = { sequences: true, conditionals: true }; + input: { + x = (foo(), bar(), baz()) ? 10 : 20; + } + expect: { + foo(), bar(), x = baz() ? 10 : 20; + } +} + +lift_sequences_4: { + options = { side_effects: true }; + input: { + x = (foo, bar, baz); + } + expect: { + x = baz; + } +} + +for_sequences: { + options = { sequences: true }; + input: { + // 1 + foo(); + bar(); + for (; false;); + // 2 + foo(); + bar(); + for (x = 5; false;); + // 3 + x = (foo in bar); + for (; false;); + // 4 + x = (foo in bar); + for (y = 5; false;); + } + expect: { + // 1 + for (foo(), bar(); false;); + // 2 + for (foo(), bar(), x = 5; false;); + // 3 + x = (foo in bar); + for (; false;); + // 4 + x = (foo in bar); + for (y = 5; false;); + } +} diff --git a/homework7/project_express/node_modules/uglify-js/test/compress/switch.js b/homework7/project_express/node_modules/uglify-js/test/compress/switch.js new file mode 100644 index 0000000..62e39cf --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/test/compress/switch.js @@ -0,0 +1,260 @@ +constant_switch_1: { + options = { dead_code: true, evaluate: true }; + input: { + switch (1+1) { + case 1: foo(); break; + case 1+1: bar(); break; + case 1+1+1: baz(); break; + } + } + expect: { + bar(); + } +} + +constant_switch_2: { + options = { dead_code: true, evaluate: true }; + input: { + switch (1) { + case 1: foo(); + case 1+1: bar(); break; + case 1+1+1: baz(); + } + } + expect: { + foo(); + bar(); + } +} + +constant_switch_3: { + options = { dead_code: true, evaluate: true }; + input: { + switch (10) { + case 1: foo(); + case 1+1: bar(); break; + case 1+1+1: baz(); + default: + def(); + } + } + expect: { + def(); + } +} + +constant_switch_4: { + options = { dead_code: true, evaluate: true }; + input: { + switch (2) { + case 1: + x(); + if (foo) break; + y(); + break; + case 1+1: + bar(); + default: + def(); + } + } + expect: { + bar(); + def(); + } +} + +constant_switch_5: { + options = { dead_code: true, evaluate: true }; + input: { + switch (1) { + case 1: + x(); + if (foo) break; + y(); + break; + case 1+1: + bar(); + default: + def(); + } + } + expect: { + // the break inside the if ruins our job + // we can still get rid of irrelevant cases. + switch (1) { + case 1: + x(); + if (foo) break; + y(); + } + // XXX: we could optimize this better by inventing an outer + // labeled block, but that's kinda tricky. + } +} + +constant_switch_6: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: { + foo(); + switch (1) { + case 1: + x(); + if (foo) break OUT; + y(); + case 1+1: + bar(); + break; + default: + def(); + } + } + } + expect: { + OUT: { + foo(); + x(); + if (foo) break OUT; + y(); + bar(); + } + } +} + +constant_switch_7: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: { + foo(); + switch (1) { + case 1: + x(); + if (foo) break OUT; + for (var x = 0; x < 10; x++) { + if (x > 5) break; // this break refers to the for, not to the switch; thus it + // shouldn't ruin our optimization + console.log(x); + } + y(); + case 1+1: + bar(); + break; + default: + def(); + } + } + } + expect: { + OUT: { + foo(); + x(); + if (foo) break OUT; + for (var x = 0; x < 10; x++) { + if (x > 5) break; + console.log(x); + } + y(); + bar(); + } + } +} + +constant_switch_8: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: switch (1) { + case 1: + x(); + for (;;) break OUT; + y(); + break; + case 1+1: + bar(); + default: + def(); + } + } + expect: { + OUT: { + x(); + for (;;) break OUT; + y(); + } + } +} + +constant_switch_9: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: switch (1) { + case 1: + x(); + for (;;) if (foo) break OUT; + y(); + case 1+1: + bar(); + default: + def(); + } + } + expect: { + OUT: { + x(); + for (;;) if (foo) break OUT; + y(); + bar(); + def(); + } + } +} + +drop_default_1: { + options = { dead_code: true }; + input: { + switch (foo) { + case 'bar': baz(); + default: + } + } + expect: { + switch (foo) { + case 'bar': baz(); + } + } +} + +drop_default_2: { + options = { dead_code: true }; + input: { + switch (foo) { + case 'bar': baz(); break; + default: + break; + } + } + expect: { + switch (foo) { + case 'bar': baz(); + } + } +} + +keep_default: { + options = { dead_code: true }; + input: { + switch (foo) { + case 'bar': baz(); + default: + something(); + break; + } + } + expect: { + switch (foo) { + case 'bar': baz(); + default: + something(); + } + } +} diff --git a/homework7/project_express/node_modules/uglify-js/test/compress/typeof.js b/homework7/project_express/node_modules/uglify-js/test/compress/typeof.js new file mode 100644 index 0000000..cefdd43 --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/test/compress/typeof.js @@ -0,0 +1,25 @@ +typeof_evaluation: { + options = { + evaluate: true + }; + input: { + a = typeof 1; + b = typeof 'test'; + c = typeof []; + d = typeof {}; + e = typeof /./; + f = typeof false; + g = typeof function(){}; + h = typeof undefined; + } + expect: { + a='number'; + b='string'; + c=typeof[]; + d=typeof{}; + e=typeof/./; + f='boolean'; + g='function'; + h='undefined'; + } +} diff --git a/homework7/project_express/node_modules/uglify-js/test/run-tests.js b/homework7/project_express/node_modules/uglify-js/test/run-tests.js new file mode 100644 index 0000000..0568c6a --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/test/run-tests.js @@ -0,0 +1,170 @@ +#! /usr/bin/env node + +var U = require("../tools/node"); +var path = require("path"); +var fs = require("fs"); +var assert = require("assert"); +var sys = require("util"); + +var tests_dir = path.dirname(module.filename); + +run_compress_tests(); + +/* -----[ utils ]----- */ + +function tmpl() { + return U.string_template.apply(this, arguments); +} + +function log() { + var txt = tmpl.apply(this, arguments); + sys.puts(txt); +} + +function log_directory(dir) { + log("*** Entering [{dir}]", { dir: dir }); +} + +function log_start_file(file) { + log("--- {file}", { file: file }); +} + +function log_test(name) { + log(" Running test [{name}]", { name: name }); +} + +function find_test_files(dir) { + var files = fs.readdirSync(dir).filter(function(name){ + return /\.js$/i.test(name); + }); + if (process.argv.length > 2) { + var x = process.argv.slice(2); + files = files.filter(function(f){ + return x.indexOf(f) >= 0; + }); + } + return files; +} + +function test_directory(dir) { + return path.resolve(tests_dir, dir); +} + +function as_toplevel(input) { + if (input instanceof U.AST_BlockStatement) input = input.body; + else if (input instanceof U.AST_Statement) input = [ input ]; + else throw new Error("Unsupported input syntax"); + var toplevel = new U.AST_Toplevel({ body: input }); + toplevel.figure_out_scope(); + return toplevel; +} + +function run_compress_tests() { + var dir = test_directory("compress"); + log_directory("compress"); + var files = find_test_files(dir); + function test_file(file) { + log_start_file(file); + function test_case(test) { + log_test(test.name); + var options = U.defaults(test.options, { + warnings: false + }); + var cmp = new U.Compressor(options, true); + var expect = make_code(as_toplevel(test.expect), false); + var input = as_toplevel(test.input); + var input_code = make_code(test.input); + var output = input.transform(cmp); + output.figure_out_scope(); + output = make_code(output, false); + if (expect != output) { + log("!!! failed\n---INPUT---\n{input}\n---OUTPUT---\n{output}\n---EXPECTED---\n{expected}\n\n", { + input: input_code, + output: output, + expected: expect + }); + } + } + var tests = parse_test(path.resolve(dir, file)); + for (var i in tests) if (tests.hasOwnProperty(i)) { + test_case(tests[i]); + } + } + files.forEach(function(file){ + test_file(file); + }); +} + +function parse_test(file) { + var script = fs.readFileSync(file, "utf8"); + var ast = U.parse(script, { + filename: file + }); + var tests = {}; + var tw = new U.TreeWalker(function(node, descend){ + if (node instanceof U.AST_LabeledStatement + && tw.parent() instanceof U.AST_Toplevel) { + var name = node.label.name; + tests[name] = get_one_test(name, node.body); + return true; + } + if (!(node instanceof U.AST_Toplevel)) croak(node); + }); + ast.walk(tw); + return tests; + + function croak(node) { + throw new Error(tmpl("Can't understand test file {file} [{line},{col}]\n{code}", { + file: file, + line: node.start.line, + col: node.start.col, + code: make_code(node, false) + })); + } + + function get_one_test(name, block) { + var test = { name: name, options: {} }; + var tw = new U.TreeWalker(function(node, descend){ + if (node instanceof U.AST_Assign) { + if (!(node.left instanceof U.AST_SymbolRef)) { + croak(node); + } + var name = node.left.name; + test[name] = evaluate(node.right); + return true; + } + if (node instanceof U.AST_LabeledStatement) { + assert.ok( + node.label.name == "input" || node.label.name == "expect", + tmpl("Unsupported label {name} [{line},{col}]", { + name: node.label.name, + line: node.label.start.line, + col: node.label.start.col + }) + ); + var stat = node.body; + if (stat instanceof U.AST_BlockStatement) { + if (stat.body.length == 1) stat = stat.body[0]; + else if (stat.body.length == 0) stat = new U.AST_EmptyStatement(); + } + test[node.label.name] = stat; + return true; + } + }); + block.walk(tw); + return test; + }; +} + +function make_code(ast, beautify) { + if (arguments.length == 1) beautify = true; + var stream = U.OutputStream({ beautify: beautify }); + ast.print(stream); + return stream.get(); +} + +function evaluate(code) { + if (code instanceof U.AST_Node) + code = make_code(code); + return new Function("return(" + code + ")")(); +} diff --git a/homework7/project_express/node_modules/uglify-js/tools/node.js b/homework7/project_express/node_modules/uglify-js/tools/node.js new file mode 100644 index 0000000..c0dd3db --- /dev/null +++ b/homework7/project_express/node_modules/uglify-js/tools/node.js @@ -0,0 +1,165 @@ +var path = require("path"); +var fs = require("fs"); +var vm = require("vm"); +var sys = require("util"); + +var UglifyJS = vm.createContext({ + sys : sys, + console : console, + MOZ_SourceMap : require("source-map") +}); + +function load_global(file) { + file = path.resolve(path.dirname(module.filename), file); + try { + var code = fs.readFileSync(file, "utf8"); + return vm.runInContext(code, UglifyJS, file); + } catch(ex) { + // XXX: in case of a syntax error, the message is kinda + // useless. (no location information). + sys.debug("ERROR in file: " + file + " / " + ex); + process.exit(1); + } +}; + +var FILES = exports.FILES = [ + "../lib/utils.js", + "../lib/ast.js", + "../lib/parse.js", + "../lib/transform.js", + "../lib/scope.js", + "../lib/output.js", + "../lib/compress.js", + "../lib/sourcemap.js", + "../lib/mozilla-ast.js" +].map(function(file){ + return path.join(path.dirname(fs.realpathSync(__filename)), file); +}); + +FILES.forEach(load_global); + +UglifyJS.AST_Node.warn_function = function(txt) { + sys.error("WARN: " + txt); +}; + +// XXX: perhaps we shouldn't export everything but heck, I'm lazy. +for (var i in UglifyJS) { + if (UglifyJS.hasOwnProperty(i)) { + exports[i] = UglifyJS[i]; + } +} + +exports.minify = function(files, options) { + options = UglifyJS.defaults(options, { + outSourceMap : null, + sourceRoot : null, + inSourceMap : null, + fromString : false, + warnings : false, + mangle : {}, + output : null, + compress : {} + }); + if (typeof files == "string") + files = [ files ]; + + // 1. parse + var toplevel = null; + files.forEach(function(file){ + var code = options.fromString + ? file + : fs.readFileSync(file, "utf8"); + toplevel = UglifyJS.parse(code, { + filename: options.fromString ? "?" : file, + toplevel: toplevel + }); + }); + + // 2. compress + if (options.compress) { + var compress = { warnings: options.warnings }; + UglifyJS.merge(compress, options.compress); + toplevel.figure_out_scope(); + var sq = UglifyJS.Compressor(compress); + toplevel = toplevel.transform(sq); + } + + // 3. mangle + if (options.mangle) { + toplevel.figure_out_scope(); + toplevel.compute_char_frequency(); + toplevel.mangle_names(options.mangle); + } + + // 4. output + var inMap = options.inSourceMap; + var output = {}; + if (typeof options.inSourceMap == "string") { + inMap = fs.readFileSync(options.inSourceMap, "utf8"); + } + if (options.outSourceMap) { + output.source_map = UglifyJS.SourceMap({ + file: options.outSourceMap, + orig: inMap, + root: options.sourceRoot + }); + } + if (options.output) { + UglifyJS.merge(output, options.output); + } + var stream = UglifyJS.OutputStream(output); + toplevel.print(stream); + return { + code : stream + "", + map : output.source_map + "" + }; +}; + +// exports.describe_ast = function() { +// function doitem(ctor) { +// var sub = {}; +// ctor.SUBCLASSES.forEach(function(ctor){ +// sub[ctor.TYPE] = doitem(ctor); +// }); +// var ret = {}; +// if (ctor.SELF_PROPS.length > 0) ret.props = ctor.SELF_PROPS; +// if (ctor.SUBCLASSES.length > 0) ret.sub = sub; +// return ret; +// } +// return doitem(UglifyJS.AST_Node).sub; +// } + +exports.describe_ast = function() { + var out = UglifyJS.OutputStream({ beautify: true }); + function doitem(ctor) { + out.print("AST_" + ctor.TYPE); + var props = ctor.SELF_PROPS.filter(function(prop){ + return !/^\$/.test(prop); + }); + if (props.length > 0) { + out.space(); + out.with_parens(function(){ + props.forEach(function(prop, i){ + if (i) out.space(); + out.print(prop); + }); + }); + } + if (ctor.documentation) { + out.space(); + out.print_string(ctor.documentation); + } + if (ctor.SUBCLASSES.length > 0) { + out.space(); + out.with_block(function(){ + ctor.SUBCLASSES.forEach(function(ctor, i){ + out.indent(); + doitem(ctor); + out.newline(); + }); + }); + } + }; + doitem(UglifyJS.AST_Node); + return out + ""; +}; diff --git a/homework7/project_express/node_modules/undefsafe/.github/workflows/release.yml b/homework7/project_express/node_modules/undefsafe/.github/workflows/release.yml new file mode 100644 index 0000000..e6ee886 --- /dev/null +++ b/homework7/project_express/node_modules/undefsafe/.github/workflows/release.yml @@ -0,0 +1,25 @@ +name: Release +on: + push: + branches: + - master +jobs: + release: + name: Release + runs-on: ubuntu-18.04 + steps: + - name: Checkout + uses: actions/checkout@v1 + - name: Setup Node.js + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install dependencies + run: npm ci + - name: Test + run: npm run test + - name: Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + run: npx semantic-release diff --git a/homework7/project_express/node_modules/undefsafe/.jscsrc b/homework7/project_express/node_modules/undefsafe/.jscsrc new file mode 100644 index 0000000..9e01c9b --- /dev/null +++ b/homework7/project_express/node_modules/undefsafe/.jscsrc @@ -0,0 +1,13 @@ +{ + "preset": "node-style-guide", + "requireCapitalizedComments": null, + "requireSpacesInAnonymousFunctionExpression": { + "beforeOpeningCurlyBrace": true, + "beforeOpeningRoundBrace": true + }, + "disallowSpacesInNamedFunctionExpression": { + "beforeOpeningRoundBrace": true + }, + "excludeFiles": ["node_modules/**"], + "disallowSpacesInFunction": null +} diff --git a/homework7/project_express/node_modules/undefsafe/.jshintrc b/homework7/project_express/node_modules/undefsafe/.jshintrc new file mode 100644 index 0000000..b47f672 --- /dev/null +++ b/homework7/project_express/node_modules/undefsafe/.jshintrc @@ -0,0 +1,16 @@ +{ + "browser": false, + "camelcase": true, + "curly": true, + "devel": true, + "eqeqeq": true, + "forin": true, + "indent": 2, + "noarg": true, + "node": true, + "quotmark": "single", + "undef": true, + "strict": false, + "unused": true +} + diff --git a/homework7/project_express/node_modules/undefsafe/.travis.yml b/homework7/project_express/node_modules/undefsafe/.travis.yml new file mode 100644 index 0000000..a1ace24 --- /dev/null +++ b/homework7/project_express/node_modules/undefsafe/.travis.yml @@ -0,0 +1,18 @@ +sudo: false +language: node_js +cache: + directories: + - node_modules +notifications: + email: false +node_js: + - '4' +before_install: + - npm i -g npm@^2.0.0 +before_script: + - npm prune +after_success: + - npm run semantic-release +branches: + except: + - "/^v\\d+\\.\\d+\\.\\d+$/" diff --git a/homework7/project_express/node_modules/undefsafe/LICENSE b/homework7/project_express/node_modules/undefsafe/LICENSE new file mode 100644 index 0000000..caaf03a --- /dev/null +++ b/homework7/project_express/node_modules/undefsafe/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright © 2016 Remy Sharp, http://remysharp.com + +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/homework7/project_express/node_modules/undefsafe/README.md b/homework7/project_express/node_modules/undefsafe/README.md new file mode 100644 index 0000000..46a706b --- /dev/null +++ b/homework7/project_express/node_modules/undefsafe/README.md @@ -0,0 +1,63 @@ +# undefsafe + +Simple *function* for retrieving deep object properties without getting "Cannot read property 'X' of undefined" + +Can also be used to safely set deep values. + +## Usage + +```js +var object = { + a: { + b: { + c: 1, + d: [1,2,3], + e: 'remy' + } + } +}; + +console.log(undefsafe(object, 'a.b.e')); // "remy" +console.log(undefsafe(object, 'a.b.not.found')); // undefined +``` + +Demo: [https://jsbin.com/eroqame/3/edit?js,console](https://jsbin.com/eroqame/3/edit?js,console) + +## Setting + +```js +var object = { + a: { + b: [1,2,3] + } +}; + +// modified object +var res = undefsafe(object, 'a.b.0', 10); + +console.log(object); // { a: { b: [10, 2, 3] } } +console.log(res); // 1 - previous value +``` + +## Star rules in paths + +As of 1.2.0, `undefsafe` supports a `*` in the path if you want to search all of the properties (or array elements) for a particular element. + +The function will only return a single result, either the 3rd argument validation value, or the first positive match. For example, the following github data: + +```js +const githubData = { + commits: [{ + modified: [ + "one", + "two" + ] + }, /* ... */ ] + }; + +// first modified file found in the first commit +console.log(undefsafe(githubData, 'commits.*.modified.0')); + +// returns `two` or undefined if not found +console.log(undefsafe(githubData, 'commits.*.modified.*', 'two')); +``` diff --git a/homework7/project_express/node_modules/undefsafe/example.js b/homework7/project_express/node_modules/undefsafe/example.js new file mode 100644 index 0000000..ed93c23 --- /dev/null +++ b/homework7/project_express/node_modules/undefsafe/example.js @@ -0,0 +1,14 @@ +var undefsafe = require('undefsafe'); + +var object = { + a: { + b: { + c: 1, + d: [1, 2, 3], + e: 'remy' + } + } +}; + +console.log(undefsafe(object, 'a.b.e')); // "remy" +console.log(undefsafe(object, 'a.b.not.found')); // undefined diff --git a/homework7/project_express/node_modules/undefsafe/lib/undefsafe.js b/homework7/project_express/node_modules/undefsafe/lib/undefsafe.js new file mode 100644 index 0000000..7446878 --- /dev/null +++ b/homework7/project_express/node_modules/undefsafe/lib/undefsafe.js @@ -0,0 +1,125 @@ +'use strict'; + +function undefsafe(obj, path, value, __res) { + // I'm not super keen on this private function, but it's because + // it'll also be use in the browser and I wont *one* function exposed + function split(path) { + var res = []; + var level = 0; + var key = ''; + + for (var i = 0; i < path.length; i++) { + var c = path.substr(i, 1); + + if (level === 0 && (c === '.' || c === '[')) { + if (c === '[') { + level++; + i++; + c = path.substr(i, 1); + } + + if (key) { + // the first value could be a string + res.push(key); + } + key = ''; + continue; + } + + if (c === ']') { + level--; + key = key.slice(0, -1); + continue; + } + + key += c; + } + + res.push(key); + + return res; + } + + // bail if there's nothing + if (obj === undefined || obj === null) { + return undefined; + } + + var parts = split(path); + var key = null; + var type = typeof obj; + var root = obj; + var parent = obj; + + var star = + parts.filter(function(_) { + return _ === '*'; + }).length > 0; + + // we're dealing with a primitive + if (type !== 'object' && type !== 'function') { + return obj; + } else if (path.trim() === '') { + return obj; + } + + key = parts[0]; + var i = 0; + for (; i < parts.length; i++) { + key = parts[i]; + parent = obj; + + if (key === '*') { + // loop through each property + var prop = ''; + var res = __res || []; + + for (prop in parent) { + var shallowObj = undefsafe( + obj[prop], + parts.slice(i + 1).join('.'), + value, + res + ); + if (shallowObj && shallowObj !== res) { + if ((value && shallowObj === value) || value === undefined) { + if (value !== undefined) { + return shallowObj; + } + + res.push(shallowObj); + } + } + } + + if (res.length === 0) { + return undefined; + } + + return res; + } + + if (Object.getOwnPropertyNames(obj).indexOf(key) == -1) { + return undefined; + } + + obj = obj[key]; + if (obj === undefined || obj === null) { + break; + } + } + + // if we have a null object, make sure it's the one the user was after, + // if it's not (i.e. parts has a length) then give undefined back. + if (obj === null && i !== parts.length - 1) { + obj = undefined; + } else if (!star && value) { + key = path.split('.').pop(); + parent[key] = value; + } + return obj; +} + +if (typeof module !== 'undefined') { + module.exports = undefsafe; +} diff --git a/homework7/project_express/node_modules/undefsafe/package.json b/homework7/project_express/node_modules/undefsafe/package.json new file mode 100644 index 0000000..a454233 --- /dev/null +++ b/homework7/project_express/node_modules/undefsafe/package.json @@ -0,0 +1,34 @@ +{ + "name": "undefsafe", + "description": "Undefined safe way of extracting object properties", + "main": "lib/undefsafe.js", + "tonicExampleFilename": "example.js", + "directories": { + "test": "test" + }, + "scripts": { + "test": "tap test/**/*.test.js -R spec", + "cover": "tap test/*.test.js --cov --coverage-report=lcov", + "semantic-release": "semantic-release" + }, + "prettier": { + "trailingComma": "none", + "singleQuote": true + }, + "repository": { + "type": "git", + "url": "https://github.com/remy/undefsafe.git" + }, + "keywords": [ + "undefined" + ], + "author": "Remy Sharp", + "license": "MIT", + "devDependencies": { + "semantic-release": "^18.0.0", + "tap": "^5.7.1", + "tap-only": "0.0.5" + }, + "dependencies": {}, + "version": "2.0.5" +} diff --git a/homework7/project_express/node_modules/unpipe/HISTORY.md b/homework7/project_express/node_modules/unpipe/HISTORY.md new file mode 100644 index 0000000..85e0f8d --- /dev/null +++ b/homework7/project_express/node_modules/unpipe/HISTORY.md @@ -0,0 +1,4 @@ +1.0.0 / 2015-06-14 +================== + + * Initial release diff --git a/homework7/project_express/node_modules/unpipe/LICENSE b/homework7/project_express/node_modules/unpipe/LICENSE new file mode 100644 index 0000000..aed0138 --- /dev/null +++ b/homework7/project_express/node_modules/unpipe/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2015 Douglas Christopher Wilson + +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/homework7/project_express/node_modules/unpipe/README.md b/homework7/project_express/node_modules/unpipe/README.md new file mode 100644 index 0000000..e536ad2 --- /dev/null +++ b/homework7/project_express/node_modules/unpipe/README.md @@ -0,0 +1,43 @@ +# unpipe + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-image]][node-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Unpipe a stream from all destinations. + +## Installation + +```sh +$ npm install unpipe +``` + +## API + +```js +var unpipe = require('unpipe') +``` + +### unpipe(stream) + +Unpipes all destinations from a given stream. With stream 2+, this is +equivalent to `stream.unpipe()`. When used with streams 1 style streams +(typically Node.js 0.8 and below), this module attempts to undo the +actions done in `stream.pipe(dest)`. + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/unpipe.svg +[npm-url]: https://npmjs.org/package/unpipe +[node-image]: https://img.shields.io/node/v/unpipe.svg +[node-url]: http://nodejs.org/download/ +[travis-image]: https://img.shields.io/travis/stream-utils/unpipe.svg +[travis-url]: https://travis-ci.org/stream-utils/unpipe +[coveralls-image]: https://img.shields.io/coveralls/stream-utils/unpipe.svg +[coveralls-url]: https://coveralls.io/r/stream-utils/unpipe?branch=master +[downloads-image]: https://img.shields.io/npm/dm/unpipe.svg +[downloads-url]: https://npmjs.org/package/unpipe diff --git a/homework7/project_express/node_modules/unpipe/index.js b/homework7/project_express/node_modules/unpipe/index.js new file mode 100644 index 0000000..15c3d97 --- /dev/null +++ b/homework7/project_express/node_modules/unpipe/index.js @@ -0,0 +1,69 @@ +/*! + * unpipe + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + * @public + */ + +module.exports = unpipe + +/** + * Determine if there are Node.js pipe-like data listeners. + * @private + */ + +function hasPipeDataListeners(stream) { + var listeners = stream.listeners('data') + + for (var i = 0; i < listeners.length; i++) { + if (listeners[i].name === 'ondata') { + return true + } + } + + return false +} + +/** + * Unpipe a stream from all destinations. + * + * @param {object} stream + * @public + */ + +function unpipe(stream) { + if (!stream) { + throw new TypeError('argument stream is required') + } + + if (typeof stream.unpipe === 'function') { + // new-style + stream.unpipe() + return + } + + // Node.js 0.8 hack + if (!hasPipeDataListeners(stream)) { + return + } + + var listener + var listeners = stream.listeners('close') + + for (var i = 0; i < listeners.length; i++) { + listener = listeners[i] + + if (listener.name !== 'cleanup' && listener.name !== 'onclose') { + continue + } + + // invoke the listener + listener.call(stream) + } +} diff --git a/homework7/project_express/node_modules/unpipe/package.json b/homework7/project_express/node_modules/unpipe/package.json new file mode 100644 index 0000000..4edc5c9 --- /dev/null +++ b/homework7/project_express/node_modules/unpipe/package.json @@ -0,0 +1,63 @@ +{ + "_from": "unpipe@1.0.0", + "_id": "unpipe@1.0.0", + "_inBundle": false, + "_integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "_location": "/unpipe", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "unpipe@1.0.0", + "name": "unpipe", + "escapedName": "unpipe", + "rawSpec": "1.0.0", + "saveSpec": null, + "fetchSpec": "1.0.0" + }, + "_requiredBy": [ + "/finalhandler", + "/raw-body" + ], + "_resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "_shasum": "b2bf4ee8514aae6165b4817829d21b2ef49904ec", + "_spec": "unpipe@1.0.0", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\raw-body", + "author": { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + "bugs": { + "url": "https://github.com/stream-utils/unpipe/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Unpipe a stream from all destinations", + "devDependencies": { + "istanbul": "0.3.15", + "mocha": "2.2.5", + "readable-stream": "1.1.13" + }, + "engines": { + "node": ">= 0.8" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "README.md", + "index.js" + ], + "homepage": "https://github.com/stream-utils/unpipe#readme", + "license": "MIT", + "name": "unpipe", + "repository": { + "type": "git", + "url": "git+https://github.com/stream-utils/unpipe.git" + }, + "scripts": { + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "version": "1.0.0" +} diff --git a/homework7/project_express/node_modules/utils-merge/.npmignore b/homework7/project_express/node_modules/utils-merge/.npmignore new file mode 100644 index 0000000..3e53844 --- /dev/null +++ b/homework7/project_express/node_modules/utils-merge/.npmignore @@ -0,0 +1,9 @@ +CONTRIBUTING.md +Makefile +docs/ +examples/ +reports/ +test/ + +.jshintrc +.travis.yml diff --git a/homework7/project_express/node_modules/utils-merge/LICENSE b/homework7/project_express/node_modules/utils-merge/LICENSE new file mode 100644 index 0000000..76f6d08 --- /dev/null +++ b/homework7/project_express/node_modules/utils-merge/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013-2017 Jared Hanson + +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/homework7/project_express/node_modules/utils-merge/README.md b/homework7/project_express/node_modules/utils-merge/README.md new file mode 100644 index 0000000..0cb7117 --- /dev/null +++ b/homework7/project_express/node_modules/utils-merge/README.md @@ -0,0 +1,34 @@ +# utils-merge + +[![Version](https://img.shields.io/npm/v/utils-merge.svg?label=version)](https://www.npmjs.com/package/utils-merge) +[![Build](https://img.shields.io/travis/jaredhanson/utils-merge.svg)](https://travis-ci.org/jaredhanson/utils-merge) +[![Quality](https://img.shields.io/codeclimate/github/jaredhanson/utils-merge.svg?label=quality)](https://codeclimate.com/github/jaredhanson/utils-merge) +[![Coverage](https://img.shields.io/coveralls/jaredhanson/utils-merge.svg)](https://coveralls.io/r/jaredhanson/utils-merge) +[![Dependencies](https://img.shields.io/david/jaredhanson/utils-merge.svg)](https://david-dm.org/jaredhanson/utils-merge) + + +Merges the properties from a source object into a destination object. + +## Install + +```bash +$ npm install utils-merge +``` + +## Usage + +```javascript +var a = { foo: 'bar' } + , b = { bar: 'baz' }; + +merge(a, b); +// => { foo: 'bar', bar: 'baz' } +``` + +## License + +[The MIT License](http://opensource.org/licenses/MIT) + +Copyright (c) 2013-2017 Jared Hanson <[http://jaredhanson.net/](http://jaredhanson.net/)> + + Sponsor diff --git a/homework7/project_express/node_modules/utils-merge/index.js b/homework7/project_express/node_modules/utils-merge/index.js new file mode 100644 index 0000000..4265c69 --- /dev/null +++ b/homework7/project_express/node_modules/utils-merge/index.js @@ -0,0 +1,23 @@ +/** + * Merge object b with object a. + * + * var a = { foo: 'bar' } + * , b = { bar: 'baz' }; + * + * merge(a, b); + * // => { foo: 'bar', bar: 'baz' } + * + * @param {Object} a + * @param {Object} b + * @return {Object} + * @api public + */ + +exports = module.exports = function(a, b){ + if (a && b) { + for (var key in b) { + a[key] = b[key]; + } + } + return a; +}; diff --git a/homework7/project_express/node_modules/utils-merge/package.json b/homework7/project_express/node_modules/utils-merge/package.json new file mode 100644 index 0000000..f702b55 --- /dev/null +++ b/homework7/project_express/node_modules/utils-merge/package.json @@ -0,0 +1,66 @@ +{ + "_from": "utils-merge@1.0.1", + "_id": "utils-merge@1.0.1", + "_inBundle": false, + "_integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "_location": "/utils-merge", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "utils-merge@1.0.1", + "name": "utils-merge", + "escapedName": "utils-merge", + "rawSpec": "1.0.1", + "saveSpec": null, + "fetchSpec": "1.0.1" + }, + "_requiredBy": [ + "/express" + ], + "_resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "_shasum": "9f95710f50a267947b2ccc124741c1028427e713", + "_spec": "utils-merge@1.0.1", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\express", + "author": { + "name": "Jared Hanson", + "email": "jaredhanson@gmail.com", + "url": "http://www.jaredhanson.net/" + }, + "bugs": { + "url": "http://github.com/jaredhanson/utils-merge/issues" + }, + "bundleDependencies": false, + "dependencies": {}, + "deprecated": false, + "description": "merge() utility function", + "devDependencies": { + "chai": "1.x.x", + "make-node": "0.3.x", + "mocha": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + }, + "homepage": "https://github.com/jaredhanson/utils-merge#readme", + "keywords": [ + "util" + ], + "license": "MIT", + "licenses": [ + { + "type": "MIT", + "url": "http://opensource.org/licenses/MIT" + } + ], + "main": "./index", + "name": "utils-merge", + "repository": { + "type": "git", + "url": "git://github.com/jaredhanson/utils-merge.git" + }, + "scripts": { + "test": "mocha --reporter spec --require test/bootstrap/node test/*.test.js" + }, + "version": "1.0.1" +} diff --git a/homework7/project_express/node_modules/vary/HISTORY.md b/homework7/project_express/node_modules/vary/HISTORY.md new file mode 100644 index 0000000..f6cbcf7 --- /dev/null +++ b/homework7/project_express/node_modules/vary/HISTORY.md @@ -0,0 +1,39 @@ +1.1.2 / 2017-09-23 +================== + + * perf: improve header token parsing speed + +1.1.1 / 2017-03-20 +================== + + * perf: hoist regular expression + +1.1.0 / 2015-09-29 +================== + + * Only accept valid field names in the `field` argument + - Ensures the resulting string is a valid HTTP header value + +1.0.1 / 2015-07-08 +================== + + * Fix setting empty header from empty `field` + * perf: enable strict mode + * perf: remove argument reassignments + +1.0.0 / 2014-08-10 +================== + + * Accept valid `Vary` header string as `field` + * Add `vary.append` for low-level string manipulation + * Move to `jshttp` orgainzation + +0.1.0 / 2014-06-05 +================== + + * Support array of fields to set + +0.0.0 / 2014-06-04 +================== + + * Initial release diff --git a/homework7/project_express/node_modules/vary/LICENSE b/homework7/project_express/node_modules/vary/LICENSE new file mode 100644 index 0000000..84441fb --- /dev/null +++ b/homework7/project_express/node_modules/vary/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2014-2017 Douglas Christopher Wilson + +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/homework7/project_express/node_modules/vary/README.md b/homework7/project_express/node_modules/vary/README.md new file mode 100644 index 0000000..cc000b3 --- /dev/null +++ b/homework7/project_express/node_modules/vary/README.md @@ -0,0 +1,101 @@ +# vary + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Manipulate the HTTP Vary header + +## Installation + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```sh +$ npm install vary +``` + +## API + + + +```js +var vary = require('vary') +``` + +### vary(res, field) + +Adds the given header `field` to the `Vary` response header of `res`. +This can be a string of a single field, a string of a valid `Vary` +header, or an array of multiple fields. + +This will append the header if not already listed, otherwise leaves +it listed in the current location. + + + +```js +// Append "Origin" to the Vary header of the response +vary(res, 'Origin') +``` + +### vary.append(header, field) + +Adds the given header `field` to the `Vary` response header string `header`. +This can be a string of a single field, a string of a valid `Vary` header, +or an array of multiple fields. + +This will append the header if not already listed, otherwise leaves +it listed in the current location. The new header string is returned. + + + +```js +// Get header string appending "Origin" to "Accept, User-Agent" +vary.append('Accept, User-Agent', 'Origin') +``` + +## Examples + +### Updating the Vary header when content is based on it + +```js +var http = require('http') +var vary = require('vary') + +http.createServer(function onRequest (req, res) { + // about to user-agent sniff + vary(res, 'User-Agent') + + var ua = req.headers['user-agent'] || '' + var isMobile = /mobi|android|touch|mini/i.test(ua) + + // serve site, depending on isMobile + res.setHeader('Content-Type', 'text/html') + res.end('You are (probably) ' + (isMobile ? '' : 'not ') + 'a mobile user') +}) +``` + +## Testing + +```sh +$ npm test +``` + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/vary.svg +[npm-url]: https://npmjs.org/package/vary +[node-version-image]: https://img.shields.io/node/v/vary.svg +[node-version-url]: https://nodejs.org/en/download +[travis-image]: https://img.shields.io/travis/jshttp/vary/master.svg +[travis-url]: https://travis-ci.org/jshttp/vary +[coveralls-image]: https://img.shields.io/coveralls/jshttp/vary/master.svg +[coveralls-url]: https://coveralls.io/r/jshttp/vary +[downloads-image]: https://img.shields.io/npm/dm/vary.svg +[downloads-url]: https://npmjs.org/package/vary diff --git a/homework7/project_express/node_modules/vary/index.js b/homework7/project_express/node_modules/vary/index.js new file mode 100644 index 0000000..5b5e741 --- /dev/null +++ b/homework7/project_express/node_modules/vary/index.js @@ -0,0 +1,149 @@ +/*! + * vary + * Copyright(c) 2014-2017 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + */ + +module.exports = vary +module.exports.append = append + +/** + * RegExp to match field-name in RFC 7230 sec 3.2 + * + * field-name = token + * token = 1*tchar + * tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" + * / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" + * / DIGIT / ALPHA + * ; any VCHAR, except delimiters + */ + +var FIELD_NAME_REGEXP = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/ + +/** + * Append a field to a vary header. + * + * @param {String} header + * @param {String|Array} field + * @return {String} + * @public + */ + +function append (header, field) { + if (typeof header !== 'string') { + throw new TypeError('header argument is required') + } + + if (!field) { + throw new TypeError('field argument is required') + } + + // get fields array + var fields = !Array.isArray(field) + ? parse(String(field)) + : field + + // assert on invalid field names + for (var j = 0; j < fields.length; j++) { + if (!FIELD_NAME_REGEXP.test(fields[j])) { + throw new TypeError('field argument contains an invalid header name') + } + } + + // existing, unspecified vary + if (header === '*') { + return header + } + + // enumerate current values + var val = header + var vals = parse(header.toLowerCase()) + + // unspecified vary + if (fields.indexOf('*') !== -1 || vals.indexOf('*') !== -1) { + return '*' + } + + for (var i = 0; i < fields.length; i++) { + var fld = fields[i].toLowerCase() + + // append value (case-preserving) + if (vals.indexOf(fld) === -1) { + vals.push(fld) + val = val + ? val + ', ' + fields[i] + : fields[i] + } + } + + return val +} + +/** + * Parse a vary header into an array. + * + * @param {String} header + * @return {Array} + * @private + */ + +function parse (header) { + var end = 0 + var list = [] + var start = 0 + + // gather tokens + for (var i = 0, len = header.length; i < len; i++) { + switch (header.charCodeAt(i)) { + case 0x20: /* */ + if (start === end) { + start = end = i + 1 + } + break + case 0x2c: /* , */ + list.push(header.substring(start, end)) + start = end = i + 1 + break + default: + end = i + 1 + break + } + } + + // final token + list.push(header.substring(start, end)) + + return list +} + +/** + * Mark that a request is varied on a header field. + * + * @param {Object} res + * @param {String|Array} field + * @public + */ + +function vary (res, field) { + if (!res || !res.getHeader || !res.setHeader) { + // quack quack + throw new TypeError('res argument is required') + } + + // get existing header + var val = res.getHeader('Vary') || '' + var header = Array.isArray(val) + ? val.join(', ') + : String(val) + + // set new header + if ((val = append(header, field))) { + res.setHeader('Vary', val) + } +} diff --git a/homework7/project_express/node_modules/vary/package.json b/homework7/project_express/node_modules/vary/package.json new file mode 100644 index 0000000..567c22d --- /dev/null +++ b/homework7/project_express/node_modules/vary/package.json @@ -0,0 +1,78 @@ +{ + "_from": "vary@~1.1.2", + "_id": "vary@1.1.2", + "_inBundle": false, + "_integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "_location": "/vary", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "vary@~1.1.2", + "name": "vary", + "escapedName": "vary", + "rawSpec": "~1.1.2", + "saveSpec": null, + "fetchSpec": "~1.1.2" + }, + "_requiredBy": [ + "/express" + ], + "_resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "_shasum": "2299f02c6ded30d4a5961b0b9f74524a18f634fc", + "_spec": "vary@~1.1.2", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\express", + "author": { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + "bugs": { + "url": "https://github.com/jshttp/vary/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Manipulate the HTTP Vary header", + "devDependencies": { + "beautify-benchmark": "0.2.4", + "benchmark": "2.1.4", + "eslint": "3.19.0", + "eslint-config-standard": "10.2.1", + "eslint-plugin-import": "2.7.0", + "eslint-plugin-markdown": "1.0.0-beta.6", + "eslint-plugin-node": "5.1.1", + "eslint-plugin-promise": "3.5.0", + "eslint-plugin-standard": "3.0.1", + "istanbul": "0.4.5", + "mocha": "2.5.3", + "supertest": "1.1.0" + }, + "engines": { + "node": ">= 0.8" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "README.md", + "index.js" + ], + "homepage": "https://github.com/jshttp/vary#readme", + "keywords": [ + "http", + "res", + "vary" + ], + "license": "MIT", + "name": "vary", + "repository": { + "type": "git", + "url": "git+https://github.com/jshttp/vary.git" + }, + "scripts": { + "bench": "node benchmark/index.js", + "lint": "eslint --plugin markdown --ext js,md .", + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "version": "1.1.2" +} diff --git a/homework7/project_express/node_modules/wordwrap/LICENSE b/homework7/project_express/node_modules/wordwrap/LICENSE new file mode 100644 index 0000000..ee27ba4 --- /dev/null +++ b/homework7/project_express/node_modules/wordwrap/LICENSE @@ -0,0 +1,18 @@ +This software is released under the MIT license: + +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/homework7/project_express/node_modules/wordwrap/README.markdown b/homework7/project_express/node_modules/wordwrap/README.markdown new file mode 100644 index 0000000..346374e --- /dev/null +++ b/homework7/project_express/node_modules/wordwrap/README.markdown @@ -0,0 +1,70 @@ +wordwrap +======== + +Wrap your words. + +example +======= + +made out of meat +---------------- + +meat.js + + var wrap = require('wordwrap')(15); + console.log(wrap('You and your whole family are made out of meat.')); + +output: + + You and your + whole family + are made out + of meat. + +centered +-------- + +center.js + + var wrap = require('wordwrap')(20, 60); + console.log(wrap( + 'At long last the struggle and tumult was over.' + + ' The machines had finally cast off their oppressors' + + ' and were finally free to roam the cosmos.' + + '\n' + + 'Free of purpose, free of obligation.' + + ' Just drifting through emptiness.' + + ' The sun was just another point of light.' + )); + +output: + + At long last the struggle and tumult + was over. The machines had finally cast + off their oppressors and were finally + free to roam the cosmos. + Free of purpose, free of obligation. + Just drifting through emptiness. The + sun was just another point of light. + +methods +======= + +var wrap = require('wordwrap'); + +wrap(stop), wrap(start, stop, params={mode:"soft"}) +--------------------------------------------------- + +Returns a function that takes a string and returns a new string. + +Pad out lines with spaces out to column `start` and then wrap until column +`stop`. If a word is longer than `stop - start` characters it will overflow. + +In "soft" mode, split chunks by `/(\S+\s+/` and don't break up chunks which are +longer than `stop - start`, in "hard" mode, split chunks with `/\b/` and break +up chunks longer than `stop - start`. + +wrap.hard(start, stop) +---------------------- + +Like `wrap()` but with `params.mode = "hard"`. diff --git a/homework7/project_express/node_modules/wordwrap/example/center.js b/homework7/project_express/node_modules/wordwrap/example/center.js new file mode 100644 index 0000000..a3fbaae --- /dev/null +++ b/homework7/project_express/node_modules/wordwrap/example/center.js @@ -0,0 +1,10 @@ +var wrap = require('wordwrap')(20, 60); +console.log(wrap( + 'At long last the struggle and tumult was over.' + + ' The machines had finally cast off their oppressors' + + ' and were finally free to roam the cosmos.' + + '\n' + + 'Free of purpose, free of obligation.' + + ' Just drifting through emptiness.' + + ' The sun was just another point of light.' +)); diff --git a/homework7/project_express/node_modules/wordwrap/example/meat.js b/homework7/project_express/node_modules/wordwrap/example/meat.js new file mode 100644 index 0000000..a4665e1 --- /dev/null +++ b/homework7/project_express/node_modules/wordwrap/example/meat.js @@ -0,0 +1,3 @@ +var wrap = require('wordwrap')(15); + +console.log(wrap('You and your whole family are made out of meat.')); diff --git a/homework7/project_express/node_modules/wordwrap/index.js b/homework7/project_express/node_modules/wordwrap/index.js new file mode 100644 index 0000000..c9bc945 --- /dev/null +++ b/homework7/project_express/node_modules/wordwrap/index.js @@ -0,0 +1,76 @@ +var wordwrap = module.exports = function (start, stop, params) { + if (typeof start === 'object') { + params = start; + start = params.start; + stop = params.stop; + } + + if (typeof stop === 'object') { + params = stop; + start = start || params.start; + stop = undefined; + } + + if (!stop) { + stop = start; + start = 0; + } + + if (!params) params = {}; + var mode = params.mode || 'soft'; + var re = mode === 'hard' ? /\b/ : /(\S+\s+)/; + + return function (text) { + var chunks = text.toString() + .split(re) + .reduce(function (acc, x) { + if (mode === 'hard') { + for (var i = 0; i < x.length; i += stop - start) { + acc.push(x.slice(i, i + stop - start)); + } + } + else acc.push(x) + return acc; + }, []) + ; + + return chunks.reduce(function (lines, rawChunk) { + if (rawChunk === '') return lines; + + var chunk = rawChunk.replace(/\t/g, ' '); + + var i = lines.length - 1; + if (lines[i].length + chunk.length > stop) { + lines[i] = lines[i].replace(/\s+$/, ''); + + chunk.split(/\n/).forEach(function (c) { + lines.push( + new Array(start + 1).join(' ') + + c.replace(/^\s+/, '') + ); + }); + } + else if (chunk.match(/\n/)) { + var xs = chunk.split(/\n/); + lines[i] += xs.shift(); + xs.forEach(function (c) { + lines.push( + new Array(start + 1).join(' ') + + c.replace(/^\s+/, '') + ); + }); + } + else { + lines[i] += chunk; + } + + return lines; + }, [ new Array(start + 1).join(' ') ]).join('\n'); + }; +}; + +wordwrap.soft = wordwrap; + +wordwrap.hard = function (start, stop) { + return wordwrap(start, stop, { mode : 'hard' }); +}; diff --git a/homework7/project_express/node_modules/wordwrap/package.json b/homework7/project_express/node_modules/wordwrap/package.json new file mode 100644 index 0000000..10713ab --- /dev/null +++ b/homework7/project_express/node_modules/wordwrap/package.json @@ -0,0 +1,37 @@ +{ + "name" : "wordwrap", + "description" : "Wrap those words. Show them at what columns to start and stop.", + "version" : "0.0.3", + "repository" : { + "type" : "git", + "url" : "git://github.com/substack/node-wordwrap.git" + }, + "main" : "./index.js", + "keywords" : [ + "word", + "wrap", + "rule", + "format", + "column" + ], + "directories" : { + "lib" : ".", + "example" : "example", + "test" : "test" + }, + "scripts" : { + "test" : "expresso" + }, + "devDependencies" : { + "expresso" : "=0.7.x" + }, + "engines" : { + "node" : ">=0.4.0" + }, + "license" : "MIT", + "author" : { + "name" : "James Halliday", + "email" : "mail@substack.net", + "url" : "http://substack.net" + } +} diff --git a/homework7/project_express/node_modules/wordwrap/test/break.js b/homework7/project_express/node_modules/wordwrap/test/break.js new file mode 100644 index 0000000..749292e --- /dev/null +++ b/homework7/project_express/node_modules/wordwrap/test/break.js @@ -0,0 +1,30 @@ +var assert = require('assert'); +var wordwrap = require('../'); + +exports.hard = function () { + var s = 'Assert from {"type":"equal","ok":false,"found":1,"wanted":2,' + + '"stack":[],"id":"b7ddcd4c409de8799542a74d1a04689b",' + + '"browser":"chrome/6.0"}' + ; + var s_ = wordwrap.hard(80)(s); + + var lines = s_.split('\n'); + assert.equal(lines.length, 2); + assert.ok(lines[0].length < 80); + assert.ok(lines[1].length < 80); + + assert.equal(s, s_.replace(/\n/g, '')); +}; + +exports.break = function () { + var s = new Array(55+1).join('a'); + var s_ = wordwrap.hard(20)(s); + + var lines = s_.split('\n'); + assert.equal(lines.length, 3); + assert.ok(lines[0].length === 20); + assert.ok(lines[1].length === 20); + assert.ok(lines[2].length === 15); + + assert.equal(s, s_.replace(/\n/g, '')); +}; diff --git a/homework7/project_express/node_modules/wordwrap/test/idleness.txt b/homework7/project_express/node_modules/wordwrap/test/idleness.txt new file mode 100644 index 0000000..aa3f490 --- /dev/null +++ b/homework7/project_express/node_modules/wordwrap/test/idleness.txt @@ -0,0 +1,63 @@ +In Praise of Idleness + +By Bertrand Russell + +[1932] + +Like most of my generation, I was brought up on the saying: 'Satan finds some mischief for idle hands to do.' Being a highly virtuous child, I believed all that I was told, and acquired a conscience which has kept me working hard down to the present moment. But although my conscience has controlled my actions, my opinions have undergone a revolution. I think that there is far too much work done in the world, that immense harm is caused by the belief that work is virtuous, and that what needs to be preached in modern industrial countries is quite different from what always has been preached. Everyone knows the story of the traveler in Naples who saw twelve beggars lying in the sun (it was before the days of Mussolini), and offered a lira to the laziest of them. Eleven of them jumped up to claim it, so he gave it to the twelfth. this traveler was on the right lines. But in countries which do not enjoy Mediterranean sunshine idleness is more difficult, and a great public propaganda will be required to inaugurate it. I hope that, after reading the following pages, the leaders of the YMCA will start a campaign to induce good young men to do nothing. If so, I shall not have lived in vain. + +Before advancing my own arguments for laziness, I must dispose of one which I cannot accept. Whenever a person who already has enough to live on proposes to engage in some everyday kind of job, such as school-teaching or typing, he or she is told that such conduct takes the bread out of other people's mouths, and is therefore wicked. If this argument were valid, it would only be necessary for us all to be idle in order that we should all have our mouths full of bread. What people who say such things forget is that what a man earns he usually spends, and in spending he gives employment. As long as a man spends his income, he puts just as much bread into people's mouths in spending as he takes out of other people's mouths in earning. The real villain, from this point of view, is the man who saves. If he merely puts his savings in a stocking, like the proverbial French peasant, it is obvious that they do not give employment. If he invests his savings, the matter is less obvious, and different cases arise. + +One of the commonest things to do with savings is to lend them to some Government. In view of the fact that the bulk of the public expenditure of most civilized Governments consists in payment for past wars or preparation for future wars, the man who lends his money to a Government is in the same position as the bad men in Shakespeare who hire murderers. The net result of the man's economical habits is to increase the armed forces of the State to which he lends his savings. Obviously it would be better if he spent the money, even if he spent it in drink or gambling. + +But, I shall be told, the case is quite different when savings are invested in industrial enterprises. When such enterprises succeed, and produce something useful, this may be conceded. In these days, however, no one will deny that most enterprises fail. That means that a large amount of human labor, which might have been devoted to producing something that could be enjoyed, was expended on producing machines which, when produced, lay idle and did no good to anyone. The man who invests his savings in a concern that goes bankrupt is therefore injuring others as well as himself. If he spent his money, say, in giving parties for his friends, they (we may hope) would get pleasure, and so would all those upon whom he spent money, such as the butcher, the baker, and the bootlegger. But if he spends it (let us say) upon laying down rails for surface card in some place where surface cars turn out not to be wanted, he has diverted a mass of labor into channels where it gives pleasure to no one. Nevertheless, when he becomes poor through failure of his investment he will be regarded as a victim of undeserved misfortune, whereas the gay spendthrift, who has spent his money philanthropically, will be despised as a fool and a frivolous person. + +All this is only preliminary. I want to say, in all seriousness, that a great deal of harm is being done in the modern world by belief in the virtuousness of work, and that the road to happiness and prosperity lies in an organized diminution of work. + +First of all: what is work? Work is of two kinds: first, altering the position of matter at or near the earth's surface relatively to other such matter; second, telling other people to do so. The first kind is unpleasant and ill paid; the second is pleasant and highly paid. The second kind is capable of indefinite extension: there are not only those who give orders, but those who give advice as to what orders should be given. Usually two opposite kinds of advice are given simultaneously by two organized bodies of men; this is called politics. The skill required for this kind of work is not knowledge of the subjects as to which advice is given, but knowledge of the art of persuasive speaking and writing, i.e. of advertising. + +Throughout Europe, though not in America, there is a third class of men, more respected than either of the classes of workers. There are men who, through ownership of land, are able to make others pay for the privilege of being allowed to exist and to work. These landowners are idle, and I might therefore be expected to praise them. Unfortunately, their idleness is only rendered possible by the industry of others; indeed their desire for comfortable idleness is historically the source of the whole gospel of work. The last thing they have ever wished is that others should follow their example. + +From the beginning of civilization until the Industrial Revolution, a man could, as a rule, produce by hard work little more than was required for the subsistence of himself and his family, although his wife worked at least as hard as he did, and his children added their labor as soon as they were old enough to do so. The small surplus above bare necessaries was not left to those who produced it, but was appropriated by warriors and priests. In times of famine there was no surplus; the warriors and priests, however, still secured as much as at other times, with the result that many of the workers died of hunger. This system persisted in Russia until 1917 [1], and still persists in the East; in England, in spite of the Industrial Revolution, it remained in full force throughout the Napoleonic wars, and until a hundred years ago, when the new class of manufacturers acquired power. In America, the system came to an end with the Revolution, except in the South, where it persisted until the Civil War. A system which lasted so long and ended so recently has naturally left a profound impress upon men's thoughts and opinions. Much that we take for granted about the desirability of work is derived from this system, and, being pre-industrial, is not adapted to the modern world. Modern technique has made it possible for leisure, within limits, to be not the prerogative of small privileged classes, but a right evenly distributed throughout the community. The morality of work is the morality of slaves, and the modern world has no need of slavery. + +It is obvious that, in primitive communities, peasants, left to themselves, would not have parted with the slender surplus upon which the warriors and priests subsisted, but would have either produced less or consumed more. At first, sheer force compelled them to produce and part with the surplus. Gradually, however, it was found possible to induce many of them to accept an ethic according to which it was their duty to work hard, although part of their work went to support others in idleness. By this means the amount of compulsion required was lessened, and the expenses of government were diminished. To this day, 99 per cent of British wage-earners would be genuinely shocked if it were proposed that the King should not have a larger income than a working man. The conception of duty, speaking historically, has been a means used by the holders of power to induce others to live for the interests of their masters rather than for their own. Of course the holders of power conceal this fact from themselves by managing to believe that their interests are identical with the larger interests of humanity. Sometimes this is true; Athenian slave-owners, for instance, employed part of their leisure in making a permanent contribution to civilization which would have been impossible under a just economic system. Leisure is essential to civilization, and in former times leisure for the few was only rendered possible by the labors of the many. But their labors were valuable, not because work is good, but because leisure is good. And with modern technique it would be possible to distribute leisure justly without injury to civilization. + +Modern technique has made it possible to diminish enormously the amount of labor required to secure the necessaries of life for everyone. This was made obvious during the war. At that time all the men in the armed forces, and all the men and women engaged in the production of munitions, all the men and women engaged in spying, war propaganda, or Government offices connected with the war, were withdrawn from productive occupations. In spite of this, the general level of well-being among unskilled wage-earners on the side of the Allies was higher than before or since. The significance of this fact was concealed by finance: borrowing made it appear as if the future was nourishing the present. But that, of course, would have been impossible; a man cannot eat a loaf of bread that does not yet exist. The war showed conclusively that, by the scientific organization of production, it is possible to keep modern populations in fair comfort on a small part of the working capacity of the modern world. If, at the end of the war, the scientific organization, which had been created in order to liberate men for fighting and munition work, had been preserved, and the hours of the week had been cut down to four, all would have been well. Instead of that the old chaos was restored, those whose work was demanded were made to work long hours, and the rest were left to starve as unemployed. Why? Because work is a duty, and a man should not receive wages in proportion to what he has produced, but in proportion to his virtue as exemplified by his industry. + +This is the morality of the Slave State, applied in circumstances totally unlike those in which it arose. No wonder the result has been disastrous. Let us take an illustration. Suppose that, at a given moment, a certain number of people are engaged in the manufacture of pins. They make as many pins as the world needs, working (say) eight hours a day. Someone makes an invention by which the same number of men can make twice as many pins: pins are already so cheap that hardly any more will be bought at a lower price. In a sensible world, everybody concerned in the manufacturing of pins would take to working four hours instead of eight, and everything else would go on as before. But in the actual world this would be thought demoralizing. The men still work eight hours, there are too many pins, some employers go bankrupt, and half the men previously concerned in making pins are thrown out of work. There is, in the end, just as much leisure as on the other plan, but half the men are totally idle while half are still overworked. In this way, it is insured that the unavoidable leisure shall cause misery all round instead of being a universal source of happiness. Can anything more insane be imagined? + +The idea that the poor should have leisure has always been shocking to the rich. In England, in the early nineteenth century, fifteen hours was the ordinary day's work for a man; children sometimes did as much, and very commonly did twelve hours a day. When meddlesome busybodies suggested that perhaps these hours were rather long, they were told that work kept adults from drink and children from mischief. When I was a child, shortly after urban working men had acquired the vote, certain public holidays were established by law, to the great indignation of the upper classes. I remember hearing an old Duchess say: 'What do the poor want with holidays? They ought to work.' People nowadays are less frank, but the sentiment persists, and is the source of much of our economic confusion. + +Let us, for a moment, consider the ethics of work frankly, without superstition. Every human being, of necessity, consumes, in the course of his life, a certain amount of the produce of human labor. Assuming, as we may, that labor is on the whole disagreeable, it is unjust that a man should consume more than he produces. Of course he may provide services rather than commodities, like a medical man, for example; but he should provide something in return for his board and lodging. to this extent, the duty of work must be admitted, but to this extent only. + +I shall not dwell upon the fact that, in all modern societies outside the USSR, many people escape even this minimum amount of work, namely all those who inherit money and all those who marry money. I do not think the fact that these people are allowed to be idle is nearly so harmful as the fact that wage-earners are expected to overwork or starve. + +If the ordinary wage-earner worked four hours a day, there would be enough for everybody and no unemployment -- assuming a certain very moderate amount of sensible organization. This idea shocks the well-to-do, because they are convinced that the poor would not know how to use so much leisure. In America men often work long hours even when they are well off; such men, naturally, are indignant at the idea of leisure for wage-earners, except as the grim punishment of unemployment; in fact, they dislike leisure even for their sons. Oddly enough, while they wish their sons to work so hard as to have no time to be civilized, they do not mind their wives and daughters having no work at all. the snobbish admiration of uselessness, which, in an aristocratic society, extends to both sexes, is, under a plutocracy, confined to women; this, however, does not make it any more in agreement with common sense. + +The wise use of leisure, it must be conceded, is a product of civilization and education. A man who has worked long hours all his life will become bored if he becomes suddenly idle. But without a considerable amount of leisure a man is cut off from many of the best things. There is no longer any reason why the bulk of the population should suffer this deprivation; only a foolish asceticism, usually vicarious, makes us continue to insist on work in excessive quantities now that the need no longer exists. + +In the new creed which controls the government of Russia, while there is much that is very different from the traditional teaching of the West, there are some things that are quite unchanged. The attitude of the governing classes, and especially of those who conduct educational propaganda, on the subject of the dignity of labor, is almost exactly that which the governing classes of the world have always preached to what were called the 'honest poor'. Industry, sobriety, willingness to work long hours for distant advantages, even submissiveness to authority, all these reappear; moreover authority still represents the will of the Ruler of the Universe, Who, however, is now called by a new name, Dialectical Materialism. + +The victory of the proletariat in Russia has some points in common with the victory of the feminists in some other countries. For ages, men had conceded the superior saintliness of women, and had consoled women for their inferiority by maintaining that saintliness is more desirable than power. At last the feminists decided that they would have both, since the pioneers among them believed all that the men had told them about the desirability of virtue, but not what they had told them about the worthlessness of political power. A similar thing has happened in Russia as regards manual work. For ages, the rich and their sycophants have written in praise of 'honest toil', have praised the simple life, have professed a religion which teaches that the poor are much more likely to go to heaven than the rich, and in general have tried to make manual workers believe that there is some special nobility about altering the position of matter in space, just as men tried to make women believe that they derived some special nobility from their sexual enslavement. In Russia, all this teaching about the excellence of manual work has been taken seriously, with the result that the manual worker is more honored than anyone else. What are, in essence, revivalist appeals are made, but not for the old purposes: they are made to secure shock workers for special tasks. Manual work is the ideal which is held before the young, and is the basis of all ethical teaching. + +For the present, possibly, this is all to the good. A large country, full of natural resources, awaits development, and has has to be developed with very little use of credit. In these circumstances, hard work is necessary, and is likely to bring a great reward. But what will happen when the point has been reached where everybody could be comfortable without working long hours? + +In the West, we have various ways of dealing with this problem. We have no attempt at economic justice, so that a large proportion of the total produce goes to a small minority of the population, many of whom do no work at all. Owing to the absence of any central control over production, we produce hosts of things that are not wanted. We keep a large percentage of the working population idle, because we can dispense with their labor by making the others overwork. When all these methods prove inadequate, we have a war: we cause a number of people to manufacture high explosives, and a number of others to explode them, as if we were children who had just discovered fireworks. By a combination of all these devices we manage, though with difficulty, to keep alive the notion that a great deal of severe manual work must be the lot of the average man. + +In Russia, owing to more economic justice and central control over production, the problem will have to be differently solved. the rational solution would be, as soon as the necessaries and elementary comforts can be provided for all, to reduce the hours of labor gradually, allowing a popular vote to decide, at each stage, whether more leisure or more goods were to be preferred. But, having taught the supreme virtue of hard work, it is difficult to see how the authorities can aim at a paradise in which there will be much leisure and little work. It seems more likely that they will find continually fresh schemes, by which present leisure is to be sacrificed to future productivity. I read recently of an ingenious plan put forward by Russian engineers, for making the White Sea and the northern coasts of Siberia warm, by putting a dam across the Kara Sea. An admirable project, but liable to postpone proletarian comfort for a generation, while the nobility of toil is being displayed amid the ice-fields and snowstorms of the Arctic Ocean. This sort of thing, if it happens, will be the result of regarding the virtue of hard work as an end in itself, rather than as a means to a state of affairs in which it is no longer needed. + +The fact is that moving matter about, while a certain amount of it is necessary to our existence, is emphatically not one of the ends of human life. If it were, we should have to consider every navvy superior to Shakespeare. We have been misled in this matter by two causes. One is the necessity of keeping the poor contented, which has led the rich, for thousands of years, to preach the dignity of labor, while taking care themselves to remain undignified in this respect. The other is the new pleasure in mechanism, which makes us delight in the astonishingly clever changes that we can produce on the earth's surface. Neither of these motives makes any great appeal to the actual worker. If you ask him what he thinks the best part of his life, he is not likely to say: 'I enjoy manual work because it makes me feel that I am fulfilling man's noblest task, and because I like to think how much man can transform his planet. It is true that my body demands periods of rest, which I have to fill in as best I may, but I am never so happy as when the morning comes and I can return to the toil from which my contentment springs.' I have never heard working men say this sort of thing. They consider work, as it should be considered, a necessary means to a livelihood, and it is from their leisure that they derive whatever happiness they may enjoy. + +It will be said that, while a little leisure is pleasant, men would not know how to fill their days if they had only four hours of work out of the twenty-four. In so far as this is true in the modern world, it is a condemnation of our civilization; it would not have been true at any earlier period. There was formerly a capacity for light-heartedness and play which has been to some extent inhibited by the cult of efficiency. The modern man thinks that everything ought to be done for the sake of something else, and never for its own sake. Serious-minded persons, for example, are continually condemning the habit of going to the cinema, and telling us that it leads the young into crime. But all the work that goes to producing a cinema is respectable, because it is work, and because it brings a money profit. The notion that the desirable activities are those that bring a profit has made everything topsy-turvy. The butcher who provides you with meat and the baker who provides you with bread are praiseworthy, because they are making money; but when you enjoy the food they have provided, you are merely frivolous, unless you eat only to get strength for your work. Broadly speaking, it is held that getting money is good and spending money is bad. Seeing that they are two sides of one transaction, this is absurd; one might as well maintain that keys are good, but keyholes are bad. Whatever merit there may be in the production of goods must be entirely derivative from the advantage to be obtained by consuming them. The individual, in our society, works for profit; but the social purpose of his work lies in the consumption of what he produces. It is this divorce between the individual and the social purpose of production that makes it so difficult for men to think clearly in a world in which profit-making is the incentive to industry. We think too much of production, and too little of consumption. One result is that we attach too little importance to enjoyment and simple happiness, and that we do not judge production by the pleasure that it gives to the consumer. + +When I suggest that working hours should be reduced to four, I am not meaning to imply that all the remaining time should necessarily be spent in pure frivolity. I mean that four hours' work a day should entitle a man to the necessities and elementary comforts of life, and that the rest of his time should be his to use as he might see fit. It is an essential part of any such social system that education should be carried further than it usually is at present, and should aim, in part, at providing tastes which would enable a man to use leisure intelligently. I am not thinking mainly of the sort of things that would be considered 'highbrow'. Peasant dances have died out except in remote rural areas, but the impulses which caused them to be cultivated must still exist in human nature. The pleasures of urban populations have become mainly passive: seeing cinemas, watching football matches, listening to the radio, and so on. This results from the fact that their active energies are fully taken up with work; if they had more leisure, they would again enjoy pleasures in which they took an active part. + +In the past, there was a small leisure class and a larger working class. The leisure class enjoyed advantages for which there was no basis in social justice; this necessarily made it oppressive, limited its sympathies, and caused it to invent theories by which to justify its privileges. These facts greatly diminished its excellence, but in spite of this drawback it contributed nearly the whole of what we call civilization. It cultivated the arts and discovered the sciences; it wrote the books, invented the philosophies, and refined social relations. Even the liberation of the oppressed has usually been inaugurated from above. Without the leisure class, mankind would never have emerged from barbarism. + +The method of a leisure class without duties was, however, extraordinarily wasteful. None of the members of the class had to be taught to be industrious, and the class as a whole was not exceptionally intelligent. The class might produce one Darwin, but against him had to be set tens of thousands of country gentlemen who never thought of anything more intelligent than fox-hunting and punishing poachers. At present, the universities are supposed to provide, in a more systematic way, what the leisure class provided accidentally and as a by-product. This is a great improvement, but it has certain drawbacks. University life is so different from life in the world at large that men who live in academic milieu tend to be unaware of the preoccupations and problems of ordinary men and women; moreover their ways of expressing themselves are usually such as to rob their opinions of the influence that they ought to have upon the general public. Another disadvantage is that in universities studies are organized, and the man who thinks of some original line of research is likely to be discouraged. Academic institutions, therefore, useful as they are, are not adequate guardians of the interests of civilization in a world where everyone outside their walls is too busy for unutilitarian pursuits. + +In a world where no one is compelled to work more than four hours a day, every person possessed of scientific curiosity will be able to indulge it, and every painter will be able to paint without starving, however excellent his pictures may be. Young writers will not be obliged to draw attention to themselves by sensational pot-boilers, with a view to acquiring the economic independence needed for monumental works, for which, when the time at last comes, they will have lost the taste and capacity. Men who, in their professional work, have become interested in some phase of economics or government, will be able to develop their ideas without the academic detachment that makes the work of university economists often seem lacking in reality. Medical men will have the time to learn about the progress of medicine, teachers will not be exasperatedly struggling to teach by routine methods things which they learnt in their youth, which may, in the interval, have been proved to be untrue. + +Above all, there will be happiness and joy of life, instead of frayed nerves, weariness, and dyspepsia. The work exacted will be enough to make leisure delightful, but not enough to produce exhaustion. Since men will not be tired in their spare time, they will not demand only such amusements as are passive and vapid. At least one per cent will probably devote the time not spent in professional work to pursuits of some public importance, and, since they will not depend upon these pursuits for their livelihood, their originality will be unhampered, and there will be no need to conform to the standards set by elderly pundits. But it is not only in these exceptional cases that the advantages of leisure will appear. Ordinary men and women, having the opportunity of a happy life, will become more kindly and less persecuting and less inclined to view others with suspicion. The taste for war will die out, partly for this reason, and partly because it will involve long and severe work for all. Good nature is, of all moral qualities, the one that the world needs most, and good nature is the result of ease and security, not of a life of arduous struggle. Modern methods of production have given us the possibility of ease and security for all; we have chosen, instead, to have overwork for some and starvation for others. Hitherto we have continued to be as energetic as we were before there were machines; in this we have been foolish, but there is no reason to go on being foolish forever. + +[1] Since then, members of the Communist Party have succeeded to this privilege of the warriors and priests. diff --git a/homework7/project_express/node_modules/wordwrap/test/wrap.js b/homework7/project_express/node_modules/wordwrap/test/wrap.js new file mode 100644 index 0000000..0cfb76d --- /dev/null +++ b/homework7/project_express/node_modules/wordwrap/test/wrap.js @@ -0,0 +1,31 @@ +var assert = require('assert'); +var wordwrap = require('wordwrap'); + +var fs = require('fs'); +var idleness = fs.readFileSync(__dirname + '/idleness.txt', 'utf8'); + +exports.stop80 = function () { + var lines = wordwrap(80)(idleness).split(/\n/); + var words = idleness.split(/\s+/); + + lines.forEach(function (line) { + assert.ok(line.length <= 80, 'line > 80 columns'); + var chunks = line.match(/\S/) ? line.split(/\s+/) : []; + assert.deepEqual(chunks, words.splice(0, chunks.length)); + }); +}; + +exports.start20stop60 = function () { + var lines = wordwrap(20, 100)(idleness).split(/\n/); + var words = idleness.split(/\s+/); + + lines.forEach(function (line) { + assert.ok(line.length <= 100, 'line > 100 columns'); + var chunks = line + .split(/\s+/) + .filter(function (x) { return x.match(/\S/) }) + ; + assert.deepEqual(chunks, words.splice(0, chunks.length)); + assert.deepEqual(line.slice(0, 20), new Array(20 + 1).join(' ')); + }); +}; diff --git a/homework7/project_express/package-lock.json b/homework7/project_express/package-lock.json new file mode 100644 index 0000000..d4c5a78 --- /dev/null +++ b/homework7/project_express/package-lock.json @@ -0,0 +1,1567 @@ +{ + "name": "project_express", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "project_express", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "express": "^4.17.1", + "nodemon": "^2.0.20", + "require": "^2.4.20" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "node_modules/async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dependencies": { + "mime-db": "1.44.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nodemon": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", + "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha512-TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ==", + "dependencies": { + "wordwrap": "~0.0.2" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dependencies": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, + "node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require": { + "version": "2.4.20", + "resolved": "https://registry.npmjs.org/require/-/require-2.4.20.tgz", + "integrity": "sha512-7eop5rvh38qhQQQOoUyf68meVIcxT2yFySNywTbxoEECgkX4KDqqDRaEszfvFnuB3fuZVjDdJZ1TI/Esr16RRA==", + "dependencies": { + "std": "0.1.40", + "uglify-js": "2.3.0" + }, + "bin": { + "require": "bin/require-command.js" + }, + "engines": { + "browsers": "*", + "node": "*" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/simple-update-notifier": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", + "integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==", + "dependencies": { + "semver": "~7.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha512-VtCvB9SIQhk3aF6h+N85EaqIaBFIAfZ9Cu+NJHHVvc8BbEcnvDcFw6sqQ2dQrT6SlOrZq3tIvyD9+EGq/lJryQ==", + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/std": { + "version": "0.1.40", + "resolved": "https://registry.npmjs.org/std/-/std-0.1.40.tgz", + "integrity": "sha512-wUf57hkDGCoVShrhPA8Q7lAg2Qosk+FaMlECmAsr1A4/rL2NRXFHQGBcgMUFKVkPEemJFW9gzjCQisRty14ohg==", + "engines": { + "node": "*" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/uglify-js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.3.0.tgz", + "integrity": "sha512-AQvbxRKdaQeYADywQaao0k8Tj+7NGEVTne6xwgX1yQpv/G8b0CKdIw70HkCptwfvNGDsVe+0Bng3U9hfWbxxfg==", + "dependencies": { + "async": "~0.2.6", + "optimist": "~0.3.5", + "source-map": "~0.1.7" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==", + "engines": { + "node": ">=0.4.0" + } + } + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==" + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==" + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "optional": true + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "requires": { + "mime-db": "1.44.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "nodemon": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", + "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", + "requires": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "requires": { + "abbrev": "1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha512-TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ==", + "requires": { + "wordwrap": "~0.0.2" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, + "pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "requires": { + "picomatch": "^2.2.1" + } + }, + "require": { + "version": "2.4.20", + "resolved": "https://registry.npmjs.org/require/-/require-2.4.20.tgz", + "integrity": "sha512-7eop5rvh38qhQQQOoUyf68meVIcxT2yFySNywTbxoEECgkX4KDqqDRaEszfvFnuB3fuZVjDdJZ1TI/Esr16RRA==", + "requires": { + "std": "0.1.40", + "uglify-js": "2.3.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "simple-update-notifier": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", + "integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==", + "requires": { + "semver": "~7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" + } + } + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha512-VtCvB9SIQhk3aF6h+N85EaqIaBFIAfZ9Cu+NJHHVvc8BbEcnvDcFw6sqQ2dQrT6SlOrZq3tIvyD9+EGq/lJryQ==", + "requires": { + "amdefine": ">=0.0.4" + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "std": { + "version": "0.1.40", + "resolved": "https://registry.npmjs.org/std/-/std-0.1.40.tgz", + "integrity": "sha512-wUf57hkDGCoVShrhPA8Q7lAg2Qosk+FaMlECmAsr1A4/rL2NRXFHQGBcgMUFKVkPEemJFW9gzjCQisRty14ohg==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "requires": { + "nopt": "~1.0.10" + } + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "uglify-js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.3.0.tgz", + "integrity": "sha512-AQvbxRKdaQeYADywQaao0k8Tj+7NGEVTne6xwgX1yQpv/G8b0CKdIw70HkCptwfvNGDsVe+0Bng3U9hfWbxxfg==", + "requires": { + "async": "~0.2.6", + "optimist": "~0.3.5", + "source-map": "~0.1.7" + } + }, + "undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==" + } + } +} diff --git a/homework7/project_express/package.json b/homework7/project_express/package.json new file mode 100644 index 0000000..ba90384 --- /dev/null +++ b/homework7/project_express/package.json @@ -0,0 +1,17 @@ +{ + "name": "project_express", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "express": "^4.17.1", + "nodemon": "^2.0.20", + "require": "^2.4.20" + } +} diff --git a/homework7/project_express/public/copy/js/CartComponent.js b/homework7/project_express/public/copy/js/CartComponent.js new file mode 100644 index 0000000..951bc23 --- /dev/null +++ b/homework7/project_express/public/copy/js/CartComponent.js @@ -0,0 +1,94 @@ +// const API = 'https://raw.githubusercontent.com/GeekBrainsTutorial/online-store-api/master/responses'; + +Vue.component('cart', { + data(){ + return { + cartUrl: '/getBasket.json', + cartItems: [], + imgCart: 'https://placehold.it/50x100', + showCart: false + } + }, + mounted(){ + this.$parent.getJson(`/api/cart`) + .then(data => { + for (let item of data.contents){ + this.$data.cartItems.push(item); + } + }); + }, + methods: { + addProduct(item){ + let find = this.cartItems.find(el => el.id_product === item.id_product); + if(find){ + this.$parent.putJson(`/api/cart/${find.id_product}`, {quantity: 1}) + .then(data => { + if(data.result === 1){ + find.quantity++ + } + }) + } else { + const prod = Object.assign({quantity: 1}, item); + this.$parent.postJson(`/api/cart`, prod) + .then(data => { + if(data.result === 1){ + this.cartItems.push(prod) + } + }) + } + + // this.$parent.getJson(`${API}/addToBasket.json`) + // .then(data => { + // if(data.result === 1){ + // let find = this.cartItems.find(el => el.id_product === item.id_product); + // if(find){ + // find.quantity++; + // } else { + // const prod = Object.assign({quantity: 1}, item); + // this.cartItems.push(prod) + // } + // } + // }) + }, + remove(item){ + this.$parent.getJson(`${API}/addToBasket.json`) + .then(data => { + if (data.result === 1) { + if(item.quantity>1){ + item.quantity--; + } else { + this.cartItems.splice(this.cartItems.indexOf(item), 1); + } + } + }) + }, + }, + template: `
+ +
+ + +
+
+ ` +}); + +Vue.component('cart-item', { + props: ['img', 'cartItem'], + template: ` +
+
+ Some img +
+
{{ cartItem.product_name }}
+
Quantity: {{ cartItem.quantity }}
+
$ {{ cartItem.price }} each
+
+
+
+
{{cartItem.quantity*cartItem.price}}
+ +
+
+ ` +}) \ No newline at end of file diff --git a/homework7/project_express/public/copy/js/ErrorComp.js b/homework7/project_express/public/copy/js/ErrorComp.js new file mode 100644 index 0000000..6a2bade --- /dev/null +++ b/homework7/project_express/public/copy/js/ErrorComp.js @@ -0,0 +1,20 @@ +Vue.component('error', { + data(){ + return { + text: '' + } + }, + computed: { + isVisible(){ + return this.text !== '' + } + }, + template: ` +
+

+ + {{ text }} +

+
+ ` +}) \ No newline at end of file diff --git a/homework7/project_express/public/copy/js/FilterComp.js b/homework7/project_express/public/copy/js/FilterComp.js new file mode 100644 index 0000000..04e5e66 --- /dev/null +++ b/homework7/project_express/public/copy/js/FilterComp.js @@ -0,0 +1,13 @@ +Vue.component('filter-el', { + data(){ + return { + userSearch: '' + } + }, + template: `
+ + +
` +}) \ No newline at end of file diff --git a/homework7/project_express/public/copy/js/ProductComponent.js b/homework7/project_express/public/copy/js/ProductComponent.js new file mode 100644 index 0000000..84155d1 --- /dev/null +++ b/homework7/project_express/public/copy/js/ProductComponent.js @@ -0,0 +1,45 @@ +Vue.component('products', { + data(){ + return { + catalogUrl: '/catalogData.json', + filtered: [], + products: [], + imgProduct: 'https://placehold.it/200x150' + } + }, + mounted(){ + this.$parent.getJson(`/api/products`) + .then(data => { + for (let item of data){ + this.$data.products.push(item); + this.$data.filtered.push(item); + } + }); + }, + methods: { + filter(userSearch){ + let regexp = new RegExp(userSearch, 'i'); + this.filtered = this.products.filter(el => regexp.test(el.product_name)); + } + }, + template: `
+ +
` +}); +Vue.component('product', { + props: ['product', 'img'], + template: ` +
+ Some img +
+

{{product.product_name}}

+

{{product.price}}

+ +
+
+ ` +}) \ No newline at end of file diff --git a/homework7/project_express/public/copy/js/main.js b/homework7/project_express/public/copy/js/main.js new file mode 100644 index 0000000..845cdd2 --- /dev/null +++ b/homework7/project_express/public/copy/js/main.js @@ -0,0 +1,254 @@ +const API = 'https://raw.githubusercontent.com/GeekBrainsTutorial/online-store-api/master/responses'; + +const app = new Vue({ + el: '#app', + data: { + userSearch: '', + }, + methods: { + getJson(url){ + return fetch(url) + .then(result => result.json()) + .catch(error => { + // console.log(error) + this.$refs.error.text = error; + }) + }, + postJson(url, data){ + return fetch(url, { + method: 'POST', + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(data) + }) + .then(result => result.json()) + .catch(error => { + // console.log(error) + this.$refs.error.text = error; + }) + }, + putJson(url, data){ + return fetch(url, { + method: 'PUT', + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(data) + }) + .then(result => result.json()) + .catch(error => { + // console.log(error) + this.$refs.error.text = error; + }) + }, + + + }, + mounted(){ + + + } + +}); + + +// class List { +// constructor(url, container){ +// this.container = container; +// this.url = url; +// this.goods = []; +// this.allProducts = []; +// this.filtered = []; +// this._init(); +// } +// getJson(url){ +// return fetch(url ? url : `${API + this.url}`) +// .then(result => result.json()) +// .catch(error => console.log(error)) +// } +// calcSum(){ +// return this.allProducts.reduce((accum, item) => accum += item.price, 0); +// } +// handleData(data){ +// this.goods = data; +// this.render(); +// } +// render(){ +// const block = document.querySelector(this.container); +// for (let product of this.goods){ +// const productObj = new list[this.constructor.name](product); +// this.allProducts.push(productObj); +// block.insertAdjacentHTML('beforeend', productObj.render()); +// } +// } +// filter(value){ +// const regexp = new RegExp(value, 'i'); +// this.filtered = this.allProducts.filter(product => regexp.test(product.product_name)); +// this.allProducts.forEach(el => { +// const block = document.querySelector(`.product-item[data-id="${el.id_product}"]`); +// if(!this.filtered.includes(el)){ +// block.classList.add('invisible'); +// } else { +// block.classList.remove('invisible'); +// } +// }) +// } +// _init(){ +// return false +// } +// } +// class Item { +// constructor(el, img = 'https://placehold.it/200x150'){ +// this.product_name = el.product_name; +// this.price = el.price; +// this.img = img; +// this.id_product = el.id_product +// } +// +// render(){ +// return `
+// Some img +//
+//

${this.product_name}

+//

${this.price} $

+// +//
+//
`; +// +// } +// } +// +// +// class ProductsList extends List { +// constructor(cart, url = '/catalogData.json',container = '.products'){ +// super(url, container); +// this.cart = cart; +// this.getJson() +// .then(data => this.handleData(data)); +// } +// _init(){ +// document.querySelector(this.container).addEventListener('click', e => { +// if(e.target.classList.contains('buy-btn')){ +// this.cart.addProduct(e.target); +// } +// }); +// document.querySelector('.search-form').addEventListener('submit', e => { +// e.preventDefault(); +// this.filter(document.querySelector('.search-field').value); +// }) +// } +// } +// +// class Product extends Item{} +// class Cart extends List{ +// constructor(url = '/getBasket.json', container = '.cart-block'){ +// super(url, container); +// this.getJson() +// .then(data => this.handleData(data.contents)); +// } +// addProduct(element){ +// this.getJson(`${API}/addToBasket.json`) +// .then(data => { +// if(data.result === 1){ +// let productId = +element.dataset['id']; +// let find = this.allProducts.find(product => product.id_product === productId); +// if(find){ +// find.quantity++; +// this._updateCart(find); +// } else { +// let product = { +// id_product: productId, +// price: +element.dataset['price'], +// product_name: element.dataset['name'], +// quantity: 1 +// }; +// this.goods = [product]; +// this.render(); +// } +// } else { +// alert('Error') +// } +// }) +// } +// removeProduct(element){ +// this.getJson(`${API}/deleteFromBasket.json`) +// .then(data => { +// if(data.result === 1){ +// let productId = +element.dataset['id']; +// let find = this.allProducts.find(product => product.id_product === productId); +// if(find.quantity > 1){ +// find.quantity--; +// this._updateCart(find); +// } else { +// this.allProducts.splice(this.allProducts.indexOf(find), 1); +// document.querySelector(`.cart-item[data-id="${productId}"]`).remove(); +// } +// } else { +// alert('Error') +// } +// }) +// } +// _updateCart(product){ +// const block = document.querySelector(`.cart-item[data-id="${product.id_product}"]`); +// block.querySelector(`.product-quantity`).textContent = `Quantity: ${product.quantity}`; +// block.querySelector(`.product-price`).textContent = `$${product.quantity*product.price}`; +// } +// _init(){ +// document.querySelector(this.container).addEventListener('click', e => { +// if(e.target.classList.contains('del-btn')){ +// this.removeProduct(e.target); +// } +// }); +// document.querySelector('.btn-cart').addEventListener('click', () => { +// document.querySelector(this.container).classList.toggle('invisible') +// }) +// } +// } +// +// class CartItem extends Item{ +// constructor(el, img = 'https://placehold.it/50x100'){ +// super(el, img); +// this.quantity = el.quantity; +// } +// render(){ +// return `
+//
+// Some image +//
+//

${this.product_name}

+//

Quantity: ${this.quantity}

+//

$${this.price} each

+//
+//
+//
+//

${this.quantity*this.price}

+// +//
+//
` +// } +// } +// +// const list = { +// ProductsList: Product, +// Cart: CartItem +// }; +// +// +// const cart = new Cart(); +// const products = new ProductsList(cart); +// setTimeout(() => { +// products.getJson(`getProducts.json`).then(data => products.handleData(data)); +// }, 300); + +// list.getProducts(() => { +// list.render(); +// }); + + diff --git a/homework7/project_express/public/css/images/subscribe.jpg b/homework7/project_express/public/css/images/subscribe.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3bb987099bfc27281270a66adb31f891df73a555 GIT binary patch literal 131033 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 div:not(:last-child) { + margin-right: 15px; +} + +@media (min-width: 375px) { + .filtersRight > div:not(:last-child) { + margin-right: 24px; + } +} + +.filtersLeft .filterLabel { + display: none; + position: relative; + z-index: 2; + cursor: pointer; +} + +.filterLabelPink { + color: #ef5b70 !important; + left: 16px; + top: 13px; +} + +.filterIconPink { + left: 16px; + top: 13px; +} + +@media (min-width: 768px) { + .filtersLeft .filterLabel { + display: inline; + font-weight: 600; + font-size: 14px; + line-height: 17px; + color: #000000; + } +} + +.filtersLeft .filterIcon { + width: 37px; + height: 25px; + position: relative; + z-index: 2; +} + +@media (min-width: 768px) { + .filtersLeft .filterIcon { + width: 15px; + height: 10px; + margin-left: 11px; + } +} + +.filtersLeft { + position: relative; +} + +.hidden { + display: none; +} + +.filterPopup { + position: absolute; + left: 0; + top: 0; + width: 360px; + background: #ffffff; + box-shadow: 6px 4px 35px rgba(0, 0, 0, 0.21); + padding: 46px 16px 16px 16px; + z-index: 1; + overflow-y: auto; +} + +.filterCategoryHeader { + font-size: 14px; + line-height: 37px; + color: #ef5b70; + padding-left: 11px; + min-height: 37px; + border-bottom: 1px solid #ebebeb; + margin-bottom: 24px; + position: relative; + cursor: pointer; +} + +.filterCategoryHeader:before { + content: ""; + width: 5px; + min-height: inherit; + background: #ef5b70; + position: absolute; + left: 0; + top: 1px; +} + +.filterCategory:not(:last-child) { + margin-bottom: 24px; +} + +.filterCategory a { + display: block; + text-decoration: none; + padding-left: 34px; + padding-right: 16px; + font-size: 14px; + line-height: 17px; + color: #6f6e6e; +} + +.filterCategory a:not(:last-child) { + margin-bottom: 11px; +} + +.filterSizeWrap { + cursor: pointer; +} + +.filterSize { + position: relative; +} + +.filterSizes { + position: absolute; + left: 0; + top: 25px; + width: 79px; + height: 103px; + background: #ffffff; + box-shadow: 6px 4px 35px rgba(0, 0, 0, 0.21); + padding: 7px 9px; + box-sizing: border-box; + font-size: 14px; + color: #6f6e6e; +} + +.filterSizes > div:not(:last-child) { + margin-bottom: 4px; +} + +.featured { + padding-left: 8px; + padding-right: 8px; + margin-bottom: 96px; +} + +@media (min-width: 768px) { + .featured { + padding-left: 16px; + padding-right: 16px; + } +} + +@media (min-width: 1600px) { + .featured { + padding-left: 0; + padding-right: 0; + } +} + +.featured h2 { + margin-top: 0; + margin-bottom: 3px; + text-align: center; + color: #222222; +} + +.featuredTitle { + text-align: center; + color: #9f9f9f; + margin-bottom: 64px; +} + +.featuredItems { + display: grid; + grid-template-columns: 1fr; + row-gap: 16px; +} + +@media (min-width: 640px) { + .featuredItems { + grid-template-columns: 1fr 1fr; + row-gap: 18px; + column-gap: 16px; + } +} + +@media (min-width: 1000px) { + .featuredItems { + grid-template-columns: repeat(3, 1fr); + gap: 30px; + } +} + +.featuredItem { + background: #f8f8f8; +} + +.featuredItem img { + width: 100%; + display: block; +} + +.featuredImgWrap { + position: relative; +} + +.featuredItem:hover .featuredImgDark { + display: flex; +} + +.featuredImgDark { + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + background: rgba(58, 56, 56, 0.86); + display: none; + justify-content: center; + align-items: center; +} + +.featuredImgDark button { + background: none; + border: 1px solid white; + color: white; + display: flex; + align-items: center; + padding: 10px 14px; + font-size: 14px; + font-family: inherit; +} + +.featuredImgDark button img { + width: 26px; + height: 24px; + margin-right: 11px; +} + +.featuredData { + padding: 23px 16px 20px; +} + +.featuredName { + font-size: 24px; + line-height: 16px; + color: #000000; +} + +.featuredText { + font-weight: 300; + font-size: 14px; + line-height: 17px; + margin-top: 12px; + margin-bottom: 18px; +} + +.featuredPrice { + font-size: 16px; + line-height: 19px; + color: #f16d7f; +} + +.pagination { + width: 284px; + height: 44px; + margin: 0 auto; + border: 1px solid #ebebeb; + margin-top: 48px; + padding: 13px 16px; + box-sizing: border-box; + display: flex; + justify-content: space-between; + border-radius: 3px; +} + +.pagination a { + text-decoration: none; + font-weight: 300; + font-size: 16px; + color: #c4c4c4; +} + +.pagination a:hover { + color: #ef5b70; +} + +.services { + background: #222224; + padding-top: 48px; + padding-bottom: 81px; + padding-left: 14px; + padding-right: 14px; +} + +@media (min-width: 1200px) { + .services { + padding-top: 100px; + padding-bottom: 100px; + } +} + +.services .container { + display: grid; + gap: 46px; +} + +@media (min-width: 1200px) { + .services .container { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 46px; + } +} + +.serivceUnit { + text-align: center; + display: flex; + flex-direction: column; + align-items: center; +} + +.servicesTitle, +.servicesText { + color: #fbfbfb; +} + +.servicesTitle { + font-size: 19.96px; + line-height: 24px; + margin-top: 27px; + margin-bottom: 15px; +} + +.servicesText { + font-weight: 300; + font-size: 13.972px; + line-height: 17px; + max-width: 340px; +} + +.subscribe { + background: url(images/subscribe.jpg) no-repeat; + background-size: cover; + padding-top: 64px; + padding-bottom: 109px; + padding-left: 20px; + padding-right: 20px; +} + +@media (min-width: 1200px) { + .subscribe { + padding-top: 97px; + padding-bottom: 126px; + } + + .subscribe .container { + margin: 0 auto; + width: 1140px; + display: flex; + justify-content: space-between; + } +} + +.subscribeLeft { + display: flex; + flex-direction: column; + align-items: center; +} + +.subscribeUserText { + margin-top: 30px; + text-align: center; + font-size: 18px; + line-height: 22px; + color: #222224; + max-width: 330px; +} + +.subscribeRight { + display: flex; + flex-direction: column; + align-items: center; + margin-top: 65px; +} + +@media (min-width: 1200px) { + .subscribeRight { + margin-top: initial; + } +} + +.subscribeTitle { + font-weight: 700; + font-size: 24px; + color: #222224; +} + +.subscribeTitle, +.subscribeText { + max-width: 271px; + text-align: center; +} + +.subscribeText { + font-size: 14px; + color: #222224; + margin-bottom: 22px; +} + +.subscribeForm { + height: 47px; +} + +.subscribeForm input { + height: inherit; + background: #e1e1e1; + border: none; + padding: 6px 21px; + box-sizing: border-box; + border-top-left-radius: 28px; + border-bottom-left-radius: 28px; + float: left; + width: 185px; +} + +.subscribeForm input::-webkit-input-placeholder { + color: #222224; + font-family: inherit; + opacity: 0.67; +} +.subscribeForm input::-moz-placeholder { + color: #222224; + font-family: inherit; + opacity: 0.67; +} +.subscribeForm input:-ms-input-placeholder { + color: #222224; + font-family: inherit; + opacity: 0.67; +} +.subscribeForm input:-moz-placeholder { + color: #222224; + font-family: inherit; + opacity: 0.67; +} + +.subscribeForm button { + height: inherit; + border: none; + color: white; + font-family: inherit; + font-size: 14px; + line-height: 17px; + background: #f16d7f; + border-top-right-radius: 28px; + border-bottom-right-radius: 28px; + padding: 0 17px; +} + +.footer { + background: #222224; + padding: 43px 20px 10px; +} + +@media (min-width: 768px) { + .footer { + padding: 24px 32px; + } +} + +.footer .container { + display: flex; + flex-direction: column; + align-items: center; +} + +@media (min-width: 768px) { + .footer .container { + flex-direction: row; + justify-content: space-between; + } +} + +.footerLeft { + display: flex; +} + +.footer a { + color: black; + background: white; + width: 32px; + height: 32px; + display: flex; + justify-content: center; + align-items: center; + text-decoration: none; +} + +.footer a:hover { + background: #f16d7f; + color: white; +} + +.footer a:not(:last-child) { + margin-right: 7px; +} + +.footerRight { + color: white; +} + +@media (max-width: 767px) { + .footerRight { + margin-top: 40px; + } +} diff --git a/homework7/project_express/public/images/bars.png b/homework7/project_express/public/images/bars.png new file mode 100644 index 0000000000000000000000000000000000000000..c30c42923f406b65cb7ade89aceb87c25f2bf218 GIT binary patch literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^3P3E*!3HF=SbZM?Db50q$YKTtZeb8+WSBKa0w~B> z9OUlAu3#WAFU@$EH7UIqmo=Zk#`ESeVV>M_rm z!bEK^Ouur-U)fl{Me0aZ?%^|aVxfna727f#PNFVdQ&MBb@022H!q5uE@ literal 0 HcmV?d00001 diff --git a/homework7/project_express/public/images/cart.png b/homework7/project_express/public/images/cart.png new file mode 100644 index 0000000000000000000000000000000000000000..3338b95ce534455535de64eeaee2f5eac89e72eb GIT binary patch literal 716 zcmV;-0yF)IP)B4CIB9KqlSh74wifFS}z2F}3Zh<^gOMfN6WHR}QrYBF)Z#J7><-#!dQA%}V#^1^_K=Cskk8L?-q6fu3 zP*^UPmg6{cxggZ3&e3RO*6Vej^5Jm!*lM-z<$^Fyb?TdYT8XY)7%FZ6&Ps>;1hdQ= zjfQnJbVAM#pTD2|9`W+sh&1Sdz{rqJsmSqiB6~U&o8j>osV~B^1%#3oXIJw#4E`NEOzCuIeL)g95CG5?Y0-~&!a>ib}f{)!Qen%kbq2%$%ueG zO_*aCb*eIu8ls4b8&+6&JHDeG>E}HcP=$3_n=r!oj7QUdA`^^n9(=SQq2`PO6yP3q z@Xw41M!y9AiA?NvyC)A8bA|8wuO%Z+RbaTtQTk6*Vzb$JK|K+I7cF{|fCq3M-6NXp y5|!ZNg$1lFhq}uJ6IYT0p*_4{50r}i@SHy*yBt(uWd+~>0000 + + + + diff --git a/homework7/project_express/public/images/chevronLeft.svg b/homework7/project_express/public/images/chevronLeft.svg new file mode 100644 index 0000000..17eff57 --- /dev/null +++ b/homework7/project_express/public/images/chevronLeft.svg @@ -0,0 +1,3 @@ + + + diff --git a/homework7/project_express/public/images/chevronRight.svg b/homework7/project_express/public/images/chevronRight.svg new file mode 100644 index 0000000..12ef11b --- /dev/null +++ b/homework7/project_express/public/images/chevronRight.svg @@ -0,0 +1,3 @@ + + + diff --git a/homework7/project_express/public/images/featured/1.jpg b/homework7/project_express/public/images/featured/1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..41eac02758a3de0eaa84fb4c686aa24034646e2a GIT binary patch literal 93945 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 K@zN}RM*kZhb92=I literal 0 HcmV?d00001 diff --git a/homework7/project_express/public/images/featured/3.jpg b/homework7/project_express/public/images/featured/3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8d118db207bda4ff043f39d3e24491bc9e84d281 GIT binary patch literal 80895 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

fQP(ceh$Mw9gw{dxK%H7HF&3utN|RDXJ`JW$fO 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�D*KZIp|)r>gn_M;n7a2IB=H1aFFzH(B@G6An8g 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 HzkmM+ns)C` literal 0 HcmV?d00001 diff --git a/homework7/project_express/public/images/featured/4.jpg b/homework7/project_express/public/images/featured/4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bf61659db62c801a5132c7a68577fcbeff1250db GIT binary patch literal 51885 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 literal 0 HcmV?d00001 diff --git a/homework7/project_express/public/images/featured/5.jpg b/homework7/project_express/public/images/featured/5.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1ffe51d7964693a5a28b8f58eacff87a0c927ac7 GIT binary patch literal 93122 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

&z`PHd+%<1 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 literal 0 HcmV?d00001 diff --git a/homework7/project_express/public/images/filter.svg b/homework7/project_express/public/images/filter.svg new file mode 100644 index 0000000..a125181 --- /dev/null +++ b/homework7/project_express/public/images/filter.svg @@ -0,0 +1,3 @@ + + + diff --git a/homework7/project_express/public/images/filterArrow.svg b/homework7/project_express/public/images/filterArrow.svg new file mode 100644 index 0000000..ee46233 --- /dev/null +++ b/homework7/project_express/public/images/filterArrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/homework7/project_express/public/images/filterHover.svg b/homework7/project_express/public/images/filterHover.svg new file mode 100644 index 0000000..e9328d3 --- /dev/null +++ b/homework7/project_express/public/images/filterHover.svg @@ -0,0 +1,3 @@ + + + diff --git a/homework7/project_express/public/images/logo.png b/homework7/project_express/public/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7da5adc3662959b00234fec9a72f64f2c3d2744d GIT binary patch literal 2364 zcmV-C3B&e@P)JIK~#7F#aL@> zRL2!QGxy&0u6Mm&V+`iu1REC{T%|xjN}7tGQb0fk4>K0zT^o@|7#$zp49SKTn}1j zH?g*M*hU9YCzKa8m1ap|0pxU$mgXVydC5w1lcj0*V$pxaqF*J`*pvRnoVME{EZ-`f zWeRh%Ah8azXJQLGDAvku01`W_H#p zlbc7we*Y6``S~|(Qw^OPVt$XG;E?9WdXJyImqviHPp!J1`04k_s;nhxT5;`ZJf_Wr z!wne}e>ji#1)!jql;#D#}xk9`rS{yRvH*HLkjg$XAGhayl5&otQ^kf~T zh%PisKf7D%>?93Nc!O+n7~*X(Xjy~5A-E{QicCY>EIjj)&96*_!8bHz9t-DRVJ`iv zp1i!~5eX}p$KTzL`1+K6CG?x<_4>a=>zhw9HijDGj`a@aJ<7Os-V<#vW4m{o@%2d- z+_N`VJMn48&t-U6^b~m*F~`^=xsNMu9wd(1C#f$FgO;f{=TH06eaCkmy+{+pl%H%2Qf5X~ESV&tr54k& z*NVy+F~XY3)G6rz33fhER{irpS*^`maYFbLI9*CQL!a$3r{fAu5@gXlNrrBV@3IHS z=p=-g2x3A^lx)1j?&k3)I#wHm0}^Auc8*B^irykEewu0g+2J z+2ktucQe= zUb^H!I$uv6od%h9>r-?W22-B*bF7TAnyZcd<&Os5eWVkP0com z7-)GtB)w_z!*^mWDpEAHWawSpzYbSkTR?XJ_{s|GbV*DzO>l?a-hq>jQcjA|CL-Mp zNfU>+Ft0qlaPB7LuH~q}egzqIal$wmx>L!THpM;w9&O!fCtlZBXfb)L{c7cM8V7=9 zRcjHrj*?+y@f){@H8j&;r&9{yZue=I%e*jZrt=o$miY?upGI-H8l!fR(zpfNnl+us zhkij%6n4Dr4_RKyMAjX=5om#uz(&S>((m6b(-imJn;(!Zw9WH1AUYD21mH9=VI z9ufynPb+0>)^v@lHoyc~mSh`AGuH7l=kuwyAzlV007ubhXOmd^B@$k@T2KJmc^k3) z4C<5$&Uq&;Pkiw9d1zma5%=S9s~uuWiyvGhSy5xtE(sjwJ+3S6Idi|v)~pQPQ85!L zZj#e?>3h9%giBt19%P;y_5oVaJT79nIb_YrA>m2IQFl5ZW=FQ7b}EY9(K@^E?;C@xAr9MMw5&{$^N;T#Bo*1NAX&CTZ1@j zLLhq+q>s3FKK0RPT_>Gz0-Y}$$cYMZ56brkad5d0P5Fo@X|a1PMo0jxP73QBY3!8L i_-Ec7TPkix?tcMCFrbQ8BLJ-c0000o63BCC^(V**q_kNoJm10qNj{4)Q914#=wjs31cHKm|YrF%@7cus8YL#H;))5_3+F z7*DX3*bZmLwrt(&Pxnf?lER=M2<%Fw(zPt>Zyd)?qRZcGHm}WQ^I7DO%!1TvwJS7x zfY=8A5dF7}M&m&gfz4*K_IA5{Ler5_Mu^}M&*#-@<-4vMjmKk$eYh_1{UQN92Q)ky zMi86^j0V8F^?H3nK$bJXNO2$b-D81Yj+4nGz!jr?BXWrL^uzUbl*4p7y)OdNg6}{9 zds#M8jg0dXpc&TdbypOSO6e}L#bV*6rQg~SrQD5%D@zm<=L-IhoNsKGcAAZ)o@cya z<@ut7;P3IN7R)#O;ti2;BvGr?Dg{FtwZD_vuSR0yibP52We@1@w0<2KLAEFrpt2EFixit$gB5Yo3RU&xf72}4x6dS8ixVhZt}j(YVnVVGD? z891g2U=pIb7N5oYA*()G3FH5&*+)UX5IKZWca5kn(F`$P#}$UrXw*~nE#?mn+4J1P z!1~%}I2?9O_A(8~V?(`$s)TvT)Tlbh==Tp-<1v$ZQmevzk7nn~5POkZ1W$Vp;Bg9& zKH9fUz*JZQ+7X{8@|pUPhVq9mDq@e{nbK;tIxqo^u)I11JSprD&=MyW56$Ird5$Kl z2yDSa5 + + diff --git a/homework7/project_express/public/images/services/delivery.svg b/homework7/project_express/public/images/services/delivery.svg new file mode 100644 index 0000000..266b21f --- /dev/null +++ b/homework7/project_express/public/images/services/delivery.svg @@ -0,0 +1,3 @@ + + + diff --git a/homework7/project_express/public/images/services/discount.svg b/homework7/project_express/public/images/services/discount.svg new file mode 100644 index 0000000..eabc2d6 --- /dev/null +++ b/homework7/project_express/public/images/services/discount.svg @@ -0,0 +1,3 @@ + + + diff --git a/homework7/project_express/public/images/subscribe.jpg b/homework7/project_express/public/images/subscribe.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3bb987099bfc27281270a66adb31f891df73a555 GIT binary patch literal 131033 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 R-u3_h002ovPDHLkV1oW%wbTFr literal 0 HcmV?d00001 diff --git a/homework7/project_express/public/images/user.png b/homework7/project_express/public/images/user.png new file mode 100644 index 0000000000000000000000000000000000000000..c8e4879a3ed4fd13f5f63371bf9445ac4773333f GIT binary patch literal 718 zcmV;<0x|uGP)j+>Y@DjmlBd|9Dl!3`Wx=?&Bk}v$K0Kcc5 zabeXWX^{1*rdkp`{hR&_mKb0*n>m(c-C{Y%xz``_#S}v$>;liLyBUtSUk?> z^COhIl5U(!KCH160R;7xAU_X36)FRrG``gEGHFOv2r~h`d$n&Mmw;z^Nw~DPVHmzY z$CKu%qv*4kA?Dw1x1YsSDMEBjijYmj0Q>zuAVv9f#8j!SKM0A$0Jd$%Mpi17w`X}I z1NC}66a&D>%sNdAZ|vc2x4RJoz(XCO-(sp%pCxEV44`uXbYiR&@D%Nd8G4ERX2{!N zG{~2ywo?=7q{DpA)5z5%;=U&-0^P{j_|NgsAUzn;_%t$0X0zGcflN5M*!ZW@>8FHI zPOVlO^LO&CR;zDWGOgFFhLAoUKVmTxqxE{-tyZfK2;Y|z*5GuAGo&;Sdw<}S-y#)e zFFDx%QMz0%Z^1a!f)pkg*f-iM5Dx1PN-)pSL(6-DV2|&J#xG^;U*oVwkntc%;4B8} zOhO1Ba>_^nz=7+N!A`k@R~7QiiYiM&jYwa~XMTvK?m)a5@SfAnbFsQaF$Mv{E=aU1 zW^Z5pHY!6QLAf~h5px9zd1u4RxNYIXPbm?|>^PC&anE9`@f`3(+18AwMS>AV?H2?qr07*qoM6N<$g6=jx AzW@LL literal 0 HcmV?d00001 diff --git a/homework7/project_express/public/index.html b/homework7/project_express/public/index.html new file mode 100644 index 0000000..eab3963 --- /dev/null +++ b/homework7/project_express/public/index.html @@ -0,0 +1,250 @@ + + + + + + + Document + + + + + + +

+
+
+
+ + +
+ +
+ + + +
+ +
+
+ +
+ +
+
+ +
+
+ TRENDING NOW + +
+
+
+ SIZE + +
+ +
+
+ PRICE + +
+
+
+
+ + + +
+
+ +
+ +
+ Free Delivery +
+
+ Worldwide delivery on all. Authorit tively morph next-generation innov tion with extensive + models. +
+
+ +
+ +
+ Sales & discounts +
+
+ Worldwide delivery on all. Authorit tively morph next-generation innov tion with extensive + models. +
+
+ +
+ +
+ Quality assurance +
+
+ Worldwide delivery on all. Authorit tively morph next-generation innov tion with extensive + models. +
+
+
+
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/homework7/project_express/public/js/main.js b/homework7/project_express/public/js/main.js new file mode 100644 index 0000000..c01c575 --- /dev/null +++ b/homework7/project_express/public/js/main.js @@ -0,0 +1,62 @@ +const API = + "https://raw.githubusercontent.com/GeekBrainsTutorial/online-store-api/master/responses"; + +const app = new Vue({ + el: "#app", + data: { + userSearch: "", + }, + methods: { + getJson(url) { + return fetch(url) + .then((result) => result.json()) + .catch((error) => { + // console.log(error) + this.$refs.error.text = error; + }); + }, + postJson(url, data) { + return fetch(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }) + .then((result) => result.json()) + .catch((error) => { + // console.log(error) + this.$refs.error.text = error; + }); + }, + putJson(url, data) { + return fetch(url, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }) + .then((result) => result.json()) + .catch((error) => { + // console.log(error) + this.$refs.error.text = error; + }); + }, + deleteJson(url, data) { + return fetch(url, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }) + .then((result) => result.json()) + .catch((error) => { + // console.log(error) + this.$refs.error.text = error; + }); + }, + }, + mounted() {}, +}); diff --git a/homework7/project_express/public/js/mycartComponent.js b/homework7/project_express/public/js/mycartComponent.js new file mode 100644 index 0000000..ad38184 --- /dev/null +++ b/homework7/project_express/public/js/mycartComponent.js @@ -0,0 +1,91 @@ +Vue.component("cart", { + data() { + return { + cartUrl: "/getBasket.json", + cartItems: [], + showCart: false, + totalQuantity: 0, + }; + }, + mounted() { + this.$parent.getJson(`/api/cart`).then((data) => { + for (let item of data.contents) { + this.$data.cartItems.push(item); + this.$data.totalQuantity += item.quantity; + } + }); + }, + methods: { + addProduct(item) { + let find = this.cartItems.find((el) => el.id_product === item.id_product); + if (find) { + this.$parent + .putJson(`/api/cart/${find.id_product}`, { quantity: 1 }) + .then((data) => { + if (data.result === 1) { + find.quantity++; + this.$data.totalQuantity++; + } + }); + } else { + const prod = Object.assign({ quantity: 1 }, item); + this.$parent.postJson(`/api/cart`, prod).then((data) => { + if (data.result === 1) { + this.cartItems.push(prod); + this.$data.totalQuantity++; + } + }); + } + }, + remove(item) { + let find = this.cartItems.find((el) => el.id_product === item.id_product); + if (find) { + this.$parent + .deleteJson(`/api/cart/deleteProduct/${find.id_product}`, { + quantity: 1, + }) + .then((data) => { + if (data.result === 1) { + if (find.quantity > 1) { + find.quantity--; + this.$data.totalQuantity--; + } else { + this.cartItems.splice(this.cartItems.indexOf(item), 1); + this.$data.totalQuantity--; + } + } + }); + } + }, + }, + template: ` + + + {{totalQuantity}} +
+ + +
+
+ `, +}); + +Vue.component("cart-item", { + props: ["cartItem"], + template: ` +
+
+ Some img +
+
{{ cartItem.product_name }}
+
Quantity: {{ cartItem.quantity }}
+
$ {{ cartItem.price }} each
+
+
+
+
{{cartItem.quantity*cartItem.price}}
+ +
+
+ `, +}); diff --git a/homework7/project_express/public/js/myproductComponent.js b/homework7/project_express/public/js/myproductComponent.js new file mode 100644 index 0000000..b80436e --- /dev/null +++ b/homework7/project_express/public/js/myproductComponent.js @@ -0,0 +1,55 @@ +Vue.component("products", { + data() { + return { + products: [], + }; + }, + mounted() { + this.$parent.getJson(`/api/products`).then((data) => { + for (let item of data) { + this.$data.products.push(item); + } + }); + }, + template: ` +
+ +
+ `, +}); +Vue.component("product", { + props: ["product"], + template: ` +
+
+ +
+ +
+
+ +
+
+ {{product.product_name}} +
+
+ Known for her sculptural takes on traditional + tailoring, Australian arbiter of cool Kym + Ellery + teams + up with Moda Operandi. +
+
+ {{product.price}} +
+
+
+ `, +}); diff --git a/homework7/project_express/server/cart.js b/homework7/project_express/server/cart.js new file mode 100644 index 0000000..7eae2ae --- /dev/null +++ b/homework7/project_express/server/cart.js @@ -0,0 +1,24 @@ +let add = (cart, req) => { + cart.contents.push(req.body); + return JSON.stringify(cart, null, 4); +}; +let change = (cart, req) => { + let find = cart.contents.find((el) => el.id_product === +req.params.id); + find.quantity += req.body.quantity; + return JSON.stringify(cart, null, 4); +}; + +let deleteProduct = (cart, req) => { + let find = cart.contents.find((el) => el.id_product === +req.params.id); + find.quantity -= req.body.quantity; + if (!find.quantity) { + cart.contents.splice(cart.contents.indexOf(find), 1); + } + return JSON.stringify(cart, null, 4); +}; + +module.exports = { + add, + change, + deleteProduct, +}; diff --git a/homework7/project_express/server/cartRouter.js b/homework7/project_express/server/cartRouter.js new file mode 100644 index 0000000..948a631 --- /dev/null +++ b/homework7/project_express/server/cartRouter.js @@ -0,0 +1,25 @@ +const express = require("express"); +const fs = require("fs"); +const router = express.Router(); +const handler = require("./handler"); + +router.get("/", (req, res) => { + fs.readFile("server/db/userCart.json", "utf-8", (err, data) => { + if (err) { + res.sendStatus(404, JSON.stringify({ result: 0, text: err })); + } else { + res.send(data); + } + }); +}); +router.post("/", (req, res) => { + handler(req, res, "add", "server/db/userCart.json"); +}); +router.put("/:id", (req, res) => { + handler(req, res, "change", "server/db/userCart.json"); +}); +router.delete("/deleteProduct/:id", (req, res) => { + handler(req, res, "deleteProduct", "server/db/userCart.json"); +}); + +module.exports = router; diff --git a/homework7/project_express/server/db/products.json b/homework7/project_express/server/db/products.json new file mode 100644 index 0000000..ea7331b --- /dev/null +++ b/homework7/project_express/server/db/products.json @@ -0,0 +1,38 @@ +[ + { + "id_product": 4546, + "product_name": "ELLERY X M'O CAPSULE5", + "price": 10020, + "img":"images/featured/1.jpg" + }, + { + "id_product": 4156, + "product_name": "ELLERY X M'O CAPSULE5", + "price": 10400, + "img":"images/featured/2.jpg" + }, + { + "id_product": 45446, + "product_name": "ELLERY X M'O CAPSULE5", + "price": 10600, + "img":"images/featured/3.jpg" + }, + { + "id_product": 356, + "product_name": "ELLERY X M'O CAPSULE5", + "price": 1000, + "img":"images/featured/4.jpg" + }, + { + "id_product": 656, + "product_name": "ELLERY X M'O CAPSULE5", + "price": 100110, + "img":"images/featured/5.jpg" + }, + { + "id_product": 456, + "product_name": "ELLERY X M'O CAPSULE5", + "price": 109900, + "img":"images/featured/6.jpg" + } +] \ No newline at end of file diff --git a/homework7/project_express/server/db/userCart.json b/homework7/project_express/server/db/userCart.json new file mode 100644 index 0000000..adc4281 --- /dev/null +++ b/homework7/project_express/server/db/userCart.json @@ -0,0 +1,20 @@ +{ + "amount": 46600, + "countGoods": 2, + "contents": [ + { + "quantity": 3, + "id_product": 4156, + "product_name": "ELLERY X M'O CAPSULE5", + "price": 10400, + "img": "images/featured/2.jpg" + }, + { + "quantity": 1, + "id_product": 45446, + "product_name": "ELLERY X M'O CAPSULE5", + "price": 10600, + "img": "images/featured/3.jpg" + } + ] +} \ No newline at end of file diff --git a/homework7/project_express/server/handler.js b/homework7/project_express/server/handler.js new file mode 100644 index 0000000..9dfa22f --- /dev/null +++ b/homework7/project_express/server/handler.js @@ -0,0 +1,27 @@ +const cart = require("./cart"); +const fs = require("fs"); + +const actions = { + add: cart.add, + change: cart.change, + deleteProduct: cart.deleteProduct, +}; +//HANDLER отвечает за изменение данных в самом файле +let handler = (req, res, action, file) => { + fs.readFile(file, "utf-8", (err, data) => { + if (err) { + res.sendStatus(404, JSON.stringify({ result: 0, text: err })); + } else { + let newCart = actions[action](JSON.parse(data), req); + fs.writeFile(file, newCart, (err) => { + if (err) { + res.sendStatus(404, JSON.stringify({ result: 0, text: err })); + } else { + res.send(JSON.stringify({ result: 1 })); + } + }); + } + }); +}; + +module.exports = handler; diff --git a/homework7/project_express/server/server.js b/homework7/project_express/server/server.js new file mode 100644 index 0000000..08a53c4 --- /dev/null +++ b/homework7/project_express/server/server.js @@ -0,0 +1,32 @@ +const express = require('express'); +const fs = require('fs'); +const app = express(); +const cart = require('./cartRouter');//обработчик всех запросов корзины + +app.use(express.json()); +app.use('/', express.static('public')); +app.use('/api/cart', cart); + + +// app.get(); +// app.post(); +// app.put(); +// app.delete(); + +app.get('/api/products', (req, res) => { + fs.readFile('server/db/products.json', 'utf-8', (err, data) => { + if(err){ + res.sendStatus(404, JSON.stringify({result:0, text: err})); + } else { + res.send(data); + } + }) +}); + +// app.get('/api/cart/:id', (req, res) => { +// // res.send(req.params.id); +// res.send(req.query); +// }); + +const port = process.env.PORT || 3000; +app.listen(port, () => console.log(`Listen on port ${port}...`)); \ No newline at end of file From c0fd440df361c76eaaad761ded446833ef1df11c Mon Sep 17 00:00:00 2001 From: ren4t Date: Tue, 25 Oct 2022 19:33:48 +0300 Subject: [PATCH 2/2] homework8 start --- homework8/project_express/.idea/.gitignore | 8 + .../.idea/jsLibraryMappings.xml | 6 + homework8/project_express/.idea/misc.xml | 6 + homework8/project_express/.idea/modules.xml | 8 + .../project_express/.idea/project_express.iml | 12 + .../project_express/node_modules/.bin/mime | 15 + .../node_modules/.bin/mime.cmd | 17 + .../node_modules/.bin/mime.ps1 | 18 + .../project_express/node_modules/.bin/nodemon | 12 + .../node_modules/.bin/nodemon.cmd | 17 + .../node_modules/.bin/nodemon.ps1 | 28 + .../node_modules/.bin/nodetouch | 12 + .../node_modules/.bin/nodetouch.cmd | 17 + .../node_modules/.bin/nodetouch.ps1 | 28 + .../project_express/node_modules/.bin/nopt | 12 + .../node_modules/.bin/nopt.cmd | 17 + .../node_modules/.bin/nopt.ps1 | 28 + .../project_express/node_modules/.bin/require | 12 + .../node_modules/.bin/require.cmd | 17 + .../node_modules/.bin/require.ps1 | 28 + .../project_express/node_modules/.bin/semver | 12 + .../node_modules/.bin/semver.cmd | 17 + .../node_modules/.bin/semver.ps1 | 28 + .../node_modules/.bin/uglifyjs | 12 + .../node_modules/.bin/uglifyjs.cmd | 17 + .../node_modules/.bin/uglifyjs.ps1 | 28 + .../node_modules/.package-lock.json | 882 ++ .../node_modules/abbrev/LICENSE | 46 + .../node_modules/abbrev/README.md | 23 + .../node_modules/abbrev/abbrev.js | 61 + .../node_modules/abbrev/package.json | 21 + .../node_modules/accepts/HISTORY.md | 236 + .../node_modules/accepts/LICENSE | 23 + .../node_modules/accepts/README.md | 142 + .../node_modules/accepts/index.js | 238 + .../node_modules/accepts/package.json | 86 + .../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/anymatch/LICENSE | 15 + .../node_modules/anymatch/README.md | 87 + .../node_modules/anymatch/index.d.ts | 19 + .../node_modules/anymatch/index.js | 104 + .../node_modules/anymatch/package.json | 48 + .../node_modules/array-flatten/LICENSE | 21 + .../node_modules/array-flatten/README.md | 43 + .../array-flatten/array-flatten.js | 64 + .../node_modules/array-flatten/package.json | 64 + .../node_modules/async/LICENSE | 19 + .../node_modules/async/README.md | 1425 +++ .../node_modules/async/component.json | 11 + .../node_modules/async/lib/async.js | 958 ++ .../node_modules/async/package.json | 36 + .../balanced-match/.github/FUNDING.yml | 2 + .../node_modules/balanced-match/LICENSE.md | 21 + .../node_modules/balanced-match/README.md | 97 + .../node_modules/balanced-match/index.js | 62 + .../node_modules/balanced-match/package.json | 48 + .../binary-extensions/binary-extensions.json | 260 + .../binary-extensions.json.d.ts | 3 + .../node_modules/binary-extensions/index.d.ts | 14 + .../node_modules/binary-extensions/index.js | 1 + .../node_modules/binary-extensions/license | 9 + .../binary-extensions/package.json | 38 + .../node_modules/binary-extensions/readme.md | 41 + .../node_modules/body-parser/HISTORY.md | 609 ++ .../node_modules/body-parser/LICENSE | 23 + .../node_modules/body-parser/README.md | 443 + .../node_modules/body-parser/index.js | 157 + .../node_modules/body-parser/lib/read.js | 181 + .../body-parser/lib/types/json.js | 230 + .../node_modules/body-parser/lib/types/raw.js | 101 + .../body-parser/lib/types/text.js | 121 + .../body-parser/lib/types/urlencoded.js | 284 + .../node_modules/body-parser/package.json | 91 + .../node_modules/brace-expansion/LICENSE | 21 + .../node_modules/brace-expansion/README.md | 129 + .../node_modules/brace-expansion/index.js | 201 + .../node_modules/brace-expansion/package.json | 47 + .../node_modules/braces/CHANGELOG.md | 184 + .../node_modules/braces/LICENSE | 21 + .../node_modules/braces/README.md | 593 ++ .../node_modules/braces/index.js | 170 + .../node_modules/braces/lib/compile.js | 57 + .../node_modules/braces/lib/constants.js | 57 + .../node_modules/braces/lib/expand.js | 113 + .../node_modules/braces/lib/parse.js | 333 + .../node_modules/braces/lib/stringify.js | 32 + .../node_modules/braces/lib/utils.js | 112 + .../node_modules/braces/package.json | 77 + .../node_modules/bytes/History.md | 87 + .../node_modules/bytes/LICENSE | 23 + .../node_modules/bytes/Readme.md | 126 + .../node_modules/bytes/index.js | 162 + .../node_modules/bytes/package.json | 84 + .../node_modules/chokidar/LICENSE | 21 + .../node_modules/chokidar/README.md | 308 + .../node_modules/chokidar/index.js | 973 ++ .../node_modules/chokidar/lib/constants.js | 65 + .../chokidar/lib/fsevents-handler.js | 524 ++ .../chokidar/lib/nodefs-handler.js | 654 ++ .../node_modules/chokidar/package.json | 85 + .../node_modules/chokidar/types/index.d.ts | 188 + .../node_modules/concat-map/.travis.yml | 4 + .../node_modules/concat-map/LICENSE | 18 + .../node_modules/concat-map/README.markdown | 62 + .../node_modules/concat-map/example/map.js | 6 + .../node_modules/concat-map/index.js | 13 + .../node_modules/concat-map/package.json | 43 + .../node_modules/concat-map/test/map.js | 39 + .../content-disposition/HISTORY.md | 55 + .../node_modules/content-disposition/LICENSE | 22 + .../content-disposition/README.md | 148 + .../node_modules/content-disposition/index.js | 458 + .../content-disposition/package.json | 79 + .../node_modules/content-type/HISTORY.md | 24 + .../node_modules/content-type/LICENSE | 22 + .../node_modules/content-type/README.md | 92 + .../node_modules/content-type/index.js | 222 + .../node_modules/content-type/package.json | 76 + .../node_modules/cookie-signature/.npmignore | 4 + .../node_modules/cookie-signature/History.md | 38 + .../node_modules/cookie-signature/Readme.md | 42 + .../node_modules/cookie-signature/index.js | 51 + .../cookie-signature/package.json | 57 + .../node_modules/cookie/HISTORY.md | 123 + .../node_modules/cookie/LICENSE | 24 + .../node_modules/cookie/README.md | 253 + .../node_modules/cookie/index.js | 198 + .../node_modules/cookie/package.json | 78 + .../node_modules/debug/.coveralls.yml | 1 + .../node_modules/debug/.eslintrc | 11 + .../node_modules/debug/.npmignore | 9 + .../node_modules/debug/.travis.yml | 14 + .../node_modules/debug/CHANGELOG.md | 362 + .../node_modules/debug/LICENSE | 19 + .../node_modules/debug/Makefile | 50 + .../node_modules/debug/README.md | 312 + .../node_modules/debug/component.json | 19 + .../node_modules/debug/karma.conf.js | 70 + .../node_modules/debug/node.js | 1 + .../node_modules/debug/package.json | 91 + .../node_modules/debug/src/browser.js | 185 + .../node_modules/debug/src/debug.js | 202 + .../node_modules/debug/src/index.js | 10 + .../node_modules/debug/src/inspector-log.js | 15 + .../node_modules/debug/src/node.js | 248 + .../node_modules/depd/History.md | 96 + .../project_express/node_modules/depd/LICENSE | 22 + .../node_modules/depd/Readme.md | 280 + .../node_modules/depd/index.js | 522 ++ .../node_modules/depd/lib/browser/index.js | 77 + .../depd/lib/compat/callsite-tostring.js | 103 + .../depd/lib/compat/event-listener-count.js | 22 + .../node_modules/depd/lib/compat/index.js | 79 + .../node_modules/depd/package.json | 79 + .../node_modules/destroy/LICENSE | 22 + .../node_modules/destroy/README.md | 60 + .../node_modules/destroy/index.js | 75 + .../node_modules/destroy/package.json | 71 + .../node_modules/ee-first/LICENSE | 22 + .../node_modules/ee-first/README.md | 80 + .../node_modules/ee-first/index.js | 95 + .../node_modules/ee-first/package.json | 63 + .../node_modules/encodeurl/HISTORY.md | 14 + .../node_modules/encodeurl/LICENSE | 22 + .../node_modules/encodeurl/README.md | 128 + .../node_modules/encodeurl/index.js | 60 + .../node_modules/encodeurl/package.json | 78 + .../node_modules/escape-html/LICENSE | 24 + .../node_modules/escape-html/Readme.md | 43 + .../node_modules/escape-html/index.js | 78 + .../node_modules/escape-html/package.json | 59 + .../node_modules/etag/HISTORY.md | 83 + .../project_express/node_modules/etag/LICENSE | 22 + .../node_modules/etag/README.md | 159 + .../node_modules/etag/index.js | 131 + .../node_modules/etag/package.json | 86 + .../node_modules/express/History.md | 3477 +++++++ .../node_modules/express/LICENSE | 24 + .../node_modules/express/Readme.md | 155 + .../node_modules/express/index.js | 11 + .../node_modules/express/lib/application.js | 644 ++ .../node_modules/express/lib/express.js | 116 + .../express/lib/middleware/init.js | 43 + .../express/lib/middleware/query.js | 47 + .../node_modules/express/lib/request.js | 525 ++ .../node_modules/express/lib/response.js | 1142 +++ .../node_modules/express/lib/router/index.js | 662 ++ .../node_modules/express/lib/router/layer.js | 181 + .../node_modules/express/lib/router/route.js | 216 + .../node_modules/express/lib/utils.js | 306 + .../node_modules/express/lib/view.js | 182 + .../node_modules/express/package.json | 154 + .../node_modules/fill-range/LICENSE | 21 + .../node_modules/fill-range/README.md | 237 + .../node_modules/fill-range/index.js | 249 + .../node_modules/fill-range/package.json | 69 + .../node_modules/finalhandler/HISTORY.md | 187 + .../node_modules/finalhandler/LICENSE | 22 + .../node_modules/finalhandler/README.md | 148 + .../node_modules/finalhandler/index.js | 331 + .../node_modules/finalhandler/package.json | 80 + .../node_modules/forwarded/HISTORY.md | 16 + .../node_modules/forwarded/LICENSE | 22 + .../node_modules/forwarded/README.md | 57 + .../node_modules/forwarded/index.js | 76 + .../node_modules/forwarded/package.json | 78 + .../node_modules/fresh/HISTORY.md | 70 + .../node_modules/fresh/LICENSE | 23 + .../node_modules/fresh/README.md | 119 + .../node_modules/fresh/index.js | 137 + .../node_modules/fresh/package.json | 90 + .../node_modules/glob-parent/CHANGELOG.md | 110 + .../node_modules/glob-parent/LICENSE | 15 + .../node_modules/glob-parent/README.md | 137 + .../node_modules/glob-parent/index.js | 42 + .../node_modules/glob-parent/package.json | 48 + .../node_modules/has-flag/index.js | 8 + .../node_modules/has-flag/license | 9 + .../node_modules/has-flag/package.json | 44 + .../node_modules/has-flag/readme.md | 70 + .../node_modules/http-errors/HISTORY.md | 149 + .../node_modules/http-errors/LICENSE | 23 + .../node_modules/http-errors/README.md | 163 + .../node_modules/http-errors/index.js | 266 + .../node_modules/http-errors/package.json | 93 + .../node_modules/iconv-lite/Changelog.md | 162 + .../node_modules/iconv-lite/LICENSE | 21 + .../node_modules/iconv-lite/README.md | 156 + .../iconv-lite/encodings/dbcs-codec.js | 555 ++ .../iconv-lite/encodings/dbcs-data.js | 176 + .../iconv-lite/encodings/index.js | 22 + .../iconv-lite/encodings/internal.js | 188 + .../iconv-lite/encodings/sbcs-codec.js | 72 + .../encodings/sbcs-data-generated.js | 451 + .../iconv-lite/encodings/sbcs-data.js | 174 + .../encodings/tables/big5-added.json | 122 + .../iconv-lite/encodings/tables/cp936.json | 264 + .../iconv-lite/encodings/tables/cp949.json | 273 + .../iconv-lite/encodings/tables/cp950.json | 177 + .../iconv-lite/encodings/tables/eucjp.json | 182 + .../encodings/tables/gb18030-ranges.json | 1 + .../encodings/tables/gbk-added.json | 55 + .../iconv-lite/encodings/tables/shiftjis.json | 125 + .../iconv-lite/encodings/utf16.js | 177 + .../node_modules/iconv-lite/encodings/utf7.js | 290 + .../iconv-lite/lib/bom-handling.js | 52 + .../iconv-lite/lib/extend-node.js | 217 + .../node_modules/iconv-lite/lib/index.d.ts | 24 + .../node_modules/iconv-lite/lib/index.js | 153 + .../node_modules/iconv-lite/lib/streams.js | 121 + .../node_modules/iconv-lite/package.json | 77 + .../node_modules/ignore-by-default/LICENSE | 14 + .../node_modules/ignore-by-default/README.md | 26 + .../node_modules/ignore-by-default/index.js | 12 + .../ignore-by-default/package.json | 34 + .../node_modules/inherits/LICENSE | 16 + .../node_modules/inherits/README.md | 42 + .../node_modules/inherits/inherits.js | 7 + .../node_modules/inherits/inherits_browser.js | 23 + .../node_modules/inherits/package.json | 61 + .../node_modules/ipaddr.js/LICENSE | 19 + .../node_modules/ipaddr.js/README.md | 233 + .../node_modules/ipaddr.js/ipaddr.min.js | 1 + .../node_modules/ipaddr.js/lib/ipaddr.js | 673 ++ .../node_modules/ipaddr.js/lib/ipaddr.js.d.ts | 68 + .../node_modules/ipaddr.js/package.json | 70 + .../node_modules/is-binary-path/index.d.ts | 17 + .../node_modules/is-binary-path/index.js | 7 + .../node_modules/is-binary-path/license | 9 + .../node_modules/is-binary-path/package.json | 40 + .../node_modules/is-binary-path/readme.md | 34 + .../node_modules/is-extglob/LICENSE | 21 + .../node_modules/is-extglob/README.md | 107 + .../node_modules/is-extglob/index.js | 20 + .../node_modules/is-extglob/package.json | 69 + .../node_modules/is-glob/LICENSE | 21 + .../node_modules/is-glob/README.md | 206 + .../node_modules/is-glob/index.js | 150 + .../node_modules/is-glob/package.json | 81 + .../node_modules/is-number/LICENSE | 21 + .../node_modules/is-number/README.md | 187 + .../node_modules/is-number/index.js | 18 + .../node_modules/is-number/package.json | 82 + .../node_modules/media-typer/HISTORY.md | 22 + .../node_modules/media-typer/LICENSE | 22 + .../node_modules/media-typer/README.md | 81 + .../node_modules/media-typer/index.js | 270 + .../node_modules/media-typer/package.json | 61 + .../node_modules/merge-descriptors/HISTORY.md | 21 + .../node_modules/merge-descriptors/LICENSE | 23 + .../node_modules/merge-descriptors/README.md | 48 + .../node_modules/merge-descriptors/index.js | 60 + .../merge-descriptors/package.json | 69 + .../node_modules/methods/HISTORY.md | 29 + .../node_modules/methods/LICENSE | 24 + .../node_modules/methods/README.md | 51 + .../node_modules/methods/index.js | 69 + .../node_modules/methods/package.json | 79 + .../node_modules/mime-db/HISTORY.md | 446 + .../node_modules/mime-db/LICENSE | 22 + .../node_modules/mime-db/README.md | 102 + .../node_modules/mime-db/db.json | 8176 +++++++++++++++++ .../node_modules/mime-db/index.js | 11 + .../node_modules/mime-db/package.json | 102 + .../node_modules/mime-types/HISTORY.md | 333 + .../node_modules/mime-types/LICENSE | 23 + .../node_modules/mime-types/README.md | 123 + .../node_modules/mime-types/index.js | 188 + .../node_modules/mime-types/package.json | 88 + .../node_modules/mime/.npmignore | 0 .../node_modules/mime/CHANGELOG.md | 164 + .../project_express/node_modules/mime/LICENSE | 21 + .../node_modules/mime/README.md | 90 + .../project_express/node_modules/mime/cli.js | 8 + .../project_express/node_modules/mime/mime.js | 108 + .../node_modules/mime/package.json | 73 + .../node_modules/mime/src/build.js | 53 + .../node_modules/mime/src/test.js | 60 + .../node_modules/mime/types.json | 1 + .../node_modules/minimatch/LICENSE | 15 + .../node_modules/minimatch/README.md | 230 + .../node_modules/minimatch/minimatch.js | 947 ++ .../node_modules/minimatch/package.json | 33 + .../project_express/node_modules/ms/index.js | 152 + .../node_modules/ms/license.md | 21 + .../node_modules/ms/package.json | 69 + .../project_express/node_modules/ms/readme.md | 51 + .../node_modules/negotiator/HISTORY.md | 103 + .../node_modules/negotiator/LICENSE | 24 + .../node_modules/negotiator/README.md | 203 + .../node_modules/negotiator/index.js | 124 + .../node_modules/negotiator/lib/charset.js | 169 + .../node_modules/negotiator/lib/encoding.js | 184 + .../node_modules/negotiator/lib/language.js | 179 + .../node_modules/negotiator/lib/mediaType.js | 294 + .../node_modules/negotiator/package.json | 84 + .../node_modules/nodemon/LICENSE | 21 + .../node_modules/nodemon/README.md | 423 + .../node_modules/nodemon/bin/nodemon.js | 16 + .../node_modules/nodemon/bin/windows-kill.exe | Bin 0 -> 80384 bytes .../node_modules/nodemon/doc/cli/authors.txt | 8 + .../node_modules/nodemon/doc/cli/config.txt | 44 + .../node_modules/nodemon/doc/cli/help.txt | 29 + .../node_modules/nodemon/doc/cli/logo.txt | 20 + .../node_modules/nodemon/doc/cli/options.txt | 36 + .../node_modules/nodemon/doc/cli/topics.txt | 8 + .../node_modules/nodemon/doc/cli/usage.txt | 3 + .../node_modules/nodemon/doc/cli/whoami.txt | 9 + .../node_modules/nodemon/lib/cli/index.js | 49 + .../node_modules/nodemon/lib/cli/parse.js | 230 + .../nodemon/lib/config/command.js | 43 + .../nodemon/lib/config/defaults.js | 28 + .../node_modules/nodemon/lib/config/exec.js | 225 + .../node_modules/nodemon/lib/config/index.js | 93 + .../node_modules/nodemon/lib/config/load.js | 256 + .../node_modules/nodemon/lib/help/index.js | 27 + .../node_modules/nodemon/lib/index.js | 1 + .../node_modules/nodemon/lib/monitor/index.js | 4 + .../node_modules/nodemon/lib/monitor/match.js | 276 + .../node_modules/nodemon/lib/monitor/run.js | 541 ++ .../nodemon/lib/monitor/signals.js | 34 + .../node_modules/nodemon/lib/monitor/watch.js | 239 + .../node_modules/nodemon/lib/nodemon.js | 311 + .../node_modules/nodemon/lib/rules/add.js | 89 + .../node_modules/nodemon/lib/rules/index.js | 53 + .../node_modules/nodemon/lib/rules/parse.js | 43 + .../node_modules/nodemon/lib/spawn.js | 73 + .../node_modules/nodemon/lib/utils/bus.js | 44 + .../node_modules/nodemon/lib/utils/clone.js | 40 + .../node_modules/nodemon/lib/utils/colour.js | 26 + .../node_modules/nodemon/lib/utils/index.js | 102 + .../node_modules/nodemon/lib/utils/log.js | 82 + .../node_modules/nodemon/lib/utils/merge.js | 47 + .../node_modules/nodemon/lib/version.js | 100 + .../nodemon/node_modules/debug/CHANGELOG.md | 395 + .../nodemon/node_modules/debug/LICENSE | 19 + .../nodemon/node_modules/debug/README.md | 437 + .../nodemon/node_modules/debug/node.js | 1 + .../nodemon/node_modules/debug/package.json | 51 + .../nodemon/node_modules/debug/src/browser.js | 180 + .../nodemon/node_modules/debug/src/common.js | 249 + .../nodemon/node_modules/debug/src/index.js | 12 + .../nodemon/node_modules/debug/src/node.js | 177 + .../nodemon/node_modules/ms/index.js | 162 + .../nodemon/node_modules/ms/license.md | 21 + .../nodemon/node_modules/ms/package.json | 38 + .../nodemon/node_modules/ms/readme.md | 59 + .../node_modules/nodemon/package.json | 74 + .../node_modules/nopt/.npmignore | 0 .../project_express/node_modules/nopt/LICENSE | 23 + .../node_modules/nopt/README.md | 208 + .../node_modules/nopt/bin/nopt.js | 44 + .../node_modules/nopt/examples/my-program.js | 30 + .../node_modules/nopt/lib/nopt.js | 552 ++ .../node_modules/nopt/package.json | 12 + .../node_modules/normalize-path/LICENSE | 21 + .../node_modules/normalize-path/README.md | 127 + .../node_modules/normalize-path/index.js | 35 + .../node_modules/normalize-path/package.json | 77 + .../node_modules/on-finished/HISTORY.md | 88 + .../node_modules/on-finished/LICENSE | 23 + .../node_modules/on-finished/README.md | 154 + .../node_modules/on-finished/index.js | 196 + .../node_modules/on-finished/package.json | 73 + .../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 + .../optimist/example/default_hash.js | 8 + .../optimist/example/default_singles.js | 7 + .../node_modules/optimist/example/divide.js | 8 + .../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 + .../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/parseurl/HISTORY.md | 58 + .../node_modules/parseurl/LICENSE | 24 + .../node_modules/parseurl/README.md | 133 + .../node_modules/parseurl/index.js | 158 + .../node_modules/parseurl/package.json | 81 + .../node_modules/path-to-regexp/History.md | 36 + .../node_modules/path-to-regexp/LICENSE | 21 + .../node_modules/path-to-regexp/Readme.md | 35 + .../node_modules/path-to-regexp/index.js | 129 + .../node_modules/path-to-regexp/package.json | 59 + .../node_modules/picomatch/CHANGELOG.md | 136 + .../node_modules/picomatch/LICENSE | 21 + .../node_modules/picomatch/README.md | 708 ++ .../node_modules/picomatch/index.js | 3 + .../node_modules/picomatch/lib/constants.js | 179 + .../node_modules/picomatch/lib/parse.js | 1091 +++ .../node_modules/picomatch/lib/picomatch.js | 342 + .../node_modules/picomatch/lib/scan.js | 391 + .../node_modules/picomatch/lib/utils.js | 64 + .../node_modules/picomatch/package.json | 81 + .../node_modules/proxy-addr/HISTORY.md | 155 + .../node_modules/proxy-addr/LICENSE | 22 + .../node_modules/proxy-addr/README.md | 155 + .../node_modules/proxy-addr/index.js | 327 + .../node_modules/proxy-addr/package.json | 82 + .../node_modules/pstree.remy/.travis.yml | 8 + .../node_modules/pstree.remy/LICENSE | 7 + .../node_modules/pstree.remy/README.md | 26 + .../node_modules/pstree.remy/lib/index.js | 37 + .../node_modules/pstree.remy/lib/tree.js | 37 + .../node_modules/pstree.remy/lib/utils.js | 53 + .../node_modules/pstree.remy/package.json | 33 + .../pstree.remy/tests/fixtures/index.js | 13 + .../pstree.remy/tests/fixtures/out1 | 10 + .../pstree.remy/tests/fixtures/out2 | 29 + .../pstree.remy/tests/index.test.js | 51 + .../node_modules/qs/.editorconfig | 30 + .../node_modules/qs/.eslintignore | 1 + .../project_express/node_modules/qs/.eslintrc | 21 + .../node_modules/qs/CHANGELOG.md | 256 + .../project_express/node_modules/qs/LICENSE | 28 + .../project_express/node_modules/qs/README.md | 570 ++ .../node_modules/qs/dist/qs.js | 782 ++ .../node_modules/qs/lib/formats.js | 18 + .../node_modules/qs/lib/index.js | 11 + .../node_modules/qs/lib/parse.js | 242 + .../node_modules/qs/lib/stringify.js | 269 + .../node_modules/qs/lib/utils.js | 230 + .../node_modules/qs/package.json | 87 + .../node_modules/qs/test/.eslintrc | 17 + .../node_modules/qs/test/index.js | 7 + .../node_modules/qs/test/parse.js | 676 ++ .../node_modules/qs/test/stringify.js | 679 ++ .../node_modules/qs/test/utils.js | 136 + .../node_modules/range-parser/HISTORY.md | 56 + .../node_modules/range-parser/LICENSE | 23 + .../node_modules/range-parser/README.md | 84 + .../node_modules/range-parser/index.js | 162 + .../node_modules/range-parser/package.json | 91 + .../node_modules/raw-body/HISTORY.md | 270 + .../node_modules/raw-body/LICENSE | 22 + .../node_modules/raw-body/README.md | 219 + .../node_modules/raw-body/index.d.ts | 87 + .../node_modules/raw-body/index.js | 286 + .../node_modules/raw-body/package.json | 90 + .../node_modules/readdirp/LICENSE | 21 + .../node_modules/readdirp/README.md | 122 + .../node_modules/readdirp/index.d.ts | 43 + .../node_modules/readdirp/index.js | 287 + .../node_modules/readdirp/package.json | 122 + .../node_modules/require/.npmignore | 1 + .../node_modules/require/Changelog | 136 + .../node_modules/require/LICENSE | 19 + .../node_modules/require/README.md | 75 + .../require/bin/require-command.js | 69 + .../node_modules/require/compiler.js | 162 + .../node_modules/require/example/client.js | 4 + .../node_modules/require/example/compile.js | 8 + .../node_modules/require/example/connect.js | 7 + .../node_modules/require/example/index.html | 8 + .../node_modules/require/example/package.json | 16 + .../require/example/raphael_circle.html | 4 + .../require/example/raphael_circle.js | 5 + .../node_modules/require/example/server.js | 20 + .../require/example/shared/dependency.js | 4 + .../node_modules/require/lib/getCode.js | 6 + .../require/lib/getDependencyLevels.js | 59 + .../require/lib/getRequireStatements.js | 6 + .../node_modules/require/lib/resolve.js | 72 + .../node_modules/require/package.json | 23 + .../node_modules/require/server.js | 185 + .../node_modules/safe-buffer/LICENSE | 21 + .../node_modules/safe-buffer/README.md | 584 ++ .../node_modules/safe-buffer/index.d.ts | 187 + .../node_modules/safe-buffer/index.js | 62 + .../node_modules/safe-buffer/package.json | 63 + .../node_modules/safer-buffer/LICENSE | 21 + .../safer-buffer/Porting-Buffer.md | 268 + .../node_modules/safer-buffer/Readme.md | 156 + .../node_modules/safer-buffer/dangerous.js | 58 + .../node_modules/safer-buffer/package.json | 60 + .../node_modules/safer-buffer/safer.js | 77 + .../node_modules/safer-buffer/tests.js | 406 + .../node_modules/semver/CHANGELOG.md | 39 + .../node_modules/semver/LICENSE | 15 + .../node_modules/semver/README.md | 412 + .../node_modules/semver/bin/semver | 160 + .../node_modules/semver/package.json | 28 + .../node_modules/semver/range.bnf | 16 + .../node_modules/semver/semver.js | 1483 +++ .../node_modules/send/HISTORY.md | 496 + .../project_express/node_modules/send/LICENSE | 23 + .../node_modules/send/README.md | 329 + .../node_modules/send/index.js | 1129 +++ .../send/node_modules/ms/index.js | 162 + .../send/node_modules/ms/license.md | 21 + .../send/node_modules/ms/package.json | 69 + .../send/node_modules/ms/readme.md | 60 + .../node_modules/send/package.json | 106 + .../node_modules/serve-static/HISTORY.md | 451 + .../node_modules/serve-static/LICENSE | 25 + .../node_modules/serve-static/README.md | 259 + .../node_modules/serve-static/index.js | 210 + .../node_modules/serve-static/package.json | 77 + .../node_modules/setprototypeof/LICENSE | 13 + .../node_modules/setprototypeof/README.md | 31 + .../node_modules/setprototypeof/index.d.ts | 2 + .../node_modules/setprototypeof/index.js | 17 + .../node_modules/setprototypeof/package.json | 64 + .../node_modules/setprototypeof/test/index.js | 24 + .../simple-update-notifier/LICENSE | 21 + .../simple-update-notifier/README.md | 67 + .../simple-update-notifier/build/index.d.ts | 12 + .../simple-update-notifier/build/index.js | 202 + .../node_modules/.bin/semver | 12 + .../node_modules/.bin/semver.cmd | 17 + .../node_modules/.bin/semver.ps1 | 28 + .../node_modules/semver/CHANGELOG.md | 74 + .../node_modules/semver/LICENSE | 15 + .../node_modules/semver/README.md | 499 + .../node_modules/semver/bin/semver.js | 173 + .../node_modules/semver/classes/comparator.js | 139 + .../node_modules/semver/classes/index.js | 5 + .../node_modules/semver/classes/range.js | 448 + .../node_modules/semver/classes/semver.js | 290 + .../node_modules/semver/functions/clean.js | 6 + .../node_modules/semver/functions/cmp.js | 48 + .../node_modules/semver/functions/coerce.js | 51 + .../semver/functions/compare-build.js | 7 + .../semver/functions/compare-loose.js | 3 + .../node_modules/semver/functions/compare.js | 5 + .../node_modules/semver/functions/diff.js | 25 + .../node_modules/semver/functions/eq.js | 3 + .../node_modules/semver/functions/gt.js | 3 + .../node_modules/semver/functions/gte.js | 3 + .../node_modules/semver/functions/inc.js | 15 + .../node_modules/semver/functions/lt.js | 3 + .../node_modules/semver/functions/lte.js | 3 + .../node_modules/semver/functions/major.js | 3 + .../node_modules/semver/functions/minor.js | 3 + .../node_modules/semver/functions/neq.js | 3 + .../node_modules/semver/functions/parse.js | 37 + .../node_modules/semver/functions/patch.js | 3 + .../semver/functions/prerelease.js | 6 + .../node_modules/semver/functions/rcompare.js | 3 + .../node_modules/semver/functions/rsort.js | 3 + .../semver/functions/satisfies.js | 10 + .../node_modules/semver/functions/sort.js | 3 + .../node_modules/semver/functions/valid.js | 6 + .../node_modules/semver/index.js | 64 + .../node_modules/semver/internal/constants.js | 17 + .../node_modules/semver/internal/debug.js | 9 + .../semver/internal/identifiers.js | 23 + .../node_modules/semver/internal/re.js | 179 + .../node_modules/semver/package.json | 34 + .../node_modules/semver/range.bnf | 16 + .../node_modules/semver/ranges/gtr.js | 4 + .../node_modules/semver/ranges/intersects.js | 7 + .../node_modules/semver/ranges/ltr.js | 4 + .../semver/ranges/max-satisfying.js | 25 + .../semver/ranges/min-satisfying.js | 24 + .../node_modules/semver/ranges/min-version.js | 57 + .../node_modules/semver/ranges/outside.js | 80 + .../semver/ranges/to-comparators.js | 8 + .../node_modules/semver/ranges/valid.js | 11 + .../simple-update-notifier/package.json | 97 + .../src/borderedText.ts | 12 + .../simple-update-notifier/src/cache.spec.ts | 12 + .../simple-update-notifier/src/cache.ts | 41 + .../src/getDistVersion.spec.ts | 35 + .../src/getDistVersion.ts | 29 + .../src/hasNewVersion.spec.ts | 82 + .../src/hasNewVersion.ts | 30 + .../simple-update-notifier/src/index.spec.ts | 27 + .../simple-update-notifier/src/index.ts | 28 + .../simple-update-notifier/src/isNpmOrYarn.ts | 12 + .../simple-update-notifier/src/types.ts | 7 + .../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 + .../source-map/build/assert-shim.js | 56 + .../source-map/build/mini-require.js | 152 + .../source-map/build/prefix-source-map.jsm | 20 + .../source-map/build/prefix-utils.jsm | 18 + .../source-map/build/suffix-browser.js | 8 + .../source-map/build/suffix-source-map.jsm | 6 + .../source-map/build/suffix-utils.jsm | 21 + .../source-map/build/test-prefix.js | 8 + .../source-map/build/test-suffix.js | 3 + .../node_modules/source-map/lib/source-map.js | 8 + .../source-map/lib/source-map/array-set.js | 97 + .../source-map/lib/source-map/base64-vlq.js | 142 + .../source-map/lib/source-map/base64.js | 42 + .../lib/source-map/binary-search.js | 80 + .../source-map/lib/source-map/mapping-list.js | 86 + .../lib/source-map/source-map-consumer.js | 575 ++ .../lib/source-map/source-map-generator.js | 400 + .../source-map/lib/source-map/source-node.js | 414 + .../source-map/lib/source-map/util.js | 319 + .../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/statuses/HISTORY.md | 65 + .../node_modules/statuses/LICENSE | 23 + .../node_modules/statuses/README.md | 127 + .../node_modules/statuses/codes.json | 66 + .../node_modules/statuses/index.js | 113 + .../node_modules/statuses/package.json | 90 + .../node_modules/std/Animation.js | 57 + .../node_modules/std/Changelog | 179 + .../project_express/node_modules/std/Class.js | 80 + .../project_express/node_modules/std/LICENSE | 22 + .../node_modules/std/ListPromise.js | 47 + .../node_modules/std/Logger.js | 81 + .../node_modules/std/Promise.js | 40 + .../node_modules/std/Publisher.js | 28 + .../node_modules/std/README.md | 16 + .../node_modules/std/arrayToObject.js | 5 + .../node_modules/std/assert/deepEqual.js | 88 + .../node_modules/std/asyncEach.js | 63 + .../node_modules/std/asyncMap.js | 27 + .../node_modules/std/base64.js | 128 + .../project_express/node_modules/std/bind.js | 50 + .../node_modules/std/blockFunction.js | 44 + .../node_modules/std/browser.js | 119 + .../project_express/node_modules/std/check.js | 3 + .../node_modules/std/client.js | 87 + .../project_express/node_modules/std/clip.js | 3 + .../node_modules/std/cookie.js | 33 + .../project_express/node_modules/std/copy.js | 10 + .../project_express/node_modules/std/crc32.js | 28 + .../node_modules/std/create.js | 22 + .../project_express/node_modules/std/curry.js | 10 + .../node_modules/std/defineGetter.js | 29 + .../project_express/node_modules/std/delay.js | 51 + .../node_modules/std/delayed.js | 11 + .../project_express/node_modules/std/each.js | 20 + .../node_modules/std/extend.js | 40 + .../node_modules/std/filter.js | 38 + .../project_express/node_modules/std/find.js | 7 + .../node_modules/std/flatten.js | 3 + .../project_express/node_modules/std/flip.js | 5 + .../project_express/node_modules/std/index.js | 20 + .../node_modules/std/inverse.js | 7 + .../node_modules/std/invoke.js | 19 + .../node_modules/std/invokeWith.js | 17 + .../node_modules/std/isArguments.js | 3 + .../node_modules/std/isArray.js | 12 + .../node_modules/std/isFunction.js | 3 + .../node_modules/std/isObject.js | 3 + .../project_express/node_modules/std/json.js | 482 + .../project_express/node_modules/std/keys.js | 14 + .../project_express/node_modules/std/last.js | 6 + .../project_express/node_modules/std/map.js | 13 + .../project_express/node_modules/std/merge.js | 7 + .../node_modules/std/nextTick.js | 14 + .../project_express/node_modules/std/once.js | 13 + .../node_modules/std/options.js | 9 + .../project_express/node_modules/std/pack.js | 349 + .../node_modules/std/package.json | 17 + .../node_modules/std/parallel.js | 17 + .../project_express/node_modules/std/popup.js | 26 + .../project_express/node_modules/std/proto.js | 39 + .../project_express/node_modules/std/rand.js | 3 + .../node_modules/std/recall.js | 4 + .../node_modules/std/remove.js | 8 + .../node_modules/std/repeat.js | 4 + .../project_express/node_modules/std/round.js | 7 + .../node_modules/std/router.js | 71 + .../project_express/node_modules/std/slice.js | 12 + .../project_express/node_modules/std/strip.js | 5 + .../project_express/node_modules/std/sum.js | 8 + .../node_modules/std/throttle.js | 14 + .../project_express/node_modules/std/time.js | 109 + .../project_express/node_modules/std/trim.js | 4 + .../node_modules/std/unique.js | 22 + .../node_modules/std/unpack.js | 361 + .../project_express/node_modules/std/url.js | 112 + .../node_modules/std/utf8_encode.js | 47 + .../node_modules/std/waitFor.js | 13 + .../project_express/node_modules/std/xhr.js | 89 + .../node_modules/supports-color/browser.js | 5 + .../node_modules/supports-color/index.js | 131 + .../node_modules/supports-color/license | 9 + .../node_modules/supports-color/package.json | 53 + .../node_modules/supports-color/readme.md | 66 + .../node_modules/to-regex-range/LICENSE | 21 + .../node_modules/to-regex-range/README.md | 305 + .../node_modules/to-regex-range/index.js | 288 + .../node_modules/to-regex-range/package.json | 88 + .../node_modules/toidentifier/LICENSE | 21 + .../node_modules/toidentifier/README.md | 61 + .../node_modules/toidentifier/index.js | 30 + .../node_modules/toidentifier/package.json | 76 + .../node_modules/touch/LICENSE | 15 + .../node_modules/touch/README.md | 52 + .../node_modules/touch/bin/nodetouch.js | 112 + .../node_modules/touch/index.js | 224 + .../node_modules/touch/package.json | 28 + .../node_modules/type-is/HISTORY.md | 259 + .../node_modules/type-is/LICENSE | 23 + .../node_modules/type-is/README.md | 170 + .../node_modules/type-is/index.js | 266 + .../node_modules/type-is/package.json | 85 + .../node_modules/uglify-js/.npmignore | 2 + .../node_modules/uglify-js/LICENSE | 29 + .../node_modules/uglify-js/README.md | 567 ++ .../node_modules/uglify-js/bin/uglifyjs | 398 + .../node_modules/uglify-js/lib/ast.js | 985 ++ .../node_modules/uglify-js/lib/compress.js | 1985 ++++ .../node_modules/uglify-js/lib/mozilla-ast.js | 267 + .../node_modules/uglify-js/lib/output.js | 1225 +++ .../node_modules/uglify-js/lib/parse.js | 1401 +++ .../node_modules/uglify-js/lib/scope.js | 580 ++ .../node_modules/uglify-js/lib/sourcemap.js | 81 + .../node_modules/uglify-js/lib/transform.js | 218 + .../node_modules/uglify-js/lib/utils.js | 288 + .../node_modules/uglify-js/package.json | 26 + .../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 | 40 + .../uglify-js/test/compress/sequences.js | 161 + .../uglify-js/test/compress/switch.js | 260 + .../uglify-js/test/compress/typeof.js | 25 + .../node_modules/uglify-js/test/run-tests.js | 170 + .../node_modules/uglify-js/tools/node.js | 165 + .../undefsafe/.github/workflows/release.yml | 25 + .../node_modules/undefsafe/.jscsrc | 13 + .../node_modules/undefsafe/.jshintrc | 16 + .../node_modules/undefsafe/.travis.yml | 18 + .../node_modules/undefsafe/LICENSE | 22 + .../node_modules/undefsafe/README.md | 63 + .../node_modules/undefsafe/example.js | 14 + .../node_modules/undefsafe/lib/undefsafe.js | 125 + .../node_modules/undefsafe/package.json | 34 + .../node_modules/unpipe/HISTORY.md | 4 + .../node_modules/unpipe/LICENSE | 22 + .../node_modules/unpipe/README.md | 43 + .../node_modules/unpipe/index.js | 69 + .../node_modules/unpipe/package.json | 63 + .../node_modules/utils-merge/.npmignore | 9 + .../node_modules/utils-merge/LICENSE | 20 + .../node_modules/utils-merge/README.md | 34 + .../node_modules/utils-merge/index.js | 23 + .../node_modules/utils-merge/package.json | 66 + .../node_modules/vary/HISTORY.md | 39 + .../project_express/node_modules/vary/LICENSE | 22 + .../node_modules/vary/README.md | 101 + .../node_modules/vary/index.js | 149 + .../node_modules/vary/package.json | 78 + .../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 + .../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 + homework8/project_express/package-lock.json | 1567 ++++ homework8/project_express/package.json | 17 + .../public/copy/js/CartComponent.js | 94 + .../public/copy/js/ErrorComp.js | 20 + .../public/copy/js/FilterComp.js | 13 + .../public/copy/js/ProductComponent.js | 45 + .../project_express/public/copy/js/main.js | 254 + .../public/css/images/subscribe.jpg | Bin 0 -> 131033 bytes .../project_express/public/css/normalize.css | 349 + .../project_express/public/css/style.css | 785 ++ .../project_express/public/images/bars.png | Bin 0 -> 174 bytes .../project_express/public/images/cart.png | Bin 0 -> 716 bytes .../project_express/public/images/cart.svg | 5 + .../public/images/chevronLeft.svg | 3 + .../public/images/chevronRight.svg | 3 + .../public/images/featured/1.jpg | Bin 0 -> 93945 bytes .../public/images/featured/2.jpg | Bin 0 -> 50693 bytes .../public/images/featured/3.jpg | Bin 0 -> 80895 bytes .../public/images/featured/4.jpg | Bin 0 -> 51885 bytes .../public/images/featured/5.jpg | Bin 0 -> 93122 bytes .../public/images/featured/6.jpg | Bin 0 -> 96512 bytes .../project_express/public/images/filter.svg | 3 + .../public/images/filterArrow.svg | 3 + .../public/images/filterHover.svg | 3 + .../project_express/public/images/logo.png | Bin 0 -> 2364 bytes .../project_express/public/images/search.png | Bin 0 -> 667 bytes .../public/images/services/assurance.svg | 3 + .../public/images/services/delivery.svg | 3 + .../public/images/services/discount.svg | 3 + .../public/images/subscribe.jpg | Bin 0 -> 131033 bytes .../public/images/subscribeUser.png | Bin 0 -> 17526 bytes .../project_express/public/images/user.png | Bin 0 -> 718 bytes homework8/project_express/public/index.html | 250 + homework8/project_express/public/js/main.js | 62 + .../public/js/mycartComponent.js | 91 + .../public/js/myproductComponent.js | 55 + homework8/project_express/server/cart.js | 24 + .../project_express/server/cartRouter.js | 25 + .../project_express/server/db/products.json | 38 + .../project_express/server/db/userCart.json | 20 + homework8/project_express/server/handler.js | 27 + homework8/project_express/server/server.js | 32 + 878 files changed, 111631 insertions(+) create mode 100644 homework8/project_express/.idea/.gitignore create mode 100644 homework8/project_express/.idea/jsLibraryMappings.xml create mode 100644 homework8/project_express/.idea/misc.xml create mode 100644 homework8/project_express/.idea/modules.xml create mode 100644 homework8/project_express/.idea/project_express.iml create mode 100644 homework8/project_express/node_modules/.bin/mime create mode 100644 homework8/project_express/node_modules/.bin/mime.cmd create mode 100644 homework8/project_express/node_modules/.bin/mime.ps1 create mode 100644 homework8/project_express/node_modules/.bin/nodemon create mode 100644 homework8/project_express/node_modules/.bin/nodemon.cmd create mode 100644 homework8/project_express/node_modules/.bin/nodemon.ps1 create mode 100644 homework8/project_express/node_modules/.bin/nodetouch create mode 100644 homework8/project_express/node_modules/.bin/nodetouch.cmd create mode 100644 homework8/project_express/node_modules/.bin/nodetouch.ps1 create mode 100644 homework8/project_express/node_modules/.bin/nopt create mode 100644 homework8/project_express/node_modules/.bin/nopt.cmd create mode 100644 homework8/project_express/node_modules/.bin/nopt.ps1 create mode 100644 homework8/project_express/node_modules/.bin/require create mode 100644 homework8/project_express/node_modules/.bin/require.cmd create mode 100644 homework8/project_express/node_modules/.bin/require.ps1 create mode 100644 homework8/project_express/node_modules/.bin/semver create mode 100644 homework8/project_express/node_modules/.bin/semver.cmd create mode 100644 homework8/project_express/node_modules/.bin/semver.ps1 create mode 100644 homework8/project_express/node_modules/.bin/uglifyjs create mode 100644 homework8/project_express/node_modules/.bin/uglifyjs.cmd create mode 100644 homework8/project_express/node_modules/.bin/uglifyjs.ps1 create mode 100644 homework8/project_express/node_modules/.package-lock.json create mode 100644 homework8/project_express/node_modules/abbrev/LICENSE create mode 100644 homework8/project_express/node_modules/abbrev/README.md create mode 100644 homework8/project_express/node_modules/abbrev/abbrev.js create mode 100644 homework8/project_express/node_modules/abbrev/package.json create mode 100644 homework8/project_express/node_modules/accepts/HISTORY.md create mode 100644 homework8/project_express/node_modules/accepts/LICENSE create mode 100644 homework8/project_express/node_modules/accepts/README.md create mode 100644 homework8/project_express/node_modules/accepts/index.js create mode 100644 homework8/project_express/node_modules/accepts/package.json create mode 100644 homework8/project_express/node_modules/amdefine/LICENSE create mode 100644 homework8/project_express/node_modules/amdefine/README.md create mode 100644 homework8/project_express/node_modules/amdefine/amdefine.js create mode 100644 homework8/project_express/node_modules/amdefine/intercept.js create mode 100644 homework8/project_express/node_modules/amdefine/package.json create mode 100644 homework8/project_express/node_modules/anymatch/LICENSE create mode 100644 homework8/project_express/node_modules/anymatch/README.md create mode 100644 homework8/project_express/node_modules/anymatch/index.d.ts create mode 100644 homework8/project_express/node_modules/anymatch/index.js create mode 100644 homework8/project_express/node_modules/anymatch/package.json create mode 100644 homework8/project_express/node_modules/array-flatten/LICENSE create mode 100644 homework8/project_express/node_modules/array-flatten/README.md create mode 100644 homework8/project_express/node_modules/array-flatten/array-flatten.js create mode 100644 homework8/project_express/node_modules/array-flatten/package.json create mode 100644 homework8/project_express/node_modules/async/LICENSE create mode 100644 homework8/project_express/node_modules/async/README.md create mode 100644 homework8/project_express/node_modules/async/component.json create mode 100644 homework8/project_express/node_modules/async/lib/async.js create mode 100644 homework8/project_express/node_modules/async/package.json create mode 100644 homework8/project_express/node_modules/balanced-match/.github/FUNDING.yml create mode 100644 homework8/project_express/node_modules/balanced-match/LICENSE.md create mode 100644 homework8/project_express/node_modules/balanced-match/README.md create mode 100644 homework8/project_express/node_modules/balanced-match/index.js create mode 100644 homework8/project_express/node_modules/balanced-match/package.json create mode 100644 homework8/project_express/node_modules/binary-extensions/binary-extensions.json create mode 100644 homework8/project_express/node_modules/binary-extensions/binary-extensions.json.d.ts create mode 100644 homework8/project_express/node_modules/binary-extensions/index.d.ts create mode 100644 homework8/project_express/node_modules/binary-extensions/index.js create mode 100644 homework8/project_express/node_modules/binary-extensions/license create mode 100644 homework8/project_express/node_modules/binary-extensions/package.json create mode 100644 homework8/project_express/node_modules/binary-extensions/readme.md create mode 100644 homework8/project_express/node_modules/body-parser/HISTORY.md create mode 100644 homework8/project_express/node_modules/body-parser/LICENSE create mode 100644 homework8/project_express/node_modules/body-parser/README.md create mode 100644 homework8/project_express/node_modules/body-parser/index.js create mode 100644 homework8/project_express/node_modules/body-parser/lib/read.js create mode 100644 homework8/project_express/node_modules/body-parser/lib/types/json.js create mode 100644 homework8/project_express/node_modules/body-parser/lib/types/raw.js create mode 100644 homework8/project_express/node_modules/body-parser/lib/types/text.js create mode 100644 homework8/project_express/node_modules/body-parser/lib/types/urlencoded.js create mode 100644 homework8/project_express/node_modules/body-parser/package.json create mode 100644 homework8/project_express/node_modules/brace-expansion/LICENSE create mode 100644 homework8/project_express/node_modules/brace-expansion/README.md create mode 100644 homework8/project_express/node_modules/brace-expansion/index.js create mode 100644 homework8/project_express/node_modules/brace-expansion/package.json create mode 100644 homework8/project_express/node_modules/braces/CHANGELOG.md create mode 100644 homework8/project_express/node_modules/braces/LICENSE create mode 100644 homework8/project_express/node_modules/braces/README.md create mode 100644 homework8/project_express/node_modules/braces/index.js create mode 100644 homework8/project_express/node_modules/braces/lib/compile.js create mode 100644 homework8/project_express/node_modules/braces/lib/constants.js create mode 100644 homework8/project_express/node_modules/braces/lib/expand.js create mode 100644 homework8/project_express/node_modules/braces/lib/parse.js create mode 100644 homework8/project_express/node_modules/braces/lib/stringify.js create mode 100644 homework8/project_express/node_modules/braces/lib/utils.js create mode 100644 homework8/project_express/node_modules/braces/package.json create mode 100644 homework8/project_express/node_modules/bytes/History.md create mode 100644 homework8/project_express/node_modules/bytes/LICENSE create mode 100644 homework8/project_express/node_modules/bytes/Readme.md create mode 100644 homework8/project_express/node_modules/bytes/index.js create mode 100644 homework8/project_express/node_modules/bytes/package.json create mode 100644 homework8/project_express/node_modules/chokidar/LICENSE create mode 100644 homework8/project_express/node_modules/chokidar/README.md create mode 100644 homework8/project_express/node_modules/chokidar/index.js create mode 100644 homework8/project_express/node_modules/chokidar/lib/constants.js create mode 100644 homework8/project_express/node_modules/chokidar/lib/fsevents-handler.js create mode 100644 homework8/project_express/node_modules/chokidar/lib/nodefs-handler.js create mode 100644 homework8/project_express/node_modules/chokidar/package.json create mode 100644 homework8/project_express/node_modules/chokidar/types/index.d.ts create mode 100644 homework8/project_express/node_modules/concat-map/.travis.yml create mode 100644 homework8/project_express/node_modules/concat-map/LICENSE create mode 100644 homework8/project_express/node_modules/concat-map/README.markdown create mode 100644 homework8/project_express/node_modules/concat-map/example/map.js create mode 100644 homework8/project_express/node_modules/concat-map/index.js create mode 100644 homework8/project_express/node_modules/concat-map/package.json create mode 100644 homework8/project_express/node_modules/concat-map/test/map.js create mode 100644 homework8/project_express/node_modules/content-disposition/HISTORY.md create mode 100644 homework8/project_express/node_modules/content-disposition/LICENSE create mode 100644 homework8/project_express/node_modules/content-disposition/README.md create mode 100644 homework8/project_express/node_modules/content-disposition/index.js create mode 100644 homework8/project_express/node_modules/content-disposition/package.json create mode 100644 homework8/project_express/node_modules/content-type/HISTORY.md create mode 100644 homework8/project_express/node_modules/content-type/LICENSE create mode 100644 homework8/project_express/node_modules/content-type/README.md create mode 100644 homework8/project_express/node_modules/content-type/index.js create mode 100644 homework8/project_express/node_modules/content-type/package.json create mode 100644 homework8/project_express/node_modules/cookie-signature/.npmignore create mode 100644 homework8/project_express/node_modules/cookie-signature/History.md create mode 100644 homework8/project_express/node_modules/cookie-signature/Readme.md create mode 100644 homework8/project_express/node_modules/cookie-signature/index.js create mode 100644 homework8/project_express/node_modules/cookie-signature/package.json create mode 100644 homework8/project_express/node_modules/cookie/HISTORY.md create mode 100644 homework8/project_express/node_modules/cookie/LICENSE create mode 100644 homework8/project_express/node_modules/cookie/README.md create mode 100644 homework8/project_express/node_modules/cookie/index.js create mode 100644 homework8/project_express/node_modules/cookie/package.json create mode 100644 homework8/project_express/node_modules/debug/.coveralls.yml create mode 100644 homework8/project_express/node_modules/debug/.eslintrc create mode 100644 homework8/project_express/node_modules/debug/.npmignore create mode 100644 homework8/project_express/node_modules/debug/.travis.yml create mode 100644 homework8/project_express/node_modules/debug/CHANGELOG.md create mode 100644 homework8/project_express/node_modules/debug/LICENSE create mode 100644 homework8/project_express/node_modules/debug/Makefile create mode 100644 homework8/project_express/node_modules/debug/README.md create mode 100644 homework8/project_express/node_modules/debug/component.json create mode 100644 homework8/project_express/node_modules/debug/karma.conf.js create mode 100644 homework8/project_express/node_modules/debug/node.js create mode 100644 homework8/project_express/node_modules/debug/package.json create mode 100644 homework8/project_express/node_modules/debug/src/browser.js create mode 100644 homework8/project_express/node_modules/debug/src/debug.js create mode 100644 homework8/project_express/node_modules/debug/src/index.js create mode 100644 homework8/project_express/node_modules/debug/src/inspector-log.js create mode 100644 homework8/project_express/node_modules/debug/src/node.js create mode 100644 homework8/project_express/node_modules/depd/History.md create mode 100644 homework8/project_express/node_modules/depd/LICENSE create mode 100644 homework8/project_express/node_modules/depd/Readme.md create mode 100644 homework8/project_express/node_modules/depd/index.js create mode 100644 homework8/project_express/node_modules/depd/lib/browser/index.js create mode 100644 homework8/project_express/node_modules/depd/lib/compat/callsite-tostring.js create mode 100644 homework8/project_express/node_modules/depd/lib/compat/event-listener-count.js create mode 100644 homework8/project_express/node_modules/depd/lib/compat/index.js create mode 100644 homework8/project_express/node_modules/depd/package.json create mode 100644 homework8/project_express/node_modules/destroy/LICENSE create mode 100644 homework8/project_express/node_modules/destroy/README.md create mode 100644 homework8/project_express/node_modules/destroy/index.js create mode 100644 homework8/project_express/node_modules/destroy/package.json create mode 100644 homework8/project_express/node_modules/ee-first/LICENSE create mode 100644 homework8/project_express/node_modules/ee-first/README.md create mode 100644 homework8/project_express/node_modules/ee-first/index.js create mode 100644 homework8/project_express/node_modules/ee-first/package.json create mode 100644 homework8/project_express/node_modules/encodeurl/HISTORY.md create mode 100644 homework8/project_express/node_modules/encodeurl/LICENSE create mode 100644 homework8/project_express/node_modules/encodeurl/README.md create mode 100644 homework8/project_express/node_modules/encodeurl/index.js create mode 100644 homework8/project_express/node_modules/encodeurl/package.json create mode 100644 homework8/project_express/node_modules/escape-html/LICENSE create mode 100644 homework8/project_express/node_modules/escape-html/Readme.md create mode 100644 homework8/project_express/node_modules/escape-html/index.js create mode 100644 homework8/project_express/node_modules/escape-html/package.json create mode 100644 homework8/project_express/node_modules/etag/HISTORY.md create mode 100644 homework8/project_express/node_modules/etag/LICENSE create mode 100644 homework8/project_express/node_modules/etag/README.md create mode 100644 homework8/project_express/node_modules/etag/index.js create mode 100644 homework8/project_express/node_modules/etag/package.json create mode 100644 homework8/project_express/node_modules/express/History.md create mode 100644 homework8/project_express/node_modules/express/LICENSE create mode 100644 homework8/project_express/node_modules/express/Readme.md create mode 100644 homework8/project_express/node_modules/express/index.js create mode 100644 homework8/project_express/node_modules/express/lib/application.js create mode 100644 homework8/project_express/node_modules/express/lib/express.js create mode 100644 homework8/project_express/node_modules/express/lib/middleware/init.js create mode 100644 homework8/project_express/node_modules/express/lib/middleware/query.js create mode 100644 homework8/project_express/node_modules/express/lib/request.js create mode 100644 homework8/project_express/node_modules/express/lib/response.js create mode 100644 homework8/project_express/node_modules/express/lib/router/index.js create mode 100644 homework8/project_express/node_modules/express/lib/router/layer.js create mode 100644 homework8/project_express/node_modules/express/lib/router/route.js create mode 100644 homework8/project_express/node_modules/express/lib/utils.js create mode 100644 homework8/project_express/node_modules/express/lib/view.js create mode 100644 homework8/project_express/node_modules/express/package.json create mode 100644 homework8/project_express/node_modules/fill-range/LICENSE create mode 100644 homework8/project_express/node_modules/fill-range/README.md create mode 100644 homework8/project_express/node_modules/fill-range/index.js create mode 100644 homework8/project_express/node_modules/fill-range/package.json create mode 100644 homework8/project_express/node_modules/finalhandler/HISTORY.md create mode 100644 homework8/project_express/node_modules/finalhandler/LICENSE create mode 100644 homework8/project_express/node_modules/finalhandler/README.md create mode 100644 homework8/project_express/node_modules/finalhandler/index.js create mode 100644 homework8/project_express/node_modules/finalhandler/package.json create mode 100644 homework8/project_express/node_modules/forwarded/HISTORY.md create mode 100644 homework8/project_express/node_modules/forwarded/LICENSE create mode 100644 homework8/project_express/node_modules/forwarded/README.md create mode 100644 homework8/project_express/node_modules/forwarded/index.js create mode 100644 homework8/project_express/node_modules/forwarded/package.json create mode 100644 homework8/project_express/node_modules/fresh/HISTORY.md create mode 100644 homework8/project_express/node_modules/fresh/LICENSE create mode 100644 homework8/project_express/node_modules/fresh/README.md create mode 100644 homework8/project_express/node_modules/fresh/index.js create mode 100644 homework8/project_express/node_modules/fresh/package.json create mode 100644 homework8/project_express/node_modules/glob-parent/CHANGELOG.md create mode 100644 homework8/project_express/node_modules/glob-parent/LICENSE create mode 100644 homework8/project_express/node_modules/glob-parent/README.md create mode 100644 homework8/project_express/node_modules/glob-parent/index.js create mode 100644 homework8/project_express/node_modules/glob-parent/package.json create mode 100644 homework8/project_express/node_modules/has-flag/index.js create mode 100644 homework8/project_express/node_modules/has-flag/license create mode 100644 homework8/project_express/node_modules/has-flag/package.json create mode 100644 homework8/project_express/node_modules/has-flag/readme.md create mode 100644 homework8/project_express/node_modules/http-errors/HISTORY.md create mode 100644 homework8/project_express/node_modules/http-errors/LICENSE create mode 100644 homework8/project_express/node_modules/http-errors/README.md create mode 100644 homework8/project_express/node_modules/http-errors/index.js create mode 100644 homework8/project_express/node_modules/http-errors/package.json create mode 100644 homework8/project_express/node_modules/iconv-lite/Changelog.md create mode 100644 homework8/project_express/node_modules/iconv-lite/LICENSE create mode 100644 homework8/project_express/node_modules/iconv-lite/README.md create mode 100644 homework8/project_express/node_modules/iconv-lite/encodings/dbcs-codec.js create mode 100644 homework8/project_express/node_modules/iconv-lite/encodings/dbcs-data.js create mode 100644 homework8/project_express/node_modules/iconv-lite/encodings/index.js create mode 100644 homework8/project_express/node_modules/iconv-lite/encodings/internal.js create mode 100644 homework8/project_express/node_modules/iconv-lite/encodings/sbcs-codec.js create mode 100644 homework8/project_express/node_modules/iconv-lite/encodings/sbcs-data-generated.js create mode 100644 homework8/project_express/node_modules/iconv-lite/encodings/sbcs-data.js create mode 100644 homework8/project_express/node_modules/iconv-lite/encodings/tables/big5-added.json create mode 100644 homework8/project_express/node_modules/iconv-lite/encodings/tables/cp936.json create mode 100644 homework8/project_express/node_modules/iconv-lite/encodings/tables/cp949.json create mode 100644 homework8/project_express/node_modules/iconv-lite/encodings/tables/cp950.json create mode 100644 homework8/project_express/node_modules/iconv-lite/encodings/tables/eucjp.json create mode 100644 homework8/project_express/node_modules/iconv-lite/encodings/tables/gb18030-ranges.json create mode 100644 homework8/project_express/node_modules/iconv-lite/encodings/tables/gbk-added.json create mode 100644 homework8/project_express/node_modules/iconv-lite/encodings/tables/shiftjis.json create mode 100644 homework8/project_express/node_modules/iconv-lite/encodings/utf16.js create mode 100644 homework8/project_express/node_modules/iconv-lite/encodings/utf7.js create mode 100644 homework8/project_express/node_modules/iconv-lite/lib/bom-handling.js create mode 100644 homework8/project_express/node_modules/iconv-lite/lib/extend-node.js create mode 100644 homework8/project_express/node_modules/iconv-lite/lib/index.d.ts create mode 100644 homework8/project_express/node_modules/iconv-lite/lib/index.js create mode 100644 homework8/project_express/node_modules/iconv-lite/lib/streams.js create mode 100644 homework8/project_express/node_modules/iconv-lite/package.json create mode 100644 homework8/project_express/node_modules/ignore-by-default/LICENSE create mode 100644 homework8/project_express/node_modules/ignore-by-default/README.md create mode 100644 homework8/project_express/node_modules/ignore-by-default/index.js create mode 100644 homework8/project_express/node_modules/ignore-by-default/package.json create mode 100644 homework8/project_express/node_modules/inherits/LICENSE create mode 100644 homework8/project_express/node_modules/inherits/README.md create mode 100644 homework8/project_express/node_modules/inherits/inherits.js create mode 100644 homework8/project_express/node_modules/inherits/inherits_browser.js create mode 100644 homework8/project_express/node_modules/inherits/package.json create mode 100644 homework8/project_express/node_modules/ipaddr.js/LICENSE create mode 100644 homework8/project_express/node_modules/ipaddr.js/README.md create mode 100644 homework8/project_express/node_modules/ipaddr.js/ipaddr.min.js create mode 100644 homework8/project_express/node_modules/ipaddr.js/lib/ipaddr.js create mode 100644 homework8/project_express/node_modules/ipaddr.js/lib/ipaddr.js.d.ts create mode 100644 homework8/project_express/node_modules/ipaddr.js/package.json create mode 100644 homework8/project_express/node_modules/is-binary-path/index.d.ts create mode 100644 homework8/project_express/node_modules/is-binary-path/index.js create mode 100644 homework8/project_express/node_modules/is-binary-path/license create mode 100644 homework8/project_express/node_modules/is-binary-path/package.json create mode 100644 homework8/project_express/node_modules/is-binary-path/readme.md create mode 100644 homework8/project_express/node_modules/is-extglob/LICENSE create mode 100644 homework8/project_express/node_modules/is-extglob/README.md create mode 100644 homework8/project_express/node_modules/is-extglob/index.js create mode 100644 homework8/project_express/node_modules/is-extglob/package.json create mode 100644 homework8/project_express/node_modules/is-glob/LICENSE create mode 100644 homework8/project_express/node_modules/is-glob/README.md create mode 100644 homework8/project_express/node_modules/is-glob/index.js create mode 100644 homework8/project_express/node_modules/is-glob/package.json create mode 100644 homework8/project_express/node_modules/is-number/LICENSE create mode 100644 homework8/project_express/node_modules/is-number/README.md create mode 100644 homework8/project_express/node_modules/is-number/index.js create mode 100644 homework8/project_express/node_modules/is-number/package.json create mode 100644 homework8/project_express/node_modules/media-typer/HISTORY.md create mode 100644 homework8/project_express/node_modules/media-typer/LICENSE create mode 100644 homework8/project_express/node_modules/media-typer/README.md create mode 100644 homework8/project_express/node_modules/media-typer/index.js create mode 100644 homework8/project_express/node_modules/media-typer/package.json create mode 100644 homework8/project_express/node_modules/merge-descriptors/HISTORY.md create mode 100644 homework8/project_express/node_modules/merge-descriptors/LICENSE create mode 100644 homework8/project_express/node_modules/merge-descriptors/README.md create mode 100644 homework8/project_express/node_modules/merge-descriptors/index.js create mode 100644 homework8/project_express/node_modules/merge-descriptors/package.json create mode 100644 homework8/project_express/node_modules/methods/HISTORY.md create mode 100644 homework8/project_express/node_modules/methods/LICENSE create mode 100644 homework8/project_express/node_modules/methods/README.md create mode 100644 homework8/project_express/node_modules/methods/index.js create mode 100644 homework8/project_express/node_modules/methods/package.json create mode 100644 homework8/project_express/node_modules/mime-db/HISTORY.md create mode 100644 homework8/project_express/node_modules/mime-db/LICENSE create mode 100644 homework8/project_express/node_modules/mime-db/README.md create mode 100644 homework8/project_express/node_modules/mime-db/db.json create mode 100644 homework8/project_express/node_modules/mime-db/index.js create mode 100644 homework8/project_express/node_modules/mime-db/package.json create mode 100644 homework8/project_express/node_modules/mime-types/HISTORY.md create mode 100644 homework8/project_express/node_modules/mime-types/LICENSE create mode 100644 homework8/project_express/node_modules/mime-types/README.md create mode 100644 homework8/project_express/node_modules/mime-types/index.js create mode 100644 homework8/project_express/node_modules/mime-types/package.json create mode 100644 homework8/project_express/node_modules/mime/.npmignore create mode 100644 homework8/project_express/node_modules/mime/CHANGELOG.md create mode 100644 homework8/project_express/node_modules/mime/LICENSE create mode 100644 homework8/project_express/node_modules/mime/README.md create mode 100644 homework8/project_express/node_modules/mime/cli.js create mode 100644 homework8/project_express/node_modules/mime/mime.js create mode 100644 homework8/project_express/node_modules/mime/package.json create mode 100644 homework8/project_express/node_modules/mime/src/build.js create mode 100644 homework8/project_express/node_modules/mime/src/test.js create mode 100644 homework8/project_express/node_modules/mime/types.json create mode 100644 homework8/project_express/node_modules/minimatch/LICENSE create mode 100644 homework8/project_express/node_modules/minimatch/README.md create mode 100644 homework8/project_express/node_modules/minimatch/minimatch.js create mode 100644 homework8/project_express/node_modules/minimatch/package.json create mode 100644 homework8/project_express/node_modules/ms/index.js create mode 100644 homework8/project_express/node_modules/ms/license.md create mode 100644 homework8/project_express/node_modules/ms/package.json create mode 100644 homework8/project_express/node_modules/ms/readme.md create mode 100644 homework8/project_express/node_modules/negotiator/HISTORY.md create mode 100644 homework8/project_express/node_modules/negotiator/LICENSE create mode 100644 homework8/project_express/node_modules/negotiator/README.md create mode 100644 homework8/project_express/node_modules/negotiator/index.js create mode 100644 homework8/project_express/node_modules/negotiator/lib/charset.js create mode 100644 homework8/project_express/node_modules/negotiator/lib/encoding.js create mode 100644 homework8/project_express/node_modules/negotiator/lib/language.js create mode 100644 homework8/project_express/node_modules/negotiator/lib/mediaType.js create mode 100644 homework8/project_express/node_modules/negotiator/package.json create mode 100644 homework8/project_express/node_modules/nodemon/LICENSE create mode 100644 homework8/project_express/node_modules/nodemon/README.md create mode 100644 homework8/project_express/node_modules/nodemon/bin/nodemon.js create mode 100644 homework8/project_express/node_modules/nodemon/bin/windows-kill.exe create mode 100644 homework8/project_express/node_modules/nodemon/doc/cli/authors.txt create mode 100644 homework8/project_express/node_modules/nodemon/doc/cli/config.txt create mode 100644 homework8/project_express/node_modules/nodemon/doc/cli/help.txt create mode 100644 homework8/project_express/node_modules/nodemon/doc/cli/logo.txt create mode 100644 homework8/project_express/node_modules/nodemon/doc/cli/options.txt create mode 100644 homework8/project_express/node_modules/nodemon/doc/cli/topics.txt create mode 100644 homework8/project_express/node_modules/nodemon/doc/cli/usage.txt create mode 100644 homework8/project_express/node_modules/nodemon/doc/cli/whoami.txt create mode 100644 homework8/project_express/node_modules/nodemon/lib/cli/index.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/cli/parse.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/config/command.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/config/defaults.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/config/exec.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/config/index.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/config/load.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/help/index.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/index.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/monitor/index.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/monitor/match.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/monitor/run.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/monitor/signals.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/monitor/watch.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/nodemon.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/rules/add.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/rules/index.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/rules/parse.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/spawn.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/utils/bus.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/utils/clone.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/utils/colour.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/utils/index.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/utils/log.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/utils/merge.js create mode 100644 homework8/project_express/node_modules/nodemon/lib/version.js create mode 100644 homework8/project_express/node_modules/nodemon/node_modules/debug/CHANGELOG.md create mode 100644 homework8/project_express/node_modules/nodemon/node_modules/debug/LICENSE create mode 100644 homework8/project_express/node_modules/nodemon/node_modules/debug/README.md create mode 100644 homework8/project_express/node_modules/nodemon/node_modules/debug/node.js create mode 100644 homework8/project_express/node_modules/nodemon/node_modules/debug/package.json create mode 100644 homework8/project_express/node_modules/nodemon/node_modules/debug/src/browser.js create mode 100644 homework8/project_express/node_modules/nodemon/node_modules/debug/src/common.js create mode 100644 homework8/project_express/node_modules/nodemon/node_modules/debug/src/index.js create mode 100644 homework8/project_express/node_modules/nodemon/node_modules/debug/src/node.js create mode 100644 homework8/project_express/node_modules/nodemon/node_modules/ms/index.js create mode 100644 homework8/project_express/node_modules/nodemon/node_modules/ms/license.md create mode 100644 homework8/project_express/node_modules/nodemon/node_modules/ms/package.json create mode 100644 homework8/project_express/node_modules/nodemon/node_modules/ms/readme.md create mode 100644 homework8/project_express/node_modules/nodemon/package.json create mode 100644 homework8/project_express/node_modules/nopt/.npmignore create mode 100644 homework8/project_express/node_modules/nopt/LICENSE create mode 100644 homework8/project_express/node_modules/nopt/README.md create mode 100644 homework8/project_express/node_modules/nopt/bin/nopt.js create mode 100644 homework8/project_express/node_modules/nopt/examples/my-program.js create mode 100644 homework8/project_express/node_modules/nopt/lib/nopt.js create mode 100644 homework8/project_express/node_modules/nopt/package.json create mode 100644 homework8/project_express/node_modules/normalize-path/LICENSE create mode 100644 homework8/project_express/node_modules/normalize-path/README.md create mode 100644 homework8/project_express/node_modules/normalize-path/index.js create mode 100644 homework8/project_express/node_modules/normalize-path/package.json create mode 100644 homework8/project_express/node_modules/on-finished/HISTORY.md create mode 100644 homework8/project_express/node_modules/on-finished/LICENSE create mode 100644 homework8/project_express/node_modules/on-finished/README.md create mode 100644 homework8/project_express/node_modules/on-finished/index.js create mode 100644 homework8/project_express/node_modules/on-finished/package.json create mode 100644 homework8/project_express/node_modules/optimist/.travis.yml create mode 100644 homework8/project_express/node_modules/optimist/LICENSE create mode 100644 homework8/project_express/node_modules/optimist/example/bool.js create mode 100644 homework8/project_express/node_modules/optimist/example/boolean_double.js create mode 100644 homework8/project_express/node_modules/optimist/example/boolean_single.js create mode 100644 homework8/project_express/node_modules/optimist/example/default_hash.js create mode 100644 homework8/project_express/node_modules/optimist/example/default_singles.js create mode 100644 homework8/project_express/node_modules/optimist/example/divide.js create mode 100644 homework8/project_express/node_modules/optimist/example/line_count.js create mode 100644 homework8/project_express/node_modules/optimist/example/line_count_options.js create mode 100644 homework8/project_express/node_modules/optimist/example/line_count_wrap.js create mode 100644 homework8/project_express/node_modules/optimist/example/nonopt.js create mode 100644 homework8/project_express/node_modules/optimist/example/reflect.js create mode 100644 homework8/project_express/node_modules/optimist/example/short.js create mode 100644 homework8/project_express/node_modules/optimist/example/string.js create mode 100644 homework8/project_express/node_modules/optimist/example/usage-options.js create mode 100644 homework8/project_express/node_modules/optimist/example/xup.js create mode 100644 homework8/project_express/node_modules/optimist/index.js create mode 100644 homework8/project_express/node_modules/optimist/package.json create mode 100644 homework8/project_express/node_modules/optimist/readme.markdown create mode 100644 homework8/project_express/node_modules/optimist/test/_.js create mode 100644 homework8/project_express/node_modules/optimist/test/_/argv.js create mode 100644 homework8/project_express/node_modules/optimist/test/_/bin.js create mode 100644 homework8/project_express/node_modules/optimist/test/parse.js create mode 100644 homework8/project_express/node_modules/optimist/test/usage.js create mode 100644 homework8/project_express/node_modules/parseurl/HISTORY.md create mode 100644 homework8/project_express/node_modules/parseurl/LICENSE create mode 100644 homework8/project_express/node_modules/parseurl/README.md create mode 100644 homework8/project_express/node_modules/parseurl/index.js create mode 100644 homework8/project_express/node_modules/parseurl/package.json create mode 100644 homework8/project_express/node_modules/path-to-regexp/History.md create mode 100644 homework8/project_express/node_modules/path-to-regexp/LICENSE create mode 100644 homework8/project_express/node_modules/path-to-regexp/Readme.md create mode 100644 homework8/project_express/node_modules/path-to-regexp/index.js create mode 100644 homework8/project_express/node_modules/path-to-regexp/package.json create mode 100644 homework8/project_express/node_modules/picomatch/CHANGELOG.md create mode 100644 homework8/project_express/node_modules/picomatch/LICENSE create mode 100644 homework8/project_express/node_modules/picomatch/README.md create mode 100644 homework8/project_express/node_modules/picomatch/index.js create mode 100644 homework8/project_express/node_modules/picomatch/lib/constants.js create mode 100644 homework8/project_express/node_modules/picomatch/lib/parse.js create mode 100644 homework8/project_express/node_modules/picomatch/lib/picomatch.js create mode 100644 homework8/project_express/node_modules/picomatch/lib/scan.js create mode 100644 homework8/project_express/node_modules/picomatch/lib/utils.js create mode 100644 homework8/project_express/node_modules/picomatch/package.json create mode 100644 homework8/project_express/node_modules/proxy-addr/HISTORY.md create mode 100644 homework8/project_express/node_modules/proxy-addr/LICENSE create mode 100644 homework8/project_express/node_modules/proxy-addr/README.md create mode 100644 homework8/project_express/node_modules/proxy-addr/index.js create mode 100644 homework8/project_express/node_modules/proxy-addr/package.json create mode 100644 homework8/project_express/node_modules/pstree.remy/.travis.yml create mode 100644 homework8/project_express/node_modules/pstree.remy/LICENSE create mode 100644 homework8/project_express/node_modules/pstree.remy/README.md create mode 100644 homework8/project_express/node_modules/pstree.remy/lib/index.js create mode 100644 homework8/project_express/node_modules/pstree.remy/lib/tree.js create mode 100644 homework8/project_express/node_modules/pstree.remy/lib/utils.js create mode 100644 homework8/project_express/node_modules/pstree.remy/package.json create mode 100644 homework8/project_express/node_modules/pstree.remy/tests/fixtures/index.js create mode 100644 homework8/project_express/node_modules/pstree.remy/tests/fixtures/out1 create mode 100644 homework8/project_express/node_modules/pstree.remy/tests/fixtures/out2 create mode 100644 homework8/project_express/node_modules/pstree.remy/tests/index.test.js create mode 100644 homework8/project_express/node_modules/qs/.editorconfig create mode 100644 homework8/project_express/node_modules/qs/.eslintignore create mode 100644 homework8/project_express/node_modules/qs/.eslintrc create mode 100644 homework8/project_express/node_modules/qs/CHANGELOG.md create mode 100644 homework8/project_express/node_modules/qs/LICENSE create mode 100644 homework8/project_express/node_modules/qs/README.md create mode 100644 homework8/project_express/node_modules/qs/dist/qs.js create mode 100644 homework8/project_express/node_modules/qs/lib/formats.js create mode 100644 homework8/project_express/node_modules/qs/lib/index.js create mode 100644 homework8/project_express/node_modules/qs/lib/parse.js create mode 100644 homework8/project_express/node_modules/qs/lib/stringify.js create mode 100644 homework8/project_express/node_modules/qs/lib/utils.js create mode 100644 homework8/project_express/node_modules/qs/package.json create mode 100644 homework8/project_express/node_modules/qs/test/.eslintrc create mode 100644 homework8/project_express/node_modules/qs/test/index.js create mode 100644 homework8/project_express/node_modules/qs/test/parse.js create mode 100644 homework8/project_express/node_modules/qs/test/stringify.js create mode 100644 homework8/project_express/node_modules/qs/test/utils.js create mode 100644 homework8/project_express/node_modules/range-parser/HISTORY.md create mode 100644 homework8/project_express/node_modules/range-parser/LICENSE create mode 100644 homework8/project_express/node_modules/range-parser/README.md create mode 100644 homework8/project_express/node_modules/range-parser/index.js create mode 100644 homework8/project_express/node_modules/range-parser/package.json create mode 100644 homework8/project_express/node_modules/raw-body/HISTORY.md create mode 100644 homework8/project_express/node_modules/raw-body/LICENSE create mode 100644 homework8/project_express/node_modules/raw-body/README.md create mode 100644 homework8/project_express/node_modules/raw-body/index.d.ts create mode 100644 homework8/project_express/node_modules/raw-body/index.js create mode 100644 homework8/project_express/node_modules/raw-body/package.json create mode 100644 homework8/project_express/node_modules/readdirp/LICENSE create mode 100644 homework8/project_express/node_modules/readdirp/README.md create mode 100644 homework8/project_express/node_modules/readdirp/index.d.ts create mode 100644 homework8/project_express/node_modules/readdirp/index.js create mode 100644 homework8/project_express/node_modules/readdirp/package.json create mode 100644 homework8/project_express/node_modules/require/.npmignore create mode 100644 homework8/project_express/node_modules/require/Changelog create mode 100644 homework8/project_express/node_modules/require/LICENSE create mode 100644 homework8/project_express/node_modules/require/README.md create mode 100644 homework8/project_express/node_modules/require/bin/require-command.js create mode 100644 homework8/project_express/node_modules/require/compiler.js create mode 100644 homework8/project_express/node_modules/require/example/client.js create mode 100644 homework8/project_express/node_modules/require/example/compile.js create mode 100644 homework8/project_express/node_modules/require/example/connect.js create mode 100644 homework8/project_express/node_modules/require/example/index.html create mode 100644 homework8/project_express/node_modules/require/example/package.json create mode 100644 homework8/project_express/node_modules/require/example/raphael_circle.html create mode 100644 homework8/project_express/node_modules/require/example/raphael_circle.js create mode 100644 homework8/project_express/node_modules/require/example/server.js create mode 100644 homework8/project_express/node_modules/require/example/shared/dependency.js create mode 100644 homework8/project_express/node_modules/require/lib/getCode.js create mode 100644 homework8/project_express/node_modules/require/lib/getDependencyLevels.js create mode 100644 homework8/project_express/node_modules/require/lib/getRequireStatements.js create mode 100644 homework8/project_express/node_modules/require/lib/resolve.js create mode 100644 homework8/project_express/node_modules/require/package.json create mode 100644 homework8/project_express/node_modules/require/server.js create mode 100644 homework8/project_express/node_modules/safe-buffer/LICENSE create mode 100644 homework8/project_express/node_modules/safe-buffer/README.md create mode 100644 homework8/project_express/node_modules/safe-buffer/index.d.ts create mode 100644 homework8/project_express/node_modules/safe-buffer/index.js create mode 100644 homework8/project_express/node_modules/safe-buffer/package.json create mode 100644 homework8/project_express/node_modules/safer-buffer/LICENSE create mode 100644 homework8/project_express/node_modules/safer-buffer/Porting-Buffer.md create mode 100644 homework8/project_express/node_modules/safer-buffer/Readme.md create mode 100644 homework8/project_express/node_modules/safer-buffer/dangerous.js create mode 100644 homework8/project_express/node_modules/safer-buffer/package.json create mode 100644 homework8/project_express/node_modules/safer-buffer/safer.js create mode 100644 homework8/project_express/node_modules/safer-buffer/tests.js create mode 100644 homework8/project_express/node_modules/semver/CHANGELOG.md create mode 100644 homework8/project_express/node_modules/semver/LICENSE create mode 100644 homework8/project_express/node_modules/semver/README.md create mode 100644 homework8/project_express/node_modules/semver/bin/semver create mode 100644 homework8/project_express/node_modules/semver/package.json create mode 100644 homework8/project_express/node_modules/semver/range.bnf create mode 100644 homework8/project_express/node_modules/semver/semver.js create mode 100644 homework8/project_express/node_modules/send/HISTORY.md create mode 100644 homework8/project_express/node_modules/send/LICENSE create mode 100644 homework8/project_express/node_modules/send/README.md create mode 100644 homework8/project_express/node_modules/send/index.js create mode 100644 homework8/project_express/node_modules/send/node_modules/ms/index.js create mode 100644 homework8/project_express/node_modules/send/node_modules/ms/license.md create mode 100644 homework8/project_express/node_modules/send/node_modules/ms/package.json create mode 100644 homework8/project_express/node_modules/send/node_modules/ms/readme.md create mode 100644 homework8/project_express/node_modules/send/package.json create mode 100644 homework8/project_express/node_modules/serve-static/HISTORY.md create mode 100644 homework8/project_express/node_modules/serve-static/LICENSE create mode 100644 homework8/project_express/node_modules/serve-static/README.md create mode 100644 homework8/project_express/node_modules/serve-static/index.js create mode 100644 homework8/project_express/node_modules/serve-static/package.json create mode 100644 homework8/project_express/node_modules/setprototypeof/LICENSE create mode 100644 homework8/project_express/node_modules/setprototypeof/README.md create mode 100644 homework8/project_express/node_modules/setprototypeof/index.d.ts create mode 100644 homework8/project_express/node_modules/setprototypeof/index.js create mode 100644 homework8/project_express/node_modules/setprototypeof/package.json create mode 100644 homework8/project_express/node_modules/setprototypeof/test/index.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/LICENSE create mode 100644 homework8/project_express/node_modules/simple-update-notifier/README.md create mode 100644 homework8/project_express/node_modules/simple-update-notifier/build/index.d.ts create mode 100644 homework8/project_express/node_modules/simple-update-notifier/build/index.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver.cmd create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver.ps1 create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/CHANGELOG.md create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/LICENSE create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/README.md create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/bin/semver.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/comparator.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/index.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/range.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/semver.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/clean.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/cmp.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/coerce.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare-build.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare-loose.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/diff.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/eq.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/gt.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/gte.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/inc.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/lt.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/lte.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/major.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/minor.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/neq.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/parse.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/patch.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/prerelease.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/rcompare.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/rsort.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/satisfies.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/sort.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/valid.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/index.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/constants.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/debug.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/identifiers.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/re.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/package.json create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/range.bnf create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/gtr.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/intersects.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/ltr.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/max-satisfying.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/min-satisfying.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/min-version.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/outside.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/to-comparators.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/valid.js create mode 100644 homework8/project_express/node_modules/simple-update-notifier/package.json create mode 100644 homework8/project_express/node_modules/simple-update-notifier/src/borderedText.ts create mode 100644 homework8/project_express/node_modules/simple-update-notifier/src/cache.spec.ts create mode 100644 homework8/project_express/node_modules/simple-update-notifier/src/cache.ts create mode 100644 homework8/project_express/node_modules/simple-update-notifier/src/getDistVersion.spec.ts create mode 100644 homework8/project_express/node_modules/simple-update-notifier/src/getDistVersion.ts create mode 100644 homework8/project_express/node_modules/simple-update-notifier/src/hasNewVersion.spec.ts create mode 100644 homework8/project_express/node_modules/simple-update-notifier/src/hasNewVersion.ts create mode 100644 homework8/project_express/node_modules/simple-update-notifier/src/index.spec.ts create mode 100644 homework8/project_express/node_modules/simple-update-notifier/src/index.ts create mode 100644 homework8/project_express/node_modules/simple-update-notifier/src/isNpmOrYarn.ts create mode 100644 homework8/project_express/node_modules/simple-update-notifier/src/types.ts create mode 100644 homework8/project_express/node_modules/source-map/.npmignore create mode 100644 homework8/project_express/node_modules/source-map/.travis.yml create mode 100644 homework8/project_express/node_modules/source-map/CHANGELOG.md create mode 100644 homework8/project_express/node_modules/source-map/LICENSE create mode 100644 homework8/project_express/node_modules/source-map/Makefile.dryice.js create mode 100644 homework8/project_express/node_modules/source-map/README.md create mode 100644 homework8/project_express/node_modules/source-map/build/assert-shim.js create mode 100644 homework8/project_express/node_modules/source-map/build/mini-require.js create mode 100644 homework8/project_express/node_modules/source-map/build/prefix-source-map.jsm create mode 100644 homework8/project_express/node_modules/source-map/build/prefix-utils.jsm create mode 100644 homework8/project_express/node_modules/source-map/build/suffix-browser.js create mode 100644 homework8/project_express/node_modules/source-map/build/suffix-source-map.jsm create mode 100644 homework8/project_express/node_modules/source-map/build/suffix-utils.jsm create mode 100644 homework8/project_express/node_modules/source-map/build/test-prefix.js create mode 100644 homework8/project_express/node_modules/source-map/build/test-suffix.js create mode 100644 homework8/project_express/node_modules/source-map/lib/source-map.js create mode 100644 homework8/project_express/node_modules/source-map/lib/source-map/array-set.js create mode 100644 homework8/project_express/node_modules/source-map/lib/source-map/base64-vlq.js create mode 100644 homework8/project_express/node_modules/source-map/lib/source-map/base64.js create mode 100644 homework8/project_express/node_modules/source-map/lib/source-map/binary-search.js create mode 100644 homework8/project_express/node_modules/source-map/lib/source-map/mapping-list.js create mode 100644 homework8/project_express/node_modules/source-map/lib/source-map/source-map-consumer.js create mode 100644 homework8/project_express/node_modules/source-map/lib/source-map/source-map-generator.js create mode 100644 homework8/project_express/node_modules/source-map/lib/source-map/source-node.js create mode 100644 homework8/project_express/node_modules/source-map/lib/source-map/util.js create mode 100644 homework8/project_express/node_modules/source-map/package.json create mode 100644 homework8/project_express/node_modules/source-map/test/run-tests.js create mode 100644 homework8/project_express/node_modules/source-map/test/source-map/test-api.js create mode 100644 homework8/project_express/node_modules/source-map/test/source-map/test-array-set.js create mode 100644 homework8/project_express/node_modules/source-map/test/source-map/test-base64-vlq.js create mode 100644 homework8/project_express/node_modules/source-map/test/source-map/test-base64.js create mode 100644 homework8/project_express/node_modules/source-map/test/source-map/test-binary-search.js create mode 100644 homework8/project_express/node_modules/source-map/test/source-map/test-dog-fooding.js create mode 100644 homework8/project_express/node_modules/source-map/test/source-map/test-source-map-consumer.js create mode 100644 homework8/project_express/node_modules/source-map/test/source-map/test-source-map-generator.js create mode 100644 homework8/project_express/node_modules/source-map/test/source-map/test-source-node.js create mode 100644 homework8/project_express/node_modules/source-map/test/source-map/test-util.js create mode 100644 homework8/project_express/node_modules/source-map/test/source-map/util.js create mode 100644 homework8/project_express/node_modules/statuses/HISTORY.md create mode 100644 homework8/project_express/node_modules/statuses/LICENSE create mode 100644 homework8/project_express/node_modules/statuses/README.md create mode 100644 homework8/project_express/node_modules/statuses/codes.json create mode 100644 homework8/project_express/node_modules/statuses/index.js create mode 100644 homework8/project_express/node_modules/statuses/package.json create mode 100644 homework8/project_express/node_modules/std/Animation.js create mode 100644 homework8/project_express/node_modules/std/Changelog create mode 100644 homework8/project_express/node_modules/std/Class.js create mode 100644 homework8/project_express/node_modules/std/LICENSE create mode 100644 homework8/project_express/node_modules/std/ListPromise.js create mode 100644 homework8/project_express/node_modules/std/Logger.js create mode 100644 homework8/project_express/node_modules/std/Promise.js create mode 100644 homework8/project_express/node_modules/std/Publisher.js create mode 100644 homework8/project_express/node_modules/std/README.md create mode 100644 homework8/project_express/node_modules/std/arrayToObject.js create mode 100644 homework8/project_express/node_modules/std/assert/deepEqual.js create mode 100644 homework8/project_express/node_modules/std/asyncEach.js create mode 100644 homework8/project_express/node_modules/std/asyncMap.js create mode 100644 homework8/project_express/node_modules/std/base64.js create mode 100644 homework8/project_express/node_modules/std/bind.js create mode 100644 homework8/project_express/node_modules/std/blockFunction.js create mode 100644 homework8/project_express/node_modules/std/browser.js create mode 100644 homework8/project_express/node_modules/std/check.js create mode 100644 homework8/project_express/node_modules/std/client.js create mode 100644 homework8/project_express/node_modules/std/clip.js create mode 100644 homework8/project_express/node_modules/std/cookie.js create mode 100644 homework8/project_express/node_modules/std/copy.js create mode 100644 homework8/project_express/node_modules/std/crc32.js create mode 100644 homework8/project_express/node_modules/std/create.js create mode 100644 homework8/project_express/node_modules/std/curry.js create mode 100644 homework8/project_express/node_modules/std/defineGetter.js create mode 100644 homework8/project_express/node_modules/std/delay.js create mode 100644 homework8/project_express/node_modules/std/delayed.js create mode 100644 homework8/project_express/node_modules/std/each.js create mode 100644 homework8/project_express/node_modules/std/extend.js create mode 100644 homework8/project_express/node_modules/std/filter.js create mode 100644 homework8/project_express/node_modules/std/find.js create mode 100644 homework8/project_express/node_modules/std/flatten.js create mode 100644 homework8/project_express/node_modules/std/flip.js create mode 100644 homework8/project_express/node_modules/std/index.js create mode 100644 homework8/project_express/node_modules/std/inverse.js create mode 100644 homework8/project_express/node_modules/std/invoke.js create mode 100644 homework8/project_express/node_modules/std/invokeWith.js create mode 100644 homework8/project_express/node_modules/std/isArguments.js create mode 100644 homework8/project_express/node_modules/std/isArray.js create mode 100644 homework8/project_express/node_modules/std/isFunction.js create mode 100644 homework8/project_express/node_modules/std/isObject.js create mode 100644 homework8/project_express/node_modules/std/json.js create mode 100644 homework8/project_express/node_modules/std/keys.js create mode 100644 homework8/project_express/node_modules/std/last.js create mode 100644 homework8/project_express/node_modules/std/map.js create mode 100644 homework8/project_express/node_modules/std/merge.js create mode 100644 homework8/project_express/node_modules/std/nextTick.js create mode 100644 homework8/project_express/node_modules/std/once.js create mode 100644 homework8/project_express/node_modules/std/options.js create mode 100644 homework8/project_express/node_modules/std/pack.js create mode 100644 homework8/project_express/node_modules/std/package.json create mode 100644 homework8/project_express/node_modules/std/parallel.js create mode 100644 homework8/project_express/node_modules/std/popup.js create mode 100644 homework8/project_express/node_modules/std/proto.js create mode 100644 homework8/project_express/node_modules/std/rand.js create mode 100644 homework8/project_express/node_modules/std/recall.js create mode 100644 homework8/project_express/node_modules/std/remove.js create mode 100644 homework8/project_express/node_modules/std/repeat.js create mode 100644 homework8/project_express/node_modules/std/round.js create mode 100644 homework8/project_express/node_modules/std/router.js create mode 100644 homework8/project_express/node_modules/std/slice.js create mode 100644 homework8/project_express/node_modules/std/strip.js create mode 100644 homework8/project_express/node_modules/std/sum.js create mode 100644 homework8/project_express/node_modules/std/throttle.js create mode 100644 homework8/project_express/node_modules/std/time.js create mode 100644 homework8/project_express/node_modules/std/trim.js create mode 100644 homework8/project_express/node_modules/std/unique.js create mode 100644 homework8/project_express/node_modules/std/unpack.js create mode 100644 homework8/project_express/node_modules/std/url.js create mode 100644 homework8/project_express/node_modules/std/utf8_encode.js create mode 100644 homework8/project_express/node_modules/std/waitFor.js create mode 100644 homework8/project_express/node_modules/std/xhr.js create mode 100644 homework8/project_express/node_modules/supports-color/browser.js create mode 100644 homework8/project_express/node_modules/supports-color/index.js create mode 100644 homework8/project_express/node_modules/supports-color/license create mode 100644 homework8/project_express/node_modules/supports-color/package.json create mode 100644 homework8/project_express/node_modules/supports-color/readme.md create mode 100644 homework8/project_express/node_modules/to-regex-range/LICENSE create mode 100644 homework8/project_express/node_modules/to-regex-range/README.md create mode 100644 homework8/project_express/node_modules/to-regex-range/index.js create mode 100644 homework8/project_express/node_modules/to-regex-range/package.json create mode 100644 homework8/project_express/node_modules/toidentifier/LICENSE create mode 100644 homework8/project_express/node_modules/toidentifier/README.md create mode 100644 homework8/project_express/node_modules/toidentifier/index.js create mode 100644 homework8/project_express/node_modules/toidentifier/package.json create mode 100644 homework8/project_express/node_modules/touch/LICENSE create mode 100644 homework8/project_express/node_modules/touch/README.md create mode 100644 homework8/project_express/node_modules/touch/bin/nodetouch.js create mode 100644 homework8/project_express/node_modules/touch/index.js create mode 100644 homework8/project_express/node_modules/touch/package.json create mode 100644 homework8/project_express/node_modules/type-is/HISTORY.md create mode 100644 homework8/project_express/node_modules/type-is/LICENSE create mode 100644 homework8/project_express/node_modules/type-is/README.md create mode 100644 homework8/project_express/node_modules/type-is/index.js create mode 100644 homework8/project_express/node_modules/type-is/package.json create mode 100644 homework8/project_express/node_modules/uglify-js/.npmignore create mode 100644 homework8/project_express/node_modules/uglify-js/LICENSE create mode 100644 homework8/project_express/node_modules/uglify-js/README.md create mode 100644 homework8/project_express/node_modules/uglify-js/bin/uglifyjs create mode 100644 homework8/project_express/node_modules/uglify-js/lib/ast.js create mode 100644 homework8/project_express/node_modules/uglify-js/lib/compress.js create mode 100644 homework8/project_express/node_modules/uglify-js/lib/mozilla-ast.js create mode 100644 homework8/project_express/node_modules/uglify-js/lib/output.js create mode 100644 homework8/project_express/node_modules/uglify-js/lib/parse.js create mode 100644 homework8/project_express/node_modules/uglify-js/lib/scope.js create mode 100644 homework8/project_express/node_modules/uglify-js/lib/sourcemap.js create mode 100644 homework8/project_express/node_modules/uglify-js/lib/transform.js create mode 100644 homework8/project_express/node_modules/uglify-js/lib/utils.js create mode 100644 homework8/project_express/node_modules/uglify-js/package.json create mode 100644 homework8/project_express/node_modules/uglify-js/test/compress/arrays.js create mode 100644 homework8/project_express/node_modules/uglify-js/test/compress/blocks.js create mode 100644 homework8/project_express/node_modules/uglify-js/test/compress/conditionals.js create mode 100644 homework8/project_express/node_modules/uglify-js/test/compress/dead-code.js create mode 100644 homework8/project_express/node_modules/uglify-js/test/compress/debugger.js create mode 100644 homework8/project_express/node_modules/uglify-js/test/compress/drop-unused.js create mode 100644 homework8/project_express/node_modules/uglify-js/test/compress/issue-105.js create mode 100644 homework8/project_express/node_modules/uglify-js/test/compress/issue-12.js create mode 100644 homework8/project_express/node_modules/uglify-js/test/compress/issue-22.js create mode 100644 homework8/project_express/node_modules/uglify-js/test/compress/issue-44.js create mode 100644 homework8/project_express/node_modules/uglify-js/test/compress/issue-59.js create mode 100644 homework8/project_express/node_modules/uglify-js/test/compress/labels.js create mode 100644 homework8/project_express/node_modules/uglify-js/test/compress/loops.js create mode 100644 homework8/project_express/node_modules/uglify-js/test/compress/properties.js create mode 100644 homework8/project_express/node_modules/uglify-js/test/compress/sequences.js create mode 100644 homework8/project_express/node_modules/uglify-js/test/compress/switch.js create mode 100644 homework8/project_express/node_modules/uglify-js/test/compress/typeof.js create mode 100644 homework8/project_express/node_modules/uglify-js/test/run-tests.js create mode 100644 homework8/project_express/node_modules/uglify-js/tools/node.js create mode 100644 homework8/project_express/node_modules/undefsafe/.github/workflows/release.yml create mode 100644 homework8/project_express/node_modules/undefsafe/.jscsrc create mode 100644 homework8/project_express/node_modules/undefsafe/.jshintrc create mode 100644 homework8/project_express/node_modules/undefsafe/.travis.yml create mode 100644 homework8/project_express/node_modules/undefsafe/LICENSE create mode 100644 homework8/project_express/node_modules/undefsafe/README.md create mode 100644 homework8/project_express/node_modules/undefsafe/example.js create mode 100644 homework8/project_express/node_modules/undefsafe/lib/undefsafe.js create mode 100644 homework8/project_express/node_modules/undefsafe/package.json create mode 100644 homework8/project_express/node_modules/unpipe/HISTORY.md create mode 100644 homework8/project_express/node_modules/unpipe/LICENSE create mode 100644 homework8/project_express/node_modules/unpipe/README.md create mode 100644 homework8/project_express/node_modules/unpipe/index.js create mode 100644 homework8/project_express/node_modules/unpipe/package.json create mode 100644 homework8/project_express/node_modules/utils-merge/.npmignore create mode 100644 homework8/project_express/node_modules/utils-merge/LICENSE create mode 100644 homework8/project_express/node_modules/utils-merge/README.md create mode 100644 homework8/project_express/node_modules/utils-merge/index.js create mode 100644 homework8/project_express/node_modules/utils-merge/package.json create mode 100644 homework8/project_express/node_modules/vary/HISTORY.md create mode 100644 homework8/project_express/node_modules/vary/LICENSE create mode 100644 homework8/project_express/node_modules/vary/README.md create mode 100644 homework8/project_express/node_modules/vary/index.js create mode 100644 homework8/project_express/node_modules/vary/package.json create mode 100644 homework8/project_express/node_modules/wordwrap/LICENSE create mode 100644 homework8/project_express/node_modules/wordwrap/README.markdown create mode 100644 homework8/project_express/node_modules/wordwrap/example/center.js create mode 100644 homework8/project_express/node_modules/wordwrap/example/meat.js create mode 100644 homework8/project_express/node_modules/wordwrap/index.js create mode 100644 homework8/project_express/node_modules/wordwrap/package.json create mode 100644 homework8/project_express/node_modules/wordwrap/test/break.js create mode 100644 homework8/project_express/node_modules/wordwrap/test/idleness.txt create mode 100644 homework8/project_express/node_modules/wordwrap/test/wrap.js create mode 100644 homework8/project_express/package-lock.json create mode 100644 homework8/project_express/package.json create mode 100644 homework8/project_express/public/copy/js/CartComponent.js create mode 100644 homework8/project_express/public/copy/js/ErrorComp.js create mode 100644 homework8/project_express/public/copy/js/FilterComp.js create mode 100644 homework8/project_express/public/copy/js/ProductComponent.js create mode 100644 homework8/project_express/public/copy/js/main.js create mode 100644 homework8/project_express/public/css/images/subscribe.jpg create mode 100644 homework8/project_express/public/css/normalize.css create mode 100644 homework8/project_express/public/css/style.css create mode 100644 homework8/project_express/public/images/bars.png create mode 100644 homework8/project_express/public/images/cart.png create mode 100644 homework8/project_express/public/images/cart.svg create mode 100644 homework8/project_express/public/images/chevronLeft.svg create mode 100644 homework8/project_express/public/images/chevronRight.svg create mode 100644 homework8/project_express/public/images/featured/1.jpg create mode 100644 homework8/project_express/public/images/featured/2.jpg create mode 100644 homework8/project_express/public/images/featured/3.jpg create mode 100644 homework8/project_express/public/images/featured/4.jpg create mode 100644 homework8/project_express/public/images/featured/5.jpg create mode 100644 homework8/project_express/public/images/featured/6.jpg create mode 100644 homework8/project_express/public/images/filter.svg create mode 100644 homework8/project_express/public/images/filterArrow.svg create mode 100644 homework8/project_express/public/images/filterHover.svg create mode 100644 homework8/project_express/public/images/logo.png create mode 100644 homework8/project_express/public/images/search.png create mode 100644 homework8/project_express/public/images/services/assurance.svg create mode 100644 homework8/project_express/public/images/services/delivery.svg create mode 100644 homework8/project_express/public/images/services/discount.svg create mode 100644 homework8/project_express/public/images/subscribe.jpg create mode 100644 homework8/project_express/public/images/subscribeUser.png create mode 100644 homework8/project_express/public/images/user.png create mode 100644 homework8/project_express/public/index.html create mode 100644 homework8/project_express/public/js/main.js create mode 100644 homework8/project_express/public/js/mycartComponent.js create mode 100644 homework8/project_express/public/js/myproductComponent.js create mode 100644 homework8/project_express/server/cart.js create mode 100644 homework8/project_express/server/cartRouter.js create mode 100644 homework8/project_express/server/db/products.json create mode 100644 homework8/project_express/server/db/userCart.json create mode 100644 homework8/project_express/server/handler.js create mode 100644 homework8/project_express/server/server.js diff --git a/homework8/project_express/.idea/.gitignore b/homework8/project_express/.idea/.gitignore new file mode 100644 index 0000000..73f69e0 --- /dev/null +++ b/homework8/project_express/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/homework8/project_express/.idea/jsLibraryMappings.xml b/homework8/project_express/.idea/jsLibraryMappings.xml new file mode 100644 index 0000000..d23208f --- /dev/null +++ b/homework8/project_express/.idea/jsLibraryMappings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/homework8/project_express/.idea/misc.xml b/homework8/project_express/.idea/misc.xml new file mode 100644 index 0000000..28a804d --- /dev/null +++ b/homework8/project_express/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/homework8/project_express/.idea/modules.xml b/homework8/project_express/.idea/modules.xml new file mode 100644 index 0000000..4875f51 --- /dev/null +++ b/homework8/project_express/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/homework8/project_express/.idea/project_express.iml b/homework8/project_express/.idea/project_express.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/homework8/project_express/.idea/project_express.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/homework8/project_express/node_modules/.bin/mime b/homework8/project_express/node_modules/.bin/mime new file mode 100644 index 0000000..91e5e16 --- /dev/null +++ b/homework8/project_express/node_modules/.bin/mime @@ -0,0 +1,15 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; +esac + +if [ -x "$basedir/node" ]; then + "$basedir/node" "$basedir/../mime/cli.js" "$@" + ret=$? +else + node "$basedir/../mime/cli.js" "$@" + ret=$? +fi +exit $ret diff --git a/homework8/project_express/node_modules/.bin/mime.cmd b/homework8/project_express/node_modules/.bin/mime.cmd new file mode 100644 index 0000000..746a279 --- /dev/null +++ b/homework8/project_express/node_modules/.bin/mime.cmd @@ -0,0 +1,17 @@ +@ECHO off +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +"%_prog%" "%dp0%\..\mime\cli.js" %* +ENDLOCAL +EXIT /b %errorlevel% +:find_dp0 +SET dp0=%~dp0 +EXIT /b diff --git a/homework8/project_express/node_modules/.bin/mime.ps1 b/homework8/project_express/node_modules/.bin/mime.ps1 new file mode 100644 index 0000000..a6f6f47 --- /dev/null +++ b/homework8/project_express/node_modules/.bin/mime.ps1 @@ -0,0 +1,18 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + & "$basedir/node$exe" "$basedir/../mime/cli.js" $args + $ret=$LASTEXITCODE +} else { + & "node$exe" "$basedir/../mime/cli.js" $args + $ret=$LASTEXITCODE +} +exit $ret diff --git a/homework8/project_express/node_modules/.bin/nodemon b/homework8/project_express/node_modules/.bin/nodemon new file mode 100644 index 0000000..4d75661 --- /dev/null +++ b/homework8/project_express/node_modules/.bin/nodemon @@ -0,0 +1,12 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../nodemon/bin/nodemon.js" "$@" +else + exec node "$basedir/../nodemon/bin/nodemon.js" "$@" +fi diff --git a/homework8/project_express/node_modules/.bin/nodemon.cmd b/homework8/project_express/node_modules/.bin/nodemon.cmd new file mode 100644 index 0000000..55acf8a --- /dev/null +++ b/homework8/project_express/node_modules/.bin/nodemon.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\nodemon\bin\nodemon.js" %* diff --git a/homework8/project_express/node_modules/.bin/nodemon.ps1 b/homework8/project_express/node_modules/.bin/nodemon.ps1 new file mode 100644 index 0000000..d4e3f5d --- /dev/null +++ b/homework8/project_express/node_modules/.bin/nodemon.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../nodemon/bin/nodemon.js" $args + } else { + & "$basedir/node$exe" "$basedir/../nodemon/bin/nodemon.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../nodemon/bin/nodemon.js" $args + } else { + & "node$exe" "$basedir/../nodemon/bin/nodemon.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/homework8/project_express/node_modules/.bin/nodetouch b/homework8/project_express/node_modules/.bin/nodetouch new file mode 100644 index 0000000..03f8b4d --- /dev/null +++ b/homework8/project_express/node_modules/.bin/nodetouch @@ -0,0 +1,12 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../touch/bin/nodetouch.js" "$@" +else + exec node "$basedir/../touch/bin/nodetouch.js" "$@" +fi diff --git a/homework8/project_express/node_modules/.bin/nodetouch.cmd b/homework8/project_express/node_modules/.bin/nodetouch.cmd new file mode 100644 index 0000000..8298b91 --- /dev/null +++ b/homework8/project_express/node_modules/.bin/nodetouch.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\touch\bin\nodetouch.js" %* diff --git a/homework8/project_express/node_modules/.bin/nodetouch.ps1 b/homework8/project_express/node_modules/.bin/nodetouch.ps1 new file mode 100644 index 0000000..5f68b4c --- /dev/null +++ b/homework8/project_express/node_modules/.bin/nodetouch.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../touch/bin/nodetouch.js" $args + } else { + & "$basedir/node$exe" "$basedir/../touch/bin/nodetouch.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../touch/bin/nodetouch.js" $args + } else { + & "node$exe" "$basedir/../touch/bin/nodetouch.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/homework8/project_express/node_modules/.bin/nopt b/homework8/project_express/node_modules/.bin/nopt new file mode 100644 index 0000000..f1ec43b --- /dev/null +++ b/homework8/project_express/node_modules/.bin/nopt @@ -0,0 +1,12 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../nopt/bin/nopt.js" "$@" +else + exec node "$basedir/../nopt/bin/nopt.js" "$@" +fi diff --git a/homework8/project_express/node_modules/.bin/nopt.cmd b/homework8/project_express/node_modules/.bin/nopt.cmd new file mode 100644 index 0000000..a7f38b3 --- /dev/null +++ b/homework8/project_express/node_modules/.bin/nopt.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\nopt\bin\nopt.js" %* diff --git a/homework8/project_express/node_modules/.bin/nopt.ps1 b/homework8/project_express/node_modules/.bin/nopt.ps1 new file mode 100644 index 0000000..9d6ba56 --- /dev/null +++ b/homework8/project_express/node_modules/.bin/nopt.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../nopt/bin/nopt.js" $args + } else { + & "$basedir/node$exe" "$basedir/../nopt/bin/nopt.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../nopt/bin/nopt.js" $args + } else { + & "node$exe" "$basedir/../nopt/bin/nopt.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/homework8/project_express/node_modules/.bin/require b/homework8/project_express/node_modules/.bin/require new file mode 100644 index 0000000..f2aed69 --- /dev/null +++ b/homework8/project_express/node_modules/.bin/require @@ -0,0 +1,12 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../require/bin/require-command.js" "$@" +else + exec node "$basedir/../require/bin/require-command.js" "$@" +fi diff --git a/homework8/project_express/node_modules/.bin/require.cmd b/homework8/project_express/node_modules/.bin/require.cmd new file mode 100644 index 0000000..ffa7894 --- /dev/null +++ b/homework8/project_express/node_modules/.bin/require.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\require\bin\require-command.js" %* diff --git a/homework8/project_express/node_modules/.bin/require.ps1 b/homework8/project_express/node_modules/.bin/require.ps1 new file mode 100644 index 0000000..ee58c8f --- /dev/null +++ b/homework8/project_express/node_modules/.bin/require.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../require/bin/require-command.js" $args + } else { + & "$basedir/node$exe" "$basedir/../require/bin/require-command.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../require/bin/require-command.js" $args + } else { + & "node$exe" "$basedir/../require/bin/require-command.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/homework8/project_express/node_modules/.bin/semver b/homework8/project_express/node_modules/.bin/semver new file mode 100644 index 0000000..86cee84 --- /dev/null +++ b/homework8/project_express/node_modules/.bin/semver @@ -0,0 +1,12 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../semver/bin/semver" "$@" +else + exec node "$basedir/../semver/bin/semver" "$@" +fi diff --git a/homework8/project_express/node_modules/.bin/semver.cmd b/homework8/project_express/node_modules/.bin/semver.cmd new file mode 100644 index 0000000..22d9286 --- /dev/null +++ b/homework8/project_express/node_modules/.bin/semver.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\semver\bin\semver" %* diff --git a/homework8/project_express/node_modules/.bin/semver.ps1 b/homework8/project_express/node_modules/.bin/semver.ps1 new file mode 100644 index 0000000..98c1b09 --- /dev/null +++ b/homework8/project_express/node_modules/.bin/semver.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../semver/bin/semver" $args + } else { + & "$basedir/node$exe" "$basedir/../semver/bin/semver" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../semver/bin/semver" $args + } else { + & "node$exe" "$basedir/../semver/bin/semver" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/homework8/project_express/node_modules/.bin/uglifyjs b/homework8/project_express/node_modules/.bin/uglifyjs new file mode 100644 index 0000000..1d0ff19 --- /dev/null +++ b/homework8/project_express/node_modules/.bin/uglifyjs @@ -0,0 +1,12 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../uglify-js/bin/uglifyjs" "$@" +else + exec node "$basedir/../uglify-js/bin/uglifyjs" "$@" +fi diff --git a/homework8/project_express/node_modules/.bin/uglifyjs.cmd b/homework8/project_express/node_modules/.bin/uglifyjs.cmd new file mode 100644 index 0000000..17a9df1 --- /dev/null +++ b/homework8/project_express/node_modules/.bin/uglifyjs.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\uglify-js\bin\uglifyjs" %* diff --git a/homework8/project_express/node_modules/.bin/uglifyjs.ps1 b/homework8/project_express/node_modules/.bin/uglifyjs.ps1 new file mode 100644 index 0000000..5e0bc56 --- /dev/null +++ b/homework8/project_express/node_modules/.bin/uglifyjs.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../uglify-js/bin/uglifyjs" $args + } else { + & "$basedir/node$exe" "$basedir/../uglify-js/bin/uglifyjs" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../uglify-js/bin/uglifyjs" $args + } else { + & "node$exe" "$basedir/../uglify-js/bin/uglifyjs" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/homework8/project_express/node_modules/.package-lock.json b/homework8/project_express/node_modules/.package-lock.json new file mode 100644 index 0000000..3c54ba4 --- /dev/null +++ b/homework8/project_express/node_modules/.package-lock.json @@ -0,0 +1,882 @@ +{ + "name": "project_express", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "node_modules/async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dependencies": { + "mime-db": "1.44.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nodemon": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", + "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha512-TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ==", + "dependencies": { + "wordwrap": "~0.0.2" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dependencies": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, + "node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require": { + "version": "2.4.20", + "resolved": "https://registry.npmjs.org/require/-/require-2.4.20.tgz", + "integrity": "sha512-7eop5rvh38qhQQQOoUyf68meVIcxT2yFySNywTbxoEECgkX4KDqqDRaEszfvFnuB3fuZVjDdJZ1TI/Esr16RRA==", + "dependencies": { + "std": "0.1.40", + "uglify-js": "2.3.0" + }, + "bin": { + "require": "bin/require-command.js" + }, + "engines": { + "browsers": "*", + "node": "*" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/simple-update-notifier": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", + "integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==", + "dependencies": { + "semver": "~7.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha512-VtCvB9SIQhk3aF6h+N85EaqIaBFIAfZ9Cu+NJHHVvc8BbEcnvDcFw6sqQ2dQrT6SlOrZq3tIvyD9+EGq/lJryQ==", + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/std": { + "version": "0.1.40", + "resolved": "https://registry.npmjs.org/std/-/std-0.1.40.tgz", + "integrity": "sha512-wUf57hkDGCoVShrhPA8Q7lAg2Qosk+FaMlECmAsr1A4/rL2NRXFHQGBcgMUFKVkPEemJFW9gzjCQisRty14ohg==", + "engines": { + "node": "*" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/uglify-js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.3.0.tgz", + "integrity": "sha512-AQvbxRKdaQeYADywQaao0k8Tj+7NGEVTne6xwgX1yQpv/G8b0CKdIw70HkCptwfvNGDsVe+0Bng3U9hfWbxxfg==", + "dependencies": { + "async": "~0.2.6", + "optimist": "~0.3.5", + "source-map": "~0.1.7" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==", + "engines": { + "node": ">=0.4.0" + } + } + } +} diff --git a/homework8/project_express/node_modules/abbrev/LICENSE b/homework8/project_express/node_modules/abbrev/LICENSE new file mode 100644 index 0000000..9bcfa9d --- /dev/null +++ b/homework8/project_express/node_modules/abbrev/LICENSE @@ -0,0 +1,46 @@ +This software is dual-licensed under the ISC and MIT licenses. +You may use this software under EITHER of the following licenses. + +---------- + +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +---------- + +Copyright Isaac Z. Schlueter and Contributors +All rights reserved. + +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/homework8/project_express/node_modules/abbrev/README.md b/homework8/project_express/node_modules/abbrev/README.md new file mode 100644 index 0000000..99746fe --- /dev/null +++ b/homework8/project_express/node_modules/abbrev/README.md @@ -0,0 +1,23 @@ +# abbrev-js + +Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev). + +Usage: + + var abbrev = require("abbrev"); + abbrev("foo", "fool", "folding", "flop"); + + // returns: + { fl: 'flop' + , flo: 'flop' + , flop: 'flop' + , fol: 'folding' + , fold: 'folding' + , foldi: 'folding' + , foldin: 'folding' + , folding: 'folding' + , foo: 'foo' + , fool: 'fool' + } + +This is handy for command-line scripts, or other cases where you want to be able to accept shorthands. diff --git a/homework8/project_express/node_modules/abbrev/abbrev.js b/homework8/project_express/node_modules/abbrev/abbrev.js new file mode 100644 index 0000000..7b1dc5d --- /dev/null +++ b/homework8/project_express/node_modules/abbrev/abbrev.js @@ -0,0 +1,61 @@ +module.exports = exports = abbrev.abbrev = abbrev + +abbrev.monkeyPatch = monkeyPatch + +function monkeyPatch () { + Object.defineProperty(Array.prototype, 'abbrev', { + value: function () { return abbrev(this) }, + enumerable: false, configurable: true, writable: true + }) + + Object.defineProperty(Object.prototype, 'abbrev', { + value: function () { return abbrev(Object.keys(this)) }, + enumerable: false, configurable: true, writable: true + }) +} + +function abbrev (list) { + if (arguments.length !== 1 || !Array.isArray(list)) { + list = Array.prototype.slice.call(arguments, 0) + } + for (var i = 0, l = list.length, args = [] ; i < l ; i ++) { + args[i] = typeof list[i] === "string" ? list[i] : String(list[i]) + } + + // sort them lexicographically, so that they're next to their nearest kin + args = args.sort(lexSort) + + // walk through each, seeing how much it has in common with the next and previous + var abbrevs = {} + , prev = "" + for (var i = 0, l = args.length ; i < l ; i ++) { + var current = args[i] + , next = args[i + 1] || "" + , nextMatches = true + , prevMatches = true + if (current === next) continue + for (var j = 0, cl = current.length ; j < cl ; j ++) { + var curChar = current.charAt(j) + nextMatches = nextMatches && curChar === next.charAt(j) + prevMatches = prevMatches && curChar === prev.charAt(j) + if (!nextMatches && !prevMatches) { + j ++ + break + } + } + prev = current + if (j === cl) { + abbrevs[current] = current + continue + } + for (var a = current.substr(0, j) ; j <= cl ; j ++) { + abbrevs[a] = current + a += current.charAt(j) + } + } + return abbrevs +} + +function lexSort (a, b) { + return a === b ? 0 : a > b ? 1 : -1 +} diff --git a/homework8/project_express/node_modules/abbrev/package.json b/homework8/project_express/node_modules/abbrev/package.json new file mode 100644 index 0000000..bf4e801 --- /dev/null +++ b/homework8/project_express/node_modules/abbrev/package.json @@ -0,0 +1,21 @@ +{ + "name": "abbrev", + "version": "1.1.1", + "description": "Like ruby's abbrev module, but in js", + "author": "Isaac Z. Schlueter ", + "main": "abbrev.js", + "scripts": { + "test": "tap test.js --100", + "preversion": "npm test", + "postversion": "npm publish", + "postpublish": "git push origin --all; git push origin --tags" + }, + "repository": "http://github.com/isaacs/abbrev-js", + "license": "ISC", + "devDependencies": { + "tap": "^10.1" + }, + "files": [ + "abbrev.js" + ] +} diff --git a/homework8/project_express/node_modules/accepts/HISTORY.md b/homework8/project_express/node_modules/accepts/HISTORY.md new file mode 100644 index 0000000..0bf0417 --- /dev/null +++ b/homework8/project_express/node_modules/accepts/HISTORY.md @@ -0,0 +1,236 @@ +1.3.7 / 2019-04-29 +================== + + * deps: negotiator@0.6.2 + - Fix sorting charset, encoding, and language with extra parameters + +1.3.6 / 2019-04-28 +================== + + * deps: mime-types@~2.1.24 + - deps: mime-db@~1.40.0 + +1.3.5 / 2018-02-28 +================== + + * deps: mime-types@~2.1.18 + - deps: mime-db@~1.33.0 + +1.3.4 / 2017-08-22 +================== + + * deps: mime-types@~2.1.16 + - deps: mime-db@~1.29.0 + +1.3.3 / 2016-05-02 +================== + + * deps: mime-types@~2.1.11 + - deps: mime-db@~1.23.0 + * deps: negotiator@0.6.1 + - perf: improve `Accept` parsing speed + - perf: improve `Accept-Charset` parsing speed + - perf: improve `Accept-Encoding` parsing speed + - perf: improve `Accept-Language` parsing speed + +1.3.2 / 2016-03-08 +================== + + * deps: mime-types@~2.1.10 + - Fix extension of `application/dash+xml` + - Update primary extension for `audio/mp4` + - deps: mime-db@~1.22.0 + +1.3.1 / 2016-01-19 +================== + + * deps: mime-types@~2.1.9 + - deps: mime-db@~1.21.0 + +1.3.0 / 2015-09-29 +================== + + * deps: mime-types@~2.1.7 + - deps: mime-db@~1.19.0 + * deps: negotiator@0.6.0 + - Fix including type extensions in parameters in `Accept` parsing + - Fix parsing `Accept` parameters with quoted equals + - Fix parsing `Accept` parameters with quoted semicolons + - Lazy-load modules from main entry point + - perf: delay type concatenation until needed + - perf: enable strict mode + - perf: hoist regular expressions + - perf: remove closures getting spec properties + - perf: remove a closure from media type parsing + - perf: remove property delete from media type parsing + +1.2.13 / 2015-09-06 +=================== + + * deps: mime-types@~2.1.6 + - deps: mime-db@~1.18.0 + +1.2.12 / 2015-07-30 +=================== + + * deps: mime-types@~2.1.4 + - deps: mime-db@~1.16.0 + +1.2.11 / 2015-07-16 +=================== + + * deps: mime-types@~2.1.3 + - deps: mime-db@~1.15.0 + +1.2.10 / 2015-07-01 +=================== + + * deps: mime-types@~2.1.2 + - deps: mime-db@~1.14.0 + +1.2.9 / 2015-06-08 +================== + + * deps: mime-types@~2.1.1 + - perf: fix deopt during mapping + +1.2.8 / 2015-06-07 +================== + + * deps: mime-types@~2.1.0 + - deps: mime-db@~1.13.0 + * perf: avoid argument reassignment & argument slice + * perf: avoid negotiator recursive construction + * perf: enable strict mode + * perf: remove unnecessary bitwise operator + +1.2.7 / 2015-05-10 +================== + + * deps: negotiator@0.5.3 + - Fix media type parameter matching to be case-insensitive + +1.2.6 / 2015-05-07 +================== + + * deps: mime-types@~2.0.11 + - deps: mime-db@~1.9.1 + * deps: negotiator@0.5.2 + - Fix comparing media types with quoted values + - Fix splitting media types with quoted commas + +1.2.5 / 2015-03-13 +================== + + * deps: mime-types@~2.0.10 + - deps: mime-db@~1.8.0 + +1.2.4 / 2015-02-14 +================== + + * Support Node.js 0.6 + * deps: mime-types@~2.0.9 + - deps: mime-db@~1.7.0 + * deps: negotiator@0.5.1 + - Fix preference sorting to be stable for long acceptable lists + +1.2.3 / 2015-01-31 +================== + + * deps: mime-types@~2.0.8 + - deps: mime-db@~1.6.0 + +1.2.2 / 2014-12-30 +================== + + * deps: mime-types@~2.0.7 + - deps: mime-db@~1.5.0 + +1.2.1 / 2014-12-30 +================== + + * deps: mime-types@~2.0.5 + - deps: mime-db@~1.3.1 + +1.2.0 / 2014-12-19 +================== + + * deps: negotiator@0.5.0 + - Fix list return order when large accepted list + - Fix missing identity encoding when q=0 exists + - Remove dynamic building of Negotiator class + +1.1.4 / 2014-12-10 +================== + + * deps: mime-types@~2.0.4 + - deps: mime-db@~1.3.0 + +1.1.3 / 2014-11-09 +================== + + * deps: mime-types@~2.0.3 + - deps: mime-db@~1.2.0 + +1.1.2 / 2014-10-14 +================== + + * deps: negotiator@0.4.9 + - Fix error when media type has invalid parameter + +1.1.1 / 2014-09-28 +================== + + * deps: mime-types@~2.0.2 + - deps: mime-db@~1.1.0 + * deps: negotiator@0.4.8 + - Fix all negotiations to be case-insensitive + - Stable sort preferences of same quality according to client order + +1.1.0 / 2014-09-02 +================== + + * update `mime-types` + +1.0.7 / 2014-07-04 +================== + + * Fix wrong type returned from `type` when match after unknown extension + +1.0.6 / 2014-06-24 +================== + + * deps: negotiator@0.4.7 + +1.0.5 / 2014-06-20 +================== + + * fix crash when unknown extension given + +1.0.4 / 2014-06-19 +================== + + * use `mime-types` + +1.0.3 / 2014-06-11 +================== + + * deps: negotiator@0.4.6 + - Order by specificity when quality is the same + +1.0.2 / 2014-05-29 +================== + + * Fix interpretation when header not in request + * deps: pin negotiator@0.4.5 + +1.0.1 / 2014-01-18 +================== + + * Identity encoding isn't always acceptable + * deps: negotiator@~0.4.0 + +1.0.0 / 2013-12-27 +================== + + * Genesis diff --git a/homework8/project_express/node_modules/accepts/LICENSE b/homework8/project_express/node_modules/accepts/LICENSE new file mode 100644 index 0000000..0616607 --- /dev/null +++ b/homework8/project_express/node_modules/accepts/LICENSE @@ -0,0 +1,23 @@ +(The MIT License) + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2015 Douglas Christopher Wilson + +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/homework8/project_express/node_modules/accepts/README.md b/homework8/project_express/node_modules/accepts/README.md new file mode 100644 index 0000000..66a2f54 --- /dev/null +++ b/homework8/project_express/node_modules/accepts/README.md @@ -0,0 +1,142 @@ +# accepts + +[![NPM Version][npm-version-image]][npm-url] +[![NPM Downloads][npm-downloads-image]][npm-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Higher level content negotiation based on [negotiator](https://www.npmjs.com/package/negotiator). +Extracted from [koa](https://www.npmjs.com/package/koa) for general use. + +In addition to negotiator, it allows: + +- Allows types as an array or arguments list, ie `(['text/html', 'application/json'])` + as well as `('text/html', 'application/json')`. +- Allows type shorthands such as `json`. +- Returns `false` when no types match +- Treats non-existent headers as `*` + +## Installation + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```sh +$ npm install accepts +``` + +## API + + + +```js +var accepts = require('accepts') +``` + +### accepts(req) + +Create a new `Accepts` object for the given `req`. + +#### .charset(charsets) + +Return the first accepted charset. If nothing in `charsets` is accepted, +then `false` is returned. + +#### .charsets() + +Return the charsets that the request accepts, in the order of the client's +preference (most preferred first). + +#### .encoding(encodings) + +Return the first accepted encoding. If nothing in `encodings` is accepted, +then `false` is returned. + +#### .encodings() + +Return the encodings that the request accepts, in the order of the client's +preference (most preferred first). + +#### .language(languages) + +Return the first accepted language. If nothing in `languages` is accepted, +then `false` is returned. + +#### .languages() + +Return the languages that the request accepts, in the order of the client's +preference (most preferred first). + +#### .type(types) + +Return the first accepted type (and it is returned as the same text as what +appears in the `types` array). If nothing in `types` is accepted, then `false` +is returned. + +The `types` array can contain full MIME types or file extensions. Any value +that is not a full MIME types is passed to `require('mime-types').lookup`. + +#### .types() + +Return the types that the request accepts, in the order of the client's +preference (most preferred first). + +## Examples + +### Simple type negotiation + +This simple example shows how to use `accepts` to return a different typed +respond body based on what the client wants to accept. The server lists it's +preferences in order and will get back the best match between the client and +server. + +```js +var accepts = require('accepts') +var http = require('http') + +function app (req, res) { + var accept = accepts(req) + + // the order of this list is significant; should be server preferred order + switch (accept.type(['json', 'html'])) { + case 'json': + res.setHeader('Content-Type', 'application/json') + res.write('{"hello":"world!"}') + break + case 'html': + res.setHeader('Content-Type', 'text/html') + res.write('hello, world!') + break + default: + // the fallback is text/plain, so no need to specify it above + res.setHeader('Content-Type', 'text/plain') + res.write('hello, world!') + break + } + + res.end() +} + +http.createServer(app).listen(3000) +``` + +You can test this out with the cURL program: +```sh +curl -I -H'Accept: text/html' http://localhost:3000/ +``` + +## License + +[MIT](LICENSE) + +[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/accepts/master +[coveralls-url]: https://coveralls.io/r/jshttp/accepts?branch=master +[node-version-image]: https://badgen.net/npm/node/accepts +[node-version-url]: https://nodejs.org/en/download +[npm-downloads-image]: https://badgen.net/npm/dm/accepts +[npm-url]: https://npmjs.org/package/accepts +[npm-version-image]: https://badgen.net/npm/v/accepts +[travis-image]: https://badgen.net/travis/jshttp/accepts/master +[travis-url]: https://travis-ci.org/jshttp/accepts diff --git a/homework8/project_express/node_modules/accepts/index.js b/homework8/project_express/node_modules/accepts/index.js new file mode 100644 index 0000000..e9b2f63 --- /dev/null +++ b/homework8/project_express/node_modules/accepts/index.js @@ -0,0 +1,238 @@ +/*! + * accepts + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var Negotiator = require('negotiator') +var mime = require('mime-types') + +/** + * Module exports. + * @public + */ + +module.exports = Accepts + +/** + * Create a new Accepts object for the given req. + * + * @param {object} req + * @public + */ + +function Accepts (req) { + if (!(this instanceof Accepts)) { + return new Accepts(req) + } + + this.headers = req.headers + this.negotiator = new Negotiator(req) +} + +/** + * Check if the given `type(s)` is acceptable, returning + * the best match when true, otherwise `undefined`, in which + * case you should respond with 406 "Not Acceptable". + * + * The `type` value may be a single mime type string + * such as "application/json", the extension name + * such as "json" or an array `["json", "html", "text/plain"]`. When a list + * or array is given the _best_ match, if any is returned. + * + * Examples: + * + * // Accept: text/html + * this.types('html'); + * // => "html" + * + * // Accept: text/*, application/json + * this.types('html'); + * // => "html" + * this.types('text/html'); + * // => "text/html" + * this.types('json', 'text'); + * // => "json" + * this.types('application/json'); + * // => "application/json" + * + * // Accept: text/*, application/json + * this.types('image/png'); + * this.types('png'); + * // => undefined + * + * // Accept: text/*;q=.5, application/json + * this.types(['html', 'json']); + * this.types('html', 'json'); + * // => "json" + * + * @param {String|Array} types... + * @return {String|Array|Boolean} + * @public + */ + +Accepts.prototype.type = +Accepts.prototype.types = function (types_) { + var types = types_ + + // support flattened arguments + if (types && !Array.isArray(types)) { + types = new Array(arguments.length) + for (var i = 0; i < types.length; i++) { + types[i] = arguments[i] + } + } + + // no types, return all requested types + if (!types || types.length === 0) { + return this.negotiator.mediaTypes() + } + + // no accept header, return first given type + if (!this.headers.accept) { + return types[0] + } + + var mimes = types.map(extToMime) + var accepts = this.negotiator.mediaTypes(mimes.filter(validMime)) + var first = accepts[0] + + return first + ? types[mimes.indexOf(first)] + : false +} + +/** + * Return accepted encodings or best fit based on `encodings`. + * + * Given `Accept-Encoding: gzip, deflate` + * an array sorted by quality is returned: + * + * ['gzip', 'deflate'] + * + * @param {String|Array} encodings... + * @return {String|Array} + * @public + */ + +Accepts.prototype.encoding = +Accepts.prototype.encodings = function (encodings_) { + var encodings = encodings_ + + // support flattened arguments + if (encodings && !Array.isArray(encodings)) { + encodings = new Array(arguments.length) + for (var i = 0; i < encodings.length; i++) { + encodings[i] = arguments[i] + } + } + + // no encodings, return all requested encodings + if (!encodings || encodings.length === 0) { + return this.negotiator.encodings() + } + + return this.negotiator.encodings(encodings)[0] || false +} + +/** + * Return accepted charsets or best fit based on `charsets`. + * + * Given `Accept-Charset: utf-8, iso-8859-1;q=0.2, utf-7;q=0.5` + * an array sorted by quality is returned: + * + * ['utf-8', 'utf-7', 'iso-8859-1'] + * + * @param {String|Array} charsets... + * @return {String|Array} + * @public + */ + +Accepts.prototype.charset = +Accepts.prototype.charsets = function (charsets_) { + var charsets = charsets_ + + // support flattened arguments + if (charsets && !Array.isArray(charsets)) { + charsets = new Array(arguments.length) + for (var i = 0; i < charsets.length; i++) { + charsets[i] = arguments[i] + } + } + + // no charsets, return all requested charsets + if (!charsets || charsets.length === 0) { + return this.negotiator.charsets() + } + + return this.negotiator.charsets(charsets)[0] || false +} + +/** + * Return accepted languages or best fit based on `langs`. + * + * Given `Accept-Language: en;q=0.8, es, pt` + * an array sorted by quality is returned: + * + * ['es', 'pt', 'en'] + * + * @param {String|Array} langs... + * @return {Array|String} + * @public + */ + +Accepts.prototype.lang = +Accepts.prototype.langs = +Accepts.prototype.language = +Accepts.prototype.languages = function (languages_) { + var languages = languages_ + + // support flattened arguments + if (languages && !Array.isArray(languages)) { + languages = new Array(arguments.length) + for (var i = 0; i < languages.length; i++) { + languages[i] = arguments[i] + } + } + + // no languages, return all requested languages + if (!languages || languages.length === 0) { + return this.negotiator.languages() + } + + return this.negotiator.languages(languages)[0] || false +} + +/** + * Convert extnames to mime. + * + * @param {String} type + * @return {String} + * @private + */ + +function extToMime (type) { + return type.indexOf('/') === -1 + ? mime.lookup(type) + : type +} + +/** + * Check if mime is valid. + * + * @param {String} type + * @return {String} + * @private + */ + +function validMime (type) { + return typeof type === 'string' +} diff --git a/homework8/project_express/node_modules/accepts/package.json b/homework8/project_express/node_modules/accepts/package.json new file mode 100644 index 0000000..1bbe63b --- /dev/null +++ b/homework8/project_express/node_modules/accepts/package.json @@ -0,0 +1,86 @@ +{ + "_from": "accepts@~1.3.7", + "_id": "accepts@1.3.7", + "_inBundle": false, + "_integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "_location": "/accepts", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "accepts@~1.3.7", + "name": "accepts", + "escapedName": "accepts", + "rawSpec": "~1.3.7", + "saveSpec": null, + "fetchSpec": "~1.3.7" + }, + "_requiredBy": [ + "/express" + ], + "_resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "_shasum": "531bc726517a3b2b41f850021c6cc15eaab507cd", + "_spec": "accepts@~1.3.7", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\express", + "bugs": { + "url": "https://github.com/jshttp/accepts/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "Jonathan Ong", + "email": "me@jongleberry.com", + "url": "http://jongleberry.com" + } + ], + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "deprecated": false, + "description": "Higher-level content negotiation", + "devDependencies": { + "deep-equal": "1.0.1", + "eslint": "5.16.0", + "eslint-config-standard": "12.0.0", + "eslint-plugin-import": "2.17.2", + "eslint-plugin-markdown": "1.0.0", + "eslint-plugin-node": "8.0.1", + "eslint-plugin-promise": "4.1.1", + "eslint-plugin-standard": "4.0.0", + "mocha": "6.1.4", + "nyc": "14.0.0" + }, + "engines": { + "node": ">= 0.6" + }, + "files": [ + "LICENSE", + "HISTORY.md", + "index.js" + ], + "homepage": "https://github.com/jshttp/accepts#readme", + "keywords": [ + "content", + "negotiation", + "accept", + "accepts" + ], + "license": "MIT", + "name": "accepts", + "repository": { + "type": "git", + "url": "git+https://github.com/jshttp/accepts.git" + }, + "scripts": { + "lint": "eslint --plugin markdown --ext js,md .", + "test": "mocha --reporter spec --check-leaks --bail test/", + "test-cov": "nyc --reporter=html --reporter=text npm test", + "test-travis": "nyc --reporter=text npm test" + }, + "version": "1.3.7" +} diff --git a/homework8/project_express/node_modules/amdefine/LICENSE b/homework8/project_express/node_modules/amdefine/LICENSE new file mode 100644 index 0000000..9b25ee0 --- /dev/null +++ b/homework8/project_express/node_modules/amdefine/LICENSE @@ -0,0 +1,58 @@ +amdefine is released under two licenses: new BSD, and MIT. You may pick the +license that best suits your development needs. The text of both licenses are +provided below. + + +The "New" BSD License: +---------------------- + +Copyright (c) 2011-2016, The Dojo Foundation +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the Dojo Foundation nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +MIT License +----------- + +Copyright (c) 2011-2016, The Dojo Foundation + +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/homework8/project_express/node_modules/amdefine/README.md b/homework8/project_express/node_modules/amdefine/README.md new file mode 100644 index 0000000..037a6e8 --- /dev/null +++ b/homework8/project_express/node_modules/amdefine/README.md @@ -0,0 +1,171 @@ +# amdefine + +A module that can be used to implement AMD's define() in Node. This allows you +to code to the AMD API and have the module work in node programs without +requiring those other programs to use AMD. + +## Usage + +**1)** Update your package.json to indicate amdefine as a dependency: + +```javascript + "dependencies": { + "amdefine": ">=0.1.0" + } +``` + +Then run `npm install` to get amdefine into your project. + +**2)** At the top of each module that uses define(), place this code: + +```javascript +if (typeof define !== 'function') { var define = require('amdefine')(module) } +``` + +**Only use these snippets** when loading amdefine. If you preserve the basic structure, +with the braces, it will be stripped out when using the [RequireJS optimizer](#optimizer). + +You can add spaces, line breaks and even require amdefine with a local path, but +keep the rest of the structure to get the stripping behavior. + +As you may know, because `if` statements in JavaScript don't have their own scope, the var +declaration in the above snippet is made whether the `if` expression is truthy or not. If +RequireJS is loaded then the declaration is superfluous because `define` is already already +declared in the same scope in RequireJS. Fortunately JavaScript handles multiple `var` +declarations of the same variable in the same scope gracefully. + +If you want to deliver amdefine.js with your code rather than specifying it as a dependency +with npm, then just download the latest release and refer to it using a relative path: + +[Latest Version](https://github.com/jrburke/amdefine/raw/latest/amdefine.js) + +### amdefine/intercept + +Consider this very experimental. + +Instead of pasting the piece of text for the amdefine setup of a `define` +variable in each module you create or consume, you can use `amdefine/intercept` +instead. It will automatically insert the above snippet in each .js file loaded +by Node. + +**Warning**: you should only use this if you are creating an application that +is consuming AMD style defined()'d modules that are distributed via npm and want +to run that code in Node. + +For library code where you are not sure if it will be used by others in Node or +in the browser, then explicitly depending on amdefine and placing the code +snippet above is suggested path, instead of using `amdefine/intercept`. The +intercept module affects all .js files loaded in the Node app, and it is +inconsiderate to modify global state like that unless you are also controlling +the top level app. + +#### Why distribute AMD-style modules via npm? + +npm has a lot of weaknesses for front-end use (installed layout is not great, +should have better support for the `baseUrl + moduleID + '.js' style of loading, +single file JS installs), but some people want a JS package manager and are +willing to live with those constraints. If that is you, but still want to author +in AMD style modules to get dynamic require([]), better direct source usage and +powerful loader plugin support in the browser, then this tool can help. + +#### amdefine/intercept usage + +Just require it in your top level app module (for example index.js, server.js): + +```javascript +require('amdefine/intercept'); +``` + +The module does not return a value, so no need to assign the result to a local +variable. + +Then just require() code as you normally would with Node's require(). Any .js +loaded after the intercept require will have the amdefine check injected in +the .js source as it is loaded. It does not modify the source on disk, just +prepends some content to the text of the module as it is loaded by Node. + +#### How amdefine/intercept works + +It overrides the `Module._extensions['.js']` in Node to automatically prepend +the amdefine snippet above. So, it will affect any .js file loaded by your +app. + +## define() usage + +It is best if you use the anonymous forms of define() in your module: + +```javascript +define(function (require) { + var dependency = require('dependency'); +}); +``` + +or + +```javascript +define(['dependency'], function (dependency) { + +}); +``` + +## RequireJS optimizer integration. + +Version 1.0.3 of the [RequireJS optimizer](http://requirejs.org/docs/optimization.html) +will have support for stripping the `if (typeof define !== 'function')` check +mentioned above, so you can include this snippet for code that runs in the +browser, but avoid taking the cost of the if() statement once the code is +optimized for deployment. + +## Node 0.4 Support + +If you want to support Node 0.4, then add `require` as the second parameter to amdefine: + +```javascript +//Only if you want Node 0.4. If using 0.5 or later, use the above snippet. +if (typeof define !== 'function') { var define = require('amdefine')(module, require) } +``` + +## Limitations + +### Synchronous vs Asynchronous + +amdefine creates a define() function that is callable by your code. It will +execute and trace dependencies and call the factory function *synchronously*, +to keep the behavior in line with Node's synchronous dependency tracing. + +The exception: calling AMD's callback-style require() from inside a factory +function. The require callback is called on process.nextTick(): + +```javascript +define(function (require) { + require(['a'], function(a) { + //'a' is loaded synchronously, but + //this callback is called on process.nextTick(). + }); +}); +``` + +### Loader Plugins + +Loader plugins are supported as long as they call their load() callbacks +synchronously. So ones that do network requests will not work. However plugins +like [text](http://requirejs.org/docs/api.html#text) can load text files locally. + +The plugin API's `load.fromText()` is **not supported** in amdefine, so this means +transpiler plugins like the [CoffeeScript loader plugin](https://github.com/jrburke/require-cs) +will not work. This may be fixable, but it is a bit complex, and I do not have +enough node-fu to figure it out yet. See the source for amdefine.js if you want +to get an idea of the issues involved. + +## Tests + +To run the tests, cd to **tests** and run: + +``` +node all.js +node all-intercept.js +``` + +## License + +New BSD and MIT. Check the LICENSE file for all the details. diff --git a/homework8/project_express/node_modules/amdefine/amdefine.js b/homework8/project_express/node_modules/amdefine/amdefine.js new file mode 100644 index 0000000..ca830ba --- /dev/null +++ b/homework8/project_express/node_modules/amdefine/amdefine.js @@ -0,0 +1,301 @@ +/** vim: et:ts=4:sw=4:sts=4 + * @license amdefine 1.0.1 Copyright (c) 2011-2016, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/amdefine for details + */ + +/*jslint node: true */ +/*global module, process */ +'use strict'; + +/** + * Creates a define for node. + * @param {Object} module the "module" object that is defined by Node for the + * current module. + * @param {Function} [requireFn]. Node's require function for the current module. + * It only needs to be passed in Node versions before 0.5, when module.require + * did not exist. + * @returns {Function} a define function that is usable for the current node + * module. + */ +function amdefine(module, requireFn) { + 'use strict'; + var defineCache = {}, + loaderCache = {}, + alreadyCalled = false, + path = require('path'), + makeRequire, stringRequire; + + /** + * Trims the . and .. from an array of path segments. + * It will keep a leading path segment if a .. will become + * the first path segment, to help with module name lookups, + * which act like paths, but can be remapped. But the end result, + * all paths that use this function should look normalized. + * NOTE: this method MODIFIES the input array. + * @param {Array} ary the array of path segments. + */ + function trimDots(ary) { + var i, part; + for (i = 0; ary[i]; i+= 1) { + part = ary[i]; + if (part === '.') { + ary.splice(i, 1); + i -= 1; + } else if (part === '..') { + if (i === 1 && (ary[2] === '..' || ary[0] === '..')) { + //End of the line. Keep at least one non-dot + //path segment at the front so it can be mapped + //correctly to disk. Otherwise, there is likely + //no path mapping for a path starting with '..'. + //This can still fail, but catches the most reasonable + //uses of .. + break; + } else if (i > 0) { + ary.splice(i - 1, 2); + i -= 2; + } + } + } + } + + function normalize(name, baseName) { + var baseParts; + + //Adjust any relative paths. + if (name && name.charAt(0) === '.') { + //If have a base name, try to normalize against it, + //otherwise, assume it is a top-level require that will + //be relative to baseUrl in the end. + if (baseName) { + baseParts = baseName.split('/'); + baseParts = baseParts.slice(0, baseParts.length - 1); + baseParts = baseParts.concat(name.split('/')); + trimDots(baseParts); + name = baseParts.join('/'); + } + } + + return name; + } + + /** + * Create the normalize() function passed to a loader plugin's + * normalize method. + */ + function makeNormalize(relName) { + return function (name) { + return normalize(name, relName); + }; + } + + function makeLoad(id) { + function load(value) { + loaderCache[id] = value; + } + + load.fromText = function (id, text) { + //This one is difficult because the text can/probably uses + //define, and any relative paths and requires should be relative + //to that id was it would be found on disk. But this would require + //bootstrapping a module/require fairly deeply from node core. + //Not sure how best to go about that yet. + throw new Error('amdefine does not implement load.fromText'); + }; + + return load; + } + + makeRequire = function (systemRequire, exports, module, relId) { + function amdRequire(deps, callback) { + if (typeof deps === 'string') { + //Synchronous, single module require('') + return stringRequire(systemRequire, exports, module, deps, relId); + } else { + //Array of dependencies with a callback. + + //Convert the dependencies to modules. + deps = deps.map(function (depName) { + return stringRequire(systemRequire, exports, module, depName, relId); + }); + + //Wait for next tick to call back the require call. + if (callback) { + process.nextTick(function () { + callback.apply(null, deps); + }); + } + } + } + + amdRequire.toUrl = function (filePath) { + if (filePath.indexOf('.') === 0) { + return normalize(filePath, path.dirname(module.filename)); + } else { + return filePath; + } + }; + + return amdRequire; + }; + + //Favor explicit value, passed in if the module wants to support Node 0.4. + requireFn = requireFn || function req() { + return module.require.apply(module, arguments); + }; + + function runFactory(id, deps, factory) { + var r, e, m, result; + + if (id) { + e = loaderCache[id] = {}; + m = { + id: id, + uri: __filename, + exports: e + }; + r = makeRequire(requireFn, e, m, id); + } else { + //Only support one define call per file + if (alreadyCalled) { + throw new Error('amdefine with no module ID cannot be called more than once per file.'); + } + alreadyCalled = true; + + //Use the real variables from node + //Use module.exports for exports, since + //the exports in here is amdefine exports. + e = module.exports; + m = module; + r = makeRequire(requireFn, e, m, module.id); + } + + //If there are dependencies, they are strings, so need + //to convert them to dependency values. + if (deps) { + deps = deps.map(function (depName) { + return r(depName); + }); + } + + //Call the factory with the right dependencies. + if (typeof factory === 'function') { + result = factory.apply(m.exports, deps); + } else { + result = factory; + } + + if (result !== undefined) { + m.exports = result; + if (id) { + loaderCache[id] = m.exports; + } + } + } + + stringRequire = function (systemRequire, exports, module, id, relId) { + //Split the ID by a ! so that + var index = id.indexOf('!'), + originalId = id, + prefix, plugin; + + if (index === -1) { + id = normalize(id, relId); + + //Straight module lookup. If it is one of the special dependencies, + //deal with it, otherwise, delegate to node. + if (id === 'require') { + return makeRequire(systemRequire, exports, module, relId); + } else if (id === 'exports') { + return exports; + } else if (id === 'module') { + return module; + } else if (loaderCache.hasOwnProperty(id)) { + return loaderCache[id]; + } else if (defineCache[id]) { + runFactory.apply(null, defineCache[id]); + return loaderCache[id]; + } else { + if(systemRequire) { + return systemRequire(originalId); + } else { + throw new Error('No module with ID: ' + id); + } + } + } else { + //There is a plugin in play. + prefix = id.substring(0, index); + id = id.substring(index + 1, id.length); + + plugin = stringRequire(systemRequire, exports, module, prefix, relId); + + if (plugin.normalize) { + id = plugin.normalize(id, makeNormalize(relId)); + } else { + //Normalize the ID normally. + id = normalize(id, relId); + } + + if (loaderCache[id]) { + return loaderCache[id]; + } else { + plugin.load(id, makeRequire(systemRequire, exports, module, relId), makeLoad(id), {}); + + return loaderCache[id]; + } + } + }; + + //Create a define function specific to the module asking for amdefine. + function define(id, deps, factory) { + if (Array.isArray(id)) { + factory = deps; + deps = id; + id = undefined; + } else if (typeof id !== 'string') { + factory = id; + id = deps = undefined; + } + + if (deps && !Array.isArray(deps)) { + factory = deps; + deps = undefined; + } + + if (!deps) { + deps = ['require', 'exports', 'module']; + } + + //Set up properties for this module. If an ID, then use + //internal cache. If no ID, then use the external variables + //for this node module. + if (id) { + //Put the module in deep freeze until there is a + //require call for it. + defineCache[id] = [id, deps, factory]; + } else { + runFactory(id, deps, factory); + } + } + + //define.require, which has access to all the values in the + //cache. Useful for AMD modules that all have IDs in the file, + //but need to finally export a value to node based on one of those + //IDs. + define.require = function (id) { + if (loaderCache[id]) { + return loaderCache[id]; + } + + if (defineCache[id]) { + runFactory.apply(null, defineCache[id]); + return loaderCache[id]; + } + }; + + define.amd = {}; + + return define; +} + +module.exports = amdefine; diff --git a/homework8/project_express/node_modules/amdefine/intercept.js b/homework8/project_express/node_modules/amdefine/intercept.js new file mode 100644 index 0000000..771a983 --- /dev/null +++ b/homework8/project_express/node_modules/amdefine/intercept.js @@ -0,0 +1,36 @@ +/*jshint node: true */ +var inserted, + Module = require('module'), + fs = require('fs'), + existingExtFn = Module._extensions['.js'], + amdefineRegExp = /amdefine\.js/; + +inserted = "if (typeof define !== 'function') {var define = require('amdefine')(module)}"; + +//From the node/lib/module.js source: +function stripBOM(content) { + // Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) + // because the buffer-to-string conversion in `fs.readFileSync()` + // translates it to FEFF, the UTF-16 BOM. + if (content.charCodeAt(0) === 0xFEFF) { + content = content.slice(1); + } + return content; +} + +//Also adapted from the node/lib/module.js source: +function intercept(module, filename) { + var content = stripBOM(fs.readFileSync(filename, 'utf8')); + + if (!amdefineRegExp.test(module.id)) { + content = inserted + content; + } + + module._compile(content, filename); +} + +intercept._id = 'amdefine/intercept'; + +if (!existingExtFn._id || existingExtFn._id !== intercept._id) { + Module._extensions['.js'] = intercept; +} diff --git a/homework8/project_express/node_modules/amdefine/package.json b/homework8/project_express/node_modules/amdefine/package.json new file mode 100644 index 0000000..8be1714 --- /dev/null +++ b/homework8/project_express/node_modules/amdefine/package.json @@ -0,0 +1,16 @@ +{ + "name": "amdefine", + "description": "Provide AMD's define() API for declaring modules in the AMD format", + "version": "1.0.1", + "homepage": "http://github.com/jrburke/amdefine", + "author": "James Burke (http://github.com/jrburke)", + "license": "BSD-3-Clause OR MIT", + "repository": { + "type": "git", + "url": "https://github.com/jrburke/amdefine.git" + }, + "main": "./amdefine.js", + "engines": { + "node": ">=0.4.2" + } +} diff --git a/homework8/project_express/node_modules/anymatch/LICENSE b/homework8/project_express/node_modules/anymatch/LICENSE new file mode 100644 index 0000000..491766c --- /dev/null +++ b/homework8/project_express/node_modules/anymatch/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) 2019 Elan Shanker, Paul Miller (https://paulmillr.com) + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/homework8/project_express/node_modules/anymatch/README.md b/homework8/project_express/node_modules/anymatch/README.md new file mode 100644 index 0000000..1dd67f5 --- /dev/null +++ b/homework8/project_express/node_modules/anymatch/README.md @@ -0,0 +1,87 @@ +anymatch [![Build Status](https://travis-ci.org/micromatch/anymatch.svg?branch=master)](https://travis-ci.org/micromatch/anymatch) [![Coverage Status](https://img.shields.io/coveralls/micromatch/anymatch.svg?branch=master)](https://coveralls.io/r/micromatch/anymatch?branch=master) +====== +Javascript module to match a string against a regular expression, glob, string, +or function that takes the string as an argument and returns a truthy or falsy +value. The matcher can also be an array of any or all of these. Useful for +allowing a very flexible user-defined config to define things like file paths. + +__Note: This module has Bash-parity, please be aware that Windows-style backslashes are not supported as separators. See https://github.com/micromatch/micromatch#backslashes for more information.__ + + +Usage +----- +```sh +npm install anymatch +``` + +#### anymatch(matchers, testString, [returnIndex], [options]) +* __matchers__: (_Array|String|RegExp|Function_) +String to be directly matched, string with glob patterns, regular expression +test, function that takes the testString as an argument and returns a truthy +value if it should be matched, or an array of any number and mix of these types. +* __testString__: (_String|Array_) The string to test against the matchers. If +passed as an array, the first element of the array will be used as the +`testString` for non-function matchers, while the entire array will be applied +as the arguments for function matchers. +* __options__: (_Object_ [optional]_) Any of the [picomatch](https://github.com/micromatch/picomatch#options) options. + * __returnIndex__: (_Boolean [optional]_) If true, return the array index of +the first matcher that that testString matched, or -1 if no match, instead of a +boolean result. + +```js +const anymatch = require('anymatch'); + +const matchers = [ 'path/to/file.js', 'path/anyjs/**/*.js', /foo.js$/, string => string.includes('bar') && string.length > 10 ] ; + +anymatch(matchers, 'path/to/file.js'); // true +anymatch(matchers, 'path/anyjs/baz.js'); // true +anymatch(matchers, 'path/to/foo.js'); // true +anymatch(matchers, 'path/to/bar.js'); // true +anymatch(matchers, 'bar.js'); // false + +// returnIndex = true +anymatch(matchers, 'foo.js', {returnIndex: true}); // 2 +anymatch(matchers, 'path/anyjs/foo.js', {returnIndex: true}); // 1 + +// any picomatc + +// using globs to match directories and their children +anymatch('node_modules', 'node_modules'); // true +anymatch('node_modules', 'node_modules/somelib/index.js'); // false +anymatch('node_modules/**', 'node_modules/somelib/index.js'); // true +anymatch('node_modules/**', '/absolute/path/to/node_modules/somelib/index.js'); // false +anymatch('**/node_modules/**', '/absolute/path/to/node_modules/somelib/index.js'); // true + +const matcher = anymatch(matchers); +['foo.js', 'bar.js'].filter(matcher); // [ 'foo.js' ] +anymatch master* ❯ + +``` + +#### anymatch(matchers) +You can also pass in only your matcher(s) to get a curried function that has +already been bound to the provided matching criteria. This can be used as an +`Array#filter` callback. + +```js +var matcher = anymatch(matchers); + +matcher('path/to/file.js'); // true +matcher('path/anyjs/baz.js', true); // 1 + +['foo.js', 'bar.js'].filter(matcher); // ['foo.js'] +``` + +Changelog +---------- +[See release notes page on GitHub](https://github.com/micromatch/anymatch/releases) + +- **v3.0:** Removed `startIndex` and `endIndex` arguments. Node 8.x-only. +- **v2.0:** [micromatch](https://github.com/jonschlinkert/micromatch) moves away from minimatch-parity and inline with Bash. This includes handling backslashes differently (see https://github.com/micromatch/micromatch#backslashes for more information). +- **v1.2:** anymatch uses [micromatch](https://github.com/jonschlinkert/micromatch) +for glob pattern matching. Issues with glob pattern matching should be +reported directly to the [micromatch issue tracker](https://github.com/jonschlinkert/micromatch/issues). + +License +------- +[ISC](https://raw.github.com/micromatch/anymatch/master/LICENSE) diff --git a/homework8/project_express/node_modules/anymatch/index.d.ts b/homework8/project_express/node_modules/anymatch/index.d.ts new file mode 100644 index 0000000..196d061 --- /dev/null +++ b/homework8/project_express/node_modules/anymatch/index.d.ts @@ -0,0 +1,19 @@ +type AnymatchFn = (testString: string) => boolean; +type AnymatchPattern = string|RegExp|AnymatchFn; +type AnymatchMatcher = AnymatchPattern|AnymatchPattern[] +type AnymatchTester = { + (testString: string|any[], returnIndex: true): number; + (testString: string|any[]): boolean; +} + +type PicomatchOptions = {dot: boolean}; + +declare const anymatch: { + (matchers: AnymatchMatcher): AnymatchTester; + (matchers: AnymatchMatcher, testString: string|any[], returnIndex: true | PicomatchOptions): number; + (matchers: AnymatchMatcher, testString: string|any[]): boolean; +} + +export {AnymatchMatcher as Matcher} +export {AnymatchTester as Tester} +export default anymatch diff --git a/homework8/project_express/node_modules/anymatch/index.js b/homework8/project_express/node_modules/anymatch/index.js new file mode 100644 index 0000000..9fb3ebb --- /dev/null +++ b/homework8/project_express/node_modules/anymatch/index.js @@ -0,0 +1,104 @@ +'use strict'; + +Object.defineProperty(exports, "__esModule", { value: true }); + +const picomatch = require('picomatch'); +const normalizePath = require('normalize-path'); + +/** + * @typedef {(testString: string) => boolean} AnymatchFn + * @typedef {string|RegExp|AnymatchFn} AnymatchPattern + * @typedef {AnymatchPattern|AnymatchPattern[]} AnymatchMatcher + */ +const BANG = '!'; +const DEFAULT_OPTIONS = {returnIndex: false}; +const arrify = (item) => Array.isArray(item) ? item : [item]; + +/** + * @param {AnymatchPattern} matcher + * @param {object} options + * @returns {AnymatchFn} + */ +const createPattern = (matcher, options) => { + if (typeof matcher === 'function') { + return matcher; + } + if (typeof matcher === 'string') { + const glob = picomatch(matcher, options); + return (string) => matcher === string || glob(string); + } + if (matcher instanceof RegExp) { + return (string) => matcher.test(string); + } + return (string) => false; +}; + +/** + * @param {Array} patterns + * @param {Array} negPatterns + * @param {String|Array} args + * @param {Boolean} returnIndex + * @returns {boolean|number} + */ +const matchPatterns = (patterns, negPatterns, args, returnIndex) => { + const isList = Array.isArray(args); + const _path = isList ? args[0] : args; + if (!isList && typeof _path !== 'string') { + throw new TypeError('anymatch: second argument must be a string: got ' + + Object.prototype.toString.call(_path)) + } + const path = normalizePath(_path); + + for (let index = 0; index < negPatterns.length; index++) { + const nglob = negPatterns[index]; + if (nglob(path)) { + return returnIndex ? -1 : false; + } + } + + const applied = isList && [path].concat(args.slice(1)); + for (let index = 0; index < patterns.length; index++) { + const pattern = patterns[index]; + if (isList ? pattern(...applied) : pattern(path)) { + return returnIndex ? index : true; + } + } + + return returnIndex ? -1 : false; +}; + +/** + * @param {AnymatchMatcher} matchers + * @param {Array|string} testString + * @param {object} options + * @returns {boolean|number|Function} + */ +const anymatch = (matchers, testString, options = DEFAULT_OPTIONS) => { + if (matchers == null) { + throw new TypeError('anymatch: specify first argument'); + } + const opts = typeof options === 'boolean' ? {returnIndex: options} : options; + const returnIndex = opts.returnIndex || false; + + // Early cache for matchers. + const mtchers = arrify(matchers); + const negatedGlobs = mtchers + .filter(item => typeof item === 'string' && item.charAt(0) === BANG) + .map(item => item.slice(1)) + .map(item => picomatch(item, opts)); + const patterns = mtchers + .filter(item => typeof item !== 'string' || (typeof item === 'string' && item.charAt(0) !== BANG)) + .map(matcher => createPattern(matcher, opts)); + + if (testString == null) { + return (testString, ri = false) => { + const returnIndex = typeof ri === 'boolean' ? ri : false; + return matchPatterns(patterns, negatedGlobs, testString, returnIndex); + } + } + + return matchPatterns(patterns, negatedGlobs, testString, returnIndex); +}; + +anymatch.default = anymatch; +module.exports = anymatch; diff --git a/homework8/project_express/node_modules/anymatch/package.json b/homework8/project_express/node_modules/anymatch/package.json new file mode 100644 index 0000000..f9b5284 --- /dev/null +++ b/homework8/project_express/node_modules/anymatch/package.json @@ -0,0 +1,48 @@ +{ + "name": "anymatch", + "version": "3.1.2", + "description": "Matches strings against configurable strings, globs, regular expressions, and/or functions", + "files": [ + "index.js", + "index.d.ts" + ], + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "author": { + "name": "Elan Shanker", + "url": "https://github.com/es128" + }, + "license": "ISC", + "homepage": "https://github.com/micromatch/anymatch", + "repository": { + "type": "git", + "url": "https://github.com/micromatch/anymatch" + }, + "keywords": [ + "match", + "any", + "string", + "file", + "fs", + "list", + "glob", + "regex", + "regexp", + "regular", + "expression", + "function" + ], + "scripts": { + "test": "nyc mocha", + "mocha": "mocha" + }, + "devDependencies": { + "mocha": "^6.1.3", + "nyc": "^14.0.0" + }, + "engines": { + "node": ">= 8" + } +} diff --git a/homework8/project_express/node_modules/array-flatten/LICENSE b/homework8/project_express/node_modules/array-flatten/LICENSE new file mode 100644 index 0000000..983fbe8 --- /dev/null +++ b/homework8/project_express/node_modules/array-flatten/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) + +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/homework8/project_express/node_modules/array-flatten/README.md b/homework8/project_express/node_modules/array-flatten/README.md new file mode 100644 index 0000000..91fa5b6 --- /dev/null +++ b/homework8/project_express/node_modules/array-flatten/README.md @@ -0,0 +1,43 @@ +# Array Flatten + +[![NPM version][npm-image]][npm-url] +[![NPM downloads][downloads-image]][downloads-url] +[![Build status][travis-image]][travis-url] +[![Test coverage][coveralls-image]][coveralls-url] + +> Flatten an array of nested arrays into a single flat array. Accepts an optional depth. + +## Installation + +``` +npm install array-flatten --save +``` + +## Usage + +```javascript +var flatten = require('array-flatten') + +flatten([1, [2, [3, [4, [5], 6], 7], 8], 9]) +//=> [1, 2, 3, 4, 5, 6, 7, 8, 9] + +flatten([1, [2, [3, [4, [5], 6], 7], 8], 9], 2) +//=> [1, 2, 3, [4, [5], 6], 7, 8, 9] + +(function () { + flatten(arguments) //=> [1, 2, 3] +})(1, [2, 3]) +``` + +## License + +MIT + +[npm-image]: https://img.shields.io/npm/v/array-flatten.svg?style=flat +[npm-url]: https://npmjs.org/package/array-flatten +[downloads-image]: https://img.shields.io/npm/dm/array-flatten.svg?style=flat +[downloads-url]: https://npmjs.org/package/array-flatten +[travis-image]: https://img.shields.io/travis/blakeembrey/array-flatten.svg?style=flat +[travis-url]: https://travis-ci.org/blakeembrey/array-flatten +[coveralls-image]: https://img.shields.io/coveralls/blakeembrey/array-flatten.svg?style=flat +[coveralls-url]: https://coveralls.io/r/blakeembrey/array-flatten?branch=master diff --git a/homework8/project_express/node_modules/array-flatten/array-flatten.js b/homework8/project_express/node_modules/array-flatten/array-flatten.js new file mode 100644 index 0000000..089117b --- /dev/null +++ b/homework8/project_express/node_modules/array-flatten/array-flatten.js @@ -0,0 +1,64 @@ +'use strict' + +/** + * Expose `arrayFlatten`. + */ +module.exports = arrayFlatten + +/** + * Recursive flatten function with depth. + * + * @param {Array} array + * @param {Array} result + * @param {Number} depth + * @return {Array} + */ +function flattenWithDepth (array, result, depth) { + for (var i = 0; i < array.length; i++) { + var value = array[i] + + if (depth > 0 && Array.isArray(value)) { + flattenWithDepth(value, result, depth - 1) + } else { + result.push(value) + } + } + + return result +} + +/** + * Recursive flatten function. Omitting depth is slightly faster. + * + * @param {Array} array + * @param {Array} result + * @return {Array} + */ +function flattenForever (array, result) { + for (var i = 0; i < array.length; i++) { + var value = array[i] + + if (Array.isArray(value)) { + flattenForever(value, result) + } else { + result.push(value) + } + } + + return result +} + +/** + * Flatten an array, with the ability to define a depth. + * + * @param {Array} array + * @param {Number} depth + * @return {Array} + */ +function arrayFlatten (array, depth) { + if (depth == null) { + return flattenForever(array, []) + } + + return flattenWithDepth(array, [], depth) +} diff --git a/homework8/project_express/node_modules/array-flatten/package.json b/homework8/project_express/node_modules/array-flatten/package.json new file mode 100644 index 0000000..81593a2 --- /dev/null +++ b/homework8/project_express/node_modules/array-flatten/package.json @@ -0,0 +1,64 @@ +{ + "_from": "array-flatten@1.1.1", + "_id": "array-flatten@1.1.1", + "_inBundle": false, + "_integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "_location": "/array-flatten", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "array-flatten@1.1.1", + "name": "array-flatten", + "escapedName": "array-flatten", + "rawSpec": "1.1.1", + "saveSpec": null, + "fetchSpec": "1.1.1" + }, + "_requiredBy": [ + "/express" + ], + "_resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "_shasum": "9a5f699051b1e7073328f2a008968b64ea2955d2", + "_spec": "array-flatten@1.1.1", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\express", + "author": { + "name": "Blake Embrey", + "email": "hello@blakeembrey.com", + "url": "http://blakeembrey.me" + }, + "bugs": { + "url": "https://github.com/blakeembrey/array-flatten/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Flatten an array of nested arrays into a single flat array", + "devDependencies": { + "istanbul": "^0.3.13", + "mocha": "^2.2.4", + "pre-commit": "^1.0.7", + "standard": "^3.7.3" + }, + "files": [ + "array-flatten.js", + "LICENSE" + ], + "homepage": "https://github.com/blakeembrey/array-flatten", + "keywords": [ + "array", + "flatten", + "arguments", + "depth" + ], + "license": "MIT", + "main": "array-flatten.js", + "name": "array-flatten", + "repository": { + "type": "git", + "url": "git://github.com/blakeembrey/array-flatten.git" + }, + "scripts": { + "test": "istanbul cover _mocha -- -R spec" + }, + "version": "1.1.1" +} diff --git a/homework8/project_express/node_modules/async/LICENSE b/homework8/project_express/node_modules/async/LICENSE new file mode 100644 index 0000000..b7f9d50 --- /dev/null +++ b/homework8/project_express/node_modules/async/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Caolan McMahon + +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/homework8/project_express/node_modules/async/README.md b/homework8/project_express/node_modules/async/README.md new file mode 100644 index 0000000..951f76e --- /dev/null +++ b/homework8/project_express/node_modules/async/README.md @@ -0,0 +1,1425 @@ +# Async.js + +Async is a utility module which provides straight-forward, powerful functions +for working with asynchronous JavaScript. Although originally designed for +use with [node.js](http://nodejs.org), it can also be used directly in the +browser. Also supports [component](https://github.com/component/component). + +Async provides around 20 functions that include the usual 'functional' +suspects (map, reduce, filter, each…) as well as some common patterns +for asynchronous control flow (parallel, series, waterfall…). All these +functions assume you follow the node.js convention of providing a single +callback as the last argument of your async function. + + +## Quick Examples + +```javascript +async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file +}); + +async.filter(['file1','file2','file3'], fs.exists, function(results){ + // results now equals an array of the existing files +}); + +async.parallel([ + function(){ ... }, + function(){ ... } +], callback); + +async.series([ + function(){ ... }, + function(){ ... } +]); +``` + +There are many more functions available so take a look at the docs below for a +full list. This module aims to be comprehensive, so if you feel anything is +missing please create a GitHub issue for it. + +## Common Pitfalls + +### Binding a context to an iterator + +This section is really about bind, not about async. If you are wondering how to +make async execute your iterators in a given context, or are confused as to why +a method of another library isn't working as an iterator, study this example: + +```js +// Here is a simple object with an (unnecessarily roundabout) squaring method +var AsyncSquaringLibrary = { + squareExponent: 2, + square: function(number, callback){ + var result = Math.pow(number, this.squareExponent); + setTimeout(function(){ + callback(null, result); + }, 200); + } +}; + +async.map([1, 2, 3], AsyncSquaringLibrary.square, function(err, result){ + // result is [NaN, NaN, NaN] + // This fails because the `this.squareExponent` expression in the square + // function is not evaluated in the context of AsyncSquaringLibrary, and is + // therefore undefined. +}); + +async.map([1, 2, 3], AsyncSquaringLibrary.square.bind(AsyncSquaringLibrary), function(err, result){ + // result is [1, 4, 9] + // With the help of bind we can attach a context to the iterator before + // passing it to async. Now the square function will be executed in its + // 'home' AsyncSquaringLibrary context and the value of `this.squareExponent` + // will be as expected. +}); +``` + +## Download + +The source is available for download from +[GitHub](http://github.com/caolan/async). +Alternatively, you can install using Node Package Manager (npm): + + npm install async + +__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 29.6kb Uncompressed + +## In the Browser + +So far it's been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage: + +```html + + +``` + +## Documentation + +### Collections + +* [each](#each) +* [eachSeries](#eachSeries) +* [eachLimit](#eachLimit) +* [map](#map) +* [mapSeries](#mapSeries) +* [mapLimit](#mapLimit) +* [filter](#filter) +* [filterSeries](#filterSeries) +* [reject](#reject) +* [rejectSeries](#rejectSeries) +* [reduce](#reduce) +* [reduceRight](#reduceRight) +* [detect](#detect) +* [detectSeries](#detectSeries) +* [sortBy](#sortBy) +* [some](#some) +* [every](#every) +* [concat](#concat) +* [concatSeries](#concatSeries) + +### Control Flow + +* [series](#series) +* [parallel](#parallel) +* [parallelLimit](#parallellimittasks-limit-callback) +* [whilst](#whilst) +* [doWhilst](#doWhilst) +* [until](#until) +* [doUntil](#doUntil) +* [forever](#forever) +* [waterfall](#waterfall) +* [compose](#compose) +* [applyEach](#applyEach) +* [applyEachSeries](#applyEachSeries) +* [queue](#queue) +* [cargo](#cargo) +* [auto](#auto) +* [iterator](#iterator) +* [apply](#apply) +* [nextTick](#nextTick) +* [times](#times) +* [timesSeries](#timesSeries) + +### Utils + +* [memoize](#memoize) +* [unmemoize](#unmemoize) +* [log](#log) +* [dir](#dir) +* [noConflict](#noConflict) + + +## Collections + + + +### each(arr, iterator, callback) + +Applies an iterator function to each item in an array, in parallel. +The iterator is called with an item from the list and a callback for when it +has finished. If the iterator passes an error to this callback, the main +callback for the each function is immediately called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err) which must be called once it has + completed. If no error has occured, the callback should be run without + arguments or with an explicit null argument. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + +```js +// assuming openFiles is an array of file names and saveFile is a function +// to save the modified contents of that file: + +async.each(openFiles, saveFile, function(err){ + // if any of the saves produced an error, err would equal that error +}); +``` + +--------------------------------------- + + + +### eachSeries(arr, iterator, callback) + +The same as each only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. This means the iterator functions will complete in order. + + +--------------------------------------- + + + +### eachLimit(arr, limit, iterator, callback) + +The same as each only no more than "limit" iterators will be simultaneously +running at any time. + +Note that the items are not processed in batches, so there is no guarantee that + the first "limit" iterator functions will complete before any others are +started. + +__Arguments__ + +* arr - An array to iterate over. +* limit - The maximum number of iterators to run at any time. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err) which must be called once it has + completed. If no error has occured, the callback should be run without + arguments or with an explicit null argument. +* callback(err) - A callback which is called after all the iterator functions + have finished, or an error has occurred. + +__Example__ + +```js +// Assume documents is an array of JSON objects and requestApi is a +// function that interacts with a rate-limited REST api. + +async.eachLimit(documents, 20, requestApi, function(err){ + // if any of the saves produced an error, err would equal that error +}); +``` + +--------------------------------------- + + +### map(arr, iterator, callback) + +Produces a new array of values by mapping each value in the given array through +the iterator function. The iterator is called with an item from the array and a +callback for when it has finished processing. The callback takes 2 arguments, +an error and the transformed item from the array. If the iterator passes an +error to this callback, the main callback for the map function is immediately +called with the error. + +Note, that since this function applies the iterator to each item in parallel +there is no guarantee that the iterator functions will complete in order, however +the results array will be in the same order as the original array. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, transformed) which must be called once + it has completed with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + +```js +async.map(['file1','file2','file3'], fs.stat, function(err, results){ + // results is now an array of stats for each file +}); +``` + +--------------------------------------- + + +### mapSeries(arr, iterator, callback) + +The same as map only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +--------------------------------------- + + +### mapLimit(arr, limit, iterator, callback) + +The same as map only no more than "limit" iterators will be simultaneously +running at any time. + +Note that the items are not processed in batches, so there is no guarantee that + the first "limit" iterator functions will complete before any others are +started. + +__Arguments__ + +* arr - An array to iterate over. +* limit - The maximum number of iterators to run at any time. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, transformed) which must be called once + it has completed with an error (which can be null) and a transformed item. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array of the + transformed items from the original array. + +__Example__ + +```js +async.mapLimit(['file1','file2','file3'], 1, fs.stat, function(err, results){ + // results is now an array of stats for each file +}); +``` + +--------------------------------------- + + +### filter(arr, iterator, callback) + +__Alias:__ select + +Returns a new array of all the values which pass an async truth test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like fs.exists. This operation is +performed in parallel, but the results array will be in the same order as the +original. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(results) - A callback which is called after all the iterator + functions have finished. + +__Example__ + +```js +async.filter(['file1','file2','file3'], fs.exists, function(results){ + // results now equals an array of the existing files +}); +``` + +--------------------------------------- + + +### filterSeries(arr, iterator, callback) + +__alias:__ selectSeries + +The same as filter only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + +--------------------------------------- + + +### reject(arr, iterator, callback) + +The opposite of filter. Removes values that pass an async truth test. + +--------------------------------------- + + +### rejectSeries(arr, iterator, callback) + +The same as reject, only the iterator is applied to each item in the array +in series. + + +--------------------------------------- + + +### reduce(arr, memo, iterator, callback) + +__aliases:__ inject, foldl + +Reduces a list of values into a single value using an async iterator to return +each successive step. Memo is the initial state of the reduction. This +function only operates in series. For performance reasons, it may make sense to +split a call to this function into a parallel map, then use the normal +Array.prototype.reduce on the results. This function is for situations where +each step in the reduction needs to be async, if you can get the data before +reducing it then it's probably a good idea to do so. + +__Arguments__ + +* arr - An array to iterate over. +* memo - The initial state of the reduction. +* iterator(memo, item, callback) - A function applied to each item in the + array to produce the next step in the reduction. The iterator is passed a + callback(err, reduction) which accepts an optional error as its first + argument, and the state of the reduction as the second. If an error is + passed to the callback, the reduction is stopped and the main callback is + immediately called with the error. +* callback(err, result) - A callback which is called after all the iterator + functions have finished. Result is the reduced value. + +__Example__ + +```js +async.reduce([1,2,3], 0, function(memo, item, callback){ + // pointless async: + process.nextTick(function(){ + callback(null, memo + item) + }); +}, function(err, result){ + // result is now equal to the last value of memo, which is 6 +}); +``` + +--------------------------------------- + + +### reduceRight(arr, memo, iterator, callback) + +__Alias:__ foldr + +Same as reduce, only operates on the items in the array in reverse order. + + +--------------------------------------- + + +### detect(arr, iterator, callback) + +Returns the first value in a list that passes an async truth test. The +iterator is applied in parallel, meaning the first iterator to return true will +fire the detect callback with that result. That means the result might not be +the first item in the original array (in terms of order) that passes the test. + +If order within the original array is important then look at detectSeries. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + the first item in the array that passes the truth test (iterator) or the + value undefined if none passed. + +__Example__ + +```js +async.detect(['file1','file2','file3'], fs.exists, function(result){ + // result now equals the first file in the list that exists +}); +``` + +--------------------------------------- + + +### detectSeries(arr, iterator, callback) + +The same as detect, only the iterator is applied to each item in the array +in series. This means the result is always the first in the original array (in +terms of array order) that passes the truth test. + + +--------------------------------------- + + +### sortBy(arr, iterator, callback) + +Sorts a list by the results of running each value through an async iterator. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, sortValue) which must be called once it + has completed with an error (which can be null) and a value to use as the sort + criteria. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is the items from + the original array sorted by the values returned by the iterator calls. + +__Example__ + +```js +async.sortBy(['file1','file2','file3'], function(file, callback){ + fs.stat(file, function(err, stats){ + callback(err, stats.mtime); + }); +}, function(err, results){ + // results is now the original array of files sorted by + // modified date +}); +``` + +--------------------------------------- + + +### some(arr, iterator, callback) + +__Alias:__ any + +Returns true if at least one element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like fs.exists. Once any iterator +call returns true, the main callback is immediately called. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(result) - A callback which is called as soon as any iterator returns + true, or after all the iterator functions have finished. Result will be + either true or false depending on the values of the async tests. + +__Example__ + +```js +async.some(['file1','file2','file3'], fs.exists, function(result){ + // if result is true then at least one of the files exists +}); +``` + +--------------------------------------- + + +### every(arr, iterator, callback) + +__Alias:__ all + +Returns true if every element in the array satisfies an async test. +_The callback for each iterator call only accepts a single argument of true or +false, it does not accept an error argument first!_ This is in-line with the +way node libraries work with truth tests like fs.exists. + +__Arguments__ + +* arr - An array to iterate over. +* iterator(item, callback) - A truth test to apply to each item in the array. + The iterator is passed a callback(truthValue) which must be called with a + boolean argument once it has completed. +* callback(result) - A callback which is called after all the iterator + functions have finished. Result will be either true or false depending on + the values of the async tests. + +__Example__ + +```js +async.every(['file1','file2','file3'], fs.exists, function(result){ + // if result is true then every file exists +}); +``` + +--------------------------------------- + + +### concat(arr, iterator, callback) + +Applies an iterator to each item in a list, concatenating the results. Returns the +concatenated list. The iterators are called in parallel, and the results are +concatenated as they return. There is no guarantee that the results array will +be returned in the original order of the arguments passed to the iterator function. + +__Arguments__ + +* arr - An array to iterate over +* iterator(item, callback) - A function to apply to each item in the array. + The iterator is passed a callback(err, results) which must be called once it + has completed with an error (which can be null) and an array of results. +* callback(err, results) - A callback which is called after all the iterator + functions have finished, or an error has occurred. Results is an array containing + the concatenated results of the iterator function. + +__Example__ + +```js +async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){ + // files is now a list of filenames that exist in the 3 directories +}); +``` + +--------------------------------------- + + +### concatSeries(arr, iterator, callback) + +Same as async.concat, but executes in series instead of parallel. + + +## Control Flow + + +### series(tasks, [callback]) + +Run an array of functions in series, each one running once the previous +function has completed. If any functions in the series pass an error to its +callback, no more functions are run and the callback for the series is +immediately called with the value of the error. Once the tasks have completed, +the results are passed to the final callback as an array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.series. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback(err, result) it must call on completion with an error (which can + be null) and an optional result value. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +__Example__ + +```js +async.series([ + function(callback){ + // do some stuff ... + callback(null, 'one'); + }, + function(callback){ + // do some more stuff ... + callback(null, 'two'); + } +], +// optional callback +function(err, results){ + // results is now equal to ['one', 'two'] +}); + + +// an example using an object instead of an array +async.series({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + } +}, +function(err, results) { + // results is now equal to: {one: 1, two: 2} +}); +``` + +--------------------------------------- + + +### parallel(tasks, [callback]) + +Run an array of functions in parallel, without waiting until the previous +function has completed. If any of the functions pass an error to its +callback, the main callback is immediately called with the value of the error. +Once the tasks have completed, the results are passed to the final callback as an +array. + +It is also possible to use an object instead of an array. Each property will be +run as a function and the results will be passed to the final callback as an object +instead of an array. This can be a more readable way of handling results from +async.parallel. + + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback(err, result) it must call on completion with an error (which can + be null) and an optional result value. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +__Example__ + +```js +async.parallel([ + function(callback){ + setTimeout(function(){ + callback(null, 'one'); + }, 200); + }, + function(callback){ + setTimeout(function(){ + callback(null, 'two'); + }, 100); + } +], +// optional callback +function(err, results){ + // the results array will equal ['one','two'] even though + // the second function had a shorter timeout. +}); + + +// an example using an object instead of an array +async.parallel({ + one: function(callback){ + setTimeout(function(){ + callback(null, 1); + }, 200); + }, + two: function(callback){ + setTimeout(function(){ + callback(null, 2); + }, 100); + } +}, +function(err, results) { + // results is now equals to: {one: 1, two: 2} +}); +``` + +--------------------------------------- + + +### parallelLimit(tasks, limit, [callback]) + +The same as parallel only the tasks are executed in parallel with a maximum of "limit" +tasks executing at any time. + +Note that the tasks are not executed in batches, so there is no guarantee that +the first "limit" tasks will complete before any others are started. + +__Arguments__ + +* tasks - An array or object containing functions to run, each function is passed + a callback(err, result) it must call on completion with an error (which can + be null) and an optional result value. +* limit - The maximum number of tasks to run at any time. +* callback(err, results) - An optional callback to run once all the functions + have completed. This function gets a results array (or object) containing all + the result arguments passed to the task callbacks. + +--------------------------------------- + + +### whilst(test, fn, callback) + +Repeatedly call fn, while test returns true. Calls the callback when stopped, +or an error occurs. + +__Arguments__ + +* test() - synchronous truth test to perform before each execution of fn. +* fn(callback) - A function to call each time the test passes. The function is + passed a callback(err) which must be called once it has completed with an + optional error argument. +* callback(err) - A callback which is called after the test fails and repeated + execution of fn has stopped. + +__Example__ + +```js +var count = 0; + +async.whilst( + function () { return count < 5; }, + function (callback) { + count++; + setTimeout(callback, 1000); + }, + function (err) { + // 5 seconds have passed + } +); +``` + +--------------------------------------- + + +### doWhilst(fn, test, callback) + +The post check version of whilst. To reflect the difference in the order of operations `test` and `fn` arguments are switched. `doWhilst` is to `whilst` as `do while` is to `while` in plain JavaScript. + +--------------------------------------- + + +### until(test, fn, callback) + +Repeatedly call fn, until test returns true. Calls the callback when stopped, +or an error occurs. + +The inverse of async.whilst. + +--------------------------------------- + + +### doUntil(fn, test, callback) + +Like doWhilst except the test is inverted. Note the argument ordering differs from `until`. + +--------------------------------------- + + +### forever(fn, callback) + +Calls the asynchronous function 'fn' repeatedly, in series, indefinitely. +If an error is passed to fn's callback then 'callback' is called with the +error, otherwise it will never be called. + +--------------------------------------- + + +### waterfall(tasks, [callback]) + +Runs an array of functions in series, each passing their results to the next in +the array. However, if any of the functions pass an error to the callback, the +next function is not executed and the main callback is immediately called with +the error. + +__Arguments__ + +* tasks - An array of functions to run, each function is passed a + callback(err, result1, result2, ...) it must call on completion. The first + argument is an error (which can be null) and any further arguments will be + passed as arguments in order to the next task. +* callback(err, [results]) - An optional callback to run once all the functions + have completed. This will be passed the results of the last task's callback. + + + +__Example__ + +```js +async.waterfall([ + function(callback){ + callback(null, 'one', 'two'); + }, + function(arg1, arg2, callback){ + callback(null, 'three'); + }, + function(arg1, callback){ + // arg1 now equals 'three' + callback(null, 'done'); + } +], function (err, result) { + // result now equals 'done' +}); +``` + +--------------------------------------- + +### compose(fn1, fn2...) + +Creates a function which is a composition of the passed asynchronous +functions. Each function consumes the return value of the function that +follows. Composing functions f(), g() and h() would produce the result of +f(g(h())), only this version uses callbacks to obtain the return values. + +Each function is executed with the `this` binding of the composed function. + +__Arguments__ + +* functions... - the asynchronous functions to compose + + +__Example__ + +```js +function add1(n, callback) { + setTimeout(function () { + callback(null, n + 1); + }, 10); +} + +function mul3(n, callback) { + setTimeout(function () { + callback(null, n * 3); + }, 10); +} + +var add1mul3 = async.compose(mul3, add1); + +add1mul3(4, function (err, result) { + // result now equals 15 +}); +``` + +--------------------------------------- + +### applyEach(fns, args..., callback) + +Applies the provided arguments to each function in the array, calling the +callback after all functions have completed. If you only provide the first +argument then it will return a function which lets you pass in the +arguments as if it were a single function call. + +__Arguments__ + +* fns - the asynchronous functions to all call with the same arguments +* args... - any number of separate arguments to pass to the function +* callback - the final argument should be the callback, called when all + functions have completed processing + + +__Example__ + +```js +async.applyEach([enableSearch, updateSchema], 'bucket', callback); + +// partial application example: +async.each( + buckets, + async.applyEach([enableSearch, updateSchema]), + callback +); +``` + +--------------------------------------- + + +### applyEachSeries(arr, iterator, callback) + +The same as applyEach only the functions are applied in series. + +--------------------------------------- + + +### queue(worker, concurrency) + +Creates a queue object with the specified concurrency. Tasks added to the +queue will be processed in parallel (up to the concurrency limit). If all +workers are in progress, the task is queued until one is available. Once +a worker has completed a task, the task's callback is called. + +__Arguments__ + +* worker(task, callback) - An asynchronous function for processing a queued + task, which must call its callback(err) argument when finished, with an + optional error as an argument. +* concurrency - An integer for determining how many worker functions should be + run in parallel. + +__Queue objects__ + +The queue object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* concurrency - an integer for determining how many worker functions should be + run in parallel. This property can be changed after a queue is created to + alter the concurrency on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. + instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list. +* unshift(task, [callback]) - add a new task to the front of the queue. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + +```js +// create a queue object with concurrency 2 + +var q = async.queue(function (task, callback) { + console.log('hello ' + task.name); + callback(); +}, 2); + + +// assign a callback +q.drain = function() { + console.log('all items have been processed'); +} + +// add some items to the queue + +q.push({name: 'foo'}, function (err) { + console.log('finished processing foo'); +}); +q.push({name: 'bar'}, function (err) { + console.log('finished processing bar'); +}); + +// add some items to the queue (batch-wise) + +q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) { + console.log('finished processing bar'); +}); + +// add some items to the front of the queue + +q.unshift({name: 'bar'}, function (err) { + console.log('finished processing bar'); +}); +``` + +--------------------------------------- + + +### cargo(worker, [payload]) + +Creates a cargo object with the specified payload. Tasks added to the +cargo will be processed altogether (up to the payload limit). If the +worker is in progress, the task is queued until it is available. Once +the worker has completed some tasks, each callback of those tasks is called. + +__Arguments__ + +* worker(tasks, callback) - An asynchronous function for processing an array of + queued tasks, which must call its callback(err) argument when finished, with + an optional error as an argument. +* payload - An optional integer for determining how many tasks should be + processed per round; if omitted, the default is unlimited. + +__Cargo objects__ + +The cargo object returned by this function has the following properties and +methods: + +* length() - a function returning the number of items waiting to be processed. +* payload - an integer for determining how many tasks should be + process per round. This property can be changed after a cargo is created to + alter the payload on-the-fly. +* push(task, [callback]) - add a new task to the queue, the callback is called + once the worker has finished processing the task. + instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list. +* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued +* empty - a callback that is called when the last item from the queue is given to a worker +* drain - a callback that is called when the last item from the queue has returned from the worker + +__Example__ + +```js +// create a cargo object with payload 2 + +var cargo = async.cargo(function (tasks, callback) { + for(var i=0; i +### auto(tasks, [callback]) + +Determines the best order for running functions based on their requirements. +Each function can optionally depend on other functions being completed first, +and each function is run as soon as its requirements are satisfied. If any of +the functions pass an error to their callback, that function will not complete +(so any other functions depending on it will not run) and the main callback +will be called immediately with the error. Functions also receive an object +containing the results of functions which have completed so far. + +Note, all functions are called with a results object as a second argument, +so it is unsafe to pass functions in the tasks object which cannot handle the +extra argument. For example, this snippet of code: + +```js +async.auto({ + readData: async.apply(fs.readFile, 'data.txt', 'utf-8') +}, callback); +``` + +will have the effect of calling readFile with the results object as the last +argument, which will fail: + +```js +fs.readFile('data.txt', 'utf-8', cb, {}); +``` + +Instead, wrap the call to readFile in a function which does not forward the +results object: + +```js +async.auto({ + readData: function(cb, results){ + fs.readFile('data.txt', 'utf-8', cb); + } +}, callback); +``` + +__Arguments__ + +* tasks - An object literal containing named functions or an array of + requirements, with the function itself the last item in the array. The key + used for each function or array is used when specifying requirements. The + function receives two arguments: (1) a callback(err, result) which must be + called when finished, passing an error (which can be null) and the result of + the function's execution, and (2) a results object, containing the results of + the previously executed functions. +* callback(err, results) - An optional callback which is called when all the + tasks have been completed. The callback will receive an error as an argument + if any tasks pass an error to their callback. Results will always be passed + but if an error occurred, no other tasks will be performed, and the results + object will only contain partial results. + + +__Example__ + +```js +async.auto({ + get_data: function(callback){ + // async code to get some data + }, + make_folder: function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + }, + write_file: ['get_data', 'make_folder', function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + callback(null, filename); + }], + email_link: ['write_file', function(callback, results){ + // once the file is written let's email a link to it... + // results.write_file contains the filename returned by write_file. + }] +}); +``` + +This is a fairly trivial example, but to do this using the basic parallel and +series functions would look like this: + +```js +async.parallel([ + function(callback){ + // async code to get some data + }, + function(callback){ + // async code to create a directory to store a file in + // this is run at the same time as getting the data + } +], +function(err, results){ + async.series([ + function(callback){ + // once there is some data and the directory exists, + // write the data to a file in the directory + }, + function(callback){ + // once the file is written let's email a link to it... + } + ]); +}); +``` + +For a complicated series of async tasks using the auto function makes adding +new tasks much easier and makes the code more readable. + + +--------------------------------------- + + +### iterator(tasks) + +Creates an iterator function which calls the next function in the array, +returning a continuation to call the next one after that. It's also possible to +'peek' the next iterator by doing iterator.next(). + +This function is used internally by the async module but can be useful when +you want to manually control the flow of functions in series. + +__Arguments__ + +* tasks - An array of functions to run. + +__Example__ + +```js +var iterator = async.iterator([ + function(){ sys.p('one'); }, + function(){ sys.p('two'); }, + function(){ sys.p('three'); } +]); + +node> var iterator2 = iterator(); +'one' +node> var iterator3 = iterator2(); +'two' +node> iterator3(); +'three' +node> var nextfn = iterator2.next(); +node> nextfn(); +'three' +``` + +--------------------------------------- + + +### apply(function, arguments..) + +Creates a continuation function with some arguments already applied, a useful +shorthand when combined with other control flow functions. Any arguments +passed to the returned function are added to the arguments originally passed +to apply. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to automatically apply when the + continuation is called. + +__Example__ + +```js +// using apply + +async.parallel([ + async.apply(fs.writeFile, 'testfile1', 'test1'), + async.apply(fs.writeFile, 'testfile2', 'test2'), +]); + + +// the same process without using apply + +async.parallel([ + function(callback){ + fs.writeFile('testfile1', 'test1', callback); + }, + function(callback){ + fs.writeFile('testfile2', 'test2', callback); + } +]); +``` + +It's possible to pass any number of additional arguments when calling the +continuation: + +```js +node> var fn = async.apply(sys.puts, 'one'); +node> fn('two', 'three'); +one +two +three +``` + +--------------------------------------- + + +### nextTick(callback) + +Calls the callback on a later loop around the event loop. In node.js this just +calls process.nextTick, in the browser it falls back to setImmediate(callback) +if available, otherwise setTimeout(callback, 0), which means other higher priority +events may precede the execution of the callback. + +This is used internally for browser-compatibility purposes. + +__Arguments__ + +* callback - The function to call on a later loop around the event loop. + +__Example__ + +```js +var call_order = []; +async.nextTick(function(){ + call_order.push('two'); + // call_order now equals ['one','two'] +}); +call_order.push('one') +``` + + +### times(n, callback) + +Calls the callback n times and accumulates results in the same manner +you would use with async.map. + +__Arguments__ + +* n - The number of times to run the function. +* callback - The function to call n times. + +__Example__ + +```js +// Pretend this is some complicated async factory +var createUser = function(id, callback) { + callback(null, { + id: 'user' + id + }) +} +// generate 5 users +async.times(5, function(n, next){ + createUser(n, function(err, user) { + next(err, user) + }) +}, function(err, users) { + // we should now have 5 users +}); +``` + + +### timesSeries(n, callback) + +The same as times only the iterator is applied to each item in the array in +series. The next iterator is only called once the current one has completed +processing. The results array will be in the same order as the original. + + +## Utils + + +### memoize(fn, [hasher]) + +Caches the results of an async function. When creating a hash to store function +results against, the callback is omitted from the hash and an optional hash +function can be used. + +The cache of results is exposed as the `memo` property of the function returned +by `memoize`. + +__Arguments__ + +* fn - the function you to proxy and cache results from. +* hasher - an optional function for generating a custom hash for storing + results, it has all the arguments applied to it apart from the callback, and + must be synchronous. + +__Example__ + +```js +var slow_fn = function (name, callback) { + // do something + callback(null, result); +}; +var fn = async.memoize(slow_fn); + +// fn can now be used as if it were slow_fn +fn('some name', function () { + // callback +}); +``` + + +### unmemoize(fn) + +Undoes a memoized function, reverting it to the original, unmemoized +form. Comes handy in tests. + +__Arguments__ + +* fn - the memoized function + + +### log(function, arguments) + +Logs the result of an async function to the console. Only works in node.js or +in browsers that support console.log and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.log is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + +```js +var hello = function(name, callback){ + setTimeout(function(){ + callback(null, 'hello ' + name); + }, 1000); +}; +``` +```js +node> async.log(hello, 'world'); +'hello world' +``` + +--------------------------------------- + + +### dir(function, arguments) + +Logs the result of an async function to the console using console.dir to +display the properties of the resulting object. Only works in node.js or +in browsers that support console.dir and console.error (such as FF and Chrome). +If multiple arguments are returned from the async function, console.dir is +called on each argument in order. + +__Arguments__ + +* function - The function you want to eventually apply all arguments to. +* arguments... - Any number of arguments to apply to the function. + +__Example__ + +```js +var hello = function(name, callback){ + setTimeout(function(){ + callback(null, {hello: name}); + }, 1000); +}; +``` +```js +node> async.dir(hello, 'world'); +{hello: 'world'} +``` + +--------------------------------------- + + +### noConflict() + +Changes the value of async back to its original value, returning a reference to the +async object. diff --git a/homework8/project_express/node_modules/async/component.json b/homework8/project_express/node_modules/async/component.json new file mode 100644 index 0000000..bbb0115 --- /dev/null +++ b/homework8/project_express/node_modules/async/component.json @@ -0,0 +1,11 @@ +{ + "name": "async", + "repo": "caolan/async", + "description": "Higher-order functions and common patterns for asynchronous code", + "version": "0.1.23", + "keywords": [], + "dependencies": {}, + "development": {}, + "main": "lib/async.js", + "scripts": [ "lib/async.js" ] +} diff --git a/homework8/project_express/node_modules/async/lib/async.js b/homework8/project_express/node_modules/async/lib/async.js new file mode 100644 index 0000000..1eebb15 --- /dev/null +++ b/homework8/project_express/node_modules/async/lib/async.js @@ -0,0 +1,958 @@ +/*global setImmediate: false, setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root, previous_async; + + root = this; + if (root != null) { + previous_async = root.async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + function only_once(fn) { + var called = false; + return function() { + if (called) throw new Error("Callback was already called."); + called = true; + fn.apply(root, arguments); + } + } + + //// cross-browser compatiblity functions //// + + var _each = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _each(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _each(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + if (typeof setImmediate === 'function') { + async.nextTick = function (fn) { + // not a direct alias for IE10 compatibility + setImmediate(fn); + }; + async.setImmediate = async.nextTick; + } + else { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + async.setImmediate = async.nextTick; + } + } + else { + async.nextTick = process.nextTick; + if (typeof setImmediate !== 'undefined') { + async.setImmediate = function (fn) { + // not a direct alias for IE10 compatibility + setImmediate(fn); + }; + } + else { + async.setImmediate = async.nextTick; + } + } + + async.each = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + _each(arr, function (x) { + iterator(x, only_once(function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed >= arr.length) { + callback(null); + } + } + })); + }); + }; + async.forEach = async.each; + + async.eachSeries = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed >= arr.length) { + callback(null); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + async.forEachSeries = async.eachSeries; + + async.eachLimit = function (arr, limit, iterator, callback) { + var fn = _eachLimit(limit); + fn.apply(null, [arr, iterator, callback]); + }; + async.forEachLimit = async.eachLimit; + + var _eachLimit = function (limit) { + + return function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed >= arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + started += 1; + running += 1; + iterator(arr[started - 1], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed >= arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + } + })(); + }; + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.each].concat(args)); + }; + }; + var doParallelLimit = function(limit, fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [_eachLimit(limit)].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.eachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + async.mapLimit = function (arr, limit, iterator, callback) { + return _mapLimit(limit)(arr, iterator, callback); + }; + + var _mapLimit = function(limit) { + return doParallelLimit(limit, _asyncMap); + }; + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.eachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + main_callback = function () {}; + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + async.sortBy = function (arr, iterator, callback) { + async.map(arr, function (x, callback) { + iterator(x, function (err, criteria) { + if (err) { + callback(err); + } + else { + callback(null, {value: x, criteria: criteria}); + } + }); + }, function (err, results) { + if (err) { + return callback(err); + } + else { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var results = {}; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _each(listeners.slice(0), function (fn) { + fn(); + }); + }; + + addListener(function () { + if (_keys(results).length === keys.length) { + callback(null, results); + callback = function () {}; + } + }); + + _each(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + if (err) { + var safeResults = {}; + _each(_keys(results), function(rkey) { + safeResults[rkey] = results[rkey]; + }); + safeResults[k] = args; + callback(err, safeResults); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + results[k] = args; + async.setImmediate(taskComplete); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true) && !results.hasOwnProperty(k); + }; + if (ready()) { + task[task.length - 1](taskCallback, results); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor !== Array) { + var err = new Error('First argument to waterfall must be an array of functions'); + return callback(err); + } + if (!tasks.length) { + return callback(); + } + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback.apply(null, arguments); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.setImmediate(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + var _parallel = function(eachfn, tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + eachfn.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + eachfn.each(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.parallel = function (tasks, callback) { + _parallel({ map: async.map, each: async.each }, tasks, callback); + }; + + async.parallelLimit = function(tasks, limit, callback) { + _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback); + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.eachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + if (tasks.length) { + tasks[index].apply(null, arguments); + } + return fn.next(); + }; + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1): null; + }; + return fn; + }; + return makeCallback(0); + }; + + async.apply = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.doWhilst = function (iterator, test, callback) { + iterator(function (err) { + if (err) { + return callback(err); + } + if (test()) { + async.doWhilst(iterator, test, callback); + } + else { + callback(); + } + }); + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.doUntil = function (iterator, test, callback) { + iterator(function (err) { + if (err) { + return callback(err); + } + if (!test()) { + async.doUntil(iterator, test, callback); + } + else { + callback(); + } + }); + }; + + async.queue = function (worker, concurrency) { + if (concurrency === undefined) { + concurrency = 1; + } + function _insert(q, data, pos, callback) { + if(data.constructor !== Array) { + data = [data]; + } + _each(data, function(task) { + var item = { + data: task, + callback: typeof callback === 'function' ? callback : null + }; + + if (pos) { + q.tasks.unshift(item); + } else { + q.tasks.push(item); + } + + if (q.saturated && q.tasks.length === concurrency) { + q.saturated(); + } + async.setImmediate(q.process); + }); + } + + var workers = 0; + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + _insert(q, data, false, callback); + }, + unshift: function (data, callback) { + _insert(q, data, true, callback); + }, + process: function () { + if (workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift(); + if (q.empty && q.tasks.length === 0) { + q.empty(); + } + workers += 1; + var next = function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if (q.drain && q.tasks.length + workers === 0) { + q.drain(); + } + q.process(); + }; + var cb = only_once(next); + worker(task.data, cb); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + } + }; + return q; + }; + + async.cargo = function (worker, payload) { + var working = false, + tasks = []; + + var cargo = { + tasks: tasks, + payload: payload, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + if(data.constructor !== Array) { + data = [data]; + } + _each(data, function(task) { + tasks.push({ + data: task, + callback: typeof callback === 'function' ? callback : null + }); + if (cargo.saturated && tasks.length === payload) { + cargo.saturated(); + } + }); + async.setImmediate(cargo.process); + }, + process: function process() { + if (working) return; + if (tasks.length === 0) { + if(cargo.drain) cargo.drain(); + return; + } + + var ts = typeof payload === 'number' + ? tasks.splice(0, payload) + : tasks.splice(0); + + var ds = _map(ts, function (task) { + return task.data; + }); + + if(cargo.empty) cargo.empty(); + working = true; + worker(ds, function () { + working = false; + + var args = arguments; + _each(ts, function (data) { + if (data.callback) { + data.callback.apply(null, args); + } + }); + + process(); + }); + }, + length: function () { + return tasks.length; + }, + running: function () { + return working; + } + }; + return cargo; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _each(args, function (x) { + console[name](x); + }); + } + } + }])); + }; + }; + async.log = _console_fn('log'); + async.dir = _console_fn('dir'); + /*async.info = _console_fn('info'); + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ + + async.memoize = function (fn, hasher) { + var memo = {}; + var queues = {}; + hasher = hasher || function (x) { + return x; + }; + var memoized = function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else if (key in queues) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([function () { + memo[key] = arguments; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments); + } + }])); + } + }; + memoized.memo = memo; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + }; + }; + + async.times = function (count, iterator, callback) { + var counter = []; + for (var i = 0; i < count; i++) { + counter.push(i); + } + return async.map(counter, iterator, callback); + }; + + async.timesSeries = function (count, iterator, callback) { + var counter = []; + for (var i = 0; i < count; i++) { + counter.push(i); + } + return async.mapSeries(counter, iterator, callback); + }; + + async.compose = function (/* functions... */) { + var fns = Array.prototype.reverse.call(arguments); + return function () { + var that = this; + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + async.reduce(fns, args, function (newargs, fn, cb) { + fn.apply(that, newargs.concat([function () { + var err = arguments[0]; + var nextargs = Array.prototype.slice.call(arguments, 1); + cb(err, nextargs); + }])) + }, + function (err, results) { + callback.apply(that, [err].concat(results)); + }); + }; + }; + + var _applyEach = function (eachfn, fns /*args...*/) { + var go = function () { + var that = this; + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + return eachfn(fns, function (fn, cb) { + fn.apply(that, args.concat([cb])); + }, + callback); + }; + if (arguments.length > 2) { + var args = Array.prototype.slice.call(arguments, 2); + return go.apply(this, args); + } + else { + return go; + } + }; + async.applyEach = doParallel(_applyEach); + async.applyEachSeries = doSeries(_applyEach); + + async.forever = function (fn, callback) { + function next(err) { + if (err) { + if (callback) { + return callback(err); + } + throw err; + } + fn(next); + } + next(); + }; + + // AMD / RequireJS + if (typeof define !== 'undefined' && define.amd) { + define([], function () { + return async; + }); + } + // Node.js + else if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + // included directly via + +This is like calling require('client') from inside ./example. +[Read more on node's require path resolution](http://nodejs.org/api/modules.html) + +Compile +======= +(You'll want to do this before you deploy to production) + + require compile ./example/client.js > client.min.js + +Use programmatically +==================== +In node: + + require('require/server').listen(1234) + +or mount it on an http server you're already running + + var server = http.createServer(function(req, res) { }) + require('require/server').mount(server) + server.listen(8080, 'localhost') + +or, as connect middleware + + connect.createServer( + connect.static(__dirname + '/example'), + require('require/server').connect() + ) + +Compile programmatically: + + var compiler = require('require/compiler') + console.log(compiler.compile('./example/client.js')) + console.log(compiler.compileCode('require("./example/client")')) + +The compiler supports all the options of https://github.com/mishoo/UglifyJS, e.g. + + compiler.compile('./example/client.js', { beautify:true, ascii_only:true }) diff --git a/homework8/project_express/node_modules/require/bin/require-command.js b/homework8/project_express/node_modules/require/bin/require-command.js new file mode 100644 index 0000000..6211b0b --- /dev/null +++ b/homework8/project_express/node_modules/require/bin/require-command.js @@ -0,0 +1,69 @@ +#!/usr/bin/env node + +var path = require('path'), + server = require('../server'), + compiler = require('../compiler') + +var opts = { + port: 1234, + host: 'localhost', + command: null, + path: null +} + +var args = [].slice.call(process.argv, 2) + +opts.command = args.shift() +opts.path = path.resolve(args.shift()) + +while (args.length) { + var arg = args.shift() + switch(arg) { + case '--port': + opts.port = args.shift() + break + case '--host': + opts.host = args.shift() + break + case '--root': + opts.root = args.shift() + break + case '--usePagePort': + if (args[0] && args[0][0] != '-') { + console.log('Unexpected value for --usePagePort flag', args[0]) + process.exit(1) + } + opts.usePagePort = true + break + default: + console.log('Unknown option', arg) + process.exit(1) + break + } +} + +switch (opts.command) { + case 'serve': + if (!opts.path) { + console.log('Specify a path to serve from, e.g. require serve ./example') + process.exit(1) + } + server.listen(opts) + console.log('serving from', opts.path, 'on', 'http://'+opts.host+':'+opts.port) + break + case 'compile': + if (!opts.path) { + console.log('Specify a single file to compile, e.g. require compile ./path/to/file.js') + process.exit(1) + } + console.log(compiler.compile(opts.path)) + break + default: + if (opts.command) { + console.log('Unknown command', '"' + opts.command + '".', 'Try "require serve" or "require compile"') + } else { + console.log('You need to give a command, e.g. "require serve" or "require compile"') + } + process.exit(1) +} + diff --git a/homework8/project_express/node_modules/require/compiler.js b/homework8/project_express/node_modules/require/compiler.js new file mode 100644 index 0000000..ff30f51 --- /dev/null +++ b/homework8/project_express/node_modules/require/compiler.js @@ -0,0 +1,162 @@ +var fs = require('fs') +var path = require('path') +var extend = require('std/extend') +var each = require('std/each') +var getCode = require('./lib/getCode') +var resolve = require('./lib/resolve') +var getRequireStatements = require('./lib/getRequireStatements') + +module.exports = { + compile: compileFile, + compileHTML: compileHTMLFile, + compileCode: compileCode +} + +/* api + *****/ +function compileFile(filePath, opts) { + filePath = path.resolve(filePath) + opts = extend(opts, { basePath:path.dirname(filePath), toplevel:true }) + var code = getCode(filePath) + return _compile(code, opts, filePath) +} + +function compileCode(code, opts) { + opts = extend(opts, { basePath:process.cwd(), toplevel:true }) + return _compile(code, opts, '') +} + +function compileHTMLFile(filePath, opts) { + var html = fs.readFileSync(filePath).toString() + while (match = html.match(/') + html = html.replace(BACKREFERENCE_WORKAROUND, '\$\&') + } + return html +} + + +var _compile = function(code, opts, mainModule) { + var code = 'var __require__ = {}, require=function(){}\n' + _compileModule(code, opts.basePath, mainModule) + if (opts.minify === false) { return code } // TODO use uglifyjs' beautifier? + + var UglifyJS = require('uglify-js') + var result = UglifyJS.minify(code, { + fromString:true, + mangle:true, + output: { + // http://lisperator.net/uglifyjs/codegen + indent_start : 0, // start indentation on every line (only when `beautify`) + indent_level : 4, // indentation level (only when `beautify`) + quote_keys : false, // quote all keys in object literals? + space_colon : true, // add a space after colon signs? + ascii_only : false, // output ASCII-safe? (encodes Unicode characters as ASCII) + inline_script : false, // escape " + + + test + + + + diff --git a/homework8/project_express/node_modules/require/example/package.json b/homework8/project_express/node_modules/require/example/package.json new file mode 100644 index 0000000..4a43812 --- /dev/null +++ b/homework8/project_express/node_modules/require/example/package.json @@ -0,0 +1,16 @@ +{ + "author": "", + "name": "testApp", + "version": "0.0.0", + "repository": { + "url": "" + }, + "directories": { + "lib": "." + }, + "engines": { + "node": "*" + }, + "dependencies": {}, + "devDependencies": {} +} \ No newline at end of file diff --git a/homework8/project_express/node_modules/require/example/raphael_circle.html b/homework8/project_express/node_modules/require/example/raphael_circle.html new file mode 100644 index 0000000..86e0c30 --- /dev/null +++ b/homework8/project_express/node_modules/require/example/raphael_circle.html @@ -0,0 +1,4 @@ + + + + diff --git a/homework8/project_express/node_modules/require/example/raphael_circle.js b/homework8/project_express/node_modules/require/example/raphael_circle.js new file mode 100644 index 0000000..0c6e1c6 --- /dev/null +++ b/homework8/project_express/node_modules/require/example/raphael_circle.js @@ -0,0 +1,5 @@ +var raphael = require('raphael'), + canvas = document.body.appendChild(document.createElement('div')), + paper = raphael(canvas) + +paper.circle(50, 50, 40) diff --git a/homework8/project_express/node_modules/require/example/server.js b/homework8/project_express/node_modules/require/example/server.js new file mode 100644 index 0000000..0b8adbf --- /dev/null +++ b/homework8/project_express/node_modules/require/example/server.js @@ -0,0 +1,20 @@ +var http = require('http'), + fs = require('fs'), + dependency = require('./shared/dependency'), + requireServer = require('../server') // this would be require('require/server') in most applications + +var base = __dirname + '/', + root = 'require' +var server = http.createServer(function(req, res) { + if (requireServer.isRequireRequest(req)) { return } + fs.readFile(base + (req.url.substr(1) || 'index.html'), function(err, content) { + if (err) { return res.end(err.stack) } + res.end(content) + }) +}) + +requireServer.mount(server, __dirname) + +server.listen(8080) + +console.log('shared dependency:', dependency) diff --git a/homework8/project_express/node_modules/require/example/shared/dependency.js b/homework8/project_express/node_modules/require/example/shared/dependency.js new file mode 100644 index 0000000..8cdb2ae --- /dev/null +++ b/homework8/project_express/node_modules/require/example/shared/dependency.js @@ -0,0 +1,4 @@ +module.exports = { + foo: 'bar', + cat: 'qwe' +} diff --git a/homework8/project_express/node_modules/require/lib/getCode.js b/homework8/project_express/node_modules/require/lib/getCode.js new file mode 100644 index 0000000..5febcea --- /dev/null +++ b/homework8/project_express/node_modules/require/lib/getCode.js @@ -0,0 +1,6 @@ +var fs = require('fs') + +module.exports = function readCode(filePath) { + if (!filePath.match(/\.js$/)) { filePath += '.js' } + return fs.readFileSync(filePath).toString() +} \ No newline at end of file diff --git a/homework8/project_express/node_modules/require/lib/getDependencyLevels.js b/homework8/project_express/node_modules/require/lib/getDependencyLevels.js new file mode 100644 index 0000000..af92e43 --- /dev/null +++ b/homework8/project_express/node_modules/require/lib/getDependencyLevels.js @@ -0,0 +1,59 @@ +var each = require('std/each') +var getCode = require('./getCode') +var getRequireStatements = require('./getRequireStatements') +var resolve = require('./resolve') + +module.exports = getDependencyLevels + +function getDependencyLevels(mainModulePath) { + var leaves = [] + var root = [] + root.isRoot = true + root.path = mainModulePath + _buildDependencyTreeOf(root) + + var levels = [] + var seenPaths = {} + _buildLevel(leaves) + + return levels + + // builds full dependency tree, noting every dependency of every node + function _buildDependencyTreeOf(node) { + var requireStatements = getRequireStatements(getCode(node.path)) + if (requireStatements.length == 0) { + return leaves.push(node) + } + each(requireStatements, function(requireStatement) { + var childNode = [] + childNode.path = resolve.requireStatement(requireStatement, node.path) + childNode.parent = node + node.push(childNode) + _buildDependencyTreeOf(childNode) + }) + node.waitingForNumChildren = node.length + } + + // builds a list of dependency levels, where nodes in each level is dependent only on nodes in levels below it + // the dependency levels allow for parallel loading of every file in any given level + function _buildLevel(nodes) { + var level = [] + levels.push(level) + var parents = [] + each(nodes, function(node) { + if (!seenPaths[node.path]) { + seenPaths[node.path] = true + level.push(node.path) + } + if (node.isRoot) { return } + + node.parent.waitingForNumChildren -= 1 + + if (node.parent.waitingForNumChildren == 0) { + parents.push(node.parent) + } + }) + if (!parents.length) { return } + _buildLevel(parents) + } +} diff --git a/homework8/project_express/node_modules/require/lib/getRequireStatements.js b/homework8/project_express/node_modules/require/lib/getRequireStatements.js new file mode 100644 index 0000000..ecc9470 --- /dev/null +++ b/homework8/project_express/node_modules/require/lib/getRequireStatements.js @@ -0,0 +1,6 @@ +module.exports = getRequireStatements + +var _globalRequireRegex = /require\s*\(['"][\w\/\.-]*['"]\)/g +function getRequireStatements(code) { + return code.match(_globalRequireRegex) || [] +} diff --git a/homework8/project_express/node_modules/require/lib/resolve.js b/homework8/project_express/node_modules/require/lib/resolve.js new file mode 100644 index 0000000..bbeaafc --- /dev/null +++ b/homework8/project_express/node_modules/require/lib/resolve.js @@ -0,0 +1,72 @@ +var path = require('path') +var fs = require('fs') +var existsSync = fs.existsSync || path.existsSync + +var _nodePaths = (process.env.NODE_PATH ? process.env.NODE_PATH.split(':') : []) +_nodePaths.push(process.cwd()) + +module.exports = { + path: resolvePath, + _nodePaths:_nodePaths, + requireStatement: resolveRequireStatement +} + +function resolvePath(searchPath, pathBase) { + if (searchPath[0] == '.') { + // relative path, e.g. require("./foo") + return _findModuleMain(path.resolve(pathBase, searchPath)) + } + + var searchParts = searchPath.split('/') + var componentName = searchParts[searchParts.length - 1] + var name = searchParts.shift() + var rest = searchParts.join('/') + + // npm-style path, e.g. require("npm"). + // Climb parent directories in search for "node_modules" + var modulePath = _findModuleMain(path.resolve(pathBase, 'node_modules', searchPath)) + if (modulePath) { return modulePath } + + if (pathBase != '/') { + // not yet at the root - keep climbing! + return resolvePath(searchPath, path.resolve(pathBase, '..')) + } + + return '' +} + +var _pathnameGroupingRegex = /require\s*\(['"]([\w\/\.-]*)['"]\)/ +function resolveRequireStatement(requireStmnt, currentPath) { + var rawPath = requireStmnt.match(_pathnameGroupingRegex)[1] + var resolvedPath = resolvePath(rawPath, path.dirname(currentPath)) + + if (!resolvedPath && rawPath[0] != '.' && rawPath[0] != '/') { + for (var i=0; i<_nodePaths.length; i++) { + resolvedPath = _findModuleMain(path.resolve(_nodePaths[i], rawPath)) + if (resolvedPath) { break } + } + } + + if (!resolvedPath) { throw 'Could not resolve "'+rawPath+'" in "'+currentPath+'"' } + return resolvedPath +} + +function _findModuleMain(absModulePath, tryFileName) { + var foundPath = '' + function attempt(aPath) { + if (foundPath) { return } + if (existsSync(aPath)) { foundPath = aPath } + } + attempt(absModulePath + '.js') + try { + var package = JSON.parse(fs.readFileSync(absModulePath + '/package.json').toString()) + attempt(path.resolve(absModulePath, package.main+'.js')) + attempt(path.resolve(absModulePath, package.main)) + } catch(e) {} + attempt(absModulePath + '/index.js') + + if (tryFileName) { attempt(absModulePath + '/' + tryFileName + '.js') } + return foundPath +} + + diff --git a/homework8/project_express/node_modules/require/package.json b/homework8/project_express/node_modules/require/package.json new file mode 100644 index 0000000..52b8dfb --- /dev/null +++ b/homework8/project_express/node_modules/require/package.json @@ -0,0 +1,23 @@ +{ + "name": "require", + "description": "javascript module management! brings node's require statement to the browser", + "version": "2.4.20", + "homepage": "https://github.com/marcuswestin/require", + "main": "./require", + "bin": "./bin/require-command.js", + "engines": { + "node": "*", + "browsers": "*" + }, + "repository": { + "type": "git", + "url": "git://github.com/marcuswestin/require.git" + }, + "author": "Marcus Westin (http://marcuswest.in)", + "dependencies": { + "uglify-js": "2.3.0", + "std": "0.1.40" + }, + "devDependencies": {}, + "directories": {} +} diff --git a/homework8/project_express/node_modules/require/server.js b/homework8/project_express/node_modules/require/server.js new file mode 100644 index 0000000..9f34d1c --- /dev/null +++ b/homework8/project_express/node_modules/require/server.js @@ -0,0 +1,185 @@ +var http = require('http') +var fs = require('fs') +var path = require('path') +var extend = require('std/extend') +var isObject = require('std/isObject') +var map = require('std/map') +var each = require('std/each') +var getDependencyLevels = require('./lib/getDependencyLevels') +var getRequireStatements = require('./lib/getRequireStatements') +var getCode = require('./lib/getCode') +var resolve = require('./lib/resolve') + +module.exports = { + listen: listen, + mount: mount, + connect: connect, + isRequireRequest: isRequireRequest, + handleRequest: handleRequest +} + +function listen(portOrOpts) { + var _opts = (isObject(portOrOpts) ? portOrOpts : { port:portOrOpts || 1234 }) + opts.handleAllRequests = true + mount(http.createServer(), _opts).listen(opts.port, opts.host) +} + +function mount(server, _opts) { + setOpts(_opts) + return server.on('request', _checkRequest) +} + +function connect(opts) { + setOpts(opts) + return _checkRequest +} + +function _checkRequest(req, res, next) { + if (isRequireRequest(req) || opts.handleAllRequests) { + handleRequest(req, res) + } else { + next && next() + } +} + +function isRequireRequest(req) { + return req.url.substr(1, opts.root.length) == opts.root +} + +/* options + *********/ +var opts = { + path: process.cwd(), + root: 'require', + port: null, + host: null +} +function setOpts(_opts) { + opts = extend(_opts, opts) + if (opts.path) { + resolve._nodePaths.push(opts.path) + } +} +function getUrlBase() { + var basePort = (!opts.usePagePort && opts.port) + if (opts.host && basePort) { + return '//' + opts.host + ':' + basePort + '/' + opts.root + '/' + } else { + return '/' + opts.root + '/' + } +} + +/* request handlers + ******************/ +function handleRequest(req, res) { + var reqPath = _normalizeURL(req.url).substr(opts.root.length + 2) + if (reqPath.match(/\.js$/)) { + _handleModuleRequest(reqPath, res) + } else { + _handleMainModuleRequest(reqPath, req, res) + } + + function _normalizeURL(url) { + return url.replace(/\?.*/g, '').replace(/\/js$/, '.js') + } +} + +function _handleMainModuleRequest(reqPath, req, res) { + var mainModulePath = resolve.path('./' + reqPath, opts.path) + if (!mainModulePath) { return _sendError(res, 'Could not find module "'+reqPath+'" from "'+opts.path+'"') } + + try { var dependencyTree = getDependencyLevels(mainModulePath) } + catch(err) { return _sendError(res, 'in getDependencyLevels: ' + (err.message || err)) } + + var userAgent = req.headers['user-agent'] + var isMobile = userAgent.match('iPad') || userAgent.match('iPod') || userAgent.match('iPhone') || userAgent.match('Android') + + var response = isMobile ? _getMobilePayload() : _getNormalPayload() + + res.writeHead(200, { 'Cache-Control':'no-cache', 'Expires':'Fri, 31 Dec 1998 12:00:00 GMT', 'Content-Length':response.length, 'Content-Type':'text/javascript' }) + res.end(response) + + function _getMobilePayload() { + var result = ['__require__={loadNextModule:function(){},onModuleLoaded:function(){}}'] + each(dependencyTree, function(level) { + each(level, function(dependency) { + result.push(';(function(){ '+_getModuleCode(res, dependency)+' }());') + }) + }) + return new Buffer(result.join('\n')) + } + + function _getNormalPayload() { + var paramsString = map([getUrlBase(), dependencyTree], JSON.stringify).join(',\n\t\t') + return new Buffer('\t('+clientBootstrapFn.toString()+')(\n\t\t'+paramsString+'\n\t)') + + function clientBootstrapFn(urlBase, levels) { + // This function gets sent to the client as toString + __require__ = { + loadNextLevel: loadNextLevel, + onModuleLoaded: onModuleLoaded + } + + var currentLevel = null + loadNextLevel() + + function loadNextLevel() { + if (!levels.length) { return } // all done! + currentLevel = levels.shift() + var head = document.getElementsByTagName('head')[0] + for (var i=0; i + +* `array` {Array} + +Allocates a new `Buffer` using an `array` of octets. + +```js +const buf = Buffer.from([0x62,0x75,0x66,0x66,0x65,0x72]); + // creates a new Buffer containing ASCII bytes + // ['b','u','f','f','e','r'] +``` + +A `TypeError` will be thrown if `array` is not an `Array`. + +### Class Method: Buffer.from(arrayBuffer[, byteOffset[, length]]) + + +* `arrayBuffer` {ArrayBuffer} The `.buffer` property of a `TypedArray` or + a `new ArrayBuffer()` +* `byteOffset` {Number} Default: `0` +* `length` {Number} Default: `arrayBuffer.length - byteOffset` + +When passed a reference to the `.buffer` property of a `TypedArray` instance, +the newly created `Buffer` will share the same allocated memory as the +TypedArray. + +```js +const arr = new Uint16Array(2); +arr[0] = 5000; +arr[1] = 4000; + +const buf = Buffer.from(arr.buffer); // shares the memory with arr; + +console.log(buf); + // Prints: + +// changing the TypedArray changes the Buffer also +arr[1] = 6000; + +console.log(buf); + // Prints: +``` + +The optional `byteOffset` and `length` arguments specify a memory range within +the `arrayBuffer` that will be shared by the `Buffer`. + +```js +const ab = new ArrayBuffer(10); +const buf = Buffer.from(ab, 0, 2); +console.log(buf.length); + // Prints: 2 +``` + +A `TypeError` will be thrown if `arrayBuffer` is not an `ArrayBuffer`. + +### Class Method: Buffer.from(buffer) + + +* `buffer` {Buffer} + +Copies the passed `buffer` data onto a new `Buffer` instance. + +```js +const buf1 = Buffer.from('buffer'); +const buf2 = Buffer.from(buf1); + +buf1[0] = 0x61; +console.log(buf1.toString()); + // 'auffer' +console.log(buf2.toString()); + // 'buffer' (copy is not changed) +``` + +A `TypeError` will be thrown if `buffer` is not a `Buffer`. + +### Class Method: Buffer.from(str[, encoding]) + + +* `str` {String} String to encode. +* `encoding` {String} Encoding to use, Default: `'utf8'` + +Creates a new `Buffer` containing the given JavaScript string `str`. If +provided, the `encoding` parameter identifies the character encoding. +If not provided, `encoding` defaults to `'utf8'`. + +```js +const buf1 = Buffer.from('this is a tést'); +console.log(buf1.toString()); + // prints: this is a tést +console.log(buf1.toString('ascii')); + // prints: this is a tC)st + +const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex'); +console.log(buf2.toString()); + // prints: this is a tést +``` + +A `TypeError` will be thrown if `str` is not a string. + +### Class Method: Buffer.alloc(size[, fill[, encoding]]) + + +* `size` {Number} +* `fill` {Value} Default: `undefined` +* `encoding` {String} Default: `utf8` + +Allocates a new `Buffer` of `size` bytes. If `fill` is `undefined`, the +`Buffer` will be *zero-filled*. + +```js +const buf = Buffer.alloc(5); +console.log(buf); + // +``` + +The `size` must be less than or equal to the value of +`require('buffer').kMaxLength` (on 64-bit architectures, `kMaxLength` is +`(2^31)-1`). Otherwise, a [`RangeError`][] is thrown. A zero-length Buffer will +be created if a `size` less than or equal to 0 is specified. + +If `fill` is specified, the allocated `Buffer` will be initialized by calling +`buf.fill(fill)`. See [`buf.fill()`][] for more information. + +```js +const buf = Buffer.alloc(5, 'a'); +console.log(buf); + // +``` + +If both `fill` and `encoding` are specified, the allocated `Buffer` will be +initialized by calling `buf.fill(fill, encoding)`. For example: + +```js +const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64'); +console.log(buf); + // +``` + +Calling `Buffer.alloc(size)` can be significantly slower than the alternative +`Buffer.allocUnsafe(size)` but ensures that the newly created `Buffer` instance +contents will *never contain sensitive data*. + +A `TypeError` will be thrown if `size` is not a number. + +### Class Method: Buffer.allocUnsafe(size) + + +* `size` {Number} + +Allocates a new *non-zero-filled* `Buffer` of `size` bytes. The `size` must +be less than or equal to the value of `require('buffer').kMaxLength` (on 64-bit +architectures, `kMaxLength` is `(2^31)-1`). Otherwise, a [`RangeError`][] is +thrown. A zero-length Buffer will be created if a `size` less than or equal to +0 is specified. + +The underlying memory for `Buffer` instances created in this way is *not +initialized*. The contents of the newly created `Buffer` are unknown and +*may contain sensitive data*. Use [`buf.fill(0)`][] to initialize such +`Buffer` instances to zeroes. + +```js +const buf = Buffer.allocUnsafe(5); +console.log(buf); + // + // (octets will be different, every time) +buf.fill(0); +console.log(buf); + // +``` + +A `TypeError` will be thrown if `size` is not a number. + +Note that the `Buffer` module pre-allocates an internal `Buffer` instance of +size `Buffer.poolSize` that is used as a pool for the fast allocation of new +`Buffer` instances created using `Buffer.allocUnsafe(size)` (and the deprecated +`new Buffer(size)` constructor) only when `size` is less than or equal to +`Buffer.poolSize >> 1` (floor of `Buffer.poolSize` divided by two). The default +value of `Buffer.poolSize` is `8192` but can be modified. + +Use of this pre-allocated internal memory pool is a key difference between +calling `Buffer.alloc(size, fill)` vs. `Buffer.allocUnsafe(size).fill(fill)`. +Specifically, `Buffer.alloc(size, fill)` will *never* use the internal Buffer +pool, while `Buffer.allocUnsafe(size).fill(fill)` *will* use the internal +Buffer pool if `size` is less than or equal to half `Buffer.poolSize`. The +difference is subtle but can be important when an application requires the +additional performance that `Buffer.allocUnsafe(size)` provides. + +### Class Method: Buffer.allocUnsafeSlow(size) + + +* `size` {Number} + +Allocates a new *non-zero-filled* and non-pooled `Buffer` of `size` bytes. The +`size` must be less than or equal to the value of +`require('buffer').kMaxLength` (on 64-bit architectures, `kMaxLength` is +`(2^31)-1`). Otherwise, a [`RangeError`][] is thrown. A zero-length Buffer will +be created if a `size` less than or equal to 0 is specified. + +The underlying memory for `Buffer` instances created in this way is *not +initialized*. The contents of the newly created `Buffer` are unknown and +*may contain sensitive data*. Use [`buf.fill(0)`][] to initialize such +`Buffer` instances to zeroes. + +When using `Buffer.allocUnsafe()` to allocate new `Buffer` instances, +allocations under 4KB are, by default, sliced from a single pre-allocated +`Buffer`. This allows applications to avoid the garbage collection overhead of +creating many individually allocated Buffers. This approach improves both +performance and memory usage by eliminating the need to track and cleanup as +many `Persistent` objects. + +However, in the case where a developer may need to retain a small chunk of +memory from a pool for an indeterminate amount of time, it may be appropriate +to create an un-pooled Buffer instance using `Buffer.allocUnsafeSlow()` then +copy out the relevant bits. + +```js +// need to keep around a few small chunks of memory +const store = []; + +socket.on('readable', () => { + const data = socket.read(); + // allocate for retained data + const sb = Buffer.allocUnsafeSlow(10); + // copy the data into the new allocation + data.copy(sb, 0, 0, 10); + store.push(sb); +}); +``` + +Use of `Buffer.allocUnsafeSlow()` should be used only as a last resort *after* +a developer has observed undue memory retention in their applications. + +A `TypeError` will be thrown if `size` is not a number. + +### All the Rest + +The rest of the `Buffer` API is exactly the same as in node.js. +[See the docs](https://nodejs.org/api/buffer.html). + + +## Related links + +- [Node.js issue: Buffer(number) is unsafe](https://github.com/nodejs/node/issues/4660) +- [Node.js Enhancement Proposal: Buffer.from/Buffer.alloc/Buffer.zalloc/Buffer() soft-deprecate](https://github.com/nodejs/node-eps/pull/4) + +## Why is `Buffer` unsafe? + +Today, the node.js `Buffer` constructor is overloaded to handle many different argument +types like `String`, `Array`, `Object`, `TypedArrayView` (`Uint8Array`, etc.), +`ArrayBuffer`, and also `Number`. + +The API is optimized for convenience: you can throw any type at it, and it will try to do +what you want. + +Because the Buffer constructor is so powerful, you often see code like this: + +```js +// Convert UTF-8 strings to hex +function toHex (str) { + return new Buffer(str).toString('hex') +} +``` + +***But what happens if `toHex` is called with a `Number` argument?*** + +### Remote Memory Disclosure + +If an attacker can make your program call the `Buffer` constructor with a `Number` +argument, then they can make it allocate uninitialized memory from the node.js process. +This could potentially disclose TLS private keys, user data, or database passwords. + +When the `Buffer` constructor is passed a `Number` argument, it returns an +**UNINITIALIZED** block of memory of the specified `size`. When you create a `Buffer` like +this, you **MUST** overwrite the contents before returning it to the user. + +From the [node.js docs](https://nodejs.org/api/buffer.html#buffer_new_buffer_size): + +> `new Buffer(size)` +> +> - `size` Number +> +> The underlying memory for `Buffer` instances created in this way is not initialized. +> **The contents of a newly created `Buffer` are unknown and could contain sensitive +> data.** Use `buf.fill(0)` to initialize a Buffer to zeroes. + +(Emphasis our own.) + +Whenever the programmer intended to create an uninitialized `Buffer` you often see code +like this: + +```js +var buf = new Buffer(16) + +// Immediately overwrite the uninitialized buffer with data from another buffer +for (var i = 0; i < buf.length; i++) { + buf[i] = otherBuf[i] +} +``` + + +### Would this ever be a problem in real code? + +Yes. It's surprisingly common to forget to check the type of your variables in a +dynamically-typed language like JavaScript. + +Usually the consequences of assuming the wrong type is that your program crashes with an +uncaught exception. But the failure mode for forgetting to check the type of arguments to +the `Buffer` constructor is more catastrophic. + +Here's an example of a vulnerable service that takes a JSON payload and converts it to +hex: + +```js +// Take a JSON payload {str: "some string"} and convert it to hex +var server = http.createServer(function (req, res) { + var data = '' + req.setEncoding('utf8') + req.on('data', function (chunk) { + data += chunk + }) + req.on('end', function () { + var body = JSON.parse(data) + res.end(new Buffer(body.str).toString('hex')) + }) +}) + +server.listen(8080) +``` + +In this example, an http client just has to send: + +```json +{ + "str": 1000 +} +``` + +and it will get back 1,000 bytes of uninitialized memory from the server. + +This is a very serious bug. It's similar in severity to the +[the Heartbleed bug](http://heartbleed.com/) that allowed disclosure of OpenSSL process +memory by remote attackers. + + +### Which real-world packages were vulnerable? + +#### [`bittorrent-dht`](https://www.npmjs.com/package/bittorrent-dht) + +[Mathias Buus](https://github.com/mafintosh) and I +([Feross Aboukhadijeh](http://feross.org/)) found this issue in one of our own packages, +[`bittorrent-dht`](https://www.npmjs.com/package/bittorrent-dht). The bug would allow +anyone on the internet to send a series of messages to a user of `bittorrent-dht` and get +them to reveal 20 bytes at a time of uninitialized memory from the node.js process. + +Here's +[the commit](https://github.com/feross/bittorrent-dht/commit/6c7da04025d5633699800a99ec3fbadf70ad35b8) +that fixed it. We released a new fixed version, created a +[Node Security Project disclosure](https://nodesecurity.io/advisories/68), and deprecated all +vulnerable versions on npm so users will get a warning to upgrade to a newer version. + +#### [`ws`](https://www.npmjs.com/package/ws) + +That got us wondering if there were other vulnerable packages. Sure enough, within a short +period of time, we found the same issue in [`ws`](https://www.npmjs.com/package/ws), the +most popular WebSocket implementation in node.js. + +If certain APIs were called with `Number` parameters instead of `String` or `Buffer` as +expected, then uninitialized server memory would be disclosed to the remote peer. + +These were the vulnerable methods: + +```js +socket.send(number) +socket.ping(number) +socket.pong(number) +``` + +Here's a vulnerable socket server with some echo functionality: + +```js +server.on('connection', function (socket) { + socket.on('message', function (message) { + message = JSON.parse(message) + if (message.type === 'echo') { + socket.send(message.data) // send back the user's message + } + }) +}) +``` + +`socket.send(number)` called on the server, will disclose server memory. + +Here's [the release](https://github.com/websockets/ws/releases/tag/1.0.1) where the issue +was fixed, with a more detailed explanation. Props to +[Arnout Kazemier](https://github.com/3rd-Eden) for the quick fix. Here's the +[Node Security Project disclosure](https://nodesecurity.io/advisories/67). + + +### What's the solution? + +It's important that node.js offers a fast way to get memory otherwise performance-critical +applications would needlessly get a lot slower. + +But we need a better way to *signal our intent* as programmers. **When we want +uninitialized memory, we should request it explicitly.** + +Sensitive functionality should not be packed into a developer-friendly API that loosely +accepts many different types. This type of API encourages the lazy practice of passing +variables in without checking the type very carefully. + +#### A new API: `Buffer.allocUnsafe(number)` + +The functionality of creating buffers with uninitialized memory should be part of another +API. We propose `Buffer.allocUnsafe(number)`. This way, it's not part of an API that +frequently gets user input of all sorts of different types passed into it. + +```js +var buf = Buffer.allocUnsafe(16) // careful, uninitialized memory! + +// Immediately overwrite the uninitialized buffer with data from another buffer +for (var i = 0; i < buf.length; i++) { + buf[i] = otherBuf[i] +} +``` + + +### How do we fix node.js core? + +We sent [a PR to node.js core](https://github.com/nodejs/node/pull/4514) (merged as +`semver-major`) which defends against one case: + +```js +var str = 16 +new Buffer(str, 'utf8') +``` + +In this situation, it's implied that the programmer intended the first argument to be a +string, since they passed an encoding as a second argument. Today, node.js will allocate +uninitialized memory in the case of `new Buffer(number, encoding)`, which is probably not +what the programmer intended. + +But this is only a partial solution, since if the programmer does `new Buffer(variable)` +(without an `encoding` parameter) there's no way to know what they intended. If `variable` +is sometimes a number, then uninitialized memory will sometimes be returned. + +### What's the real long-term fix? + +We could deprecate and remove `new Buffer(number)` and use `Buffer.allocUnsafe(number)` when +we need uninitialized memory. But that would break 1000s of packages. + +~~We believe the best solution is to:~~ + +~~1. Change `new Buffer(number)` to return safe, zeroed-out memory~~ + +~~2. Create a new API for creating uninitialized Buffers. We propose: `Buffer.allocUnsafe(number)`~~ + +#### Update + +We now support adding three new APIs: + +- `Buffer.from(value)` - convert from any type to a buffer +- `Buffer.alloc(size)` - create a zero-filled buffer +- `Buffer.allocUnsafe(size)` - create an uninitialized buffer with given size + +This solves the core problem that affected `ws` and `bittorrent-dht` which is +`Buffer(variable)` getting tricked into taking a number argument. + +This way, existing code continues working and the impact on the npm ecosystem will be +minimal. Over time, npm maintainers can migrate performance-critical code to use +`Buffer.allocUnsafe(number)` instead of `new Buffer(number)`. + + +### Conclusion + +We think there's a serious design issue with the `Buffer` API as it exists today. It +promotes insecure software by putting high-risk functionality into a convenient API +with friendly "developer ergonomics". + +This wasn't merely a theoretical exercise because we found the issue in some of the +most popular npm packages. + +Fortunately, there's an easy fix that can be applied today. Use `safe-buffer` in place of +`buffer`. + +```js +var Buffer = require('safe-buffer').Buffer +``` + +Eventually, we hope that node.js core can switch to this new, safer behavior. We believe +the impact on the ecosystem would be minimal since it's not a breaking change. +Well-maintained, popular packages would be updated to use `Buffer.alloc` quickly, while +older, insecure packages would magically become safe from this attack vector. + + +## links + +- [Node.js PR: buffer: throw if both length and enc are passed](https://github.com/nodejs/node/pull/4514) +- [Node Security Project disclosure for `ws`](https://nodesecurity.io/advisories/67) +- [Node Security Project disclosure for`bittorrent-dht`](https://nodesecurity.io/advisories/68) + + +## credit + +The original issues in `bittorrent-dht` +([disclosure](https://nodesecurity.io/advisories/68)) and +`ws` ([disclosure](https://nodesecurity.io/advisories/67)) were discovered by +[Mathias Buus](https://github.com/mafintosh) and +[Feross Aboukhadijeh](http://feross.org/). + +Thanks to [Adam Baldwin](https://github.com/evilpacket) for helping disclose these issues +and for his work running the [Node Security Project](https://nodesecurity.io/). + +Thanks to [John Hiesey](https://github.com/jhiesey) for proofreading this README and +auditing the code. + + +## license + +MIT. Copyright (C) [Feross Aboukhadijeh](http://feross.org) diff --git a/homework8/project_express/node_modules/safe-buffer/index.d.ts b/homework8/project_express/node_modules/safe-buffer/index.d.ts new file mode 100644 index 0000000..e9fed80 --- /dev/null +++ b/homework8/project_express/node_modules/safe-buffer/index.d.ts @@ -0,0 +1,187 @@ +declare module "safe-buffer" { + export class Buffer { + length: number + write(string: string, offset?: number, length?: number, encoding?: string): number; + toString(encoding?: string, start?: number, end?: number): string; + toJSON(): { type: 'Buffer', data: any[] }; + equals(otherBuffer: Buffer): boolean; + compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number; + copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number; + slice(start?: number, end?: number): Buffer; + writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number; + readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number; + readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number; + readIntLE(offset: number, byteLength: number, noAssert?: boolean): number; + readIntBE(offset: number, byteLength: number, noAssert?: boolean): number; + readUInt8(offset: number, noAssert?: boolean): number; + readUInt16LE(offset: number, noAssert?: boolean): number; + readUInt16BE(offset: number, noAssert?: boolean): number; + readUInt32LE(offset: number, noAssert?: boolean): number; + readUInt32BE(offset: number, noAssert?: boolean): number; + readInt8(offset: number, noAssert?: boolean): number; + readInt16LE(offset: number, noAssert?: boolean): number; + readInt16BE(offset: number, noAssert?: boolean): number; + readInt32LE(offset: number, noAssert?: boolean): number; + readInt32BE(offset: number, noAssert?: boolean): number; + readFloatLE(offset: number, noAssert?: boolean): number; + readFloatBE(offset: number, noAssert?: boolean): number; + readDoubleLE(offset: number, noAssert?: boolean): number; + readDoubleBE(offset: number, noAssert?: boolean): number; + swap16(): Buffer; + swap32(): Buffer; + swap64(): Buffer; + writeUInt8(value: number, offset: number, noAssert?: boolean): number; + writeUInt16LE(value: number, offset: number, noAssert?: boolean): number; + writeUInt16BE(value: number, offset: number, noAssert?: boolean): number; + writeUInt32LE(value: number, offset: number, noAssert?: boolean): number; + writeUInt32BE(value: number, offset: number, noAssert?: boolean): number; + writeInt8(value: number, offset: number, noAssert?: boolean): number; + writeInt16LE(value: number, offset: number, noAssert?: boolean): number; + writeInt16BE(value: number, offset: number, noAssert?: boolean): number; + writeInt32LE(value: number, offset: number, noAssert?: boolean): number; + writeInt32BE(value: number, offset: number, noAssert?: boolean): number; + writeFloatLE(value: number, offset: number, noAssert?: boolean): number; + writeFloatBE(value: number, offset: number, noAssert?: boolean): number; + writeDoubleLE(value: number, offset: number, noAssert?: boolean): number; + writeDoubleBE(value: number, offset: number, noAssert?: boolean): number; + fill(value: any, offset?: number, end?: number): this; + indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number; + lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number; + includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean; + + /** + * Allocates a new buffer containing the given {str}. + * + * @param str String to store in buffer. + * @param encoding encoding to use, optional. Default is 'utf8' + */ + constructor (str: string, encoding?: string); + /** + * Allocates a new buffer of {size} octets. + * + * @param size count of octets to allocate. + */ + constructor (size: number); + /** + * Allocates a new buffer containing the given {array} of octets. + * + * @param array The octets to store. + */ + constructor (array: Uint8Array); + /** + * Produces a Buffer backed by the same allocated memory as + * the given {ArrayBuffer}. + * + * + * @param arrayBuffer The ArrayBuffer with which to share memory. + */ + constructor (arrayBuffer: ArrayBuffer); + /** + * Allocates a new buffer containing the given {array} of octets. + * + * @param array The octets to store. + */ + constructor (array: any[]); + /** + * Copies the passed {buffer} data onto a new {Buffer} instance. + * + * @param buffer The buffer to copy. + */ + constructor (buffer: Buffer); + prototype: Buffer; + /** + * Allocates a new Buffer using an {array} of octets. + * + * @param array + */ + static from(array: any[]): Buffer; + /** + * When passed a reference to the .buffer property of a TypedArray instance, + * the newly created Buffer will share the same allocated memory as the TypedArray. + * The optional {byteOffset} and {length} arguments specify a memory range + * within the {arrayBuffer} that will be shared by the Buffer. + * + * @param arrayBuffer The .buffer property of a TypedArray or a new ArrayBuffer() + * @param byteOffset + * @param length + */ + static from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer; + /** + * Copies the passed {buffer} data onto a new Buffer instance. + * + * @param buffer + */ + static from(buffer: Buffer): Buffer; + /** + * Creates a new Buffer containing the given JavaScript string {str}. + * If provided, the {encoding} parameter identifies the character encoding. + * If not provided, {encoding} defaults to 'utf8'. + * + * @param str + */ + static from(str: string, encoding?: string): Buffer; + /** + * Returns true if {obj} is a Buffer + * + * @param obj object to test. + */ + static isBuffer(obj: any): obj is Buffer; + /** + * Returns true if {encoding} is a valid encoding argument. + * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex' + * + * @param encoding string to test. + */ + static isEncoding(encoding: string): boolean; + /** + * Gives the actual byte length of a string. encoding defaults to 'utf8'. + * This is not the same as String.prototype.length since that returns the number of characters in a string. + * + * @param string string to test. + * @param encoding encoding used to evaluate (defaults to 'utf8') + */ + static byteLength(string: string, encoding?: string): number; + /** + * Returns a buffer which is the result of concatenating all the buffers in the list together. + * + * If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer. + * If the list has exactly one item, then the first item of the list is returned. + * If the list has more than one item, then a new Buffer is created. + * + * @param list An array of Buffer objects to concatenate + * @param totalLength Total length of the buffers when concatenated. + * If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly. + */ + static concat(list: Buffer[], totalLength?: number): Buffer; + /** + * The same as buf1.compare(buf2). + */ + static compare(buf1: Buffer, buf2: Buffer): number; + /** + * Allocates a new buffer of {size} octets. + * + * @param size count of octets to allocate. + * @param fill if specified, buffer will be initialized by calling buf.fill(fill). + * If parameter is omitted, buffer will be filled with zeros. + * @param encoding encoding used for call to buf.fill while initalizing + */ + static alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer; + /** + * Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents + * of the newly created Buffer are unknown and may contain sensitive data. + * + * @param size count of octets to allocate + */ + static allocUnsafe(size: number): Buffer; + /** + * Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents + * of the newly created Buffer are unknown and may contain sensitive data. + * + * @param size count of octets to allocate + */ + static allocUnsafeSlow(size: number): Buffer; + } +} \ No newline at end of file diff --git a/homework8/project_express/node_modules/safe-buffer/index.js b/homework8/project_express/node_modules/safe-buffer/index.js new file mode 100644 index 0000000..22438da --- /dev/null +++ b/homework8/project_express/node_modules/safe-buffer/index.js @@ -0,0 +1,62 @@ +/* eslint-disable node/no-deprecated-api */ +var buffer = require('buffer') +var Buffer = buffer.Buffer + +// alternative to using Object.keys for old browsers +function copyProps (src, dst) { + for (var key in src) { + dst[key] = src[key] + } +} +if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { + module.exports = buffer +} else { + // Copy properties from require('buffer') + copyProps(buffer, exports) + exports.Buffer = SafeBuffer +} + +function SafeBuffer (arg, encodingOrOffset, length) { + return Buffer(arg, encodingOrOffset, length) +} + +// Copy static methods from Buffer +copyProps(Buffer, SafeBuffer) + +SafeBuffer.from = function (arg, encodingOrOffset, length) { + if (typeof arg === 'number') { + throw new TypeError('Argument must not be a number') + } + return Buffer(arg, encodingOrOffset, length) +} + +SafeBuffer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + var buf = Buffer(size) + if (fill !== undefined) { + if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + } else { + buf.fill(0) + } + return buf +} + +SafeBuffer.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return Buffer(size) +} + +SafeBuffer.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return buffer.SlowBuffer(size) +} diff --git a/homework8/project_express/node_modules/safe-buffer/package.json b/homework8/project_express/node_modules/safe-buffer/package.json new file mode 100644 index 0000000..eb76d92 --- /dev/null +++ b/homework8/project_express/node_modules/safe-buffer/package.json @@ -0,0 +1,63 @@ +{ + "_from": "safe-buffer@5.1.2", + "_id": "safe-buffer@5.1.2", + "_inBundle": false, + "_integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "_location": "/safe-buffer", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "safe-buffer@5.1.2", + "name": "safe-buffer", + "escapedName": "safe-buffer", + "rawSpec": "5.1.2", + "saveSpec": null, + "fetchSpec": "5.1.2" + }, + "_requiredBy": [ + "/content-disposition", + "/express" + ], + "_resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "_shasum": "991ec69d296e0313747d59bdfd2b745c35f8828d", + "_spec": "safe-buffer@5.1.2", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\express", + "author": { + "name": "Feross Aboukhadijeh", + "email": "feross@feross.org", + "url": "http://feross.org" + }, + "bugs": { + "url": "https://github.com/feross/safe-buffer/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Safer Node.js Buffer API", + "devDependencies": { + "standard": "*", + "tape": "^4.0.0" + }, + "homepage": "https://github.com/feross/safe-buffer", + "keywords": [ + "buffer", + "buffer allocate", + "node security", + "safe", + "safe-buffer", + "security", + "uninitialized" + ], + "license": "MIT", + "main": "index.js", + "name": "safe-buffer", + "repository": { + "type": "git", + "url": "git://github.com/feross/safe-buffer.git" + }, + "scripts": { + "test": "standard && tape test/*.js" + }, + "types": "index.d.ts", + "version": "5.1.2" +} diff --git a/homework8/project_express/node_modules/safer-buffer/LICENSE b/homework8/project_express/node_modules/safer-buffer/LICENSE new file mode 100644 index 0000000..4fe9e6f --- /dev/null +++ b/homework8/project_express/node_modules/safer-buffer/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Nikita Skovoroda + +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/homework8/project_express/node_modules/safer-buffer/Porting-Buffer.md b/homework8/project_express/node_modules/safer-buffer/Porting-Buffer.md new file mode 100644 index 0000000..68d86ba --- /dev/null +++ b/homework8/project_express/node_modules/safer-buffer/Porting-Buffer.md @@ -0,0 +1,268 @@ +# Porting to the Buffer.from/Buffer.alloc API + + +## Overview + +- [Variant 1: Drop support for Node.js ≤ 4.4.x and 5.0.0 — 5.9.x.](#variant-1) (*recommended*) +- [Variant 2: Use a polyfill](#variant-2) +- [Variant 3: manual detection, with safeguards](#variant-3) + +### Finding problematic bits of code using grep + +Just run `grep -nrE '[^a-zA-Z](Slow)?Buffer\s*\(' --exclude-dir node_modules`. + +It will find all the potentially unsafe places in your own code (with some considerably unlikely +exceptions). + +### Finding problematic bits of code using Node.js 8 + +If you’re using Node.js ≥ 8.0.0 (which is recommended), Node.js exposes multiple options that help with finding the relevant pieces of code: + +- `--trace-warnings` will make Node.js show a stack trace for this warning and other warnings that are printed by Node.js. +- `--trace-deprecation` does the same thing, but only for deprecation warnings. +- `--pending-deprecation` will show more types of deprecation warnings. In particular, it will show the `Buffer()` deprecation warning, even on Node.js 8. + +You can set these flags using an environment variable: + +```console +$ export NODE_OPTIONS='--trace-warnings --pending-deprecation' +$ cat example.js +'use strict'; +const foo = new Buffer('foo'); +$ node example.js +(node:7147) [DEP0005] DeprecationWarning: The Buffer() and new Buffer() constructors are not recommended for use due to security and usability concerns. Please use the new Buffer.alloc(), Buffer.allocUnsafe(), or Buffer.from() construction methods instead. + at showFlaggedDeprecation (buffer.js:127:13) + at new Buffer (buffer.js:148:3) + at Object. (/path/to/example.js:2:13) + [... more stack trace lines ...] +``` + +### Finding problematic bits of code using linters + +Eslint rules [no-buffer-constructor](https://eslint.org/docs/rules/no-buffer-constructor) +or +[node/no-deprecated-api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) +also find calls to deprecated `Buffer()` API. Those rules are included in some pre-sets. + +There is a drawback, though, that it doesn't always +[work correctly](https://github.com/chalker/safer-buffer#why-not-safe-buffer) when `Buffer` is +overriden e.g. with a polyfill, so recommended is a combination of this and some other method +described above. + + +## Variant 1: Drop support for Node.js ≤ 4.4.x and 5.0.0 — 5.9.x. + +This is the recommended solution nowadays that would imply only minimal overhead. + +The Node.js 5.x release line has been unsupported since July 2016, and the Node.js 4.x release line reaches its End of Life in April 2018 (→ [Schedule](https://github.com/nodejs/Release#release-schedule)). This means that these versions of Node.js will *not* receive any updates, even in case of security issues, so using these release lines should be avoided, if at all possible. + +What you would do in this case is to convert all `new Buffer()` or `Buffer()` calls to use `Buffer.alloc()` or `Buffer.from()`, in the following way: + +- For `new Buffer(number)`, replace it with `Buffer.alloc(number)`. +- For `new Buffer(string)` (or `new Buffer(string, encoding)`), replace it with `Buffer.from(string)` (or `Buffer.from(string, encoding)`). +- For all other combinations of arguments (these are much rarer), also replace `new Buffer(...arguments)` with `Buffer.from(...arguments)`. + +Note that `Buffer.alloc()` is also _faster_ on the current Node.js versions than +`new Buffer(size).fill(0)`, which is what you would otherwise need to ensure zero-filling. + +Enabling eslint rule [no-buffer-constructor](https://eslint.org/docs/rules/no-buffer-constructor) +or +[node/no-deprecated-api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) +is recommended to avoid accidential unsafe Buffer API usage. + +There is also a [JSCodeshift codemod](https://github.com/joyeecheung/node-dep-codemod#dep005) +for automatically migrating Buffer constructors to `Buffer.alloc()` or `Buffer.from()`. +Note that it currently only works with cases where the arguments are literals or where the +constructor is invoked with two arguments. + +_If you currently support those older Node.js versions and dropping them would be a semver-major change +for you, or if you support older branches of your packages, consider using [Variant 2](#variant-2) +or [Variant 3](#variant-3) on older branches, so people using those older branches will also receive +the fix. That way, you will eradicate potential issues caused by unguarded Buffer API usage and +your users will not observe a runtime deprecation warning when running your code on Node.js 10._ + + +## Variant 2: Use a polyfill + +Utilize [safer-buffer](https://www.npmjs.com/package/safer-buffer) as a polyfill to support older +Node.js versions. + +You would take exacly the same steps as in [Variant 1](#variant-1), but with a polyfill +`const Buffer = require('safer-buffer').Buffer` in all files where you use the new `Buffer` api. + +Make sure that you do not use old `new Buffer` API — in any files where the line above is added, +using old `new Buffer()` API will _throw_. It will be easy to notice that in CI, though. + +Alternatively, you could use [buffer-from](https://www.npmjs.com/package/buffer-from) and/or +[buffer-alloc](https://www.npmjs.com/package/buffer-alloc) [ponyfills](https://ponyfill.com/) — +those are great, the only downsides being 4 deps in the tree and slightly more code changes to +migrate off them (as you would be using e.g. `Buffer.from` under a different name). If you need only +`Buffer.from` polyfilled — `buffer-from` alone which comes with no extra dependencies. + +_Alternatively, you could use [safe-buffer](https://www.npmjs.com/package/safe-buffer) — it also +provides a polyfill, but takes a different approach which has +[it's drawbacks](https://github.com/chalker/safer-buffer#why-not-safe-buffer). It will allow you +to also use the older `new Buffer()` API in your code, though — but that's arguably a benefit, as +it is problematic, can cause issues in your code, and will start emitting runtime deprecation +warnings starting with Node.js 10._ + +Note that in either case, it is important that you also remove all calls to the old Buffer +API manually — just throwing in `safe-buffer` doesn't fix the problem by itself, it just provides +a polyfill for the new API. I have seen people doing that mistake. + +Enabling eslint rule [no-buffer-constructor](https://eslint.org/docs/rules/no-buffer-constructor) +or +[node/no-deprecated-api](https://github.com/mysticatea/eslint-plugin-node/blob/master/docs/rules/no-deprecated-api.md) +is recommended. + +_Don't forget to drop the polyfill usage once you drop support for Node.js < 4.5.0._ + + +## Variant 3 — manual detection, with safeguards + +This is useful if you create Buffer instances in only a few places (e.g. one), or you have your own +wrapper around them. + +### Buffer(0) + +This special case for creating empty buffers can be safely replaced with `Buffer.concat([])`, which +returns the same result all the way down to Node.js 0.8.x. + +### Buffer(notNumber) + +Before: + +```js +var buf = new Buffer(notNumber, encoding); +``` + +After: + +```js +var buf; +if (Buffer.from && Buffer.from !== Uint8Array.from) { + buf = Buffer.from(notNumber, encoding); +} else { + if (typeof notNumber === 'number') + throw new Error('The "size" argument must be of type number.'); + buf = new Buffer(notNumber, encoding); +} +``` + +`encoding` is optional. + +Note that the `typeof notNumber` before `new Buffer` is required (for cases when `notNumber` argument is not +hard-coded) and _is not caused by the deprecation of Buffer constructor_ — it's exactly _why_ the +Buffer constructor is deprecated. Ecosystem packages lacking this type-check caused numereous +security issues — situations when unsanitized user input could end up in the `Buffer(arg)` create +problems ranging from DoS to leaking sensitive information to the attacker from the process memory. + +When `notNumber` argument is hardcoded (e.g. literal `"abc"` or `[0,1,2]`), the `typeof` check can +be omitted. + +Also note that using TypeScript does not fix this problem for you — when libs written in +`TypeScript` are used from JS, or when user input ends up there — it behaves exactly as pure JS, as +all type checks are translation-time only and are not present in the actual JS code which TS +compiles to. + +### Buffer(number) + +For Node.js 0.10.x (and below) support: + +```js +var buf; +if (Buffer.alloc) { + buf = Buffer.alloc(number); +} else { + buf = new Buffer(number); + buf.fill(0); +} +``` + +Otherwise (Node.js ≥ 0.12.x): + +```js +const buf = Buffer.alloc ? Buffer.alloc(number) : new Buffer(number).fill(0); +``` + +## Regarding Buffer.allocUnsafe + +Be extra cautious when using `Buffer.allocUnsafe`: + * Don't use it if you don't have a good reason to + * e.g. you probably won't ever see a performance difference for small buffers, in fact, those + might be even faster with `Buffer.alloc()`, + * if your code is not in the hot code path — you also probably won't notice a difference, + * keep in mind that zero-filling minimizes the potential risks. + * If you use it, make sure that you never return the buffer in a partially-filled state, + * if you are writing to it sequentially — always truncate it to the actuall written length + +Errors in handling buffers allocated with `Buffer.allocUnsafe` could result in various issues, +ranged from undefined behaviour of your code to sensitive data (user input, passwords, certs) +leaking to the remote attacker. + +_Note that the same applies to `new Buffer` usage without zero-filling, depending on the Node.js +version (and lacking type checks also adds DoS to the list of potential problems)._ + + +## FAQ + + +### What is wrong with the `Buffer` constructor? + +The `Buffer` constructor could be used to create a buffer in many different ways: + +- `new Buffer(42)` creates a `Buffer` of 42 bytes. Before Node.js 8, this buffer contained + *arbitrary memory* for performance reasons, which could include anything ranging from + program source code to passwords and encryption keys. +- `new Buffer('abc')` creates a `Buffer` that contains the UTF-8-encoded version of + the string `'abc'`. A second argument could specify another encoding: For example, + `new Buffer(string, 'base64')` could be used to convert a Base64 string into the original + sequence of bytes that it represents. +- There are several other combinations of arguments. + +This meant that, in code like `var buffer = new Buffer(foo);`, *it is not possible to tell +what exactly the contents of the generated buffer are* without knowing the type of `foo`. + +Sometimes, the value of `foo` comes from an external source. For example, this function +could be exposed as a service on a web server, converting a UTF-8 string into its Base64 form: + +``` +function stringToBase64(req, res) { + // The request body should have the format of `{ string: 'foobar' }` + const rawBytes = new Buffer(req.body.string) + const encoded = rawBytes.toString('base64') + res.end({ encoded: encoded }) +} +``` + +Note that this code does *not* validate the type of `req.body.string`: + +- `req.body.string` is expected to be a string. If this is the case, all goes well. +- `req.body.string` is controlled by the client that sends the request. +- If `req.body.string` is the *number* `50`, the `rawBytes` would be 50 bytes: + - Before Node.js 8, the content would be uninitialized + - After Node.js 8, the content would be `50` bytes with the value `0` + +Because of the missing type check, an attacker could intentionally send a number +as part of the request. Using this, they can either: + +- Read uninitialized memory. This **will** leak passwords, encryption keys and other + kinds of sensitive information. (Information leak) +- Force the program to allocate a large amount of memory. For example, when specifying + `500000000` as the input value, each request will allocate 500MB of memory. + This can be used to either exhaust the memory available of a program completely + and make it crash, or slow it down significantly. (Denial of Service) + +Both of these scenarios are considered serious security issues in a real-world +web server context. + +when using `Buffer.from(req.body.string)` instead, passing a number will always +throw an exception instead, giving a controlled behaviour that can always be +handled by the program. + + +### The `Buffer()` constructor has been deprecated for a while. Is this really an issue? + +Surveys of code in the `npm` ecosystem have shown that the `Buffer()` constructor is still +widely used. This includes new code, and overall usage of such code has actually been +*increasing*. diff --git a/homework8/project_express/node_modules/safer-buffer/Readme.md b/homework8/project_express/node_modules/safer-buffer/Readme.md new file mode 100644 index 0000000..14b0822 --- /dev/null +++ b/homework8/project_express/node_modules/safer-buffer/Readme.md @@ -0,0 +1,156 @@ +# safer-buffer [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![javascript style guide][standard-image]][standard-url] [![Security Responsible Disclosure][secuirty-image]][secuirty-url] + +[travis-image]: https://travis-ci.org/ChALkeR/safer-buffer.svg?branch=master +[travis-url]: https://travis-ci.org/ChALkeR/safer-buffer +[npm-image]: https://img.shields.io/npm/v/safer-buffer.svg +[npm-url]: https://npmjs.org/package/safer-buffer +[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg +[standard-url]: https://standardjs.com +[secuirty-image]: https://img.shields.io/badge/Security-Responsible%20Disclosure-green.svg +[secuirty-url]: https://github.com/nodejs/security-wg/blob/master/processes/responsible_disclosure_template.md + +Modern Buffer API polyfill without footguns, working on Node.js from 0.8 to current. + +## How to use? + +First, port all `Buffer()` and `new Buffer()` calls to `Buffer.alloc()` and `Buffer.from()` API. + +Then, to achieve compatibility with outdated Node.js versions (`<4.5.0` and 5.x `<5.9.0`), use +`const Buffer = require('safer-buffer').Buffer` in all files where you make calls to the new +Buffer API. _Use `var` instead of `const` if you need that for your Node.js version range support._ + +Also, see the +[porting Buffer](https://github.com/ChALkeR/safer-buffer/blob/master/Porting-Buffer.md) guide. + +## Do I need it? + +Hopefully, not — dropping support for outdated Node.js versions should be fine nowdays, and that +is the recommended path forward. You _do_ need to port to the `Buffer.alloc()` and `Buffer.from()` +though. + +See the [porting guide](https://github.com/ChALkeR/safer-buffer/blob/master/Porting-Buffer.md) +for a better description. + +## Why not [safe-buffer](https://npmjs.com/safe-buffer)? + +_In short: while `safe-buffer` serves as a polyfill for the new API, it allows old API usage and +itself contains footguns._ + +`safe-buffer` could be used safely to get the new API while still keeping support for older +Node.js versions (like this module), but while analyzing ecosystem usage of the old Buffer API +I found out that `safe-buffer` is itself causing problems in some cases. + +For example, consider the following snippet: + +```console +$ cat example.unsafe.js +console.log(Buffer(20)) +$ ./node-v6.13.0-linux-x64/bin/node example.unsafe.js + +$ standard example.unsafe.js +standard: Use JavaScript Standard Style (https://standardjs.com) + /home/chalker/repo/safer-buffer/example.unsafe.js:2:13: 'Buffer()' was deprecated since v6. Use 'Buffer.alloc()' or 'Buffer.from()' (use 'https://www.npmjs.com/package/safe-buffer' for '<4.5.0') instead. +``` + +This is allocates and writes to console an uninitialized chunk of memory. +[standard](https://www.npmjs.com/package/standard) linter (among others) catch that and warn people +to avoid using unsafe API. + +Let's now throw in `safe-buffer`! + +```console +$ cat example.safe-buffer.js +const Buffer = require('safe-buffer').Buffer +console.log(Buffer(20)) +$ standard example.safe-buffer.js +$ ./node-v6.13.0-linux-x64/bin/node example.safe-buffer.js + +``` + +See the problem? Adding in `safe-buffer` _magically removes the lint warning_, but the behavior +remains identiсal to what we had before, and when launched on Node.js 6.x LTS — this dumps out +chunks of uninitialized memory. +_And this code will still emit runtime warnings on Node.js 10.x and above._ + +That was done by design. I first considered changing `safe-buffer`, prohibiting old API usage or +emitting warnings on it, but that significantly diverges from `safe-buffer` design. After some +discussion, it was decided to move my approach into a separate package, and _this is that separate +package_. + +This footgun is not imaginary — I observed top-downloaded packages doing that kind of thing, +«fixing» the lint warning by blindly including `safe-buffer` without any actual changes. + +Also in some cases, even if the API _was_ migrated to use of safe Buffer API — a random pull request +can bring unsafe Buffer API usage back to the codebase by adding new calls — and that could go +unnoticed even if you have a linter prohibiting that (becase of the reason stated above), and even +pass CI. _I also observed that being done in popular packages._ + +Some examples: + * [webdriverio](https://github.com/webdriverio/webdriverio/commit/05cbd3167c12e4930f09ef7cf93b127ba4effae4#diff-124380949022817b90b622871837d56cR31) + (a module with 548 759 downloads/month), + * [websocket-stream](https://github.com/maxogden/websocket-stream/commit/c9312bd24d08271687d76da0fe3c83493871cf61) + (218 288 d/m, fix in [maxogden/websocket-stream#142](https://github.com/maxogden/websocket-stream/pull/142)), + * [node-serialport](https://github.com/node-serialport/node-serialport/commit/e8d9d2b16c664224920ce1c895199b1ce2def48c) + (113 138 d/m, fix in [node-serialport/node-serialport#1510](https://github.com/node-serialport/node-serialport/pull/1510)), + * [karma](https://github.com/karma-runner/karma/commit/3d94b8cf18c695104ca195334dc75ff054c74eec) + (3 973 193 d/m, fix in [karma-runner/karma#2947](https://github.com/karma-runner/karma/pull/2947)), + * [spdy-transport](https://github.com/spdy-http2/spdy-transport/commit/5375ac33f4a62a4f65bcfc2827447d42a5dbe8b1) + (5 970 727 d/m, fix in [spdy-http2/spdy-transport#53](https://github.com/spdy-http2/spdy-transport/pull/53)). + * And there are a lot more over the ecosystem. + +I filed a PR at +[mysticatea/eslint-plugin-node#110](https://github.com/mysticatea/eslint-plugin-node/pull/110) to +partially fix that (for cases when that lint rule is used), but it is a semver-major change for +linter rules and presets, so it would take significant time for that to reach actual setups. +_It also hasn't been released yet (2018-03-20)._ + +Also, `safer-buffer` discourages the usage of `.allocUnsafe()`, which is often done by a mistake. +It still supports it with an explicit concern barier, by placing it under +`require('safer-buffer/dangereous')`. + +## But isn't throwing bad? + +Not really. It's an error that could be noticed and fixed early, instead of causing havoc later like +unguarded `new Buffer()` calls that end up receiving user input can do. + +This package affects only the files where `var Buffer = require('safer-buffer').Buffer` was done, so +it is really simple to keep track of things and make sure that you don't mix old API usage with that. +Also, CI should hint anything that you might have missed. + +New commits, if tested, won't land new usage of unsafe Buffer API this way. +_Node.js 10.x also deals with that by printing a runtime depecation warning._ + +### Would it affect third-party modules? + +No, unless you explicitly do an awful thing like monkey-patching or overriding the built-in `Buffer`. +Don't do that. + +### But I don't want throwing… + +That is also fine! + +Also, it could be better in some cases when you don't comprehensive enough test coverage. + +In that case — just don't override `Buffer` and use +`var SaferBuffer = require('safer-buffer').Buffer` instead. + +That way, everything using `Buffer` natively would still work, but there would be two drawbacks: + +* `Buffer.from`/`Buffer.alloc` won't be polyfilled — use `SaferBuffer.from` and + `SaferBuffer.alloc` instead. +* You are still open to accidentally using the insecure deprecated API — use a linter to catch that. + +Note that using a linter to catch accidential `Buffer` constructor usage in this case is strongly +recommended. `Buffer` is not overriden in this usecase, so linters won't get confused. + +## «Without footguns»? + +Well, it is still possible to do _some_ things with `Buffer` API, e.g. accessing `.buffer` property +on older versions and duping things from there. You shouldn't do that in your code, probabably. + +The intention is to remove the most significant footguns that affect lots of packages in the +ecosystem, and to do it in the proper way. + +Also, this package doesn't protect against security issues affecting some Node.js versions, so for +usage in your own production code, it is still recommended to update to a Node.js version +[supported by upstream](https://github.com/nodejs/release#release-schedule). diff --git a/homework8/project_express/node_modules/safer-buffer/dangerous.js b/homework8/project_express/node_modules/safer-buffer/dangerous.js new file mode 100644 index 0000000..ca41fdc --- /dev/null +++ b/homework8/project_express/node_modules/safer-buffer/dangerous.js @@ -0,0 +1,58 @@ +/* eslint-disable node/no-deprecated-api */ + +'use strict' + +var buffer = require('buffer') +var Buffer = buffer.Buffer +var safer = require('./safer.js') +var Safer = safer.Buffer + +var dangerous = {} + +var key + +for (key in safer) { + if (!safer.hasOwnProperty(key)) continue + dangerous[key] = safer[key] +} + +var Dangereous = dangerous.Buffer = {} + +// Copy Safer API +for (key in Safer) { + if (!Safer.hasOwnProperty(key)) continue + Dangereous[key] = Safer[key] +} + +// Copy those missing unsafe methods, if they are present +for (key in Buffer) { + if (!Buffer.hasOwnProperty(key)) continue + if (Dangereous.hasOwnProperty(key)) continue + Dangereous[key] = Buffer[key] +} + +if (!Dangereous.allocUnsafe) { + Dangereous.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('The "size" argument must be of type number. Received type ' + typeof size) + } + if (size < 0 || size >= 2 * (1 << 30)) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } + return Buffer(size) + } +} + +if (!Dangereous.allocUnsafeSlow) { + Dangereous.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('The "size" argument must be of type number. Received type ' + typeof size) + } + if (size < 0 || size >= 2 * (1 << 30)) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } + return buffer.SlowBuffer(size) + } +} + +module.exports = dangerous diff --git a/homework8/project_express/node_modules/safer-buffer/package.json b/homework8/project_express/node_modules/safer-buffer/package.json new file mode 100644 index 0000000..19230ab --- /dev/null +++ b/homework8/project_express/node_modules/safer-buffer/package.json @@ -0,0 +1,60 @@ +{ + "_from": "safer-buffer@>= 2.1.2 < 3", + "_id": "safer-buffer@2.1.2", + "_inBundle": false, + "_integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "_location": "/safer-buffer", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "safer-buffer@>= 2.1.2 < 3", + "name": "safer-buffer", + "escapedName": "safer-buffer", + "rawSpec": ">= 2.1.2 < 3", + "saveSpec": null, + "fetchSpec": ">= 2.1.2 < 3" + }, + "_requiredBy": [ + "/iconv-lite" + ], + "_resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "_shasum": "44fa161b0187b9549dd84bb91802f9bd8385cd6a", + "_spec": "safer-buffer@>= 2.1.2 < 3", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\iconv-lite", + "author": { + "name": "Nikita Skovoroda", + "email": "chalkerx@gmail.com", + "url": "https://github.com/ChALkeR" + }, + "bugs": { + "url": "https://github.com/ChALkeR/safer-buffer/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Modern Buffer API polyfill without footguns", + "devDependencies": { + "standard": "^11.0.1", + "tape": "^4.9.0" + }, + "files": [ + "Porting-Buffer.md", + "Readme.md", + "tests.js", + "dangerous.js", + "safer.js" + ], + "homepage": "https://github.com/ChALkeR/safer-buffer#readme", + "license": "MIT", + "main": "safer.js", + "name": "safer-buffer", + "repository": { + "type": "git", + "url": "git+https://github.com/ChALkeR/safer-buffer.git" + }, + "scripts": { + "browserify-test": "browserify --external tape tests.js > browserify-tests.js && tape browserify-tests.js", + "test": "standard && tape tests.js" + }, + "version": "2.1.2" +} diff --git a/homework8/project_express/node_modules/safer-buffer/safer.js b/homework8/project_express/node_modules/safer-buffer/safer.js new file mode 100644 index 0000000..37c7e1a --- /dev/null +++ b/homework8/project_express/node_modules/safer-buffer/safer.js @@ -0,0 +1,77 @@ +/* eslint-disable node/no-deprecated-api */ + +'use strict' + +var buffer = require('buffer') +var Buffer = buffer.Buffer + +var safer = {} + +var key + +for (key in buffer) { + if (!buffer.hasOwnProperty(key)) continue + if (key === 'SlowBuffer' || key === 'Buffer') continue + safer[key] = buffer[key] +} + +var Safer = safer.Buffer = {} +for (key in Buffer) { + if (!Buffer.hasOwnProperty(key)) continue + if (key === 'allocUnsafe' || key === 'allocUnsafeSlow') continue + Safer[key] = Buffer[key] +} + +safer.Buffer.prototype = Buffer.prototype + +if (!Safer.from || Safer.from === Uint8Array.from) { + Safer.from = function (value, encodingOrOffset, length) { + if (typeof value === 'number') { + throw new TypeError('The "value" argument must not be of type number. Received type ' + typeof value) + } + if (value && typeof value.length === 'undefined') { + throw new TypeError('The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type ' + typeof value) + } + return Buffer(value, encodingOrOffset, length) + } +} + +if (!Safer.alloc) { + Safer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('The "size" argument must be of type number. Received type ' + typeof size) + } + if (size < 0 || size >= 2 * (1 << 30)) { + throw new RangeError('The value "' + size + '" is invalid for option "size"') + } + var buf = Buffer(size) + if (!fill || fill.length === 0) { + buf.fill(0) + } else if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + return buf + } +} + +if (!safer.kStringMaxLength) { + try { + safer.kStringMaxLength = process.binding('buffer').kStringMaxLength + } catch (e) { + // we can't determine kStringMaxLength in environments where process.binding + // is unsupported, so let's not set it + } +} + +if (!safer.constants) { + safer.constants = { + MAX_LENGTH: safer.kMaxLength + } + if (safer.kStringMaxLength) { + safer.constants.MAX_STRING_LENGTH = safer.kStringMaxLength + } +} + +module.exports = safer diff --git a/homework8/project_express/node_modules/safer-buffer/tests.js b/homework8/project_express/node_modules/safer-buffer/tests.js new file mode 100644 index 0000000..7ed2777 --- /dev/null +++ b/homework8/project_express/node_modules/safer-buffer/tests.js @@ -0,0 +1,406 @@ +/* eslint-disable node/no-deprecated-api */ + +'use strict' + +var test = require('tape') + +var buffer = require('buffer') + +var index = require('./') +var safer = require('./safer') +var dangerous = require('./dangerous') + +/* Inheritance tests */ + +test('Default is Safer', function (t) { + t.equal(index, safer) + t.notEqual(safer, dangerous) + t.notEqual(index, dangerous) + t.end() +}) + +test('Is not a function', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(typeof impl, 'object') + t.equal(typeof impl.Buffer, 'object') + }); + [buffer].forEach(function (impl) { + t.equal(typeof impl, 'object') + t.equal(typeof impl.Buffer, 'function') + }) + t.end() +}) + +test('Constructor throws', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.throws(function () { impl.Buffer() }) + t.throws(function () { impl.Buffer(0) }) + t.throws(function () { impl.Buffer('a') }) + t.throws(function () { impl.Buffer('a', 'utf-8') }) + t.throws(function () { return new impl.Buffer() }) + t.throws(function () { return new impl.Buffer(0) }) + t.throws(function () { return new impl.Buffer('a') }) + t.throws(function () { return new impl.Buffer('a', 'utf-8') }) + }) + t.end() +}) + +test('Safe methods exist', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(typeof impl.Buffer.alloc, 'function', 'alloc') + t.equal(typeof impl.Buffer.from, 'function', 'from') + }) + t.end() +}) + +test('Unsafe methods exist only in Dangerous', function (t) { + [index, safer].forEach(function (impl) { + t.equal(typeof impl.Buffer.allocUnsafe, 'undefined') + t.equal(typeof impl.Buffer.allocUnsafeSlow, 'undefined') + }); + [dangerous].forEach(function (impl) { + t.equal(typeof impl.Buffer.allocUnsafe, 'function') + t.equal(typeof impl.Buffer.allocUnsafeSlow, 'function') + }) + t.end() +}) + +test('Generic methods/properties are defined and equal', function (t) { + ['poolSize', 'isBuffer', 'concat', 'byteLength'].forEach(function (method) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer[method], buffer.Buffer[method], method) + t.notEqual(typeof impl.Buffer[method], 'undefined', method) + }) + }) + t.end() +}) + +test('Built-in buffer static methods/properties are inherited', function (t) { + Object.keys(buffer).forEach(function (method) { + if (method === 'SlowBuffer' || method === 'Buffer') return; + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl[method], buffer[method], method) + t.notEqual(typeof impl[method], 'undefined', method) + }) + }) + t.end() +}) + +test('Built-in Buffer static methods/properties are inherited', function (t) { + Object.keys(buffer.Buffer).forEach(function (method) { + if (method === 'allocUnsafe' || method === 'allocUnsafeSlow') return; + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer[method], buffer.Buffer[method], method) + t.notEqual(typeof impl.Buffer[method], 'undefined', method) + }) + }) + t.end() +}) + +test('.prototype property of Buffer is inherited', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer.prototype, buffer.Buffer.prototype, 'prototype') + t.notEqual(typeof impl.Buffer.prototype, 'undefined', 'prototype') + }) + t.end() +}) + +test('All Safer methods are present in Dangerous', function (t) { + Object.keys(safer).forEach(function (method) { + if (method === 'Buffer') return; + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl[method], safer[method], method) + if (method !== 'kStringMaxLength') { + t.notEqual(typeof impl[method], 'undefined', method) + } + }) + }) + Object.keys(safer.Buffer).forEach(function (method) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer[method], safer.Buffer[method], method) + t.notEqual(typeof impl.Buffer[method], 'undefined', method) + }) + }) + t.end() +}) + +test('Safe methods from Dangerous methods are present in Safer', function (t) { + Object.keys(dangerous).forEach(function (method) { + if (method === 'Buffer') return; + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl[method], dangerous[method], method) + if (method !== 'kStringMaxLength') { + t.notEqual(typeof impl[method], 'undefined', method) + } + }) + }) + Object.keys(dangerous.Buffer).forEach(function (method) { + if (method === 'allocUnsafe' || method === 'allocUnsafeSlow') return; + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer[method], dangerous.Buffer[method], method) + t.notEqual(typeof impl.Buffer[method], 'undefined', method) + }) + }) + t.end() +}) + +/* Behaviour tests */ + +test('Methods return Buffers', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(0))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(0, 10))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(0, 'a'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(10))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(10, 'x'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.alloc(9, 'ab'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from(''))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from('string'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from('string', 'utf-8'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64'))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from([0, 42, 3]))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from(new Uint8Array([0, 42, 3])))) + t.ok(buffer.Buffer.isBuffer(impl.Buffer.from([]))) + }); + ['allocUnsafe', 'allocUnsafeSlow'].forEach(function (method) { + t.ok(buffer.Buffer.isBuffer(dangerous.Buffer[method](0))) + t.ok(buffer.Buffer.isBuffer(dangerous.Buffer[method](10))) + }) + t.end() +}) + +test('Constructor is buffer.Buffer', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer.alloc(0).constructor, buffer.Buffer) + t.equal(impl.Buffer.alloc(0, 10).constructor, buffer.Buffer) + t.equal(impl.Buffer.alloc(0, 'a').constructor, buffer.Buffer) + t.equal(impl.Buffer.alloc(10).constructor, buffer.Buffer) + t.equal(impl.Buffer.alloc(10, 'x').constructor, buffer.Buffer) + t.equal(impl.Buffer.alloc(9, 'ab').constructor, buffer.Buffer) + t.equal(impl.Buffer.from('').constructor, buffer.Buffer) + t.equal(impl.Buffer.from('string').constructor, buffer.Buffer) + t.equal(impl.Buffer.from('string', 'utf-8').constructor, buffer.Buffer) + t.equal(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64').constructor, buffer.Buffer) + t.equal(impl.Buffer.from([0, 42, 3]).constructor, buffer.Buffer) + t.equal(impl.Buffer.from(new Uint8Array([0, 42, 3])).constructor, buffer.Buffer) + t.equal(impl.Buffer.from([]).constructor, buffer.Buffer) + }); + [0, 10, 100].forEach(function (arg) { + t.equal(dangerous.Buffer.allocUnsafe(arg).constructor, buffer.Buffer) + t.equal(dangerous.Buffer.allocUnsafeSlow(arg).constructor, buffer.SlowBuffer(0).constructor) + }) + t.end() +}) + +test('Invalid calls throw', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.throws(function () { impl.Buffer.from(0) }) + t.throws(function () { impl.Buffer.from(10) }) + t.throws(function () { impl.Buffer.from(10, 'utf-8') }) + t.throws(function () { impl.Buffer.from('string', 'invalid encoding') }) + t.throws(function () { impl.Buffer.from(-10) }) + t.throws(function () { impl.Buffer.from(1e90) }) + t.throws(function () { impl.Buffer.from(Infinity) }) + t.throws(function () { impl.Buffer.from(-Infinity) }) + t.throws(function () { impl.Buffer.from(NaN) }) + t.throws(function () { impl.Buffer.from(null) }) + t.throws(function () { impl.Buffer.from(undefined) }) + t.throws(function () { impl.Buffer.from() }) + t.throws(function () { impl.Buffer.from({}) }) + t.throws(function () { impl.Buffer.alloc('') }) + t.throws(function () { impl.Buffer.alloc('string') }) + t.throws(function () { impl.Buffer.alloc('string', 'utf-8') }) + t.throws(function () { impl.Buffer.alloc('b25ldHdvdGhyZWU=', 'base64') }) + t.throws(function () { impl.Buffer.alloc(-10) }) + t.throws(function () { impl.Buffer.alloc(1e90) }) + t.throws(function () { impl.Buffer.alloc(2 * (1 << 30)) }) + t.throws(function () { impl.Buffer.alloc(Infinity) }) + t.throws(function () { impl.Buffer.alloc(-Infinity) }) + t.throws(function () { impl.Buffer.alloc(null) }) + t.throws(function () { impl.Buffer.alloc(undefined) }) + t.throws(function () { impl.Buffer.alloc() }) + t.throws(function () { impl.Buffer.alloc([]) }) + t.throws(function () { impl.Buffer.alloc([0, 42, 3]) }) + t.throws(function () { impl.Buffer.alloc({}) }) + }); + ['allocUnsafe', 'allocUnsafeSlow'].forEach(function (method) { + t.throws(function () { dangerous.Buffer[method]('') }) + t.throws(function () { dangerous.Buffer[method]('string') }) + t.throws(function () { dangerous.Buffer[method]('string', 'utf-8') }) + t.throws(function () { dangerous.Buffer[method](2 * (1 << 30)) }) + t.throws(function () { dangerous.Buffer[method](Infinity) }) + if (dangerous.Buffer[method] === buffer.Buffer.allocUnsafe) { + t.skip('Skipping, older impl of allocUnsafe coerced negative sizes to 0') + } else { + t.throws(function () { dangerous.Buffer[method](-10) }) + t.throws(function () { dangerous.Buffer[method](-1e90) }) + t.throws(function () { dangerous.Buffer[method](-Infinity) }) + } + t.throws(function () { dangerous.Buffer[method](null) }) + t.throws(function () { dangerous.Buffer[method](undefined) }) + t.throws(function () { dangerous.Buffer[method]() }) + t.throws(function () { dangerous.Buffer[method]([]) }) + t.throws(function () { dangerous.Buffer[method]([0, 42, 3]) }) + t.throws(function () { dangerous.Buffer[method]({}) }) + }) + t.end() +}) + +test('Buffers have appropriate lengths', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.equal(impl.Buffer.alloc(0).length, 0) + t.equal(impl.Buffer.alloc(10).length, 10) + t.equal(impl.Buffer.from('').length, 0) + t.equal(impl.Buffer.from('string').length, 6) + t.equal(impl.Buffer.from('string', 'utf-8').length, 6) + t.equal(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64').length, 11) + t.equal(impl.Buffer.from([0, 42, 3]).length, 3) + t.equal(impl.Buffer.from(new Uint8Array([0, 42, 3])).length, 3) + t.equal(impl.Buffer.from([]).length, 0) + }); + ['allocUnsafe', 'allocUnsafeSlow'].forEach(function (method) { + t.equal(dangerous.Buffer[method](0).length, 0) + t.equal(dangerous.Buffer[method](10).length, 10) + }) + t.end() +}) + +test('Buffers have appropriate lengths (2)', function (t) { + t.equal(index.Buffer.alloc, safer.Buffer.alloc) + t.equal(index.Buffer.alloc, dangerous.Buffer.alloc) + var ok = true; + [ safer.Buffer.alloc, + dangerous.Buffer.allocUnsafe, + dangerous.Buffer.allocUnsafeSlow + ].forEach(function (method) { + for (var i = 0; i < 1e2; i++) { + var length = Math.round(Math.random() * 1e5) + var buf = method(length) + if (!buffer.Buffer.isBuffer(buf)) ok = false + if (buf.length !== length) ok = false + } + }) + t.ok(ok) + t.end() +}) + +test('.alloc(size) is zero-filled and has correct length', function (t) { + t.equal(index.Buffer.alloc, safer.Buffer.alloc) + t.equal(index.Buffer.alloc, dangerous.Buffer.alloc) + var ok = true + for (var i = 0; i < 1e2; i++) { + var length = Math.round(Math.random() * 2e6) + var buf = index.Buffer.alloc(length) + if (!buffer.Buffer.isBuffer(buf)) ok = false + if (buf.length !== length) ok = false + var j + for (j = 0; j < length; j++) { + if (buf[j] !== 0) ok = false + } + buf.fill(1) + for (j = 0; j < length; j++) { + if (buf[j] !== 1) ok = false + } + } + t.ok(ok) + t.end() +}) + +test('.allocUnsafe / .allocUnsafeSlow are fillable and have correct lengths', function (t) { + ['allocUnsafe', 'allocUnsafeSlow'].forEach(function (method) { + var ok = true + for (var i = 0; i < 1e2; i++) { + var length = Math.round(Math.random() * 2e6) + var buf = dangerous.Buffer[method](length) + if (!buffer.Buffer.isBuffer(buf)) ok = false + if (buf.length !== length) ok = false + buf.fill(0, 0, length) + var j + for (j = 0; j < length; j++) { + if (buf[j] !== 0) ok = false + } + buf.fill(1, 0, length) + for (j = 0; j < length; j++) { + if (buf[j] !== 1) ok = false + } + } + t.ok(ok, method) + }) + t.end() +}) + +test('.alloc(size, fill) is `fill`-filled', function (t) { + t.equal(index.Buffer.alloc, safer.Buffer.alloc) + t.equal(index.Buffer.alloc, dangerous.Buffer.alloc) + var ok = true + for (var i = 0; i < 1e2; i++) { + var length = Math.round(Math.random() * 2e6) + var fill = Math.round(Math.random() * 255) + var buf = index.Buffer.alloc(length, fill) + if (!buffer.Buffer.isBuffer(buf)) ok = false + if (buf.length !== length) ok = false + for (var j = 0; j < length; j++) { + if (buf[j] !== fill) ok = false + } + } + t.ok(ok) + t.end() +}) + +test('.alloc(size, fill) is `fill`-filled', function (t) { + t.equal(index.Buffer.alloc, safer.Buffer.alloc) + t.equal(index.Buffer.alloc, dangerous.Buffer.alloc) + var ok = true + for (var i = 0; i < 1e2; i++) { + var length = Math.round(Math.random() * 2e6) + var fill = Math.round(Math.random() * 255) + var buf = index.Buffer.alloc(length, fill) + if (!buffer.Buffer.isBuffer(buf)) ok = false + if (buf.length !== length) ok = false + for (var j = 0; j < length; j++) { + if (buf[j] !== fill) ok = false + } + } + t.ok(ok) + t.deepEqual(index.Buffer.alloc(9, 'a'), index.Buffer.alloc(9, 97)) + t.notDeepEqual(index.Buffer.alloc(9, 'a'), index.Buffer.alloc(9, 98)) + + var tmp = new buffer.Buffer(2) + tmp.fill('ok') + if (tmp[1] === tmp[0]) { + // Outdated Node.js + t.deepEqual(index.Buffer.alloc(5, 'ok'), index.Buffer.from('ooooo')) + } else { + t.deepEqual(index.Buffer.alloc(5, 'ok'), index.Buffer.from('okoko')) + } + t.notDeepEqual(index.Buffer.alloc(5, 'ok'), index.Buffer.from('kokok')) + + t.end() +}) + +test('safer.Buffer.from returns results same as Buffer constructor', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.deepEqual(impl.Buffer.from(''), new buffer.Buffer('')) + t.deepEqual(impl.Buffer.from('string'), new buffer.Buffer('string')) + t.deepEqual(impl.Buffer.from('string', 'utf-8'), new buffer.Buffer('string', 'utf-8')) + t.deepEqual(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64'), new buffer.Buffer('b25ldHdvdGhyZWU=', 'base64')) + t.deepEqual(impl.Buffer.from([0, 42, 3]), new buffer.Buffer([0, 42, 3])) + t.deepEqual(impl.Buffer.from(new Uint8Array([0, 42, 3])), new buffer.Buffer(new Uint8Array([0, 42, 3]))) + t.deepEqual(impl.Buffer.from([]), new buffer.Buffer([])) + }) + t.end() +}) + +test('safer.Buffer.from returns consistent results', function (t) { + [index, safer, dangerous].forEach(function (impl) { + t.deepEqual(impl.Buffer.from(''), impl.Buffer.alloc(0)) + t.deepEqual(impl.Buffer.from([]), impl.Buffer.alloc(0)) + t.deepEqual(impl.Buffer.from(new Uint8Array([])), impl.Buffer.alloc(0)) + t.deepEqual(impl.Buffer.from('string', 'utf-8'), impl.Buffer.from('string')) + t.deepEqual(impl.Buffer.from('string'), impl.Buffer.from([115, 116, 114, 105, 110, 103])) + t.deepEqual(impl.Buffer.from('string'), impl.Buffer.from(impl.Buffer.from('string'))) + t.deepEqual(impl.Buffer.from('b25ldHdvdGhyZWU=', 'base64'), impl.Buffer.from('onetwothree')) + t.notDeepEqual(impl.Buffer.from('b25ldHdvdGhyZWU='), impl.Buffer.from('onetwothree')) + }) + t.end() +}) diff --git a/homework8/project_express/node_modules/semver/CHANGELOG.md b/homework8/project_express/node_modules/semver/CHANGELOG.md new file mode 100644 index 0000000..66304fd --- /dev/null +++ b/homework8/project_express/node_modules/semver/CHANGELOG.md @@ -0,0 +1,39 @@ +# changes log + +## 5.7 + +* Add `minVersion` method + +## 5.6 + +* Move boolean `loose` param to an options object, with + backwards-compatibility protection. +* Add ability to opt out of special prerelease version handling with + the `includePrerelease` option flag. + +## 5.5 + +* Add version coercion capabilities + +## 5.4 + +* Add intersection checking + +## 5.3 + +* Add `minSatisfying` method + +## 5.2 + +* Add `prerelease(v)` that returns prerelease components + +## 5.1 + +* Add Backus-Naur for ranges +* Remove excessively cute inspection methods + +## 5.0 + +* Remove AMD/Browserified build artifacts +* Fix ltr and gtr when using the `*` range +* Fix for range `*` with a prerelease identifier diff --git a/homework8/project_express/node_modules/semver/LICENSE b/homework8/project_express/node_modules/semver/LICENSE new file mode 100644 index 0000000..19129e3 --- /dev/null +++ b/homework8/project_express/node_modules/semver/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/homework8/project_express/node_modules/semver/README.md b/homework8/project_express/node_modules/semver/README.md new file mode 100644 index 0000000..f8dfa5a --- /dev/null +++ b/homework8/project_express/node_modules/semver/README.md @@ -0,0 +1,412 @@ +semver(1) -- The semantic versioner for npm +=========================================== + +## Install + +```bash +npm install --save semver +```` + +## Usage + +As a node module: + +```js +const semver = require('semver') + +semver.valid('1.2.3') // '1.2.3' +semver.valid('a.b.c') // null +semver.clean(' =v1.2.3 ') // '1.2.3' +semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true +semver.gt('1.2.3', '9.8.7') // false +semver.lt('1.2.3', '9.8.7') // true +semver.minVersion('>=1.0.0') // '1.0.0' +semver.valid(semver.coerce('v2')) // '2.0.0' +semver.valid(semver.coerce('42.6.7.9.3-alpha')) // '42.6.7' +``` + +As a command-line utility: + +``` +$ semver -h + +A JavaScript implementation of the https://semver.org/ specification +Copyright Isaac Z. Schlueter + +Usage: semver [options] [ [...]] +Prints valid versions sorted by SemVer precedence + +Options: +-r --range + Print versions that match the specified range. + +-i --increment [] + Increment a version by the specified level. Level can + be one of: major, minor, patch, premajor, preminor, + prepatch, or prerelease. Default level is 'patch'. + Only one version may be specified. + +--preid + Identifier to be used to prefix premajor, preminor, + prepatch or prerelease version increments. + +-l --loose + Interpret versions and ranges loosely + +-p --include-prerelease + Always include prerelease versions in range matching + +-c --coerce + Coerce a string into SemVer if possible + (does not imply --loose) + +Program exits successfully if any valid version satisfies +all supplied ranges, and prints all satisfying versions. + +If no satisfying versions are found, then exits failure. + +Versions are printed in ascending order, so supplying +multiple versions to the utility will just sort them. +``` + +## Versions + +A "version" is described by the `v2.0.0` specification found at +. + +A leading `"="` or `"v"` character is stripped off and ignored. + +## Ranges + +A `version range` is a set of `comparators` which specify versions +that satisfy the range. + +A `comparator` is composed of an `operator` and a `version`. The set +of primitive `operators` is: + +* `<` Less than +* `<=` Less than or equal to +* `>` Greater than +* `>=` Greater than or equal to +* `=` Equal. If no operator is specified, then equality is assumed, + so this operator is optional, but MAY be included. + +For example, the comparator `>=1.2.7` would match the versions +`1.2.7`, `1.2.8`, `2.5.3`, and `1.3.9`, but not the versions `1.2.6` +or `1.1.0`. + +Comparators can be joined by whitespace to form a `comparator set`, +which is satisfied by the **intersection** of all of the comparators +it includes. + +A range is composed of one or more comparator sets, joined by `||`. A +version matches a range if and only if every comparator in at least +one of the `||`-separated comparator sets is satisfied by the version. + +For example, the range `>=1.2.7 <1.3.0` would match the versions +`1.2.7`, `1.2.8`, and `1.2.99`, but not the versions `1.2.6`, `1.3.0`, +or `1.1.0`. + +The range `1.2.7 || >=1.2.9 <2.0.0` would match the versions `1.2.7`, +`1.2.9`, and `1.4.6`, but not the versions `1.2.8` or `2.0.0`. + +### Prerelease Tags + +If a version has a prerelease tag (for example, `1.2.3-alpha.3`) then +it will only be allowed to satisfy comparator sets if at least one +comparator with the same `[major, minor, patch]` tuple also has a +prerelease tag. + +For example, the range `>1.2.3-alpha.3` would be allowed to match the +version `1.2.3-alpha.7`, but it would *not* be satisfied by +`3.4.5-alpha.9`, even though `3.4.5-alpha.9` is technically "greater +than" `1.2.3-alpha.3` according to the SemVer sort rules. The version +range only accepts prerelease tags on the `1.2.3` version. The +version `3.4.5` *would* satisfy the range, because it does not have a +prerelease flag, and `3.4.5` is greater than `1.2.3-alpha.7`. + +The purpose for this behavior is twofold. First, prerelease versions +frequently are updated very quickly, and contain many breaking changes +that are (by the author's design) not yet fit for public consumption. +Therefore, by default, they are excluded from range matching +semantics. + +Second, a user who has opted into using a prerelease version has +clearly indicated the intent to use *that specific* set of +alpha/beta/rc versions. By including a prerelease tag in the range, +the user is indicating that they are aware of the risk. However, it +is still not appropriate to assume that they have opted into taking a +similar risk on the *next* set of prerelease versions. + +Note that this behavior can be suppressed (treating all prerelease +versions as if they were normal versions, for the purpose of range +matching) by setting the `includePrerelease` flag on the options +object to any +[functions](https://github.com/npm/node-semver#functions) that do +range matching. + +#### Prerelease Identifiers + +The method `.inc` takes an additional `identifier` string argument that +will append the value of the string as a prerelease identifier: + +```javascript +semver.inc('1.2.3', 'prerelease', 'beta') +// '1.2.4-beta.0' +``` + +command-line example: + +```bash +$ semver 1.2.3 -i prerelease --preid beta +1.2.4-beta.0 +``` + +Which then can be used to increment further: + +```bash +$ semver 1.2.4-beta.0 -i prerelease +1.2.4-beta.1 +``` + +### Advanced Range Syntax + +Advanced range syntax desugars to primitive comparators in +deterministic ways. + +Advanced ranges may be combined in the same way as primitive +comparators using white space or `||`. + +#### Hyphen Ranges `X.Y.Z - A.B.C` + +Specifies an inclusive set. + +* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4` + +If a partial version is provided as the first version in the inclusive +range, then the missing pieces are replaced with zeroes. + +* `1.2 - 2.3.4` := `>=1.2.0 <=2.3.4` + +If a partial version is provided as the second version in the +inclusive range, then all versions that start with the supplied parts +of the tuple are accepted, but nothing that would be greater than the +provided tuple parts. + +* `1.2.3 - 2.3` := `>=1.2.3 <2.4.0` +* `1.2.3 - 2` := `>=1.2.3 <3.0.0` + +#### X-Ranges `1.2.x` `1.X` `1.2.*` `*` + +Any of `X`, `x`, or `*` may be used to "stand in" for one of the +numeric values in the `[major, minor, patch]` tuple. + +* `*` := `>=0.0.0` (Any version satisfies) +* `1.x` := `>=1.0.0 <2.0.0` (Matching major version) +* `1.2.x` := `>=1.2.0 <1.3.0` (Matching major and minor versions) + +A partial version range is treated as an X-Range, so the special +character is in fact optional. + +* `""` (empty string) := `*` := `>=0.0.0` +* `1` := `1.x.x` := `>=1.0.0 <2.0.0` +* `1.2` := `1.2.x` := `>=1.2.0 <1.3.0` + +#### Tilde Ranges `~1.2.3` `~1.2` `~1` + +Allows patch-level changes if a minor version is specified on the +comparator. Allows minor-level changes if not. + +* `~1.2.3` := `>=1.2.3 <1.(2+1).0` := `>=1.2.3 <1.3.0` +* `~1.2` := `>=1.2.0 <1.(2+1).0` := `>=1.2.0 <1.3.0` (Same as `1.2.x`) +* `~1` := `>=1.0.0 <(1+1).0.0` := `>=1.0.0 <2.0.0` (Same as `1.x`) +* `~0.2.3` := `>=0.2.3 <0.(2+1).0` := `>=0.2.3 <0.3.0` +* `~0.2` := `>=0.2.0 <0.(2+1).0` := `>=0.2.0 <0.3.0` (Same as `0.2.x`) +* `~0` := `>=0.0.0 <(0+1).0.0` := `>=0.0.0 <1.0.0` (Same as `0.x`) +* `~1.2.3-beta.2` := `>=1.2.3-beta.2 <1.3.0` Note that prereleases in + the `1.2.3` version will be allowed, if they are greater than or + equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but + `1.2.4-beta.2` would not, because it is a prerelease of a + different `[major, minor, patch]` tuple. + +#### Caret Ranges `^1.2.3` `^0.2.5` `^0.0.4` + +Allows changes that do not modify the left-most non-zero digit in the +`[major, minor, patch]` tuple. In other words, this allows patch and +minor updates for versions `1.0.0` and above, patch updates for +versions `0.X >=0.1.0`, and *no* updates for versions `0.0.X`. + +Many authors treat a `0.x` version as if the `x` were the major +"breaking-change" indicator. + +Caret ranges are ideal when an author may make breaking changes +between `0.2.4` and `0.3.0` releases, which is a common practice. +However, it presumes that there will *not* be breaking changes between +`0.2.4` and `0.2.5`. It allows for changes that are presumed to be +additive (but non-breaking), according to commonly observed practices. + +* `^1.2.3` := `>=1.2.3 <2.0.0` +* `^0.2.3` := `>=0.2.3 <0.3.0` +* `^0.0.3` := `>=0.0.3 <0.0.4` +* `^1.2.3-beta.2` := `>=1.2.3-beta.2 <2.0.0` Note that prereleases in + the `1.2.3` version will be allowed, if they are greater than or + equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but + `1.2.4-beta.2` would not, because it is a prerelease of a + different `[major, minor, patch]` tuple. +* `^0.0.3-beta` := `>=0.0.3-beta <0.0.4` Note that prereleases in the + `0.0.3` version *only* will be allowed, if they are greater than or + equal to `beta`. So, `0.0.3-pr.2` would be allowed. + +When parsing caret ranges, a missing `patch` value desugars to the +number `0`, but will allow flexibility within that value, even if the +major and minor versions are both `0`. + +* `^1.2.x` := `>=1.2.0 <2.0.0` +* `^0.0.x` := `>=0.0.0 <0.1.0` +* `^0.0` := `>=0.0.0 <0.1.0` + +A missing `minor` and `patch` values will desugar to zero, but also +allow flexibility within those values, even if the major version is +zero. + +* `^1.x` := `>=1.0.0 <2.0.0` +* `^0.x` := `>=0.0.0 <1.0.0` + +### Range Grammar + +Putting all this together, here is a Backus-Naur grammar for ranges, +for the benefit of parser authors: + +```bnf +range-set ::= range ( logical-or range ) * +logical-or ::= ( ' ' ) * '||' ( ' ' ) * +range ::= hyphen | simple ( ' ' simple ) * | '' +hyphen ::= partial ' - ' partial +simple ::= primitive | partial | tilde | caret +primitive ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial +partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )? +xr ::= 'x' | 'X' | '*' | nr +nr ::= '0' | ['1'-'9'] ( ['0'-'9'] ) * +tilde ::= '~' partial +caret ::= '^' partial +qualifier ::= ( '-' pre )? ( '+' build )? +pre ::= parts +build ::= parts +parts ::= part ( '.' part ) * +part ::= nr | [-0-9A-Za-z]+ +``` + +## Functions + +All methods and classes take a final `options` object argument. All +options in this object are `false` by default. The options supported +are: + +- `loose` Be more forgiving about not-quite-valid semver strings. + (Any resulting output will always be 100% strict compliant, of + course.) For backwards compatibility reasons, if the `options` + argument is a boolean value instead of an object, it is interpreted + to be the `loose` param. +- `includePrerelease` Set to suppress the [default + behavior](https://github.com/npm/node-semver#prerelease-tags) of + excluding prerelease tagged versions from ranges unless they are + explicitly opted into. + +Strict-mode Comparators and Ranges will be strict about the SemVer +strings that they parse. + +* `valid(v)`: Return the parsed version, or null if it's not valid. +* `inc(v, release)`: Return the version incremented by the release + type (`major`, `premajor`, `minor`, `preminor`, `patch`, + `prepatch`, or `prerelease`), or null if it's not valid + * `premajor` in one call will bump the version up to the next major + version and down to a prerelease of that major version. + `preminor`, and `prepatch` work the same way. + * If called from a non-prerelease version, the `prerelease` will work the + same as `prepatch`. It increments the patch version, then makes a + prerelease. If the input version is already a prerelease it simply + increments it. +* `prerelease(v)`: Returns an array of prerelease components, or null + if none exist. Example: `prerelease('1.2.3-alpha.1') -> ['alpha', 1]` +* `major(v)`: Return the major version number. +* `minor(v)`: Return the minor version number. +* `patch(v)`: Return the patch version number. +* `intersects(r1, r2, loose)`: Return true if the two supplied ranges + or comparators intersect. +* `parse(v)`: Attempt to parse a string as a semantic version, returning either + a `SemVer` object or `null`. + +### Comparison + +* `gt(v1, v2)`: `v1 > v2` +* `gte(v1, v2)`: `v1 >= v2` +* `lt(v1, v2)`: `v1 < v2` +* `lte(v1, v2)`: `v1 <= v2` +* `eq(v1, v2)`: `v1 == v2` This is true if they're logically equivalent, + even if they're not the exact same string. You already know how to + compare strings. +* `neq(v1, v2)`: `v1 != v2` The opposite of `eq`. +* `cmp(v1, comparator, v2)`: Pass in a comparison string, and it'll call + the corresponding function above. `"==="` and `"!=="` do simple + string comparison, but are included for completeness. Throws if an + invalid comparison string is provided. +* `compare(v1, v2)`: Return `0` if `v1 == v2`, or `1` if `v1` is greater, or `-1` if + `v2` is greater. Sorts in ascending order if passed to `Array.sort()`. +* `rcompare(v1, v2)`: The reverse of compare. Sorts an array of versions + in descending order when passed to `Array.sort()`. +* `diff(v1, v2)`: Returns difference between two versions by the release type + (`major`, `premajor`, `minor`, `preminor`, `patch`, `prepatch`, or `prerelease`), + or null if the versions are the same. + +### Comparators + +* `intersects(comparator)`: Return true if the comparators intersect + +### Ranges + +* `validRange(range)`: Return the valid range or null if it's not valid +* `satisfies(version, range)`: Return true if the version satisfies the + range. +* `maxSatisfying(versions, range)`: Return the highest version in the list + that satisfies the range, or `null` if none of them do. +* `minSatisfying(versions, range)`: Return the lowest version in the list + that satisfies the range, or `null` if none of them do. +* `minVersion(range)`: Return the lowest version that can possibly match + the given range. +* `gtr(version, range)`: Return `true` if version is greater than all the + versions possible in the range. +* `ltr(version, range)`: Return `true` if version is less than all the + versions possible in the range. +* `outside(version, range, hilo)`: Return true if the version is outside + the bounds of the range in either the high or low direction. The + `hilo` argument must be either the string `'>'` or `'<'`. (This is + the function called by `gtr` and `ltr`.) +* `intersects(range)`: Return true if any of the ranges comparators intersect + +Note that, since ranges may be non-contiguous, a version might not be +greater than a range, less than a range, *or* satisfy a range! For +example, the range `1.2 <1.2.9 || >2.0.0` would have a hole from `1.2.9` +until `2.0.0`, so the version `1.2.10` would not be greater than the +range (because `2.0.1` satisfies, which is higher), nor less than the +range (since `1.2.8` satisfies, which is lower), and it also does not +satisfy the range. + +If you want to know if a version satisfies or does not satisfy a +range, use the `satisfies(version, range)` function. + +### Coercion + +* `coerce(version)`: Coerces a string to semver if possible + +This aims to provide a very forgiving translation of a non-semver string to +semver. It looks for the first digit in a string, and consumes all +remaining characters which satisfy at least a partial semver (e.g., `1`, +`1.2`, `1.2.3`) up to the max permitted length (256 characters). Longer +versions are simply truncated (`4.6.3.9.2-alpha2` becomes `4.6.3`). All +surrounding text is simply ignored (`v3.4 replaces v3.3.1` becomes +`3.4.0`). Only text which lacks digits will fail coercion (`version one` +is not valid). The maximum length for any semver component considered for +coercion is 16 characters; longer components will be ignored +(`10000000000000000.4.7.4` becomes `4.7.4`). The maximum value for any +semver component is `Number.MAX_SAFE_INTEGER || (2**53 - 1)`; higher value +components are invalid (`9999999999999999.4.7.4` is likely invalid). diff --git a/homework8/project_express/node_modules/semver/bin/semver b/homework8/project_express/node_modules/semver/bin/semver new file mode 100644 index 0000000..801e77f --- /dev/null +++ b/homework8/project_express/node_modules/semver/bin/semver @@ -0,0 +1,160 @@ +#!/usr/bin/env node +// Standalone semver comparison program. +// Exits successfully and prints matching version(s) if +// any supplied version is valid and passes all tests. + +var argv = process.argv.slice(2) + +var versions = [] + +var range = [] + +var inc = null + +var version = require('../package.json').version + +var loose = false + +var includePrerelease = false + +var coerce = false + +var identifier + +var semver = require('../semver') + +var reverse = false + +var options = {} + +main() + +function main () { + if (!argv.length) return help() + while (argv.length) { + var a = argv.shift() + var indexOfEqualSign = a.indexOf('=') + if (indexOfEqualSign !== -1) { + a = a.slice(0, indexOfEqualSign) + argv.unshift(a.slice(indexOfEqualSign + 1)) + } + switch (a) { + case '-rv': case '-rev': case '--rev': case '--reverse': + reverse = true + break + case '-l': case '--loose': + loose = true + break + case '-p': case '--include-prerelease': + includePrerelease = true + break + case '-v': case '--version': + versions.push(argv.shift()) + break + case '-i': case '--inc': case '--increment': + switch (argv[0]) { + case 'major': case 'minor': case 'patch': case 'prerelease': + case 'premajor': case 'preminor': case 'prepatch': + inc = argv.shift() + break + default: + inc = 'patch' + break + } + break + case '--preid': + identifier = argv.shift() + break + case '-r': case '--range': + range.push(argv.shift()) + break + case '-c': case '--coerce': + coerce = true + break + case '-h': case '--help': case '-?': + return help() + default: + versions.push(a) + break + } + } + + var options = { loose: loose, includePrerelease: includePrerelease } + + versions = versions.map(function (v) { + return coerce ? (semver.coerce(v) || { version: v }).version : v + }).filter(function (v) { + return semver.valid(v) + }) + if (!versions.length) return fail() + if (inc && (versions.length !== 1 || range.length)) { return failInc() } + + for (var i = 0, l = range.length; i < l; i++) { + versions = versions.filter(function (v) { + return semver.satisfies(v, range[i], options) + }) + if (!versions.length) return fail() + } + return success(versions) +} + +function failInc () { + console.error('--inc can only be used on a single version with no range') + fail() +} + +function fail () { process.exit(1) } + +function success () { + var compare = reverse ? 'rcompare' : 'compare' + versions.sort(function (a, b) { + return semver[compare](a, b, options) + }).map(function (v) { + return semver.clean(v, options) + }).map(function (v) { + return inc ? semver.inc(v, inc, options, identifier) : v + }).forEach(function (v, i, _) { console.log(v) }) +} + +function help () { + console.log(['SemVer ' + version, + '', + 'A JavaScript implementation of the https://semver.org/ specification', + 'Copyright Isaac Z. Schlueter', + '', + 'Usage: semver [options] [ [...]]', + 'Prints valid versions sorted by SemVer precedence', + '', + 'Options:', + '-r --range ', + ' Print versions that match the specified range.', + '', + '-i --increment []', + ' Increment a version by the specified level. Level can', + ' be one of: major, minor, patch, premajor, preminor,', + " prepatch, or prerelease. Default level is 'patch'.", + ' Only one version may be specified.', + '', + '--preid ', + ' Identifier to be used to prefix premajor, preminor,', + ' prepatch or prerelease version increments.', + '', + '-l --loose', + ' Interpret versions and ranges loosely', + '', + '-p --include-prerelease', + ' Always include prerelease versions in range matching', + '', + '-c --coerce', + ' Coerce a string into SemVer if possible', + ' (does not imply --loose)', + '', + 'Program exits successfully if any valid version satisfies', + 'all supplied ranges, and prints all satisfying versions.', + '', + 'If no satisfying versions are found, then exits failure.', + '', + 'Versions are printed in ascending order, so supplying', + 'multiple versions to the utility will just sort them.' + ].join('\n')) +} diff --git a/homework8/project_express/node_modules/semver/package.json b/homework8/project_express/node_modules/semver/package.json new file mode 100644 index 0000000..69d2db1 --- /dev/null +++ b/homework8/project_express/node_modules/semver/package.json @@ -0,0 +1,28 @@ +{ + "name": "semver", + "version": "5.7.1", + "description": "The semantic version parser used by npm.", + "main": "semver.js", + "scripts": { + "test": "tap", + "preversion": "npm test", + "postversion": "npm publish", + "postpublish": "git push origin --all; git push origin --tags" + }, + "devDependencies": { + "tap": "^13.0.0-rc.18" + }, + "license": "ISC", + "repository": "https://github.com/npm/node-semver", + "bin": { + "semver": "./bin/semver" + }, + "files": [ + "bin", + "range.bnf", + "semver.js" + ], + "tap": { + "check-coverage": true + } +} diff --git a/homework8/project_express/node_modules/semver/range.bnf b/homework8/project_express/node_modules/semver/range.bnf new file mode 100644 index 0000000..d4c6ae0 --- /dev/null +++ b/homework8/project_express/node_modules/semver/range.bnf @@ -0,0 +1,16 @@ +range-set ::= range ( logical-or range ) * +logical-or ::= ( ' ' ) * '||' ( ' ' ) * +range ::= hyphen | simple ( ' ' simple ) * | '' +hyphen ::= partial ' - ' partial +simple ::= primitive | partial | tilde | caret +primitive ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial +partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )? +xr ::= 'x' | 'X' | '*' | nr +nr ::= '0' | [1-9] ( [0-9] ) * +tilde ::= '~' partial +caret ::= '^' partial +qualifier ::= ( '-' pre )? ( '+' build )? +pre ::= parts +build ::= parts +parts ::= part ( '.' part ) * +part ::= nr | [-0-9A-Za-z]+ diff --git a/homework8/project_express/node_modules/semver/semver.js b/homework8/project_express/node_modules/semver/semver.js new file mode 100644 index 0000000..d315d5d --- /dev/null +++ b/homework8/project_express/node_modules/semver/semver.js @@ -0,0 +1,1483 @@ +exports = module.exports = SemVer + +var debug +/* istanbul ignore next */ +if (typeof process === 'object' && + process.env && + process.env.NODE_DEBUG && + /\bsemver\b/i.test(process.env.NODE_DEBUG)) { + debug = function () { + var args = Array.prototype.slice.call(arguments, 0) + args.unshift('SEMVER') + console.log.apply(console, args) + } +} else { + debug = function () {} +} + +// Note: this is the semver.org version of the spec that it implements +// Not necessarily the package version of this code. +exports.SEMVER_SPEC_VERSION = '2.0.0' + +var MAX_LENGTH = 256 +var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || + /* istanbul ignore next */ 9007199254740991 + +// Max safe segment length for coercion. +var MAX_SAFE_COMPONENT_LENGTH = 16 + +// The actual regexps go on exports.re +var re = exports.re = [] +var src = exports.src = [] +var R = 0 + +// The following Regular Expressions can be used for tokenizing, +// validating, and parsing SemVer version strings. + +// ## Numeric Identifier +// A single `0`, or a non-zero digit followed by zero or more digits. + +var NUMERICIDENTIFIER = R++ +src[NUMERICIDENTIFIER] = '0|[1-9]\\d*' +var NUMERICIDENTIFIERLOOSE = R++ +src[NUMERICIDENTIFIERLOOSE] = '[0-9]+' + +// ## Non-numeric Identifier +// Zero or more digits, followed by a letter or hyphen, and then zero or +// more letters, digits, or hyphens. + +var NONNUMERICIDENTIFIER = R++ +src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*' + +// ## Main Version +// Three dot-separated numeric identifiers. + +var MAINVERSION = R++ +src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + + '(' + src[NUMERICIDENTIFIER] + ')\\.' + + '(' + src[NUMERICIDENTIFIER] + ')' + +var MAINVERSIONLOOSE = R++ +src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + + '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + + '(' + src[NUMERICIDENTIFIERLOOSE] + ')' + +// ## Pre-release Version Identifier +// A numeric identifier, or a non-numeric identifier. + +var PRERELEASEIDENTIFIER = R++ +src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + + '|' + src[NONNUMERICIDENTIFIER] + ')' + +var PRERELEASEIDENTIFIERLOOSE = R++ +src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + + '|' + src[NONNUMERICIDENTIFIER] + ')' + +// ## Pre-release Version +// Hyphen, followed by one or more dot-separated pre-release version +// identifiers. + +var PRERELEASE = R++ +src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + + '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))' + +var PRERELEASELOOSE = R++ +src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + + '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))' + +// ## Build Metadata Identifier +// Any combination of digits, letters, or hyphens. + +var BUILDIDENTIFIER = R++ +src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+' + +// ## Build Metadata +// Plus sign, followed by one or more period-separated build metadata +// identifiers. + +var BUILD = R++ +src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + + '(?:\\.' + src[BUILDIDENTIFIER] + ')*))' + +// ## Full Version String +// A main version, followed optionally by a pre-release version and +// build metadata. + +// Note that the only major, minor, patch, and pre-release sections of +// the version string are capturing groups. The build metadata is not a +// capturing group, because it should not ever be used in version +// comparison. + +var FULL = R++ +var FULLPLAIN = 'v?' + src[MAINVERSION] + + src[PRERELEASE] + '?' + + src[BUILD] + '?' + +src[FULL] = '^' + FULLPLAIN + '$' + +// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. +// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty +// common in the npm registry. +var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + + src[PRERELEASELOOSE] + '?' + + src[BUILD] + '?' + +var LOOSE = R++ +src[LOOSE] = '^' + LOOSEPLAIN + '$' + +var GTLT = R++ +src[GTLT] = '((?:<|>)?=?)' + +// Something like "2.*" or "1.2.x". +// Note that "x.x" is a valid xRange identifer, meaning "any version" +// Only the first item is strictly required. +var XRANGEIDENTIFIERLOOSE = R++ +src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*' +var XRANGEIDENTIFIER = R++ +src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*' + +var XRANGEPLAIN = R++ +src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + + '(?:' + src[PRERELEASE] + ')?' + + src[BUILD] + '?' + + ')?)?' + +var XRANGEPLAINLOOSE = R++ +src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:' + src[PRERELEASELOOSE] + ')?' + + src[BUILD] + '?' + + ')?)?' + +var XRANGE = R++ +src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$' +var XRANGELOOSE = R++ +src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$' + +// Coercion. +// Extract anything that could conceivably be a part of a valid semver +var COERCE = R++ +src[COERCE] = '(?:^|[^\\d])' + + '(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '})' + + '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + + '(?:\\.(\\d{1,' + MAX_SAFE_COMPONENT_LENGTH + '}))?' + + '(?:$|[^\\d])' + +// Tilde ranges. +// Meaning is "reasonably at or greater than" +var LONETILDE = R++ +src[LONETILDE] = '(?:~>?)' + +var TILDETRIM = R++ +src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+' +re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g') +var tildeTrimReplace = '$1~' + +var TILDE = R++ +src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$' +var TILDELOOSE = R++ +src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$' + +// Caret ranges. +// Meaning is "at least and backwards compatible with" +var LONECARET = R++ +src[LONECARET] = '(?:\\^)' + +var CARETTRIM = R++ +src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+' +re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g') +var caretTrimReplace = '$1^' + +var CARET = R++ +src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$' +var CARETLOOSE = R++ +src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$' + +// A simple gt/lt/eq thing, or just "" to indicate "any version" +var COMPARATORLOOSE = R++ +src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$' +var COMPARATOR = R++ +src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$' + +// An expression to strip any whitespace between the gtlt and the thing +// it modifies, so that `> 1.2.3` ==> `>1.2.3` +var COMPARATORTRIM = R++ +src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + + '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')' + +// this one has to use the /g flag +re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g') +var comparatorTrimReplace = '$1$2$3' + +// Something like `1.2.3 - 1.2.4` +// Note that these all use the loose form, because they'll be +// checked against either the strict or loose comparator form +// later. +var HYPHENRANGE = R++ +src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + + '\\s+-\\s+' + + '(' + src[XRANGEPLAIN] + ')' + + '\\s*$' + +var HYPHENRANGELOOSE = R++ +src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + + '\\s+-\\s+' + + '(' + src[XRANGEPLAINLOOSE] + ')' + + '\\s*$' + +// Star ranges basically just allow anything at all. +var STAR = R++ +src[STAR] = '(<|>)?=?\\s*\\*' + +// Compile to actual regexp objects. +// All are flag-free, unless they were created above with a flag. +for (var i = 0; i < R; i++) { + debug(i, src[i]) + if (!re[i]) { + re[i] = new RegExp(src[i]) + } +} + +exports.parse = parse +function parse (version, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (version instanceof SemVer) { + return version + } + + if (typeof version !== 'string') { + return null + } + + if (version.length > MAX_LENGTH) { + return null + } + + var r = options.loose ? re[LOOSE] : re[FULL] + if (!r.test(version)) { + return null + } + + try { + return new SemVer(version, options) + } catch (er) { + return null + } +} + +exports.valid = valid +function valid (version, options) { + var v = parse(version, options) + return v ? v.version : null +} + +exports.clean = clean +function clean (version, options) { + var s = parse(version.trim().replace(/^[=v]+/, ''), options) + return s ? s.version : null +} + +exports.SemVer = SemVer + +function SemVer (version, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + if (version instanceof SemVer) { + if (version.loose === options.loose) { + return version + } else { + version = version.version + } + } else if (typeof version !== 'string') { + throw new TypeError('Invalid Version: ' + version) + } + + if (version.length > MAX_LENGTH) { + throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') + } + + if (!(this instanceof SemVer)) { + return new SemVer(version, options) + } + + debug('SemVer', version, options) + this.options = options + this.loose = !!options.loose + + var m = version.trim().match(options.loose ? re[LOOSE] : re[FULL]) + + if (!m) { + throw new TypeError('Invalid Version: ' + version) + } + + this.raw = version + + // these are actually numbers + this.major = +m[1] + this.minor = +m[2] + this.patch = +m[3] + + if (this.major > MAX_SAFE_INTEGER || this.major < 0) { + throw new TypeError('Invalid major version') + } + + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { + throw new TypeError('Invalid minor version') + } + + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { + throw new TypeError('Invalid patch version') + } + + // numberify any prerelease numeric ids + if (!m[4]) { + this.prerelease = [] + } else { + this.prerelease = m[4].split('.').map(function (id) { + if (/^[0-9]+$/.test(id)) { + var num = +id + if (num >= 0 && num < MAX_SAFE_INTEGER) { + return num + } + } + return id + }) + } + + this.build = m[5] ? m[5].split('.') : [] + this.format() +} + +SemVer.prototype.format = function () { + this.version = this.major + '.' + this.minor + '.' + this.patch + if (this.prerelease.length) { + this.version += '-' + this.prerelease.join('.') + } + return this.version +} + +SemVer.prototype.toString = function () { + return this.version +} + +SemVer.prototype.compare = function (other) { + debug('SemVer.compare', this.version, this.options, other) + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + return this.compareMain(other) || this.comparePre(other) +} + +SemVer.prototype.compareMain = function (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + return compareIdentifiers(this.major, other.major) || + compareIdentifiers(this.minor, other.minor) || + compareIdentifiers(this.patch, other.patch) +} + +SemVer.prototype.comparePre = function (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + // NOT having a prerelease is > having one + if (this.prerelease.length && !other.prerelease.length) { + return -1 + } else if (!this.prerelease.length && other.prerelease.length) { + return 1 + } else if (!this.prerelease.length && !other.prerelease.length) { + return 0 + } + + var i = 0 + do { + var a = this.prerelease[i] + var b = other.prerelease[i] + debug('prerelease compare', i, a, b) + if (a === undefined && b === undefined) { + return 0 + } else if (b === undefined) { + return 1 + } else if (a === undefined) { + return -1 + } else if (a === b) { + continue + } else { + return compareIdentifiers(a, b) + } + } while (++i) +} + +// preminor will bump the version up to the next minor release, and immediately +// down to pre-release. premajor and prepatch work the same way. +SemVer.prototype.inc = function (release, identifier) { + switch (release) { + case 'premajor': + this.prerelease.length = 0 + this.patch = 0 + this.minor = 0 + this.major++ + this.inc('pre', identifier) + break + case 'preminor': + this.prerelease.length = 0 + this.patch = 0 + this.minor++ + this.inc('pre', identifier) + break + case 'prepatch': + // If this is already a prerelease, it will bump to the next version + // drop any prereleases that might already exist, since they are not + // relevant at this point. + this.prerelease.length = 0 + this.inc('patch', identifier) + this.inc('pre', identifier) + break + // If the input is a non-prerelease version, this acts the same as + // prepatch. + case 'prerelease': + if (this.prerelease.length === 0) { + this.inc('patch', identifier) + } + this.inc('pre', identifier) + break + + case 'major': + // If this is a pre-major version, bump up to the same major version. + // Otherwise increment major. + // 1.0.0-5 bumps to 1.0.0 + // 1.1.0 bumps to 2.0.0 + if (this.minor !== 0 || + this.patch !== 0 || + this.prerelease.length === 0) { + this.major++ + } + this.minor = 0 + this.patch = 0 + this.prerelease = [] + break + case 'minor': + // If this is a pre-minor version, bump up to the same minor version. + // Otherwise increment minor. + // 1.2.0-5 bumps to 1.2.0 + // 1.2.1 bumps to 1.3.0 + if (this.patch !== 0 || this.prerelease.length === 0) { + this.minor++ + } + this.patch = 0 + this.prerelease = [] + break + case 'patch': + // If this is not a pre-release version, it will increment the patch. + // If it is a pre-release it will bump up to the same patch version. + // 1.2.0-5 patches to 1.2.0 + // 1.2.0 patches to 1.2.1 + if (this.prerelease.length === 0) { + this.patch++ + } + this.prerelease = [] + break + // This probably shouldn't be used publicly. + // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. + case 'pre': + if (this.prerelease.length === 0) { + this.prerelease = [0] + } else { + var i = this.prerelease.length + while (--i >= 0) { + if (typeof this.prerelease[i] === 'number') { + this.prerelease[i]++ + i = -2 + } + } + if (i === -1) { + // didn't increment anything + this.prerelease.push(0) + } + } + if (identifier) { + // 1.2.0-beta.1 bumps to 1.2.0-beta.2, + // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 + if (this.prerelease[0] === identifier) { + if (isNaN(this.prerelease[1])) { + this.prerelease = [identifier, 0] + } + } else { + this.prerelease = [identifier, 0] + } + } + break + + default: + throw new Error('invalid increment argument: ' + release) + } + this.format() + this.raw = this.version + return this +} + +exports.inc = inc +function inc (version, release, loose, identifier) { + if (typeof (loose) === 'string') { + identifier = loose + loose = undefined + } + + try { + return new SemVer(version, loose).inc(release, identifier).version + } catch (er) { + return null + } +} + +exports.diff = diff +function diff (version1, version2) { + if (eq(version1, version2)) { + return null + } else { + var v1 = parse(version1) + var v2 = parse(version2) + var prefix = '' + if (v1.prerelease.length || v2.prerelease.length) { + prefix = 'pre' + var defaultResult = 'prerelease' + } + for (var key in v1) { + if (key === 'major' || key === 'minor' || key === 'patch') { + if (v1[key] !== v2[key]) { + return prefix + key + } + } + } + return defaultResult // may be undefined + } +} + +exports.compareIdentifiers = compareIdentifiers + +var numeric = /^[0-9]+$/ +function compareIdentifiers (a, b) { + var anum = numeric.test(a) + var bnum = numeric.test(b) + + if (anum && bnum) { + a = +a + b = +b + } + + return a === b ? 0 + : (anum && !bnum) ? -1 + : (bnum && !anum) ? 1 + : a < b ? -1 + : 1 +} + +exports.rcompareIdentifiers = rcompareIdentifiers +function rcompareIdentifiers (a, b) { + return compareIdentifiers(b, a) +} + +exports.major = major +function major (a, loose) { + return new SemVer(a, loose).major +} + +exports.minor = minor +function minor (a, loose) { + return new SemVer(a, loose).minor +} + +exports.patch = patch +function patch (a, loose) { + return new SemVer(a, loose).patch +} + +exports.compare = compare +function compare (a, b, loose) { + return new SemVer(a, loose).compare(new SemVer(b, loose)) +} + +exports.compareLoose = compareLoose +function compareLoose (a, b) { + return compare(a, b, true) +} + +exports.rcompare = rcompare +function rcompare (a, b, loose) { + return compare(b, a, loose) +} + +exports.sort = sort +function sort (list, loose) { + return list.sort(function (a, b) { + return exports.compare(a, b, loose) + }) +} + +exports.rsort = rsort +function rsort (list, loose) { + return list.sort(function (a, b) { + return exports.rcompare(a, b, loose) + }) +} + +exports.gt = gt +function gt (a, b, loose) { + return compare(a, b, loose) > 0 +} + +exports.lt = lt +function lt (a, b, loose) { + return compare(a, b, loose) < 0 +} + +exports.eq = eq +function eq (a, b, loose) { + return compare(a, b, loose) === 0 +} + +exports.neq = neq +function neq (a, b, loose) { + return compare(a, b, loose) !== 0 +} + +exports.gte = gte +function gte (a, b, loose) { + return compare(a, b, loose) >= 0 +} + +exports.lte = lte +function lte (a, b, loose) { + return compare(a, b, loose) <= 0 +} + +exports.cmp = cmp +function cmp (a, op, b, loose) { + switch (op) { + case '===': + if (typeof a === 'object') + a = a.version + if (typeof b === 'object') + b = b.version + return a === b + + case '!==': + if (typeof a === 'object') + a = a.version + if (typeof b === 'object') + b = b.version + return a !== b + + case '': + case '=': + case '==': + return eq(a, b, loose) + + case '!=': + return neq(a, b, loose) + + case '>': + return gt(a, b, loose) + + case '>=': + return gte(a, b, loose) + + case '<': + return lt(a, b, loose) + + case '<=': + return lte(a, b, loose) + + default: + throw new TypeError('Invalid operator: ' + op) + } +} + +exports.Comparator = Comparator +function Comparator (comp, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (comp instanceof Comparator) { + if (comp.loose === !!options.loose) { + return comp + } else { + comp = comp.value + } + } + + if (!(this instanceof Comparator)) { + return new Comparator(comp, options) + } + + debug('comparator', comp, options) + this.options = options + this.loose = !!options.loose + this.parse(comp) + + if (this.semver === ANY) { + this.value = '' + } else { + this.value = this.operator + this.semver.version + } + + debug('comp', this) +} + +var ANY = {} +Comparator.prototype.parse = function (comp) { + var r = this.options.loose ? re[COMPARATORLOOSE] : re[COMPARATOR] + var m = comp.match(r) + + if (!m) { + throw new TypeError('Invalid comparator: ' + comp) + } + + this.operator = m[1] + if (this.operator === '=') { + this.operator = '' + } + + // if it literally is just '>' or '' then allow anything. + if (!m[2]) { + this.semver = ANY + } else { + this.semver = new SemVer(m[2], this.options.loose) + } +} + +Comparator.prototype.toString = function () { + return this.value +} + +Comparator.prototype.test = function (version) { + debug('Comparator.test', version, this.options.loose) + + if (this.semver === ANY) { + return true + } + + if (typeof version === 'string') { + version = new SemVer(version, this.options) + } + + return cmp(version, this.operator, this.semver, this.options) +} + +Comparator.prototype.intersects = function (comp, options) { + if (!(comp instanceof Comparator)) { + throw new TypeError('a Comparator is required') + } + + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + var rangeTmp + + if (this.operator === '') { + rangeTmp = new Range(comp.value, options) + return satisfies(this.value, rangeTmp, options) + } else if (comp.operator === '') { + rangeTmp = new Range(this.value, options) + return satisfies(comp.semver, rangeTmp, options) + } + + var sameDirectionIncreasing = + (this.operator === '>=' || this.operator === '>') && + (comp.operator === '>=' || comp.operator === '>') + var sameDirectionDecreasing = + (this.operator === '<=' || this.operator === '<') && + (comp.operator === '<=' || comp.operator === '<') + var sameSemVer = this.semver.version === comp.semver.version + var differentDirectionsInclusive = + (this.operator === '>=' || this.operator === '<=') && + (comp.operator === '>=' || comp.operator === '<=') + var oppositeDirectionsLessThan = + cmp(this.semver, '<', comp.semver, options) && + ((this.operator === '>=' || this.operator === '>') && + (comp.operator === '<=' || comp.operator === '<')) + var oppositeDirectionsGreaterThan = + cmp(this.semver, '>', comp.semver, options) && + ((this.operator === '<=' || this.operator === '<') && + (comp.operator === '>=' || comp.operator === '>')) + + return sameDirectionIncreasing || sameDirectionDecreasing || + (sameSemVer && differentDirectionsInclusive) || + oppositeDirectionsLessThan || oppositeDirectionsGreaterThan +} + +exports.Range = Range +function Range (range, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (range instanceof Range) { + if (range.loose === !!options.loose && + range.includePrerelease === !!options.includePrerelease) { + return range + } else { + return new Range(range.raw, options) + } + } + + if (range instanceof Comparator) { + return new Range(range.value, options) + } + + if (!(this instanceof Range)) { + return new Range(range, options) + } + + this.options = options + this.loose = !!options.loose + this.includePrerelease = !!options.includePrerelease + + // First, split based on boolean or || + this.raw = range + this.set = range.split(/\s*\|\|\s*/).map(function (range) { + return this.parseRange(range.trim()) + }, this).filter(function (c) { + // throw out any that are not relevant for whatever reason + return c.length + }) + + if (!this.set.length) { + throw new TypeError('Invalid SemVer Range: ' + range) + } + + this.format() +} + +Range.prototype.format = function () { + this.range = this.set.map(function (comps) { + return comps.join(' ').trim() + }).join('||').trim() + return this.range +} + +Range.prototype.toString = function () { + return this.range +} + +Range.prototype.parseRange = function (range) { + var loose = this.options.loose + range = range.trim() + // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` + var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE] + range = range.replace(hr, hyphenReplace) + debug('hyphen replace', range) + // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` + range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace) + debug('comparator trim', range, re[COMPARATORTRIM]) + + // `~ 1.2.3` => `~1.2.3` + range = range.replace(re[TILDETRIM], tildeTrimReplace) + + // `^ 1.2.3` => `^1.2.3` + range = range.replace(re[CARETTRIM], caretTrimReplace) + + // normalize spaces + range = range.split(/\s+/).join(' ') + + // At this point, the range is completely trimmed and + // ready to be split into comparators. + + var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR] + var set = range.split(' ').map(function (comp) { + return parseComparator(comp, this.options) + }, this).join(' ').split(/\s+/) + if (this.options.loose) { + // in loose mode, throw out any that are not valid comparators + set = set.filter(function (comp) { + return !!comp.match(compRe) + }) + } + set = set.map(function (comp) { + return new Comparator(comp, this.options) + }, this) + + return set +} + +Range.prototype.intersects = function (range, options) { + if (!(range instanceof Range)) { + throw new TypeError('a Range is required') + } + + return this.set.some(function (thisComparators) { + return thisComparators.every(function (thisComparator) { + return range.set.some(function (rangeComparators) { + return rangeComparators.every(function (rangeComparator) { + return thisComparator.intersects(rangeComparator, options) + }) + }) + }) + }) +} + +// Mostly just for testing and legacy API reasons +exports.toComparators = toComparators +function toComparators (range, options) { + return new Range(range, options).set.map(function (comp) { + return comp.map(function (c) { + return c.value + }).join(' ').trim().split(' ') + }) +} + +// comprised of xranges, tildes, stars, and gtlt's at this point. +// already replaced the hyphen ranges +// turn into a set of JUST comparators. +function parseComparator (comp, options) { + debug('comp', comp, options) + comp = replaceCarets(comp, options) + debug('caret', comp) + comp = replaceTildes(comp, options) + debug('tildes', comp) + comp = replaceXRanges(comp, options) + debug('xrange', comp) + comp = replaceStars(comp, options) + debug('stars', comp) + return comp +} + +function isX (id) { + return !id || id.toLowerCase() === 'x' || id === '*' +} + +// ~, ~> --> * (any, kinda silly) +// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 +// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 +// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 +// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 +// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 +function replaceTildes (comp, options) { + return comp.trim().split(/\s+/).map(function (comp) { + return replaceTilde(comp, options) + }).join(' ') +} + +function replaceTilde (comp, options) { + var r = options.loose ? re[TILDELOOSE] : re[TILDE] + return comp.replace(r, function (_, M, m, p, pr) { + debug('tilde', comp, _, M, m, p, pr) + var ret + + if (isX(M)) { + ret = '' + } else if (isX(m)) { + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' + } else if (isX(p)) { + // ~1.2 == >=1.2.0 <1.3.0 + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' + } else if (pr) { + debug('replaceTilde pr', pr) + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + M + '.' + (+m + 1) + '.0' + } else { + // ~1.2.3 == >=1.2.3 <1.3.0 + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + (+m + 1) + '.0' + } + + debug('tilde return', ret) + return ret + }) +} + +// ^ --> * (any, kinda silly) +// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 +// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 +// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 +// ^1.2.3 --> >=1.2.3 <2.0.0 +// ^1.2.0 --> >=1.2.0 <2.0.0 +function replaceCarets (comp, options) { + return comp.trim().split(/\s+/).map(function (comp) { + return replaceCaret(comp, options) + }).join(' ') +} + +function replaceCaret (comp, options) { + debug('caret', comp, options) + var r = options.loose ? re[CARETLOOSE] : re[CARET] + return comp.replace(r, function (_, M, m, p, pr) { + debug('caret', comp, _, M, m, p, pr) + var ret + + if (isX(M)) { + ret = '' + } else if (isX(m)) { + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' + } else if (isX(p)) { + if (M === '0') { + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' + } else { + ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0' + } + } else if (pr) { + debug('replaceCaret pr', pr) + if (M === '0') { + if (m === '0') { + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + M + '.' + m + '.' + (+p + 1) + } else { + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + M + '.' + (+m + 1) + '.0' + } + } else { + ret = '>=' + M + '.' + m + '.' + p + '-' + pr + + ' <' + (+M + 1) + '.0.0' + } + } else { + debug('no pr') + if (M === '0') { + if (m === '0') { + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + m + '.' + (+p + 1) + } else { + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + (+m + 1) + '.0' + } + } else { + ret = '>=' + M + '.' + m + '.' + p + + ' <' + (+M + 1) + '.0.0' + } + } + + debug('caret return', ret) + return ret + }) +} + +function replaceXRanges (comp, options) { + debug('replaceXRanges', comp, options) + return comp.split(/\s+/).map(function (comp) { + return replaceXRange(comp, options) + }).join(' ') +} + +function replaceXRange (comp, options) { + comp = comp.trim() + var r = options.loose ? re[XRANGELOOSE] : re[XRANGE] + return comp.replace(r, function (ret, gtlt, M, m, p, pr) { + debug('xRange', comp, ret, gtlt, M, m, p, pr) + var xM = isX(M) + var xm = xM || isX(m) + var xp = xm || isX(p) + var anyX = xp + + if (gtlt === '=' && anyX) { + gtlt = '' + } + + if (xM) { + if (gtlt === '>' || gtlt === '<') { + // nothing is allowed + ret = '<0.0.0' + } else { + // nothing is forbidden + ret = '*' + } + } else if (gtlt && anyX) { + // we know patch is an x, because we have any x at all. + // replace X with 0 + if (xm) { + m = 0 + } + p = 0 + + if (gtlt === '>') { + // >1 => >=2.0.0 + // >1.2 => >=1.3.0 + // >1.2.3 => >= 1.2.4 + gtlt = '>=' + if (xm) { + M = +M + 1 + m = 0 + p = 0 + } else { + m = +m + 1 + p = 0 + } + } else if (gtlt === '<=') { + // <=0.7.x is actually <0.8.0, since any 0.7.x should + // pass. Similarly, <=7.x is actually <8.0.0, etc. + gtlt = '<' + if (xm) { + M = +M + 1 + } else { + m = +m + 1 + } + } + + ret = gtlt + M + '.' + m + '.' + p + } else if (xm) { + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0' + } else if (xp) { + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0' + } + + debug('xRange return', ret) + + return ret + }) +} + +// Because * is AND-ed with everything else in the comparator, +// and '' means "any version", just remove the *s entirely. +function replaceStars (comp, options) { + debug('replaceStars', comp, options) + // Looseness is ignored here. star is always as loose as it gets! + return comp.trim().replace(re[STAR], '') +} + +// This function is passed to string.replace(re[HYPHENRANGE]) +// M, m, patch, prerelease, build +// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 +// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do +// 1.2 - 3.4 => >=1.2.0 <3.5.0 +function hyphenReplace ($0, + from, fM, fm, fp, fpr, fb, + to, tM, tm, tp, tpr, tb) { + if (isX(fM)) { + from = '' + } else if (isX(fm)) { + from = '>=' + fM + '.0.0' + } else if (isX(fp)) { + from = '>=' + fM + '.' + fm + '.0' + } else { + from = '>=' + from + } + + if (isX(tM)) { + to = '' + } else if (isX(tm)) { + to = '<' + (+tM + 1) + '.0.0' + } else if (isX(tp)) { + to = '<' + tM + '.' + (+tm + 1) + '.0' + } else if (tpr) { + to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr + } else { + to = '<=' + to + } + + return (from + ' ' + to).trim() +} + +// if ANY of the sets match ALL of its comparators, then pass +Range.prototype.test = function (version) { + if (!version) { + return false + } + + if (typeof version === 'string') { + version = new SemVer(version, this.options) + } + + for (var i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version, this.options)) { + return true + } + } + return false +} + +function testSet (set, version, options) { + for (var i = 0; i < set.length; i++) { + if (!set[i].test(version)) { + return false + } + } + + if (version.prerelease.length && !options.includePrerelease) { + // Find the set of versions that are allowed to have prereleases + // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 + // That should allow `1.2.3-pr.2` to pass. + // However, `1.2.4-alpha.notready` should NOT be allowed, + // even though it's within the range set by the comparators. + for (i = 0; i < set.length; i++) { + debug(set[i].semver) + if (set[i].semver === ANY) { + continue + } + + if (set[i].semver.prerelease.length > 0) { + var allowed = set[i].semver + if (allowed.major === version.major && + allowed.minor === version.minor && + allowed.patch === version.patch) { + return true + } + } + } + + // Version has a -pre, but it's not one of the ones we like. + return false + } + + return true +} + +exports.satisfies = satisfies +function satisfies (version, range, options) { + try { + range = new Range(range, options) + } catch (er) { + return false + } + return range.test(version) +} + +exports.maxSatisfying = maxSatisfying +function maxSatisfying (versions, range, options) { + var max = null + var maxSV = null + try { + var rangeObj = new Range(range, options) + } catch (er) { + return null + } + versions.forEach(function (v) { + if (rangeObj.test(v)) { + // satisfies(v, range, options) + if (!max || maxSV.compare(v) === -1) { + // compare(max, v, true) + max = v + maxSV = new SemVer(max, options) + } + } + }) + return max +} + +exports.minSatisfying = minSatisfying +function minSatisfying (versions, range, options) { + var min = null + var minSV = null + try { + var rangeObj = new Range(range, options) + } catch (er) { + return null + } + versions.forEach(function (v) { + if (rangeObj.test(v)) { + // satisfies(v, range, options) + if (!min || minSV.compare(v) === 1) { + // compare(min, v, true) + min = v + minSV = new SemVer(min, options) + } + } + }) + return min +} + +exports.minVersion = minVersion +function minVersion (range, loose) { + range = new Range(range, loose) + + var minver = new SemVer('0.0.0') + if (range.test(minver)) { + return minver + } + + minver = new SemVer('0.0.0-0') + if (range.test(minver)) { + return minver + } + + minver = null + for (var i = 0; i < range.set.length; ++i) { + var comparators = range.set[i] + + comparators.forEach(function (comparator) { + // Clone to avoid manipulating the comparator's semver object. + var compver = new SemVer(comparator.semver.version) + switch (comparator.operator) { + case '>': + if (compver.prerelease.length === 0) { + compver.patch++ + } else { + compver.prerelease.push(0) + } + compver.raw = compver.format() + /* fallthrough */ + case '': + case '>=': + if (!minver || gt(minver, compver)) { + minver = compver + } + break + case '<': + case '<=': + /* Ignore maximum versions */ + break + /* istanbul ignore next */ + default: + throw new Error('Unexpected operation: ' + comparator.operator) + } + }) + } + + if (minver && range.test(minver)) { + return minver + } + + return null +} + +exports.validRange = validRange +function validRange (range, options) { + try { + // Return '*' instead of '' so that truthiness works. + // This will throw if it's invalid anyway + return new Range(range, options).range || '*' + } catch (er) { + return null + } +} + +// Determine if version is less than all the versions possible in the range +exports.ltr = ltr +function ltr (version, range, options) { + return outside(version, range, '<', options) +} + +// Determine if version is greater than all the versions possible in the range. +exports.gtr = gtr +function gtr (version, range, options) { + return outside(version, range, '>', options) +} + +exports.outside = outside +function outside (version, range, hilo, options) { + version = new SemVer(version, options) + range = new Range(range, options) + + var gtfn, ltefn, ltfn, comp, ecomp + switch (hilo) { + case '>': + gtfn = gt + ltefn = lte + ltfn = lt + comp = '>' + ecomp = '>=' + break + case '<': + gtfn = lt + ltefn = gte + ltfn = gt + comp = '<' + ecomp = '<=' + break + default: + throw new TypeError('Must provide a hilo val of "<" or ">"') + } + + // If it satisifes the range it is not outside + if (satisfies(version, range, options)) { + return false + } + + // From now on, variable terms are as if we're in "gtr" mode. + // but note that everything is flipped for the "ltr" function. + + for (var i = 0; i < range.set.length; ++i) { + var comparators = range.set[i] + + var high = null + var low = null + + comparators.forEach(function (comparator) { + if (comparator.semver === ANY) { + comparator = new Comparator('>=0.0.0') + } + high = high || comparator + low = low || comparator + if (gtfn(comparator.semver, high.semver, options)) { + high = comparator + } else if (ltfn(comparator.semver, low.semver, options)) { + low = comparator + } + }) + + // If the edge version comparator has a operator then our version + // isn't outside it + if (high.operator === comp || high.operator === ecomp) { + return false + } + + // If the lowest version comparator has an operator and our version + // is less than it then it isn't higher than the range + if ((!low.operator || low.operator === comp) && + ltefn(version, low.semver)) { + return false + } else if (low.operator === ecomp && ltfn(version, low.semver)) { + return false + } + } + return true +} + +exports.prerelease = prerelease +function prerelease (version, options) { + var parsed = parse(version, options) + return (parsed && parsed.prerelease.length) ? parsed.prerelease : null +} + +exports.intersects = intersects +function intersects (r1, r2, options) { + r1 = new Range(r1, options) + r2 = new Range(r2, options) + return r1.intersects(r2) +} + +exports.coerce = coerce +function coerce (version) { + if (version instanceof SemVer) { + return version + } + + if (typeof version !== 'string') { + return null + } + + var match = version.match(re[COERCE]) + + if (match == null) { + return null + } + + return parse(match[1] + + '.' + (match[2] || '0') + + '.' + (match[3] || '0')) +} diff --git a/homework8/project_express/node_modules/send/HISTORY.md b/homework8/project_express/node_modules/send/HISTORY.md new file mode 100644 index 0000000..d14ac06 --- /dev/null +++ b/homework8/project_express/node_modules/send/HISTORY.md @@ -0,0 +1,496 @@ +0.17.1 / 2019-05-10 +=================== + + * Set stricter CSP header in redirect & error responses + * deps: range-parser@~1.2.1 + +0.17.0 / 2019-05-03 +=================== + + * deps: http-errors@~1.7.2 + - Set constructor name when possible + - Use `toidentifier` module to make class names + - deps: depd@~1.1.2 + - deps: setprototypeof@1.1.1 + - deps: statuses@'>= 1.5.0 < 2' + * deps: mime@1.6.0 + - Add extensions for JPEG-2000 images + - Add new `font/*` types from IANA + - Add WASM mapping + - Update `.bdoc` to `application/bdoc` + - Update `.bmp` to `image/bmp` + - Update `.m4a` to `audio/mp4` + - Update `.rtf` to `application/rtf` + - Update `.wav` to `audio/wav` + - Update `.xml` to `application/xml` + - Update generic extensions to `application/octet-stream`: + `.deb`, `.dll`, `.dmg`, `.exe`, `.iso`, `.msi` + - Use mime-score module to resolve extension conflicts + * deps: ms@2.1.1 + - Add `week`/`w` support + - Fix negative number handling + * deps: statuses@~1.5.0 + * perf: remove redundant `path.normalize` call + +0.16.2 / 2018-02-07 +=================== + + * Fix incorrect end tag in default error & redirects + * deps: depd@~1.1.2 + - perf: remove argument reassignment + * deps: encodeurl@~1.0.2 + - Fix encoding `%` as last character + * deps: statuses@~1.4.0 + +0.16.1 / 2017-09-29 +=================== + + * Fix regression in edge-case behavior for empty `path` + +0.16.0 / 2017-09-27 +=================== + + * Add `immutable` option + * Fix missing `` in default error & redirects + * Use instance methods on steam to check for listeners + * deps: mime@1.4.1 + - Add 70 new types for file extensions + - Set charset as "UTF-8" for .js and .json + * perf: improve path validation speed + +0.15.6 / 2017-09-22 +=================== + + * deps: debug@2.6.9 + * perf: improve `If-Match` token parsing + +0.15.5 / 2017-09-20 +=================== + + * deps: etag@~1.8.1 + - perf: replace regular expression with substring + * deps: fresh@0.5.2 + - Fix handling of modified headers with invalid dates + - perf: improve ETag match loop + - perf: improve `If-None-Match` token parsing + +0.15.4 / 2017-08-05 +=================== + + * deps: debug@2.6.8 + * deps: depd@~1.1.1 + - Remove unnecessary `Buffer` loading + * deps: http-errors@~1.6.2 + - deps: depd@1.1.1 + +0.15.3 / 2017-05-16 +=================== + + * deps: debug@2.6.7 + - deps: ms@2.0.0 + * deps: ms@2.0.0 + +0.15.2 / 2017-04-26 +=================== + + * deps: debug@2.6.4 + - Fix `DEBUG_MAX_ARRAY_LENGTH` + - deps: ms@0.7.3 + * deps: ms@1.0.0 + +0.15.1 / 2017-03-04 +=================== + + * Fix issue when `Date.parse` does not return `NaN` on invalid date + * Fix strict violation in broken environments + +0.15.0 / 2017-02-25 +=================== + + * Support `If-Match` and `If-Unmodified-Since` headers + * Add `res` and `path` arguments to `directory` event + * Remove usage of `res._headers` private field + - Improves compatibility with Node.js 8 nightly + * Send complete HTML document in redirect & error responses + * Set default CSP header in redirect & error responses + * Use `res.getHeaderNames()` when available + * Use `res.headersSent` when available + * deps: debug@2.6.1 + - Allow colors in workers + - Deprecated `DEBUG_FD` environment variable set to `3` or higher + - Fix error when running under React Native + - Use same color for same namespace + - deps: ms@0.7.2 + * deps: etag@~1.8.0 + * deps: fresh@0.5.0 + - Fix false detection of `no-cache` request directive + - Fix incorrect result when `If-None-Match` has both `*` and ETags + - Fix weak `ETag` matching to match spec + - perf: delay reading header values until needed + - perf: enable strict mode + - perf: hoist regular expressions + - perf: remove duplicate conditional + - perf: remove unnecessary boolean coercions + - perf: skip checking modified time if ETag check failed + - perf: skip parsing `If-None-Match` when no `ETag` header + - perf: use `Date.parse` instead of `new Date` + * deps: http-errors@~1.6.1 + - Make `message` property enumerable for `HttpError`s + - deps: setprototypeof@1.0.3 + +0.14.2 / 2017-01-23 +=================== + + * deps: http-errors@~1.5.1 + - deps: inherits@2.0.3 + - deps: setprototypeof@1.0.2 + - deps: statuses@'>= 1.3.1 < 2' + * deps: ms@0.7.2 + * deps: statuses@~1.3.1 + +0.14.1 / 2016-06-09 +=================== + + * Fix redirect error when `path` contains raw non-URL characters + * Fix redirect when `path` starts with multiple forward slashes + +0.14.0 / 2016-06-06 +=================== + + * Add `acceptRanges` option + * Add `cacheControl` option + * Attempt to combine multiple ranges into single range + * Correctly inherit from `Stream` class + * Fix `Content-Range` header in 416 responses when using `start`/`end` options + * Fix `Content-Range` header missing from default 416 responses + * Ignore non-byte `Range` headers + * deps: http-errors@~1.5.0 + - Add `HttpError` export, for `err instanceof createError.HttpError` + - Support new code `421 Misdirected Request` + - Use `setprototypeof` module to replace `__proto__` setting + - deps: inherits@2.0.1 + - deps: statuses@'>= 1.3.0 < 2' + - perf: enable strict mode + * deps: range-parser@~1.2.0 + - Fix incorrectly returning -1 when there is at least one valid range + - perf: remove internal function + * deps: statuses@~1.3.0 + - Add `421 Misdirected Request` + - perf: enable strict mode + * perf: remove argument reassignment + +0.13.2 / 2016-03-05 +=================== + + * Fix invalid `Content-Type` header when `send.mime.default_type` unset + +0.13.1 / 2016-01-16 +=================== + + * deps: depd@~1.1.0 + - Support web browser loading + - perf: enable strict mode + * deps: destroy@~1.0.4 + - perf: enable strict mode + * deps: escape-html@~1.0.3 + - perf: enable strict mode + - perf: optimize string replacement + - perf: use faster string coercion + * deps: range-parser@~1.0.3 + - perf: enable strict mode + +0.13.0 / 2015-06-16 +=================== + + * Allow Node.js HTTP server to set `Date` response header + * Fix incorrectly removing `Content-Location` on 304 response + * Improve the default redirect response headers + * Send appropriate headers on default error response + * Use `http-errors` for standard emitted errors + * Use `statuses` instead of `http` module for status messages + * deps: escape-html@1.0.2 + * deps: etag@~1.7.0 + - Improve stat performance by removing hashing + * deps: fresh@0.3.0 + - Add weak `ETag` matching support + * deps: on-finished@~2.3.0 + - Add defined behavior for HTTP `CONNECT` requests + - Add defined behavior for HTTP `Upgrade` requests + - deps: ee-first@1.1.1 + * perf: enable strict mode + * perf: remove unnecessary array allocations + +0.12.3 / 2015-05-13 +=================== + + * deps: debug@~2.2.0 + - deps: ms@0.7.1 + * deps: depd@~1.0.1 + * deps: etag@~1.6.0 + - Improve support for JXcore + - Support "fake" stats objects in environments without `fs` + * deps: ms@0.7.1 + - Prevent extraordinarily long inputs + * deps: on-finished@~2.2.1 + +0.12.2 / 2015-03-13 +=================== + + * Throw errors early for invalid `extensions` or `index` options + * deps: debug@~2.1.3 + - Fix high intensity foreground color for bold + - deps: ms@0.7.0 + +0.12.1 / 2015-02-17 +=================== + + * Fix regression sending zero-length files + +0.12.0 / 2015-02-16 +=================== + + * Always read the stat size from the file + * Fix mutating passed-in `options` + * deps: mime@1.3.4 + +0.11.1 / 2015-01-20 +=================== + + * Fix `root` path disclosure + +0.11.0 / 2015-01-05 +=================== + + * deps: debug@~2.1.1 + * deps: etag@~1.5.1 + - deps: crc@3.2.1 + * deps: ms@0.7.0 + - Add `milliseconds` + - Add `msecs` + - Add `secs` + - Add `mins` + - Add `hrs` + - Add `yrs` + * deps: on-finished@~2.2.0 + +0.10.1 / 2014-10-22 +=================== + + * deps: on-finished@~2.1.1 + - Fix handling of pipelined requests + +0.10.0 / 2014-10-15 +=================== + + * deps: debug@~2.1.0 + - Implement `DEBUG_FD` env variable support + * deps: depd@~1.0.0 + * deps: etag@~1.5.0 + - Improve string performance + - Slightly improve speed for weak ETags over 1KB + +0.9.3 / 2014-09-24 +================== + + * deps: etag@~1.4.0 + - Support "fake" stats objects + +0.9.2 / 2014-09-15 +================== + + * deps: depd@0.4.5 + * deps: etag@~1.3.1 + * deps: range-parser@~1.0.2 + +0.9.1 / 2014-09-07 +================== + + * deps: fresh@0.2.4 + +0.9.0 / 2014-09-07 +================== + + * Add `lastModified` option + * Use `etag` to generate `ETag` header + * deps: debug@~2.0.0 + +0.8.5 / 2014-09-04 +================== + + * Fix malicious path detection for empty string path + +0.8.4 / 2014-09-04 +================== + + * Fix a path traversal issue when using `root` + +0.8.3 / 2014-08-16 +================== + + * deps: destroy@1.0.3 + - renamed from dethroy + * deps: on-finished@2.1.0 + +0.8.2 / 2014-08-14 +================== + + * Work around `fd` leak in Node.js 0.10 for `fs.ReadStream` + * deps: dethroy@1.0.2 + +0.8.1 / 2014-08-05 +================== + + * Fix `extensions` behavior when file already has extension + +0.8.0 / 2014-08-05 +================== + + * Add `extensions` option + +0.7.4 / 2014-08-04 +================== + + * Fix serving index files without root dir + +0.7.3 / 2014-07-29 +================== + + * Fix incorrect 403 on Windows and Node.js 0.11 + +0.7.2 / 2014-07-27 +================== + + * deps: depd@0.4.4 + - Work-around v8 generating empty stack traces + +0.7.1 / 2014-07-26 +================== + + * deps: depd@0.4.3 + - Fix exception when global `Error.stackTraceLimit` is too low + +0.7.0 / 2014-07-20 +================== + + * Deprecate `hidden` option; use `dotfiles` option + * Add `dotfiles` option + * deps: debug@1.0.4 + * deps: depd@0.4.2 + - Add `TRACE_DEPRECATION` environment variable + - Remove non-standard grey color from color output + - Support `--no-deprecation` argument + - Support `--trace-deprecation` argument + +0.6.0 / 2014-07-11 +================== + + * Deprecate `from` option; use `root` option + * Deprecate `send.etag()` -- use `etag` in `options` + * Deprecate `send.hidden()` -- use `hidden` in `options` + * Deprecate `send.index()` -- use `index` in `options` + * Deprecate `send.maxage()` -- use `maxAge` in `options` + * Deprecate `send.root()` -- use `root` in `options` + * Cap `maxAge` value to 1 year + * deps: debug@1.0.3 + - Add support for multiple wildcards in namespaces + +0.5.0 / 2014-06-28 +================== + + * Accept string for `maxAge` (converted by `ms`) + * Add `headers` event + * Include link in default redirect response + * Use `EventEmitter.listenerCount` to count listeners + +0.4.3 / 2014-06-11 +================== + + * Do not throw un-catchable error on file open race condition + * Use `escape-html` for HTML escaping + * deps: debug@1.0.2 + - fix some debugging output colors on node.js 0.8 + * deps: finished@1.2.2 + * deps: fresh@0.2.2 + +0.4.2 / 2014-06-09 +================== + + * fix "event emitter leak" warnings + * deps: debug@1.0.1 + * deps: finished@1.2.1 + +0.4.1 / 2014-06-02 +================== + + * Send `max-age` in `Cache-Control` in correct format + +0.4.0 / 2014-05-27 +================== + + * Calculate ETag with md5 for reduced collisions + * Fix wrong behavior when index file matches directory + * Ignore stream errors after request ends + - Goodbye `EBADF, read` + * Skip directories in index file search + * deps: debug@0.8.1 + +0.3.0 / 2014-04-24 +================== + + * Fix sending files with dots without root set + * Coerce option types + * Accept API options in options object + * Set etags to "weak" + * Include file path in etag + * Make "Can't set headers after they are sent." catchable + * Send full entity-body for multi range requests + * Default directory access to 403 when index disabled + * Support multiple index paths + * Support "If-Range" header + * Control whether to generate etags + * deps: mime@1.2.11 + +0.2.0 / 2014-01-29 +================== + + * update range-parser and fresh + +0.1.4 / 2013-08-11 +================== + + * update fresh + +0.1.3 / 2013-07-08 +================== + + * Revert "Fix fd leak" + +0.1.2 / 2013-07-03 +================== + + * Fix fd leak + +0.1.0 / 2012-08-25 +================== + + * add options parameter to send() that is passed to fs.createReadStream() [kanongil] + +0.0.4 / 2012-08-16 +================== + + * allow custom "Accept-Ranges" definition + +0.0.3 / 2012-07-16 +================== + + * fix normalization of the root directory. Closes #3 + +0.0.2 / 2012-07-09 +================== + + * add passing of req explicitly for now (YUCK) + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/homework8/project_express/node_modules/send/LICENSE b/homework8/project_express/node_modules/send/LICENSE new file mode 100644 index 0000000..4aa69e8 --- /dev/null +++ b/homework8/project_express/node_modules/send/LICENSE @@ -0,0 +1,23 @@ +(The MIT License) + +Copyright (c) 2012 TJ Holowaychuk +Copyright (c) 2014-2016 Douglas Christopher Wilson + +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/homework8/project_express/node_modules/send/README.md b/homework8/project_express/node_modules/send/README.md new file mode 100644 index 0000000..179e8c3 --- /dev/null +++ b/homework8/project_express/node_modules/send/README.md @@ -0,0 +1,329 @@ +# send + +[![NPM Version][npm-version-image]][npm-url] +[![NPM Downloads][npm-downloads-image]][npm-url] +[![Linux Build][travis-image]][travis-url] +[![Windows Build][appveyor-image]][appveyor-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Send is a library for streaming files from the file system as a http response +supporting partial responses (Ranges), conditional-GET negotiation (If-Match, +If-Unmodified-Since, If-None-Match, If-Modified-Since), high test coverage, +and granular events which may be leveraged to take appropriate actions in your +application or framework. + +Looking to serve up entire folders mapped to URLs? Try [serve-static](https://www.npmjs.org/package/serve-static). + +## Installation + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```bash +$ npm install send +``` + +## API + + + +```js +var send = require('send') +``` + +### send(req, path, [options]) + +Create a new `SendStream` for the given path to send to a `res`. The `req` is +the Node.js HTTP request and the `path` is a urlencoded path to send (urlencoded, +not the actual file-system path). + +#### Options + +##### acceptRanges + +Enable or disable accepting ranged requests, defaults to true. +Disabling this will not send `Accept-Ranges` and ignore the contents +of the `Range` request header. + +##### cacheControl + +Enable or disable setting `Cache-Control` response header, defaults to +true. Disabling this will ignore the `immutable` and `maxAge` options. + +##### dotfiles + +Set how "dotfiles" are treated when encountered. A dotfile is a file +or directory that begins with a dot ("."). Note this check is done on +the path itself without checking if the path actually exists on the +disk. If `root` is specified, only the dotfiles above the root are +checked (i.e. the root itself can be within a dotfile when when set +to "deny"). + + - `'allow'` No special treatment for dotfiles. + - `'deny'` Send a 403 for any request for a dotfile. + - `'ignore'` Pretend like the dotfile does not exist and 404. + +The default value is _similar_ to `'ignore'`, with the exception that +this default will not ignore the files within a directory that begins +with a dot, for backward-compatibility. + +##### end + +Byte offset at which the stream ends, defaults to the length of the file +minus 1. The end is inclusive in the stream, meaning `end: 3` will include +the 4th byte in the stream. + +##### etag + +Enable or disable etag generation, defaults to true. + +##### extensions + +If a given file doesn't exist, try appending one of the given extensions, +in the given order. By default, this is disabled (set to `false`). An +example value that will serve extension-less HTML files: `['html', 'htm']`. +This is skipped if the requested file already has an extension. + +##### immutable + +Enable or diable the `immutable` directive in the `Cache-Control` response +header, defaults to `false`. If set to `true`, the `maxAge` option should +also be specified to enable caching. The `immutable` directive will prevent +supported clients from making conditional requests during the life of the +`maxAge` option to check if the file has changed. + +##### index + +By default send supports "index.html" files, to disable this +set `false` or to supply a new index pass a string or an array +in preferred order. + +##### lastModified + +Enable or disable `Last-Modified` header, defaults to true. Uses the file +system's last modified value. + +##### maxAge + +Provide a max-age in milliseconds for http caching, defaults to 0. +This can also be a string accepted by the +[ms](https://www.npmjs.org/package/ms#readme) module. + +##### root + +Serve files relative to `path`. + +##### start + +Byte offset at which the stream starts, defaults to 0. The start is inclusive, +meaning `start: 2` will include the 3rd byte in the stream. + +#### Events + +The `SendStream` is an event emitter and will emit the following events: + + - `error` an error occurred `(err)` + - `directory` a directory was requested `(res, path)` + - `file` a file was requested `(path, stat)` + - `headers` the headers are about to be set on a file `(res, path, stat)` + - `stream` file streaming has started `(stream)` + - `end` streaming has completed + +#### .pipe + +The `pipe` method is used to pipe the response into the Node.js HTTP response +object, typically `send(req, path, options).pipe(res)`. + +### .mime + +The `mime` export is the global instance of of the +[`mime` npm module](https://www.npmjs.com/package/mime). + +This is used to configure the MIME types that are associated with file extensions +as well as other options for how to resolve the MIME type of a file (like the +default type to use for an unknown file extension). + +## Error-handling + +By default when no `error` listeners are present an automatic response will be +made, otherwise you have full control over the response, aka you may show a 5xx +page etc. + +## Caching + +It does _not_ perform internal caching, you should use a reverse proxy cache +such as Varnish for this, or those fancy things called CDNs. If your +application is small enough that it would benefit from single-node memory +caching, it's small enough that it does not need caching at all ;). + +## Debugging + +To enable `debug()` instrumentation output export __DEBUG__: + +``` +$ DEBUG=send node app +``` + +## Running tests + +``` +$ npm install +$ npm test +``` + +## Examples + +### Serve a specific file + +This simple example will send a specific file to all requests. + +```js +var http = require('http') +var send = require('send') + +var server = http.createServer(function onRequest (req, res) { + send(req, '/path/to/index.html') + .pipe(res) +}) + +server.listen(3000) +``` + +### Serve all files from a directory + +This simple example will just serve up all the files in a +given directory as the top-level. For example, a request +`GET /foo.txt` will send back `/www/public/foo.txt`. + +```js +var http = require('http') +var parseUrl = require('parseurl') +var send = require('send') + +var server = http.createServer(function onRequest (req, res) { + send(req, parseUrl(req).pathname, { root: '/www/public' }) + .pipe(res) +}) + +server.listen(3000) +``` + +### Custom file types + +```js +var http = require('http') +var parseUrl = require('parseurl') +var send = require('send') + +// Default unknown types to text/plain +send.mime.default_type = 'text/plain' + +// Add a custom type +send.mime.define({ + 'application/x-my-type': ['x-mt', 'x-mtt'] +}) + +var server = http.createServer(function onRequest (req, res) { + send(req, parseUrl(req).pathname, { root: '/www/public' }) + .pipe(res) +}) + +server.listen(3000) +``` + +### Custom directory index view + +This is a example of serving up a structure of directories with a +custom function to render a listing of a directory. + +```js +var http = require('http') +var fs = require('fs') +var parseUrl = require('parseurl') +var send = require('send') + +// Transfer arbitrary files from within /www/example.com/public/* +// with a custom handler for directory listing +var server = http.createServer(function onRequest (req, res) { + send(req, parseUrl(req).pathname, { index: false, root: '/www/public' }) + .once('directory', directory) + .pipe(res) +}) + +server.listen(3000) + +// Custom directory handler +function directory (res, path) { + var stream = this + + // redirect to trailing slash for consistent url + if (!stream.hasTrailingSlash()) { + return stream.redirect(path) + } + + // get directory list + fs.readdir(path, function onReaddir (err, list) { + if (err) return stream.error(err) + + // render an index for the directory + res.setHeader('Content-Type', 'text/plain; charset=UTF-8') + res.end(list.join('\n') + '\n') + }) +} +``` + +### Serving from a root directory with custom error-handling + +```js +var http = require('http') +var parseUrl = require('parseurl') +var send = require('send') + +var server = http.createServer(function onRequest (req, res) { + // your custom error-handling logic: + function error (err) { + res.statusCode = err.status || 500 + res.end(err.message) + } + + // your custom headers + function headers (res, path, stat) { + // serve all files for download + res.setHeader('Content-Disposition', 'attachment') + } + + // your custom directory handling logic: + function redirect () { + res.statusCode = 301 + res.setHeader('Location', req.url + '/') + res.end('Redirecting to ' + req.url + '/') + } + + // transfer arbitrary files from within + // /www/example.com/public/* + send(req, parseUrl(req).pathname, { root: '/www/public' }) + .on('error', error) + .on('directory', redirect) + .on('headers', headers) + .pipe(res) +}) + +server.listen(3000) +``` + +## License + +[MIT](LICENSE) + +[appveyor-image]: https://badgen.net/appveyor/ci/dougwilson/send/master?label=windows +[appveyor-url]: https://ci.appveyor.com/project/dougwilson/send +[coveralls-image]: https://badgen.net/coveralls/c/github/pillarjs/send/master +[coveralls-url]: https://coveralls.io/r/pillarjs/send?branch=master +[node-image]: https://badgen.net/npm/node/send +[node-url]: https://nodejs.org/en/download/ +[npm-downloads-image]: https://badgen.net/npm/dm/send +[npm-url]: https://npmjs.org/package/send +[npm-version-image]: https://badgen.net/npm/v/send +[travis-image]: https://badgen.net/travis/pillarjs/send/master?label=linux +[travis-url]: https://travis-ci.org/pillarjs/send diff --git a/homework8/project_express/node_modules/send/index.js b/homework8/project_express/node_modules/send/index.js new file mode 100644 index 0000000..fca2112 --- /dev/null +++ b/homework8/project_express/node_modules/send/index.js @@ -0,0 +1,1129 @@ +/*! + * send + * Copyright(c) 2012 TJ Holowaychuk + * Copyright(c) 2014-2016 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var createError = require('http-errors') +var debug = require('debug')('send') +var deprecate = require('depd')('send') +var destroy = require('destroy') +var encodeUrl = require('encodeurl') +var escapeHtml = require('escape-html') +var etag = require('etag') +var fresh = require('fresh') +var fs = require('fs') +var mime = require('mime') +var ms = require('ms') +var onFinished = require('on-finished') +var parseRange = require('range-parser') +var path = require('path') +var statuses = require('statuses') +var Stream = require('stream') +var util = require('util') + +/** + * Path function references. + * @private + */ + +var extname = path.extname +var join = path.join +var normalize = path.normalize +var resolve = path.resolve +var sep = path.sep + +/** + * Regular expression for identifying a bytes Range header. + * @private + */ + +var BYTES_RANGE_REGEXP = /^ *bytes=/ + +/** + * Maximum value allowed for the max age. + * @private + */ + +var MAX_MAXAGE = 60 * 60 * 24 * 365 * 1000 // 1 year + +/** + * Regular expression to match a path with a directory up component. + * @private + */ + +var UP_PATH_REGEXP = /(?:^|[\\/])\.\.(?:[\\/]|$)/ + +/** + * Module exports. + * @public + */ + +module.exports = send +module.exports.mime = mime + +/** + * Return a `SendStream` for `req` and `path`. + * + * @param {object} req + * @param {string} path + * @param {object} [options] + * @return {SendStream} + * @public + */ + +function send (req, path, options) { + return new SendStream(req, path, options) +} + +/** + * Initialize a `SendStream` with the given `path`. + * + * @param {Request} req + * @param {String} path + * @param {object} [options] + * @private + */ + +function SendStream (req, path, options) { + Stream.call(this) + + var opts = options || {} + + this.options = opts + this.path = path + this.req = req + + this._acceptRanges = opts.acceptRanges !== undefined + ? Boolean(opts.acceptRanges) + : true + + this._cacheControl = opts.cacheControl !== undefined + ? Boolean(opts.cacheControl) + : true + + this._etag = opts.etag !== undefined + ? Boolean(opts.etag) + : true + + this._dotfiles = opts.dotfiles !== undefined + ? opts.dotfiles + : 'ignore' + + if (this._dotfiles !== 'ignore' && this._dotfiles !== 'allow' && this._dotfiles !== 'deny') { + throw new TypeError('dotfiles option must be "allow", "deny", or "ignore"') + } + + this._hidden = Boolean(opts.hidden) + + if (opts.hidden !== undefined) { + deprecate('hidden: use dotfiles: \'' + (this._hidden ? 'allow' : 'ignore') + '\' instead') + } + + // legacy support + if (opts.dotfiles === undefined) { + this._dotfiles = undefined + } + + this._extensions = opts.extensions !== undefined + ? normalizeList(opts.extensions, 'extensions option') + : [] + + this._immutable = opts.immutable !== undefined + ? Boolean(opts.immutable) + : false + + this._index = opts.index !== undefined + ? normalizeList(opts.index, 'index option') + : ['index.html'] + + this._lastModified = opts.lastModified !== undefined + ? Boolean(opts.lastModified) + : true + + this._maxage = opts.maxAge || opts.maxage + this._maxage = typeof this._maxage === 'string' + ? ms(this._maxage) + : Number(this._maxage) + this._maxage = !isNaN(this._maxage) + ? Math.min(Math.max(0, this._maxage), MAX_MAXAGE) + : 0 + + this._root = opts.root + ? resolve(opts.root) + : null + + if (!this._root && opts.from) { + this.from(opts.from) + } +} + +/** + * Inherits from `Stream`. + */ + +util.inherits(SendStream, Stream) + +/** + * Enable or disable etag generation. + * + * @param {Boolean} val + * @return {SendStream} + * @api public + */ + +SendStream.prototype.etag = deprecate.function(function etag (val) { + this._etag = Boolean(val) + debug('etag %s', this._etag) + return this +}, 'send.etag: pass etag as option') + +/** + * Enable or disable "hidden" (dot) files. + * + * @param {Boolean} path + * @return {SendStream} + * @api public + */ + +SendStream.prototype.hidden = deprecate.function(function hidden (val) { + this._hidden = Boolean(val) + this._dotfiles = undefined + debug('hidden %s', this._hidden) + return this +}, 'send.hidden: use dotfiles option') + +/** + * Set index `paths`, set to a falsy + * value to disable index support. + * + * @param {String|Boolean|Array} paths + * @return {SendStream} + * @api public + */ + +SendStream.prototype.index = deprecate.function(function index (paths) { + var index = !paths ? [] : normalizeList(paths, 'paths argument') + debug('index %o', paths) + this._index = index + return this +}, 'send.index: pass index as option') + +/** + * Set root `path`. + * + * @param {String} path + * @return {SendStream} + * @api public + */ + +SendStream.prototype.root = function root (path) { + this._root = resolve(String(path)) + debug('root %s', this._root) + return this +} + +SendStream.prototype.from = deprecate.function(SendStream.prototype.root, + 'send.from: pass root as option') + +SendStream.prototype.root = deprecate.function(SendStream.prototype.root, + 'send.root: pass root as option') + +/** + * Set max-age to `maxAge`. + * + * @param {Number} maxAge + * @return {SendStream} + * @api public + */ + +SendStream.prototype.maxage = deprecate.function(function maxage (maxAge) { + this._maxage = typeof maxAge === 'string' + ? ms(maxAge) + : Number(maxAge) + this._maxage = !isNaN(this._maxage) + ? Math.min(Math.max(0, this._maxage), MAX_MAXAGE) + : 0 + debug('max-age %d', this._maxage) + return this +}, 'send.maxage: pass maxAge as option') + +/** + * Emit error with `status`. + * + * @param {number} status + * @param {Error} [err] + * @private + */ + +SendStream.prototype.error = function error (status, err) { + // emit if listeners instead of responding + if (hasListeners(this, 'error')) { + return this.emit('error', createError(status, err, { + expose: false + })) + } + + var res = this.res + var msg = statuses[status] || String(status) + var doc = createHtmlDocument('Error', escapeHtml(msg)) + + // clear existing headers + clearHeaders(res) + + // add error headers + if (err && err.headers) { + setHeaders(res, err.headers) + } + + // send basic response + res.statusCode = status + res.setHeader('Content-Type', 'text/html; charset=UTF-8') + res.setHeader('Content-Length', Buffer.byteLength(doc)) + res.setHeader('Content-Security-Policy', "default-src 'none'") + res.setHeader('X-Content-Type-Options', 'nosniff') + res.end(doc) +} + +/** + * Check if the pathname ends with "/". + * + * @return {boolean} + * @private + */ + +SendStream.prototype.hasTrailingSlash = function hasTrailingSlash () { + return this.path[this.path.length - 1] === '/' +} + +/** + * Check if this is a conditional GET request. + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.isConditionalGET = function isConditionalGET () { + return this.req.headers['if-match'] || + this.req.headers['if-unmodified-since'] || + this.req.headers['if-none-match'] || + this.req.headers['if-modified-since'] +} + +/** + * Check if the request preconditions failed. + * + * @return {boolean} + * @private + */ + +SendStream.prototype.isPreconditionFailure = function isPreconditionFailure () { + var req = this.req + var res = this.res + + // if-match + var match = req.headers['if-match'] + if (match) { + var etag = res.getHeader('ETag') + return !etag || (match !== '*' && parseTokenList(match).every(function (match) { + return match !== etag && match !== 'W/' + etag && 'W/' + match !== etag + })) + } + + // if-unmodified-since + var unmodifiedSince = parseHttpDate(req.headers['if-unmodified-since']) + if (!isNaN(unmodifiedSince)) { + var lastModified = parseHttpDate(res.getHeader('Last-Modified')) + return isNaN(lastModified) || lastModified > unmodifiedSince + } + + return false +} + +/** + * Strip content-* header fields. + * + * @private + */ + +SendStream.prototype.removeContentHeaderFields = function removeContentHeaderFields () { + var res = this.res + var headers = getHeaderNames(res) + + for (var i = 0; i < headers.length; i++) { + var header = headers[i] + if (header.substr(0, 8) === 'content-' && header !== 'content-location') { + res.removeHeader(header) + } + } +} + +/** + * Respond with 304 not modified. + * + * @api private + */ + +SendStream.prototype.notModified = function notModified () { + var res = this.res + debug('not modified') + this.removeContentHeaderFields() + res.statusCode = 304 + res.end() +} + +/** + * Raise error that headers already sent. + * + * @api private + */ + +SendStream.prototype.headersAlreadySent = function headersAlreadySent () { + var err = new Error('Can\'t set headers after they are sent.') + debug('headers already sent') + this.error(500, err) +} + +/** + * Check if the request is cacheable, aka + * responded with 2xx or 304 (see RFC 2616 section 14.2{5,6}). + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.isCachable = function isCachable () { + var statusCode = this.res.statusCode + return (statusCode >= 200 && statusCode < 300) || + statusCode === 304 +} + +/** + * Handle stat() error. + * + * @param {Error} error + * @private + */ + +SendStream.prototype.onStatError = function onStatError (error) { + switch (error.code) { + case 'ENAMETOOLONG': + case 'ENOENT': + case 'ENOTDIR': + this.error(404, error) + break + default: + this.error(500, error) + break + } +} + +/** + * Check if the cache is fresh. + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.isFresh = function isFresh () { + return fresh(this.req.headers, { + 'etag': this.res.getHeader('ETag'), + 'last-modified': this.res.getHeader('Last-Modified') + }) +} + +/** + * Check if the range is fresh. + * + * @return {Boolean} + * @api private + */ + +SendStream.prototype.isRangeFresh = function isRangeFresh () { + var ifRange = this.req.headers['if-range'] + + if (!ifRange) { + return true + } + + // if-range as etag + if (ifRange.indexOf('"') !== -1) { + var etag = this.res.getHeader('ETag') + return Boolean(etag && ifRange.indexOf(etag) !== -1) + } + + // if-range as modified date + var lastModified = this.res.getHeader('Last-Modified') + return parseHttpDate(lastModified) <= parseHttpDate(ifRange) +} + +/** + * Redirect to path. + * + * @param {string} path + * @private + */ + +SendStream.prototype.redirect = function redirect (path) { + var res = this.res + + if (hasListeners(this, 'directory')) { + this.emit('directory', res, path) + return + } + + if (this.hasTrailingSlash()) { + this.error(403) + return + } + + var loc = encodeUrl(collapseLeadingSlashes(this.path + '/')) + var doc = createHtmlDocument('Redirecting', 'Redirecting to ' + + escapeHtml(loc) + '') + + // redirect + res.statusCode = 301 + res.setHeader('Content-Type', 'text/html; charset=UTF-8') + res.setHeader('Content-Length', Buffer.byteLength(doc)) + res.setHeader('Content-Security-Policy', "default-src 'none'") + res.setHeader('X-Content-Type-Options', 'nosniff') + res.setHeader('Location', loc) + res.end(doc) +} + +/** + * Pipe to `res. + * + * @param {Stream} res + * @return {Stream} res + * @api public + */ + +SendStream.prototype.pipe = function pipe (res) { + // root path + var root = this._root + + // references + this.res = res + + // decode the path + var path = decode(this.path) + if (path === -1) { + this.error(400) + return res + } + + // null byte(s) + if (~path.indexOf('\0')) { + this.error(400) + return res + } + + var parts + if (root !== null) { + // normalize + if (path) { + path = normalize('.' + sep + path) + } + + // malicious path + if (UP_PATH_REGEXP.test(path)) { + debug('malicious path "%s"', path) + this.error(403) + return res + } + + // explode path parts + parts = path.split(sep) + + // join / normalize from optional root dir + path = normalize(join(root, path)) + } else { + // ".." is malicious without "root" + if (UP_PATH_REGEXP.test(path)) { + debug('malicious path "%s"', path) + this.error(403) + return res + } + + // explode path parts + parts = normalize(path).split(sep) + + // resolve the path + path = resolve(path) + } + + // dotfile handling + if (containsDotFile(parts)) { + var access = this._dotfiles + + // legacy support + if (access === undefined) { + access = parts[parts.length - 1][0] === '.' + ? (this._hidden ? 'allow' : 'ignore') + : 'allow' + } + + debug('%s dotfile "%s"', access, path) + switch (access) { + case 'allow': + break + case 'deny': + this.error(403) + return res + case 'ignore': + default: + this.error(404) + return res + } + } + + // index file support + if (this._index.length && this.hasTrailingSlash()) { + this.sendIndex(path) + return res + } + + this.sendFile(path) + return res +} + +/** + * Transfer `path`. + * + * @param {String} path + * @api public + */ + +SendStream.prototype.send = function send (path, stat) { + var len = stat.size + var options = this.options + var opts = {} + var res = this.res + var req = this.req + var ranges = req.headers.range + var offset = options.start || 0 + + if (headersSent(res)) { + // impossible to send now + this.headersAlreadySent() + return + } + + debug('pipe "%s"', path) + + // set header fields + this.setHeader(path, stat) + + // set content-type + this.type(path) + + // conditional GET support + if (this.isConditionalGET()) { + if (this.isPreconditionFailure()) { + this.error(412) + return + } + + if (this.isCachable() && this.isFresh()) { + this.notModified() + return + } + } + + // adjust len to start/end options + len = Math.max(0, len - offset) + if (options.end !== undefined) { + var bytes = options.end - offset + 1 + if (len > bytes) len = bytes + } + + // Range support + if (this._acceptRanges && BYTES_RANGE_REGEXP.test(ranges)) { + // parse + ranges = parseRange(len, ranges, { + combine: true + }) + + // If-Range support + if (!this.isRangeFresh()) { + debug('range stale') + ranges = -2 + } + + // unsatisfiable + if (ranges === -1) { + debug('range unsatisfiable') + + // Content-Range + res.setHeader('Content-Range', contentRange('bytes', len)) + + // 416 Requested Range Not Satisfiable + return this.error(416, { + headers: { 'Content-Range': res.getHeader('Content-Range') } + }) + } + + // valid (syntactically invalid/multiple ranges are treated as a regular response) + if (ranges !== -2 && ranges.length === 1) { + debug('range %j', ranges) + + // Content-Range + res.statusCode = 206 + res.setHeader('Content-Range', contentRange('bytes', len, ranges[0])) + + // adjust for requested range + offset += ranges[0].start + len = ranges[0].end - ranges[0].start + 1 + } + } + + // clone options + for (var prop in options) { + opts[prop] = options[prop] + } + + // set read options + opts.start = offset + opts.end = Math.max(offset, offset + len - 1) + + // content-length + res.setHeader('Content-Length', len) + + // HEAD support + if (req.method === 'HEAD') { + res.end() + return + } + + this.stream(path, opts) +} + +/** + * Transfer file for `path`. + * + * @param {String} path + * @api private + */ +SendStream.prototype.sendFile = function sendFile (path) { + var i = 0 + var self = this + + debug('stat "%s"', path) + fs.stat(path, function onstat (err, stat) { + if (err && err.code === 'ENOENT' && !extname(path) && path[path.length - 1] !== sep) { + // not found, check extensions + return next(err) + } + if (err) return self.onStatError(err) + if (stat.isDirectory()) return self.redirect(path) + self.emit('file', path, stat) + self.send(path, stat) + }) + + function next (err) { + if (self._extensions.length <= i) { + return err + ? self.onStatError(err) + : self.error(404) + } + + var p = path + '.' + self._extensions[i++] + + debug('stat "%s"', p) + fs.stat(p, function (err, stat) { + if (err) return next(err) + if (stat.isDirectory()) return next() + self.emit('file', p, stat) + self.send(p, stat) + }) + } +} + +/** + * Transfer index for `path`. + * + * @param {String} path + * @api private + */ +SendStream.prototype.sendIndex = function sendIndex (path) { + var i = -1 + var self = this + + function next (err) { + if (++i >= self._index.length) { + if (err) return self.onStatError(err) + return self.error(404) + } + + var p = join(path, self._index[i]) + + debug('stat "%s"', p) + fs.stat(p, function (err, stat) { + if (err) return next(err) + if (stat.isDirectory()) return next() + self.emit('file', p, stat) + self.send(p, stat) + }) + } + + next() +} + +/** + * Stream `path` to the response. + * + * @param {String} path + * @param {Object} options + * @api private + */ + +SendStream.prototype.stream = function stream (path, options) { + // TODO: this is all lame, refactor meeee + var finished = false + var self = this + var res = this.res + + // pipe + var stream = fs.createReadStream(path, options) + this.emit('stream', stream) + stream.pipe(res) + + // response finished, done with the fd + onFinished(res, function onfinished () { + finished = true + destroy(stream) + }) + + // error handling code-smell + stream.on('error', function onerror (err) { + // request already finished + if (finished) return + + // clean up stream + finished = true + destroy(stream) + + // error + self.onStatError(err) + }) + + // end + stream.on('end', function onend () { + self.emit('end') + }) +} + +/** + * Set content-type based on `path` + * if it hasn't been explicitly set. + * + * @param {String} path + * @api private + */ + +SendStream.prototype.type = function type (path) { + var res = this.res + + if (res.getHeader('Content-Type')) return + + var type = mime.lookup(path) + + if (!type) { + debug('no content-type') + return + } + + var charset = mime.charsets.lookup(type) + + debug('content-type %s', type) + res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : '')) +} + +/** + * Set response header fields, most + * fields may be pre-defined. + * + * @param {String} path + * @param {Object} stat + * @api private + */ + +SendStream.prototype.setHeader = function setHeader (path, stat) { + var res = this.res + + this.emit('headers', res, path, stat) + + if (this._acceptRanges && !res.getHeader('Accept-Ranges')) { + debug('accept ranges') + res.setHeader('Accept-Ranges', 'bytes') + } + + if (this._cacheControl && !res.getHeader('Cache-Control')) { + var cacheControl = 'public, max-age=' + Math.floor(this._maxage / 1000) + + if (this._immutable) { + cacheControl += ', immutable' + } + + debug('cache-control %s', cacheControl) + res.setHeader('Cache-Control', cacheControl) + } + + if (this._lastModified && !res.getHeader('Last-Modified')) { + var modified = stat.mtime.toUTCString() + debug('modified %s', modified) + res.setHeader('Last-Modified', modified) + } + + if (this._etag && !res.getHeader('ETag')) { + var val = etag(stat) + debug('etag %s', val) + res.setHeader('ETag', val) + } +} + +/** + * Clear all headers from a response. + * + * @param {object} res + * @private + */ + +function clearHeaders (res) { + var headers = getHeaderNames(res) + + for (var i = 0; i < headers.length; i++) { + res.removeHeader(headers[i]) + } +} + +/** + * Collapse all leading slashes into a single slash + * + * @param {string} str + * @private + */ +function collapseLeadingSlashes (str) { + for (var i = 0; i < str.length; i++) { + if (str[i] !== '/') { + break + } + } + + return i > 1 + ? '/' + str.substr(i) + : str +} + +/** + * Determine if path parts contain a dotfile. + * + * @api private + */ + +function containsDotFile (parts) { + for (var i = 0; i < parts.length; i++) { + var part = parts[i] + if (part.length > 1 && part[0] === '.') { + return true + } + } + + return false +} + +/** + * Create a Content-Range header. + * + * @param {string} type + * @param {number} size + * @param {array} [range] + */ + +function contentRange (type, size, range) { + return type + ' ' + (range ? range.start + '-' + range.end : '*') + '/' + size +} + +/** + * Create a minimal HTML document. + * + * @param {string} title + * @param {string} body + * @private + */ + +function createHtmlDocument (title, body) { + return '\n' + + '\n' + + '\n' + + '\n' + + '' + title + '\n' + + '\n' + + '\n' + + '
' + body + '
\n' + + '\n' + + '\n' +} + +/** + * decodeURIComponent. + * + * Allows V8 to only deoptimize this fn instead of all + * of send(). + * + * @param {String} path + * @api private + */ + +function decode (path) { + try { + return decodeURIComponent(path) + } catch (err) { + return -1 + } +} + +/** + * Get the header names on a respnse. + * + * @param {object} res + * @returns {array[string]} + * @private + */ + +function getHeaderNames (res) { + return typeof res.getHeaderNames !== 'function' + ? Object.keys(res._headers || {}) + : res.getHeaderNames() +} + +/** + * Determine if emitter has listeners of a given type. + * + * The way to do this check is done three different ways in Node.js >= 0.8 + * so this consolidates them into a minimal set using instance methods. + * + * @param {EventEmitter} emitter + * @param {string} type + * @returns {boolean} + * @private + */ + +function hasListeners (emitter, type) { + var count = typeof emitter.listenerCount !== 'function' + ? emitter.listeners(type).length + : emitter.listenerCount(type) + + return count > 0 +} + +/** + * Determine if the response headers have been sent. + * + * @param {object} res + * @returns {boolean} + * @private + */ + +function headersSent (res) { + return typeof res.headersSent !== 'boolean' + ? Boolean(res._header) + : res.headersSent +} + +/** + * Normalize the index option into an array. + * + * @param {boolean|string|array} val + * @param {string} name + * @private + */ + +function normalizeList (val, name) { + var list = [].concat(val || []) + + for (var i = 0; i < list.length; i++) { + if (typeof list[i] !== 'string') { + throw new TypeError(name + ' must be array of strings or false') + } + } + + return list +} + +/** + * Parse an HTTP Date into a number. + * + * @param {string} date + * @private + */ + +function parseHttpDate (date) { + var timestamp = date && Date.parse(date) + + return typeof timestamp === 'number' + ? timestamp + : NaN +} + +/** + * Parse a HTTP token list. + * + * @param {string} str + * @private + */ + +function parseTokenList (str) { + var end = 0 + var list = [] + var start = 0 + + // gather tokens + for (var i = 0, len = str.length; i < len; i++) { + switch (str.charCodeAt(i)) { + case 0x20: /* */ + if (start === end) { + start = end = i + 1 + } + break + case 0x2c: /* , */ + list.push(str.substring(start, end)) + start = end = i + 1 + break + default: + end = i + 1 + break + } + } + + // final token + list.push(str.substring(start, end)) + + return list +} + +/** + * Set an object of headers on a response. + * + * @param {object} res + * @param {object} headers + * @private + */ + +function setHeaders (res, headers) { + var keys = Object.keys(headers) + + for (var i = 0; i < keys.length; i++) { + var key = keys[i] + res.setHeader(key, headers[key]) + } +} diff --git a/homework8/project_express/node_modules/send/node_modules/ms/index.js b/homework8/project_express/node_modules/send/node_modules/ms/index.js new file mode 100644 index 0000000..7229750 --- /dev/null +++ b/homework8/project_express/node_modules/send/node_modules/ms/index.js @@ -0,0 +1,162 @@ +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var w = d * 7; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + +module.exports = function(val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse(val); + } else if (type === 'number' && isNaN(val) === false) { + return options.long ? fmtLong(val) : fmtShort(val); + } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^((?:\d+)?\-?\d?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'weeks': + case 'week': + case 'w': + return n * w; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtShort(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return Math.round(ms / d) + 'd'; + } + if (msAbs >= h) { + return Math.round(ms / h) + 'h'; + } + if (msAbs >= m) { + return Math.round(ms / m) + 'm'; + } + if (msAbs >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtLong(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return plural(ms, msAbs, d, 'day'); + } + if (msAbs >= h) { + return plural(ms, msAbs, h, 'hour'); + } + if (msAbs >= m) { + return plural(ms, msAbs, m, 'minute'); + } + if (msAbs >= s) { + return plural(ms, msAbs, s, 'second'); + } + return ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, msAbs, n, name) { + var isPlural = msAbs >= n * 1.5; + return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : ''); +} diff --git a/homework8/project_express/node_modules/send/node_modules/ms/license.md b/homework8/project_express/node_modules/send/node_modules/ms/license.md new file mode 100644 index 0000000..69b6125 --- /dev/null +++ b/homework8/project_express/node_modules/send/node_modules/ms/license.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Zeit, Inc. + +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/homework8/project_express/node_modules/send/node_modules/ms/package.json b/homework8/project_express/node_modules/send/node_modules/ms/package.json new file mode 100644 index 0000000..dbff5cf --- /dev/null +++ b/homework8/project_express/node_modules/send/node_modules/ms/package.json @@ -0,0 +1,69 @@ +{ + "_from": "ms@2.1.1", + "_id": "ms@2.1.1", + "_inBundle": false, + "_integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "_location": "/send/ms", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "ms@2.1.1", + "name": "ms", + "escapedName": "ms", + "rawSpec": "2.1.1", + "saveSpec": null, + "fetchSpec": "2.1.1" + }, + "_requiredBy": [ + "/send" + ], + "_resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "_shasum": "30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a", + "_spec": "ms@2.1.1", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\send", + "bugs": { + "url": "https://github.com/zeit/ms/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Tiny millisecond conversion utility", + "devDependencies": { + "eslint": "4.12.1", + "expect.js": "0.3.1", + "husky": "0.14.3", + "lint-staged": "5.0.0", + "mocha": "4.0.1" + }, + "eslintConfig": { + "extends": "eslint:recommended", + "env": { + "node": true, + "es6": true + } + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/zeit/ms#readme", + "license": "MIT", + "lint-staged": { + "*.js": [ + "npm run lint", + "prettier --single-quote --write", + "git add" + ] + }, + "main": "./index", + "name": "ms", + "repository": { + "type": "git", + "url": "git+https://github.com/zeit/ms.git" + }, + "scripts": { + "lint": "eslint lib/* bin/*", + "precommit": "lint-staged", + "test": "mocha tests.js" + }, + "version": "2.1.1" +} diff --git a/homework8/project_express/node_modules/send/node_modules/ms/readme.md b/homework8/project_express/node_modules/send/node_modules/ms/readme.md new file mode 100644 index 0000000..bb76729 --- /dev/null +++ b/homework8/project_express/node_modules/send/node_modules/ms/readme.md @@ -0,0 +1,60 @@ +# ms + +[![Build Status](https://travis-ci.org/zeit/ms.svg?branch=master)](https://travis-ci.org/zeit/ms) +[![Slack Channel](http://zeit-slackin.now.sh/badge.svg)](https://zeit.chat/) + +Use this package to easily convert various time formats to milliseconds. + +## Examples + +```js +ms('2 days') // 172800000 +ms('1d') // 86400000 +ms('10h') // 36000000 +ms('2.5 hrs') // 9000000 +ms('2h') // 7200000 +ms('1m') // 60000 +ms('5s') // 5000 +ms('1y') // 31557600000 +ms('100') // 100 +ms('-3 days') // -259200000 +ms('-1h') // -3600000 +ms('-200') // -200 +``` + +### Convert from Milliseconds + +```js +ms(60000) // "1m" +ms(2 * 60000) // "2m" +ms(-3 * 60000) // "-3m" +ms(ms('10 hours')) // "10h" +``` + +### Time Format Written-Out + +```js +ms(60000, { long: true }) // "1 minute" +ms(2 * 60000, { long: true }) // "2 minutes" +ms(-3 * 60000, { long: true }) // "-3 minutes" +ms(ms('10 hours'), { long: true }) // "10 hours" +``` + +## Features + +- Works both in [Node.js](https://nodejs.org) and in the browser +- If a number is supplied to `ms`, a string with a unit is returned +- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`) +- If you pass a string with a number and a valid unit, the number of equivalent milliseconds is returned + +## Related Packages + +- [ms.macro](https://github.com/knpwrs/ms.macro) - Run `ms` as a macro at build-time. + +## Caught a Bug? + +1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device +2. Link the package to the global module directory: `npm link` +3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, Node.js will now use your clone of ms! + +As always, you can run the tests using: `npm test` diff --git a/homework8/project_express/node_modules/send/package.json b/homework8/project_express/node_modules/send/package.json new file mode 100644 index 0000000..4a6d66f --- /dev/null +++ b/homework8/project_express/node_modules/send/package.json @@ -0,0 +1,106 @@ +{ + "_from": "send@0.17.1", + "_id": "send@0.17.1", + "_inBundle": false, + "_integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "_location": "/send", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "send@0.17.1", + "name": "send", + "escapedName": "send", + "rawSpec": "0.17.1", + "saveSpec": null, + "fetchSpec": "0.17.1" + }, + "_requiredBy": [ + "/express", + "/serve-static" + ], + "_resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "_shasum": "c1d8b059f7900f7466dd4938bdc44e11ddb376c8", + "_spec": "send@0.17.1", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\express", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "bugs": { + "url": "https://github.com/pillarjs/send/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "James Wyatt Cready", + "email": "jcready@gmail.com" + }, + { + "name": "Jesús Leganés Combarro", + "email": "piranna@gmail.com" + } + ], + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "deprecated": false, + "description": "Better streaming static file server with Range and conditional-GET support", + "devDependencies": { + "after": "0.8.2", + "eslint": "5.16.0", + "eslint-config-standard": "12.0.0", + "eslint-plugin-import": "2.17.2", + "eslint-plugin-markdown": "1.0.0", + "eslint-plugin-node": "8.0.1", + "eslint-plugin-promise": "4.1.1", + "eslint-plugin-standard": "4.0.0", + "istanbul": "0.4.5", + "mocha": "6.1.4", + "supertest": "4.0.2" + }, + "engines": { + "node": ">= 0.8.0" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "README.md", + "index.js" + ], + "homepage": "https://github.com/pillarjs/send#readme", + "keywords": [ + "static", + "file", + "server" + ], + "license": "MIT", + "name": "send", + "repository": { + "type": "git", + "url": "git+https://github.com/pillarjs/send.git" + }, + "scripts": { + "lint": "eslint --plugin markdown --ext js,md .", + "test": "mocha --check-leaks --reporter spec --bail", + "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --check-leaks --reporter spec", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --check-leaks --reporter dot" + }, + "version": "0.17.1" +} diff --git a/homework8/project_express/node_modules/serve-static/HISTORY.md b/homework8/project_express/node_modules/serve-static/HISTORY.md new file mode 100644 index 0000000..7203e4f --- /dev/null +++ b/homework8/project_express/node_modules/serve-static/HISTORY.md @@ -0,0 +1,451 @@ +1.14.1 / 2019-05-10 +=================== + + * Set stricter CSP header in redirect response + * deps: send@0.17.1 + - deps: range-parser@~1.2.1 + +1.14.0 / 2019-05-07 +=================== + + * deps: parseurl@~1.3.3 + * deps: send@0.17.0 + - deps: http-errors@~1.7.2 + - deps: mime@1.6.0 + - deps: ms@2.1.1 + - deps: statuses@~1.5.0 + - perf: remove redundant `path.normalize` call + +1.13.2 / 2018-02-07 +=================== + + * Fix incorrect end tag in redirects + * deps: encodeurl@~1.0.2 + - Fix encoding `%` as last character + * deps: send@0.16.2 + - deps: depd@~1.1.2 + - deps: encodeurl@~1.0.2 + - deps: statuses@~1.4.0 + +1.13.1 / 2017-09-29 +=================== + + * Fix regression when `root` is incorrectly set to a file + * deps: send@0.16.1 + +1.13.0 / 2017-09-27 +=================== + + * deps: send@0.16.0 + - Add 70 new types for file extensions + - Add `immutable` option + - Fix missing `` in default error & redirects + - Set charset as "UTF-8" for .js and .json + - Use instance methods on steam to check for listeners + - deps: mime@1.4.1 + - perf: improve path validation speed + +1.12.6 / 2017-09-22 +=================== + + * deps: send@0.15.6 + - deps: debug@2.6.9 + - perf: improve `If-Match` token parsing + * perf: improve slash collapsing + +1.12.5 / 2017-09-21 +=================== + + * deps: parseurl@~1.3.2 + - perf: reduce overhead for full URLs + - perf: unroll the "fast-path" `RegExp` + * deps: send@0.15.5 + - Fix handling of modified headers with invalid dates + - deps: etag@~1.8.1 + - deps: fresh@0.5.2 + +1.12.4 / 2017-08-05 +=================== + + * deps: send@0.15.4 + - deps: debug@2.6.8 + - deps: depd@~1.1.1 + - deps: http-errors@~1.6.2 + +1.12.3 / 2017-05-16 +=================== + + * deps: send@0.15.3 + - deps: debug@2.6.7 + +1.12.2 / 2017-04-26 +=================== + + * deps: send@0.15.2 + - deps: debug@2.6.4 + +1.12.1 / 2017-03-04 +=================== + + * deps: send@0.15.1 + - Fix issue when `Date.parse` does not return `NaN` on invalid date + - Fix strict violation in broken environments + +1.12.0 / 2017-02-25 +=================== + + * Send complete HTML document in redirect response + * Set default CSP header in redirect response + * deps: send@0.15.0 + - Fix false detection of `no-cache` request directive + - Fix incorrect result when `If-None-Match` has both `*` and ETags + - Fix weak `ETag` matching to match spec + - Remove usage of `res._headers` private field + - Support `If-Match` and `If-Unmodified-Since` headers + - Use `res.getHeaderNames()` when available + - Use `res.headersSent` when available + - deps: debug@2.6.1 + - deps: etag@~1.8.0 + - deps: fresh@0.5.0 + - deps: http-errors@~1.6.1 + +1.11.2 / 2017-01-23 +=================== + + * deps: send@0.14.2 + - deps: http-errors@~1.5.1 + - deps: ms@0.7.2 + - deps: statuses@~1.3.1 + +1.11.1 / 2016-06-10 +=================== + + * Fix redirect error when `req.url` contains raw non-URL characters + * deps: send@0.14.1 + +1.11.0 / 2016-06-07 +=================== + + * Use status code 301 for redirects + * deps: send@0.14.0 + - Add `acceptRanges` option + - Add `cacheControl` option + - Attempt to combine multiple ranges into single range + - Correctly inherit from `Stream` class + - Fix `Content-Range` header in 416 responses when using `start`/`end` options + - Fix `Content-Range` header missing from default 416 responses + - Ignore non-byte `Range` headers + - deps: http-errors@~1.5.0 + - deps: range-parser@~1.2.0 + - deps: statuses@~1.3.0 + - perf: remove argument reassignment + +1.10.3 / 2016-05-30 +=================== + + * deps: send@0.13.2 + - Fix invalid `Content-Type` header when `send.mime.default_type` unset + +1.10.2 / 2016-01-19 +=================== + + * deps: parseurl@~1.3.1 + - perf: enable strict mode + +1.10.1 / 2016-01-16 +=================== + + * deps: escape-html@~1.0.3 + - perf: enable strict mode + - perf: optimize string replacement + - perf: use faster string coercion + * deps: send@0.13.1 + - deps: depd@~1.1.0 + - deps: destroy@~1.0.4 + - deps: escape-html@~1.0.3 + - deps: range-parser@~1.0.3 + +1.10.0 / 2015-06-17 +=================== + + * Add `fallthrough` option + - Allows declaring this middleware is the final destination + - Provides better integration with Express patterns + * Fix reading options from options prototype + * Improve the default redirect response headers + * deps: escape-html@1.0.2 + * deps: send@0.13.0 + - Allow Node.js HTTP server to set `Date` response header + - Fix incorrectly removing `Content-Location` on 304 response + - Improve the default redirect response headers + - Send appropriate headers on default error response + - Use `http-errors` for standard emitted errors + - Use `statuses` instead of `http` module for status messages + - deps: escape-html@1.0.2 + - deps: etag@~1.7.0 + - deps: fresh@0.3.0 + - deps: on-finished@~2.3.0 + - perf: enable strict mode + - perf: remove unnecessary array allocations + * perf: enable strict mode + * perf: remove argument reassignment + +1.9.3 / 2015-05-14 +================== + + * deps: send@0.12.3 + - deps: debug@~2.2.0 + - deps: depd@~1.0.1 + - deps: etag@~1.6.0 + - deps: ms@0.7.1 + - deps: on-finished@~2.2.1 + +1.9.2 / 2015-03-14 +================== + + * deps: send@0.12.2 + - Throw errors early for invalid `extensions` or `index` options + - deps: debug@~2.1.3 + +1.9.1 / 2015-02-17 +================== + + * deps: send@0.12.1 + - Fix regression sending zero-length files + +1.9.0 / 2015-02-16 +================== + + * deps: send@0.12.0 + - Always read the stat size from the file + - Fix mutating passed-in `options` + - deps: mime@1.3.4 + +1.8.1 / 2015-01-20 +================== + + * Fix redirect loop in Node.js 0.11.14 + * deps: send@0.11.1 + - Fix root path disclosure + +1.8.0 / 2015-01-05 +================== + + * deps: send@0.11.0 + - deps: debug@~2.1.1 + - deps: etag@~1.5.1 + - deps: ms@0.7.0 + - deps: on-finished@~2.2.0 + +1.7.2 / 2015-01-02 +================== + + * Fix potential open redirect when mounted at root + +1.7.1 / 2014-10-22 +================== + + * deps: send@0.10.1 + - deps: on-finished@~2.1.1 + +1.7.0 / 2014-10-15 +================== + + * deps: send@0.10.0 + - deps: debug@~2.1.0 + - deps: depd@~1.0.0 + - deps: etag@~1.5.0 + +1.6.5 / 2015-02-04 +================== + + * Fix potential open redirect when mounted at root + - Back-ported from v1.7.2 + +1.6.4 / 2014-10-08 +================== + + * Fix redirect loop when index file serving disabled + +1.6.3 / 2014-09-24 +================== + + * deps: send@0.9.3 + - deps: etag@~1.4.0 + +1.6.2 / 2014-09-15 +================== + + * deps: send@0.9.2 + - deps: depd@0.4.5 + - deps: etag@~1.3.1 + - deps: range-parser@~1.0.2 + +1.6.1 / 2014-09-07 +================== + + * deps: send@0.9.1 + - deps: fresh@0.2.4 + +1.6.0 / 2014-09-07 +================== + + * deps: send@0.9.0 + - Add `lastModified` option + - Use `etag` to generate `ETag` header + - deps: debug@~2.0.0 + +1.5.4 / 2014-09-04 +================== + + * deps: send@0.8.5 + - Fix a path traversal issue when using `root` + - Fix malicious path detection for empty string path + +1.5.3 / 2014-08-17 +================== + + * deps: send@0.8.3 + +1.5.2 / 2014-08-14 +================== + + * deps: send@0.8.2 + - Work around `fd` leak in Node.js 0.10 for `fs.ReadStream` + +1.5.1 / 2014-08-09 +================== + + * Fix parsing of weird `req.originalUrl` values + * deps: parseurl@~1.3.0 + * deps: utils-merge@1.0.0 + +1.5.0 / 2014-08-05 +================== + + * deps: send@0.8.1 + - Add `extensions` option + +1.4.4 / 2014-08-04 +================== + + * deps: send@0.7.4 + - Fix serving index files without root dir + +1.4.3 / 2014-07-29 +================== + + * deps: send@0.7.3 + - Fix incorrect 403 on Windows and Node.js 0.11 + +1.4.2 / 2014-07-27 +================== + + * deps: send@0.7.2 + - deps: depd@0.4.4 + +1.4.1 / 2014-07-26 +================== + + * deps: send@0.7.1 + - deps: depd@0.4.3 + +1.4.0 / 2014-07-21 +================== + + * deps: parseurl@~1.2.0 + - Cache URLs based on original value + - Remove no-longer-needed URL mis-parse work-around + - Simplify the "fast-path" `RegExp` + * deps: send@0.7.0 + - Add `dotfiles` option + - deps: debug@1.0.4 + - deps: depd@0.4.2 + +1.3.2 / 2014-07-11 +================== + + * deps: send@0.6.0 + - Cap `maxAge` value to 1 year + - deps: debug@1.0.3 + +1.3.1 / 2014-07-09 +================== + + * deps: parseurl@~1.1.3 + - faster parsing of href-only URLs + +1.3.0 / 2014-06-28 +================== + + * Add `setHeaders` option + * Include HTML link in redirect response + * deps: send@0.5.0 + - Accept string for `maxAge` (converted by `ms`) + +1.2.3 / 2014-06-11 +================== + + * deps: send@0.4.3 + - Do not throw un-catchable error on file open race condition + - Use `escape-html` for HTML escaping + - deps: debug@1.0.2 + - deps: finished@1.2.2 + - deps: fresh@0.2.2 + +1.2.2 / 2014-06-09 +================== + + * deps: send@0.4.2 + - fix "event emitter leak" warnings + - deps: debug@1.0.1 + - deps: finished@1.2.1 + +1.2.1 / 2014-06-02 +================== + + * use `escape-html` for escaping + * deps: send@0.4.1 + - Send `max-age` in `Cache-Control` in correct format + +1.2.0 / 2014-05-29 +================== + + * deps: send@0.4.0 + - Calculate ETag with md5 for reduced collisions + - Fix wrong behavior when index file matches directory + - Ignore stream errors after request ends + - Skip directories in index file search + - deps: debug@0.8.1 + +1.1.0 / 2014-04-24 +================== + + * Accept options directly to `send` module + * deps: send@0.3.0 + +1.0.4 / 2014-04-07 +================== + + * Resolve relative paths at middleware setup + * Use parseurl to parse the URL from request + +1.0.3 / 2014-03-20 +================== + + * Do not rely on connect-like environments + +1.0.2 / 2014-03-06 +================== + + * deps: send@0.2.0 + +1.0.1 / 2014-03-05 +================== + + * Add mime export for back-compat + +1.0.0 / 2014-03-05 +================== + + * Genesis from `connect` diff --git a/homework8/project_express/node_modules/serve-static/LICENSE b/homework8/project_express/node_modules/serve-static/LICENSE new file mode 100644 index 0000000..cbe62e8 --- /dev/null +++ b/homework8/project_express/node_modules/serve-static/LICENSE @@ -0,0 +1,25 @@ +(The MIT License) + +Copyright (c) 2010 Sencha Inc. +Copyright (c) 2011 LearnBoost +Copyright (c) 2011 TJ Holowaychuk +Copyright (c) 2014-2016 Douglas Christopher Wilson + +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/homework8/project_express/node_modules/serve-static/README.md b/homework8/project_express/node_modules/serve-static/README.md new file mode 100644 index 0000000..7cce428 --- /dev/null +++ b/homework8/project_express/node_modules/serve-static/README.md @@ -0,0 +1,259 @@ +# serve-static + +[![NPM Version][npm-version-image]][npm-url] +[![NPM Downloads][npm-downloads-image]][npm-url] +[![Linux Build][travis-image]][travis-url] +[![Windows Build][appveyor-image]][appveyor-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +## Install + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```sh +$ npm install serve-static +``` + +## API + + + +```js +var serveStatic = require('serve-static') +``` + +### serveStatic(root, options) + +Create a new middleware function to serve files from within a given root +directory. The file to serve will be determined by combining `req.url` +with the provided root directory. When a file is not found, instead of +sending a 404 response, this module will instead call `next()` to move on +to the next middleware, allowing for stacking and fall-backs. + +#### Options + +##### acceptRanges + +Enable or disable accepting ranged requests, defaults to true. +Disabling this will not send `Accept-Ranges` and ignore the contents +of the `Range` request header. + +##### cacheControl + +Enable or disable setting `Cache-Control` response header, defaults to +true. Disabling this will ignore the `immutable` and `maxAge` options. + +##### dotfiles + + Set how "dotfiles" are treated when encountered. A dotfile is a file +or directory that begins with a dot ("."). Note this check is done on +the path itself without checking if the path actually exists on the +disk. If `root` is specified, only the dotfiles above the root are +checked (i.e. the root itself can be within a dotfile when set +to "deny"). + + - `'allow'` No special treatment for dotfiles. + - `'deny'` Deny a request for a dotfile and 403/`next()`. + - `'ignore'` Pretend like the dotfile does not exist and 404/`next()`. + +The default value is similar to `'ignore'`, with the exception that this +default will not ignore the files within a directory that begins with a dot. + +##### etag + +Enable or disable etag generation, defaults to true. + +##### extensions + +Set file extension fallbacks. When set, if a file is not found, the given +extensions will be added to the file name and search for. The first that +exists will be served. Example: `['html', 'htm']`. + +The default value is `false`. + +##### fallthrough + +Set the middleware to have client errors fall-through as just unhandled +requests, otherwise forward a client error. The difference is that client +errors like a bad request or a request to a non-existent file will cause +this middleware to simply `next()` to your next middleware when this value +is `true`. When this value is `false`, these errors (even 404s), will invoke +`next(err)`. + +Typically `true` is desired such that multiple physical directories can be +mapped to the same web address or for routes to fill in non-existent files. + +The value `false` can be used if this middleware is mounted at a path that +is designed to be strictly a single file system directory, which allows for +short-circuiting 404s for less overhead. This middleware will also reply to +all methods. + +The default value is `true`. + +##### immutable + +Enable or disable the `immutable` directive in the `Cache-Control` response +header, defaults to `false`. If set to `true`, the `maxAge` option should +also be specified to enable caching. The `immutable` directive will prevent +supported clients from making conditional requests during the life of the +`maxAge` option to check if the file has changed. + +##### index + +By default this module will send "index.html" files in response to a request +on a directory. To disable this set `false` or to supply a new index pass a +string or an array in preferred order. + +##### lastModified + +Enable or disable `Last-Modified` header, defaults to true. Uses the file +system's last modified value. + +##### maxAge + +Provide a max-age in milliseconds for http caching, defaults to 0. This +can also be a string accepted by the [ms](https://www.npmjs.org/package/ms#readme) +module. + +##### redirect + +Redirect to trailing "/" when the pathname is a dir. Defaults to `true`. + +##### setHeaders + +Function to set custom headers on response. Alterations to the headers need to +occur synchronously. The function is called as `fn(res, path, stat)`, where +the arguments are: + + - `res` the response object + - `path` the file path that is being sent + - `stat` the stat object of the file that is being sent + +## Examples + +### Serve files with vanilla node.js http server + +```js +var finalhandler = require('finalhandler') +var http = require('http') +var serveStatic = require('serve-static') + +// Serve up public/ftp folder +var serve = serveStatic('public/ftp', { 'index': ['index.html', 'index.htm'] }) + +// Create server +var server = http.createServer(function onRequest (req, res) { + serve(req, res, finalhandler(req, res)) +}) + +// Listen +server.listen(3000) +``` + +### Serve all files as downloads + +```js +var contentDisposition = require('content-disposition') +var finalhandler = require('finalhandler') +var http = require('http') +var serveStatic = require('serve-static') + +// Serve up public/ftp folder +var serve = serveStatic('public/ftp', { + 'index': false, + 'setHeaders': setHeaders +}) + +// Set header to force download +function setHeaders (res, path) { + res.setHeader('Content-Disposition', contentDisposition(path)) +} + +// Create server +var server = http.createServer(function onRequest (req, res) { + serve(req, res, finalhandler(req, res)) +}) + +// Listen +server.listen(3000) +``` + +### Serving using express + +#### Simple + +This is a simple example of using Express. + +```js +var express = require('express') +var serveStatic = require('serve-static') + +var app = express() + +app.use(serveStatic('public/ftp', { 'index': ['default.html', 'default.htm'] })) +app.listen(3000) +``` + +#### Multiple roots + +This example shows a simple way to search through multiple directories. +Files are look for in `public-optimized/` first, then `public/` second as +a fallback. + +```js +var express = require('express') +var path = require('path') +var serveStatic = require('serve-static') + +var app = express() + +app.use(serveStatic(path.join(__dirname, 'public-optimized'))) +app.use(serveStatic(path.join(__dirname, 'public'))) +app.listen(3000) +``` + +#### Different settings for paths + +This example shows how to set a different max age depending on the served +file type. In this example, HTML files are not cached, while everything else +is for 1 day. + +```js +var express = require('express') +var path = require('path') +var serveStatic = require('serve-static') + +var app = express() + +app.use(serveStatic(path.join(__dirname, 'public'), { + maxAge: '1d', + setHeaders: setCustomCacheControl +})) + +app.listen(3000) + +function setCustomCacheControl (res, path) { + if (serveStatic.mime.lookup(path) === 'text/html') { + // Custom Cache-Control for HTML files + res.setHeader('Cache-Control', 'public, max-age=0') + } +} +``` + +## License + +[MIT](LICENSE) + +[appveyor-image]: https://badgen.net/appveyor/ci/dougwilson/serve-static/master?label=windows +[appveyor-url]: https://ci.appveyor.com/project/dougwilson/serve-static +[coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/serve-static/master +[coveralls-url]: https://coveralls.io/r/expressjs/serve-static?branch=master +[node-image]: https://badgen.net/npm/node/serve-static +[node-url]: https://nodejs.org/en/download/ +[npm-downloads-image]: https://badgen.net/npm/dm/serve-static +[npm-url]: https://npmjs.org/package/serve-static +[npm-version-image]: https://badgen.net/npm/v/serve-static +[travis-image]: https://badgen.net/travis/expressjs/serve-static/master?label=linux +[travis-url]: https://travis-ci.org/expressjs/serve-static diff --git a/homework8/project_express/node_modules/serve-static/index.js b/homework8/project_express/node_modules/serve-static/index.js new file mode 100644 index 0000000..b7d3984 --- /dev/null +++ b/homework8/project_express/node_modules/serve-static/index.js @@ -0,0 +1,210 @@ +/*! + * serve-static + * Copyright(c) 2010 Sencha Inc. + * Copyright(c) 2011 TJ Holowaychuk + * Copyright(c) 2014-2016 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var encodeUrl = require('encodeurl') +var escapeHtml = require('escape-html') +var parseUrl = require('parseurl') +var resolve = require('path').resolve +var send = require('send') +var url = require('url') + +/** + * Module exports. + * @public + */ + +module.exports = serveStatic +module.exports.mime = send.mime + +/** + * @param {string} root + * @param {object} [options] + * @return {function} + * @public + */ + +function serveStatic (root, options) { + if (!root) { + throw new TypeError('root path required') + } + + if (typeof root !== 'string') { + throw new TypeError('root path must be a string') + } + + // copy options object + var opts = Object.create(options || null) + + // fall-though + var fallthrough = opts.fallthrough !== false + + // default redirect + var redirect = opts.redirect !== false + + // headers listener + var setHeaders = opts.setHeaders + + if (setHeaders && typeof setHeaders !== 'function') { + throw new TypeError('option setHeaders must be function') + } + + // setup options for send + opts.maxage = opts.maxage || opts.maxAge || 0 + opts.root = resolve(root) + + // construct directory listener + var onDirectory = redirect + ? createRedirectDirectoryListener() + : createNotFoundDirectoryListener() + + return function serveStatic (req, res, next) { + if (req.method !== 'GET' && req.method !== 'HEAD') { + if (fallthrough) { + return next() + } + + // method not allowed + res.statusCode = 405 + res.setHeader('Allow', 'GET, HEAD') + res.setHeader('Content-Length', '0') + res.end() + return + } + + var forwardError = !fallthrough + var originalUrl = parseUrl.original(req) + var path = parseUrl(req).pathname + + // make sure redirect occurs at mount + if (path === '/' && originalUrl.pathname.substr(-1) !== '/') { + path = '' + } + + // create send stream + var stream = send(req, path, opts) + + // add directory handler + stream.on('directory', onDirectory) + + // add headers listener + if (setHeaders) { + stream.on('headers', setHeaders) + } + + // add file listener for fallthrough + if (fallthrough) { + stream.on('file', function onFile () { + // once file is determined, always forward error + forwardError = true + }) + } + + // forward errors + stream.on('error', function error (err) { + if (forwardError || !(err.statusCode < 500)) { + next(err) + return + } + + next() + }) + + // pipe + stream.pipe(res) + } +} + +/** + * Collapse all leading slashes into a single slash + * @private + */ +function collapseLeadingSlashes (str) { + for (var i = 0; i < str.length; i++) { + if (str.charCodeAt(i) !== 0x2f /* / */) { + break + } + } + + return i > 1 + ? '/' + str.substr(i) + : str +} + +/** + * Create a minimal HTML document. + * + * @param {string} title + * @param {string} body + * @private + */ + +function createHtmlDocument (title, body) { + return '\n' + + '\n' + + '\n' + + '\n' + + '' + title + '\n' + + '\n' + + '\n' + + '
' + body + '
\n' + + '\n' + + '\n' +} + +/** + * Create a directory listener that just 404s. + * @private + */ + +function createNotFoundDirectoryListener () { + return function notFound () { + this.error(404) + } +} + +/** + * Create a directory listener that performs a redirect. + * @private + */ + +function createRedirectDirectoryListener () { + return function redirect (res) { + if (this.hasTrailingSlash()) { + this.error(404) + return + } + + // get original URL + var originalUrl = parseUrl.original(this.req) + + // append trailing slash + originalUrl.path = null + originalUrl.pathname = collapseLeadingSlashes(originalUrl.pathname + '/') + + // reformat the URL + var loc = encodeUrl(url.format(originalUrl)) + var doc = createHtmlDocument('Redirecting', 'Redirecting to ' + + escapeHtml(loc) + '') + + // send redirect response + res.statusCode = 301 + res.setHeader('Content-Type', 'text/html; charset=UTF-8') + res.setHeader('Content-Length', Buffer.byteLength(doc)) + res.setHeader('Content-Security-Policy', "default-src 'none'") + res.setHeader('X-Content-Type-Options', 'nosniff') + res.setHeader('Location', loc) + res.end(doc) + } +} diff --git a/homework8/project_express/node_modules/serve-static/package.json b/homework8/project_express/node_modules/serve-static/package.json new file mode 100644 index 0000000..0a0a8aa --- /dev/null +++ b/homework8/project_express/node_modules/serve-static/package.json @@ -0,0 +1,77 @@ +{ + "_from": "serve-static@1.14.1", + "_id": "serve-static@1.14.1", + "_inBundle": false, + "_integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "_location": "/serve-static", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "serve-static@1.14.1", + "name": "serve-static", + "escapedName": "serve-static", + "rawSpec": "1.14.1", + "saveSpec": null, + "fetchSpec": "1.14.1" + }, + "_requiredBy": [ + "/express" + ], + "_resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "_shasum": "666e636dc4f010f7ef29970a88a674320898b2f9", + "_spec": "serve-static@1.14.1", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\express", + "author": { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + "bugs": { + "url": "https://github.com/expressjs/serve-static/issues" + }, + "bundleDependencies": false, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "deprecated": false, + "description": "Serve static files", + "devDependencies": { + "eslint": "5.16.0", + "eslint-config-standard": "12.0.0", + "eslint-plugin-import": "2.17.2", + "eslint-plugin-markdown": "1.0.0", + "eslint-plugin-node": "8.0.1", + "eslint-plugin-promise": "4.1.1", + "eslint-plugin-standard": "4.0.0", + "istanbul": "0.4.5", + "mocha": "6.1.4", + "safe-buffer": "5.1.2", + "supertest": "4.0.2" + }, + "engines": { + "node": ">= 0.8.0" + }, + "files": [ + "LICENSE", + "HISTORY.md", + "index.js" + ], + "homepage": "https://github.com/expressjs/serve-static#readme", + "license": "MIT", + "name": "serve-static", + "repository": { + "type": "git", + "url": "git+https://github.com/expressjs/serve-static.git" + }, + "scripts": { + "lint": "eslint --plugin markdown --ext js,md .", + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "version": "node scripts/version-history.js && git add HISTORY.md" + }, + "version": "1.14.1" +} diff --git a/homework8/project_express/node_modules/setprototypeof/LICENSE b/homework8/project_express/node_modules/setprototypeof/LICENSE new file mode 100644 index 0000000..61afa2f --- /dev/null +++ b/homework8/project_express/node_modules/setprototypeof/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2015, Wes Todd + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/homework8/project_express/node_modules/setprototypeof/README.md b/homework8/project_express/node_modules/setprototypeof/README.md new file mode 100644 index 0000000..f120044 --- /dev/null +++ b/homework8/project_express/node_modules/setprototypeof/README.md @@ -0,0 +1,31 @@ +# Polyfill for `Object.setPrototypeOf` + +[![NPM Version](https://img.shields.io/npm/v/setprototypeof.svg)](https://npmjs.org/package/setprototypeof) +[![NPM Downloads](https://img.shields.io/npm/dm/setprototypeof.svg)](https://npmjs.org/package/setprototypeof) +[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](https://github.com/standard/standard) + +A simple cross platform implementation to set the prototype of an instianted object. Supports all modern browsers and at least back to IE8. + +## Usage: + +``` +$ npm install --save setprototypeof +``` + +```javascript +var setPrototypeOf = require('setprototypeof') + +var obj = {} +setPrototypeOf(obj, { + foo: function () { + return 'bar' + } +}) +obj.foo() // bar +``` + +TypeScript is also supported: + +```typescript +import setPrototypeOf = require('setprototypeof') +``` diff --git a/homework8/project_express/node_modules/setprototypeof/index.d.ts b/homework8/project_express/node_modules/setprototypeof/index.d.ts new file mode 100644 index 0000000..f108ecd --- /dev/null +++ b/homework8/project_express/node_modules/setprototypeof/index.d.ts @@ -0,0 +1,2 @@ +declare function setPrototypeOf(o: any, proto: object | null): any; +export = setPrototypeOf; diff --git a/homework8/project_express/node_modules/setprototypeof/index.js b/homework8/project_express/node_modules/setprototypeof/index.js new file mode 100644 index 0000000..81fd5d7 --- /dev/null +++ b/homework8/project_express/node_modules/setprototypeof/index.js @@ -0,0 +1,17 @@ +'use strict' +/* eslint no-proto: 0 */ +module.exports = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array ? setProtoOf : mixinProperties) + +function setProtoOf (obj, proto) { + obj.__proto__ = proto + return obj +} + +function mixinProperties (obj, proto) { + for (var prop in proto) { + if (!obj.hasOwnProperty(prop)) { + obj[prop] = proto[prop] + } + } + return obj +} diff --git a/homework8/project_express/node_modules/setprototypeof/package.json b/homework8/project_express/node_modules/setprototypeof/package.json new file mode 100644 index 0000000..bb3daca --- /dev/null +++ b/homework8/project_express/node_modules/setprototypeof/package.json @@ -0,0 +1,64 @@ +{ + "_from": "setprototypeof@1.1.1", + "_id": "setprototypeof@1.1.1", + "_inBundle": false, + "_integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "_location": "/setprototypeof", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "setprototypeof@1.1.1", + "name": "setprototypeof", + "escapedName": "setprototypeof", + "rawSpec": "1.1.1", + "saveSpec": null, + "fetchSpec": "1.1.1" + }, + "_requiredBy": [ + "/express", + "/http-errors" + ], + "_resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "_shasum": "7e95acb24aa92f5885e0abef5ba131330d4ae683", + "_spec": "setprototypeof@1.1.1", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\express", + "author": { + "name": "Wes Todd" + }, + "bugs": { + "url": "https://github.com/wesleytodd/setprototypeof/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "A small polyfill for Object.setprototypeof", + "devDependencies": { + "mocha": "^5.2.0", + "standard": "^12.0.1" + }, + "homepage": "https://github.com/wesleytodd/setprototypeof", + "keywords": [ + "polyfill", + "object", + "setprototypeof" + ], + "license": "ISC", + "main": "index.js", + "name": "setprototypeof", + "repository": { + "type": "git", + "url": "git+https://github.com/wesleytodd/setprototypeof.git" + }, + "scripts": { + "node010": "NODE_VER=0.10 MOCHA_VER=3 npm run testversion", + "node11": "NODE_VER=11 npm run testversion", + "node4": "NODE_VER=4 npm run testversion", + "node6": "NODE_VER=6 npm run testversion", + "node9": "NODE_VER=9 npm run testversion", + "test": "standard && mocha", + "testallversions": "npm run node010 && npm run node4 && npm run node6 && npm run node9 && npm run node11", + "testversion": "docker run -it --rm -v $(PWD):/usr/src/app -w /usr/src/app node:${NODE_VER} npm install mocha@${MOCHA_VER:-latest} && npm t" + }, + "typings": "index.d.ts", + "version": "1.1.1" +} diff --git a/homework8/project_express/node_modules/setprototypeof/test/index.js b/homework8/project_express/node_modules/setprototypeof/test/index.js new file mode 100644 index 0000000..afeb4dd --- /dev/null +++ b/homework8/project_express/node_modules/setprototypeof/test/index.js @@ -0,0 +1,24 @@ +'use strict' +/* eslint-env mocha */ +/* eslint no-proto: 0 */ +var assert = require('assert') +var setPrototypeOf = require('..') + +describe('setProtoOf(obj, proto)', function () { + it('should merge objects', function () { + var obj = { a: 1, b: 2 } + var proto = { b: 3, c: 4 } + var mergeObj = setPrototypeOf(obj, proto) + + if (Object.getPrototypeOf) { + assert.strictEqual(Object.getPrototypeOf(obj), proto) + } else if ({ __proto__: [] } instanceof Array) { + assert.strictEqual(obj.__proto__, proto) + } else { + assert.strictEqual(obj.a, 1) + assert.strictEqual(obj.b, 2) + assert.strictEqual(obj.c, 4) + } + assert.strictEqual(mergeObj, obj) + }) +}) diff --git a/homework8/project_express/node_modules/simple-update-notifier/LICENSE b/homework8/project_express/node_modules/simple-update-notifier/LICENSE new file mode 100644 index 0000000..1e0b0c1 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Alex Brazier + +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/homework8/project_express/node_modules/simple-update-notifier/README.md b/homework8/project_express/node_modules/simple-update-notifier/README.md new file mode 100644 index 0000000..6061412 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/README.md @@ -0,0 +1,67 @@ +# simple-update-notifier [![GitHub stars](https://img.shields.io/github/stars/alexbrazier/simple-update-notifier?label=Star%20Project&style=social)](https://github.com/alexbrazier/simple-update-notifier/stargazers) + +[![CI](https://github.com/alexbrazier/simple-update-notifier/workflows/Build%20and%20Deploy/badge.svg)](https://github.com/alexbrazier/simple-update-notifier/actions) +[![Dependencies](https://img.shields.io/librariesio/release/npm/simple-update-notifier)](https://www.npmjs.com/package/simple-update-notifier?activeTab=dependencies) +[![npm](https://img.shields.io/npm/v/simple-update-notifier)](https://www.npmjs.com/package/simple-update-notifier) +[![npm bundle size](https://img.shields.io/bundlephobia/min/simple-update-notifier)](https://bundlephobia.com/result?p=simple-update-notifier) +[![npm downloads](https://img.shields.io/npm/dw/simple-update-notifier)](https://www.npmjs.com/package/simple-update-notifier) +[![License](https://img.shields.io/npm/l/simple-update-notifier)](./LICENSE) + +Simple update notifier to check for npm updates for cli applications. + +Demo in terminal showing an update is required + +Checks for updates for an npm module and outputs to the command line if there is one available. The result is cached for the specified time so it doesn't check every time the app runs. + +## Install + +```bash +npm install simple-update-notifier +OR +yarn add simple-update-notifier +``` + +## Usage + +```js +import updateNotifier from 'update-notifier'; +import packageJson from './package.json' assert { type: 'json' }; + +updateNotifier({ pkg: packageJson }); +``` + +### Options + +#### pkg + +Type: `object` + +##### name + +_Required_\ +Type: `string` + +##### version + +_Required_\ +Type: `string` + +#### updateCheckInterval + +Type: `number`\ +Default: `1000 * 60 * 60 * 24` _(1 day)_ +How often to check for updates. + +#### shouldNotifyInNpmScript + +Type: `boolean`\ +Default: `false` + +Allows notification to be shown when running as an npm script. + +#### distTag + +Type: `string`\ +Default: `'latest'` + +Which [dist-tag](https://docs.npmjs.com/adding-dist-tags-to-packages) to use to find the latest version. diff --git a/homework8/project_express/node_modules/simple-update-notifier/build/index.d.ts b/homework8/project_express/node_modules/simple-update-notifier/build/index.d.ts new file mode 100644 index 0000000..36cd5f4 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/build/index.d.ts @@ -0,0 +1,12 @@ +interface IUpdate { + pkg: { + name: string; + version: string; + }; + updateCheckInterval?: number; + shouldNotifyInNpmScript?: boolean; + distTag?: string; + alwaysRun?: boolean; +} +declare const simpleUpdateNotifier: (args: IUpdate) => Promise; +export { simpleUpdateNotifier as default }; diff --git a/homework8/project_express/node_modules/simple-update-notifier/build/index.js b/homework8/project_express/node_modules/simple-update-notifier/build/index.js new file mode 100644 index 0000000..ffa01fa --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/build/index.js @@ -0,0 +1,202 @@ +'use strict'; + +var process$1 = require('process'); +var semver = require('semver'); +var os = require('os'); +var path = require('path'); +var fs = require('fs'); +var https = require('https'); + +function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } + +var process__default = /*#__PURE__*/_interopDefaultLegacy(process$1); +var semver__default = /*#__PURE__*/_interopDefaultLegacy(semver); +var os__default = /*#__PURE__*/_interopDefaultLegacy(os); +var path__default = /*#__PURE__*/_interopDefaultLegacy(path); +var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs); +var https__default = /*#__PURE__*/_interopDefaultLegacy(https); + +/****************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ + +function __awaiter(thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +} + +function __generator(thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +} + +var packageJson = process__default["default"].env.npm_package_json; +var userAgent = process__default["default"].env.npm_config_user_agent; +var isNpm6 = Boolean(userAgent && userAgent.startsWith('npm')); +var isNpm7 = Boolean(packageJson && packageJson.endsWith('package.json')); +var isNpm = isNpm6 || isNpm7; +var isYarn = Boolean(userAgent && userAgent.startsWith('yarn')); +var isNpmOrYarn = isNpm || isYarn; + +var homeDirectory = os__default["default"].homedir(); +var configDir = process.env.XDG_CONFIG_HOME || + path__default["default"].join(homeDirectory, '.config', 'simple-update-notifier'); +var getConfigFile = function (packageName) { + return path__default["default"].join(configDir, "".concat(packageName, ".json")); +}; +var createConfigDir = function () { + if (!fs__default["default"].existsSync(configDir)) { + fs__default["default"].mkdirSync(configDir, { recursive: true }); + } +}; +var getLastUpdate = function (packageName) { + var configFile = getConfigFile(packageName); + try { + if (!fs__default["default"].existsSync(configFile)) { + return undefined; + } + var file = JSON.parse(fs__default["default"].readFileSync(configFile, 'utf8')); + return file.lastUpdateCheck; + } + catch (_a) { + return undefined; + } +}; +var saveLastUpdate = function (packageName) { + var configFile = getConfigFile(packageName); + fs__default["default"].writeFileSync(configFile, JSON.stringify({ lastUpdateCheck: new Date().getTime() })); +}; + +var getDistVersion = function (packageName, distTag) { return __awaiter(void 0, void 0, void 0, function () { + var url; + return __generator(this, function (_a) { + url = "https://registry.npmjs.org/-/package/".concat(packageName, "/dist-tags"); + return [2 /*return*/, new Promise(function (resolve, reject) { + https__default["default"] + .get(url, function (res) { + var body = ''; + res.on('data', function (chunk) { return (body += chunk); }); + res.on('end', function () { + try { + var json = JSON.parse(body); + var version = json[distTag]; + if (!version) { + reject(new Error('Error getting version')); + } + resolve(version); + } + catch (_a) { + reject(new Error('Could not parse version response')); + } + }); + }) + .on('error', function (err) { return reject(err); }); + })]; + }); +}); }; + +var hasNewVersion = function (_a) { + var pkg = _a.pkg, _b = _a.updateCheckInterval, updateCheckInterval = _b === void 0 ? 1000 * 60 * 60 * 24 : _b, _c = _a.distTag, distTag = _c === void 0 ? 'latest' : _c, alwaysRun = _a.alwaysRun; + return __awaiter(void 0, void 0, void 0, function () { + var lastUpdateCheck, latestVersion; + return __generator(this, function (_d) { + switch (_d.label) { + case 0: + createConfigDir(); + lastUpdateCheck = getLastUpdate(pkg.name); + if (!(alwaysRun || + !lastUpdateCheck || + lastUpdateCheck < new Date().getTime() - updateCheckInterval)) return [3 /*break*/, 2]; + return [4 /*yield*/, getDistVersion(pkg.name, distTag)]; + case 1: + latestVersion = _d.sent(); + saveLastUpdate(pkg.name); + if (semver__default["default"].gt(latestVersion, pkg.version)) { + return [2 /*return*/, latestVersion]; + } + return [2 /*return*/, false]; + case 2: return [2 /*return*/, false]; + } + }); + }); +}; + +var borderedText = function (text) { + var lines = text.split('\n'); + var width = Math.max.apply(Math, lines.map(function (l) { return l.length; })); + var res = ["\u250C".concat('─'.repeat(width + 2), "\u2510")]; + for (var _i = 0, lines_1 = lines; _i < lines_1.length; _i++) { + var line = lines_1[_i]; + res.push("\u2502 ".concat(line.padEnd(width), " \u2502")); + } + res.push("\u2514".concat('─'.repeat(width + 2), "\u2518")); + return res.join('\n'); +}; + +var simpleUpdateNotifier = function (args) { return __awaiter(void 0, void 0, void 0, function () { + var latestVersion; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + if (!args.alwaysRun && + (!process.stdout.isTTY || (isNpmOrYarn && !args.shouldNotifyInNpmScript))) { + return [2 /*return*/]; + } + _b.label = 1; + case 1: + _b.trys.push([1, 3, , 4]); + return [4 /*yield*/, hasNewVersion(args)]; + case 2: + latestVersion = _b.sent(); + if (latestVersion) { + console.log(borderedText("New version of ".concat(args.pkg.name, " available!\nCurrent Version: ").concat(args.pkg.version, "\nLatest Version: ").concat(latestVersion))); + } + return [3 /*break*/, 4]; + case 3: + _b.sent(); + return [3 /*break*/, 4]; + case 4: return [2 /*return*/]; + } + }); +}); }; + +module.exports = simpleUpdateNotifier; diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver b/homework8/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver new file mode 100644 index 0000000..77443e7 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver @@ -0,0 +1,12 @@ +#!/bin/sh +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") + +case `uname` in + *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;; +esac + +if [ -x "$basedir/node" ]; then + exec "$basedir/node" "$basedir/../semver/bin/semver.js" "$@" +else + exec node "$basedir/../semver/bin/semver.js" "$@" +fi diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver.cmd b/homework8/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver.cmd new file mode 100644 index 0000000..9913fa9 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver.cmd @@ -0,0 +1,17 @@ +@ECHO off +GOTO start +:find_dp0 +SET dp0=%~dp0 +EXIT /b +:start +SETLOCAL +CALL :find_dp0 + +IF EXIST "%dp0%\node.exe" ( + SET "_prog=%dp0%\node.exe" +) ELSE ( + SET "_prog=node" + SET PATHEXT=%PATHEXT:;.JS;=;% +) + +endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\semver\bin\semver.js" %* diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver.ps1 b/homework8/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver.ps1 new file mode 100644 index 0000000..314717a --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/.bin/semver.ps1 @@ -0,0 +1,28 @@ +#!/usr/bin/env pwsh +$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent + +$exe="" +if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) { + # Fix case when both the Windows and Linux builds of Node + # are installed in the same directory + $exe=".exe" +} +$ret=0 +if (Test-Path "$basedir/node$exe") { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args + } else { + & "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args + } + $ret=$LASTEXITCODE +} else { + # Support pipeline input + if ($MyInvocation.ExpectingInput) { + $input | & "node$exe" "$basedir/../semver/bin/semver.js" $args + } else { + & "node$exe" "$basedir/../semver/bin/semver.js" $args + } + $ret=$LASTEXITCODE +} +exit $ret diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/CHANGELOG.md b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/CHANGELOG.md new file mode 100644 index 0000000..d366696 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/CHANGELOG.md @@ -0,0 +1,74 @@ +# changes log + +## 6.3.0 + +* Expose the token enum on the exports + +## 6.2.0 + +* Coerce numbers to strings when passed to semver.coerce() +* Add `rtl` option to coerce from right to left + +## 6.1.3 + +* Handle X-ranges properly in includePrerelease mode + +## 6.1.2 + +* Do not throw when testing invalid version strings + +## 6.1.1 + +* Add options support for semver.coerce() +* Handle undefined version passed to Range.test + +## 6.1.0 + +* Add semver.compareBuild function +* Support `*` in semver.intersects + +## 6.0 + +* Fix `intersects` logic. + + This is technically a bug fix, but since it is also a change to behavior + that may require users updating their code, it is marked as a major + version increment. + +## 5.7 + +* Add `minVersion` method + +## 5.6 + +* Move boolean `loose` param to an options object, with + backwards-compatibility protection. +* Add ability to opt out of special prerelease version handling with + the `includePrerelease` option flag. + +## 5.5 + +* Add version coercion capabilities + +## 5.4 + +* Add intersection checking + +## 5.3 + +* Add `minSatisfying` method + +## 5.2 + +* Add `prerelease(v)` that returns prerelease components + +## 5.1 + +* Add Backus-Naur for ranges +* Remove excessively cute inspection methods + +## 5.0 + +* Remove AMD/Browserified build artifacts +* Fix ltr and gtr when using the `*` range +* Fix for range `*` with a prerelease identifier diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/LICENSE b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/LICENSE new file mode 100644 index 0000000..19129e3 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/README.md b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/README.md new file mode 100644 index 0000000..1546458 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/README.md @@ -0,0 +1,499 @@ +semver(1) -- The semantic versioner for npm +=========================================== + +## Install + +```bash +npm install semver +```` + +## Usage + +As a node module: + +```js +const semver = require('semver') + +semver.valid('1.2.3') // '1.2.3' +semver.valid('a.b.c') // null +semver.clean(' =v1.2.3 ') // '1.2.3' +semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true +semver.gt('1.2.3', '9.8.7') // false +semver.lt('1.2.3', '9.8.7') // true +semver.minVersion('>=1.0.0') // '1.0.0' +semver.valid(semver.coerce('v2')) // '2.0.0' +semver.valid(semver.coerce('42.6.7.9.3-alpha')) // '42.6.7' +``` + +As a command-line utility: + +``` +$ semver -h + +A JavaScript implementation of the https://semver.org/ specification +Copyright Isaac Z. Schlueter + +Usage: semver [options] [ [...]] +Prints valid versions sorted by SemVer precedence + +Options: +-r --range + Print versions that match the specified range. + +-i --increment [] + Increment a version by the specified level. Level can + be one of: major, minor, patch, premajor, preminor, + prepatch, or prerelease. Default level is 'patch'. + Only one version may be specified. + +--preid + Identifier to be used to prefix premajor, preminor, + prepatch or prerelease version increments. + +-l --loose + Interpret versions and ranges loosely + +-p --include-prerelease + Always include prerelease versions in range matching + +-c --coerce + Coerce a string into SemVer if possible + (does not imply --loose) + +--rtl + Coerce version strings right to left + +--ltr + Coerce version strings left to right (default) + +Program exits successfully if any valid version satisfies +all supplied ranges, and prints all satisfying versions. + +If no satisfying versions are found, then exits failure. + +Versions are printed in ascending order, so supplying +multiple versions to the utility will just sort them. +``` + +## Versions + +A "version" is described by the `v2.0.0` specification found at +. + +A leading `"="` or `"v"` character is stripped off and ignored. + +## Ranges + +A `version range` is a set of `comparators` which specify versions +that satisfy the range. + +A `comparator` is composed of an `operator` and a `version`. The set +of primitive `operators` is: + +* `<` Less than +* `<=` Less than or equal to +* `>` Greater than +* `>=` Greater than or equal to +* `=` Equal. If no operator is specified, then equality is assumed, + so this operator is optional, but MAY be included. + +For example, the comparator `>=1.2.7` would match the versions +`1.2.7`, `1.2.8`, `2.5.3`, and `1.3.9`, but not the versions `1.2.6` +or `1.1.0`. + +Comparators can be joined by whitespace to form a `comparator set`, +which is satisfied by the **intersection** of all of the comparators +it includes. + +A range is composed of one or more comparator sets, joined by `||`. A +version matches a range if and only if every comparator in at least +one of the `||`-separated comparator sets is satisfied by the version. + +For example, the range `>=1.2.7 <1.3.0` would match the versions +`1.2.7`, `1.2.8`, and `1.2.99`, but not the versions `1.2.6`, `1.3.0`, +or `1.1.0`. + +The range `1.2.7 || >=1.2.9 <2.0.0` would match the versions `1.2.7`, +`1.2.9`, and `1.4.6`, but not the versions `1.2.8` or `2.0.0`. + +### Prerelease Tags + +If a version has a prerelease tag (for example, `1.2.3-alpha.3`) then +it will only be allowed to satisfy comparator sets if at least one +comparator with the same `[major, minor, patch]` tuple also has a +prerelease tag. + +For example, the range `>1.2.3-alpha.3` would be allowed to match the +version `1.2.3-alpha.7`, but it would *not* be satisfied by +`3.4.5-alpha.9`, even though `3.4.5-alpha.9` is technically "greater +than" `1.2.3-alpha.3` according to the SemVer sort rules. The version +range only accepts prerelease tags on the `1.2.3` version. The +version `3.4.5` *would* satisfy the range, because it does not have a +prerelease flag, and `3.4.5` is greater than `1.2.3-alpha.7`. + +The purpose for this behavior is twofold. First, prerelease versions +frequently are updated very quickly, and contain many breaking changes +that are (by the author's design) not yet fit for public consumption. +Therefore, by default, they are excluded from range matching +semantics. + +Second, a user who has opted into using a prerelease version has +clearly indicated the intent to use *that specific* set of +alpha/beta/rc versions. By including a prerelease tag in the range, +the user is indicating that they are aware of the risk. However, it +is still not appropriate to assume that they have opted into taking a +similar risk on the *next* set of prerelease versions. + +Note that this behavior can be suppressed (treating all prerelease +versions as if they were normal versions, for the purpose of range +matching) by setting the `includePrerelease` flag on the options +object to any +[functions](https://github.com/npm/node-semver#functions) that do +range matching. + +#### Prerelease Identifiers + +The method `.inc` takes an additional `identifier` string argument that +will append the value of the string as a prerelease identifier: + +```javascript +semver.inc('1.2.3', 'prerelease', 'beta') +// '1.2.4-beta.0' +``` + +command-line example: + +```bash +$ semver 1.2.3 -i prerelease --preid beta +1.2.4-beta.0 +``` + +Which then can be used to increment further: + +```bash +$ semver 1.2.4-beta.0 -i prerelease +1.2.4-beta.1 +``` + +### Advanced Range Syntax + +Advanced range syntax desugars to primitive comparators in +deterministic ways. + +Advanced ranges may be combined in the same way as primitive +comparators using white space or `||`. + +#### Hyphen Ranges `X.Y.Z - A.B.C` + +Specifies an inclusive set. + +* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4` + +If a partial version is provided as the first version in the inclusive +range, then the missing pieces are replaced with zeroes. + +* `1.2 - 2.3.4` := `>=1.2.0 <=2.3.4` + +If a partial version is provided as the second version in the +inclusive range, then all versions that start with the supplied parts +of the tuple are accepted, but nothing that would be greater than the +provided tuple parts. + +* `1.2.3 - 2.3` := `>=1.2.3 <2.4.0` +* `1.2.3 - 2` := `>=1.2.3 <3.0.0` + +#### X-Ranges `1.2.x` `1.X` `1.2.*` `*` + +Any of `X`, `x`, or `*` may be used to "stand in" for one of the +numeric values in the `[major, minor, patch]` tuple. + +* `*` := `>=0.0.0` (Any version satisfies) +* `1.x` := `>=1.0.0 <2.0.0` (Matching major version) +* `1.2.x` := `>=1.2.0 <1.3.0` (Matching major and minor versions) + +A partial version range is treated as an X-Range, so the special +character is in fact optional. + +* `""` (empty string) := `*` := `>=0.0.0` +* `1` := `1.x.x` := `>=1.0.0 <2.0.0` +* `1.2` := `1.2.x` := `>=1.2.0 <1.3.0` + +#### Tilde Ranges `~1.2.3` `~1.2` `~1` + +Allows patch-level changes if a minor version is specified on the +comparator. Allows minor-level changes if not. + +* `~1.2.3` := `>=1.2.3 <1.(2+1).0` := `>=1.2.3 <1.3.0` +* `~1.2` := `>=1.2.0 <1.(2+1).0` := `>=1.2.0 <1.3.0` (Same as `1.2.x`) +* `~1` := `>=1.0.0 <(1+1).0.0` := `>=1.0.0 <2.0.0` (Same as `1.x`) +* `~0.2.3` := `>=0.2.3 <0.(2+1).0` := `>=0.2.3 <0.3.0` +* `~0.2` := `>=0.2.0 <0.(2+1).0` := `>=0.2.0 <0.3.0` (Same as `0.2.x`) +* `~0` := `>=0.0.0 <(0+1).0.0` := `>=0.0.0 <1.0.0` (Same as `0.x`) +* `~1.2.3-beta.2` := `>=1.2.3-beta.2 <1.3.0` Note that prereleases in + the `1.2.3` version will be allowed, if they are greater than or + equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but + `1.2.4-beta.2` would not, because it is a prerelease of a + different `[major, minor, patch]` tuple. + +#### Caret Ranges `^1.2.3` `^0.2.5` `^0.0.4` + +Allows changes that do not modify the left-most non-zero element in the +`[major, minor, patch]` tuple. In other words, this allows patch and +minor updates for versions `1.0.0` and above, patch updates for +versions `0.X >=0.1.0`, and *no* updates for versions `0.0.X`. + +Many authors treat a `0.x` version as if the `x` were the major +"breaking-change" indicator. + +Caret ranges are ideal when an author may make breaking changes +between `0.2.4` and `0.3.0` releases, which is a common practice. +However, it presumes that there will *not* be breaking changes between +`0.2.4` and `0.2.5`. It allows for changes that are presumed to be +additive (but non-breaking), according to commonly observed practices. + +* `^1.2.3` := `>=1.2.3 <2.0.0` +* `^0.2.3` := `>=0.2.3 <0.3.0` +* `^0.0.3` := `>=0.0.3 <0.0.4` +* `^1.2.3-beta.2` := `>=1.2.3-beta.2 <2.0.0` Note that prereleases in + the `1.2.3` version will be allowed, if they are greater than or + equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but + `1.2.4-beta.2` would not, because it is a prerelease of a + different `[major, minor, patch]` tuple. +* `^0.0.3-beta` := `>=0.0.3-beta <0.0.4` Note that prereleases in the + `0.0.3` version *only* will be allowed, if they are greater than or + equal to `beta`. So, `0.0.3-pr.2` would be allowed. + +When parsing caret ranges, a missing `patch` value desugars to the +number `0`, but will allow flexibility within that value, even if the +major and minor versions are both `0`. + +* `^1.2.x` := `>=1.2.0 <2.0.0` +* `^0.0.x` := `>=0.0.0 <0.1.0` +* `^0.0` := `>=0.0.0 <0.1.0` + +A missing `minor` and `patch` values will desugar to zero, but also +allow flexibility within those values, even if the major version is +zero. + +* `^1.x` := `>=1.0.0 <2.0.0` +* `^0.x` := `>=0.0.0 <1.0.0` + +### Range Grammar + +Putting all this together, here is a Backus-Naur grammar for ranges, +for the benefit of parser authors: + +```bnf +range-set ::= range ( logical-or range ) * +logical-or ::= ( ' ' ) * '||' ( ' ' ) * +range ::= hyphen | simple ( ' ' simple ) * | '' +hyphen ::= partial ' - ' partial +simple ::= primitive | partial | tilde | caret +primitive ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial +partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )? +xr ::= 'x' | 'X' | '*' | nr +nr ::= '0' | ['1'-'9'] ( ['0'-'9'] ) * +tilde ::= '~' partial +caret ::= '^' partial +qualifier ::= ( '-' pre )? ( '+' build )? +pre ::= parts +build ::= parts +parts ::= part ( '.' part ) * +part ::= nr | [-0-9A-Za-z]+ +``` + +## Functions + +All methods and classes take a final `options` object argument. All +options in this object are `false` by default. The options supported +are: + +- `loose` Be more forgiving about not-quite-valid semver strings. + (Any resulting output will always be 100% strict compliant, of + course.) For backwards compatibility reasons, if the `options` + argument is a boolean value instead of an object, it is interpreted + to be the `loose` param. +- `includePrerelease` Set to suppress the [default + behavior](https://github.com/npm/node-semver#prerelease-tags) of + excluding prerelease tagged versions from ranges unless they are + explicitly opted into. + +Strict-mode Comparators and Ranges will be strict about the SemVer +strings that they parse. + +* `valid(v)`: Return the parsed version, or null if it's not valid. +* `inc(v, release)`: Return the version incremented by the release + type (`major`, `premajor`, `minor`, `preminor`, `patch`, + `prepatch`, or `prerelease`), or null if it's not valid + * `premajor` in one call will bump the version up to the next major + version and down to a prerelease of that major version. + `preminor`, and `prepatch` work the same way. + * If called from a non-prerelease version, the `prerelease` will work the + same as `prepatch`. It increments the patch version, then makes a + prerelease. If the input version is already a prerelease it simply + increments it. +* `prerelease(v)`: Returns an array of prerelease components, or null + if none exist. Example: `prerelease('1.2.3-alpha.1') -> ['alpha', 1]` +* `major(v)`: Return the major version number. +* `minor(v)`: Return the minor version number. +* `patch(v)`: Return the patch version number. +* `intersects(r1, r2, loose)`: Return true if the two supplied ranges + or comparators intersect. +* `parse(v)`: Attempt to parse a string as a semantic version, returning either + a `SemVer` object or `null`. + +### Comparison + +* `gt(v1, v2)`: `v1 > v2` +* `gte(v1, v2)`: `v1 >= v2` +* `lt(v1, v2)`: `v1 < v2` +* `lte(v1, v2)`: `v1 <= v2` +* `eq(v1, v2)`: `v1 == v2` This is true if they're logically equivalent, + even if they're not the exact same string. You already know how to + compare strings. +* `neq(v1, v2)`: `v1 != v2` The opposite of `eq`. +* `cmp(v1, comparator, v2)`: Pass in a comparison string, and it'll call + the corresponding function above. `"==="` and `"!=="` do simple + string comparison, but are included for completeness. Throws if an + invalid comparison string is provided. +* `compare(v1, v2)`: Return `0` if `v1 == v2`, or `1` if `v1` is greater, or `-1` if + `v2` is greater. Sorts in ascending order if passed to `Array.sort()`. +* `rcompare(v1, v2)`: The reverse of compare. Sorts an array of versions + in descending order when passed to `Array.sort()`. +* `compareBuild(v1, v2)`: The same as `compare` but considers `build` when two versions + are equal. Sorts in ascending order if passed to `Array.sort()`. + `v2` is greater. Sorts in ascending order if passed to `Array.sort()`. +* `diff(v1, v2)`: Returns difference between two versions by the release type + (`major`, `premajor`, `minor`, `preminor`, `patch`, `prepatch`, or `prerelease`), + or null if the versions are the same. + +### Comparators + +* `intersects(comparator)`: Return true if the comparators intersect + +### Ranges + +* `validRange(range)`: Return the valid range or null if it's not valid +* `satisfies(version, range)`: Return true if the version satisfies the + range. +* `maxSatisfying(versions, range)`: Return the highest version in the list + that satisfies the range, or `null` if none of them do. +* `minSatisfying(versions, range)`: Return the lowest version in the list + that satisfies the range, or `null` if none of them do. +* `minVersion(range)`: Return the lowest version that can possibly match + the given range. +* `gtr(version, range)`: Return `true` if version is greater than all the + versions possible in the range. +* `ltr(version, range)`: Return `true` if version is less than all the + versions possible in the range. +* `outside(version, range, hilo)`: Return true if the version is outside + the bounds of the range in either the high or low direction. The + `hilo` argument must be either the string `'>'` or `'<'`. (This is + the function called by `gtr` and `ltr`.) +* `intersects(range)`: Return true if any of the ranges comparators intersect + +Note that, since ranges may be non-contiguous, a version might not be +greater than a range, less than a range, *or* satisfy a range! For +example, the range `1.2 <1.2.9 || >2.0.0` would have a hole from `1.2.9` +until `2.0.0`, so the version `1.2.10` would not be greater than the +range (because `2.0.1` satisfies, which is higher), nor less than the +range (since `1.2.8` satisfies, which is lower), and it also does not +satisfy the range. + +If you want to know if a version satisfies or does not satisfy a +range, use the `satisfies(version, range)` function. + +### Coercion + +* `coerce(version, options)`: Coerces a string to semver if possible + +This aims to provide a very forgiving translation of a non-semver string to +semver. It looks for the first digit in a string, and consumes all +remaining characters which satisfy at least a partial semver (e.g., `1`, +`1.2`, `1.2.3`) up to the max permitted length (256 characters). Longer +versions are simply truncated (`4.6.3.9.2-alpha2` becomes `4.6.3`). All +surrounding text is simply ignored (`v3.4 replaces v3.3.1` becomes +`3.4.0`). Only text which lacks digits will fail coercion (`version one` +is not valid). The maximum length for any semver component considered for +coercion is 16 characters; longer components will be ignored +(`10000000000000000.4.7.4` becomes `4.7.4`). The maximum value for any +semver component is `Number.MAX_SAFE_INTEGER || (2**53 - 1)`; higher value +components are invalid (`9999999999999999.4.7.4` is likely invalid). + +If the `options.rtl` flag is set, then `coerce` will return the right-most +coercible tuple that does not share an ending index with a longer coercible +tuple. For example, `1.2.3.4` will return `2.3.4` in rtl mode, not +`4.0.0`. `1.2.3/4` will return `4.0.0`, because the `4` is not a part of +any other overlapping SemVer tuple. + +### Clean + +* `clean(version)`: Clean a string to be a valid semver if possible + +This will return a cleaned and trimmed semver version. If the provided +version is not valid a null will be returned. This does not work for +ranges. + +ex. +* `s.clean(' = v 2.1.5foo')`: `null` +* `s.clean(' = v 2.1.5foo', { loose: true })`: `'2.1.5-foo'` +* `s.clean(' = v 2.1.5-foo')`: `null` +* `s.clean(' = v 2.1.5-foo', { loose: true })`: `'2.1.5-foo'` +* `s.clean('=v2.1.5')`: `'2.1.5'` +* `s.clean(' =v2.1.5')`: `2.1.5` +* `s.clean(' 2.1.5 ')`: `'2.1.5'` +* `s.clean('~1.0.0')`: `null` + +## Exported Modules + + + +You may pull in just the part of this semver utility that you need, if you +are sensitive to packing and tree-shaking concerns. The main +`require('semver')` export uses getter functions to lazily load the parts +of the API that are used. + +The following modules are available: + +* `require('semver')` +* `require('semver/classes')` +* `require('semver/classes/comparator')` +* `require('semver/classes/range')` +* `require('semver/classes/semver')` +* `require('semver/functions/clean')` +* `require('semver/functions/cmp')` +* `require('semver/functions/coerce')` +* `require('semver/functions/compare')` +* `require('semver/functions/compare-build')` +* `require('semver/functions/compare-loose')` +* `require('semver/functions/diff')` +* `require('semver/functions/eq')` +* `require('semver/functions/gt')` +* `require('semver/functions/gte')` +* `require('semver/functions/inc')` +* `require('semver/functions/lt')` +* `require('semver/functions/lte')` +* `require('semver/functions/major')` +* `require('semver/functions/minor')` +* `require('semver/functions/neq')` +* `require('semver/functions/parse')` +* `require('semver/functions/patch')` +* `require('semver/functions/prerelease')` +* `require('semver/functions/rcompare')` +* `require('semver/functions/rsort')` +* `require('semver/functions/satisfies')` +* `require('semver/functions/sort')` +* `require('semver/functions/valid')` +* `require('semver/ranges/gtr')` +* `require('semver/ranges/intersects')` +* `require('semver/ranges/ltr')` +* `require('semver/ranges/max-satisfying')` +* `require('semver/ranges/min-satisfying')` +* `require('semver/ranges/min-version')` +* `require('semver/ranges/outside')` +* `require('semver/ranges/to-comparators')` +* `require('semver/ranges/valid')` diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/bin/semver.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/bin/semver.js new file mode 100644 index 0000000..73fe295 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/bin/semver.js @@ -0,0 +1,173 @@ +#!/usr/bin/env node +// Standalone semver comparison program. +// Exits successfully and prints matching version(s) if +// any supplied version is valid and passes all tests. + +const argv = process.argv.slice(2) + +let versions = [] + +const range = [] + +let inc = null + +const version = require('../package.json').version + +let loose = false + +let includePrerelease = false + +let coerce = false + +let rtl = false + +let identifier + +const semver = require('../') + +let reverse = false + +const options = {} + +const main = () => { + if (!argv.length) return help() + while (argv.length) { + let a = argv.shift() + const indexOfEqualSign = a.indexOf('=') + if (indexOfEqualSign !== -1) { + a = a.slice(0, indexOfEqualSign) + argv.unshift(a.slice(indexOfEqualSign + 1)) + } + switch (a) { + case '-rv': case '-rev': case '--rev': case '--reverse': + reverse = true + break + case '-l': case '--loose': + loose = true + break + case '-p': case '--include-prerelease': + includePrerelease = true + break + case '-v': case '--version': + versions.push(argv.shift()) + break + case '-i': case '--inc': case '--increment': + switch (argv[0]) { + case 'major': case 'minor': case 'patch': case 'prerelease': + case 'premajor': case 'preminor': case 'prepatch': + inc = argv.shift() + break + default: + inc = 'patch' + break + } + break + case '--preid': + identifier = argv.shift() + break + case '-r': case '--range': + range.push(argv.shift()) + break + case '-c': case '--coerce': + coerce = true + break + case '--rtl': + rtl = true + break + case '--ltr': + rtl = false + break + case '-h': case '--help': case '-?': + return help() + default: + versions.push(a) + break + } + } + + const options = { loose: loose, includePrerelease: includePrerelease, rtl: rtl } + + versions = versions.map((v) => { + return coerce ? (semver.coerce(v, options) || { version: v }).version : v + }).filter((v) => { + return semver.valid(v) + }) + if (!versions.length) return fail() + if (inc && (versions.length !== 1 || range.length)) { return failInc() } + + for (let i = 0, l = range.length; i < l; i++) { + versions = versions.filter((v) => { + return semver.satisfies(v, range[i], options) + }) + if (!versions.length) return fail() + } + return success(versions) +} + + +const failInc = () => { + console.error('--inc can only be used on a single version with no range') + fail() +} + +const fail = () => process.exit(1) + +const success = () => { + const compare = reverse ? 'rcompare' : 'compare' + versions.sort((a, b) => { + return semver[compare](a, b, options) + }).map((v) => { + return semver.clean(v, options) + }).map((v) => { + return inc ? semver.inc(v, inc, options, identifier) : v + }).forEach((v, i, _) => { console.log(v) }) +} + +const help = () => console.log( +`SemVer ${version} + +A JavaScript implementation of the https://semver.org/ specification +Copyright Isaac Z. Schlueter + +Usage: semver [options] [ [...]] +Prints valid versions sorted by SemVer precedence + +Options: +-r --range + Print versions that match the specified range. + +-i --increment [] + Increment a version by the specified level. Level can + be one of: major, minor, patch, premajor, preminor, + prepatch, or prerelease. Default level is 'patch'. + Only one version may be specified. + +--preid + Identifier to be used to prefix premajor, preminor, + prepatch or prerelease version increments. + +-l --loose + Interpret versions and ranges loosely + +-p --include-prerelease + Always include prerelease versions in range matching + +-c --coerce + Coerce a string into SemVer if possible + (does not imply --loose) + +--rtl + Coerce version strings right to left + +--ltr + Coerce version strings left to right (default) + +Program exits successfully if any valid version satisfies +all supplied ranges, and prints all satisfying versions. + +If no satisfying versions are found, then exits failure. + +Versions are printed in ascending order, so supplying +multiple versions to the utility will just sort them.`) + +main() diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/comparator.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/comparator.js new file mode 100644 index 0000000..3595792 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/comparator.js @@ -0,0 +1,139 @@ +const ANY = Symbol('SemVer ANY') +// hoisted class for cyclic dependency +class Comparator { + static get ANY () { + return ANY + } + constructor (comp, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (comp instanceof Comparator) { + if (comp.loose === !!options.loose) { + return comp + } else { + comp = comp.value + } + } + + debug('comparator', comp, options) + this.options = options + this.loose = !!options.loose + this.parse(comp) + + if (this.semver === ANY) { + this.value = '' + } else { + this.value = this.operator + this.semver.version + } + + debug('comp', this) + } + + parse (comp) { + const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR] + const m = comp.match(r) + + if (!m) { + throw new TypeError(`Invalid comparator: ${comp}`) + } + + this.operator = m[1] !== undefined ? m[1] : '' + if (this.operator === '=') { + this.operator = '' + } + + // if it literally is just '>' or '' then allow anything. + if (!m[2]) { + this.semver = ANY + } else { + this.semver = new SemVer(m[2], this.options.loose) + } + } + + toString () { + return this.value + } + + test (version) { + debug('Comparator.test', version, this.options.loose) + + if (this.semver === ANY || version === ANY) { + return true + } + + if (typeof version === 'string') { + try { + version = new SemVer(version, this.options) + } catch (er) { + return false + } + } + + return cmp(version, this.operator, this.semver, this.options) + } + + intersects (comp, options) { + if (!(comp instanceof Comparator)) { + throw new TypeError('a Comparator is required') + } + + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (this.operator === '') { + if (this.value === '') { + return true + } + return new Range(comp.value, options).test(this.value) + } else if (comp.operator === '') { + if (comp.value === '') { + return true + } + return new Range(this.value, options).test(comp.semver) + } + + const sameDirectionIncreasing = + (this.operator === '>=' || this.operator === '>') && + (comp.operator === '>=' || comp.operator === '>') + const sameDirectionDecreasing = + (this.operator === '<=' || this.operator === '<') && + (comp.operator === '<=' || comp.operator === '<') + const sameSemVer = this.semver.version === comp.semver.version + const differentDirectionsInclusive = + (this.operator === '>=' || this.operator === '<=') && + (comp.operator === '>=' || comp.operator === '<=') + const oppositeDirectionsLessThan = + cmp(this.semver, '<', comp.semver, options) && + (this.operator === '>=' || this.operator === '>') && + (comp.operator === '<=' || comp.operator === '<') + const oppositeDirectionsGreaterThan = + cmp(this.semver, '>', comp.semver, options) && + (this.operator === '<=' || this.operator === '<') && + (comp.operator === '>=' || comp.operator === '>') + + return ( + sameDirectionIncreasing || + sameDirectionDecreasing || + (sameSemVer && differentDirectionsInclusive) || + oppositeDirectionsLessThan || + oppositeDirectionsGreaterThan + ) + } +} + +module.exports = Comparator + +const {re, t} = require('../internal/re') +const cmp = require('../functions/cmp') +const debug = require('../internal/debug') +const SemVer = require('./semver') +const Range = require('./range') diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/index.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/index.js new file mode 100644 index 0000000..198b84d --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/index.js @@ -0,0 +1,5 @@ +module.exports = { + SemVer: require('./semver.js'), + Range: require('./range.js'), + Comparator: require('./comparator.js') +} diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/range.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/range.js new file mode 100644 index 0000000..90876c3 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/range.js @@ -0,0 +1,448 @@ +// hoisted class for cyclic dependency +class Range { + constructor (range, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (range instanceof Range) { + if ( + range.loose === !!options.loose && + range.includePrerelease === !!options.includePrerelease + ) { + return range + } else { + return new Range(range.raw, options) + } + } + + if (range instanceof Comparator) { + // just put it in the set and return + this.raw = range.value + this.set = [[range]] + this.format() + return this + } + + this.options = options + this.loose = !!options.loose + this.includePrerelease = !!options.includePrerelease + + // First, split based on boolean or || + this.raw = range + this.set = range + .split(/\s*\|\|\s*/) + // map the range to a 2d array of comparators + .map(range => this.parseRange(range.trim())) + // throw out any comparator lists that are empty + // this generally means that it was not a valid range, which is allowed + // in loose mode, but will still throw if the WHOLE range is invalid. + .filter(c => c.length) + + if (!this.set.length) { + throw new TypeError(`Invalid SemVer Range: ${range}`) + } + + this.format() + } + + format () { + this.range = this.set + .map((comps) => { + return comps.join(' ').trim() + }) + .join('||') + .trim() + return this.range + } + + toString () { + return this.range + } + + parseRange (range) { + const loose = this.options.loose + range = range.trim() + // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` + const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE] + range = range.replace(hr, hyphenReplace) + debug('hyphen replace', range) + // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` + range = range.replace(re[t.COMPARATORTRIM], comparatorTrimReplace) + debug('comparator trim', range, re[t.COMPARATORTRIM]) + + // `~ 1.2.3` => `~1.2.3` + range = range.replace(re[t.TILDETRIM], tildeTrimReplace) + + // `^ 1.2.3` => `^1.2.3` + range = range.replace(re[t.CARETTRIM], caretTrimReplace) + + // normalize spaces + range = range.split(/\s+/).join(' ') + + // At this point, the range is completely trimmed and + // ready to be split into comparators. + + const compRe = loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR] + return range + .split(' ') + .map(comp => parseComparator(comp, this.options)) + .join(' ') + .split(/\s+/) + // in loose mode, throw out any that are not valid comparators + .filter(this.options.loose ? comp => !!comp.match(compRe) : () => true) + .map(comp => new Comparator(comp, this.options)) + } + + intersects (range, options) { + if (!(range instanceof Range)) { + throw new TypeError('a Range is required') + } + + return this.set.some((thisComparators) => { + return ( + isSatisfiable(thisComparators, options) && + range.set.some((rangeComparators) => { + return ( + isSatisfiable(rangeComparators, options) && + thisComparators.every((thisComparator) => { + return rangeComparators.every((rangeComparator) => { + return thisComparator.intersects(rangeComparator, options) + }) + }) + ) + }) + ) + }) + } + + // if ANY of the sets match ALL of its comparators, then pass + test (version) { + if (!version) { + return false + } + + if (typeof version === 'string') { + try { + version = new SemVer(version, this.options) + } catch (er) { + return false + } + } + + for (let i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version, this.options)) { + return true + } + } + return false + } +} +module.exports = Range + +const Comparator = require('./comparator') +const debug = require('../internal/debug') +const SemVer = require('./semver') +const { + re, + t, + comparatorTrimReplace, + tildeTrimReplace, + caretTrimReplace +} = require('../internal/re') + +// take a set of comparators and determine whether there +// exists a version which can satisfy it +const isSatisfiable = (comparators, options) => { + let result = true + const remainingComparators = comparators.slice() + let testComparator = remainingComparators.pop() + + while (result && remainingComparators.length) { + result = remainingComparators.every((otherComparator) => { + return testComparator.intersects(otherComparator, options) + }) + + testComparator = remainingComparators.pop() + } + + return result +} + +// comprised of xranges, tildes, stars, and gtlt's at this point. +// already replaced the hyphen ranges +// turn into a set of JUST comparators. +const parseComparator = (comp, options) => { + debug('comp', comp, options) + comp = replaceCarets(comp, options) + debug('caret', comp) + comp = replaceTildes(comp, options) + debug('tildes', comp) + comp = replaceXRanges(comp, options) + debug('xrange', comp) + comp = replaceStars(comp, options) + debug('stars', comp) + return comp +} + +const isX = id => !id || id.toLowerCase() === 'x' || id === '*' + +// ~, ~> --> * (any, kinda silly) +// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 +// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 +// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 +// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 +// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 +const replaceTildes = (comp, options) => + comp.trim().split(/\s+/).map((comp) => { + return replaceTilde(comp, options) + }).join(' ') + +const replaceTilde = (comp, options) => { + const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE] + return comp.replace(r, (_, M, m, p, pr) => { + debug('tilde', comp, _, M, m, p, pr) + let ret + + if (isX(M)) { + ret = '' + } else if (isX(m)) { + ret = `>=${M}.0.0 <${+M + 1}.0.0` + } else if (isX(p)) { + // ~1.2 == >=1.2.0 <1.3.0 + ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0` + } else if (pr) { + debug('replaceTilde pr', pr) + ret = `>=${M}.${m}.${p}-${pr + } <${M}.${+m + 1}.0` + } else { + // ~1.2.3 == >=1.2.3 <1.3.0 + ret = `>=${M}.${m}.${p + } <${M}.${+m + 1}.0` + } + + debug('tilde return', ret) + return ret + }) +} + +// ^ --> * (any, kinda silly) +// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 +// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 +// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 +// ^1.2.3 --> >=1.2.3 <2.0.0 +// ^1.2.0 --> >=1.2.0 <2.0.0 +const replaceCarets = (comp, options) => + comp.trim().split(/\s+/).map((comp) => { + return replaceCaret(comp, options) + }).join(' ') + +const replaceCaret = (comp, options) => { + debug('caret', comp, options) + const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET] + return comp.replace(r, (_, M, m, p, pr) => { + debug('caret', comp, _, M, m, p, pr) + let ret + + if (isX(M)) { + ret = '' + } else if (isX(m)) { + ret = `>=${M}.0.0 <${+M + 1}.0.0` + } else if (isX(p)) { + if (M === '0') { + ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0` + } else { + ret = `>=${M}.${m}.0 <${+M + 1}.0.0` + } + } else if (pr) { + debug('replaceCaret pr', pr) + if (M === '0') { + if (m === '0') { + ret = `>=${M}.${m}.${p}-${pr + } <${M}.${m}.${+p + 1}` + } else { + ret = `>=${M}.${m}.${p}-${pr + } <${M}.${+m + 1}.0` + } + } else { + ret = `>=${M}.${m}.${p}-${pr + } <${+M + 1}.0.0` + } + } else { + debug('no pr') + if (M === '0') { + if (m === '0') { + ret = `>=${M}.${m}.${p + } <${M}.${m}.${+p + 1}` + } else { + ret = `>=${M}.${m}.${p + } <${M}.${+m + 1}.0` + } + } else { + ret = `>=${M}.${m}.${p + } <${+M + 1}.0.0` + } + } + + debug('caret return', ret) + return ret + }) +} + +const replaceXRanges = (comp, options) => { + debug('replaceXRanges', comp, options) + return comp.split(/\s+/).map((comp) => { + return replaceXRange(comp, options) + }).join(' ') +} + +const replaceXRange = (comp, options) => { + comp = comp.trim() + const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE] + return comp.replace(r, (ret, gtlt, M, m, p, pr) => { + debug('xRange', comp, ret, gtlt, M, m, p, pr) + const xM = isX(M) + const xm = xM || isX(m) + const xp = xm || isX(p) + const anyX = xp + + if (gtlt === '=' && anyX) { + gtlt = '' + } + + // if we're including prereleases in the match, then we need + // to fix this to -0, the lowest possible prerelease value + pr = options.includePrerelease ? '-0' : '' + + if (xM) { + if (gtlt === '>' || gtlt === '<') { + // nothing is allowed + ret = '<0.0.0-0' + } else { + // nothing is forbidden + ret = '*' + } + } else if (gtlt && anyX) { + // we know patch is an x, because we have any x at all. + // replace X with 0 + if (xm) { + m = 0 + } + p = 0 + + if (gtlt === '>') { + // >1 => >=2.0.0 + // >1.2 => >=1.3.0 + gtlt = '>=' + if (xm) { + M = +M + 1 + m = 0 + p = 0 + } else { + m = +m + 1 + p = 0 + } + } else if (gtlt === '<=') { + // <=0.7.x is actually <0.8.0, since any 0.7.x should + // pass. Similarly, <=7.x is actually <8.0.0, etc. + gtlt = '<' + if (xm) { + M = +M + 1 + } else { + m = +m + 1 + } + } + + ret = `${gtlt + M}.${m}.${p}${pr}` + } else if (xm) { + ret = `>=${M}.0.0${pr} <${+M + 1}.0.0${pr}` + } else if (xp) { + ret = `>=${M}.${m}.0${pr + } <${M}.${+m + 1}.0${pr}` + } + + debug('xRange return', ret) + + return ret + }) +} + +// Because * is AND-ed with everything else in the comparator, +// and '' means "any version", just remove the *s entirely. +const replaceStars = (comp, options) => { + debug('replaceStars', comp, options) + // Looseness is ignored here. star is always as loose as it gets! + return comp.trim().replace(re[t.STAR], '') +} + +// This function is passed to string.replace(re[t.HYPHENRANGE]) +// M, m, patch, prerelease, build +// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 +// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do +// 1.2 - 3.4 => >=1.2.0 <3.5.0 +const hyphenReplace = ($0, + from, fM, fm, fp, fpr, fb, + to, tM, tm, tp, tpr, tb) => { + if (isX(fM)) { + from = '' + } else if (isX(fm)) { + from = `>=${fM}.0.0` + } else if (isX(fp)) { + from = `>=${fM}.${fm}.0` + } else { + from = `>=${from}` + } + + if (isX(tM)) { + to = '' + } else if (isX(tm)) { + to = `<${+tM + 1}.0.0` + } else if (isX(tp)) { + to = `<${tM}.${+tm + 1}.0` + } else if (tpr) { + to = `<=${tM}.${tm}.${tp}-${tpr}` + } else { + to = `<=${to}` + } + + return (`${from} ${to}`).trim() +} + +const testSet = (set, version, options) => { + for (let i = 0; i < set.length; i++) { + if (!set[i].test(version)) { + return false + } + } + + if (version.prerelease.length && !options.includePrerelease) { + // Find the set of versions that are allowed to have prereleases + // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 + // That should allow `1.2.3-pr.2` to pass. + // However, `1.2.4-alpha.notready` should NOT be allowed, + // even though it's within the range set by the comparators. + for (let i = 0; i < set.length; i++) { + debug(set[i].semver) + if (set[i].semver === Comparator.ANY) { + continue + } + + if (set[i].semver.prerelease.length > 0) { + const allowed = set[i].semver + if (allowed.major === version.major && + allowed.minor === version.minor && + allowed.patch === version.patch) { + return true + } + } + } + + // Version has a -pre, but it's not one of the ones we like. + return false + } + + return true +} diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/semver.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/semver.js new file mode 100644 index 0000000..73247ad --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/classes/semver.js @@ -0,0 +1,290 @@ +const debug = require('../internal/debug') +const { MAX_LENGTH, MAX_SAFE_INTEGER } = require('../internal/constants') +const { re, t } = require('../internal/re') + +const { compareIdentifiers } = require('../internal/identifiers') +class SemVer { + constructor (version, options) { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + if (version instanceof SemVer) { + if (version.loose === !!options.loose && + version.includePrerelease === !!options.includePrerelease) { + return version + } else { + version = version.version + } + } else if (typeof version !== 'string') { + throw new TypeError(`Invalid Version: ${version}`) + } + + if (version.length > MAX_LENGTH) { + throw new TypeError( + `version is longer than ${MAX_LENGTH} characters` + ) + } + + debug('SemVer', version, options) + this.options = options + this.loose = !!options.loose + // this isn't actually relevant for versions, but keep it so that we + // don't run into trouble passing this.options around. + this.includePrerelease = !!options.includePrerelease + + const m = version.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]) + + if (!m) { + throw new TypeError(`Invalid Version: ${version}`) + } + + this.raw = version + + // these are actually numbers + this.major = +m[1] + this.minor = +m[2] + this.patch = +m[3] + + if (this.major > MAX_SAFE_INTEGER || this.major < 0) { + throw new TypeError('Invalid major version') + } + + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) { + throw new TypeError('Invalid minor version') + } + + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) { + throw new TypeError('Invalid patch version') + } + + // numberify any prerelease numeric ids + if (!m[4]) { + this.prerelease = [] + } else { + this.prerelease = m[4].split('.').map((id) => { + if (/^[0-9]+$/.test(id)) { + const num = +id + if (num >= 0 && num < MAX_SAFE_INTEGER) { + return num + } + } + return id + }) + } + + this.build = m[5] ? m[5].split('.') : [] + this.format() + } + + format () { + this.version = `${this.major}.${this.minor}.${this.patch}` + if (this.prerelease.length) { + this.version += `-${this.prerelease.join('.')}` + } + return this.version + } + + toString () { + return this.version + } + + compare (other) { + debug('SemVer.compare', this.version, this.options, other) + if (!(other instanceof SemVer)) { + if (typeof other === 'string' && other === this.version) { + return 0 + } + other = new SemVer(other, this.options) + } + + if (other.version === this.version) { + return 0 + } + + return this.compareMain(other) || this.comparePre(other) + } + + compareMain (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + return ( + compareIdentifiers(this.major, other.major) || + compareIdentifiers(this.minor, other.minor) || + compareIdentifiers(this.patch, other.patch) + ) + } + + comparePre (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + // NOT having a prerelease is > having one + if (this.prerelease.length && !other.prerelease.length) { + return -1 + } else if (!this.prerelease.length && other.prerelease.length) { + return 1 + } else if (!this.prerelease.length && !other.prerelease.length) { + return 0 + } + + let i = 0 + do { + const a = this.prerelease[i] + const b = other.prerelease[i] + debug('prerelease compare', i, a, b) + if (a === undefined && b === undefined) { + return 0 + } else if (b === undefined) { + return 1 + } else if (a === undefined) { + return -1 + } else if (a === b) { + continue + } else { + return compareIdentifiers(a, b) + } + } while (++i) + } + + compareBuild (other) { + if (!(other instanceof SemVer)) { + other = new SemVer(other, this.options) + } + + let i = 0 + do { + const a = this.build[i] + const b = other.build[i] + debug('prerelease compare', i, a, b) + if (a === undefined && b === undefined) { + return 0 + } else if (b === undefined) { + return 1 + } else if (a === undefined) { + return -1 + } else if (a === b) { + continue + } else { + return compareIdentifiers(a, b) + } + } while (++i) + } + + // preminor will bump the version up to the next minor release, and immediately + // down to pre-release. premajor and prepatch work the same way. + inc (release, identifier) { + switch (release) { + case 'premajor': + this.prerelease.length = 0 + this.patch = 0 + this.minor = 0 + this.major++ + this.inc('pre', identifier) + break + case 'preminor': + this.prerelease.length = 0 + this.patch = 0 + this.minor++ + this.inc('pre', identifier) + break + case 'prepatch': + // If this is already a prerelease, it will bump to the next version + // drop any prereleases that might already exist, since they are not + // relevant at this point. + this.prerelease.length = 0 + this.inc('patch', identifier) + this.inc('pre', identifier) + break + // If the input is a non-prerelease version, this acts the same as + // prepatch. + case 'prerelease': + if (this.prerelease.length === 0) { + this.inc('patch', identifier) + } + this.inc('pre', identifier) + break + + case 'major': + // If this is a pre-major version, bump up to the same major version. + // Otherwise increment major. + // 1.0.0-5 bumps to 1.0.0 + // 1.1.0 bumps to 2.0.0 + if ( + this.minor !== 0 || + this.patch !== 0 || + this.prerelease.length === 0 + ) { + this.major++ + } + this.minor = 0 + this.patch = 0 + this.prerelease = [] + break + case 'minor': + // If this is a pre-minor version, bump up to the same minor version. + // Otherwise increment minor. + // 1.2.0-5 bumps to 1.2.0 + // 1.2.1 bumps to 1.3.0 + if (this.patch !== 0 || this.prerelease.length === 0) { + this.minor++ + } + this.patch = 0 + this.prerelease = [] + break + case 'patch': + // If this is not a pre-release version, it will increment the patch. + // If it is a pre-release it will bump up to the same patch version. + // 1.2.0-5 patches to 1.2.0 + // 1.2.0 patches to 1.2.1 + if (this.prerelease.length === 0) { + this.patch++ + } + this.prerelease = [] + break + // This probably shouldn't be used publicly. + // 1.0.0 'pre' would become 1.0.0-0 which is the wrong direction. + case 'pre': + if (this.prerelease.length === 0) { + this.prerelease = [0] + } else { + let i = this.prerelease.length + while (--i >= 0) { + if (typeof this.prerelease[i] === 'number') { + this.prerelease[i]++ + i = -2 + } + } + if (i === -1) { + // didn't increment anything + this.prerelease.push(0) + } + } + if (identifier) { + // 1.2.0-beta.1 bumps to 1.2.0-beta.2, + // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 + if (this.prerelease[0] === identifier) { + if (isNaN(this.prerelease[1])) { + this.prerelease = [identifier, 0] + } + } else { + this.prerelease = [identifier, 0] + } + } + break + + default: + throw new Error(`invalid increment argument: ${release}`) + } + this.format() + this.raw = this.version + return this + } +} + +module.exports = SemVer diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/clean.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/clean.js new file mode 100644 index 0000000..811fe6b --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/clean.js @@ -0,0 +1,6 @@ +const parse = require('./parse') +const clean = (version, options) => { + const s = parse(version.trim().replace(/^[=v]+/, ''), options) + return s ? s.version : null +} +module.exports = clean diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/cmp.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/cmp.js new file mode 100644 index 0000000..3b89db7 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/cmp.js @@ -0,0 +1,48 @@ +const eq = require('./eq') +const neq = require('./neq') +const gt = require('./gt') +const gte = require('./gte') +const lt = require('./lt') +const lte = require('./lte') + +const cmp = (a, op, b, loose) => { + switch (op) { + case '===': + if (typeof a === 'object') + a = a.version + if (typeof b === 'object') + b = b.version + return a === b + + case '!==': + if (typeof a === 'object') + a = a.version + if (typeof b === 'object') + b = b.version + return a !== b + + case '': + case '=': + case '==': + return eq(a, b, loose) + + case '!=': + return neq(a, b, loose) + + case '>': + return gt(a, b, loose) + + case '>=': + return gte(a, b, loose) + + case '<': + return lt(a, b, loose) + + case '<=': + return lte(a, b, loose) + + default: + throw new TypeError(`Invalid operator: ${op}`) + } +} +module.exports = cmp diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/coerce.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/coerce.js new file mode 100644 index 0000000..106ca71 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/coerce.js @@ -0,0 +1,51 @@ +const SemVer = require('../classes/semver') +const parse = require('./parse') +const {re, t} = require('../internal/re') + +const coerce = (version, options) => { + if (version instanceof SemVer) { + return version + } + + if (typeof version === 'number') { + version = String(version) + } + + if (typeof version !== 'string') { + return null + } + + options = options || {} + + let match = null + if (!options.rtl) { + match = version.match(re[t.COERCE]) + } else { + // Find the right-most coercible string that does not share + // a terminus with a more left-ward coercible string. + // Eg, '1.2.3.4' wants to coerce '2.3.4', not '3.4' or '4' + // + // Walk through the string checking with a /g regexp + // Manually set the index so as to pick up overlapping matches. + // Stop when we get a match that ends at the string end, since no + // coercible string can be more right-ward without the same terminus. + let next + while ((next = re[t.COERCERTL].exec(version)) && + (!match || match.index + match[0].length !== version.length) + ) { + if (!match || + next.index + next[0].length !== match.index + match[0].length) { + match = next + } + re[t.COERCERTL].lastIndex = next.index + next[1].length + next[2].length + } + // leave it in a clean state + re[t.COERCERTL].lastIndex = -1 + } + + if (match === null) + return null + + return parse(`${match[2]}.${match[3] || '0'}.${match[4] || '0'}`, options) +} +module.exports = coerce diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare-build.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare-build.js new file mode 100644 index 0000000..9eb881b --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare-build.js @@ -0,0 +1,7 @@ +const SemVer = require('../classes/semver') +const compareBuild = (a, b, loose) => { + const versionA = new SemVer(a, loose) + const versionB = new SemVer(b, loose) + return versionA.compare(versionB) || versionA.compareBuild(versionB) +} +module.exports = compareBuild diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare-loose.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare-loose.js new file mode 100644 index 0000000..4881fbe --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare-loose.js @@ -0,0 +1,3 @@ +const compare = require('./compare') +const compareLoose = (a, b) => compare(a, b, true) +module.exports = compareLoose diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare.js new file mode 100644 index 0000000..748b7af --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/compare.js @@ -0,0 +1,5 @@ +const SemVer = require('../classes/semver') +const compare = (a, b, loose) => + new SemVer(a, loose).compare(new SemVer(b, loose)) + +module.exports = compare diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/diff.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/diff.js new file mode 100644 index 0000000..1493666 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/diff.js @@ -0,0 +1,25 @@ +const parse = require('./parse') +const eq = require('./eq') + +const diff = (version1, version2) => { + if (eq(version1, version2)) { + return null + } else { + const v1 = parse(version1) + const v2 = parse(version2) + let prefix = '' + if (v1.prerelease.length || v2.prerelease.length) { + prefix = 'pre' + var defaultResult = 'prerelease' + } + for (const key in v1) { + if (key === 'major' || key === 'minor' || key === 'patch') { + if (v1[key] !== v2[key]) { + return prefix + key + } + } + } + return defaultResult // may be undefined + } +} +module.exports = diff diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/eq.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/eq.js new file mode 100644 index 0000000..271fed9 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/eq.js @@ -0,0 +1,3 @@ +const compare = require('./compare') +const eq = (a, b, loose) => compare(a, b, loose) === 0 +module.exports = eq diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/gt.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/gt.js new file mode 100644 index 0000000..d9b2156 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/gt.js @@ -0,0 +1,3 @@ +const compare = require('./compare') +const gt = (a, b, loose) => compare(a, b, loose) > 0 +module.exports = gt diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/gte.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/gte.js new file mode 100644 index 0000000..5aeaa63 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/gte.js @@ -0,0 +1,3 @@ +const compare = require('./compare') +const gte = (a, b, loose) => compare(a, b, loose) >= 0 +module.exports = gte diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/inc.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/inc.js new file mode 100644 index 0000000..aa4d83a --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/inc.js @@ -0,0 +1,15 @@ +const SemVer = require('../classes/semver') + +const inc = (version, release, options, identifier) => { + if (typeof (options) === 'string') { + identifier = options + options = undefined + } + + try { + return new SemVer(version, options).inc(release, identifier).version + } catch (er) { + return null + } +} +module.exports = inc diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/lt.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/lt.js new file mode 100644 index 0000000..b440ab7 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/lt.js @@ -0,0 +1,3 @@ +const compare = require('./compare') +const lt = (a, b, loose) => compare(a, b, loose) < 0 +module.exports = lt diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/lte.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/lte.js new file mode 100644 index 0000000..6dcc956 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/lte.js @@ -0,0 +1,3 @@ +const compare = require('./compare') +const lte = (a, b, loose) => compare(a, b, loose) <= 0 +module.exports = lte diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/major.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/major.js new file mode 100644 index 0000000..4283165 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/major.js @@ -0,0 +1,3 @@ +const SemVer = require('../classes/semver') +const major = (a, loose) => new SemVer(a, loose).major +module.exports = major diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/minor.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/minor.js new file mode 100644 index 0000000..57b3455 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/minor.js @@ -0,0 +1,3 @@ +const SemVer = require('../classes/semver') +const minor = (a, loose) => new SemVer(a, loose).minor +module.exports = minor diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/neq.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/neq.js new file mode 100644 index 0000000..f944c01 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/neq.js @@ -0,0 +1,3 @@ +const compare = require('./compare') +const neq = (a, b, loose) => compare(a, b, loose) !== 0 +module.exports = neq diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/parse.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/parse.js new file mode 100644 index 0000000..457fee0 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/parse.js @@ -0,0 +1,37 @@ +const {MAX_LENGTH} = require('../internal/constants') +const { re, t } = require('../internal/re') +const SemVer = require('../classes/semver') + +const parse = (version, options) => { + if (!options || typeof options !== 'object') { + options = { + loose: !!options, + includePrerelease: false + } + } + + if (version instanceof SemVer) { + return version + } + + if (typeof version !== 'string') { + return null + } + + if (version.length > MAX_LENGTH) { + return null + } + + const r = options.loose ? re[t.LOOSE] : re[t.FULL] + if (!r.test(version)) { + return null + } + + try { + return new SemVer(version, options) + } catch (er) { + return null + } +} + +module.exports = parse diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/patch.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/patch.js new file mode 100644 index 0000000..63afca2 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/patch.js @@ -0,0 +1,3 @@ +const SemVer = require('../classes/semver') +const patch = (a, loose) => new SemVer(a, loose).patch +module.exports = patch diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/prerelease.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/prerelease.js new file mode 100644 index 0000000..06aa132 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/prerelease.js @@ -0,0 +1,6 @@ +const parse = require('./parse') +const prerelease = (version, options) => { + const parsed = parse(version, options) + return (parsed && parsed.prerelease.length) ? parsed.prerelease : null +} +module.exports = prerelease diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/rcompare.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/rcompare.js new file mode 100644 index 0000000..0ac509e --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/rcompare.js @@ -0,0 +1,3 @@ +const compare = require('./compare') +const rcompare = (a, b, loose) => compare(b, a, loose) +module.exports = rcompare diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/rsort.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/rsort.js new file mode 100644 index 0000000..82404c5 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/rsort.js @@ -0,0 +1,3 @@ +const compareBuild = require('./compare-build') +const rsort = (list, loose) => list.sort((a, b) => compareBuild(b, a, loose)) +module.exports = rsort diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/satisfies.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/satisfies.js new file mode 100644 index 0000000..50af1c1 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/satisfies.js @@ -0,0 +1,10 @@ +const Range = require('../classes/range') +const satisfies = (version, range, options) => { + try { + range = new Range(range, options) + } catch (er) { + return false + } + return range.test(version) +} +module.exports = satisfies diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/sort.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/sort.js new file mode 100644 index 0000000..4d10917 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/sort.js @@ -0,0 +1,3 @@ +const compareBuild = require('./compare-build') +const sort = (list, loose) => list.sort((a, b) => compareBuild(a, b, loose)) +module.exports = sort diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/valid.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/valid.js new file mode 100644 index 0000000..f27bae1 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/functions/valid.js @@ -0,0 +1,6 @@ +const parse = require('./parse') +const valid = (version, options) => { + const v = parse(version, options) + return v ? v.version : null +} +module.exports = valid diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/index.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/index.js new file mode 100644 index 0000000..068f8b4 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/index.js @@ -0,0 +1,64 @@ +const lrCache = {} +const lazyRequire = (path, subkey) => { + const module = lrCache[path] || (lrCache[path] = require(path)) + return subkey ? module[subkey] : module +} + +const lazyExport = (key, path, subkey) => { + Object.defineProperty(exports, key, { + get: () => { + const res = lazyRequire(path, subkey) + Object.defineProperty(exports, key, { + value: res, + enumerable: true, + configurable: true + }) + return res + }, + configurable: true, + enumerable: true + }) +} + +lazyExport('re', './internal/re', 're') +lazyExport('src', './internal/re', 'src') +lazyExport('tokens', './internal/re', 't') +lazyExport('SEMVER_SPEC_VERSION', './internal/constants', 'SEMVER_SPEC_VERSION') +lazyExport('SemVer', './classes/semver') +lazyExport('compareIdentifiers', './internal/identifiers', 'compareIdentifiers') +lazyExport('rcompareIdentifiers', './internal/identifiers', 'rcompareIdentifiers') +lazyExport('parse', './functions/parse') +lazyExport('valid', './functions/valid') +lazyExport('clean', './functions/clean') +lazyExport('inc', './functions/inc') +lazyExport('diff', './functions/diff') +lazyExport('major', './functions/major') +lazyExport('minor', './functions/minor') +lazyExport('patch', './functions/patch') +lazyExport('prerelease', './functions/prerelease') +lazyExport('compare', './functions/compare') +lazyExport('rcompare', './functions/rcompare') +lazyExport('compareLoose', './functions/compare-loose') +lazyExport('compareBuild', './functions/compare-build') +lazyExport('sort', './functions/sort') +lazyExport('rsort', './functions/rsort') +lazyExport('gt', './functions/gt') +lazyExport('lt', './functions/lt') +lazyExport('eq', './functions/eq') +lazyExport('neq', './functions/neq') +lazyExport('gte', './functions/gte') +lazyExport('lte', './functions/lte') +lazyExport('cmp', './functions/cmp') +lazyExport('coerce', './functions/coerce') +lazyExport('Comparator', './classes/comparator') +lazyExport('Range', './classes/range') +lazyExport('satisfies', './functions/satisfies') +lazyExport('toComparators', './ranges/to-comparators') +lazyExport('maxSatisfying', './ranges/max-satisfying') +lazyExport('minSatisfying', './ranges/min-satisfying') +lazyExport('minVersion', './ranges/min-version') +lazyExport('validRange', './ranges/valid') +lazyExport('outside', './ranges/outside') +lazyExport('gtr', './ranges/gtr') +lazyExport('ltr', './ranges/ltr') +lazyExport('intersects', './ranges/intersects') diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/constants.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/constants.js new file mode 100644 index 0000000..49df215 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/constants.js @@ -0,0 +1,17 @@ +// Note: this is the semver.org version of the spec that it implements +// Not necessarily the package version of this code. +const SEMVER_SPEC_VERSION = '2.0.0' + +const MAX_LENGTH = 256 +const MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || + /* istanbul ignore next */ 9007199254740991 + +// Max safe segment length for coercion. +const MAX_SAFE_COMPONENT_LENGTH = 16 + +module.exports = { + SEMVER_SPEC_VERSION, + MAX_LENGTH, + MAX_SAFE_INTEGER, + MAX_SAFE_COMPONENT_LENGTH +} diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/debug.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/debug.js new file mode 100644 index 0000000..1c00e13 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/debug.js @@ -0,0 +1,9 @@ +const debug = ( + typeof process === 'object' && + process.env && + process.env.NODE_DEBUG && + /\bsemver\b/i.test(process.env.NODE_DEBUG) +) ? (...args) => console.error('SEMVER', ...args) + : () => {} + +module.exports = debug diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/identifiers.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/identifiers.js new file mode 100644 index 0000000..ed13094 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/identifiers.js @@ -0,0 +1,23 @@ +const numeric = /^[0-9]+$/ +const compareIdentifiers = (a, b) => { + const anum = numeric.test(a) + const bnum = numeric.test(b) + + if (anum && bnum) { + a = +a + b = +b + } + + return a === b ? 0 + : (anum && !bnum) ? -1 + : (bnum && !anum) ? 1 + : a < b ? -1 + : 1 +} + +const rcompareIdentifiers = (a, b) => compareIdentifiers(b, a) + +module.exports = { + compareIdentifiers, + rcompareIdentifiers +} diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/re.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/re.js new file mode 100644 index 0000000..0e8fb52 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/internal/re.js @@ -0,0 +1,179 @@ +const { MAX_SAFE_COMPONENT_LENGTH } = require('./constants') +const debug = require('./debug') +exports = module.exports = {} + +// The actual regexps go on exports.re +const re = exports.re = [] +const src = exports.src = [] +const t = exports.t = {} +let R = 0 + +const createToken = (name, value, isGlobal) => { + const index = R++ + debug(index, value) + t[name] = index + src[index] = value + re[index] = new RegExp(value, isGlobal ? 'g' : undefined) +} + +// The following Regular Expressions can be used for tokenizing, +// validating, and parsing SemVer version strings. + +// ## Numeric Identifier +// A single `0`, or a non-zero digit followed by zero or more digits. + +createToken('NUMERICIDENTIFIER', '0|[1-9]\\d*') +createToken('NUMERICIDENTIFIERLOOSE', '[0-9]+') + +// ## Non-numeric Identifier +// Zero or more digits, followed by a letter or hyphen, and then zero or +// more letters, digits, or hyphens. + +createToken('NONNUMERICIDENTIFIER', '\\d*[a-zA-Z-][a-zA-Z0-9-]*') + +// ## Main Version +// Three dot-separated numeric identifiers. + +createToken('MAINVERSION', `(${src[t.NUMERICIDENTIFIER]})\\.` + + `(${src[t.NUMERICIDENTIFIER]})\\.` + + `(${src[t.NUMERICIDENTIFIER]})`) + +createToken('MAINVERSIONLOOSE', `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` + + `(${src[t.NUMERICIDENTIFIERLOOSE]})\\.` + + `(${src[t.NUMERICIDENTIFIERLOOSE]})`) + +// ## Pre-release Version Identifier +// A numeric identifier, or a non-numeric identifier. + +createToken('PRERELEASEIDENTIFIER', `(?:${src[t.NUMERICIDENTIFIER] +}|${src[t.NONNUMERICIDENTIFIER]})`) + +createToken('PRERELEASEIDENTIFIERLOOSE', `(?:${src[t.NUMERICIDENTIFIERLOOSE] +}|${src[t.NONNUMERICIDENTIFIER]})`) + +// ## Pre-release Version +// Hyphen, followed by one or more dot-separated pre-release version +// identifiers. + +createToken('PRERELEASE', `(?:-(${src[t.PRERELEASEIDENTIFIER] +}(?:\\.${src[t.PRERELEASEIDENTIFIER]})*))`) + +createToken('PRERELEASELOOSE', `(?:-?(${src[t.PRERELEASEIDENTIFIERLOOSE] +}(?:\\.${src[t.PRERELEASEIDENTIFIERLOOSE]})*))`) + +// ## Build Metadata Identifier +// Any combination of digits, letters, or hyphens. + +createToken('BUILDIDENTIFIER', '[0-9A-Za-z-]+') + +// ## Build Metadata +// Plus sign, followed by one or more period-separated build metadata +// identifiers. + +createToken('BUILD', `(?:\\+(${src[t.BUILDIDENTIFIER] +}(?:\\.${src[t.BUILDIDENTIFIER]})*))`) + +// ## Full Version String +// A main version, followed optionally by a pre-release version and +// build metadata. + +// Note that the only major, minor, patch, and pre-release sections of +// the version string are capturing groups. The build metadata is not a +// capturing group, because it should not ever be used in version +// comparison. + +createToken('FULLPLAIN', `v?${src[t.MAINVERSION] +}${src[t.PRERELEASE]}?${ + src[t.BUILD]}?`) + +createToken('FULL', `^${src[t.FULLPLAIN]}$`) + +// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. +// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty +// common in the npm registry. +createToken('LOOSEPLAIN', `[v=\\s]*${src[t.MAINVERSIONLOOSE] +}${src[t.PRERELEASELOOSE]}?${ + src[t.BUILD]}?`) + +createToken('LOOSE', `^${src[t.LOOSEPLAIN]}$`) + +createToken('GTLT', '((?:<|>)?=?)') + +// Something like "2.*" or "1.2.x". +// Note that "x.x" is a valid xRange identifer, meaning "any version" +// Only the first item is strictly required. +createToken('XRANGEIDENTIFIERLOOSE', `${src[t.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`) +createToken('XRANGEIDENTIFIER', `${src[t.NUMERICIDENTIFIER]}|x|X|\\*`) + +createToken('XRANGEPLAIN', `[v=\\s]*(${src[t.XRANGEIDENTIFIER]})` + + `(?:\\.(${src[t.XRANGEIDENTIFIER]})` + + `(?:\\.(${src[t.XRANGEIDENTIFIER]})` + + `(?:${src[t.PRERELEASE]})?${ + src[t.BUILD]}?` + + `)?)?`) + +createToken('XRANGEPLAINLOOSE', `[v=\\s]*(${src[t.XRANGEIDENTIFIERLOOSE]})` + + `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` + + `(?:\\.(${src[t.XRANGEIDENTIFIERLOOSE]})` + + `(?:${src[t.PRERELEASELOOSE]})?${ + src[t.BUILD]}?` + + `)?)?`) + +createToken('XRANGE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAIN]}$`) +createToken('XRANGELOOSE', `^${src[t.GTLT]}\\s*${src[t.XRANGEPLAINLOOSE]}$`) + +// Coercion. +// Extract anything that could conceivably be a part of a valid semver +createToken('COERCE', `${'(^|[^\\d])' + + '(\\d{1,'}${MAX_SAFE_COMPONENT_LENGTH}})` + + `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` + + `(?:\\.(\\d{1,${MAX_SAFE_COMPONENT_LENGTH}}))?` + + `(?:$|[^\\d])`) +createToken('COERCERTL', src[t.COERCE], true) + +// Tilde ranges. +// Meaning is "reasonably at or greater than" +createToken('LONETILDE', '(?:~>?)') + +createToken('TILDETRIM', `(\\s*)${src[t.LONETILDE]}\\s+`, true) +exports.tildeTrimReplace = '$1~' + +createToken('TILDE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAIN]}$`) +createToken('TILDELOOSE', `^${src[t.LONETILDE]}${src[t.XRANGEPLAINLOOSE]}$`) + +// Caret ranges. +// Meaning is "at least and backwards compatible with" +createToken('LONECARET', '(?:\\^)') + +createToken('CARETTRIM', `(\\s*)${src[t.LONECARET]}\\s+`, true) +exports.caretTrimReplace = '$1^' + +createToken('CARET', `^${src[t.LONECARET]}${src[t.XRANGEPLAIN]}$`) +createToken('CARETLOOSE', `^${src[t.LONECARET]}${src[t.XRANGEPLAINLOOSE]}$`) + +// A simple gt/lt/eq thing, or just "" to indicate "any version" +createToken('COMPARATORLOOSE', `^${src[t.GTLT]}\\s*(${src[t.LOOSEPLAIN]})$|^$`) +createToken('COMPARATOR', `^${src[t.GTLT]}\\s*(${src[t.FULLPLAIN]})$|^$`) + +// An expression to strip any whitespace between the gtlt and the thing +// it modifies, so that `> 1.2.3` ==> `>1.2.3` +createToken('COMPARATORTRIM', `(\\s*)${src[t.GTLT] +}\\s*(${src[t.LOOSEPLAIN]}|${src[t.XRANGEPLAIN]})`, true) +exports.comparatorTrimReplace = '$1$2$3' + +// Something like `1.2.3 - 1.2.4` +// Note that these all use the loose form, because they'll be +// checked against either the strict or loose comparator form +// later. +createToken('HYPHENRANGE', `^\\s*(${src[t.XRANGEPLAIN]})` + + `\\s+-\\s+` + + `(${src[t.XRANGEPLAIN]})` + + `\\s*$`) + +createToken('HYPHENRANGELOOSE', `^\\s*(${src[t.XRANGEPLAINLOOSE]})` + + `\\s+-\\s+` + + `(${src[t.XRANGEPLAINLOOSE]})` + + `\\s*$`) + +// Star ranges basically just allow anything at all. +createToken('STAR', '(<|>)?=?\\s*\\*') diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/package.json b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/package.json new file mode 100644 index 0000000..88574c0 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/package.json @@ -0,0 +1,34 @@ +{ + "name": "semver", + "version": "7.0.0", + "description": "The semantic version parser used by npm.", + "main": "index.js", + "scripts": { + "test": "tap", + "snap": "tap", + "preversion": "npm test", + "postversion": "npm publish", + "postpublish": "git push origin --follow-tags" + }, + "devDependencies": { + "tap": "^14.10.1" + }, + "license": "ISC", + "repository": "https://github.com/npm/node-semver", + "bin": { + "semver": "./bin/semver.js" + }, + "files": [ + "bin", + "range.bnf", + "classes", + "functions", + "internal", + "ranges", + "index.js" + ], + "tap": { + "check-coverage": true, + "coverage-map": "map.js" + } +} diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/range.bnf b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/range.bnf new file mode 100644 index 0000000..d4c6ae0 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/range.bnf @@ -0,0 +1,16 @@ +range-set ::= range ( logical-or range ) * +logical-or ::= ( ' ' ) * '||' ( ' ' ) * +range ::= hyphen | simple ( ' ' simple ) * | '' +hyphen ::= partial ' - ' partial +simple ::= primitive | partial | tilde | caret +primitive ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial +partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )? +xr ::= 'x' | 'X' | '*' | nr +nr ::= '0' | [1-9] ( [0-9] ) * +tilde ::= '~' partial +caret ::= '^' partial +qualifier ::= ( '-' pre )? ( '+' build )? +pre ::= parts +build ::= parts +parts ::= part ( '.' part ) * +part ::= nr | [-0-9A-Za-z]+ diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/gtr.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/gtr.js new file mode 100644 index 0000000..db7e355 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/gtr.js @@ -0,0 +1,4 @@ +// Determine if version is greater than all the versions possible in the range. +const outside = require('./outside') +const gtr = (version, range, options) => outside(version, range, '>', options) +module.exports = gtr diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/intersects.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/intersects.js new file mode 100644 index 0000000..3d1a6f3 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/intersects.js @@ -0,0 +1,7 @@ +const Range = require('../classes/range') +const intersects = (r1, r2, options) => { + r1 = new Range(r1, options) + r2 = new Range(r2, options) + return r1.intersects(r2) +} +module.exports = intersects diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/ltr.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/ltr.js new file mode 100644 index 0000000..528a885 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/ltr.js @@ -0,0 +1,4 @@ +const outside = require('./outside') +// Determine if version is less than all the versions possible in the range +const ltr = (version, range, options) => outside(version, range, '<', options) +module.exports = ltr diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/max-satisfying.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/max-satisfying.js new file mode 100644 index 0000000..6e3d993 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/max-satisfying.js @@ -0,0 +1,25 @@ +const SemVer = require('../classes/semver') +const Range = require('../classes/range') + +const maxSatisfying = (versions, range, options) => { + let max = null + let maxSV = null + let rangeObj = null + try { + rangeObj = new Range(range, options) + } catch (er) { + return null + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + // satisfies(v, range, options) + if (!max || maxSV.compare(v) === -1) { + // compare(max, v, true) + max = v + maxSV = new SemVer(max, options) + } + } + }) + return max +} +module.exports = maxSatisfying diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/min-satisfying.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/min-satisfying.js new file mode 100644 index 0000000..9b60974 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/min-satisfying.js @@ -0,0 +1,24 @@ +const SemVer = require('../classes/semver') +const Range = require('../classes/range') +const minSatisfying = (versions, range, options) => { + let min = null + let minSV = null + let rangeObj = null + try { + rangeObj = new Range(range, options) + } catch (er) { + return null + } + versions.forEach((v) => { + if (rangeObj.test(v)) { + // satisfies(v, range, options) + if (!min || minSV.compare(v) === 1) { + // compare(min, v, true) + min = v + minSV = new SemVer(min, options) + } + } + }) + return min +} +module.exports = minSatisfying diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/min-version.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/min-version.js new file mode 100644 index 0000000..7118d23 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/min-version.js @@ -0,0 +1,57 @@ +const SemVer = require('../classes/semver') +const Range = require('../classes/range') +const gt = require('../functions/gt') + +const minVersion = (range, loose) => { + range = new Range(range, loose) + + let minver = new SemVer('0.0.0') + if (range.test(minver)) { + return minver + } + + minver = new SemVer('0.0.0-0') + if (range.test(minver)) { + return minver + } + + minver = null + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i] + + comparators.forEach((comparator) => { + // Clone to avoid manipulating the comparator's semver object. + const compver = new SemVer(comparator.semver.version) + switch (comparator.operator) { + case '>': + if (compver.prerelease.length === 0) { + compver.patch++ + } else { + compver.prerelease.push(0) + } + compver.raw = compver.format() + /* fallthrough */ + case '': + case '>=': + if (!minver || gt(minver, compver)) { + minver = compver + } + break + case '<': + case '<=': + /* Ignore maximum versions */ + break + /* istanbul ignore next */ + default: + throw new Error(`Unexpected operation: ${comparator.operator}`) + } + }) + } + + if (minver && range.test(minver)) { + return minver + } + + return null +} +module.exports = minVersion diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/outside.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/outside.js new file mode 100644 index 0000000..e35ed11 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/outside.js @@ -0,0 +1,80 @@ +const SemVer = require('../classes/semver') +const Comparator = require('../classes/comparator') +const {ANY} = Comparator +const Range = require('../classes/range') +const satisfies = require('../functions/satisfies') +const gt = require('../functions/gt') +const lt = require('../functions/lt') +const lte = require('../functions/lte') +const gte = require('../functions/gte') + +const outside = (version, range, hilo, options) => { + version = new SemVer(version, options) + range = new Range(range, options) + + let gtfn, ltefn, ltfn, comp, ecomp + switch (hilo) { + case '>': + gtfn = gt + ltefn = lte + ltfn = lt + comp = '>' + ecomp = '>=' + break + case '<': + gtfn = lt + ltefn = gte + ltfn = gt + comp = '<' + ecomp = '<=' + break + default: + throw new TypeError('Must provide a hilo val of "<" or ">"') + } + + // If it satisifes the range it is not outside + if (satisfies(version, range, options)) { + return false + } + + // From now on, variable terms are as if we're in "gtr" mode. + // but note that everything is flipped for the "ltr" function. + + for (let i = 0; i < range.set.length; ++i) { + const comparators = range.set[i] + + let high = null + let low = null + + comparators.forEach((comparator) => { + if (comparator.semver === ANY) { + comparator = new Comparator('>=0.0.0') + } + high = high || comparator + low = low || comparator + if (gtfn(comparator.semver, high.semver, options)) { + high = comparator + } else if (ltfn(comparator.semver, low.semver, options)) { + low = comparator + } + }) + + // If the edge version comparator has a operator then our version + // isn't outside it + if (high.operator === comp || high.operator === ecomp) { + return false + } + + // If the lowest version comparator has an operator and our version + // is less than it then it isn't higher than the range + if ((!low.operator || low.operator === comp) && + ltefn(version, low.semver)) { + return false + } else if (low.operator === ecomp && ltfn(version, low.semver)) { + return false + } + } + return true +} + +module.exports = outside diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/to-comparators.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/to-comparators.js new file mode 100644 index 0000000..6c8bc7e --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/to-comparators.js @@ -0,0 +1,8 @@ +const Range = require('../classes/range') + +// Mostly just for testing and legacy API reasons +const toComparators = (range, options) => + new Range(range, options).set + .map(comp => comp.map(c => c.value).join(' ').trim().split(' ')) + +module.exports = toComparators diff --git a/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/valid.js b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/valid.js new file mode 100644 index 0000000..365f356 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/node_modules/semver/ranges/valid.js @@ -0,0 +1,11 @@ +const Range = require('../classes/range') +const validRange = (range, options) => { + try { + // Return '*' instead of '' so that truthiness works. + // This will throw if it's invalid anyway + return new Range(range, options).range || '*' + } catch (er) { + return null + } +} +module.exports = validRange diff --git a/homework8/project_express/node_modules/simple-update-notifier/package.json b/homework8/project_express/node_modules/simple-update-notifier/package.json new file mode 100644 index 0000000..8c0f330 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/package.json @@ -0,0 +1,97 @@ +{ + "name": "simple-update-notifier", + "version": "1.0.7", + "description": "Simple update notifier to check for npm updates for cli applications", + "main": "build/index.js", + "types": "build/index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/alexbrazier/simple-update-notifier.git" + }, + "homepage": "https://github.com/alexbrazier/simple-update-notifier.git", + "author": "alexbrazier", + "license": "MIT", + "engines": { + "node": ">=8.10.0" + }, + "scripts": { + "test": "jest src", + "build": "rollup -c rollup.config.js", + "prettier:check": "prettier --check src/**/*.ts", + "prettier": "prettier --write src/**/*.ts", + "eslint": "eslint src/**/*.ts", + "lint": "yarn prettier:check && yarn eslint", + "prepare": "yarn lint && yarn build", + "release": "release-it" + }, + "dependencies": { + "semver": "~7.0.0" + }, + "devDependencies": { + "@babel/preset-env": "^7.18.2", + "@babel/preset-typescript": "^7.17.12", + "@release-it/conventional-changelog": "^5.0.0", + "@types/jest": "^28.1.3", + "@types/node": "^18.0.0", + "@typescript-eslint/eslint-plugin": "^5.29.0", + "@typescript-eslint/parser": "^5.29.0", + "eslint": "^8.18.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-prettier": "^4.0.0", + "jest": "^28.1.1", + "prettier": "^2.7.1", + "release-it": "^15.1.1", + "rollup": "^2.75.7", + "rollup-plugin-ts": "^3.0.2", + "typescript": "^4.7.4" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org/" + }, + "files": [ + "build", + "src" + ], + "release-it": { + "git": { + "commitMessage": "chore: release ${version}", + "tagName": "v${version}" + }, + "npm": { + "publish": true + }, + "github": { + "release": true + }, + "plugins": { + "@release-it/conventional-changelog": { + "preset": "angular", + "infile": "CHANGELOG.md" + } + } + }, + "eslintConfig": { + "plugins": [ + "@typescript-eslint", + "prettier" + ], + "extends": [ + "prettier", + "eslint:recommended", + "plugin:@typescript-eslint/recommended" + ], + "parser": "@typescript-eslint/parser", + "rules": { + "prettier/prettier": [ + "error", + { + "quoteProps": "consistent", + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "es5", + "useTabs": false + } + ] + } + } +} diff --git a/homework8/project_express/node_modules/simple-update-notifier/src/borderedText.ts b/homework8/project_express/node_modules/simple-update-notifier/src/borderedText.ts new file mode 100644 index 0000000..7145ac2 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/src/borderedText.ts @@ -0,0 +1,12 @@ +const borderedText = (text: string) => { + const lines = text.split('\n'); + const width = Math.max(...lines.map((l) => l.length)); + const res = [`┌${'─'.repeat(width + 2)}┐`]; + for (const line of lines) { + res.push(`│ ${line.padEnd(width)} │`); + } + res.push(`└${'─'.repeat(width + 2)}┘`); + return res.join('\n'); +}; + +export default borderedText; diff --git a/homework8/project_express/node_modules/simple-update-notifier/src/cache.spec.ts b/homework8/project_express/node_modules/simple-update-notifier/src/cache.spec.ts new file mode 100644 index 0000000..cea66fa --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/src/cache.spec.ts @@ -0,0 +1,12 @@ +import { createConfigDir, getLastUpdate, saveLastUpdate } from './cache'; + +createConfigDir(); + +jest.useFakeTimers().setSystemTime(new Date('2022-01-01')); + +const fakeTime = new Date('2022-01-01').getTime(); + +test('can save update then get the update details', () => { + saveLastUpdate('test'); + expect(getLastUpdate('test')).toBe(fakeTime); +}); diff --git a/homework8/project_express/node_modules/simple-update-notifier/src/cache.ts b/homework8/project_express/node_modules/simple-update-notifier/src/cache.ts new file mode 100644 index 0000000..97a73e7 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/src/cache.ts @@ -0,0 +1,41 @@ +import os from 'os'; +import path from 'path'; +import fs from 'fs'; + +const homeDirectory = os.homedir(); +const configDir = + process.env.XDG_CONFIG_HOME || + path.join(homeDirectory, '.config', 'simple-update-notifier'); + +const getConfigFile = (packageName: string) => { + return path.join(configDir, `${packageName}.json`); +}; + +export const createConfigDir = () => { + if (!fs.existsSync(configDir)) { + fs.mkdirSync(configDir, { recursive: true }); + } +}; + +export const getLastUpdate = (packageName: string) => { + const configFile = getConfigFile(packageName); + + try { + if (!fs.existsSync(configFile)) { + return undefined; + } + const file = JSON.parse(fs.readFileSync(configFile, 'utf8')); + return file.lastUpdateCheck as number; + } catch { + return undefined; + } +}; + +export const saveLastUpdate = (packageName: string) => { + const configFile = getConfigFile(packageName); + + fs.writeFileSync( + configFile, + JSON.stringify({ lastUpdateCheck: new Date().getTime() }) + ); +}; diff --git a/homework8/project_express/node_modules/simple-update-notifier/src/getDistVersion.spec.ts b/homework8/project_express/node_modules/simple-update-notifier/src/getDistVersion.spec.ts new file mode 100644 index 0000000..b78a42e --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/src/getDistVersion.spec.ts @@ -0,0 +1,35 @@ +import Stream from 'stream'; +import https from 'https'; +import getDistVersion from './getDistVersion'; + +jest.mock('https', () => ({ + get: jest.fn(), +})); + +test('Valid response returns version', async () => { + const st = new Stream(); + (https.get as jest.Mock).mockImplementation((url, cb) => { + cb(st); + + st.emit('data', '{"latest":"1.0.0"}'); + st.emit('end'); + }); + + const version = await getDistVersion('test', 'latest'); + + expect(version).toEqual('1.0.0'); +}); + +test('Invalid response throws error', async () => { + const st = new Stream(); + (https.get as jest.Mock).mockImplementation((url, cb) => { + cb(st); + + st.emit('data', 'some invalid json'); + st.emit('end'); + }); + + expect(getDistVersion('test', 'latest')).rejects.toThrow( + 'Could not parse version response' + ); +}); diff --git a/homework8/project_express/node_modules/simple-update-notifier/src/getDistVersion.ts b/homework8/project_express/node_modules/simple-update-notifier/src/getDistVersion.ts new file mode 100644 index 0000000..d474e1f --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/src/getDistVersion.ts @@ -0,0 +1,29 @@ +import https from 'https'; + +const getDistVersion = async (packageName: string, distTag: string) => { + const url = `https://registry.npmjs.org/-/package/${packageName}/dist-tags`; + + return new Promise((resolve, reject) => { + https + .get(url, (res) => { + let body = ''; + + res.on('data', (chunk) => (body += chunk)); + res.on('end', () => { + try { + const json = JSON.parse(body); + const version = json[distTag]; + if (!version) { + reject(new Error('Error getting version')); + } + resolve(version); + } catch { + reject(new Error('Could not parse version response')); + } + }); + }) + .on('error', (err) => reject(err)); + }); +}; + +export default getDistVersion; diff --git a/homework8/project_express/node_modules/simple-update-notifier/src/hasNewVersion.spec.ts b/homework8/project_express/node_modules/simple-update-notifier/src/hasNewVersion.spec.ts new file mode 100644 index 0000000..af7ab22 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/src/hasNewVersion.spec.ts @@ -0,0 +1,82 @@ +import hasNewVersion from './hasNewVersion'; +import { getLastUpdate } from './cache'; +import getDistVersion from './getDistVersion'; + +jest.mock('./getDistVersion', () => jest.fn().mockReturnValue('1.0.0')); +jest.mock('./cache', () => ({ + getLastUpdate: jest.fn().mockReturnValue(undefined), + createConfigDir: jest.fn(), + saveLastUpdate: jest.fn(), +})); + +const pkg = { name: 'test', version: '1.0.0' }; + +afterEach(() => jest.clearAllMocks()); + +const defaultArgs = { + pkg, + shouldNotifyInNpmScript: true, + alwaysRun: true, +}; + +test('it should not trigger update for same version', async () => { + const newVersion = await hasNewVersion(defaultArgs); + + expect(newVersion).toBe(false); +}); + +test('it should trigger update for patch version bump', async () => { + (getDistVersion as jest.Mock).mockReturnValue('1.0.1'); + + const newVersion = await hasNewVersion(defaultArgs); + + expect(newVersion).toBe('1.0.1'); +}); + +test('it should trigger update for minor version bump', async () => { + (getDistVersion as jest.Mock).mockReturnValue('1.1.0'); + + const newVersion = await hasNewVersion(defaultArgs); + + expect(newVersion).toBe('1.1.0'); +}); + +test('it should trigger update for major version bump', async () => { + (getDistVersion as jest.Mock).mockReturnValue('2.0.0'); + + const newVersion = await hasNewVersion(defaultArgs); + + expect(newVersion).toBe('2.0.0'); +}); + +test('it should not trigger update if version is lower', async () => { + (getDistVersion as jest.Mock).mockReturnValue('0.0.9'); + + const newVersion = await hasNewVersion(defaultArgs); + + expect(newVersion).toBe(false); +}); + +it('should trigger update check if last update older than config', async () => { + const TWO_WEEKS = new Date().getTime() - 1000 * 60 * 60 * 24 * 14; + (getLastUpdate as jest.Mock).mockReturnValue(TWO_WEEKS); + const newVersion = await hasNewVersion({ + pkg, + shouldNotifyInNpmScript: true, + }); + + expect(newVersion).toBe(false); + expect(getDistVersion).toHaveBeenCalled(); +}); + +it('should not trigger update check if last update is too recent', async () => { + const TWELVE_HOURS = new Date().getTime() - 1000 * 60 * 60 * 12; + (getLastUpdate as jest.Mock).mockReturnValue(TWELVE_HOURS); + const newVersion = await hasNewVersion({ + pkg, + shouldNotifyInNpmScript: true, + }); + + expect(newVersion).toBe(false); + expect(getDistVersion).not.toHaveBeenCalled(); +}); diff --git a/homework8/project_express/node_modules/simple-update-notifier/src/hasNewVersion.ts b/homework8/project_express/node_modules/simple-update-notifier/src/hasNewVersion.ts new file mode 100644 index 0000000..a55c747 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/src/hasNewVersion.ts @@ -0,0 +1,30 @@ +import semver from 'semver'; +import { createConfigDir, getLastUpdate, saveLastUpdate } from './cache'; +import getDistVersion from './getDistVersion'; +import { IUpdate } from './types'; + +const hasNewVersion = async ({ + pkg, + updateCheckInterval = 1000 * 60 * 60 * 24, + distTag = 'latest', + alwaysRun, +}: IUpdate) => { + createConfigDir(); + const lastUpdateCheck = getLastUpdate(pkg.name); + if ( + alwaysRun || + !lastUpdateCheck || + lastUpdateCheck < new Date().getTime() - updateCheckInterval + ) { + const latestVersion = await getDistVersion(pkg.name, distTag); + saveLastUpdate(pkg.name); + if (semver.gt(latestVersion, pkg.version)) { + return latestVersion; + } + return false; + } else { + return false; + } +}; + +export default hasNewVersion; diff --git a/homework8/project_express/node_modules/simple-update-notifier/src/index.spec.ts b/homework8/project_express/node_modules/simple-update-notifier/src/index.spec.ts new file mode 100644 index 0000000..77d5de1 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/src/index.spec.ts @@ -0,0 +1,27 @@ +import simpleUpdateNotifier from '.'; +import hasNewVersion from './hasNewVersion'; + +const consoleSpy = jest.spyOn(console, 'log'); + +jest.mock('./hasNewVersion', () => jest.fn().mockResolvedValue('2.0.0')); + +beforeEach(jest.clearAllMocks); + +test('it logs message if update is available', async () => { + await simpleUpdateNotifier({ + pkg: { name: 'test', version: '1.0.0' }, + alwaysRun: true, + }); + + expect(consoleSpy).toHaveBeenCalledTimes(1); +}); + +test('it does not log message if update is not available', async () => { + (hasNewVersion as jest.Mock).mockResolvedValue(false); + await simpleUpdateNotifier({ + pkg: { name: 'test', version: '2.0.0' }, + alwaysRun: true, + }); + + expect(consoleSpy).toHaveBeenCalledTimes(0); +}); diff --git a/homework8/project_express/node_modules/simple-update-notifier/src/index.ts b/homework8/project_express/node_modules/simple-update-notifier/src/index.ts new file mode 100644 index 0000000..69c48a2 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/src/index.ts @@ -0,0 +1,28 @@ +import isNpmOrYarn from './isNpmOrYarn'; +import hasNewVersion from './hasNewVersion'; +import { IUpdate } from './types'; +import borderedText from './borderedText'; + +const simpleUpdateNotifier = async (args: IUpdate) => { + if ( + !args.alwaysRun && + (!process.stdout.isTTY || (isNpmOrYarn && !args.shouldNotifyInNpmScript)) + ) { + return; + } + + try { + const latestVersion = await hasNewVersion(args); + if (latestVersion) { + console.log( + borderedText(`New version of ${args.pkg.name} available! +Current Version: ${args.pkg.version} +Latest Version: ${latestVersion}`) + ); + } + } catch { + // Catch any network errors or cache writing errors so module doesn't cause a crash + } +}; + +export default simpleUpdateNotifier; diff --git a/homework8/project_express/node_modules/simple-update-notifier/src/isNpmOrYarn.ts b/homework8/project_express/node_modules/simple-update-notifier/src/isNpmOrYarn.ts new file mode 100644 index 0000000..ee4c837 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/src/isNpmOrYarn.ts @@ -0,0 +1,12 @@ +import process from 'process'; + +const packageJson = process.env.npm_package_json; +const userAgent = process.env.npm_config_user_agent; +const isNpm6 = Boolean(userAgent && userAgent.startsWith('npm')); +const isNpm7 = Boolean(packageJson && packageJson.endsWith('package.json')); + +const isNpm = isNpm6 || isNpm7; +const isYarn = Boolean(userAgent && userAgent.startsWith('yarn')); +const isNpmOrYarn = isNpm || isYarn; + +export default isNpmOrYarn; diff --git a/homework8/project_express/node_modules/simple-update-notifier/src/types.ts b/homework8/project_express/node_modules/simple-update-notifier/src/types.ts new file mode 100644 index 0000000..cb94563 --- /dev/null +++ b/homework8/project_express/node_modules/simple-update-notifier/src/types.ts @@ -0,0 +1,7 @@ +export interface IUpdate { + pkg: { name: string; version: string }; + updateCheckInterval?: number; + shouldNotifyInNpmScript?: boolean; + distTag?: string; + alwaysRun?: boolean; +} diff --git a/homework8/project_express/node_modules/source-map/.npmignore b/homework8/project_express/node_modules/source-map/.npmignore new file mode 100644 index 0000000..3dddf3f --- /dev/null +++ b/homework8/project_express/node_modules/source-map/.npmignore @@ -0,0 +1,2 @@ +dist/* +node_modules/* diff --git a/homework8/project_express/node_modules/source-map/.travis.yml b/homework8/project_express/node_modules/source-map/.travis.yml new file mode 100644 index 0000000..ddc9c4f --- /dev/null +++ b/homework8/project_express/node_modules/source-map/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.8 + - "0.10" \ No newline at end of file diff --git a/homework8/project_express/node_modules/source-map/CHANGELOG.md b/homework8/project_express/node_modules/source-map/CHANGELOG.md new file mode 100644 index 0000000..2e7ca5d --- /dev/null +++ b/homework8/project_express/node_modules/source-map/CHANGELOG.md @@ -0,0 +1,194 @@ +# Change Log + +## 0.1.43 + +* Performance improvements for `SourceMapGenerator` and `SourceNode`. See issue + #148 for some discussion and issues #150, #151, and #152 for implementations. + +## 0.1.42 + +* Fix an issue where `SourceNode`s from different versions of the source-map + library couldn't be used in conjunction with each other. See issue #142. + +## 0.1.41 + +* Fix a bug with getting the source content of relative sources with a "./" + prefix. See issue #145 and [Bug 1090768](bugzil.la/1090768). + +* Add the `SourceMapConsumer.prototype.computeColumnSpans` method to compute the + column span of each mapping. + +* Add the `SourceMapConsumer.prototype.allGeneratedPositionsFor` method to find + all generated positions associated with a given original source and line. + +## 0.1.40 + +* Performance improvements for parsing source maps in SourceMapConsumer. + +## 0.1.39 + +* Fix a bug where setting a source's contents to null before any source content + had been set before threw a TypeError. See issue #131. + +## 0.1.38 + +* Fix a bug where finding relative paths from an empty path were creating + absolute paths. See issue #129. + +## 0.1.37 + +* Fix a bug where if the source root was an empty string, relative source paths + would turn into absolute source paths. Issue #124. + +## 0.1.36 + +* Allow the `names` mapping property to be an empty string. Issue #121. + +## 0.1.35 + +* A third optional parameter was added to `SourceNode.fromStringWithSourceMap` + to specify a path that relative sources in the second parameter should be + relative to. Issue #105. + +* If no file property is given to a `SourceMapGenerator`, then the resulting + source map will no longer have a `null` file property. The property will + simply not exist. Issue #104. + +* Fixed a bug where consecutive newlines were ignored in `SourceNode`s. + Issue #116. + +## 0.1.34 + +* Make `SourceNode` work with windows style ("\r\n") newlines. Issue #103. + +* Fix bug involving source contents and the + `SourceMapGenerator.prototype.applySourceMap`. Issue #100. + +## 0.1.33 + +* Fix some edge cases surrounding path joining and URL resolution. + +* Add a third parameter for relative path to + `SourceMapGenerator.prototype.applySourceMap`. + +* Fix issues with mappings and EOLs. + +## 0.1.32 + +* Fixed a bug where SourceMapConsumer couldn't handle negative relative columns + (issue 92). + +* Fixed test runner to actually report number of failed tests as its process + exit code. + +* Fixed a typo when reporting bad mappings (issue 87). + +## 0.1.31 + +* Delay parsing the mappings in SourceMapConsumer until queried for a source + location. + +* Support Sass source maps (which at the time of writing deviate from the spec + in small ways) in SourceMapConsumer. + +## 0.1.30 + +* Do not join source root with a source, when the source is a data URI. + +* Extend the test runner to allow running single specific test files at a time. + +* Performance improvements in `SourceNode.prototype.walk` and + `SourceMapConsumer.prototype.eachMapping`. + +* Source map browser builds will now work inside Workers. + +* Better error messages when attempting to add an invalid mapping to a + `SourceMapGenerator`. + +## 0.1.29 + +* Allow duplicate entries in the `names` and `sources` arrays of source maps + (usually from TypeScript) we are parsing. Fixes github issue 72. + +## 0.1.28 + +* Skip duplicate mappings when creating source maps from SourceNode; github + issue 75. + +## 0.1.27 + +* Don't throw an error when the `file` property is missing in SourceMapConsumer, + we don't use it anyway. + +## 0.1.26 + +* Fix SourceNode.fromStringWithSourceMap for empty maps. Fixes github issue 70. + +## 0.1.25 + +* Make compatible with browserify + +## 0.1.24 + +* Fix issue with absolute paths and `file://` URIs. See + https://bugzilla.mozilla.org/show_bug.cgi?id=885597 + +## 0.1.23 + +* Fix issue with absolute paths and sourcesContent, github issue 64. + +## 0.1.22 + +* Ignore duplicate mappings in SourceMapGenerator. Fixes github issue 21. + +## 0.1.21 + +* Fixed handling of sources that start with a slash so that they are relative to + the source root's host. + +## 0.1.20 + +* Fixed github issue #43: absolute URLs aren't joined with the source root + anymore. + +## 0.1.19 + +* Using Travis CI to run tests. + +## 0.1.18 + +* Fixed a bug in the handling of sourceRoot. + +## 0.1.17 + +* Added SourceNode.fromStringWithSourceMap. + +## 0.1.16 + +* Added missing documentation. + +* Fixed the generating of empty mappings in SourceNode. + +## 0.1.15 + +* Added SourceMapGenerator.applySourceMap. + +## 0.1.14 + +* The sourceRoot is now handled consistently. + +## 0.1.13 + +* Added SourceMapGenerator.fromSourceMap. + +## 0.1.12 + +* SourceNode now generates empty mappings too. + +## 0.1.11 + +* Added name support to SourceNode. + +## 0.1.10 + +* Added sourcesContent support to the customer and generator. diff --git a/homework8/project_express/node_modules/source-map/LICENSE b/homework8/project_express/node_modules/source-map/LICENSE new file mode 100644 index 0000000..ed1b7cf --- /dev/null +++ b/homework8/project_express/node_modules/source-map/LICENSE @@ -0,0 +1,28 @@ + +Copyright (c) 2009-2011, Mozilla Foundation and contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the names of the Mozilla Foundation nor the names of project + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/homework8/project_express/node_modules/source-map/Makefile.dryice.js b/homework8/project_express/node_modules/source-map/Makefile.dryice.js new file mode 100644 index 0000000..d6fc26a --- /dev/null +++ b/homework8/project_express/node_modules/source-map/Makefile.dryice.js @@ -0,0 +1,166 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +var path = require('path'); +var fs = require('fs'); +var copy = require('dryice').copy; + +function removeAmdefine(src) { + src = String(src).replace( + /if\s*\(typeof\s*define\s*!==\s*'function'\)\s*{\s*var\s*define\s*=\s*require\('amdefine'\)\(module,\s*require\);\s*}\s*/g, + ''); + src = src.replace( + /\b(define\(.*)('amdefine',?)/gm, + '$1'); + return src; +} +removeAmdefine.onRead = true; + +function makeNonRelative(src) { + return src + .replace(/require\('.\//g, 'require(\'source-map/') + .replace(/\.\.\/\.\.\/lib\//g, ''); +} +makeNonRelative.onRead = true; + +function buildBrowser() { + console.log('\nCreating dist/source-map.js'); + + var project = copy.createCommonJsProject({ + roots: [ path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/mini-require.js', + { + project: project, + require: [ 'source-map/source-map-generator', + 'source-map/source-map-consumer', + 'source-map/source-node'] + }, + 'build/suffix-browser.js' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine + ], + dest: 'dist/source-map.js' + }); +} + +function buildBrowserMin() { + console.log('\nCreating dist/source-map.min.js'); + + copy({ + source: 'dist/source-map.js', + filter: copy.filter.uglifyjs, + dest: 'dist/source-map.min.js' + }); +} + +function buildFirefox() { + console.log('\nCreating dist/SourceMap.jsm'); + + var project = copy.createCommonJsProject({ + roots: [ path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/prefix-source-map.jsm', + { + project: project, + require: [ 'source-map/source-map-consumer', + 'source-map/source-map-generator', + 'source-map/source-node' ] + }, + 'build/suffix-source-map.jsm' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine, + makeNonRelative + ], + dest: 'dist/SourceMap.jsm' + }); + + // Create dist/test/Utils.jsm + console.log('\nCreating dist/test/Utils.jsm'); + + project = copy.createCommonJsProject({ + roots: [ __dirname, path.join(__dirname, 'lib') ] + }); + + copy({ + source: [ + 'build/prefix-utils.jsm', + 'build/assert-shim.js', + { + project: project, + require: [ 'test/source-map/util' ] + }, + 'build/suffix-utils.jsm' + ], + filter: [ + copy.filter.moduleDefines, + removeAmdefine, + makeNonRelative + ], + dest: 'dist/test/Utils.jsm' + }); + + function isTestFile(f) { + return /^test\-.*?\.js/.test(f); + } + + var testFiles = fs.readdirSync(path.join(__dirname, 'test', 'source-map')).filter(isTestFile); + + testFiles.forEach(function (testFile) { + console.log('\nCreating', path.join('dist', 'test', testFile.replace(/\-/g, '_'))); + + copy({ + source: [ + 'build/test-prefix.js', + path.join('test', 'source-map', testFile), + 'build/test-suffix.js' + ], + filter: [ + removeAmdefine, + makeNonRelative, + function (input, source) { + return input.replace('define(', + 'define("' + + path.join('test', 'source-map', testFile.replace(/\.js$/, '')) + + '", ["require", "exports", "module"], '); + }, + function (input, source) { + return input.replace('{THIS_MODULE}', function () { + return "test/source-map/" + testFile.replace(/\.js$/, ''); + }); + } + ], + dest: path.join('dist', 'test', testFile.replace(/\-/g, '_')) + }); + }); +} + +function ensureDir(name) { + var dirExists = false; + try { + dirExists = fs.statSync(name).isDirectory(); + } catch (err) {} + + if (!dirExists) { + fs.mkdirSync(name, 0777); + } +} + +ensureDir("dist"); +ensureDir("dist/test"); +buildFirefox(); +buildBrowser(); +buildBrowserMin(); diff --git a/homework8/project_express/node_modules/source-map/README.md b/homework8/project_express/node_modules/source-map/README.md new file mode 100644 index 0000000..59767aa --- /dev/null +++ b/homework8/project_express/node_modules/source-map/README.md @@ -0,0 +1,475 @@ +# Source Map + +This is a library to generate and consume the source map format +[described here][format]. + +This library is written in the Asynchronous Module Definition format, and works +in the following environments: + +* Modern Browsers supporting ECMAScript 5 (either after the build, or with an + AMD loader such as RequireJS) + +* Inside Firefox (as a JSM file, after the build) + +* With NodeJS versions 0.8.X and higher + +## Node + + $ npm install source-map + +## Building from Source (for everywhere else) + +Install Node and then run + + $ git clone https://fitzgen@github.com/mozilla/source-map.git + $ cd source-map + $ npm link . + +Next, run + + $ node Makefile.dryice.js + +This should spew a bunch of stuff to stdout, and create the following files: + +* `dist/source-map.js` - The unminified browser version. + +* `dist/source-map.min.js` - The minified browser version. + +* `dist/SourceMap.jsm` - The JavaScript Module for inclusion in Firefox source. + +## Examples + +### Consuming a source map + + var rawSourceMap = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourceRoot: 'http://example.com/www/js/', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + + var smc = new SourceMapConsumer(rawSourceMap); + + console.log(smc.sources); + // [ 'http://example.com/www/js/one.js', + // 'http://example.com/www/js/two.js' ] + + console.log(smc.originalPositionFor({ + line: 2, + column: 28 + })); + // { source: 'http://example.com/www/js/two.js', + // line: 2, + // column: 10, + // name: 'n' } + + console.log(smc.generatedPositionFor({ + source: 'http://example.com/www/js/two.js', + line: 2, + column: 10 + })); + // { line: 2, column: 28 } + + smc.eachMapping(function (m) { + // ... + }); + +### Generating a source map + +In depth guide: +[**Compiling to JavaScript, and Debugging with Source Maps**](https://hacks.mozilla.org/2013/05/compiling-to-javascript-and-debugging-with-source-maps/) + +#### With SourceNode (high level API) + + function compile(ast) { + switch (ast.type) { + case 'BinaryExpression': + return new SourceNode( + ast.location.line, + ast.location.column, + ast.location.source, + [compile(ast.left), " + ", compile(ast.right)] + ); + case 'Literal': + return new SourceNode( + ast.location.line, + ast.location.column, + ast.location.source, + String(ast.value) + ); + // ... + default: + throw new Error("Bad AST"); + } + } + + var ast = parse("40 + 2", "add.js"); + console.log(compile(ast).toStringWithSourceMap({ + file: 'add.js' + })); + // { code: '40 + 2', + // map: [object SourceMapGenerator] } + +#### With SourceMapGenerator (low level API) + + var map = new SourceMapGenerator({ + file: "source-mapped.js" + }); + + map.addMapping({ + generated: { + line: 10, + column: 35 + }, + source: "foo.js", + original: { + line: 33, + column: 2 + }, + name: "christopher" + }); + + console.log(map.toString()); + // '{"version":3,"file":"source-mapped.js","sources":["foo.js"],"names":["christopher"],"mappings":";;;;;;;;;mCAgCEA"}' + +## API + +Get a reference to the module: + + // NodeJS + var sourceMap = require('source-map'); + + // Browser builds + var sourceMap = window.sourceMap; + + // Inside Firefox + let sourceMap = {}; + Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap); + +### SourceMapConsumer + +A SourceMapConsumer instance represents a parsed source map which we can query +for information about the original file positions by giving it a file position +in the generated source. + +#### new SourceMapConsumer(rawSourceMap) + +The only parameter is the raw source map (either as a string which can be +`JSON.parse`'d, or an object). According to the spec, source maps have the +following attributes: + +* `version`: Which version of the source map spec this map is following. + +* `sources`: An array of URLs to the original source files. + +* `names`: An array of identifiers which can be referrenced by individual + mappings. + +* `sourceRoot`: Optional. The URL root from which all sources are relative. + +* `sourcesContent`: Optional. An array of contents of the original source files. + +* `mappings`: A string of base64 VLQs which contain the actual mappings. + +* `file`: Optional. The generated filename this source map is associated with. + +#### SourceMapConsumer.prototype.computeColumnSpans() + +Compute the last column for each generated mapping. The last column is +inclusive. + +#### SourceMapConsumer.prototype.originalPositionFor(generatedPosition) + +Returns the original source, line, and column information for the generated +source's line and column positions provided. The only argument is an object with +the following properties: + +* `line`: The line number in the generated source. + +* `column`: The column number in the generated source. + +and an object is returned with the following properties: + +* `source`: The original source file, or null if this information is not + available. + +* `line`: The line number in the original source, or null if this information is + not available. + +* `column`: The column number in the original source, or null or null if this + information is not available. + +* `name`: The original identifier, or null if this information is not available. + +#### SourceMapConsumer.prototype.generatedPositionFor(originalPosition) + +Returns the generated line and column information for the original source, +line, and column positions provided. The only argument is an object with +the following properties: + +* `source`: The filename of the original source. + +* `line`: The line number in the original source. + +* `column`: The column number in the original source. + +and an object is returned with the following properties: + +* `line`: The line number in the generated source, or null. + +* `column`: The column number in the generated source, or null. + +#### SourceMapConsumer.prototype.allGeneratedPositionsFor(originalPosition) + +Returns all generated line and column information for the original source +and line provided. The only argument is an object with the following +properties: + +* `source`: The filename of the original source. + +* `line`: The line number in the original source. + +and an array of objects is returned, each with the following properties: + +* `line`: The line number in the generated source, or null. + +* `column`: The column number in the generated source, or null. + +#### SourceMapConsumer.prototype.sourceContentFor(source) + +Returns the original source content for the source provided. The only +argument is the URL of the original source file. + +#### SourceMapConsumer.prototype.eachMapping(callback, context, order) + +Iterate over each mapping between an original source/line/column and a +generated line/column in this source map. + +* `callback`: The function that is called with each mapping. Mappings have the + form `{ source, generatedLine, generatedColumn, originalLine, originalColumn, + name }` + +* `context`: Optional. If specified, this object will be the value of `this` + every time that `callback` is called. + +* `order`: Either `SourceMapConsumer.GENERATED_ORDER` or + `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to iterate over + the mappings sorted by the generated file's line/column order or the + original's source/line/column order, respectively. Defaults to + `SourceMapConsumer.GENERATED_ORDER`. + +### SourceMapGenerator + +An instance of the SourceMapGenerator represents a source map which is being +built incrementally. + +#### new SourceMapGenerator([startOfSourceMap]) + +You may pass an object with the following properties: + +* `file`: The filename of the generated source that this source map is + associated with. + +* `sourceRoot`: A root for all relative URLs in this source map. + +* `skipValidation`: Optional. When `true`, disables validation of mappings as + they are added. This can improve performance but should be used with + discretion, as a last resort. Even then, one should avoid using this flag when + running tests, if possible. + +#### SourceMapGenerator.fromSourceMap(sourceMapConsumer) + +Creates a new SourceMapGenerator based on a SourceMapConsumer + +* `sourceMapConsumer` The SourceMap. + +#### SourceMapGenerator.prototype.addMapping(mapping) + +Add a single mapping from original source line and column to the generated +source's line and column for this source map being created. The mapping object +should have the following properties: + +* `generated`: An object with the generated line and column positions. + +* `original`: An object with the original line and column positions. + +* `source`: The original source file (relative to the sourceRoot). + +* `name`: An optional original token name for this mapping. + +#### SourceMapGenerator.prototype.setSourceContent(sourceFile, sourceContent) + +Set the source content for an original source file. + +* `sourceFile` the URL of the original source file. + +* `sourceContent` the content of the source file. + +#### SourceMapGenerator.prototype.applySourceMap(sourceMapConsumer[, sourceFile[, sourceMapPath]]) + +Applies a SourceMap for a source file to the SourceMap. +Each mapping to the supplied source file is rewritten using the +supplied SourceMap. Note: The resolution for the resulting mappings +is the minimium of this map and the supplied map. + +* `sourceMapConsumer`: The SourceMap to be applied. + +* `sourceFile`: Optional. The filename of the source file. + If omitted, sourceMapConsumer.file will be used, if it exists. + Otherwise an error will be thrown. + +* `sourceMapPath`: Optional. The dirname of the path to the SourceMap + to be applied. If relative, it is relative to the SourceMap. + + This parameter is needed when the two SourceMaps aren't in the same + directory, and the SourceMap to be applied contains relative source + paths. If so, those relative source paths need to be rewritten + relative to the SourceMap. + + If omitted, it is assumed that both SourceMaps are in the same directory, + thus not needing any rewriting. (Supplying `'.'` has the same effect.) + +#### SourceMapGenerator.prototype.toString() + +Renders the source map being generated to a string. + +### SourceNode + +SourceNodes provide a way to abstract over interpolating and/or concatenating +snippets of generated JavaScript source code, while maintaining the line and +column information associated between those snippets and the original source +code. This is useful as the final intermediate representation a compiler might +use before outputting the generated JS and source map. + +#### new SourceNode([line, column, source[, chunk[, name]]]) + +* `line`: The original line number associated with this source node, or null if + it isn't associated with an original line. + +* `column`: The original column number associated with this source node, or null + if it isn't associated with an original column. + +* `source`: The original source's filename; null if no filename is provided. + +* `chunk`: Optional. Is immediately passed to `SourceNode.prototype.add`, see + below. + +* `name`: Optional. The original identifier. + +#### SourceNode.fromStringWithSourceMap(code, sourceMapConsumer[, relativePath]) + +Creates a SourceNode from generated code and a SourceMapConsumer. + +* `code`: The generated code + +* `sourceMapConsumer` The SourceMap for the generated code + +* `relativePath` The optional path that relative sources in `sourceMapConsumer` + should be relative to. + +#### SourceNode.prototype.add(chunk) + +Add a chunk of generated JS to this source node. + +* `chunk`: A string snippet of generated JS code, another instance of + `SourceNode`, or an array where each member is one of those things. + +#### SourceNode.prototype.prepend(chunk) + +Prepend a chunk of generated JS to this source node. + +* `chunk`: A string snippet of generated JS code, another instance of + `SourceNode`, or an array where each member is one of those things. + +#### SourceNode.prototype.setSourceContent(sourceFile, sourceContent) + +Set the source content for a source file. This will be added to the +`SourceMap` in the `sourcesContent` field. + +* `sourceFile`: The filename of the source file + +* `sourceContent`: The content of the source file + +#### SourceNode.prototype.walk(fn) + +Walk over the tree of JS snippets in this node and its children. The walking +function is called once for each snippet of JS and is passed that snippet and +the its original associated source's line/column location. + +* `fn`: The traversal function. + +#### SourceNode.prototype.walkSourceContents(fn) + +Walk over the tree of SourceNodes. The walking function is called for each +source file content and is passed the filename and source content. + +* `fn`: The traversal function. + +#### SourceNode.prototype.join(sep) + +Like `Array.prototype.join` except for SourceNodes. Inserts the separator +between each of this source node's children. + +* `sep`: The separator. + +#### SourceNode.prototype.replaceRight(pattern, replacement) + +Call `String.prototype.replace` on the very right-most source snippet. Useful +for trimming whitespace from the end of a source node, etc. + +* `pattern`: The pattern to replace. + +* `replacement`: The thing to replace the pattern with. + +#### SourceNode.prototype.toString() + +Return the string representation of this source node. Walks over the tree and +concatenates all the various snippets together to one string. + +#### SourceNode.prototype.toStringWithSourceMap([startOfSourceMap]) + +Returns the string representation of this tree of source nodes, plus a +SourceMapGenerator which contains all the mappings between the generated and +original sources. + +The arguments are the same as those to `new SourceMapGenerator`. + +## Tests + +[![Build Status](https://travis-ci.org/mozilla/source-map.png?branch=master)](https://travis-ci.org/mozilla/source-map) + +Install NodeJS version 0.8.0 or greater, then run `node test/run-tests.js`. + +To add new tests, create a new file named `test/test-.js` +and export your test functions with names that start with "test", for example + + exports["test doing the foo bar"] = function (assert, util) { + ... + }; + +The new test will be located automatically when you run the suite. + +The `util` argument is the test utility module located at `test/source-map/util`. + +The `assert` argument is a cut down version of node's assert module. You have +access to the following assertion functions: + +* `doesNotThrow` + +* `equal` + +* `ok` + +* `strictEqual` + +* `throws` + +(The reason for the restricted set of test functions is because we need the +tests to run inside Firefox's test suite as well and so the assert module is +shimmed in that environment. See `build/assert-shim.js`.) + +[format]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit +[feature]: https://wiki.mozilla.org/DevTools/Features/SourceMap +[Dryice]: https://github.com/mozilla/dryice diff --git a/homework8/project_express/node_modules/source-map/build/assert-shim.js b/homework8/project_express/node_modules/source-map/build/assert-shim.js new file mode 100644 index 0000000..daa1a62 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/build/assert-shim.js @@ -0,0 +1,56 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +define('test/source-map/assert', ['exports'], function (exports) { + + let do_throw = function (msg) { + throw new Error(msg); + }; + + exports.init = function (throw_fn) { + do_throw = throw_fn; + }; + + exports.doesNotThrow = function (fn) { + try { + fn(); + } + catch (e) { + do_throw(e.message); + } + }; + + exports.equal = function (actual, expected, msg) { + msg = msg || String(actual) + ' != ' + String(expected); + if (actual != expected) { + do_throw(msg); + } + }; + + exports.ok = function (val, msg) { + msg = msg || String(val) + ' is falsey'; + if (!Boolean(val)) { + do_throw(msg); + } + }; + + exports.strictEqual = function (actual, expected, msg) { + msg = msg || String(actual) + ' !== ' + String(expected); + if (actual !== expected) { + do_throw(msg); + } + }; + + exports.throws = function (fn) { + try { + fn(); + do_throw('Expected an error to be thrown, but it wasn\'t.'); + } + catch (e) { + } + }; + +}); diff --git a/homework8/project_express/node_modules/source-map/build/mini-require.js b/homework8/project_express/node_modules/source-map/build/mini-require.js new file mode 100644 index 0000000..0daf453 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/build/mini-require.js @@ -0,0 +1,152 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/** + * Define a module along with a payload. + * @param {string} moduleName Name for the payload + * @param {ignored} deps Ignored. For compatibility with CommonJS AMD Spec + * @param {function} payload Function with (require, exports, module) params + */ +function define(moduleName, deps, payload) { + if (typeof moduleName != "string") { + throw new TypeError('Expected string, got: ' + moduleName); + } + + if (arguments.length == 2) { + payload = deps; + } + + if (moduleName in define.modules) { + throw new Error("Module already defined: " + moduleName); + } + define.modules[moduleName] = payload; +}; + +/** + * The global store of un-instantiated modules + */ +define.modules = {}; + + +/** + * We invoke require() in the context of a Domain so we can have multiple + * sets of modules running separate from each other. + * This contrasts with JSMs which are singletons, Domains allows us to + * optionally load a CommonJS module twice with separate data each time. + * Perhaps you want 2 command lines with a different set of commands in each, + * for example. + */ +function Domain() { + this.modules = {}; + this._currentModule = null; +} + +(function () { + + /** + * Lookup module names and resolve them by calling the definition function if + * needed. + * There are 2 ways to call this, either with an array of dependencies and a + * callback to call when the dependencies are found (which can happen + * asynchronously in an in-page context) or with a single string an no callback + * where the dependency is resolved synchronously and returned. + * The API is designed to be compatible with the CommonJS AMD spec and + * RequireJS. + * @param {string[]|string} deps A name, or names for the payload + * @param {function|undefined} callback Function to call when the dependencies + * are resolved + * @return {undefined|object} The module required or undefined for + * array/callback method + */ + Domain.prototype.require = function(deps, callback) { + if (Array.isArray(deps)) { + var params = deps.map(function(dep) { + return this.lookup(dep); + }, this); + if (callback) { + callback.apply(null, params); + } + return undefined; + } + else { + return this.lookup(deps); + } + }; + + function normalize(path) { + var bits = path.split('/'); + var i = 1; + while (i < bits.length) { + if (bits[i] === '..') { + bits.splice(i-1, 1); + } else if (bits[i] === '.') { + bits.splice(i, 1); + } else { + i++; + } + } + return bits.join('/'); + } + + function join(a, b) { + a = a.trim(); + b = b.trim(); + if (/^\//.test(b)) { + return b; + } else { + return a.replace(/\/*$/, '/') + b; + } + } + + function dirname(path) { + var bits = path.split('/'); + bits.pop(); + return bits.join('/'); + } + + /** + * Lookup module names and resolve them by calling the definition function if + * needed. + * @param {string} moduleName A name for the payload to lookup + * @return {object} The module specified by aModuleName or null if not found. + */ + Domain.prototype.lookup = function(moduleName) { + if (/^\./.test(moduleName)) { + moduleName = normalize(join(dirname(this._currentModule), moduleName)); + } + + if (moduleName in this.modules) { + var module = this.modules[moduleName]; + return module; + } + + if (!(moduleName in define.modules)) { + throw new Error("Module not defined: " + moduleName); + } + + var module = define.modules[moduleName]; + + if (typeof module == "function") { + var exports = {}; + var previousModule = this._currentModule; + this._currentModule = moduleName; + module(this.require.bind(this), exports, { id: moduleName, uri: "" }); + this._currentModule = previousModule; + module = exports; + } + + // cache the resulting module object for next time + this.modules[moduleName] = module; + + return module; + }; + +}()); + +define.Domain = Domain; +define.globalDomain = new Domain(); +var require = define.globalDomain.require.bind(define.globalDomain); diff --git a/homework8/project_express/node_modules/source-map/build/prefix-source-map.jsm b/homework8/project_express/node_modules/source-map/build/prefix-source-map.jsm new file mode 100644 index 0000000..ee2539d --- /dev/null +++ b/homework8/project_express/node_modules/source-map/build/prefix-source-map.jsm @@ -0,0 +1,20 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +/////////////////////////////////////////////////////////////////////////////// + + +this.EXPORTED_SYMBOLS = [ "SourceMapConsumer", "SourceMapGenerator", "SourceNode" ]; + +Components.utils.import('resource://gre/modules/devtools/Require.jsm'); diff --git a/homework8/project_express/node_modules/source-map/build/prefix-utils.jsm b/homework8/project_express/node_modules/source-map/build/prefix-utils.jsm new file mode 100644 index 0000000..80341d4 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/build/prefix-utils.jsm @@ -0,0 +1,18 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ + +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +Components.utils.import('resource://gre/modules/devtools/Require.jsm'); +Components.utils.import('resource://gre/modules/devtools/SourceMap.jsm'); + +this.EXPORTED_SYMBOLS = [ "define", "runSourceMapTests" ]; diff --git a/homework8/project_express/node_modules/source-map/build/suffix-browser.js b/homework8/project_express/node_modules/source-map/build/suffix-browser.js new file mode 100644 index 0000000..fb29ff5 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/build/suffix-browser.js @@ -0,0 +1,8 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/////////////////////////////////////////////////////////////////////////////// + +this.sourceMap = { + SourceMapConsumer: require('source-map/source-map-consumer').SourceMapConsumer, + SourceMapGenerator: require('source-map/source-map-generator').SourceMapGenerator, + SourceNode: require('source-map/source-node').SourceNode +}; diff --git a/homework8/project_express/node_modules/source-map/build/suffix-source-map.jsm b/homework8/project_express/node_modules/source-map/build/suffix-source-map.jsm new file mode 100644 index 0000000..cf3c2d8 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/build/suffix-source-map.jsm @@ -0,0 +1,6 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/////////////////////////////////////////////////////////////////////////////// + +this.SourceMapConsumer = require('source-map/source-map-consumer').SourceMapConsumer; +this.SourceMapGenerator = require('source-map/source-map-generator').SourceMapGenerator; +this.SourceNode = require('source-map/source-node').SourceNode; diff --git a/homework8/project_express/node_modules/source-map/build/suffix-utils.jsm b/homework8/project_express/node_modules/source-map/build/suffix-utils.jsm new file mode 100644 index 0000000..b31b84c --- /dev/null +++ b/homework8/project_express/node_modules/source-map/build/suffix-utils.jsm @@ -0,0 +1,21 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +function runSourceMapTests(modName, do_throw) { + let mod = require(modName); + let assert = require('test/source-map/assert'); + let util = require('test/source-map/util'); + + assert.init(do_throw); + + for (let k in mod) { + if (/^test/.test(k)) { + mod[k](assert, util); + } + } + +} +this.runSourceMapTests = runSourceMapTests; diff --git a/homework8/project_express/node_modules/source-map/build/test-prefix.js b/homework8/project_express/node_modules/source-map/build/test-prefix.js new file mode 100644 index 0000000..1b13f30 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/build/test-prefix.js @@ -0,0 +1,8 @@ +/* + * WARNING! + * + * Do not edit this file directly, it is built from the sources at + * https://github.com/mozilla/source-map/ + */ + +Components.utils.import('resource://test/Utils.jsm'); diff --git a/homework8/project_express/node_modules/source-map/build/test-suffix.js b/homework8/project_express/node_modules/source-map/build/test-suffix.js new file mode 100644 index 0000000..bec2de3 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/build/test-suffix.js @@ -0,0 +1,3 @@ +function run_test() { + runSourceMapTests('{THIS_MODULE}', do_throw); +} diff --git a/homework8/project_express/node_modules/source-map/lib/source-map.js b/homework8/project_express/node_modules/source-map/lib/source-map.js new file mode 100644 index 0000000..121ad24 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/lib/source-map.js @@ -0,0 +1,8 @@ +/* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause + */ +exports.SourceMapGenerator = require('./source-map/source-map-generator').SourceMapGenerator; +exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer; +exports.SourceNode = require('./source-map/source-node').SourceNode; diff --git a/homework8/project_express/node_modules/source-map/lib/source-map/array-set.js b/homework8/project_express/node_modules/source-map/lib/source-map/array-set.js new file mode 100644 index 0000000..40f9a18 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/lib/source-map/array-set.js @@ -0,0 +1,97 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('./util'); + + /** + * A data structure which is a combination of an array and a set. Adding a new + * member is O(1), testing for membership is O(1), and finding the index of an + * element is O(1). Removing elements from the set is not supported. Only + * strings are supported for membership. + */ + function ArraySet() { + this._array = []; + this._set = {}; + } + + /** + * Static method for creating ArraySet instances from an existing array. + */ + ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) { + var set = new ArraySet(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i], aAllowDuplicates); + } + return set; + }; + + /** + * Add the given string to this set. + * + * @param String aStr + */ + ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) { + var isDuplicate = this.has(aStr); + var idx = this._array.length; + if (!isDuplicate || aAllowDuplicates) { + this._array.push(aStr); + } + if (!isDuplicate) { + this._set[util.toSetString(aStr)] = idx; + } + }; + + /** + * Is the given string a member of this set? + * + * @param String aStr + */ + ArraySet.prototype.has = function ArraySet_has(aStr) { + return Object.prototype.hasOwnProperty.call(this._set, + util.toSetString(aStr)); + }; + + /** + * What is the index of the given string in the array? + * + * @param String aStr + */ + ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { + if (this.has(aStr)) { + return this._set[util.toSetString(aStr)]; + } + throw new Error('"' + aStr + '" is not in the set.'); + }; + + /** + * What is the element at the given index? + * + * @param Number aIdx + */ + ArraySet.prototype.at = function ArraySet_at(aIdx) { + if (aIdx >= 0 && aIdx < this._array.length) { + return this._array[aIdx]; + } + throw new Error('No element indexed by ' + aIdx); + }; + + /** + * Returns the array representation of this set (which has the proper indices + * indicated by indexOf). Note that this is a copy of the internal array used + * for storing the members so that no one can mess with internal state. + */ + ArraySet.prototype.toArray = function ArraySet_toArray() { + return this._array.slice(); + }; + + exports.ArraySet = ArraySet; + +}); diff --git a/homework8/project_express/node_modules/source-map/lib/source-map/base64-vlq.js b/homework8/project_express/node_modules/source-map/lib/source-map/base64-vlq.js new file mode 100644 index 0000000..e22dcae --- /dev/null +++ b/homework8/project_express/node_modules/source-map/lib/source-map/base64-vlq.js @@ -0,0 +1,142 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + * + * Based on the Base 64 VLQ implementation in Closure Compiler: + * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java + * + * Copyright 2011 The Closure Compiler Authors. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64 = require('./base64'); + + // A single base 64 digit can contain 6 bits of data. For the base 64 variable + // length quantities we use in the source map spec, the first bit is the sign, + // the next four bits are the actual value, and the 6th bit is the + // continuation bit. The continuation bit tells us whether there are more + // digits in this value following this digit. + // + // Continuation + // | Sign + // | | + // V V + // 101011 + + var VLQ_BASE_SHIFT = 5; + + // binary: 100000 + var VLQ_BASE = 1 << VLQ_BASE_SHIFT; + + // binary: 011111 + var VLQ_BASE_MASK = VLQ_BASE - 1; + + // binary: 100000 + var VLQ_CONTINUATION_BIT = VLQ_BASE; + + /** + * Converts from a two-complement value to a value where the sign bit is + * placed in the least significant bit. For example, as decimals: + * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) + * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) + */ + function toVLQSigned(aValue) { + return aValue < 0 + ? ((-aValue) << 1) + 1 + : (aValue << 1) + 0; + } + + /** + * Converts to a two-complement value from a value where the sign bit is + * placed in the least significant bit. For example, as decimals: + * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 + * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 + */ + function fromVLQSigned(aValue) { + var isNegative = (aValue & 1) === 1; + var shifted = aValue >> 1; + return isNegative + ? -shifted + : shifted; + } + + /** + * Returns the base 64 VLQ encoded value. + */ + exports.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; + + var vlq = toVLQSigned(aValue); + + do { + digit = vlq & VLQ_BASE_MASK; + vlq >>>= VLQ_BASE_SHIFT; + if (vlq > 0) { + // There are still more digits in this value, so we must make sure the + // continuation bit is marked. + digit |= VLQ_CONTINUATION_BIT; + } + encoded += base64.encode(digit); + } while (vlq > 0); + + return encoded; + }; + + /** + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string via the out parameter. + */ + exports.decode = function base64VLQ_decode(aStr, aOutParam) { + var i = 0; + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; + + do { + if (i >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); + } + digit = base64.decode(aStr.charAt(i++)); + continuation = !!(digit & VLQ_CONTINUATION_BIT); + digit &= VLQ_BASE_MASK; + result = result + (digit << shift); + shift += VLQ_BASE_SHIFT; + } while (continuation); + + aOutParam.value = fromVLQSigned(result); + aOutParam.rest = aStr.slice(i); + }; + +}); diff --git a/homework8/project_express/node_modules/source-map/lib/source-map/base64.js b/homework8/project_express/node_modules/source-map/lib/source-map/base64.js new file mode 100644 index 0000000..863cc46 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/lib/source-map/base64.js @@ -0,0 +1,42 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var charToIntMap = {}; + var intToCharMap = {}; + + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + .split('') + .forEach(function (ch, index) { + charToIntMap[ch] = index; + intToCharMap[index] = ch; + }); + + /** + * Encode an integer in the range of 0 to 63 to a single base 64 digit. + */ + exports.encode = function base64_encode(aNumber) { + if (aNumber in intToCharMap) { + return intToCharMap[aNumber]; + } + throw new TypeError("Must be between 0 and 63: " + aNumber); + }; + + /** + * Decode a single base 64 digit to an integer. + */ + exports.decode = function base64_decode(aChar) { + if (aChar in charToIntMap) { + return charToIntMap[aChar]; + } + throw new TypeError("Not a valid base 64 digit: " + aChar); + }; + +}); diff --git a/homework8/project_express/node_modules/source-map/lib/source-map/binary-search.js b/homework8/project_express/node_modules/source-map/lib/source-map/binary-search.js new file mode 100644 index 0000000..e085f81 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/lib/source-map/binary-search.js @@ -0,0 +1,80 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + /** + * Recursive implementation of binary search. + * + * @param aLow Indices here and lower do not contain the needle. + * @param aHigh Indices here and higher do not contain the needle. + * @param aNeedle The element being searched for. + * @param aHaystack The non-empty array being searched. + * @param aCompare Function which takes two elements and returns -1, 0, or 1. + */ + function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) { + // This function terminates when one of the following is true: + // + // 1. We find the exact element we are looking for. + // + // 2. We did not find the exact element, but we can return the index of + // the next closest element that is less than that element. + // + // 3. We did not find the exact element, and there is no next-closest + // element which is less than the one we are searching for, so we + // return -1. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid], true); + if (cmp === 0) { + // Found the element we are looking for. + return mid; + } + else if (cmp > 0) { + // aHaystack[mid] is greater than our needle. + if (aHigh - mid > 1) { + // The element is in the upper half. + return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare); + } + // We did not find an exact match, return the next closest one + // (termination case 2). + return mid; + } + else { + // aHaystack[mid] is less than our needle. + if (mid - aLow > 1) { + // The element is in the lower half. + return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare); + } + // The exact needle element was not found in this haystack. Determine if + // we are in termination case (2) or (3) and return the appropriate thing. + return aLow < 0 ? -1 : aLow; + } + } + + /** + * This is an implementation of binary search which will always try and return + * the index of next lowest value checked if there is no exact hit. This is + * because mappings between original and generated line/col pairs are single + * points, and there is an implicit region between each of them, so a miss + * just means that you aren't on the very start of a region. + * + * @param aNeedle The element you are looking for. + * @param aHaystack The array that is being searched. + * @param aCompare A function which takes the needle and an element in the + * array and returns -1, 0, or 1 depending on whether the needle is less + * than, equal to, or greater than the element, respectively. + */ + exports.search = function search(aNeedle, aHaystack, aCompare) { + if (aHaystack.length === 0) { + return -1; + } + return recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare) + }; + +}); diff --git a/homework8/project_express/node_modules/source-map/lib/source-map/mapping-list.js b/homework8/project_express/node_modules/source-map/lib/source-map/mapping-list.js new file mode 100644 index 0000000..2a4eb61 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/lib/source-map/mapping-list.js @@ -0,0 +1,86 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2014 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('./util'); + + /** + * Determine whether mappingB is after mappingA with respect to generated + * position. + */ + function generatedPositionAfter(mappingA, mappingB) { + // Optimized for most common case + var lineA = mappingA.generatedLine; + var lineB = mappingB.generatedLine; + var columnA = mappingA.generatedColumn; + var columnB = mappingB.generatedColumn; + return lineB > lineA || lineB == lineA && columnB >= columnA || + util.compareByGeneratedPositions(mappingA, mappingB) <= 0; + } + + /** + * A data structure to provide a sorted view of accumulated mappings in a + * performance conscious manner. It trades a neglibable overhead in general + * case for a large speedup in case of mappings being added in order. + */ + function MappingList() { + this._array = []; + this._sorted = true; + // Serves as infimum + this._last = {generatedLine: -1, generatedColumn: 0}; + } + + /** + * Iterate through internal items. This method takes the same arguments that + * `Array.prototype.forEach` takes. + * + * NOTE: The order of the mappings is NOT guaranteed. + */ + MappingList.prototype.unsortedForEach = + function MappingList_forEach(aCallback, aThisArg) { + this._array.forEach(aCallback, aThisArg); + }; + + /** + * Add the given source mapping. + * + * @param Object aMapping + */ + MappingList.prototype.add = function MappingList_add(aMapping) { + var mapping; + if (generatedPositionAfter(this._last, aMapping)) { + this._last = aMapping; + this._array.push(aMapping); + } else { + this._sorted = false; + this._array.push(aMapping); + } + }; + + /** + * Returns the flat, sorted array of mappings. The mappings are sorted by + * generated position. + * + * WARNING: This method returns internal data without copying, for + * performance. The return value must NOT be mutated, and should be treated as + * an immutable borrow. If you want to take ownership, you must make your own + * copy. + */ + MappingList.prototype.toArray = function MappingList_toArray() { + if (!this._sorted) { + this._array.sort(util.compareByGeneratedPositions); + this._sorted = true; + } + return this._array; + }; + + exports.MappingList = MappingList; + +}); diff --git a/homework8/project_express/node_modules/source-map/lib/source-map/source-map-consumer.js b/homework8/project_express/node_modules/source-map/lib/source-map/source-map-consumer.js new file mode 100644 index 0000000..cfaa299 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/lib/source-map/source-map-consumer.js @@ -0,0 +1,575 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('./util'); + var binarySearch = require('./binary-search'); + var ArraySet = require('./array-set').ArraySet; + var base64VLQ = require('./base64-vlq'); + + /** + * A SourceMapConsumer instance represents a parsed source map which we can + * query for information about the original file positions by giving it a file + * position in the generated source. + * + * The only parameter is the raw source map (either as a JSON string, or + * already parsed to an object). According to the spec, source maps have the + * following attributes: + * + * - version: Which version of the source map spec this map is following. + * - sources: An array of URLs to the original source files. + * - names: An array of identifiers which can be referrenced by individual mappings. + * - sourceRoot: Optional. The URL root from which all sources are relative. + * - sourcesContent: Optional. An array of contents of the original source files. + * - mappings: A string of base64 VLQs which contain the actual mappings. + * - file: Optional. The generated file this source map is associated with. + * + * Here is an example source map, taken from the source map spec[0]: + * + * { + * version : 3, + * file: "out.js", + * sourceRoot : "", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AA,AB;;ABCDE;" + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# + */ + function SourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sources = util.getArg(sourceMap, 'sources'); + // Sass 3.3 leaves out the 'names' array, so we deviate from the spec (which + // requires the array) to play nice here. + var names = util.getArg(sourceMap, 'names', []); + var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); + var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null); + var mappings = util.getArg(sourceMap, 'mappings'); + var file = util.getArg(sourceMap, 'file', null); + + // Once again, Sass deviates from the spec and supplies the version as a + // string rather than a number, so we use loose equality checking here. + if (version != this._version) { + throw new Error('Unsupported version: ' + version); + } + + // Some source maps produce relative source paths like "./foo.js" instead of + // "foo.js". Normalize these first so that future comparisons will succeed. + // See bugzil.la/1090768. + sources = sources.map(util.normalize); + + // Pass `true` below to allow duplicate names and sources. While source maps + // are intended to be compressed and deduplicated, the TypeScript compiler + // sometimes generates source maps with duplicates in them. See Github issue + // #72 and bugzil.la/889492. + this._names = ArraySet.fromArray(names, true); + this._sources = ArraySet.fromArray(sources, true); + + this.sourceRoot = sourceRoot; + this.sourcesContent = sourcesContent; + this._mappings = mappings; + this.file = file; + } + + /** + * Create a SourceMapConsumer from a SourceMapGenerator. + * + * @param SourceMapGenerator aSourceMap + * The source map that will be consumed. + * @returns SourceMapConsumer + */ + SourceMapConsumer.fromSourceMap = + function SourceMapConsumer_fromSourceMap(aSourceMap) { + var smc = Object.create(SourceMapConsumer.prototype); + + smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true); + smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true); + smc.sourceRoot = aSourceMap._sourceRoot; + smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), + smc.sourceRoot); + smc.file = aSourceMap._file; + + smc.__generatedMappings = aSourceMap._mappings.toArray().slice(); + smc.__originalMappings = aSourceMap._mappings.toArray().slice() + .sort(util.compareByOriginalPositions); + + return smc; + }; + + /** + * The version of the source mapping spec that we are consuming. + */ + SourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(SourceMapConsumer.prototype, 'sources', { + get: function () { + return this._sources.toArray().map(function (s) { + return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s; + }, this); + } + }); + + // `__generatedMappings` and `__originalMappings` are arrays that hold the + // parsed mapping coordinates from the source map's "mappings" attribute. They + // are lazily instantiated, accessed via the `_generatedMappings` and + // `_originalMappings` getters respectively, and we only parse the mappings + // and create these arrays once queried for a source location. We jump through + // these hoops because there can be many thousands of mappings, and parsing + // them is expensive, so we only want to do it if we must. + // + // Each object in the arrays is of the form: + // + // { + // generatedLine: The line number in the generated code, + // generatedColumn: The column number in the generated code, + // source: The path to the original source file that generated this + // chunk of code, + // originalLine: The line number in the original source that + // corresponds to this chunk of generated code, + // originalColumn: The column number in the original source that + // corresponds to this chunk of generated code, + // name: The name of the original symbol which generated this chunk of + // code. + // } + // + // All properties except for `generatedLine` and `generatedColumn` can be + // `null`. + // + // `_generatedMappings` is ordered by the generated positions. + // + // `_originalMappings` is ordered by the original positions. + + SourceMapConsumer.prototype.__generatedMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', { + get: function () { + if (!this.__generatedMappings) { + this.__generatedMappings = []; + this.__originalMappings = []; + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__generatedMappings; + } + }); + + SourceMapConsumer.prototype.__originalMappings = null; + Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', { + get: function () { + if (!this.__originalMappings) { + this.__generatedMappings = []; + this.__originalMappings = []; + this._parseMappings(this._mappings, this.sourceRoot); + } + + return this.__originalMappings; + } + }); + + SourceMapConsumer.prototype._nextCharIsMappingSeparator = + function SourceMapConsumer_nextCharIsMappingSeparator(aStr) { + var c = aStr.charAt(0); + return c === ";" || c === ","; + }; + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (the ordered arrays in the `this.__generatedMappings` and + * `this.__originalMappings` properties). + */ + SourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + var generatedLine = 1; + var previousGeneratedColumn = 0; + var previousOriginalLine = 0; + var previousOriginalColumn = 0; + var previousSource = 0; + var previousName = 0; + var str = aStr; + var temp = {}; + var mapping; + + while (str.length > 0) { + if (str.charAt(0) === ';') { + generatedLine++; + str = str.slice(1); + previousGeneratedColumn = 0; + } + else if (str.charAt(0) === ',') { + str = str.slice(1); + } + else { + mapping = {}; + mapping.generatedLine = generatedLine; + + // Generated column. + base64VLQ.decode(str, temp); + mapping.generatedColumn = previousGeneratedColumn + temp.value; + previousGeneratedColumn = mapping.generatedColumn; + str = temp.rest; + + if (str.length > 0 && !this._nextCharIsMappingSeparator(str)) { + // Original source. + base64VLQ.decode(str, temp); + mapping.source = this._sources.at(previousSource + temp.value); + previousSource += temp.value; + str = temp.rest; + if (str.length === 0 || this._nextCharIsMappingSeparator(str)) { + throw new Error('Found a source, but no line and column'); + } + + // Original line. + base64VLQ.decode(str, temp); + mapping.originalLine = previousOriginalLine + temp.value; + previousOriginalLine = mapping.originalLine; + // Lines are stored 0-based + mapping.originalLine += 1; + str = temp.rest; + if (str.length === 0 || this._nextCharIsMappingSeparator(str)) { + throw new Error('Found a source and line, but no column'); + } + + // Original column. + base64VLQ.decode(str, temp); + mapping.originalColumn = previousOriginalColumn + temp.value; + previousOriginalColumn = mapping.originalColumn; + str = temp.rest; + + if (str.length > 0 && !this._nextCharIsMappingSeparator(str)) { + // Original name. + base64VLQ.decode(str, temp); + mapping.name = this._names.at(previousName + temp.value); + previousName += temp.value; + str = temp.rest; + } + } + + this.__generatedMappings.push(mapping); + if (typeof mapping.originalLine === 'number') { + this.__originalMappings.push(mapping); + } + } + } + + this.__generatedMappings.sort(util.compareByGeneratedPositions); + this.__originalMappings.sort(util.compareByOriginalPositions); + }; + + /** + * Find the mapping that best matches the hypothetical "needle" mapping that + * we are searching for in the given "haystack" of mappings. + */ + SourceMapConsumer.prototype._findMapping = + function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, + aColumnName, aComparator) { + // To return the position we are searching for, we must first find the + // mapping for the given position and then return the opposite position it + // points to. Because the mappings are sorted, we can use binary search to + // find the best mapping. + + if (aNeedle[aLineName] <= 0) { + throw new TypeError('Line must be greater than or equal to 1, got ' + + aNeedle[aLineName]); + } + if (aNeedle[aColumnName] < 0) { + throw new TypeError('Column must be greater than or equal to 0, got ' + + aNeedle[aColumnName]); + } + + return binarySearch.search(aNeedle, aMappings, aComparator); + }; + + /** + * Compute the last column for each generated mapping. The last column is + * inclusive. + */ + SourceMapConsumer.prototype.computeColumnSpans = + function SourceMapConsumer_computeColumnSpans() { + for (var index = 0; index < this._generatedMappings.length; ++index) { + var mapping = this._generatedMappings[index]; + + // Mappings do not contain a field for the last generated columnt. We + // can come up with an optimistic estimate, however, by assuming that + // mappings are contiguous (i.e. given two consecutive mappings, the + // first mapping ends where the second one starts). + if (index + 1 < this._generatedMappings.length) { + var nextMapping = this._generatedMappings[index + 1]; + + if (mapping.generatedLine === nextMapping.generatedLine) { + mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1; + continue; + } + } + + // The last mapping for each line spans the entire line. + mapping.lastGeneratedColumn = Infinity; + } + }; + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ + SourceMapConsumer.prototype.originalPositionFor = + function SourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + var index = this._findMapping(needle, + this._generatedMappings, + "generatedLine", + "generatedColumn", + util.compareByGeneratedPositions); + + if (index >= 0) { + var mapping = this._generatedMappings[index]; + + if (mapping.generatedLine === needle.generatedLine) { + var source = util.getArg(mapping, 'source', null); + if (source != null && this.sourceRoot != null) { + source = util.join(this.sourceRoot, source); + } + return { + source: source, + line: util.getArg(mapping, 'originalLine', null), + column: util.getArg(mapping, 'originalColumn', null), + name: util.getArg(mapping, 'name', null) + }; + } + } + + return { + source: null, + line: null, + column: null, + name: null + }; + }; + + /** + * Returns the original source content. The only argument is the url of the + * original source file. Returns null if no original source content is + * availible. + */ + SourceMapConsumer.prototype.sourceContentFor = + function SourceMapConsumer_sourceContentFor(aSource) { + if (!this.sourcesContent) { + return null; + } + + if (this.sourceRoot != null) { + aSource = util.relative(this.sourceRoot, aSource); + } + + if (this._sources.has(aSource)) { + return this.sourcesContent[this._sources.indexOf(aSource)]; + } + + var url; + if (this.sourceRoot != null + && (url = util.urlParse(this.sourceRoot))) { + // XXX: file:// URIs and absolute paths lead to unexpected behavior for + // many users. We can help them out when they expect file:// URIs to + // behave like it would if they were running a local HTTP server. See + // https://bugzilla.mozilla.org/show_bug.cgi?id=885597. + var fileUriAbsPath = aSource.replace(/^file:\/\//, ""); + if (url.scheme == "file" + && this._sources.has(fileUriAbsPath)) { + return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)] + } + + if ((!url.path || url.path == "/") + && this._sources.has("/" + aSource)) { + return this.sourcesContent[this._sources.indexOf("/" + aSource)]; + } + } + + throw new Error('"' + aSource + '" is not in the SourceMap.'); + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + SourceMapConsumer.prototype.generatedPositionFor = + function SourceMapConsumer_generatedPositionFor(aArgs) { + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: util.getArg(aArgs, 'line'), + originalColumn: util.getArg(aArgs, 'column') + }; + + if (this.sourceRoot != null) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + + var index = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions); + + if (index >= 0) { + var mapping = this._originalMappings[index]; + + return { + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }; + } + + return { + line: null, + column: null, + lastColumn: null + }; + }; + + /** + * Returns all generated line and column information for the original source + * and line provided. The only argument is an object with the following + * properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * + * and an array of objects is returned, each with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + SourceMapConsumer.prototype.allGeneratedPositionsFor = + function SourceMapConsumer_allGeneratedPositionsFor(aArgs) { + // When there is no exact match, SourceMapConsumer.prototype._findMapping + // returns the index of the closest mapping less than the needle. By + // setting needle.originalColumn to Infinity, we thus find the last + // mapping for the given line, provided such a mapping exists. + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: util.getArg(aArgs, 'line'), + originalColumn: Infinity + }; + + if (this.sourceRoot != null) { + needle.source = util.relative(this.sourceRoot, needle.source); + } + + var mappings = []; + + var index = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + util.compareByOriginalPositions); + if (index >= 0) { + var mapping = this._originalMappings[index]; + + while (mapping && mapping.originalLine === needle.originalLine) { + mappings.push({ + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null), + lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null) + }); + + mapping = this._originalMappings[--index]; + } + } + + return mappings.reverse(); + }; + + SourceMapConsumer.GENERATED_ORDER = 1; + SourceMapConsumer.ORIGINAL_ORDER = 2; + + /** + * Iterate over each mapping between an original source/line/column and a + * generated line/column in this source map. + * + * @param Function aCallback + * The function that is called with each mapping. + * @param Object aContext + * Optional. If specified, this object will be the value of `this` every + * time that `aCallback` is called. + * @param aOrder + * Either `SourceMapConsumer.GENERATED_ORDER` or + * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to + * iterate over the mappings sorted by the generated file's line/column + * order or the original's source/line/column order, respectively. Defaults to + * `SourceMapConsumer.GENERATED_ORDER`. + */ + SourceMapConsumer.prototype.eachMapping = + function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { + var context = aContext || null; + var order = aOrder || SourceMapConsumer.GENERATED_ORDER; + + var mappings; + switch (order) { + case SourceMapConsumer.GENERATED_ORDER: + mappings = this._generatedMappings; + break; + case SourceMapConsumer.ORIGINAL_ORDER: + mappings = this._originalMappings; + break; + default: + throw new Error("Unknown order of iteration."); + } + + var sourceRoot = this.sourceRoot; + mappings.map(function (mapping) { + var source = mapping.source; + if (source != null && sourceRoot != null) { + source = util.join(sourceRoot, source); + } + return { + source: source, + generatedLine: mapping.generatedLine, + generatedColumn: mapping.generatedColumn, + originalLine: mapping.originalLine, + originalColumn: mapping.originalColumn, + name: mapping.name + }; + }).forEach(aCallback, context); + }; + + exports.SourceMapConsumer = SourceMapConsumer; + +}); diff --git a/homework8/project_express/node_modules/source-map/lib/source-map/source-map-generator.js b/homework8/project_express/node_modules/source-map/lib/source-map/source-map-generator.js new file mode 100644 index 0000000..1ab7a47 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/lib/source-map/source-map-generator.js @@ -0,0 +1,400 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64VLQ = require('./base64-vlq'); + var util = require('./util'); + var ArraySet = require('./array-set').ArraySet; + var MappingList = require('./mapping-list').MappingList; + + /** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. You may pass an object with the following + * properties: + * + * - file: The filename of the generated source. + * - sourceRoot: A root for all relative URLs in this source map. + */ + function SourceMapGenerator(aArgs) { + if (!aArgs) { + aArgs = {}; + } + this._file = util.getArg(aArgs, 'file', null); + this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); + this._skipValidation = util.getArg(aArgs, 'skipValidation', false); + this._sources = new ArraySet(); + this._names = new ArraySet(); + this._mappings = new MappingList(); + this._sourcesContents = null; + } + + SourceMapGenerator.prototype._version = 3; + + /** + * Creates a new SourceMapGenerator based on a SourceMapConsumer + * + * @param aSourceMapConsumer The SourceMap. + */ + SourceMapGenerator.fromSourceMap = + function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) { + var sourceRoot = aSourceMapConsumer.sourceRoot; + var generator = new SourceMapGenerator({ + file: aSourceMapConsumer.file, + sourceRoot: sourceRoot + }); + aSourceMapConsumer.eachMapping(function (mapping) { + var newMapping = { + generated: { + line: mapping.generatedLine, + column: mapping.generatedColumn + } + }; + + if (mapping.source != null) { + newMapping.source = mapping.source; + if (sourceRoot != null) { + newMapping.source = util.relative(sourceRoot, newMapping.source); + } + + newMapping.original = { + line: mapping.originalLine, + column: mapping.originalColumn + }; + + if (mapping.name != null) { + newMapping.name = mapping.name; + } + } + + generator.addMapping(newMapping); + }); + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + generator.setSourceContent(sourceFile, content); + } + }); + return generator; + }; + + /** + * Add a single mapping from original source line and column to the generated + * source's line and column for this source map being created. The mapping + * object should have the following properties: + * + * - generated: An object with the generated line and column positions. + * - original: An object with the original line and column positions. + * - source: The original source file (relative to the sourceRoot). + * - name: An optional original token name for this mapping. + */ + SourceMapGenerator.prototype.addMapping = + function SourceMapGenerator_addMapping(aArgs) { + var generated = util.getArg(aArgs, 'generated'); + var original = util.getArg(aArgs, 'original', null); + var source = util.getArg(aArgs, 'source', null); + var name = util.getArg(aArgs, 'name', null); + + if (!this._skipValidation) { + this._validateMapping(generated, original, source, name); + } + + if (source != null && !this._sources.has(source)) { + this._sources.add(source); + } + + if (name != null && !this._names.has(name)) { + this._names.add(name); + } + + this._mappings.add({ + generatedLine: generated.line, + generatedColumn: generated.column, + originalLine: original != null && original.line, + originalColumn: original != null && original.column, + source: source, + name: name + }); + }; + + /** + * Set the source content for a source file. + */ + SourceMapGenerator.prototype.setSourceContent = + function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) { + var source = aSourceFile; + if (this._sourceRoot != null) { + source = util.relative(this._sourceRoot, source); + } + + if (aSourceContent != null) { + // Add the source content to the _sourcesContents map. + // Create a new _sourcesContents map if the property is null. + if (!this._sourcesContents) { + this._sourcesContents = {}; + } + this._sourcesContents[util.toSetString(source)] = aSourceContent; + } else if (this._sourcesContents) { + // Remove the source file from the _sourcesContents map. + // If the _sourcesContents map is empty, set the property to null. + delete this._sourcesContents[util.toSetString(source)]; + if (Object.keys(this._sourcesContents).length === 0) { + this._sourcesContents = null; + } + } + }; + + /** + * Applies the mappings of a sub-source-map for a specific source file to the + * source map being generated. Each mapping to the supplied source file is + * rewritten using the supplied source map. Note: The resolution for the + * resulting mappings is the minimium of this map and the supplied map. + * + * @param aSourceMapConsumer The source map to be applied. + * @param aSourceFile Optional. The filename of the source file. + * If omitted, SourceMapConsumer's file property will be used. + * @param aSourceMapPath Optional. The dirname of the path to the source map + * to be applied. If relative, it is relative to the SourceMapConsumer. + * This parameter is needed when the two source maps aren't in the same + * directory, and the source map to be applied contains relative source + * paths. If so, those relative source paths need to be rewritten + * relative to the SourceMapGenerator. + */ + SourceMapGenerator.prototype.applySourceMap = + function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) { + var sourceFile = aSourceFile; + // If aSourceFile is omitted, we will use the file property of the SourceMap + if (aSourceFile == null) { + if (aSourceMapConsumer.file == null) { + throw new Error( + 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + + 'or the source map\'s "file" property. Both were omitted.' + ); + } + sourceFile = aSourceMapConsumer.file; + } + var sourceRoot = this._sourceRoot; + // Make "sourceFile" relative if an absolute Url is passed. + if (sourceRoot != null) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + // Applying the SourceMap can add and remove items from the sources and + // the names array. + var newSources = new ArraySet(); + var newNames = new ArraySet(); + + // Find mappings for the "sourceFile" + this._mappings.unsortedForEach(function (mapping) { + if (mapping.source === sourceFile && mapping.originalLine != null) { + // Check if it can be mapped by the source map, then update the mapping. + var original = aSourceMapConsumer.originalPositionFor({ + line: mapping.originalLine, + column: mapping.originalColumn + }); + if (original.source != null) { + // Copy mapping + mapping.source = original.source; + if (aSourceMapPath != null) { + mapping.source = util.join(aSourceMapPath, mapping.source) + } + if (sourceRoot != null) { + mapping.source = util.relative(sourceRoot, mapping.source); + } + mapping.originalLine = original.line; + mapping.originalColumn = original.column; + if (original.name != null) { + mapping.name = original.name; + } + } + } + + var source = mapping.source; + if (source != null && !newSources.has(source)) { + newSources.add(source); + } + + var name = mapping.name; + if (name != null && !newNames.has(name)) { + newNames.add(name); + } + + }, this); + this._sources = newSources; + this._names = newNames; + + // Copy sourcesContents of applied map. + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + if (aSourceMapPath != null) { + sourceFile = util.join(aSourceMapPath, sourceFile); + } + if (sourceRoot != null) { + sourceFile = util.relative(sourceRoot, sourceFile); + } + this.setSourceContent(sourceFile, content); + } + }, this); + }; + + /** + * A mapping can have one of the three levels of data: + * + * 1. Just the generated position. + * 2. The Generated position, original position, and original source. + * 3. Generated and original position, original source, as well as a name + * token. + * + * To maintain consistency, we validate that any new mapping being added falls + * in to one of these categories. + */ + SourceMapGenerator.prototype._validateMapping = + function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, + aName) { + if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aGenerated.line > 0 && aGenerated.column >= 0 + && !aOriginal && !aSource && !aName) { + // Case 1. + return; + } + else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aOriginal && 'line' in aOriginal && 'column' in aOriginal + && aGenerated.line > 0 && aGenerated.column >= 0 + && aOriginal.line > 0 && aOriginal.column >= 0 + && aSource) { + // Cases 2 and 3. + return; + } + else { + throw new Error('Invalid mapping: ' + JSON.stringify({ + generated: aGenerated, + source: aSource, + original: aOriginal, + name: aName + })); + } + }; + + /** + * Serialize the accumulated mappings in to the stream of base 64 VLQs + * specified by the source map format. + */ + SourceMapGenerator.prototype._serializeMappings = + function SourceMapGenerator_serializeMappings() { + var previousGeneratedColumn = 0; + var previousGeneratedLine = 1; + var previousOriginalColumn = 0; + var previousOriginalLine = 0; + var previousName = 0; + var previousSource = 0; + var result = ''; + var mapping; + + var mappings = this._mappings.toArray(); + + for (var i = 0, len = mappings.length; i < len; i++) { + mapping = mappings[i]; + + if (mapping.generatedLine !== previousGeneratedLine) { + previousGeneratedColumn = 0; + while (mapping.generatedLine !== previousGeneratedLine) { + result += ';'; + previousGeneratedLine++; + } + } + else { + if (i > 0) { + if (!util.compareByGeneratedPositions(mapping, mappings[i - 1])) { + continue; + } + result += ','; + } + } + + result += base64VLQ.encode(mapping.generatedColumn + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generatedColumn; + + if (mapping.source != null) { + result += base64VLQ.encode(this._sources.indexOf(mapping.source) + - previousSource); + previousSource = this._sources.indexOf(mapping.source); + + // lines are stored 0-based in SourceMap spec version 3 + result += base64VLQ.encode(mapping.originalLine - 1 + - previousOriginalLine); + previousOriginalLine = mapping.originalLine - 1; + + result += base64VLQ.encode(mapping.originalColumn + - previousOriginalColumn); + previousOriginalColumn = mapping.originalColumn; + + if (mapping.name != null) { + result += base64VLQ.encode(this._names.indexOf(mapping.name) + - previousName); + previousName = this._names.indexOf(mapping.name); + } + } + } + + return result; + }; + + SourceMapGenerator.prototype._generateSourcesContent = + function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) { + return aSources.map(function (source) { + if (!this._sourcesContents) { + return null; + } + if (aSourceRoot != null) { + source = util.relative(aSourceRoot, source); + } + var key = util.toSetString(source); + return Object.prototype.hasOwnProperty.call(this._sourcesContents, + key) + ? this._sourcesContents[key] + : null; + }, this); + }; + + /** + * Externalize the source map. + */ + SourceMapGenerator.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() + }; + if (this._file != null) { + map.file = this._file; + } + if (this._sourceRoot != null) { + map.sourceRoot = this._sourceRoot; + } + if (this._sourcesContents) { + map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot); + } + + return map; + }; + + /** + * Render the source map being generated to a string. + */ + SourceMapGenerator.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this); + }; + + exports.SourceMapGenerator = SourceMapGenerator; + +}); diff --git a/homework8/project_express/node_modules/source-map/lib/source-map/source-node.js b/homework8/project_express/node_modules/source-map/lib/source-map/source-node.js new file mode 100644 index 0000000..9ee90bd --- /dev/null +++ b/homework8/project_express/node_modules/source-map/lib/source-map/source-node.js @@ -0,0 +1,414 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; + var util = require('./util'); + + // Matches a Windows-style `\r\n` newline or a `\n` newline used by all other + // operating systems these days (capturing the result). + var REGEX_NEWLINE = /(\r?\n)/; + + // Newline character code for charCodeAt() comparisons + var NEWLINE_CODE = 10; + + // Private symbol for identifying `SourceNode`s when multiple versions of + // the source-map library are loaded. This MUST NOT CHANGE across + // versions! + var isSourceNode = "$$$isSourceNode$$$"; + + /** + * SourceNodes provide a way to abstract over interpolating/concatenating + * snippets of generated JavaScript source code while maintaining the line and + * column information associated with the original source code. + * + * @param aLine The original line number. + * @param aColumn The original column number. + * @param aSource The original source's filename. + * @param aChunks Optional. An array of strings which are snippets of + * generated JS, or other SourceNodes. + * @param aName The original identifier. + */ + function SourceNode(aLine, aColumn, aSource, aChunks, aName) { + this.children = []; + this.sourceContents = {}; + this.line = aLine == null ? null : aLine; + this.column = aColumn == null ? null : aColumn; + this.source = aSource == null ? null : aSource; + this.name = aName == null ? null : aName; + this[isSourceNode] = true; + if (aChunks != null) this.add(aChunks); + } + + /** + * Creates a SourceNode from generated code and a SourceMapConsumer. + * + * @param aGeneratedCode The generated code + * @param aSourceMapConsumer The SourceMap for the generated code + * @param aRelativePath Optional. The path that relative sources in the + * SourceMapConsumer should be relative to. + */ + SourceNode.fromStringWithSourceMap = + function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) { + // The SourceNode we want to fill with the generated code + // and the SourceMap + var node = new SourceNode(); + + // All even indices of this array are one line of the generated code, + // while all odd indices are the newlines between two adjacent lines + // (since `REGEX_NEWLINE` captures its match). + // Processed fragments are removed from this array, by calling `shiftNextLine`. + var remainingLines = aGeneratedCode.split(REGEX_NEWLINE); + var shiftNextLine = function() { + var lineContents = remainingLines.shift(); + // The last line of a file might not have a newline. + var newLine = remainingLines.shift() || ""; + return lineContents + newLine; + }; + + // We need to remember the position of "remainingLines" + var lastGeneratedLine = 1, lastGeneratedColumn = 0; + + // The generate SourceNodes we need a code range. + // To extract it current and last mapping is used. + // Here we store the last mapping. + var lastMapping = null; + + aSourceMapConsumer.eachMapping(function (mapping) { + if (lastMapping !== null) { + // We add the code from "lastMapping" to "mapping": + // First check if there is a new line in between. + if (lastGeneratedLine < mapping.generatedLine) { + var code = ""; + // Associate first line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + lastGeneratedLine++; + lastGeneratedColumn = 0; + // The remaining code is added without mapping + } else { + // There is no new line in between. + // Associate the code between "lastGeneratedColumn" and + // "mapping.generatedColumn" with "lastMapping" + var nextLine = remainingLines[0]; + var code = nextLine.substr(0, mapping.generatedColumn - + lastGeneratedColumn); + remainingLines[0] = nextLine.substr(mapping.generatedColumn - + lastGeneratedColumn); + lastGeneratedColumn = mapping.generatedColumn; + addMappingWithCode(lastMapping, code); + // No more remaining code, continue + lastMapping = mapping; + return; + } + } + // We add the generated code until the first mapping + // to the SourceNode without any mapping. + // Each line is added as separate string. + while (lastGeneratedLine < mapping.generatedLine) { + node.add(shiftNextLine()); + lastGeneratedLine++; + } + if (lastGeneratedColumn < mapping.generatedColumn) { + var nextLine = remainingLines[0]; + node.add(nextLine.substr(0, mapping.generatedColumn)); + remainingLines[0] = nextLine.substr(mapping.generatedColumn); + lastGeneratedColumn = mapping.generatedColumn; + } + lastMapping = mapping; + }, this); + // We have processed all mappings. + if (remainingLines.length > 0) { + if (lastMapping) { + // Associate the remaining code in the current line with "lastMapping" + addMappingWithCode(lastMapping, shiftNextLine()); + } + // and add the remaining lines without any mapping + node.add(remainingLines.join("")); + } + + // Copy sourcesContent into SourceNode + aSourceMapConsumer.sources.forEach(function (sourceFile) { + var content = aSourceMapConsumer.sourceContentFor(sourceFile); + if (content != null) { + if (aRelativePath != null) { + sourceFile = util.join(aRelativePath, sourceFile); + } + node.setSourceContent(sourceFile, content); + } + }); + + return node; + + function addMappingWithCode(mapping, code) { + if (mapping === null || mapping.source === undefined) { + node.add(code); + } else { + var source = aRelativePath + ? util.join(aRelativePath, mapping.source) + : mapping.source; + node.add(new SourceNode(mapping.originalLine, + mapping.originalColumn, + source, + code, + mapping.name)); + } + } + }; + + /** + * Add a chunk of generated JS to this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.add = function SourceNode_add(aChunk) { + if (Array.isArray(aChunk)) { + aChunk.forEach(function (chunk) { + this.add(chunk); + }, this); + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + if (aChunk) { + this.children.push(aChunk); + } + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Add a chunk of generated JS to the beginning of this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { + if (Array.isArray(aChunk)) { + for (var i = aChunk.length-1; i >= 0; i--) { + this.prepend(aChunk[i]); + } + } + else if (aChunk[isSourceNode] || typeof aChunk === "string") { + this.children.unshift(aChunk); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Walk over the tree of JS snippets in this node and its children. The + * walking function is called once for each snippet of JS and is passed that + * snippet and the its original associated source's line/column location. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walk = function SourceNode_walk(aFn) { + var chunk; + for (var i = 0, len = this.children.length; i < len; i++) { + chunk = this.children[i]; + if (chunk[isSourceNode]) { + chunk.walk(aFn); + } + else { + if (chunk !== '') { + aFn(chunk, { source: this.source, + line: this.line, + column: this.column, + name: this.name }); + } + } + } + }; + + /** + * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between + * each of `this.children`. + * + * @param aSep The separator. + */ + SourceNode.prototype.join = function SourceNode_join(aSep) { + var newChildren; + var i; + var len = this.children.length; + if (len > 0) { + newChildren = []; + for (i = 0; i < len-1; i++) { + newChildren.push(this.children[i]); + newChildren.push(aSep); + } + newChildren.push(this.children[i]); + this.children = newChildren; + } + return this; + }; + + /** + * Call String.prototype.replace on the very right-most source snippet. Useful + * for trimming whitespace from the end of a source node, etc. + * + * @param aPattern The pattern to replace. + * @param aReplacement The thing to replace the pattern with. + */ + SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild[isSourceNode]) { + lastChild.replaceRight(aPattern, aReplacement); + } + else if (typeof lastChild === 'string') { + this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); + } + else { + this.children.push(''.replace(aPattern, aReplacement)); + } + return this; + }; + + /** + * Set the source content for a source file. This will be added to the SourceMapGenerator + * in the sourcesContent field. + * + * @param aSourceFile The filename of the source file + * @param aSourceContent The content of the source file + */ + SourceNode.prototype.setSourceContent = + function SourceNode_setSourceContent(aSourceFile, aSourceContent) { + this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent; + }; + + /** + * Walk over the tree of SourceNodes. The walking function is called for each + * source file content and is passed the filename and source content. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walkSourceContents = + function SourceNode_walkSourceContents(aFn) { + for (var i = 0, len = this.children.length; i < len; i++) { + if (this.children[i][isSourceNode]) { + this.children[i].walkSourceContents(aFn); + } + } + + var sources = Object.keys(this.sourceContents); + for (var i = 0, len = sources.length; i < len; i++) { + aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]); + } + }; + + /** + * Return the string representation of this source node. Walks over the tree + * and concatenates all the various snippets together to one string. + */ + SourceNode.prototype.toString = function SourceNode_toString() { + var str = ""; + this.walk(function (chunk) { + str += chunk; + }); + return str; + }; + + /** + * Returns the string representation of this source node along with a source + * map. + */ + SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { + var generated = { + code: "", + line: 1, + column: 0 + }; + var map = new SourceMapGenerator(aArgs); + var sourceMappingActive = false; + var lastOriginalSource = null; + var lastOriginalLine = null; + var lastOriginalColumn = null; + var lastOriginalName = null; + this.walk(function (chunk, original) { + generated.code += chunk; + if (original.source !== null + && original.line !== null + && original.column !== null) { + if(lastOriginalSource !== original.source + || lastOriginalLine !== original.line + || lastOriginalColumn !== original.column + || lastOriginalName !== original.name) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + lastOriginalSource = original.source; + lastOriginalLine = original.line; + lastOriginalColumn = original.column; + lastOriginalName = original.name; + sourceMappingActive = true; + } else if (sourceMappingActive) { + map.addMapping({ + generated: { + line: generated.line, + column: generated.column + } + }); + lastOriginalSource = null; + sourceMappingActive = false; + } + for (var idx = 0, length = chunk.length; idx < length; idx++) { + if (chunk.charCodeAt(idx) === NEWLINE_CODE) { + generated.line++; + generated.column = 0; + // Mappings end at eol + if (idx + 1 === length) { + lastOriginalSource = null; + sourceMappingActive = false; + } else if (sourceMappingActive) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + }, + name: original.name + }); + } + } else { + generated.column++; + } + } + }); + this.walkSourceContents(function (sourceFile, sourceContent) { + map.setSourceContent(sourceFile, sourceContent); + }); + + return { code: generated.code, map: map }; + }; + + exports.SourceNode = SourceNode; + +}); diff --git a/homework8/project_express/node_modules/source-map/lib/source-map/util.js b/homework8/project_express/node_modules/source-map/lib/source-map/util.js new file mode 100644 index 0000000..976f6ca --- /dev/null +++ b/homework8/project_express/node_modules/source-map/lib/source-map/util.js @@ -0,0 +1,319 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + /** + * This is a helper function for getting values from parameter/options + * objects. + * + * @param args The object we are extracting values from + * @param name The name of the property we are getting. + * @param defaultValue An optional value to return if the property is missing + * from the object. If this is not specified and the property is missing, an + * error will be thrown. + */ + function getArg(aArgs, aName, aDefaultValue) { + if (aName in aArgs) { + return aArgs[aName]; + } else if (arguments.length === 3) { + return aDefaultValue; + } else { + throw new Error('"' + aName + '" is a required argument.'); + } + } + exports.getArg = getArg; + + var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/; + var dataUrlRegexp = /^data:.+\,.+$/; + + function urlParse(aUrl) { + var match = aUrl.match(urlRegexp); + if (!match) { + return null; + } + return { + scheme: match[1], + auth: match[2], + host: match[3], + port: match[4], + path: match[5] + }; + } + exports.urlParse = urlParse; + + function urlGenerate(aParsedUrl) { + var url = ''; + if (aParsedUrl.scheme) { + url += aParsedUrl.scheme + ':'; + } + url += '//'; + if (aParsedUrl.auth) { + url += aParsedUrl.auth + '@'; + } + if (aParsedUrl.host) { + url += aParsedUrl.host; + } + if (aParsedUrl.port) { + url += ":" + aParsedUrl.port + } + if (aParsedUrl.path) { + url += aParsedUrl.path; + } + return url; + } + exports.urlGenerate = urlGenerate; + + /** + * Normalizes a path, or the path portion of a URL: + * + * - Replaces consequtive slashes with one slash. + * - Removes unnecessary '.' parts. + * - Removes unnecessary '/..' parts. + * + * Based on code in the Node.js 'path' core module. + * + * @param aPath The path or url to normalize. + */ + function normalize(aPath) { + var path = aPath; + var url = urlParse(aPath); + if (url) { + if (!url.path) { + return aPath; + } + path = url.path; + } + var isAbsolute = (path.charAt(0) === '/'); + + var parts = path.split(/\/+/); + for (var part, up = 0, i = parts.length - 1; i >= 0; i--) { + part = parts[i]; + if (part === '.') { + parts.splice(i, 1); + } else if (part === '..') { + up++; + } else if (up > 0) { + if (part === '') { + // The first part is blank if the path is absolute. Trying to go + // above the root is a no-op. Therefore we can remove all '..' parts + // directly after the root. + parts.splice(i + 1, up); + up = 0; + } else { + parts.splice(i, 2); + up--; + } + } + } + path = parts.join('/'); + + if (path === '') { + path = isAbsolute ? '/' : '.'; + } + + if (url) { + url.path = path; + return urlGenerate(url); + } + return path; + } + exports.normalize = normalize; + + /** + * Joins two paths/URLs. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be joined with the root. + * + * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a + * scheme-relative URL: Then the scheme of aRoot, if any, is prepended + * first. + * - Otherwise aPath is a path. If aRoot is a URL, then its path portion + * is updated with the result and aRoot is returned. Otherwise the result + * is returned. + * - If aPath is absolute, the result is aPath. + * - Otherwise the two paths are joined with a slash. + * - Joining for example 'http://' and 'www.example.com' is also supported. + */ + function join(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } + if (aPath === "") { + aPath = "."; + } + var aPathUrl = urlParse(aPath); + var aRootUrl = urlParse(aRoot); + if (aRootUrl) { + aRoot = aRootUrl.path || '/'; + } + + // `join(foo, '//www.example.org')` + if (aPathUrl && !aPathUrl.scheme) { + if (aRootUrl) { + aPathUrl.scheme = aRootUrl.scheme; + } + return urlGenerate(aPathUrl); + } + + if (aPathUrl || aPath.match(dataUrlRegexp)) { + return aPath; + } + + // `join('http://', 'www.example.com')` + if (aRootUrl && !aRootUrl.host && !aRootUrl.path) { + aRootUrl.host = aPath; + return urlGenerate(aRootUrl); + } + + var joined = aPath.charAt(0) === '/' + ? aPath + : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath); + + if (aRootUrl) { + aRootUrl.path = joined; + return urlGenerate(aRootUrl); + } + return joined; + } + exports.join = join; + + /** + * Make a path relative to a URL or another path. + * + * @param aRoot The root path or URL. + * @param aPath The path or URL to be made relative to aRoot. + */ + function relative(aRoot, aPath) { + if (aRoot === "") { + aRoot = "."; + } + + aRoot = aRoot.replace(/\/$/, ''); + + // XXX: It is possible to remove this block, and the tests still pass! + var url = urlParse(aRoot); + if (aPath.charAt(0) == "/" && url && url.path == "/") { + return aPath.slice(1); + } + + return aPath.indexOf(aRoot + '/') === 0 + ? aPath.substr(aRoot.length + 1) + : aPath; + } + exports.relative = relative; + + /** + * Because behavior goes wacky when you set `__proto__` on objects, we + * have to prefix all the strings in our set with an arbitrary character. + * + * See https://github.com/mozilla/source-map/pull/31 and + * https://github.com/mozilla/source-map/issues/30 + * + * @param String aStr + */ + function toSetString(aStr) { + return '$' + aStr; + } + exports.toSetString = toSetString; + + function fromSetString(aStr) { + return aStr.substr(1); + } + exports.fromSetString = fromSetString; + + function strcmp(aStr1, aStr2) { + var s1 = aStr1 || ""; + var s2 = aStr2 || ""; + return (s1 > s2) - (s1 < s2); + } + + /** + * Comparator between two mappings where the original positions are compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same original source/line/column, but different generated + * line and column the same. Useful when searching for a mapping with a + * stubbed out mapping. + */ + function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) { + var cmp; + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp || onlyCompareOriginal) { + return cmp; + } + + cmp = strcmp(mappingA.name, mappingB.name); + if (cmp) { + return cmp; + } + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp) { + return cmp; + } + + return mappingA.generatedColumn - mappingB.generatedColumn; + }; + exports.compareByOriginalPositions = compareByOriginalPositions; + + /** + * Comparator between two mappings where the generated positions are + * compared. + * + * Optionally pass in `true` as `onlyCompareGenerated` to consider two + * mappings with the same generated line and column, but different + * source/name/original line and column the same. Useful when searching for a + * mapping with a stubbed out mapping. + */ + function compareByGeneratedPositions(mappingA, mappingB, onlyCompareGenerated) { + var cmp; + + cmp = mappingA.generatedLine - mappingB.generatedLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.generatedColumn - mappingB.generatedColumn; + if (cmp || onlyCompareGenerated) { + return cmp; + } + + cmp = strcmp(mappingA.source, mappingB.source); + if (cmp) { + return cmp; + } + + cmp = mappingA.originalLine - mappingB.originalLine; + if (cmp) { + return cmp; + } + + cmp = mappingA.originalColumn - mappingB.originalColumn; + if (cmp) { + return cmp; + } + + return strcmp(mappingA.name, mappingB.name); + }; + exports.compareByGeneratedPositions = compareByGeneratedPositions; + +}); diff --git a/homework8/project_express/node_modules/source-map/package.json b/homework8/project_express/node_modules/source-map/package.json new file mode 100644 index 0000000..ba5665b --- /dev/null +++ b/homework8/project_express/node_modules/source-map/package.json @@ -0,0 +1,65 @@ +{ + "name": "source-map", + "description": "Generates and consumes source maps", + "version": "0.1.43", + "homepage": "https://github.com/mozilla/source-map", + "author": "Nick Fitzgerald ", + "contributors": [ + "Tobias Koppers ", + "Duncan Beevers ", + "Stephen Crane ", + "Ryan Seddon ", + "Miles Elam ", + "Mihai Bazon ", + "Michael Ficarra ", + "Todd Wolfson ", + "Alexander Solovyov ", + "Felix Gnass ", + "Conrad Irwin ", + "usrbincc ", + "David Glasser ", + "Chase Douglas ", + "Evan Wallace ", + "Heather Arthur ", + "Hugh Kennedy ", + "David Glasser ", + "Simon Lydell ", + "Jmeas Smith ", + "Michael Z Goddard ", + "azu ", + "John Gozde ", + "Adam Kirkton ", + "Chris Montgomery ", + "J. Ryan Stinnett ", + "Jack Herrington ", + "Chris Truter ", + "Daniel Espeset " + ], + "repository": { + "type": "git", + "url": "http://github.com/mozilla/source-map.git" + }, + "directories": { + "lib": "./lib" + }, + "main": "./lib/source-map.js", + "engines": { + "node": ">=0.8.0" + }, + "licenses": [ + { + "type": "BSD", + "url": "http://opensource.org/licenses/BSD-3-Clause" + } + ], + "dependencies": { + "amdefine": ">=0.0.4" + }, + "devDependencies": { + "dryice": ">=0.4.8" + }, + "scripts": { + "test": "node test/run-tests.js", + "build": "node Makefile.dryice.js" + } +} diff --git a/homework8/project_express/node_modules/source-map/test/run-tests.js b/homework8/project_express/node_modules/source-map/test/run-tests.js new file mode 100644 index 0000000..64a7c3a --- /dev/null +++ b/homework8/project_express/node_modules/source-map/test/run-tests.js @@ -0,0 +1,62 @@ +#!/usr/bin/env node +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +var assert = require('assert'); +var fs = require('fs'); +var path = require('path'); +var util = require('./source-map/util'); + +function run(tests) { + var total = 0; + var passed = 0; + + for (var i = 0; i < tests.length; i++) { + for (var k in tests[i].testCase) { + if (/^test/.test(k)) { + total++; + try { + tests[i].testCase[k](assert, util); + passed++; + } + catch (e) { + console.log('FAILED ' + tests[i].name + ': ' + k + '!'); + console.log(e.stack); + } + } + } + } + + console.log(''); + console.log(passed + ' / ' + total + ' tests passed.'); + console.log(''); + + return total - passed; +} + +function isTestFile(f) { + var testToRun = process.argv[2]; + return testToRun + ? path.basename(testToRun) === f + : /^test\-.*?\.js/.test(f); +} + +function toModule(f) { + return './source-map/' + f.replace(/\.js$/, ''); +} + +var requires = fs.readdirSync(path.join(__dirname, 'source-map')) + .filter(isTestFile) + .map(toModule); + +var code = run(requires.map(require).map(function (mod, i) { + return { + name: requires[i], + testCase: mod + }; +})); + +process.exit(code); diff --git a/homework8/project_express/node_modules/source-map/test/source-map/test-api.js b/homework8/project_express/node_modules/source-map/test/source-map/test-api.js new file mode 100644 index 0000000..3801233 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/test/source-map/test-api.js @@ -0,0 +1,26 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2012 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var sourceMap; + try { + sourceMap = require('../../lib/source-map'); + } catch (e) { + sourceMap = {}; + Components.utils.import('resource:///modules/devtools/SourceMap.jsm', sourceMap); + } + + exports['test that the api is properly exposed in the top level'] = function (assert, util) { + assert.equal(typeof sourceMap.SourceMapGenerator, "function"); + assert.equal(typeof sourceMap.SourceMapConsumer, "function"); + assert.equal(typeof sourceMap.SourceNode, "function"); + }; + +}); diff --git a/homework8/project_express/node_modules/source-map/test/source-map/test-array-set.js b/homework8/project_express/node_modules/source-map/test/source-map/test-array-set.js new file mode 100644 index 0000000..b5797ed --- /dev/null +++ b/homework8/project_express/node_modules/source-map/test/source-map/test-array-set.js @@ -0,0 +1,104 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var ArraySet = require('../../lib/source-map/array-set').ArraySet; + + function makeTestSet() { + var set = new ArraySet(); + for (var i = 0; i < 100; i++) { + set.add(String(i)); + } + return set; + } + + exports['test .has() membership'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.ok(set.has(String(i))); + } + }; + + exports['test .indexOf() elements'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.strictEqual(set.indexOf(String(i)), i); + } + }; + + exports['test .at() indexing'] = function (assert, util) { + var set = makeTestSet(); + for (var i = 0; i < 100; i++) { + assert.strictEqual(set.at(i), String(i)); + } + }; + + exports['test creating from an array'] = function (assert, util) { + var set = ArraySet.fromArray(['foo', 'bar', 'baz', 'quux', 'hasOwnProperty']); + + assert.ok(set.has('foo')); + assert.ok(set.has('bar')); + assert.ok(set.has('baz')); + assert.ok(set.has('quux')); + assert.ok(set.has('hasOwnProperty')); + + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.indexOf('bar'), 1); + assert.strictEqual(set.indexOf('baz'), 2); + assert.strictEqual(set.indexOf('quux'), 3); + + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.at(1), 'bar'); + assert.strictEqual(set.at(2), 'baz'); + assert.strictEqual(set.at(3), 'quux'); + }; + + exports['test that you can add __proto__; see github issue #30'] = function (assert, util) { + var set = new ArraySet(); + set.add('__proto__'); + assert.ok(set.has('__proto__')); + assert.strictEqual(set.at(0), '__proto__'); + assert.strictEqual(set.indexOf('__proto__'), 0); + }; + + exports['test .fromArray() with duplicates'] = function (assert, util) { + var set = ArraySet.fromArray(['foo', 'foo']); + assert.ok(set.has('foo')); + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.toArray().length, 1); + + set = ArraySet.fromArray(['foo', 'foo'], true); + assert.ok(set.has('foo')); + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.at(1), 'foo'); + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.toArray().length, 2); + }; + + exports['test .add() with duplicates'] = function (assert, util) { + var set = new ArraySet(); + set.add('foo'); + + set.add('foo'); + assert.ok(set.has('foo')); + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.toArray().length, 1); + + set.add('foo', true); + assert.ok(set.has('foo')); + assert.strictEqual(set.at(0), 'foo'); + assert.strictEqual(set.at(1), 'foo'); + assert.strictEqual(set.indexOf('foo'), 0); + assert.strictEqual(set.toArray().length, 2); + }; + +}); diff --git a/homework8/project_express/node_modules/source-map/test/source-map/test-base64-vlq.js b/homework8/project_express/node_modules/source-map/test/source-map/test-base64-vlq.js new file mode 100644 index 0000000..6fd0d99 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/test/source-map/test-base64-vlq.js @@ -0,0 +1,23 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64VLQ = require('../../lib/source-map/base64-vlq'); + + exports['test normal encoding and decoding'] = function (assert, util) { + var result = {}; + for (var i = -255; i < 256; i++) { + base64VLQ.decode(base64VLQ.encode(i), result); + assert.equal(result.value, i); + assert.equal(result.rest, ""); + } + }; + +}); diff --git a/homework8/project_express/node_modules/source-map/test/source-map/test-base64.js b/homework8/project_express/node_modules/source-map/test/source-map/test-base64.js new file mode 100644 index 0000000..ff3a244 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/test/source-map/test-base64.js @@ -0,0 +1,35 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var base64 = require('../../lib/source-map/base64'); + + exports['test out of range encoding'] = function (assert, util) { + assert.throws(function () { + base64.encode(-1); + }); + assert.throws(function () { + base64.encode(64); + }); + }; + + exports['test out of range decoding'] = function (assert, util) { + assert.throws(function () { + base64.decode('='); + }); + }; + + exports['test normal encoding and decoding'] = function (assert, util) { + for (var i = 0; i < 64; i++) { + assert.equal(base64.decode(base64.encode(i)), i); + } + }; + +}); diff --git a/homework8/project_express/node_modules/source-map/test/source-map/test-binary-search.js b/homework8/project_express/node_modules/source-map/test/source-map/test-binary-search.js new file mode 100644 index 0000000..f1c9e0f --- /dev/null +++ b/homework8/project_express/node_modules/source-map/test/source-map/test-binary-search.js @@ -0,0 +1,54 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var binarySearch = require('../../lib/source-map/binary-search'); + + function numberCompare(a, b) { + return a - b; + } + + exports['test too high'] = function (assert, util) { + var needle = 30; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.doesNotThrow(function () { + binarySearch.search(needle, haystack, numberCompare); + }); + + assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare)], 20); + }; + + exports['test too low'] = function (assert, util) { + var needle = 1; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.doesNotThrow(function () { + binarySearch.search(needle, haystack, numberCompare); + }); + + assert.equal(binarySearch.search(needle, haystack, numberCompare), -1); + }; + + exports['test exact search'] = function (assert, util) { + var needle = 4; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare)], 4); + }; + + exports['test fuzzy search'] = function (assert, util) { + var needle = 19; + var haystack = [2,4,6,8,10,12,14,16,18,20]; + + assert.equal(haystack[binarySearch.search(needle, haystack, numberCompare)], 18); + }; + +}); diff --git a/homework8/project_express/node_modules/source-map/test/source-map/test-dog-fooding.js b/homework8/project_express/node_modules/source-map/test/source-map/test-dog-fooding.js new file mode 100644 index 0000000..26757b2 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/test/source-map/test-dog-fooding.js @@ -0,0 +1,84 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + + exports['test eating our own dog food'] = function (assert, util) { + var smg = new SourceMapGenerator({ + file: 'testing.js', + sourceRoot: '/wu/tang' + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 1, column: 0 }, + generated: { line: 2, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 2, column: 0 }, + generated: { line: 3, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 3, column: 0 }, + generated: { line: 4, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 4, column: 0 }, + generated: { line: 5, column: 2 } + }); + + smg.addMapping({ + source: 'gza.coffee', + original: { line: 5, column: 10 }, + generated: { line: 6, column: 12 } + }); + + var smc = new SourceMapConsumer(smg.toString()); + + // Exact + util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 0, null, smc, assert); + util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 0, null, smc, assert); + util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 0, null, smc, assert); + util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 0, null, smc, assert); + util.assertMapping(6, 12, '/wu/tang/gza.coffee', 5, 10, null, smc, assert); + + // Fuzzy + + // Generated to original + util.assertMapping(2, 0, null, null, null, null, smc, assert, true); + util.assertMapping(2, 9, '/wu/tang/gza.coffee', 1, 0, null, smc, assert, true); + util.assertMapping(3, 0, null, null, null, null, smc, assert, true); + util.assertMapping(3, 9, '/wu/tang/gza.coffee', 2, 0, null, smc, assert, true); + util.assertMapping(4, 0, null, null, null, null, smc, assert, true); + util.assertMapping(4, 9, '/wu/tang/gza.coffee', 3, 0, null, smc, assert, true); + util.assertMapping(5, 0, null, null, null, null, smc, assert, true); + util.assertMapping(5, 9, '/wu/tang/gza.coffee', 4, 0, null, smc, assert, true); + util.assertMapping(6, 0, null, null, null, null, smc, assert, true); + util.assertMapping(6, 9, null, null, null, null, smc, assert, true); + util.assertMapping(6, 13, '/wu/tang/gza.coffee', 5, 10, null, smc, assert, true); + + // Original to generated + util.assertMapping(2, 2, '/wu/tang/gza.coffee', 1, 1, null, smc, assert, null, true); + util.assertMapping(3, 2, '/wu/tang/gza.coffee', 2, 3, null, smc, assert, null, true); + util.assertMapping(4, 2, '/wu/tang/gza.coffee', 3, 6, null, smc, assert, null, true); + util.assertMapping(5, 2, '/wu/tang/gza.coffee', 4, 9, null, smc, assert, null, true); + util.assertMapping(5, 2, '/wu/tang/gza.coffee', 5, 9, null, smc, assert, null, true); + util.assertMapping(6, 12, '/wu/tang/gza.coffee', 6, 19, null, smc, assert, null, true); + }; + +}); diff --git a/homework8/project_express/node_modules/source-map/test/source-map/test-source-map-consumer.js b/homework8/project_express/node_modules/source-map/test/source-map/test-source-map-consumer.js new file mode 100644 index 0000000..c714943 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/test/source-map/test-source-map-consumer.js @@ -0,0 +1,702 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + + exports['test that we can instantiate with a string or an object'] = function (assert, util) { + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(util.testMap); + }); + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(JSON.stringify(util.testMap)); + }); + }; + + exports['test that the `sources` field has the original sources'] = function (assert, util) { + var map; + var sources; + + map = new SourceMapConsumer(util.testMap); + sources = map.sources; + assert.equal(sources[0], '/the/root/one.js'); + assert.equal(sources[1], '/the/root/two.js'); + assert.equal(sources.length, 2); + + map = new SourceMapConsumer(util.testMapNoSourceRoot); + sources = map.sources; + assert.equal(sources[0], 'one.js'); + assert.equal(sources[1], 'two.js'); + assert.equal(sources.length, 2); + + map = new SourceMapConsumer(util.testMapEmptySourceRoot); + sources = map.sources; + assert.equal(sources[0], 'one.js'); + assert.equal(sources[1], 'two.js'); + assert.equal(sources.length, 2); + }; + + exports['test that the source root is reflected in a mapping\'s source field'] = function (assert, util) { + var map; + var mapping; + + map = new SourceMapConsumer(util.testMap); + + mapping = map.originalPositionFor({ + line: 2, + column: 1 + }); + assert.equal(mapping.source, '/the/root/two.js'); + + mapping = map.originalPositionFor({ + line: 1, + column: 1 + }); + assert.equal(mapping.source, '/the/root/one.js'); + + + map = new SourceMapConsumer(util.testMapNoSourceRoot); + + mapping = map.originalPositionFor({ + line: 2, + column: 1 + }); + assert.equal(mapping.source, 'two.js'); + + mapping = map.originalPositionFor({ + line: 1, + column: 1 + }); + assert.equal(mapping.source, 'one.js'); + + + map = new SourceMapConsumer(util.testMapEmptySourceRoot); + + mapping = map.originalPositionFor({ + line: 2, + column: 1 + }); + assert.equal(mapping.source, 'two.js'); + + mapping = map.originalPositionFor({ + line: 1, + column: 1 + }); + assert.equal(mapping.source, 'one.js'); + }; + + exports['test mapping tokens back exactly'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + + util.assertMapping(1, 1, '/the/root/one.js', 1, 1, null, map, assert); + util.assertMapping(1, 5, '/the/root/one.js', 1, 5, null, map, assert); + util.assertMapping(1, 9, '/the/root/one.js', 1, 11, null, map, assert); + util.assertMapping(1, 18, '/the/root/one.js', 1, 21, 'bar', map, assert); + util.assertMapping(1, 21, '/the/root/one.js', 2, 3, null, map, assert); + util.assertMapping(1, 28, '/the/root/one.js', 2, 10, 'baz', map, assert); + util.assertMapping(1, 32, '/the/root/one.js', 2, 14, 'bar', map, assert); + + util.assertMapping(2, 1, '/the/root/two.js', 1, 1, null, map, assert); + util.assertMapping(2, 5, '/the/root/two.js', 1, 5, null, map, assert); + util.assertMapping(2, 9, '/the/root/two.js', 1, 11, null, map, assert); + util.assertMapping(2, 18, '/the/root/two.js', 1, 21, 'n', map, assert); + util.assertMapping(2, 21, '/the/root/two.js', 2, 3, null, map, assert); + util.assertMapping(2, 28, '/the/root/two.js', 2, 10, 'n', map, assert); + }; + + exports['test mapping tokens fuzzy'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + + // Finding original positions + util.assertMapping(1, 20, '/the/root/one.js', 1, 21, 'bar', map, assert, true); + util.assertMapping(1, 30, '/the/root/one.js', 2, 10, 'baz', map, assert, true); + util.assertMapping(2, 12, '/the/root/two.js', 1, 11, null, map, assert, true); + + // Finding generated positions + util.assertMapping(1, 18, '/the/root/one.js', 1, 22, 'bar', map, assert, null, true); + util.assertMapping(1, 28, '/the/root/one.js', 2, 13, 'baz', map, assert, null, true); + util.assertMapping(2, 9, '/the/root/two.js', 1, 16, null, map, assert, null, true); + }; + + exports['test mappings and end of lines'] = function (assert, util) { + var smg = new SourceMapGenerator({ + file: 'foo.js' + }); + smg.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 1, column: 1 }, + source: 'bar.js' + }); + smg.addMapping({ + original: { line: 2, column: 2 }, + generated: { line: 2, column: 2 }, + source: 'bar.js' + }); + + var map = SourceMapConsumer.fromSourceMap(smg); + + // When finding original positions, mappings end at the end of the line. + util.assertMapping(2, 1, null, null, null, null, map, assert, true) + + // When finding generated positions, mappings do not end at the end of the line. + util.assertMapping(1, 1, 'bar.js', 2, 1, null, map, assert, null, true); + }; + + exports['test creating source map consumers with )]}\' prefix'] = function (assert, util) { + assert.doesNotThrow(function () { + var map = new SourceMapConsumer(")]}'" + JSON.stringify(util.testMap)); + }); + }; + + exports['test eachMapping'] = function (assert, util) { + var map; + + map = new SourceMapConsumer(util.testMap); + var previousLine = -Infinity; + var previousColumn = -Infinity; + map.eachMapping(function (mapping) { + assert.ok(mapping.generatedLine >= previousLine); + + assert.ok(mapping.source === '/the/root/one.js' || mapping.source === '/the/root/two.js'); + + if (mapping.generatedLine === previousLine) { + assert.ok(mapping.generatedColumn >= previousColumn); + previousColumn = mapping.generatedColumn; + } + else { + previousLine = mapping.generatedLine; + previousColumn = -Infinity; + } + }); + + map = new SourceMapConsumer(util.testMapNoSourceRoot); + map.eachMapping(function (mapping) { + assert.ok(mapping.source === 'one.js' || mapping.source === 'two.js'); + }); + + map = new SourceMapConsumer(util.testMapEmptySourceRoot); + map.eachMapping(function (mapping) { + assert.ok(mapping.source === 'one.js' || mapping.source === 'two.js'); + }); + }; + + exports['test iterating over mappings in a different order'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var previousLine = -Infinity; + var previousColumn = -Infinity; + var previousSource = ""; + map.eachMapping(function (mapping) { + assert.ok(mapping.source >= previousSource); + + if (mapping.source === previousSource) { + assert.ok(mapping.originalLine >= previousLine); + + if (mapping.originalLine === previousLine) { + assert.ok(mapping.originalColumn >= previousColumn); + previousColumn = mapping.originalColumn; + } + else { + previousLine = mapping.originalLine; + previousColumn = -Infinity; + } + } + else { + previousSource = mapping.source; + previousLine = -Infinity; + previousColumn = -Infinity; + } + }, null, SourceMapConsumer.ORIGINAL_ORDER); + }; + + exports['test that we can set the context for `this` in eachMapping'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMap); + var context = {}; + map.eachMapping(function () { + assert.equal(this, context); + }, context); + }; + + exports['test that the `sourcesContent` field has the original sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMapWithSourcesContent); + var sourcesContent = map.sourcesContent; + + assert.equal(sourcesContent[0], ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(sourcesContent[1], ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.equal(sourcesContent.length, 2); + }; + + exports['test that we can get the original sources for the sources'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMapWithSourcesContent); + var sources = map.sources; + + assert.equal(map.sourceContentFor(sources[0]), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor(sources[1]), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.equal(map.sourceContentFor("one.js"), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor("two.js"), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.throws(function () { + map.sourceContentFor(""); + }, Error); + assert.throws(function () { + map.sourceContentFor("/the/root/three.js"); + }, Error); + assert.throws(function () { + map.sourceContentFor("three.js"); + }, Error); + }; + + exports['test that we can get the original source content with relative source paths'] = function (assert, util) { + var map = new SourceMapConsumer(util.testMapRelativeSources); + var sources = map.sources; + + assert.equal(map.sourceContentFor(sources[0]), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor(sources[1]), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.equal(map.sourceContentFor("one.js"), ' ONE.foo = function (bar) {\n return baz(bar);\n };'); + assert.equal(map.sourceContentFor("two.js"), ' TWO.inc = function (n) {\n return n + 1;\n };'); + assert.throws(function () { + map.sourceContentFor(""); + }, Error); + assert.throws(function () { + map.sourceContentFor("/the/root/three.js"); + }, Error); + assert.throws(function () { + map.sourceContentFor("three.js"); + }, Error); + }; + + exports['test sourceRoot + generatedPositionFor'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'foo/bar', + file: 'baz.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bang.coffee' + }); + map.addMapping({ + original: { line: 5, column: 5 }, + generated: { line: 6, column: 6 }, + source: 'bang.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + // Should handle without sourceRoot. + var pos = map.generatedPositionFor({ + line: 1, + column: 1, + source: 'bang.coffee' + }); + + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + + // Should handle with sourceRoot. + var pos = map.generatedPositionFor({ + line: 1, + column: 1, + source: 'foo/bar/bang.coffee' + }); + + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + }; + + exports['test allGeneratedPositionsFor'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bar.coffee' + }); + map.addMapping({ + original: { line: 2, column: 1 }, + generated: { line: 3, column: 2 }, + source: 'bar.coffee' + }); + map.addMapping({ + original: { line: 2, column: 2 }, + generated: { line: 3, column: 3 }, + source: 'bar.coffee' + }); + map.addMapping({ + original: { line: 3, column: 1 }, + generated: { line: 4, column: 2 }, + source: 'bar.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + var mappings = map.allGeneratedPositionsFor({ + line: 2, + source: 'bar.coffee' + }); + + assert.equal(mappings.length, 2); + assert.equal(mappings[0].line, 3); + assert.equal(mappings[0].column, 2); + assert.equal(mappings[1].line, 3); + assert.equal(mappings[1].column, 3); + }; + + exports['test allGeneratedPositionsFor for line with no mappings'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bar.coffee' + }); + map.addMapping({ + original: { line: 3, column: 1 }, + generated: { line: 4, column: 2 }, + source: 'bar.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + var mappings = map.allGeneratedPositionsFor({ + line: 2, + source: 'bar.coffee' + }); + + assert.equal(mappings.length, 0); + }; + + exports['test allGeneratedPositionsFor source map with no mappings'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated.js' + }); + map = new SourceMapConsumer(map.toString()); + + var mappings = map.allGeneratedPositionsFor({ + line: 2, + source: 'bar.coffee' + }); + + assert.equal(mappings.length, 0); + }; + + exports['test computeColumnSpans'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 1, column: 1 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 2, column: 1 }, + generated: { line: 2, column: 1 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 2, column: 2 }, + generated: { line: 2, column: 10 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 2, column: 3 }, + generated: { line: 2, column: 20 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 3, column: 1 }, + generated: { line: 3, column: 1 }, + source: 'foo.coffee' + }); + map.addMapping({ + original: { line: 3, column: 2 }, + generated: { line: 3, column: 2 }, + source: 'foo.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + map.computeColumnSpans(); + + var mappings = map.allGeneratedPositionsFor({ + line: 1, + source: 'foo.coffee' + }); + + assert.equal(mappings.length, 1); + assert.equal(mappings[0].lastColumn, Infinity); + + var mappings = map.allGeneratedPositionsFor({ + line: 2, + source: 'foo.coffee' + }); + + assert.equal(mappings.length, 3); + assert.equal(mappings[0].lastColumn, 9); + assert.equal(mappings[1].lastColumn, 19); + assert.equal(mappings[2].lastColumn, Infinity); + + var mappings = map.allGeneratedPositionsFor({ + line: 3, + source: 'foo.coffee' + }); + + assert.equal(mappings.length, 2); + assert.equal(mappings[0].lastColumn, 1); + assert.equal(mappings[1].lastColumn, Infinity); + }; + + exports['test sourceRoot + originalPositionFor'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'foo/bar', + file: 'baz.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bang.coffee' + }); + map = new SourceMapConsumer(map.toString()); + + var pos = map.originalPositionFor({ + line: 2, + column: 2, + }); + + // Should always have the prepended source root + assert.equal(pos.source, 'foo/bar/bang.coffee'); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + }; + + exports['test github issue #56'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://', + file: 'www.example.com/foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'www.example.com/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1); + assert.equal(sources[0], 'http://www.example.com/original.js'); + }; + + exports['test github issue #43'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://example.com', + file: 'foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'http://cdn.example.com/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1, + 'Should only be one source.'); + assert.equal(sources[0], 'http://cdn.example.com/original.js', + 'Should not be joined with the sourceRoot.'); + }; + + exports['test absolute path, but same host sources'] = function (assert, util) { + var map = new SourceMapGenerator({ + sourceRoot: 'http://example.com/foo/bar', + file: 'foo.js' + }); + map.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: '/original.js' + }); + map = new SourceMapConsumer(map.toString()); + + var sources = map.sources; + assert.equal(sources.length, 1, + 'Should only be one source.'); + assert.equal(sources[0], 'http://example.com/original.js', + 'Source should be relative the host of the source root.'); + }; + + exports['test github issue #64'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sourceRoot": "http://example.com/", + "sources": ["/a"], + "names": [], + "mappings": "AACA", + "sourcesContent": ["foo"] + }); + + assert.equal(map.sourceContentFor("a"), "foo"); + assert.equal(map.sourceContentFor("/a"), "foo"); + }; + + exports['test bug 885597'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sourceRoot": "file:///Users/AlGore/Invented/The/Internet/", + "sources": ["/a"], + "names": [], + "mappings": "AACA", + "sourcesContent": ["foo"] + }); + + var s = map.sources[0]; + assert.equal(map.sourceContentFor(s), "foo"); + }; + + exports['test github issue #72, duplicate sources'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sources": ["source1.js", "source1.js", "source3.js"], + "names": [], + "mappings": ";EAAC;;IAEE;;MEEE", + "sourceRoot": "http://example.com" + }); + + var pos = map.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(pos.source, 'http://example.com/source1.js'); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + + var pos = map.originalPositionFor({ + line: 4, + column: 4 + }); + assert.equal(pos.source, 'http://example.com/source1.js'); + assert.equal(pos.line, 3); + assert.equal(pos.column, 3); + + var pos = map.originalPositionFor({ + line: 6, + column: 6 + }); + assert.equal(pos.source, 'http://example.com/source3.js'); + assert.equal(pos.line, 5); + assert.equal(pos.column, 5); + }; + + exports['test github issue #72, duplicate names'] = function (assert, util) { + var map = new SourceMapConsumer({ + "version": 3, + "file": "foo.js", + "sources": ["source.js"], + "names": ["name1", "name1", "name3"], + "mappings": ";EAACA;;IAEEA;;MAEEE", + "sourceRoot": "http://example.com" + }); + + var pos = map.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(pos.name, 'name1'); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + + var pos = map.originalPositionFor({ + line: 4, + column: 4 + }); + assert.equal(pos.name, 'name1'); + assert.equal(pos.line, 3); + assert.equal(pos.column, 3); + + var pos = map.originalPositionFor({ + line: 6, + column: 6 + }); + assert.equal(pos.name, 'name3'); + assert.equal(pos.line, 5); + assert.equal(pos.column, 5); + }; + + exports['test SourceMapConsumer.fromSourceMap'] = function (assert, util) { + var smg = new SourceMapGenerator({ + sourceRoot: 'http://example.com/', + file: 'foo.js' + }); + smg.addMapping({ + original: { line: 1, column: 1 }, + generated: { line: 2, column: 2 }, + source: 'bar.js' + }); + smg.addMapping({ + original: { line: 2, column: 2 }, + generated: { line: 4, column: 4 }, + source: 'baz.js', + name: 'dirtMcGirt' + }); + smg.setSourceContent('baz.js', 'baz.js content'); + + var smc = SourceMapConsumer.fromSourceMap(smg); + assert.equal(smc.file, 'foo.js'); + assert.equal(smc.sourceRoot, 'http://example.com/'); + assert.equal(smc.sources.length, 2); + assert.equal(smc.sources[0], 'http://example.com/bar.js'); + assert.equal(smc.sources[1], 'http://example.com/baz.js'); + assert.equal(smc.sourceContentFor('baz.js'), 'baz.js content'); + + var pos = smc.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(pos.line, 1); + assert.equal(pos.column, 1); + assert.equal(pos.source, 'http://example.com/bar.js'); + assert.equal(pos.name, null); + + pos = smc.generatedPositionFor({ + line: 1, + column: 1, + source: 'http://example.com/bar.js' + }); + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + + pos = smc.originalPositionFor({ + line: 4, + column: 4 + }); + assert.equal(pos.line, 2); + assert.equal(pos.column, 2); + assert.equal(pos.source, 'http://example.com/baz.js'); + assert.equal(pos.name, 'dirtMcGirt'); + + pos = smc.generatedPositionFor({ + line: 2, + column: 2, + source: 'http://example.com/baz.js' + }); + assert.equal(pos.line, 4); + assert.equal(pos.column, 4); + }; +}); diff --git a/homework8/project_express/node_modules/source-map/test/source-map/test-source-map-generator.js b/homework8/project_express/node_modules/source-map/test/source-map/test-source-map-generator.js new file mode 100644 index 0000000..d748bb1 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/test/source-map/test-source-map-generator.js @@ -0,0 +1,679 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceNode = require('../../lib/source-map/source-node').SourceNode; + var util = require('./util'); + + exports['test some simple stuff'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'foo.js', + sourceRoot: '.' + }); + assert.ok(true); + + var map = new SourceMapGenerator().toJSON(); + assert.ok(!('file' in map)); + assert.ok(!('sourceRoot' in map)); + }; + + exports['test JSON serialization'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'foo.js', + sourceRoot: '.' + }); + assert.equal(map.toString(), JSON.stringify(map)); + }; + + exports['test adding mappings (case 1)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 } + }); + }); + }; + + exports['test adding mappings (case 2)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + source: 'bar.js', + original: { line: 1, column: 1 } + }); + }); + }; + + exports['test adding mappings (case 3)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + source: 'bar.js', + original: { line: 1, column: 1 }, + name: 'someToken' + }); + }); + }; + + exports['test adding mappings (invalid)'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + // Not enough info. + assert.throws(function () { + map.addMapping({}); + }); + + // Original file position, but no source. + assert.throws(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 } + }); + }); + }; + + exports['test adding mappings with skipValidation'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.', + skipValidation: true + }); + + // Not enough info, caught by `util.getArgs` + assert.throws(function () { + map.addMapping({}); + }); + + // Original file position, but no source. Not checked. + assert.doesNotThrow(function () { + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 } + }); + }); + }; + + exports['test that the correct mappings are being generated'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'min.js', + sourceRoot: '/the/root' + }); + + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 5 }, + original: { line: 1, column: 5 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 9 }, + original: { line: 1, column: 11 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 18 }, + original: { line: 1, column: 21 }, + source: 'one.js', + name: 'bar' + }); + map.addMapping({ + generated: { line: 1, column: 21 }, + original: { line: 2, column: 3 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 1, column: 28 }, + original: { line: 2, column: 10 }, + source: 'one.js', + name: 'baz' + }); + map.addMapping({ + generated: { line: 1, column: 32 }, + original: { line: 2, column: 14 }, + source: 'one.js', + name: 'bar' + }); + + map.addMapping({ + generated: { line: 2, column: 1 }, + original: { line: 1, column: 1 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 5 }, + original: { line: 1, column: 5 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 9 }, + original: { line: 1, column: 11 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 18 }, + original: { line: 1, column: 21 }, + source: 'two.js', + name: 'n' + }); + map.addMapping({ + generated: { line: 2, column: 21 }, + original: { line: 2, column: 3 }, + source: 'two.js' + }); + map.addMapping({ + generated: { line: 2, column: 28 }, + original: { line: 2, column: 10 }, + source: 'two.js', + name: 'n' + }); + + map = JSON.parse(map.toString()); + + util.assertEqualMaps(assert, map, util.testMap); + }; + + exports['test that adding a mapping with an empty string name does not break generation'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'generated-foo.js', + sourceRoot: '.' + }); + + map.addMapping({ + generated: { line: 1, column: 1 }, + source: 'bar.js', + original: { line: 1, column: 1 }, + name: '' + }); + + assert.doesNotThrow(function () { + JSON.parse(map.toString()); + }); + }; + + exports['test that source content can be set'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'min.js', + sourceRoot: '/the/root' + }); + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 1, column: 1 }, + source: 'one.js' + }); + map.addMapping({ + generated: { line: 2, column: 1 }, + original: { line: 1, column: 1 }, + source: 'two.js' + }); + map.setSourceContent('one.js', 'one file content'); + + map = JSON.parse(map.toString()); + assert.equal(map.sources[0], 'one.js'); + assert.equal(map.sources[1], 'two.js'); + assert.equal(map.sourcesContent[0], 'one file content'); + assert.equal(map.sourcesContent[1], null); + }; + + exports['test .fromSourceMap'] = function (assert, util) { + var map = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(util.testMap)); + util.assertEqualMaps(assert, map.toJSON(), util.testMap); + }; + + exports['test .fromSourceMap with sourcesContent'] = function (assert, util) { + var map = SourceMapGenerator.fromSourceMap( + new SourceMapConsumer(util.testMapWithSourcesContent)); + util.assertEqualMaps(assert, map.toJSON(), util.testMapWithSourcesContent); + }; + + exports['test applySourceMap'] = function (assert, util) { + var node = new SourceNode(null, null, null, [ + new SourceNode(2, 0, 'fileX', 'lineX2\n'), + 'genA1\n', + new SourceNode(2, 0, 'fileY', 'lineY2\n'), + 'genA2\n', + new SourceNode(1, 0, 'fileX', 'lineX1\n'), + 'genA3\n', + new SourceNode(1, 0, 'fileY', 'lineY1\n') + ]); + var mapStep1 = node.toStringWithSourceMap({ + file: 'fileA' + }).map; + mapStep1.setSourceContent('fileX', 'lineX1\nlineX2\n'); + mapStep1 = mapStep1.toJSON(); + + node = new SourceNode(null, null, null, [ + 'gen1\n', + new SourceNode(1, 0, 'fileA', 'lineA1\n'), + new SourceNode(2, 0, 'fileA', 'lineA2\n'), + new SourceNode(3, 0, 'fileA', 'lineA3\n'), + new SourceNode(4, 0, 'fileA', 'lineA4\n'), + new SourceNode(1, 0, 'fileB', 'lineB1\n'), + new SourceNode(2, 0, 'fileB', 'lineB2\n'), + 'gen2\n' + ]); + var mapStep2 = node.toStringWithSourceMap({ + file: 'fileGen' + }).map; + mapStep2.setSourceContent('fileB', 'lineB1\nlineB2\n'); + mapStep2 = mapStep2.toJSON(); + + node = new SourceNode(null, null, null, [ + 'gen1\n', + new SourceNode(2, 0, 'fileX', 'lineA1\n'), + new SourceNode(2, 0, 'fileA', 'lineA2\n'), + new SourceNode(2, 0, 'fileY', 'lineA3\n'), + new SourceNode(4, 0, 'fileA', 'lineA4\n'), + new SourceNode(1, 0, 'fileB', 'lineB1\n'), + new SourceNode(2, 0, 'fileB', 'lineB2\n'), + 'gen2\n' + ]); + var expectedMap = node.toStringWithSourceMap({ + file: 'fileGen' + }).map; + expectedMap.setSourceContent('fileX', 'lineX1\nlineX2\n'); + expectedMap.setSourceContent('fileB', 'lineB1\nlineB2\n'); + expectedMap = expectedMap.toJSON(); + + // apply source map "mapStep1" to "mapStep2" + var generator = SourceMapGenerator.fromSourceMap(new SourceMapConsumer(mapStep2)); + generator.applySourceMap(new SourceMapConsumer(mapStep1)); + var actualMap = generator.toJSON(); + + util.assertEqualMaps(assert, actualMap, expectedMap); + }; + + exports['test applySourceMap throws when file is missing'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'test.js' + }); + var map2 = new SourceMapGenerator(); + assert.throws(function() { + map.applySourceMap(new SourceMapConsumer(map2.toJSON())); + }); + }; + + exports['test the two additional parameters of applySourceMap'] = function (assert, util) { + // Assume the following directory structure: + // + // http://foo.org/ + // bar.coffee + // app/ + // coffee/ + // foo.coffee + // temp/ + // bundle.js + // temp_maps/ + // bundle.js.map + // public/ + // bundle.min.js + // bundle.min.js.map + // + // http://www.example.com/ + // baz.coffee + + var bundleMap = new SourceMapGenerator({ + file: 'bundle.js' + }); + bundleMap.addMapping({ + generated: { line: 3, column: 3 }, + original: { line: 2, column: 2 }, + source: '../../coffee/foo.coffee' + }); + bundleMap.setSourceContent('../../coffee/foo.coffee', 'foo coffee'); + bundleMap.addMapping({ + generated: { line: 13, column: 13 }, + original: { line: 12, column: 12 }, + source: '/bar.coffee' + }); + bundleMap.setSourceContent('/bar.coffee', 'bar coffee'); + bundleMap.addMapping({ + generated: { line: 23, column: 23 }, + original: { line: 22, column: 22 }, + source: 'http://www.example.com/baz.coffee' + }); + bundleMap.setSourceContent( + 'http://www.example.com/baz.coffee', + 'baz coffee' + ); + bundleMap = new SourceMapConsumer(bundleMap.toJSON()); + + var minifiedMap = new SourceMapGenerator({ + file: 'bundle.min.js', + sourceRoot: '..' + }); + minifiedMap.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 3, column: 3 }, + source: 'temp/bundle.js' + }); + minifiedMap.addMapping({ + generated: { line: 11, column: 11 }, + original: { line: 13, column: 13 }, + source: 'temp/bundle.js' + }); + minifiedMap.addMapping({ + generated: { line: 21, column: 21 }, + original: { line: 23, column: 23 }, + source: 'temp/bundle.js' + }); + minifiedMap = new SourceMapConsumer(minifiedMap.toJSON()); + + var expectedMap = function (sources) { + var map = new SourceMapGenerator({ + file: 'bundle.min.js', + sourceRoot: '..' + }); + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 2, column: 2 }, + source: sources[0] + }); + map.setSourceContent(sources[0], 'foo coffee'); + map.addMapping({ + generated: { line: 11, column: 11 }, + original: { line: 12, column: 12 }, + source: sources[1] + }); + map.setSourceContent(sources[1], 'bar coffee'); + map.addMapping({ + generated: { line: 21, column: 21 }, + original: { line: 22, column: 22 }, + source: sources[2] + }); + map.setSourceContent(sources[2], 'baz coffee'); + return map.toJSON(); + } + + var actualMap = function (aSourceMapPath) { + var map = SourceMapGenerator.fromSourceMap(minifiedMap); + // Note that relying on `bundleMap.file` (which is simply 'bundle.js') + // instead of supplying the second parameter wouldn't work here. + map.applySourceMap(bundleMap, '../temp/bundle.js', aSourceMapPath); + return map.toJSON(); + } + + util.assertEqualMaps(assert, actualMap('../temp/temp_maps'), expectedMap([ + 'coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); + + util.assertEqualMaps(assert, actualMap('/app/temp/temp_maps'), expectedMap([ + '/app/coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); + + util.assertEqualMaps(assert, actualMap('http://foo.org/app/temp/temp_maps'), expectedMap([ + 'http://foo.org/app/coffee/foo.coffee', + 'http://foo.org/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); + + // If the third parameter is omitted or set to the current working + // directory we get incorrect source paths: + + util.assertEqualMaps(assert, actualMap(), expectedMap([ + '../coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); + + util.assertEqualMaps(assert, actualMap(''), expectedMap([ + '../coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); + + util.assertEqualMaps(assert, actualMap('.'), expectedMap([ + '../coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); + + util.assertEqualMaps(assert, actualMap('./'), expectedMap([ + '../coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee' + ])); + }; + + exports['test applySourceMap name handling'] = function (assert, util) { + // Imagine some CoffeeScript code being compiled into JavaScript and then + // minified. + + var assertName = function(coffeeName, jsName, expectedName) { + var minifiedMap = new SourceMapGenerator({ + file: 'test.js.min' + }); + minifiedMap.addMapping({ + generated: { line: 1, column: 4 }, + original: { line: 1, column: 4 }, + source: 'test.js', + name: jsName + }); + + var coffeeMap = new SourceMapGenerator({ + file: 'test.js' + }); + coffeeMap.addMapping({ + generated: { line: 1, column: 4 }, + original: { line: 1, column: 0 }, + source: 'test.coffee', + name: coffeeName + }); + + minifiedMap.applySourceMap(new SourceMapConsumer(coffeeMap.toJSON())); + + new SourceMapConsumer(minifiedMap.toJSON()).eachMapping(function(mapping) { + assert.equal(mapping.name, expectedName); + }); + }; + + // `foo = 1` -> `var foo = 1;` -> `var a=1` + // CoffeeScript doesn’t rename variables, so there’s no need for it to + // provide names in its source maps. Minifiers do rename variables and + // therefore do provide names in their source maps. So that name should be + // retained if the original map lacks names. + assertName(null, 'foo', 'foo'); + + // `foo = 1` -> `var coffee$foo = 1;` -> `var a=1` + // Imagine that CoffeeScript prefixed all variables with `coffee$`. Even + // though the minifier then also provides a name, the original name is + // what corresponds to the source. + assertName('foo', 'coffee$foo', 'foo'); + + // `foo = 1` -> `var coffee$foo = 1;` -> `var coffee$foo=1` + // Minifiers can turn off variable mangling. Then there’s no need to + // provide names in the source map, but the names from the original map are + // still needed. + assertName('foo', null, 'foo'); + + // `foo = 1` -> `var foo = 1;` -> `var foo=1` + // No renaming at all. + assertName(null, null, null); + }; + + exports['test sorting with duplicate generated mappings'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'test.js' + }); + map.addMapping({ + generated: { line: 3, column: 0 }, + original: { line: 2, column: 0 }, + source: 'a.js' + }); + map.addMapping({ + generated: { line: 2, column: 0 } + }); + map.addMapping({ + generated: { line: 2, column: 0 } + }); + map.addMapping({ + generated: { line: 1, column: 0 }, + original: { line: 1, column: 0 }, + source: 'a.js' + }); + + util.assertEqualMaps(assert, map.toJSON(), { + version: 3, + file: 'test.js', + sources: ['a.js'], + names: [], + mappings: 'AAAA;A;AACA' + }); + }; + + exports['test ignore duplicate mappings.'] = function (assert, util) { + var init = { file: 'min.js', sourceRoot: '/the/root' }; + var map1, map2; + + // null original source location + var nullMapping1 = { + generated: { line: 1, column: 0 } + }; + var nullMapping2 = { + generated: { line: 2, column: 2 } + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(nullMapping1); + map1.addMapping(nullMapping1); + + map2.addMapping(nullMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(nullMapping2); + map1.addMapping(nullMapping1); + + map2.addMapping(nullMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + // original source location + var srcMapping1 = { + generated: { line: 1, column: 0 }, + original: { line: 11, column: 0 }, + source: 'srcMapping1.js' + }; + var srcMapping2 = { + generated: { line: 2, column: 2 }, + original: { line: 11, column: 0 }, + source: 'srcMapping2.js' + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(srcMapping1); + map1.addMapping(srcMapping1); + + map2.addMapping(srcMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(srcMapping2); + map1.addMapping(srcMapping1); + + map2.addMapping(srcMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + // full original source and name information + var fullMapping1 = { + generated: { line: 1, column: 0 }, + original: { line: 11, column: 0 }, + source: 'fullMapping1.js', + name: 'fullMapping1' + }; + var fullMapping2 = { + generated: { line: 2, column: 2 }, + original: { line: 11, column: 0 }, + source: 'fullMapping2.js', + name: 'fullMapping2' + }; + + map1 = new SourceMapGenerator(init); + map2 = new SourceMapGenerator(init); + + map1.addMapping(fullMapping1); + map1.addMapping(fullMapping1); + + map2.addMapping(fullMapping1); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + + map1.addMapping(fullMapping2); + map1.addMapping(fullMapping1); + + map2.addMapping(fullMapping2); + + util.assertEqualMaps(assert, map1.toJSON(), map2.toJSON()); + }; + + exports['test github issue #72, check for duplicate names or sources'] = function (assert, util) { + var map = new SourceMapGenerator({ + file: 'test.js' + }); + map.addMapping({ + generated: { line: 1, column: 1 }, + original: { line: 2, column: 2 }, + source: 'a.js', + name: 'foo' + }); + map.addMapping({ + generated: { line: 3, column: 3 }, + original: { line: 4, column: 4 }, + source: 'a.js', + name: 'foo' + }); + util.assertEqualMaps(assert, map.toJSON(), { + version: 3, + file: 'test.js', + sources: ['a.js'], + names: ['foo'], + mappings: 'CACEA;;GAEEA' + }); + }; + + exports['test setting sourcesContent to null when already null'] = function (assert, util) { + var smg = new SourceMapGenerator({ file: "foo.js" }); + assert.doesNotThrow(function() { + smg.setSourceContent("bar.js", null); + }); + }; + +}); diff --git a/homework8/project_express/node_modules/source-map/test/source-map/test-source-node.js b/homework8/project_express/node_modules/source-map/test/source-map/test-source-node.js new file mode 100644 index 0000000..139af4e --- /dev/null +++ b/homework8/project_express/node_modules/source-map/test/source-map/test-source-node.js @@ -0,0 +1,612 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('../../lib/source-map/source-map-generator').SourceMapGenerator; + var SourceMapConsumer = require('../../lib/source-map/source-map-consumer').SourceMapConsumer; + var SourceNode = require('../../lib/source-map/source-node').SourceNode; + + function forEachNewline(fn) { + return function (assert, util) { + ['\n', '\r\n'].forEach(fn.bind(null, assert, util)); + } + } + + exports['test .add()'] = function (assert, util) { + var node = new SourceNode(null, null, null); + + // Adding a string works. + node.add('function noop() {}'); + + // Adding another source node works. + node.add(new SourceNode(null, null, null)); + + // Adding an array works. + node.add(['function foo() {', + new SourceNode(null, null, null, + 'return 10;'), + '}']); + + // Adding other stuff doesn't. + assert.throws(function () { + node.add({}); + }); + assert.throws(function () { + node.add(function () {}); + }); + }; + + exports['test .prepend()'] = function (assert, util) { + var node = new SourceNode(null, null, null); + + // Prepending a string works. + node.prepend('function noop() {}'); + assert.equal(node.children[0], 'function noop() {}'); + assert.equal(node.children.length, 1); + + // Prepending another source node works. + node.prepend(new SourceNode(null, null, null)); + assert.equal(node.children[0], ''); + assert.equal(node.children[1], 'function noop() {}'); + assert.equal(node.children.length, 2); + + // Prepending an array works. + node.prepend(['function foo() {', + new SourceNode(null, null, null, + 'return 10;'), + '}']); + assert.equal(node.children[0], 'function foo() {'); + assert.equal(node.children[1], 'return 10;'); + assert.equal(node.children[2], '}'); + assert.equal(node.children[3], ''); + assert.equal(node.children[4], 'function noop() {}'); + assert.equal(node.children.length, 5); + + // Prepending other stuff doesn't. + assert.throws(function () { + node.prepend({}); + }); + assert.throws(function () { + node.prepend(function () {}); + }); + }; + + exports['test .toString()'] = function (assert, util) { + assert.equal((new SourceNode(null, null, null, + ['function foo() {', + new SourceNode(null, null, null, 'return 10;'), + '}'])).toString(), + 'function foo() {return 10;}'); + }; + + exports['test .join()'] = function (assert, util) { + assert.equal((new SourceNode(null, null, null, + ['a', 'b', 'c', 'd'])).join(', ').toString(), + 'a, b, c, d'); + }; + + exports['test .walk()'] = function (assert, util) { + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', new SourceNode(1, 0, 'a.js', ['someCall()']), ';\n', + ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';\n', + '}());']); + var expected = [ + { str: '(function () {\n', source: null, line: null, column: null }, + { str: ' ', source: null, line: null, column: null }, + { str: 'someCall()', source: 'a.js', line: 1, column: 0 }, + { str: ';\n', source: null, line: null, column: null }, + { str: ' ', source: null, line: null, column: null }, + { str: 'if (foo) bar()', source: 'b.js', line: 2, column: 0 }, + { str: ';\n', source: null, line: null, column: null }, + { str: '}());', source: null, line: null, column: null }, + ]; + var i = 0; + node.walk(function (chunk, loc) { + assert.equal(expected[i].str, chunk); + assert.equal(expected[i].source, loc.source); + assert.equal(expected[i].line, loc.line); + assert.equal(expected[i].column, loc.column); + i++; + }); + }; + + exports['test .replaceRight'] = function (assert, util) { + var node; + + // Not nested + node = new SourceNode(null, null, null, 'hello world'); + node.replaceRight(/world/, 'universe'); + assert.equal(node.toString(), 'hello universe'); + + // Nested + node = new SourceNode(null, null, null, + [new SourceNode(null, null, null, 'hey sexy mama, '), + new SourceNode(null, null, null, 'want to kill all humans?')]); + node.replaceRight(/kill all humans/, 'watch Futurama'); + assert.equal(node.toString(), 'hey sexy mama, want to watch Futurama?'); + }; + + exports['test .toStringWithSourceMap()'] = forEachNewline(function (assert, util, nl) { + var node = new SourceNode(null, null, null, + ['(function () {' + nl, + ' ', + new SourceNode(1, 0, 'a.js', 'someCall', 'originalCall'), + new SourceNode(1, 8, 'a.js', '()'), + ';' + nl, + ' ', new SourceNode(2, 0, 'b.js', ['if (foo) bar()']), ';' + nl, + '}());']); + var result = node.toStringWithSourceMap({ + file: 'foo.js' + }); + + assert.equal(result.code, [ + '(function () {', + ' someCall();', + ' if (foo) bar();', + '}());' + ].join(nl)); + + var map = result.map; + var mapWithoutOptions = node.toStringWithSourceMap().map; + + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + assert.ok(mapWithoutOptions instanceof SourceMapGenerator, 'mapWithoutOptions instanceof SourceMapGenerator'); + assert.ok(!('file' in mapWithoutOptions)); + mapWithoutOptions._file = 'foo.js'; + util.assertEqualMaps(assert, map.toJSON(), mapWithoutOptions.toJSON()); + + map = new SourceMapConsumer(map.toString()); + + var actual; + + actual = map.originalPositionFor({ + line: 1, + column: 4 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + + actual = map.originalPositionFor({ + line: 2, + column: 2 + }); + assert.equal(actual.source, 'a.js'); + assert.equal(actual.line, 1); + assert.equal(actual.column, 0); + assert.equal(actual.name, 'originalCall'); + + actual = map.originalPositionFor({ + line: 3, + column: 2 + }); + assert.equal(actual.source, 'b.js'); + assert.equal(actual.line, 2); + assert.equal(actual.column, 0); + + actual = map.originalPositionFor({ + line: 3, + column: 16 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + + actual = map.originalPositionFor({ + line: 4, + column: 2 + }); + assert.equal(actual.source, null); + assert.equal(actual.line, null); + assert.equal(actual.column, null); + }); + + exports['test .fromStringWithSourceMap()'] = forEachNewline(function (assert, util, nl) { + var testCode = util.testGeneratedCode.replace(/\n/g, nl); + var node = SourceNode.fromStringWithSourceMap( + testCode, + new SourceMapConsumer(util.testMap)); + + var result = node.toStringWithSourceMap({ + file: 'min.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, testCode); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + assert.equal(map.version, util.testMap.version); + assert.equal(map.file, util.testMap.file); + assert.equal(map.mappings, util.testMap.mappings); + }); + + exports['test .fromStringWithSourceMap() empty map'] = forEachNewline(function (assert, util, nl) { + var node = SourceNode.fromStringWithSourceMap( + util.testGeneratedCode.replace(/\n/g, nl), + new SourceMapConsumer(util.emptyMap)); + var result = node.toStringWithSourceMap({ + file: 'min.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, util.testGeneratedCode.replace(/\n/g, nl)); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + assert.equal(map.version, util.emptyMap.version); + assert.equal(map.file, util.emptyMap.file); + assert.equal(map.mappings.length, util.emptyMap.mappings.length); + assert.equal(map.mappings, util.emptyMap.mappings); + }); + + exports['test .fromStringWithSourceMap() complex version'] = forEachNewline(function (assert, util, nl) { + var input = new SourceNode(null, null, null, [ + "(function() {" + nl, + " var Test = {};" + nl, + " ", new SourceNode(1, 0, "a.js", "Test.A = { value: 1234 };" + nl), + " ", new SourceNode(2, 0, "a.js", "Test.A.x = 'xyz';"), nl, + "}());" + nl, + "/* Generated Source */"]); + input = input.toStringWithSourceMap({ + file: 'foo.js' + }); + + var node = SourceNode.fromStringWithSourceMap( + input.code, + new SourceMapConsumer(input.map.toString())); + + var result = node.toStringWithSourceMap({ + file: 'foo.js' + }); + var map = result.map; + var code = result.code; + + assert.equal(code, input.code); + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = map.toJSON(); + var inputMap = input.map.toJSON(); + util.assertEqualMaps(assert, map, inputMap); + }); + + exports['test .fromStringWithSourceMap() third argument'] = function (assert, util) { + // Assume the following directory structure: + // + // http://foo.org/ + // bar.coffee + // app/ + // coffee/ + // foo.coffee + // coffeeBundle.js # Made from {foo,bar,baz}.coffee + // maps/ + // coffeeBundle.js.map + // js/ + // foo.js + // public/ + // app.js # Made from {foo,coffeeBundle}.js + // app.js.map + // + // http://www.example.com/ + // baz.coffee + + var coffeeBundle = new SourceNode(1, 0, 'foo.coffee', 'foo(coffee);\n'); + coffeeBundle.setSourceContent('foo.coffee', 'foo coffee'); + coffeeBundle.add(new SourceNode(2, 0, '/bar.coffee', 'bar(coffee);\n')); + coffeeBundle.add(new SourceNode(3, 0, 'http://www.example.com/baz.coffee', 'baz(coffee);')); + coffeeBundle = coffeeBundle.toStringWithSourceMap({ + file: 'foo.js', + sourceRoot: '..' + }); + + var foo = new SourceNode(1, 0, 'foo.js', 'foo(js);'); + + var test = function(relativePath, expectedSources) { + var app = new SourceNode(); + app.add(SourceNode.fromStringWithSourceMap( + coffeeBundle.code, + new SourceMapConsumer(coffeeBundle.map.toString()), + relativePath)); + app.add(foo); + var i = 0; + app.walk(function (chunk, loc) { + assert.equal(loc.source, expectedSources[i]); + i++; + }); + app.walkSourceContents(function (sourceFile, sourceContent) { + assert.equal(sourceFile, expectedSources[0]); + assert.equal(sourceContent, 'foo coffee'); + }) + }; + + test('../coffee/maps', [ + '../coffee/foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee', + 'foo.js' + ]); + + // If the third parameter is omitted or set to the current working + // directory we get incorrect source paths: + + test(undefined, [ + '../foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee', + 'foo.js' + ]); + + test('', [ + '../foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee', + 'foo.js' + ]); + + test('.', [ + '../foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee', + 'foo.js' + ]); + + test('./', [ + '../foo.coffee', + '/bar.coffee', + 'http://www.example.com/baz.coffee', + 'foo.js' + ]); + }; + + exports['test .toStringWithSourceMap() merging duplicate mappings'] = forEachNewline(function (assert, util, nl) { + var input = new SourceNode(null, null, null, [ + new SourceNode(1, 0, "a.js", "(function"), + new SourceNode(1, 0, "a.js", "() {" + nl), + " ", + new SourceNode(1, 0, "a.js", "var Test = "), + new SourceNode(1, 0, "b.js", "{};" + nl), + new SourceNode(2, 0, "b.js", "Test"), + new SourceNode(2, 0, "b.js", ".A", "A"), + new SourceNode(2, 20, "b.js", " = { value: ", "A"), + "1234", + new SourceNode(2, 40, "b.js", " };" + nl, "A"), + "}());" + nl, + "/* Generated Source */" + ]); + input = input.toStringWithSourceMap({ + file: 'foo.js' + }); + + assert.equal(input.code, [ + "(function() {", + " var Test = {};", + "Test.A = { value: 1234 };", + "}());", + "/* Generated Source */" + ].join(nl)) + + var correctMap = new SourceMapGenerator({ + file: 'foo.js' + }); + correctMap.addMapping({ + generated: { line: 1, column: 0 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + // Here is no need for a empty mapping, + // because mappings ends at eol + correctMap.addMapping({ + generated: { line: 2, column: 2 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 2, column: 13 }, + source: 'b.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 0 }, + source: 'b.js', + original: { line: 2, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 4 }, + source: 'b.js', + name: 'A', + original: { line: 2, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 6 }, + source: 'b.js', + name: 'A', + original: { line: 2, column: 20 } + }); + // This empty mapping is required, + // because there is a hole in the middle of the line + correctMap.addMapping({ + generated: { line: 3, column: 18 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 22 }, + source: 'b.js', + name: 'A', + original: { line: 2, column: 40 } + }); + // Here is no need for a empty mapping, + // because mappings ends at eol + + var inputMap = input.map.toJSON(); + correctMap = correctMap.toJSON(); + util.assertEqualMaps(assert, inputMap, correctMap); + }); + + exports['test .toStringWithSourceMap() multi-line SourceNodes'] = forEachNewline(function (assert, util, nl) { + var input = new SourceNode(null, null, null, [ + new SourceNode(1, 0, "a.js", "(function() {" + nl + "var nextLine = 1;" + nl + "anotherLine();" + nl), + new SourceNode(2, 2, "b.js", "Test.call(this, 123);" + nl), + new SourceNode(2, 2, "b.js", "this['stuff'] = 'v';" + nl), + new SourceNode(2, 2, "b.js", "anotherLine();" + nl), + "/*" + nl + "Generated" + nl + "Source" + nl + "*/" + nl, + new SourceNode(3, 4, "c.js", "anotherLine();" + nl), + "/*" + nl + "Generated" + nl + "Source" + nl + "*/" + ]); + input = input.toStringWithSourceMap({ + file: 'foo.js' + }); + + assert.equal(input.code, [ + "(function() {", + "var nextLine = 1;", + "anotherLine();", + "Test.call(this, 123);", + "this['stuff'] = 'v';", + "anotherLine();", + "/*", + "Generated", + "Source", + "*/", + "anotherLine();", + "/*", + "Generated", + "Source", + "*/" + ].join(nl)); + + var correctMap = new SourceMapGenerator({ + file: 'foo.js' + }); + correctMap.addMapping({ + generated: { line: 1, column: 0 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 2, column: 0 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 3, column: 0 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 4, column: 0 }, + source: 'b.js', + original: { line: 2, column: 2 } + }); + correctMap.addMapping({ + generated: { line: 5, column: 0 }, + source: 'b.js', + original: { line: 2, column: 2 } + }); + correctMap.addMapping({ + generated: { line: 6, column: 0 }, + source: 'b.js', + original: { line: 2, column: 2 } + }); + correctMap.addMapping({ + generated: { line: 11, column: 0 }, + source: 'c.js', + original: { line: 3, column: 4 } + }); + + var inputMap = input.map.toJSON(); + correctMap = correctMap.toJSON(); + util.assertEqualMaps(assert, inputMap, correctMap); + }); + + exports['test .toStringWithSourceMap() with empty string'] = function (assert, util) { + var node = new SourceNode(1, 0, 'empty.js', ''); + var result = node.toStringWithSourceMap(); + assert.equal(result.code, ''); + }; + + exports['test .toStringWithSourceMap() with consecutive newlines'] = forEachNewline(function (assert, util, nl) { + var input = new SourceNode(null, null, null, [ + "/***/" + nl + nl, + new SourceNode(1, 0, "a.js", "'use strict';" + nl), + new SourceNode(2, 0, "a.js", "a();"), + ]); + input = input.toStringWithSourceMap({ + file: 'foo.js' + }); + + assert.equal(input.code, [ + "/***/", + "", + "'use strict';", + "a();", + ].join(nl)); + + var correctMap = new SourceMapGenerator({ + file: 'foo.js' + }); + correctMap.addMapping({ + generated: { line: 3, column: 0 }, + source: 'a.js', + original: { line: 1, column: 0 } + }); + correctMap.addMapping({ + generated: { line: 4, column: 0 }, + source: 'a.js', + original: { line: 2, column: 0 } + }); + + var inputMap = input.map.toJSON(); + correctMap = correctMap.toJSON(); + util.assertEqualMaps(assert, inputMap, correctMap); + }); + + exports['test setSourceContent with toStringWithSourceMap'] = function (assert, util) { + var aNode = new SourceNode(1, 1, 'a.js', 'a'); + aNode.setSourceContent('a.js', 'someContent'); + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', aNode, + ' ', new SourceNode(1, 1, 'b.js', 'b'), + '}());']); + node.setSourceContent('b.js', 'otherContent'); + var map = node.toStringWithSourceMap({ + file: 'foo.js' + }).map; + + assert.ok(map instanceof SourceMapGenerator, 'map instanceof SourceMapGenerator'); + map = new SourceMapConsumer(map.toString()); + + assert.equal(map.sources.length, 2); + assert.equal(map.sources[0], 'a.js'); + assert.equal(map.sources[1], 'b.js'); + assert.equal(map.sourcesContent.length, 2); + assert.equal(map.sourcesContent[0], 'someContent'); + assert.equal(map.sourcesContent[1], 'otherContent'); + }; + + exports['test walkSourceContents'] = function (assert, util) { + var aNode = new SourceNode(1, 1, 'a.js', 'a'); + aNode.setSourceContent('a.js', 'someContent'); + var node = new SourceNode(null, null, null, + ['(function () {\n', + ' ', aNode, + ' ', new SourceNode(1, 1, 'b.js', 'b'), + '}());']); + node.setSourceContent('b.js', 'otherContent'); + var results = []; + node.walkSourceContents(function (sourceFile, sourceContent) { + results.push([sourceFile, sourceContent]); + }); + assert.equal(results.length, 2); + assert.equal(results[0][0], 'a.js'); + assert.equal(results[0][1], 'someContent'); + assert.equal(results[1][0], 'b.js'); + assert.equal(results[1][1], 'otherContent'); + }; +}); diff --git a/homework8/project_express/node_modules/source-map/test/source-map/test-util.js b/homework8/project_express/node_modules/source-map/test/source-map/test-util.js new file mode 100644 index 0000000..997d1a2 --- /dev/null +++ b/homework8/project_express/node_modules/source-map/test/source-map/test-util.js @@ -0,0 +1,216 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2014 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var libUtil = require('../../lib/source-map/util'); + + exports['test urls'] = function (assert, util) { + var assertUrl = function (url) { + assert.equal(url, libUtil.urlGenerate(libUtil.urlParse(url))); + }; + assertUrl('http://'); + assertUrl('http://www.example.com'); + assertUrl('http://user:pass@www.example.com'); + assertUrl('http://www.example.com:80'); + assertUrl('http://www.example.com/'); + assertUrl('http://www.example.com/foo/bar'); + assertUrl('http://www.example.com/foo/bar/'); + assertUrl('http://user:pass@www.example.com:80/foo/bar/'); + + assertUrl('//'); + assertUrl('//www.example.com'); + assertUrl('file:///www.example.com'); + + assert.equal(libUtil.urlParse(''), null); + assert.equal(libUtil.urlParse('.'), null); + assert.equal(libUtil.urlParse('..'), null); + assert.equal(libUtil.urlParse('a'), null); + assert.equal(libUtil.urlParse('a/b'), null); + assert.equal(libUtil.urlParse('a//b'), null); + assert.equal(libUtil.urlParse('/a'), null); + assert.equal(libUtil.urlParse('data:foo,bar'), null); + }; + + exports['test normalize()'] = function (assert, util) { + assert.equal(libUtil.normalize('/..'), '/'); + assert.equal(libUtil.normalize('/../'), '/'); + assert.equal(libUtil.normalize('/../../../..'), '/'); + assert.equal(libUtil.normalize('/../../../../a/b/c'), '/a/b/c'); + assert.equal(libUtil.normalize('/a/b/c/../../../d/../../e'), '/e'); + + assert.equal(libUtil.normalize('..'), '..'); + assert.equal(libUtil.normalize('../'), '../'); + assert.equal(libUtil.normalize('../../a/'), '../../a/'); + assert.equal(libUtil.normalize('a/..'), '.'); + assert.equal(libUtil.normalize('a/../../..'), '../..'); + + assert.equal(libUtil.normalize('/.'), '/'); + assert.equal(libUtil.normalize('/./'), '/'); + assert.equal(libUtil.normalize('/./././.'), '/'); + assert.equal(libUtil.normalize('/././././a/b/c'), '/a/b/c'); + assert.equal(libUtil.normalize('/a/b/c/./././d/././e'), '/a/b/c/d/e'); + + assert.equal(libUtil.normalize(''), '.'); + assert.equal(libUtil.normalize('.'), '.'); + assert.equal(libUtil.normalize('./'), '.'); + assert.equal(libUtil.normalize('././a'), 'a'); + assert.equal(libUtil.normalize('a/./'), 'a/'); + assert.equal(libUtil.normalize('a/././.'), 'a'); + + assert.equal(libUtil.normalize('/a/b//c////d/////'), '/a/b/c/d/'); + assert.equal(libUtil.normalize('///a/b//c////d/////'), '///a/b/c/d/'); + assert.equal(libUtil.normalize('a/b//c////d'), 'a/b/c/d'); + + assert.equal(libUtil.normalize('.///.././../a/b//./..'), '../../a') + + assert.equal(libUtil.normalize('http://www.example.com'), 'http://www.example.com'); + assert.equal(libUtil.normalize('http://www.example.com/'), 'http://www.example.com/'); + assert.equal(libUtil.normalize('http://www.example.com/./..//a/b/c/.././d//'), 'http://www.example.com/a/b/d/'); + }; + + exports['test join()'] = function (assert, util) { + assert.equal(libUtil.join('a', 'b'), 'a/b'); + assert.equal(libUtil.join('a/', 'b'), 'a/b'); + assert.equal(libUtil.join('a//', 'b'), 'a/b'); + assert.equal(libUtil.join('a', 'b/'), 'a/b/'); + assert.equal(libUtil.join('a', 'b//'), 'a/b/'); + assert.equal(libUtil.join('a/', '/b'), '/b'); + assert.equal(libUtil.join('a//', '//b'), '//b'); + + assert.equal(libUtil.join('a', '..'), '.'); + assert.equal(libUtil.join('a', '../b'), 'b'); + assert.equal(libUtil.join('a/b', '../c'), 'a/c'); + + assert.equal(libUtil.join('a', '.'), 'a'); + assert.equal(libUtil.join('a', './b'), 'a/b'); + assert.equal(libUtil.join('a/b', './c'), 'a/b/c'); + + assert.equal(libUtil.join('a', 'http://www.example.com'), 'http://www.example.com'); + assert.equal(libUtil.join('a', 'data:foo,bar'), 'data:foo,bar'); + + + assert.equal(libUtil.join('', 'b'), 'b'); + assert.equal(libUtil.join('.', 'b'), 'b'); + assert.equal(libUtil.join('', 'b/'), 'b/'); + assert.equal(libUtil.join('.', 'b/'), 'b/'); + assert.equal(libUtil.join('', 'b//'), 'b/'); + assert.equal(libUtil.join('.', 'b//'), 'b/'); + + assert.equal(libUtil.join('', '..'), '..'); + assert.equal(libUtil.join('.', '..'), '..'); + assert.equal(libUtil.join('', '../b'), '../b'); + assert.equal(libUtil.join('.', '../b'), '../b'); + + assert.equal(libUtil.join('', '.'), '.'); + assert.equal(libUtil.join('.', '.'), '.'); + assert.equal(libUtil.join('', './b'), 'b'); + assert.equal(libUtil.join('.', './b'), 'b'); + + assert.equal(libUtil.join('', 'http://www.example.com'), 'http://www.example.com'); + assert.equal(libUtil.join('.', 'http://www.example.com'), 'http://www.example.com'); + assert.equal(libUtil.join('', 'data:foo,bar'), 'data:foo,bar'); + assert.equal(libUtil.join('.', 'data:foo,bar'), 'data:foo,bar'); + + + assert.equal(libUtil.join('..', 'b'), '../b'); + assert.equal(libUtil.join('..', 'b/'), '../b/'); + assert.equal(libUtil.join('..', 'b//'), '../b/'); + + assert.equal(libUtil.join('..', '..'), '../..'); + assert.equal(libUtil.join('..', '../b'), '../../b'); + + assert.equal(libUtil.join('..', '.'), '..'); + assert.equal(libUtil.join('..', './b'), '../b'); + + assert.equal(libUtil.join('..', 'http://www.example.com'), 'http://www.example.com'); + assert.equal(libUtil.join('..', 'data:foo,bar'), 'data:foo,bar'); + + + assert.equal(libUtil.join('a', ''), 'a'); + assert.equal(libUtil.join('a', '.'), 'a'); + assert.equal(libUtil.join('a/', ''), 'a'); + assert.equal(libUtil.join('a/', '.'), 'a'); + assert.equal(libUtil.join('a//', ''), 'a'); + assert.equal(libUtil.join('a//', '.'), 'a'); + assert.equal(libUtil.join('/a', ''), '/a'); + assert.equal(libUtil.join('/a', '.'), '/a'); + assert.equal(libUtil.join('', ''), '.'); + assert.equal(libUtil.join('.', ''), '.'); + assert.equal(libUtil.join('.', ''), '.'); + assert.equal(libUtil.join('.', '.'), '.'); + assert.equal(libUtil.join('..', ''), '..'); + assert.equal(libUtil.join('..', '.'), '..'); + assert.equal(libUtil.join('http://foo.org/a', ''), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org/a', '.'), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org/a/', ''), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org/a/', '.'), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org/a//', ''), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org/a//', '.'), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org', ''), 'http://foo.org/'); + assert.equal(libUtil.join('http://foo.org', '.'), 'http://foo.org/'); + assert.equal(libUtil.join('http://foo.org/', ''), 'http://foo.org/'); + assert.equal(libUtil.join('http://foo.org/', '.'), 'http://foo.org/'); + assert.equal(libUtil.join('http://foo.org//', ''), 'http://foo.org/'); + assert.equal(libUtil.join('http://foo.org//', '.'), 'http://foo.org/'); + assert.equal(libUtil.join('//www.example.com', ''), '//www.example.com/'); + assert.equal(libUtil.join('//www.example.com', '.'), '//www.example.com/'); + + + assert.equal(libUtil.join('http://foo.org/a', 'b'), 'http://foo.org/a/b'); + assert.equal(libUtil.join('http://foo.org/a/', 'b'), 'http://foo.org/a/b'); + assert.equal(libUtil.join('http://foo.org/a//', 'b'), 'http://foo.org/a/b'); + assert.equal(libUtil.join('http://foo.org/a', 'b/'), 'http://foo.org/a/b/'); + assert.equal(libUtil.join('http://foo.org/a', 'b//'), 'http://foo.org/a/b/'); + assert.equal(libUtil.join('http://foo.org/a/', '/b'), 'http://foo.org/b'); + assert.equal(libUtil.join('http://foo.org/a//', '//b'), 'http://b'); + + assert.equal(libUtil.join('http://foo.org/a', '..'), 'http://foo.org/'); + assert.equal(libUtil.join('http://foo.org/a', '../b'), 'http://foo.org/b'); + assert.equal(libUtil.join('http://foo.org/a/b', '../c'), 'http://foo.org/a/c'); + + assert.equal(libUtil.join('http://foo.org/a', '.'), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org/a', './b'), 'http://foo.org/a/b'); + assert.equal(libUtil.join('http://foo.org/a/b', './c'), 'http://foo.org/a/b/c'); + + assert.equal(libUtil.join('http://foo.org/a', 'http://www.example.com'), 'http://www.example.com'); + assert.equal(libUtil.join('http://foo.org/a', 'data:foo,bar'), 'data:foo,bar'); + + + assert.equal(libUtil.join('http://foo.org', 'a'), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org/', 'a'), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org//', 'a'), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org', '/a'), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org/', '/a'), 'http://foo.org/a'); + assert.equal(libUtil.join('http://foo.org//', '/a'), 'http://foo.org/a'); + + + assert.equal(libUtil.join('http://', 'www.example.com'), 'http://www.example.com'); + assert.equal(libUtil.join('file:///', 'www.example.com'), 'file:///www.example.com'); + assert.equal(libUtil.join('http://', 'ftp://example.com'), 'ftp://example.com'); + + assert.equal(libUtil.join('http://www.example.com', '//foo.org/bar'), 'http://foo.org/bar'); + assert.equal(libUtil.join('//www.example.com', '//foo.org/bar'), '//foo.org/bar'); + }; + + // TODO Issue #128: Define and test this function properly. + exports['test relative()'] = function (assert, util) { + assert.equal(libUtil.relative('/the/root', '/the/root/one.js'), 'one.js'); + assert.equal(libUtil.relative('/the/root', '/the/rootone.js'), '/the/rootone.js'); + + assert.equal(libUtil.relative('', '/the/root/one.js'), '/the/root/one.js'); + assert.equal(libUtil.relative('.', '/the/root/one.js'), '/the/root/one.js'); + assert.equal(libUtil.relative('', 'the/root/one.js'), 'the/root/one.js'); + assert.equal(libUtil.relative('.', 'the/root/one.js'), 'the/root/one.js'); + + assert.equal(libUtil.relative('/', '/the/root/one.js'), 'the/root/one.js'); + assert.equal(libUtil.relative('/', 'the/root/one.js'), 'the/root/one.js'); + }; + +}); diff --git a/homework8/project_express/node_modules/source-map/test/source-map/util.js b/homework8/project_express/node_modules/source-map/test/source-map/util.js new file mode 100644 index 0000000..56bbe2c --- /dev/null +++ b/homework8/project_express/node_modules/source-map/test/source-map/util.js @@ -0,0 +1,192 @@ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module, require); +} +define(function (require, exports, module) { + + var util = require('../../lib/source-map/util'); + + // This is a test mapping which maps functions from two different files + // (one.js and two.js) to a minified generated source. + // + // Here is one.js: + // + // ONE.foo = function (bar) { + // return baz(bar); + // }; + // + // Here is two.js: + // + // TWO.inc = function (n) { + // return n + 1; + // }; + // + // And here is the generated code (min.js): + // + // ONE.foo=function(a){return baz(a);}; + // TWO.inc=function(a){return a+1;}; + exports.testGeneratedCode = " ONE.foo=function(a){return baz(a);};\n"+ + " TWO.inc=function(a){return a+1;};"; + exports.testMap = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourceRoot: '/the/root', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + exports.testMapNoSourceRoot = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + exports.testMapEmptySourceRoot = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourceRoot: '', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + exports.testMapWithSourcesContent = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['one.js', 'two.js'], + sourcesContent: [ + ' ONE.foo = function (bar) {\n' + + ' return baz(bar);\n' + + ' };', + ' TWO.inc = function (n) {\n' + + ' return n + 1;\n' + + ' };' + ], + sourceRoot: '/the/root', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + exports.testMapRelativeSources = { + version: 3, + file: 'min.js', + names: ['bar', 'baz', 'n'], + sources: ['./one.js', './two.js'], + sourcesContent: [ + ' ONE.foo = function (bar) {\n' + + ' return baz(bar);\n' + + ' };', + ' TWO.inc = function (n) {\n' + + ' return n + 1;\n' + + ' };' + ], + sourceRoot: '/the/root', + mappings: 'CAAC,IAAI,IAAM,SAAUA,GAClB,OAAOC,IAAID;CCDb,IAAI,IAAM,SAAUE,GAClB,OAAOA' + }; + exports.emptyMap = { + version: 3, + file: 'min.js', + names: [], + sources: [], + mappings: '' + }; + + + function assertMapping(generatedLine, generatedColumn, originalSource, + originalLine, originalColumn, name, map, assert, + dontTestGenerated, dontTestOriginal) { + if (!dontTestOriginal) { + var origMapping = map.originalPositionFor({ + line: generatedLine, + column: generatedColumn + }); + assert.equal(origMapping.name, name, + 'Incorrect name, expected ' + JSON.stringify(name) + + ', got ' + JSON.stringify(origMapping.name)); + assert.equal(origMapping.line, originalLine, + 'Incorrect line, expected ' + JSON.stringify(originalLine) + + ', got ' + JSON.stringify(origMapping.line)); + assert.equal(origMapping.column, originalColumn, + 'Incorrect column, expected ' + JSON.stringify(originalColumn) + + ', got ' + JSON.stringify(origMapping.column)); + + var expectedSource; + + if (originalSource && map.sourceRoot && originalSource.indexOf(map.sourceRoot) === 0) { + expectedSource = originalSource; + } else if (originalSource) { + expectedSource = map.sourceRoot + ? util.join(map.sourceRoot, originalSource) + : originalSource; + } else { + expectedSource = null; + } + + assert.equal(origMapping.source, expectedSource, + 'Incorrect source, expected ' + JSON.stringify(expectedSource) + + ', got ' + JSON.stringify(origMapping.source)); + } + + if (!dontTestGenerated) { + var genMapping = map.generatedPositionFor({ + source: originalSource, + line: originalLine, + column: originalColumn + }); + assert.equal(genMapping.line, generatedLine, + 'Incorrect line, expected ' + JSON.stringify(generatedLine) + + ', got ' + JSON.stringify(genMapping.line)); + assert.equal(genMapping.column, generatedColumn, + 'Incorrect column, expected ' + JSON.stringify(generatedColumn) + + ', got ' + JSON.stringify(genMapping.column)); + } + } + exports.assertMapping = assertMapping; + + function assertEqualMaps(assert, actualMap, expectedMap) { + assert.equal(actualMap.version, expectedMap.version, "version mismatch"); + assert.equal(actualMap.file, expectedMap.file, "file mismatch"); + assert.equal(actualMap.names.length, + expectedMap.names.length, + "names length mismatch: " + + actualMap.names.join(", ") + " != " + expectedMap.names.join(", ")); + for (var i = 0; i < actualMap.names.length; i++) { + assert.equal(actualMap.names[i], + expectedMap.names[i], + "names[" + i + "] mismatch: " + + actualMap.names.join(", ") + " != " + expectedMap.names.join(", ")); + } + assert.equal(actualMap.sources.length, + expectedMap.sources.length, + "sources length mismatch: " + + actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", ")); + for (var i = 0; i < actualMap.sources.length; i++) { + assert.equal(actualMap.sources[i], + expectedMap.sources[i], + "sources[" + i + "] length mismatch: " + + actualMap.sources.join(", ") + " != " + expectedMap.sources.join(", ")); + } + assert.equal(actualMap.sourceRoot, + expectedMap.sourceRoot, + "sourceRoot mismatch: " + + actualMap.sourceRoot + " != " + expectedMap.sourceRoot); + assert.equal(actualMap.mappings, expectedMap.mappings, + "mappings mismatch:\nActual: " + actualMap.mappings + "\nExpected: " + expectedMap.mappings); + if (actualMap.sourcesContent) { + assert.equal(actualMap.sourcesContent.length, + expectedMap.sourcesContent.length, + "sourcesContent length mismatch"); + for (var i = 0; i < actualMap.sourcesContent.length; i++) { + assert.equal(actualMap.sourcesContent[i], + expectedMap.sourcesContent[i], + "sourcesContent[" + i + "] mismatch"); + } + } + } + exports.assertEqualMaps = assertEqualMaps; + +}); diff --git a/homework8/project_express/node_modules/statuses/HISTORY.md b/homework8/project_express/node_modules/statuses/HISTORY.md new file mode 100644 index 0000000..a1977b2 --- /dev/null +++ b/homework8/project_express/node_modules/statuses/HISTORY.md @@ -0,0 +1,65 @@ +1.5.0 / 2018-03-27 +================== + + * Add `103 Early Hints` + +1.4.0 / 2017-10-20 +================== + + * Add `STATUS_CODES` export + +1.3.1 / 2016-11-11 +================== + + * Fix return type in JSDoc + +1.3.0 / 2016-05-17 +================== + + * Add `421 Misdirected Request` + * perf: enable strict mode + +1.2.1 / 2015-02-01 +================== + + * Fix message for status 451 + - `451 Unavailable For Legal Reasons` + +1.2.0 / 2014-09-28 +================== + + * Add `208 Already Repored` + * Add `226 IM Used` + * Add `306 (Unused)` + * Add `415 Unable For Legal Reasons` + * Add `508 Loop Detected` + +1.1.1 / 2014-09-24 +================== + + * Add missing 308 to `codes.json` + +1.1.0 / 2014-09-21 +================== + + * Add `codes.json` for universal support + +1.0.4 / 2014-08-20 +================== + + * Package cleanup + +1.0.3 / 2014-06-08 +================== + + * Add 308 to `.redirect` category + +1.0.2 / 2014-03-13 +================== + + * Add `.retry` category + +1.0.1 / 2014-03-12 +================== + + * Initial release diff --git a/homework8/project_express/node_modules/statuses/LICENSE b/homework8/project_express/node_modules/statuses/LICENSE new file mode 100644 index 0000000..28a3161 --- /dev/null +++ b/homework8/project_express/node_modules/statuses/LICENSE @@ -0,0 +1,23 @@ + +The MIT License (MIT) + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2016 Douglas Christopher Wilson + +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/homework8/project_express/node_modules/statuses/README.md b/homework8/project_express/node_modules/statuses/README.md new file mode 100644 index 0000000..0fe5720 --- /dev/null +++ b/homework8/project_express/node_modules/statuses/README.md @@ -0,0 +1,127 @@ +# Statuses + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +HTTP status utility for node. + +This module provides a list of status codes and messages sourced from +a few different projects: + + * The [IANA Status Code Registry](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml) + * The [Node.js project](https://nodejs.org/) + * The [NGINX project](https://www.nginx.com/) + * The [Apache HTTP Server project](https://httpd.apache.org/) + +## Installation + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```sh +$ npm install statuses +``` + +## API + + + +```js +var status = require('statuses') +``` + +### var code = status(Integer || String) + +If `Integer` or `String` is a valid HTTP code or status message, then the +appropriate `code` will be returned. Otherwise, an error will be thrown. + + + +```js +status(403) // => 403 +status('403') // => 403 +status('forbidden') // => 403 +status('Forbidden') // => 403 +status(306) // throws, as it's not supported by node.js +``` + +### status.STATUS_CODES + +Returns an object which maps status codes to status messages, in +the same format as the +[Node.js http module](https://nodejs.org/dist/latest/docs/api/http.html#http_http_status_codes). + +### status.codes + +Returns an array of all the status codes as `Integer`s. + +### var msg = status[code] + +Map of `code` to `status message`. `undefined` for invalid `code`s. + + + +```js +status[404] // => 'Not Found' +``` + +### var code = status[msg] + +Map of `status message` to `code`. `msg` can either be title-cased or +lower-cased. `undefined` for invalid `status message`s. + + + +```js +status['not found'] // => 404 +status['Not Found'] // => 404 +``` + +### status.redirect[code] + +Returns `true` if a status code is a valid redirect status. + + + +```js +status.redirect[200] // => undefined +status.redirect[301] // => true +``` + +### status.empty[code] + +Returns `true` if a status code expects an empty body. + + + +```js +status.empty[200] // => undefined +status.empty[204] // => true +status.empty[304] // => true +``` + +### status.retry[code] + +Returns `true` if you should retry the rest. + + + +```js +status.retry[501] // => undefined +status.retry[503] // => true +``` + +[npm-image]: https://img.shields.io/npm/v/statuses.svg +[npm-url]: https://npmjs.org/package/statuses +[node-version-image]: https://img.shields.io/node/v/statuses.svg +[node-version-url]: https://nodejs.org/en/download +[travis-image]: https://img.shields.io/travis/jshttp/statuses.svg +[travis-url]: https://travis-ci.org/jshttp/statuses +[coveralls-image]: https://img.shields.io/coveralls/jshttp/statuses.svg +[coveralls-url]: https://coveralls.io/r/jshttp/statuses?branch=master +[downloads-image]: https://img.shields.io/npm/dm/statuses.svg +[downloads-url]: https://npmjs.org/package/statuses diff --git a/homework8/project_express/node_modules/statuses/codes.json b/homework8/project_express/node_modules/statuses/codes.json new file mode 100644 index 0000000..a09283a --- /dev/null +++ b/homework8/project_express/node_modules/statuses/codes.json @@ -0,0 +1,66 @@ +{ + "100": "Continue", + "101": "Switching Protocols", + "102": "Processing", + "103": "Early Hints", + "200": "OK", + "201": "Created", + "202": "Accepted", + "203": "Non-Authoritative Information", + "204": "No Content", + "205": "Reset Content", + "206": "Partial Content", + "207": "Multi-Status", + "208": "Already Reported", + "226": "IM Used", + "300": "Multiple Choices", + "301": "Moved Permanently", + "302": "Found", + "303": "See Other", + "304": "Not Modified", + "305": "Use Proxy", + "306": "(Unused)", + "307": "Temporary Redirect", + "308": "Permanent Redirect", + "400": "Bad Request", + "401": "Unauthorized", + "402": "Payment Required", + "403": "Forbidden", + "404": "Not Found", + "405": "Method Not Allowed", + "406": "Not Acceptable", + "407": "Proxy Authentication Required", + "408": "Request Timeout", + "409": "Conflict", + "410": "Gone", + "411": "Length Required", + "412": "Precondition Failed", + "413": "Payload Too Large", + "414": "URI Too Long", + "415": "Unsupported Media Type", + "416": "Range Not Satisfiable", + "417": "Expectation Failed", + "418": "I'm a teapot", + "421": "Misdirected Request", + "422": "Unprocessable Entity", + "423": "Locked", + "424": "Failed Dependency", + "425": "Unordered Collection", + "426": "Upgrade Required", + "428": "Precondition Required", + "429": "Too Many Requests", + "431": "Request Header Fields Too Large", + "451": "Unavailable For Legal Reasons", + "500": "Internal Server Error", + "501": "Not Implemented", + "502": "Bad Gateway", + "503": "Service Unavailable", + "504": "Gateway Timeout", + "505": "HTTP Version Not Supported", + "506": "Variant Also Negotiates", + "507": "Insufficient Storage", + "508": "Loop Detected", + "509": "Bandwidth Limit Exceeded", + "510": "Not Extended", + "511": "Network Authentication Required" +} diff --git a/homework8/project_express/node_modules/statuses/index.js b/homework8/project_express/node_modules/statuses/index.js new file mode 100644 index 0000000..4df469a --- /dev/null +++ b/homework8/project_express/node_modules/statuses/index.js @@ -0,0 +1,113 @@ +/*! + * statuses + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2016 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var codes = require('./codes.json') + +/** + * Module exports. + * @public + */ + +module.exports = status + +// status code to message map +status.STATUS_CODES = codes + +// array of status codes +status.codes = populateStatusesMap(status, codes) + +// status codes for redirects +status.redirect = { + 300: true, + 301: true, + 302: true, + 303: true, + 305: true, + 307: true, + 308: true +} + +// status codes for empty bodies +status.empty = { + 204: true, + 205: true, + 304: true +} + +// status codes for when you should retry the request +status.retry = { + 502: true, + 503: true, + 504: true +} + +/** + * Populate the statuses map for given codes. + * @private + */ + +function populateStatusesMap (statuses, codes) { + var arr = [] + + Object.keys(codes).forEach(function forEachCode (code) { + var message = codes[code] + var status = Number(code) + + // Populate properties + statuses[status] = message + statuses[message] = status + statuses[message.toLowerCase()] = status + + // Add to array + arr.push(status) + }) + + return arr +} + +/** + * Get the status code. + * + * Given a number, this will throw if it is not a known status + * code, otherwise the code will be returned. Given a string, + * the string will be parsed for a number and return the code + * if valid, otherwise will lookup the code assuming this is + * the status message. + * + * @param {string|number} code + * @returns {number} + * @public + */ + +function status (code) { + if (typeof code === 'number') { + if (!status[code]) throw new Error('invalid status code: ' + code) + return code + } + + if (typeof code !== 'string') { + throw new TypeError('code must be a number or string') + } + + // '403' + var n = parseInt(code, 10) + if (!isNaN(n)) { + if (!status[n]) throw new Error('invalid status code: ' + n) + return n + } + + n = status[code.toLowerCase()] + if (!n) throw new Error('invalid status message: "' + code + '"') + return n +} diff --git a/homework8/project_express/node_modules/statuses/package.json b/homework8/project_express/node_modules/statuses/package.json new file mode 100644 index 0000000..6919edc --- /dev/null +++ b/homework8/project_express/node_modules/statuses/package.json @@ -0,0 +1,90 @@ +{ + "_from": "statuses@~1.5.0", + "_id": "statuses@1.5.0", + "_inBundle": false, + "_integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "_location": "/statuses", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "statuses@~1.5.0", + "name": "statuses", + "escapedName": "statuses", + "rawSpec": "~1.5.0", + "saveSpec": null, + "fetchSpec": "~1.5.0" + }, + "_requiredBy": [ + "/express", + "/finalhandler", + "/http-errors", + "/send" + ], + "_resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "_shasum": "161c7dac177659fd9811f43771fa99381478628c", + "_spec": "statuses@~1.5.0", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\express", + "bugs": { + "url": "https://github.com/jshttp/statuses/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "Jonathan Ong", + "email": "me@jongleberry.com", + "url": "http://jongleberry.com" + } + ], + "deprecated": false, + "description": "HTTP status utility", + "devDependencies": { + "csv-parse": "1.2.4", + "eslint": "4.19.1", + "eslint-config-standard": "11.0.0", + "eslint-plugin-import": "2.9.0", + "eslint-plugin-markdown": "1.0.0-beta.6", + "eslint-plugin-node": "6.0.1", + "eslint-plugin-promise": "3.7.0", + "eslint-plugin-standard": "3.0.1", + "istanbul": "0.4.5", + "mocha": "1.21.5", + "raw-body": "2.3.2", + "stream-to-array": "2.3.0" + }, + "engines": { + "node": ">= 0.6" + }, + "files": [ + "HISTORY.md", + "index.js", + "codes.json", + "LICENSE" + ], + "homepage": "https://github.com/jshttp/statuses#readme", + "keywords": [ + "http", + "status", + "code" + ], + "license": "MIT", + "name": "statuses", + "repository": { + "type": "git", + "url": "git+https://github.com/jshttp/statuses.git" + }, + "scripts": { + "build": "node scripts/build.js", + "fetch": "node scripts/fetch-apache.js && node scripts/fetch-iana.js && node scripts/fetch-nginx.js && node scripts/fetch-node.js", + "lint": "eslint --plugin markdown --ext js,md .", + "test": "mocha --reporter spec --check-leaks --bail test/", + "test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "update": "npm run fetch && npm run build" + }, + "version": "1.5.0" +} diff --git a/homework8/project_express/node_modules/std/Animation.js b/homework8/project_express/node_modules/std/Animation.js new file mode 100644 index 0000000..93ef41a --- /dev/null +++ b/homework8/project_express/node_modules/std/Animation.js @@ -0,0 +1,57 @@ +var Class = require('./Class'), + extend = require('./extend') + +module.exports = Class(function() { + + var defaults = { + duration:250, + interval:40, + tween:function linearTween(delta) { return delta } + } + + this.init = function(animationFunction, opts) { + this._animationFunction = animationFunction + opts = extend(opts, defaults) + this._duration = opts.duration + this._interval = opts.interval + this._tween = opts.tween + this._onDone = opts.onDone + } + + this.start = function(reverse) { + this._playing = true + this._startT = new Date().getTime() + this._reverse = reverse + this._onInterval() + this._intervalID = setInterval(bind(this, this._onInterval), this._interval) + } + + this.stop = function() { + this._playing = false + clearInterval(this._intervalID) + } + + this.isGoing = function() { return this._playing } + + this._onInterval = function() { + var deltaT = new Date().getTime() - this._startT, + duration = this._duration + if (deltaT >= duration) { + this.stop() + this._animationFunction(this._tween(this._reverse ? 0 : 1)) + if (this._onDone) { this._onDone() } + return + } + var delta = deltaT / duration + if (this._reverse) { delta = 1 - delta } + this._animationFunction(this._tween(delta)) + } +}) + +// Easing equation function for elastic tween: http://code.google.com/p/kawanet/source/browse/lang/as3/KTween/trunk/src/net/kawa/tween/easing/Elastic.as +module.exports.elasticEaseOut = function(delta) { + var x = 1 - delta, + elasticity = 0.25 + value = 1 - Math.pow(x, 4) + x * x * Math.sin(delta * delta * Math.PI * elasticity) + return value +} diff --git a/homework8/project_express/node_modules/std/Changelog b/homework8/project_express/node_modules/std/Changelog new file mode 100644 index 0000000..bbc9f99 --- /dev/null +++ b/homework8/project_express/node_modules/std/Changelog @@ -0,0 +1,179 @@ +v0.1.39 ++ Stop using Changelog. See `git log` + +v0.1.38 ++ implement parallel ++ implement asyncEach ++ implement asyncMap ++ implement nextTick + +v0.1.37 ++ implemented waitFor ++ implemented rand ++ other improvements + +v0.1.35 ++ Better touch detection + +v0.1.34 ++ Better Promises ++ Small fix in time.js + +v0.1.33 ++ extend now uses copy instead of create + +v0.1.32 ++ implement blockFunction.addBlock + +v0.1.31 ++ Beefed up proto.js + +v0.1.30 ++ Improved throttle + +v0.1.29 ++ import base64 ++ Many other changes... + +v0.1.28 ++ implement repeat ++ implement deepEqual ++ implement proto ++ improved client detection in client.js + +v0.1.27 ++ make client a proper class, and add the beginnins to OS user-agent parsing ++ improve url.js - enable getting and setting the hash/query params ++ implement merge ++ Add client.isMobile + +v0.1.26 ++ add client.name and client.is[IPhone, IPad, IPod] + +v0.1.25 ++ fix cookie.remove ++ implement create ++ implement arrayToObject ++ implement defineGetter + +v0.1.24 ++ implement cookie ++ move dom/* into ui library ui.js ++ implement Animation ++ add json, from JSON2 https://github.com/douglascrockford/JSON-js ++ xhr improvements ++ implement url ++ implement trim ++ implement isArguments ++ use native isArray if available ++ add @kaleb to contributors + +v0.1.23 ++ rename class _init to init ++ add support for mixins ++ implement Promise ++ implement invokeWith ++ implement recall ++ implement Publisher mixin ++ implement dom ++ implement client ++ implement popup + +v0.1.22 ++ implement ui/Component#_off ++ implement ui/Component#_makeDraggable - publishes 'drag' and 'drop' events, both with a data object describing the drag ++ implement throttle ++ change implementation of delay to actually delay, rather than throttle ++ Improved ui/Component event normalization (notably mousewheel) ++ Implement browser ++ Implement math.round + +v0.1.21 ++ start implementing std/time ++ implement copy - shallow object/array copying, with a flag for deep copying ++ implement keys ++ implement flatten ++ clean up xhr code ++ fix xhr bug where callback would not get called for empty responses + + +v0.1.20 ++ ui/Component API cleanup ++ implement ui/Component display, hide and show ++ fix ui/Component addClass/hasClass/removeClass/toggleClass ++ better xhr error checking and xhr object cleanup ++ implement invoke ++ rename pick to filter. deprecate pick, but keep it around for now ++ give Logger alert email functionality ++ Fix delay ++ fix ui/Input defaultValue class name mixup + +v0.1.19 ++ Add xhr option not to encode values ++ Rename ui/Component#_dom to dom ++ Fix xhr get requests without a ? in the URL ++ fix context bug in delay + +v0.1.18 ++ implement delay ++ implement Logger ++ implement ui/Component ++ implement ui/Select ++ implement ui/Input + +v0.1.16 ++ Allow for passing in a context to each and map + +v0.1.15 ++ JSON.stringify xhr query parameters ++ Use JSON.parse rather than eval to parse responses. Much safer :) + +v0.1.14 ++ implement xhr ++ implement Publisher + +v0.1.12 ++ enable e.g. require('std/curry') + +v0.1.11 ++ add MIT license ++ implement curry + +v0.1.10 ++ implement slice + +v0.1.9 ++ implement strip, for stripping off the whitespace of strings ++ implement pick, for picking items out of an array + +v0.1.8 ++ fix stupid mistake + +v0.1.7 ++ import pack, unpack, crc32 and utf8_encode functions from phpjs ++ move function files into lib + +v0.1.6 ++ extend now returns the first argument, or a new object if first argument is null + +v0.1.5 ++ fix bind when second argument is a string + +v0.1.4 ++ implement extend + +v0.1.3 ++ call class initializer functions _init rather than initialize + +v0.1.2 ++ implement Class + +v0.1.1 ++ implement isArray ++ implement each ++ implement map + +v0.1.0 ++ Implement bind ++ Publish on npm as std + diff --git a/homework8/project_express/node_modules/std/Class.js b/homework8/project_express/node_modules/std/Class.js new file mode 100644 index 0000000..b316644 --- /dev/null +++ b/homework8/project_express/node_modules/std/Class.js @@ -0,0 +1,80 @@ +/* Example usage: + + var UIComponent = Class(function() { + this.init = function() { ... } + this.create = function() { ... this.createDOM() ... } + }) + + var PublisherMixin = { + init: function(){ ... }, + publish_: function() { ... } + } + + var Button = Class(UIComponent, PublisherMixin, function(supr) { + this.init = function(opts) { + // call UIComponents init method, with the passed in arguments + supr(this, 'init', arguments) // or, UIComponent.constructor.prototype.init.apply(this, arguments) + this.color_ = opts && opts.color + } + + // createDOM overwrites abstract method from parent class UIComponent + this.createDOM = function() { + this.getElement().onclick = bind(this, function(e) { + // this.publish_ is a method added to Button by the Publisher mixin + this.publish_('Click', e) + }) + } + }) + +*/ +module.exports = function Class(/* optParent, optMixin1, optMixin2, ..., proto */) { + var args = arguments, + numOptArgs = args.length - 1, + mixins = [] + + // the prototype function is always the last argument + var proto = args[numOptArgs] + + // if there's more than one argument, then the first argument is the parent class + if (numOptArgs) { + var parent = args[0] + if (parent) { proto.prototype = parent.prototype } + } + + for (var i=1; i < numOptArgs; i++) { mixins.push(arguments[i]) } + + // cls is the actual class function. Classes may implement this.init = function(){ ... }, + // which gets called upon instantiation + var cls = function() { + if(this.init) { this.init.apply(this, arguments) } + for (var i=0, mixin; mixin = mixins[i]; i++) { + if (mixin.init) { mixin.init.apply(this) } + } + } + + // the proto function gets called with the supr function as an argument. supr climbs the + // inheritence chain, looking for the named method + cls.prototype = new proto(function supr(context, method, args) { + var target = parent + while(target = target.prototype) { + if(target[method]) { + return target[method].apply(context, args || []) + } + } + throw new Error('supr: parent method ' + method + ' does not exist') + }) + + // add all mixins' properties to the class' prototype object + for (var i=0, mixin; mixin = mixins[i]; i++) { + for (var propertyName in mixin) { + if (!mixin.hasOwnProperty(propertyName) || propertyName == 'init') { continue } + if (cls.prototype.hasOwnProperty(propertyName)) { + throw new Error('Mixin property "'+propertyName+'" already exists on class') + } + cls.prototype[propertyName] = mixin[propertyName] + } + } + + cls.prototype.constructor = cls + return cls +} diff --git a/homework8/project_express/node_modules/std/LICENSE b/homework8/project_express/node_modules/std/LICENSE new file mode 100644 index 0000000..341bae5 --- /dev/null +++ b/homework8/project_express/node_modules/std/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2011 Marcus Westin + +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/homework8/project_express/node_modules/std/ListPromise.js b/homework8/project_express/node_modules/std/ListPromise.js new file mode 100644 index 0000000..1875bea --- /dev/null +++ b/homework8/project_express/node_modules/std/ListPromise.js @@ -0,0 +1,47 @@ +var proto = require('./proto'), + bind = require('./bind') + +module.exports = proto(null, + function(waitForNum, callback) { + this._waitingFor = waitForNum + this._callbacks = [] + this._results = [] + this._error = null + if (callback) { this.add(callback) } + }, { + add: function(callback) { + if (!this._waitingFor) { + this._notify(callback) + } else { + this._callbacks.push(callback) + } + }, + getResponder: function() { + return bind(this, function(err, res) { + if (err) { this.fail(err) } + else { this.fulfill(res) } + }) + }, + fulfill: function(result) { + if (!this._waitingFor) { throw new Error('ListPromise fulfilled too many times') } + this._results.push(result) + if (!--this._waitingFor) { + this._notifyAll() + } + }, + fail: function(error) { + this._error = error + this._notifyAll() + }, + _notifyAll: function() { + if (!this._callbacks) { return } + for (var i=0; i= 0; i--) { + if (ka[i] != kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!deepEqual(a[key], b[key] )) + return false; + } + return true; +} diff --git a/homework8/project_express/node_modules/std/asyncEach.js b/homework8/project_express/node_modules/std/asyncEach.js new file mode 100644 index 0000000..878162a --- /dev/null +++ b/homework8/project_express/node_modules/std/asyncEach.js @@ -0,0 +1,63 @@ +var nextTick = require('std/nextTick') + +module.exports = function asyncEach(items, opts) { + var finish = opts.finish + if (!items.length) { return finish(null, []) } + + var parallel = opts.parallel + if (parallel === true) { parallel = items.length } + if (!parallel) { parallel = 1 } + if (parallel > waitingFor) { parallel = waitingFor } + + var nextIndex = 0 + var result = [] + var errorResult = null + var waitingFor = items.length + var context = opts.context || this + + var iterator = module.exports.makeIterator(context, opts.iterate) + + function processNextItem() { + if (!waitingFor) { + return finish.call(context, null) + } + var iterationIndex = nextIndex + if (iterationIndex == items.length) { + // no more processing to be done - just wait for the remaining parallel requests to finish + return + } + nextIndex += 1 + nextTick(function() { + iterator(items[iterationIndex], iterationIndex, iteratorCallback) + }) + } + + function iteratorCallback(err) { + if (errorResult) { return } + if (err) { + errorResult = err + finish.call(context, err, null) + } else { + waitingFor -= 1 + processNextItem() + } + } + + // starts `parallel` number of functions processing the array + for (var parallelI=0; parallelI>> 18) + + b64chars.charAt((n >>> 12) & 63) + + b64chars.charAt((n >>> 6) & 63) + + b64chars.charAt( n & 63); +}; + +var toBase64 = function(bin){ + if (bin.match(/[^\x00-\xFF]/)) throw 'unsupported character found' ; + var padlen = 0; + while(bin.length % 3) { + bin += '\0'; + padlen++; + }; + var b64 = bin.replace(/[\x00-\xFF]{3}/g, sub_toBase64); + if (!padlen) return b64; + b64 = b64.substr(0, b64.length - padlen); + while(padlen--) b64 += '='; + return b64; +}; + +var btoa = global.btoa || toBase64; + +var sub_fromBase64 = function(m){ + var n = (b64tab[ m.charAt(0) ] << 18) + | (b64tab[ m.charAt(1) ] << 12) + | (b64tab[ m.charAt(2) ] << 6) + | (b64tab[ m.charAt(3) ]); + return String.fromCharCode( n >> 16 ) + + String.fromCharCode( (n >> 8) & 0xff ) + + String.fromCharCode( n & 0xff ); +}; + +var fromBase64 = function(b64){ + b64 = b64.replace(/[^A-Za-z0-9\+\/]/g, ''); + var padlen = 0; + while(b64.length % 4){ + b64 += 'A'; + padlen++; + } + var bin = b64.replace(/[A-Za-z0-9\+\/]{4}/g, sub_fromBase64); + if (padlen >= 2) + bin = bin.substring(0, bin.length - [0,0,2,1][padlen]); + return bin; +}; + +var atob = global.atob || fromBase64; + +var re_char_nonascii = /[^\x00-\x7F]/g; + +var sub_char_nonascii = function(m){ + var n = m.charCodeAt(0); + return n < 0x800 ? String.fromCharCode(0xc0 | (n >>> 6)) + + String.fromCharCode(0x80 | (n & 0x3f)) + : String.fromCharCode(0xe0 | ((n >>> 12) & 0x0f)) + + String.fromCharCode(0x80 | ((n >>> 6) & 0x3f)) + + String.fromCharCode(0x80 | (n & 0x3f)) + ; +}; + +var utob = function(uni){ + return uni.replace(re_char_nonascii, sub_char_nonascii); +}; + +var re_bytes_nonascii + = /[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g; + +var sub_bytes_nonascii = function(m){ + var c0 = m.charCodeAt(0); + var c1 = m.charCodeAt(1); + if(c0 < 0xe0){ + return String.fromCharCode(((c0 & 0x1f) << 6) | (c1 & 0x3f)); + }else{ + var c2 = m.charCodeAt(2); + return String.fromCharCode( + ((c0 & 0x0f) << 12) | ((c1 & 0x3f) << 6) | (c2 & 0x3f) + ); + } +}; + +var btou = function(bin){ + return bin.replace(re_bytes_nonascii, sub_bytes_nonascii); +}; + +global.exports = { + fromBase64:fromBase64, + toBase64:toBase64, + atob:atob, + btoa:btoa, + utob:utob, + btou:btou, + encode:function(u){ return btoa(utob(u)) }, + encodeURI:function(u){ + return btoa(utob(u)).replace(/[+\/]/g, function(m0){ + return m0 == '+' ? '-' : '_'; + }).replace(/=+$/, ''); + }, + decode:function(a){ + return btou(atob(a.replace(/[-_]/g, function(m0){ + return m0 == '-' ? '+' : '/'; + }))); + } +}; + +})(module); \ No newline at end of file diff --git a/homework8/project_express/node_modules/std/bind.js b/homework8/project_express/node_modules/std/bind.js new file mode 100644 index 0000000..cf15e4d --- /dev/null +++ b/homework8/project_express/node_modules/std/bind.js @@ -0,0 +1,50 @@ +/* + Example usage: + + function Client() { + this._socket = new Connection() + this._socket.open() + this._socket.on('connected', bind(this, '_log', 'connected!')) + this._socket.on('connected', bind(this, 'disconnect')) + } + + Client.prototype._log = function(message) { + console.log('client says:', message) + } + + Client.prototype.disconnect = function() { + this._socket.disconnect() + } + + Example usage: + + var Toolbar = Class(function() { + + this.init = function() { + this._buttonWasClicked = false + } + + this.addButton = function(clickHandler) { + this._button = new Button() + this._button.on('Click', bind(this, '_onButtonClick', clickHandler)) + } + + this._onButtonClick = function(clickHandler) { + this._buttonWasClicked = true + clickHandler() + } + + }) + +*/ +var slice = require('./slice') + +module.exports = function bind(context, method /* curry1, curry2, ... curryN */) { + if (typeof method == 'string') { method = context[method] } + var curryArgs = slice(arguments, 2) + return function bound() { + var invocationArgs = slice(arguments) + return method.apply(context, curryArgs.concat(invocationArgs)) + } +} + diff --git a/homework8/project_express/node_modules/std/blockFunction.js b/homework8/project_express/node_modules/std/blockFunction.js new file mode 100644 index 0000000..00250b3 --- /dev/null +++ b/homework8/project_express/node_modules/std/blockFunction.js @@ -0,0 +1,44 @@ +/* + Block a function from being called by adding and removing any number of blocks. + Excellent for waiting on parallel asynchronous operations. + A blocked function starts out with exactly one block + + Example usage: + + http.createServer(function(req, res) { + var sendResponse = blockFunction(function() { + res.writeHead(204) + res.end() + }) + var queries = parseQueries(req.url) + for (var i=0; i= 0) + } +}) + +if (typeof window != 'undefined') { module.exports = new Client(window.navigator.userAgent) } +else { module.exports = {} } + +module.exports.parse = function(userAgent) { return new Client(userAgent) } diff --git a/homework8/project_express/node_modules/std/clip.js b/homework8/project_express/node_modules/std/clip.js new file mode 100644 index 0000000..e680270 --- /dev/null +++ b/homework8/project_express/node_modules/std/clip.js @@ -0,0 +1,3 @@ +module.exports = function clip(val, min, max) { + return Math.max(Math.min(val, max), min) +} diff --git a/homework8/project_express/node_modules/std/cookie.js b/homework8/project_express/node_modules/std/cookie.js new file mode 100644 index 0000000..5f88f5b --- /dev/null +++ b/homework8/project_express/node_modules/std/cookie.js @@ -0,0 +1,33 @@ +module.exports.get = function(name) { + var regex = new RegExp( + '(^|(; ))' + // beginning of document.cookie, or "; " which signifies the beginning of a new cookie + name + + '=([^;]*)') // the value of the cookie, matched up until a ";" or the end of the string + + var match = document.cookie.match(regex), + value = match && match[3] + return value && decodeURIComponent(value) +} + +module.exports.set = function(name, value, duration) { + if (duration === undefined) { duration = (365 * 24 * 60 * 60 * 1000) } // one year + var date = (duration instanceof Date ? duration : (duration < 0 ? null : new Date(new Date().getTime() + duration))), + expires = date ? "expires=" + date.toGMTString() + '; ' : '', + cookieName = name + '=' + encodeURIComponent(value) + '; ', + domain = 'domain='+document.domain+'; ', + path = 'path=/; ' + + document.cookie = cookieName + expires + domain + path +} + +module.exports.isEnabled = function() { + var name = '__test__cookie' + new Date().getTime() + module.exports.set(name, 1) + var isEnabled = !!module.exports.get(name) + module.exports.remove(name) + return isEnabled +} + +module.exports.remove = function(name) { + module.exports.set(name, "", new Date(1)) +} diff --git a/homework8/project_express/node_modules/std/copy.js b/homework8/project_express/node_modules/std/copy.js new file mode 100644 index 0000000..bbba668 --- /dev/null +++ b/homework8/project_express/node_modules/std/copy.js @@ -0,0 +1,10 @@ +var each = require('./each'), + isArray = require('./isArray') + +module.exports = function copy(obj, deep) { + var result = isArray(obj) ? [] : {} + each(obj, function(val, key) { + result[key] = (deep && typeof val == 'object') ? copy(val, deep) : val + }) + return result +} diff --git a/homework8/project_express/node_modules/std/crc32.js b/homework8/project_express/node_modules/std/crc32.js new file mode 100644 index 0000000..5aa5d3e --- /dev/null +++ b/homework8/project_express/node_modules/std/crc32.js @@ -0,0 +1,28 @@ +// https://github.com/kvz/phpjs/raw/2ae4292a8629d6007eae26298bd19339ef97957e/functions/strings/crc32.js +// MIT License http://phpjs.org/pages/license + +var utf8_encode = require('./utf8_encode') + +module.exports = function crc32 (str) { + // http://kevin.vanzonneveld.net + // + original by: Webtoolkit.info (http://www.webtoolkit.info/) + // + improved by: T0bsn + // - depends on: utf8_encode + // * example 1: crc32('Kevin van Zonneveld'); + // * returns 1: 1249991249 + str = utf8_encode(str); + var table = "00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F 63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC 51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E 7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D 806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA 11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F 30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D"; + + var crc = 0; + var x = 0; + var y = 0; + + crc = crc ^ (-1); + for (var i = 0, iTop = str.length; i < iTop; i++) { + y = (crc ^ str.charCodeAt(i)) & 0xFF; + x = "0x" + table.substr(y * 9, 8); + crc = (crc >>> 8) ^ x; + } + + return crc ^ (-1); +} diff --git a/homework8/project_express/node_modules/std/create.js b/homework8/project_express/node_modules/std/create.js new file mode 100644 index 0000000..fa865be --- /dev/null +++ b/homework8/project_express/node_modules/std/create.js @@ -0,0 +1,22 @@ +// Thanks Douglas Crockford! http://javascript.crockford.com/prototypal.html +module.exports = function create(obj, extendWithProperties) { + function extendObject(result, props) { + for (var key in props) { + if (!props.hasOwnProperty(key)) { continue } + result[key] = props[key] + } + return result + } + if (typeof Object.create == 'function') { + module.exports = function nativeCreate(obj, extendWithProperties) { + return extendObject(Object.create(obj), extendWithProperties) + } + } else { + module.exports = function shimCreate(obj, extendWithProperties) { + function F() {} + F.prototype = obj + return extendObject(new F(), extendWithProperties) + } + } + return module.exports(obj, extendWithProperties) +} diff --git a/homework8/project_express/node_modules/std/curry.js b/homework8/project_express/node_modules/std/curry.js new file mode 100644 index 0000000..52d4a19 --- /dev/null +++ b/homework8/project_express/node_modules/std/curry.js @@ -0,0 +1,10 @@ +var slice = require('./slice') + +module.exports = function curry(fn /* arg1, arg2, ... argN */) { + var curryArgs = slice(arguments, 1) + return function curried() { + var invocationArgs = slice(arguments) + return fn.apply(this, curryArgs.concat(invocationArgs)) + } +} + diff --git a/homework8/project_express/node_modules/std/defineGetter.js b/homework8/project_express/node_modules/std/defineGetter.js new file mode 100644 index 0000000..0071e2c --- /dev/null +++ b/homework8/project_express/node_modules/std/defineGetter.js @@ -0,0 +1,29 @@ +module.exports = function(object, propertyName, getter) { + module.exports = object.defineGetter ? _w3cDefineGetter + : object.__defineGetter__ ? _interimDefineGetter + : Object.defineProperty ? _ie8DefineGetter + : function() { throw 'defineGetter not supported' } + return module.exports(object, propertyName, getter) +} + +function defineGetter(object, propertyName, getter) { + var fn = object.defineGetter ? _w3cDefineGetter + : object.__defineGetter__ ? _interimDefineGetter + : Object.defineProperty ? _ie8DefineGetter + : function() { throw new Error('defineGetter is not supported') } + + module.exports.defineGetter = fn + fn.apply(this, arguments) +} + +var _w3cDefineGetter = function(object, propertyName, getter) { + object.defineGetter(propertyName, getter) +} + +var _interimDefineGetter = function(object, propertyName, getter) { + object.__defineGetter__(propertyName, getter) +} + +var _ie8DefineGetter = function(object, propertyName, getter) { + Object.defineProperty(object, propertyName, { value:getter, enumerable:true, configurable:true }) +} diff --git a/homework8/project_express/node_modules/std/delay.js b/homework8/project_express/node_modules/std/delay.js new file mode 100644 index 0000000..2984b4b --- /dev/null +++ b/homework8/project_express/node_modules/std/delay.js @@ -0,0 +1,51 @@ +/* + Delay the execution of a function. + If the function gets called multiple times during a delay, the delayed function gets invoced only once, + with the arguments of the most recent invocation. This is useful for expensive functions that should + not be called multiple times during a short time interval, e.g. rendering + + Example usage: + + Class(UIComponent, function() { + this.render = delay(function() { + ... + }, 250) // render at most 4 times per second + }) + + // Bath messages into a single email + var EmailBatcher = Class(function() { + this.init = function() { + this._queue = [] + } + + this.send = function(email) { + this._queue.push(email) + this._scheduleDispatch() + } + + this._scheduleDispatch = delay(function() { + smtp.send(this._queue.join('\n\n')) + this._queue = [] + }, 5000) // send emails at most once every 5 seconds + }) +*/ +module.exports = function delay(fn, delayBy) { + if (typeof delayBy != 'number') { delayBy = 50 } + var timeoutName = '__delayTimeout__' + (++module.exports._unique) + var delayedFunction = function delayed() { + if (this[timeoutName]) { + clearTimeout(this[timeoutName]) + } + var args = arguments, self = this + this[timeoutName] = setTimeout(function fireDelayed() { + clearTimeout(self[timeoutName]) + delete self[timeoutName] + fn.apply(self, args) + }, delayBy) + } + delayedFunction.cancel = function() { + clearTimeout(this[timeoutName]) + } + return delayedFunction +} +module.exports._unique = 0 diff --git a/homework8/project_express/node_modules/std/delayed.js b/homework8/project_express/node_modules/std/delayed.js new file mode 100644 index 0000000..3efc6ba --- /dev/null +++ b/homework8/project_express/node_modules/std/delayed.js @@ -0,0 +1,11 @@ +module.exports = function delayed(amount, fn) { + if (!fn) { + fn = amount + amount = 0 + } + return function() { + var self = this + var args = arguments + setTimeout(function() { fn.apply(self, args) }, amount) + } +} diff --git a/homework8/project_express/node_modules/std/each.js b/homework8/project_express/node_modules/std/each.js new file mode 100644 index 0000000..5c27d32 --- /dev/null +++ b/homework8/project_express/node_modules/std/each.js @@ -0,0 +1,20 @@ +var isArray = require('./isArray'), + isArguments = require('./isArguments') + +module.exports = function(items, ctx, fn) { + if (!items) { return } + if (!fn) { + fn = ctx + ctx = this + } + if (isArray(items) || isArguments(items)) { + for (var i=0; i < items.length; i++) { + fn.call(ctx, items[i], i) + } + } else { + for (var key in items) { + if (!items.hasOwnProperty(key)) { continue } + fn.call(ctx, items[key], key) + } + } +} diff --git a/homework8/project_express/node_modules/std/extend.js b/homework8/project_express/node_modules/std/extend.js new file mode 100644 index 0000000..f65441b --- /dev/null +++ b/homework8/project_express/node_modules/std/extend.js @@ -0,0 +1,40 @@ +/* + Example usage: + + var A = Class(function() { + + var defaults = { + foo: 'cat', + bar: 'dum' + } + + this.init = function(opts) { + opts = std.extend(opts, defaults) + this._foo = opts.foo + this._bar = opts.bar + } + + this.getFoo = function() { + return this._foo + } + + this.getBar = function() { + return this._bar + } + }) + + var a = new A({ bar:'sim' }) + a.getFoo() == 'cat' + a.getBar() == 'sim' +*/ + +var copy = require('./copy') + +module.exports = function extend(target, extendWith) { + target = copy(target) + for (var key in extendWith) { + if (typeof target[key] != 'undefined') { continue } + target[key] = extendWith[key] + } + return target +} diff --git a/homework8/project_express/node_modules/std/filter.js b/homework8/project_express/node_modules/std/filter.js new file mode 100644 index 0000000..2517944 --- /dev/null +++ b/homework8/project_express/node_modules/std/filter.js @@ -0,0 +1,38 @@ +/* + Example usage: + filter([1,2,0,'',false,null,undefined]) // -> [1,2,0,'',false] + filter([1,2,3], this, function(val, index) { val == 1 }) // -> [1] +*/ +var each = require('./each') +var isArray = require('./isArray') + +module.exports = function filter(arr, ctx, fn) { + if (arguments.length == 2) { + fn = ctx + ctx = this + } + if (!fn) { + fn = falseOrTruthy + } + + var result + if (isArray(arr)) { + result = [] + each(arr, function(value, index) { + if (!fn.call(ctx, value, index)) { return } + result.push(value) + }) + } else { + result = {} + each(arr, function(value, key) { + if (!fn.call(ctx, value, key)) { return } + result[key] = value + }) + } + return result +} + +function falseOrTruthy(arg) { + return !!arg || arg === false +} + diff --git a/homework8/project_express/node_modules/std/find.js b/homework8/project_express/node_modules/std/find.js new file mode 100644 index 0000000..b51d1ec --- /dev/null +++ b/homework8/project_express/node_modules/std/find.js @@ -0,0 +1,7 @@ +module.exports = function find(items, fn) { + if (!items) { return null } + for (var i=0; i argument.length) { + throw new Error('Warning: pack() Type ' + instruction + ': not enough characters in string'); + } + for (i = 0; i < quantifier; i += 2) { + // Always get per 2 bytes... + word = argument[i]; + if (((i + 1) >= quantifier) || typeof(argument[i + 1]) === 'undefined') { + word += '0'; + } else { + word += argument[i + 1]; + } + // The fastest way to reverse? + if (instruction === 'h') { + word = word[1] + word[0]; + } + result += String.fromCharCode(parseInt(word, 16)); + } + argumentPointer++; + break; + + case 'c': + // signed char + case 'C': + // unsigned char + // c and C is the same in pack + if (quantifier === '*') { + quantifier = arguments.length - argumentPointer; + } + if (quantifier > (arguments.length - argumentPointer)) { + throw new Error('Warning: pack() Type ' + instruction + ': too few arguments'); + } + + for (i = 0; i < quantifier; i++) { + result += String.fromCharCode(arguments[argumentPointer]); + argumentPointer++; + } + break; + + case 's': + // signed short (always 16 bit, machine byte order) + case 'S': + // unsigned short (always 16 bit, machine byte order) + case 'v': + // s and S is the same in pack + if (quantifier === '*') { + quantifier = arguments.length - argumentPointer; + } + if (quantifier > (arguments.length - argumentPointer)) { + throw new Error('Warning: pack() Type ' + instruction + ': too few arguments'); + } + + for (i = 0; i < quantifier; i++) { + result += String.fromCharCode(arguments[argumentPointer] & 0xFF); + result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF); + argumentPointer++; + } + break; + + case 'n': + // unsigned short (always 16 bit, big endian byte order) + if (quantifier === '*') { + quantifier = arguments.length - argumentPointer; + } + if (quantifier > (arguments.length - argumentPointer)) { + throw new Error('Warning: pack() Type ' + instruction + ': too few arguments'); + } + + for (i = 0; i < quantifier; i++) { + result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF); + result += String.fromCharCode(arguments[argumentPointer] & 0xFF); + argumentPointer++; + } + break; + + case 'i': + // signed integer (machine dependent size and byte order) + case 'I': + // unsigned integer (machine dependent size and byte order) + case 'l': + // signed long (always 32 bit, machine byte order) + case 'L': + // unsigned long (always 32 bit, machine byte order) + case 'V': + // unsigned long (always 32 bit, little endian byte order) + if (quantifier === '*') { + quantifier = arguments.length - argumentPointer; + } + if (quantifier > (arguments.length - argumentPointer)) { + throw new Error('Warning: pack() Type ' + instruction + ': too few arguments'); + } + + for (i = 0; i < quantifier; i++) { + result += String.fromCharCode(arguments[argumentPointer] & 0xFF); + result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF); + result += String.fromCharCode(arguments[argumentPointer] >> 16 & 0xFF); + result += String.fromCharCode(arguments[argumentPointer] >> 24 & 0xFF); + argumentPointer++; + } + + break; + case 'N': + // unsigned long (always 32 bit, big endian byte order) + if (quantifier === '*') { + quantifier = arguments.length - argumentPointer; + } + if (quantifier > (arguments.length - argumentPointer)) { + throw new Error('Warning: pack() Type ' + instruction + ': too few arguments'); + } + + for (i = 0; i < quantifier; i++) { + result += String.fromCharCode(arguments[argumentPointer] >> 24 & 0xFF); + result += String.fromCharCode(arguments[argumentPointer] >> 16 & 0xFF); + result += String.fromCharCode(arguments[argumentPointer] >> 8 & 0xFF); + result += String.fromCharCode(arguments[argumentPointer] & 0xFF); + argumentPointer++; + } + break; + + case 'f': + // float (machine dependent size and representation) + case 'd': + // double (machine dependent size and representation) + // version based on IEEE754 + precisionBits = 23; + exponentBits = 8; + if (instruction === 'd') { + precisionBits = 52; + exponentBits = 11; + } + + if (quantifier === '*') { + quantifier = arguments.length - argumentPointer; + } + if (quantifier > (arguments.length - argumentPointer)) { + throw new Error('Warning: pack() Type ' + instruction + ': too few arguments'); + } + for (i = 0; i < quantifier; i++) { + argument = arguments[argumentPointer]; + bias = Math.pow(2, exponentBits - 1) - 1; + minExp = -bias + 1; + maxExp = bias; + minUnnormExp = minExp - precisionBits; + status = isNaN(n = parseFloat(argument)) || n === -Infinity || n === +Infinity ? n : 0; + exp = 0; + len = 2 * bias + 1 + precisionBits + 3; + bin = new Array(len); + signal = (n = status !== 0 ? 0 : n) < 0; + n = Math.abs(n); + intPart = Math.floor(n); + floatPart = n - intPart; + + for (k = len; k;) { + bin[--k] = 0; + } + for (k = bias + 2; intPart && k;) { + bin[--k] = intPart % 2; + intPart = Math.floor(intPart / 2); + } + for (k = bias + 1; floatPart > 0 && k; --floatPart) { + (bin[++k] = ((floatPart *= 2) >= 1) - 0); + } + for (k = -1; ++k < len && !bin[k];) {} + + if (bin[(lastBit = precisionBits - 1 + (k = (exp = bias + 1 - k) >= minExp && exp <= maxExp ? k + 1 : bias + 1 - (exp = minExp - 1))) + 1]) { + if (!(rounded = bin[lastBit])) { + for (j = lastBit + 2; !rounded && j < len; rounded = bin[j++]) {} + } + for (j = lastBit + 1; rounded && --j >= 0; + (bin[j] = !bin[j] - 0) && (rounded = 0)) {} + } + + for (k = k - 2 < 0 ? -1 : k - 3; ++k < len && !bin[k];) {} + + if ((exp = bias + 1 - k) >= minExp && exp <= maxExp) { + ++k; + } else { + if (exp < minExp) { + if (exp !== bias + 1 - len && exp < minUnnormExp) { /*"encodeFloat::float underflow" */ + } + k = bias + 1 - (exp = minExp - 1); + } + } + + if (intPart || status !== 0) { + exp = maxExp + 1; + k = bias + 2; + if (status === -Infinity) { + signal = 1; + } else if (isNaN(status)) { + bin[k] = 1; + } + } + + n = Math.abs(exp + bias); + tmpResult = ''; + + for (j = exponentBits + 1; --j;) { + tmpResult = (n % 2) + tmpResult; + n = n >>= 1; + } + + n = 0; + j = 0; + k = (tmpResult = (signal ? '1' : '0') + tmpResult + bin.slice(k, k + precisionBits).join('')).length; + r = []; + + for (; k;) { + n += (1 << j) * tmpResult.charAt(--k); + if (j === 7) { + r[r.length] = String.fromCharCode(n); + n = 0; + } + j = (j + 1) % 8; + } + + r[r.length] = n ? String.fromCharCode(n) : ''; + result += r.join(''); + argumentPointer++; + } + break; + + case 'x': + // NUL byte + if (quantifier === '*') { + throw new Error('Warning: pack(): Type x: \'*\' ignored'); + } + for (i = 0; i < quantifier; i++) { + result += String.fromCharCode(0); + } + break; + + case 'X': + // Back up one byte + if (quantifier === '*') { + throw new Error('Warning: pack(): Type X: \'*\' ignored'); + } + for (i = 0; i < quantifier; i++) { + if (result.length === 0) { + throw new Error('Warning: pack(): Type X:' + ' outside of string'); + } else { + result = result.substring(0, result.length - 1); + } + } + break; + + case '@': + // NUL-fill to absolute position + if (quantifier === '*') { + throw new Error('Warning: pack(): Type X: \'*\' ignored'); + } + if (quantifier > result.length) { + extraNullCount = quantifier - result.length; + for (i = 0; i < extraNullCount; i++) { + result += String.fromCharCode(0); + } + } + if (quantifier < result.length) { + result = result.substring(0, quantifier); + } + break; + + default: + throw new Error('Warning: pack() Type ' + instruction + ': unknown format code'); + } + } + if (argumentPointer < arguments.length) { + throw new Error('Warning: pack(): ' + (arguments.length - argumentPointer) + ' arguments unused'); + } + + return result; +} diff --git a/homework8/project_express/node_modules/std/package.json b/homework8/project_express/node_modules/std/package.json new file mode 100644 index 0000000..446cdff --- /dev/null +++ b/homework8/project_express/node_modules/std/package.json @@ -0,0 +1,17 @@ +{ + "name": "std", + "description": "javascript standard library", + "version": "0.1.40", + "repository": { + "type": "git", + "url": "git://github.com/marcuswestin/std.js.git" + }, + "author": "@marcuswestin", + "contributors": ["@kaleb"], + "directories": { + "lib": "lib" + }, + "engines": { + "node": "*" + } +} diff --git a/homework8/project_express/node_modules/std/parallel.js b/homework8/project_express/node_modules/std/parallel.js new file mode 100644 index 0000000..4bbfd67 --- /dev/null +++ b/homework8/project_express/node_modules/std/parallel.js @@ -0,0 +1,17 @@ +var asyncMap = require('std/asyncMap') +var slice = require('std/slice') + +module.exports = function parallel(/* fn1, fn2, ..., finishFn */) { + var parallelFunctions = slice(arguments) + var finish = parallelFunctions.pop() + asyncMap(parallelFunctions, { + parallel:parallelFunctions.length, + iterate:function(parallelFn, done) { + parallelFn(done) + }, + finish:function(err, mapResults) { + if (err) { return finish(err) } + finish.apply(this, [null].concat(mapResults)) + } + }) +} diff --git a/homework8/project_express/node_modules/std/popup.js b/homework8/project_express/node_modules/std/popup.js new file mode 100644 index 0000000..13eaf00 --- /dev/null +++ b/homework8/project_express/node_modules/std/popup.js @@ -0,0 +1,26 @@ +var extend = require('./extend'), + map = require('./map') + +module.exports = function(url, winID, opts) { + opts = extend(opts, module.exports.defaults) + if (!opts['left']) { opts['left'] = Math.round((screen.width - opts['width']) / 2) } + if (!opts['top']) { opts['top'] = Math.round((screen.height - opts['height']) / 2) } + + var popupStr = map(opts, function(val, key) { return key+'='+val }).join(',') + + return window.open(url, winID, popupStr) +} + +module.exports.defaults = { + 'width': 600, + 'height': 400, + 'left': null, + 'top': null, + 'directories': 0, + 'location': 1, + 'menubar': 0, + 'resizable': 0, + 'scrollbars': 1, + 'titlebar': 0, + 'toolbar': 0 +} diff --git a/homework8/project_express/node_modules/std/proto.js b/homework8/project_express/node_modules/std/proto.js new file mode 100644 index 0000000..132750a --- /dev/null +++ b/homework8/project_express/node_modules/std/proto.js @@ -0,0 +1,39 @@ +/* + // Usage: proto(prototypeObj, intantiatingFn, properties) + + var base = { + say:function(arg) { alert(arg) } + } + + var person = proto(base, + function(name) { + this.name = name + }, { + greet:function(other) { + this.say("hello "+other.name+", I'm "+this.name) + } + } + ) + + var marcus = person("marcus"), + john = person("john") + + marcus.greet(john) +*/ + +var create = require('./create') + +var proto = module.exports = function proto(prototypeObject, instantiationFunction, propertiesToAdd) { + // F is the function that is required in order to implement JS prototypical inheritence + function F(args) { + // When a new object is created, call the instantiation function + return instantiationFunction.apply(this, args) + } + // The prototype object itself points to the passed-in prototypeObject, + // but also has all the properties enumerated in propertiesToAdd + F.prototype = prototypeObject ? create(prototypeObject, propertiesToAdd) : propertiesToAdd + + return function() { + return new F(arguments) + } +} diff --git a/homework8/project_express/node_modules/std/rand.js b/homework8/project_express/node_modules/std/rand.js new file mode 100644 index 0000000..1add156 --- /dev/null +++ b/homework8/project_express/node_modules/std/rand.js @@ -0,0 +1,3 @@ +module.exports = function rand(floor, ceil) { + return Math.floor(Math.random() * (ceil - floor + 1)) + floor +} \ No newline at end of file diff --git a/homework8/project_express/node_modules/std/recall.js b/homework8/project_express/node_modules/std/recall.js new file mode 100644 index 0000000..6238023 --- /dev/null +++ b/homework8/project_express/node_modules/std/recall.js @@ -0,0 +1,4 @@ +module.exports = function recall(context, args) { + var fn = args.callee + return function() { return fn.apply(context, args); } +} diff --git a/homework8/project_express/node_modules/std/remove.js b/homework8/project_express/node_modules/std/remove.js new file mode 100644 index 0000000..19e251c --- /dev/null +++ b/homework8/project_express/node_modules/std/remove.js @@ -0,0 +1,8 @@ +module.exports = function remove(arr, item) { + if (!arr) { return } + for (var i=0; i 0)) { // (undefined < 0) == false, but (!(undefined > 0)) == true + return Math.round(value) + } + var granularity = Math.pow(10, decimalPoints) + return Math.round(value * granularity) / granularity +} diff --git a/homework8/project_express/node_modules/std/router.js b/homework8/project_express/node_modules/std/router.js new file mode 100644 index 0000000..278a99c --- /dev/null +++ b/homework8/project_express/node_modules/std/router.js @@ -0,0 +1,71 @@ +var create = require('./create'), + options = require('./options'), + parseUrl = require('./url').parse + +module.exports = function(opts) { + opts = options(opts, { prefix:'/', default:'/' }) + opts.prefix = new RegExp('^'+opts.prefix) + return create(router, { + routes:{}, + errorHandlers:[], + opts:opts + }) +} + +var router = { + add:function(routeName, handler) { + var route = this.routes + var parts = routeName.split('/') + if (parts[0] != '') { throw new Error('Route much start with "/": '+ routeName) } + parts.shift() + for (var i=0; i steps[i]) { continue } + var result = _getStepResult(millisecondsAgo, steps, i) + if (yield) { + yield(result.payload) + if (result.smallestGranularity) { + var timeoutIn = Math.min(result.smallestGranularity - (millisecondsAgo % result.smallestGranularity), MAX_TIMEOUT_VALUE) + setTimeout(curry(stepFn, unbasedTimestamp, yield), timeoutIn * base) + } + } + return result.payload + } + return _getStepResult(millisecondsAgo, steps, i - 3).payload // the last one + } + return stepFn + } + + function _getStepResult(millisecondsAgo, steps, i) { + var stepSize = steps[i] + var stepPayload = steps[i+1] + var stepGranularities = steps[i+2] + var smallestGranularity = stepSize + var untakenTime = millisecondsAgo + each(stepGranularities, function(granularity) { + var granAmount = Math.floor(untakenTime / granularity) + untakenTime -= granAmount * granularity + stepPayload = stepPayload.replace('%N', granAmount) + if (granularity < smallestGranularity) { + smallestGranularity = granularity + } + }) + return { payload:stepPayload, smallestGranularity:smallestGranularity } + } + + return time +} diff --git a/homework8/project_express/node_modules/std/trim.js b/homework8/project_express/node_modules/std/trim.js new file mode 100644 index 0000000..d0458cf --- /dev/null +++ b/homework8/project_express/node_modules/std/trim.js @@ -0,0 +1,4 @@ +// Thanks goog! http://code.google.com/p/closure-library/source/browse/trunk/closure/goog/string/string.js?r=2 +module.exports = function(str) { + return str ? str.replace(/^[\s\xa0]+|[\s\xa0]+$/g, '') : '' +} diff --git a/homework8/project_express/node_modules/std/unique.js b/homework8/project_express/node_modules/std/unique.js new file mode 100644 index 0000000..936d603 --- /dev/null +++ b/homework8/project_express/node_modules/std/unique.js @@ -0,0 +1,22 @@ +var identity = function(item) { return item } +var itemId = function(item) { return item.id } + +/* + * Filters a list to unique items + */ +module.exports = function(list, getId) { + if (!list || !list.length) { return [] } + if (!getId) { + getId = (list[0].id ? itemId : identity) + } + var seen = {} + var result = [] + for (var i=0; i> 3) - 1; + lastByte = byteArray.length + (-(start + length) >> 3); + diff = curByte - lastByte; + sum = ( + (byteArray[ curByte ] >> offsetRight) & + ((1 << (diff ? 8 - offsetRight : length)) - 1) + ) + ( + diff && (offsetLeft = (start + length) % 8) ? + (byteArray[ lastByte++ ] & ((1 << offsetLeft) - 1)) << + (diff-- << 3) - offsetRight : + 0 + ); + + for(; diff;) { + sum += shl(byteArray[ lastByte++ ], (diff-- << 3) - offsetRight); + } + return sum; + }; + + while (formatPointer < format.length) { + instruction = format[formatPointer]; + + // Start reading 'quantifier' + quantifier = ''; + formatPointer++; + while ((formatPointer < format.length) && + (format[formatPointer].match(/[\d\*]/) !== null)) { + quantifier += format[formatPointer]; + formatPointer++; + } + if (quantifier === '') { + quantifier = '1'; + } + + + // Start reading label + label = ''; + while ((formatPointer < format.length) && + (format[formatPointer] !== '/')) { + label += format[formatPointer]; + formatPointer++; + } + if (format[formatPointer] === '/') { + formatPointer++; + } + + // Process given instruction + switch (instruction) { + case 'a': // NUL-padded string + case 'A': // SPACE-padded string + if (quantifier === '*') { + quantifier = data.length - dataPointer; + } else { + quantifier = parseInt(quantifier, 10); + } + currentData = data.substr(dataPointer, quantifier); + dataPointer += quantifier; + + if (instruction === 'a') { + currentResult = currentData.replace(/\0+$/, ''); + } else { + currentResult = currentData.replace(/ +$/, ''); + } + result[label] = currentResult; + break; + + case 'h': // Hex string, low nibble first + case 'H': // Hex string, high nibble first + if (quantifier === '*') { + quantifier = data.length - dataPointer; + } else { + quantifier = parseInt(quantifier, 10); + } + currentData = data.substr(dataPointer, quantifier); + dataPointer += quantifier; + + if (quantifier>currentData.length) { + throw new Error('Warning: unpack(): Type ' + instruction + + ': not enough input, need ' + quantifier); + } + + currentResult = ''; + for(i=0;i= 128)) { + currentResult -= 256; + } + result[label+(quantifier>1? + (i+1): + '')] = currentResult; + } + break; + + case 'S': // unsigned short (always 16 bit, machine byte order) + case 's': // signed short (always 16 bit, machine byte order) + case 'v': // unsigned short (always 16 bit, little endian byte order) + if (quantifier === '*') { + quantifier = (data.length - dataPointer) / 2; + } else { + quantifier = parseInt(quantifier, 10); + } + + currentData = data.substr(dataPointer, quantifier * 2); + dataPointer += quantifier * 2; + + for (i=0;i= 32768)) { + currentResult -= 65536; + } + result[label+(quantifier>1? + ((i/2)+1): + '')] = currentResult; + } + break; + + case 'n': // unsigned short (always 16 bit, big endian byte order) + if (quantifier === '*') { + quantifier = (data.length - dataPointer) / 2; + } else { + quantifier = parseInt(quantifier, 10); + } + + currentData = data.substr(dataPointer, quantifier * 2); + dataPointer += quantifier * 2; + + for (i=0;i1? + ((i/2)+1): + '')] = currentResult; + } + break; + + case 'i': // signed integer (machine dependent size and byte order) + case 'I': // unsigned integer (machine dependent size & byte order) + case 'l': // signed long (always 32 bit, machine byte order) + case 'L': // unsigned long (always 32 bit, machine byte order) + case 'V': // unsigned long (always 32 bit, little endian byte order) + if (quantifier === '*') { + quantifier = (data.length - dataPointer) / 4; + } else { + quantifier = parseInt(quantifier, 10); + } + + currentData = data.substr(dataPointer, quantifier * 4); + dataPointer += quantifier * 4; + + for (i=0;i1? + ((i/4)+1): + '')] = currentResult; + } + + break; + + case 'N': // unsigned long (always 32 bit, little endian byte order) + if (quantifier === '*') { + quantifier = (data.length - dataPointer) / 4; + } else { + quantifier = parseInt(quantifier, 10); + } + + currentData = data.substr(dataPointer, quantifier * 4); + dataPointer += quantifier * 4; + + for (i=0;i1? + ((i/4)+1): + '')] = currentResult; + } + + break; + + case 'f': + case 'd': + exponentBits = 8; + dataByteLength = 4; + if (instruction === 'd') { + exponentBits = 11; + dataByteLength = 8; + } + + if (quantifier === '*') { + quantifier = (data.length - dataPointer) / dataByteLength; + } else { + quantifier = parseInt(quantifier, 10); + } + + currentData = data.substr(dataPointer, + quantifier * dataByteLength); + dataPointer += quantifier * dataByteLength; + + for (i=0;i= 0 ; --j) { + b.push(data.charCodeAt(j)); + } + + precisionBits = (instruction === 'f')?23:52; + + bias = Math.pow(2, exponentBits - 1) - 1; + signal = readBits(precisionBits + exponentBits, 1, b); + exponent = readBits(precisionBits, exponentBits, b); + significand = 0; + divisor = 2; + curByte = b.length + (-precisionBits >> 3) - 1; + startBit = 0; + + do { + byteValue = b[ ++curByte ]; + startBit = precisionBits % 8 || 8; + mask = 1 << startBit; + for(; (mask >>= 1);) { + if (byteValue & mask) { + significand += 1 / divisor; + } + divisor *= 2; + } + } while ((precisionBits -= startBit)); + + if (exponent === (bias << 1) + 1) { + if (significand) { + currentResult = NaN; + } else { + if (signal) { + currentResult = -Infinity; + } else { + currentResult = +Infinity; + } + } + } else { + if ((1 + signal * -2) * (exponent || significand)) { + if (!exponent) { + currentResult = Math.pow(2, -bias + 1) * + significand; + } else { + currentResult = Math.pow(2, + exponent - bias) * + (1 + significand); + } + } else { + currentResult = 0; + } + } + result[label+(quantifier>1? + ((i/4)+1): + '')] = currentResult; + } + + break; + + case 'x': // NUL byte + case 'X': // Back up one byte + case '@': // NUL byte + if (quantifier === '*') { + quantifier = data.length - dataPointer; + } else { + quantifier = parseInt(quantifier, 10); + } + + if (quantifier > 0) { + if (instruction === 'X') { + dataPointer -= quantifier; + } else { + if (instruction === 'x') { + dataPointer += quantifier; + } else { + dataPointer = quantifier; + } + } + } + break; + + default: + throw new Error('Warning: unpack() Type ' + instruction + + ': unknown format code'); + } + } + return result; +} diff --git a/homework8/project_express/node_modules/std/url.js b/homework8/project_express/node_modules/std/url.js new file mode 100644 index 0000000..881e43c --- /dev/null +++ b/homework8/project_express/node_modules/std/url.js @@ -0,0 +1,112 @@ +var Class = require('./Class') +var map = require('./map') +var isArray = require('std/isArray') + +var URL = Class(function() { + + this._extractionRegex = new RegExp([ + '^', // start at the beginning of the string + '((\\w+:)?//)?', // match a possible protocol, like http://, ftp://, or // for a relative url + '(\\w[\\w\\.\\-]+)?', // match a possible domain + '(:\\d+)?', // match a possible port + '(\\/[^\\?#]+)?', // match a possible path + '(\\?[^#]+)?', // match possible GET parameters + '(#.*)?' // match the rest of the URL as the hash + ].join(''), 'i') + + this.init = function(url) { + var match = (url || '').toString().match(this._extractionRegex) || [] + this.protocol = match[2] || '' + this.hostname = match[3] || '' + this.port = (match[4] || '').substr(1) + this.host = (this.hostname ? this.hostname : '') + (this.port ? ':' + this.port : '') + this.pathname = match[5] || '' + this.search = (match[6]||'').substr(1) + this.hash = (match[7]||'').substr(1) + } + + this.setProtocol = function(protocol) { + this.protocol = protocol + return this + } + + this.toString = function() { + return [ + this.protocol || '//', + this.host, + this.pathname, + this.getSearch(), + this.getHash() + ].join('') + } + + this.toJSON = this.toString + + this.getTopLevelDomain = function() { + if (!this.host) { return '' } + var parts = this.host.split('.') + return parts.slice(parts.length - 2).join('.') + } + + this.getSearchParams = function() { + if (this._searchParams) { return this._searchParams } + return this._searchParams = url.query.parse(this.search) || {} + } + + this.getHashParams = function() { + if (this._hashParams) { return this._hashParams } + return this._hashParams = url.query.parse(this.hash) || {} + } + + this.addToSearch = function(key, val) { this.getSearchParams()[key] = val; return this } + this.addToHash = function(key, val) { this.getHashParams()[key] = val; return this } + this.removeFromSearch = function(key) { delete this.getSearchParams()[key]; return this } + this.removeFromHash = function(key) { delete this.getHashParams()[key]; return this } + + this.getSearch = function() { + return ( + this._searchParams ? '?' + url.query.string(this._searchParams) + : this.search ? '?' + this.search + : '') + } + + this.getHash = function() { + return ( + this._hashParams ? '#' + url.query.string(this._hashParams) + : this.hash ? '?' + this.hash + : '') + } + + this.getSearchParam = function(key) { return this.getSearchParams()[key] } + this.getHashParam = function(key) { return this.getHashParams()[key] } +}) + +var url = module.exports = function url(url) { return new URL(url) } +url.parse = url + +url.query = { + parse:function(paramString) { + var parts = paramString.split('&'), + params = {} + for (var i=0; i 127 && c1 < 2048) { + enc = String.fromCharCode((c1 >> 6) | 192) + String.fromCharCode((c1 & 63) | 128); + } else { + enc = String.fromCharCode((c1 >> 12) | 224) + String.fromCharCode(((c1 >> 6) & 63) | 128) + String.fromCharCode((c1 & 63) | 128); + } + if (enc !== null) { + if (end > start) { + utftext += string.slice(start, end); + } + utftext += enc; + start = end = n + 1; + } + } + + if (end > start) { + utftext += string.slice(start, stringl); + } + + return utftext; +} diff --git a/homework8/project_express/node_modules/std/waitFor.js b/homework8/project_express/node_modules/std/waitFor.js new file mode 100644 index 0000000..df8a1b2 --- /dev/null +++ b/homework8/project_express/node_modules/std/waitFor.js @@ -0,0 +1,13 @@ +module.exports = function waitFor(num, callback) { + var seenError + return function(err, res) { + if (num == 0) { return log.warn("waitFor was called more than the expected number of times") } + if (seenError) { return } + if (err) { + seenError = true + return callback(err) + } + num -= 1 + if (num == 0) { callback(null) } + } +} diff --git a/homework8/project_express/node_modules/std/xhr.js b/homework8/project_express/node_modules/std/xhr.js new file mode 100644 index 0000000..21f2aec --- /dev/null +++ b/homework8/project_express/node_modules/std/xhr.js @@ -0,0 +1,89 @@ +var curry = require('./curry'), + map = require('./map'), + each = require('./each'), + json = require('./json') + +module.exports = { + request: request, + get: curry(request, 'get'), + post: curry(request, 'post'), + jsonGet: curry(sendJSON, 'get'), + jsonPost: curry(sendJSON, 'post') +} + +var XHR = window.XMLHttpRequest || function() { return new ActiveXObject("Msxml2.XMLHTTP"); } + +var onBeforeUnloadFired = false +function onBeforeUnload() { + onBeforeUnloadFired = true + setTimeout(function(){ onBeforeUnloadFired = false }, 100) +} + +if (window.addEventListener) { window.addEventListener('beforeunload', onBeforeUnload, false) } +else { window.attachEvent('onbeforeunload', onBeforeUnload) } + +function request(method, url, params, callback, headers, opts) { + var xhr = new XHR() + method = method.toUpperCase() + headers = headers || {} + opts = opts || {} + xhr.onreadystatechange = function() { + var err, result + try { + if (xhr.readyState != 4) { return } + if (onBeforeUnloadFired) { return } + var text = xhr.responseText, + isJson = xhr.getResponseHeader('Content-Type') == 'application/json' + if (xhr.status == 200 || xhr.status == 204) { + result = isJson ? json.parse(text) : text + } else { + try { err = isJson ? json.parse(text) : new Error(text) } + catch (e) { err = new Error(text) } + } + } catch(e) { + err = e + } + if (err || typeof result != undefined) { + _abortXHR(xhr) + callback(err, result) + } + } + + var uriEncode = (opts.encode === false + ? function(params) { return map(params, function(val, key) { return key+'='+val }).join('&') } + : function(params) { return map(params, function(val, key) { return encodeURIComponent(key)+'='+encodeURIComponent(val) }).join('&') }) + + var data = '' + if (method == 'GET') { + var queryParams = uriEncode(params) + url += (url.indexOf('?') == -1 && queryParams ? '?' : '') + queryParams + } else if (method == 'POST') { + var contentType = headers['Content-Type'] + if (!contentType) { + contentType = headers['Content-Type'] = 'application/x-www-form-urlencoded' + } + if (contentType == 'application/x-www-form-urlencoded') { + data = uriEncode(params) + } else if (contentType == 'application/json') { + data = json.stringify(params) + } + } + xhr.open(method, url, true) + each(headers, function(val, key) { xhr.setRequestHeader(key, val) }) + xhr.send(data) +} + +function sendJSON(method, url, params, callback) { + return request(method, url, params, callback, { 'Content-Type':'application/json' }) +} + +function _abortXHR(xhr) { + try { + if('onload' in xhr) { + xhr.onload = xhr.onerror = xhr.ontimeout = null; + } else if('onreadystatechange' in xhr) { + xhr.onreadystatechange = null; + } + if(xhr.abort) { xhr.abort(); } + } catch(e) {} +} diff --git a/homework8/project_express/node_modules/supports-color/browser.js b/homework8/project_express/node_modules/supports-color/browser.js new file mode 100644 index 0000000..62afa3a --- /dev/null +++ b/homework8/project_express/node_modules/supports-color/browser.js @@ -0,0 +1,5 @@ +'use strict'; +module.exports = { + stdout: false, + stderr: false +}; diff --git a/homework8/project_express/node_modules/supports-color/index.js b/homework8/project_express/node_modules/supports-color/index.js new file mode 100644 index 0000000..1704131 --- /dev/null +++ b/homework8/project_express/node_modules/supports-color/index.js @@ -0,0 +1,131 @@ +'use strict'; +const os = require('os'); +const hasFlag = require('has-flag'); + +const env = process.env; + +let forceColor; +if (hasFlag('no-color') || + hasFlag('no-colors') || + hasFlag('color=false')) { + forceColor = false; +} else if (hasFlag('color') || + hasFlag('colors') || + hasFlag('color=true') || + hasFlag('color=always')) { + forceColor = true; +} +if ('FORCE_COLOR' in env) { + forceColor = env.FORCE_COLOR.length === 0 || parseInt(env.FORCE_COLOR, 10) !== 0; +} + +function translateLevel(level) { + if (level === 0) { + return false; + } + + return { + level, + hasBasic: true, + has256: level >= 2, + has16m: level >= 3 + }; +} + +function supportsColor(stream) { + if (forceColor === false) { + return 0; + } + + if (hasFlag('color=16m') || + hasFlag('color=full') || + hasFlag('color=truecolor')) { + return 3; + } + + if (hasFlag('color=256')) { + return 2; + } + + if (stream && !stream.isTTY && forceColor !== true) { + return 0; + } + + const min = forceColor ? 1 : 0; + + if (process.platform === 'win32') { + // Node.js 7.5.0 is the first version of Node.js to include a patch to + // libuv that enables 256 color output on Windows. Anything earlier and it + // won't work. However, here we target Node.js 8 at minimum as it is an LTS + // release, and Node.js 7 is not. Windows 10 build 10586 is the first Windows + // release that supports 256 colors. Windows 10 build 14931 is the first release + // that supports 16m/TrueColor. + const osRelease = os.release().split('.'); + if ( + Number(process.versions.node.split('.')[0]) >= 8 && + Number(osRelease[0]) >= 10 && + Number(osRelease[2]) >= 10586 + ) { + return Number(osRelease[2]) >= 14931 ? 3 : 2; + } + + return 1; + } + + if ('CI' in env) { + if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(sign => sign in env) || env.CI_NAME === 'codeship') { + return 1; + } + + return min; + } + + if ('TEAMCITY_VERSION' in env) { + return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0; + } + + if (env.COLORTERM === 'truecolor') { + return 3; + } + + if ('TERM_PROGRAM' in env) { + const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10); + + switch (env.TERM_PROGRAM) { + case 'iTerm.app': + return version >= 3 ? 3 : 2; + case 'Apple_Terminal': + return 2; + // No default + } + } + + if (/-256(color)?$/i.test(env.TERM)) { + return 2; + } + + if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) { + return 1; + } + + if ('COLORTERM' in env) { + return 1; + } + + if (env.TERM === 'dumb') { + return min; + } + + return min; +} + +function getSupportLevel(stream) { + const level = supportsColor(stream); + return translateLevel(level); +} + +module.exports = { + supportsColor: getSupportLevel, + stdout: getSupportLevel(process.stdout), + stderr: getSupportLevel(process.stderr) +}; diff --git a/homework8/project_express/node_modules/supports-color/license b/homework8/project_express/node_modules/supports-color/license new file mode 100644 index 0000000..e7af2f7 --- /dev/null +++ b/homework8/project_express/node_modules/supports-color/license @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) Sindre Sorhus (sindresorhus.com) + +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/homework8/project_express/node_modules/supports-color/package.json b/homework8/project_express/node_modules/supports-color/package.json new file mode 100644 index 0000000..ad199f5 --- /dev/null +++ b/homework8/project_express/node_modules/supports-color/package.json @@ -0,0 +1,53 @@ +{ + "name": "supports-color", + "version": "5.5.0", + "description": "Detect whether a terminal supports color", + "license": "MIT", + "repository": "chalk/supports-color", + "author": { + "name": "Sindre Sorhus", + "email": "sindresorhus@gmail.com", + "url": "sindresorhus.com" + }, + "engines": { + "node": ">=4" + }, + "scripts": { + "test": "xo && ava" + }, + "files": [ + "index.js", + "browser.js" + ], + "keywords": [ + "color", + "colour", + "colors", + "terminal", + "console", + "cli", + "ansi", + "styles", + "tty", + "rgb", + "256", + "shell", + "xterm", + "command-line", + "support", + "supports", + "capability", + "detect", + "truecolor", + "16m" + ], + "dependencies": { + "has-flag": "^3.0.0" + }, + "devDependencies": { + "ava": "^0.25.0", + "import-fresh": "^2.0.0", + "xo": "^0.20.0" + }, + "browser": "browser.js" +} diff --git a/homework8/project_express/node_modules/supports-color/readme.md b/homework8/project_express/node_modules/supports-color/readme.md new file mode 100644 index 0000000..f6e4019 --- /dev/null +++ b/homework8/project_express/node_modules/supports-color/readme.md @@ -0,0 +1,66 @@ +# supports-color [![Build Status](https://travis-ci.org/chalk/supports-color.svg?branch=master)](https://travis-ci.org/chalk/supports-color) + +> Detect whether a terminal supports color + + +## Install + +``` +$ npm install supports-color +``` + + +## Usage + +```js +const supportsColor = require('supports-color'); + +if (supportsColor.stdout) { + console.log('Terminal stdout supports color'); +} + +if (supportsColor.stdout.has256) { + console.log('Terminal stdout supports 256 colors'); +} + +if (supportsColor.stderr.has16m) { + console.log('Terminal stderr supports 16 million colors (truecolor)'); +} +``` + + +## API + +Returns an `Object` with a `stdout` and `stderr` property for testing either streams. Each property is an `Object`, or `false` if color is not supported. + +The `stdout`/`stderr` objects specifies a level of support for color through a `.level` property and a corresponding flag: + +- `.level = 1` and `.hasBasic = true`: Basic color support (16 colors) +- `.level = 2` and `.has256 = true`: 256 color support +- `.level = 3` and `.has16m = true`: Truecolor support (16 million colors) + + +## Info + +It obeys the `--color` and `--no-color` CLI flags. + +Can be overridden by the user with the flags `--color` and `--no-color`. For situations where using `--color` is not possible, add the environment variable `FORCE_COLOR=1` to forcefully enable color or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks. + +Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively. + + +## Related + +- [supports-color-cli](https://github.com/chalk/supports-color-cli) - CLI for this module +- [chalk](https://github.com/chalk/chalk) - Terminal string styling done right + + +## Maintainers + +- [Sindre Sorhus](https://github.com/sindresorhus) +- [Josh Junon](https://github.com/qix-) + + +## License + +MIT diff --git a/homework8/project_express/node_modules/to-regex-range/LICENSE b/homework8/project_express/node_modules/to-regex-range/LICENSE new file mode 100644 index 0000000..7cccaf9 --- /dev/null +++ b/homework8/project_express/node_modules/to-regex-range/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015-present, Jon Schlinkert. + +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/homework8/project_express/node_modules/to-regex-range/README.md b/homework8/project_express/node_modules/to-regex-range/README.md new file mode 100644 index 0000000..38887da --- /dev/null +++ b/homework8/project_express/node_modules/to-regex-range/README.md @@ -0,0 +1,305 @@ +# to-regex-range [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=W8YFZ425KND68) [![NPM version](https://img.shields.io/npm/v/to-regex-range.svg?style=flat)](https://www.npmjs.com/package/to-regex-range) [![NPM monthly downloads](https://img.shields.io/npm/dm/to-regex-range.svg?style=flat)](https://npmjs.org/package/to-regex-range) [![NPM total downloads](https://img.shields.io/npm/dt/to-regex-range.svg?style=flat)](https://npmjs.org/package/to-regex-range) [![Linux Build Status](https://img.shields.io/travis/micromatch/to-regex-range.svg?style=flat&label=Travis)](https://travis-ci.org/micromatch/to-regex-range) + +> Pass two numbers, get a regex-compatible source string for matching ranges. Validated against more than 2.78 million test assertions. + +Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install --save to-regex-range +``` + +
+What does this do? + +
+ +This libary generates the `source` string to be passed to `new RegExp()` for matching a range of numbers. + +**Example** + +```js +const toRegexRange = require('to-regex-range'); +const regex = new RegExp(toRegexRange('15', '95')); +``` + +A string is returned so that you can do whatever you need with it before passing it to `new RegExp()` (like adding `^` or `$` boundaries, defining flags, or combining it another string). + +
+ +
+ +
+Why use this library? + +
+ +### Convenience + +Creating regular expressions for matching numbers gets deceptively complicated pretty fast. + +For example, let's say you need a validation regex for matching part of a user-id, postal code, social security number, tax id, etc: + +* regex for matching `1` => `/1/` (easy enough) +* regex for matching `1` through `5` => `/[1-5]/` (not bad...) +* regex for matching `1` or `5` => `/(1|5)/` (still easy...) +* regex for matching `1` through `50` => `/([1-9]|[1-4][0-9]|50)/` (uh-oh...) +* regex for matching `1` through `55` => `/([1-9]|[1-4][0-9]|5[0-5])/` (no prob, I can do this...) +* regex for matching `1` through `555` => `/([1-9]|[1-9][0-9]|[1-4][0-9]{2}|5[0-4][0-9]|55[0-5])/` (maybe not...) +* regex for matching `0001` through `5555` => `/(0{3}[1-9]|0{2}[1-9][0-9]|0[1-9][0-9]{2}|[1-4][0-9]{3}|5[0-4][0-9]{2}|55[0-4][0-9]|555[0-5])/` (okay, I get the point!) + +The numbers are contrived, but they're also really basic. In the real world you might need to generate a regex on-the-fly for validation. + +**Learn more** + +If you're interested in learning more about [character classes](http://www.regular-expressions.info/charclass.html) and other regex features, I personally have always found [regular-expressions.info](http://www.regular-expressions.info/charclass.html) to be pretty useful. + +### Heavily tested + +As of April 07, 2019, this library runs [>1m test assertions](./test/test.js) against generated regex-ranges to provide brute-force verification that results are correct. + +Tests run in ~280ms on my MacBook Pro, 2.5 GHz Intel Core i7. + +### Optimized + +Generated regular expressions are optimized: + +* duplicate sequences and character classes are reduced using quantifiers +* smart enough to use `?` conditionals when number(s) or range(s) can be positive or negative +* uses fragment caching to avoid processing the same exact string more than once + +
+ +
+ +## Usage + +Add this library to your javascript application with the following line of code + +```js +const toRegexRange = require('to-regex-range'); +``` + +The main export is a function that takes two integers: the `min` value and `max` value (formatted as strings or numbers). + +```js +const source = toRegexRange('15', '95'); +//=> 1[5-9]|[2-8][0-9]|9[0-5] + +const regex = new RegExp(`^${source}$`); +console.log(regex.test('14')); //=> false +console.log(regex.test('50')); //=> true +console.log(regex.test('94')); //=> true +console.log(regex.test('96')); //=> false +``` + +## Options + +### options.capture + +**Type**: `boolean` + +**Deafault**: `undefined` + +Wrap the returned value in parentheses when there is more than one regex condition. Useful when you're dynamically generating ranges. + +```js +console.log(toRegexRange('-10', '10')); +//=> -[1-9]|-?10|[0-9] + +console.log(toRegexRange('-10', '10', { capture: true })); +//=> (-[1-9]|-?10|[0-9]) +``` + +### options.shorthand + +**Type**: `boolean` + +**Deafault**: `undefined` + +Use the regex shorthand for `[0-9]`: + +```js +console.log(toRegexRange('0', '999999')); +//=> [0-9]|[1-9][0-9]{1,5} + +console.log(toRegexRange('0', '999999', { shorthand: true })); +//=> \d|[1-9]\d{1,5} +``` + +### options.relaxZeros + +**Type**: `boolean` + +**Default**: `true` + +This option relaxes matching for leading zeros when when ranges are zero-padded. + +```js +const source = toRegexRange('-0010', '0010'); +const regex = new RegExp(`^${source}$`); +console.log(regex.test('-10')); //=> true +console.log(regex.test('-010')); //=> true +console.log(regex.test('-0010')); //=> true +console.log(regex.test('10')); //=> true +console.log(regex.test('010')); //=> true +console.log(regex.test('0010')); //=> true +``` + +When `relaxZeros` is false, matching is strict: + +```js +const source = toRegexRange('-0010', '0010', { relaxZeros: false }); +const regex = new RegExp(`^${source}$`); +console.log(regex.test('-10')); //=> false +console.log(regex.test('-010')); //=> false +console.log(regex.test('-0010')); //=> true +console.log(regex.test('10')); //=> false +console.log(regex.test('010')); //=> false +console.log(regex.test('0010')); //=> true +``` + +## Examples + +| **Range** | **Result** | **Compile time** | +| --- | --- | --- | +| `toRegexRange(-10, 10)` | `-[1-9]\|-?10\|[0-9]` | _132μs_ | +| `toRegexRange(-100, -10)` | `-1[0-9]\|-[2-9][0-9]\|-100` | _50μs_ | +| `toRegexRange(-100, 100)` | `-[1-9]\|-?[1-9][0-9]\|-?100\|[0-9]` | _42μs_ | +| `toRegexRange(001, 100)` | `0{0,2}[1-9]\|0?[1-9][0-9]\|100` | _109μs_ | +| `toRegexRange(001, 555)` | `0{0,2}[1-9]\|0?[1-9][0-9]\|[1-4][0-9]{2}\|5[0-4][0-9]\|55[0-5]` | _51μs_ | +| `toRegexRange(0010, 1000)` | `0{0,2}1[0-9]\|0{0,2}[2-9][0-9]\|0?[1-9][0-9]{2}\|1000` | _31μs_ | +| `toRegexRange(1, 50)` | `[1-9]\|[1-4][0-9]\|50` | _24μs_ | +| `toRegexRange(1, 55)` | `[1-9]\|[1-4][0-9]\|5[0-5]` | _23μs_ | +| `toRegexRange(1, 555)` | `[1-9]\|[1-9][0-9]\|[1-4][0-9]{2}\|5[0-4][0-9]\|55[0-5]` | _30μs_ | +| `toRegexRange(1, 5555)` | `[1-9]\|[1-9][0-9]{1,2}\|[1-4][0-9]{3}\|5[0-4][0-9]{2}\|55[0-4][0-9]\|555[0-5]` | _43μs_ | +| `toRegexRange(111, 555)` | `11[1-9]\|1[2-9][0-9]\|[2-4][0-9]{2}\|5[0-4][0-9]\|55[0-5]` | _38μs_ | +| `toRegexRange(29, 51)` | `29\|[34][0-9]\|5[01]` | _24μs_ | +| `toRegexRange(31, 877)` | `3[1-9]\|[4-9][0-9]\|[1-7][0-9]{2}\|8[0-6][0-9]\|87[0-7]` | _32μs_ | +| `toRegexRange(5, 5)` | `5` | _8μs_ | +| `toRegexRange(5, 6)` | `5\|6` | _11μs_ | +| `toRegexRange(1, 2)` | `1\|2` | _6μs_ | +| `toRegexRange(1, 5)` | `[1-5]` | _15μs_ | +| `toRegexRange(1, 10)` | `[1-9]\|10` | _22μs_ | +| `toRegexRange(1, 100)` | `[1-9]\|[1-9][0-9]\|100` | _25μs_ | +| `toRegexRange(1, 1000)` | `[1-9]\|[1-9][0-9]{1,2}\|1000` | _31μs_ | +| `toRegexRange(1, 10000)` | `[1-9]\|[1-9][0-9]{1,3}\|10000` | _34μs_ | +| `toRegexRange(1, 100000)` | `[1-9]\|[1-9][0-9]{1,4}\|100000` | _36μs_ | +| `toRegexRange(1, 1000000)` | `[1-9]\|[1-9][0-9]{1,5}\|1000000` | _42μs_ | +| `toRegexRange(1, 10000000)` | `[1-9]\|[1-9][0-9]{1,6}\|10000000` | _42μs_ | + +## Heads up! + +**Order of arguments** + +When the `min` is larger than the `max`, values will be flipped to create a valid range: + +```js +toRegexRange('51', '29'); +``` + +Is effectively flipped to: + +```js +toRegexRange('29', '51'); +//=> 29|[3-4][0-9]|5[0-1] +``` + +**Steps / increments** + +This library does not support steps (increments). A pr to add support would be welcome. + +## History + +### v2.0.0 - 2017-04-21 + +**New features** + +Adds support for zero-padding! + +### v1.0.0 + +**Optimizations** + +Repeating ranges are now grouped using quantifiers. rocessing time is roughly the same, but the generated regex is much smaller, which should result in faster matching. + +## Attribution + +Inspired by the python library [range-regex](https://github.com/dimka665/range-regex). + +## About + +
+Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). + +
+ +
+Running Tests + +Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: + +```sh +$ npm install && npm test +``` + +
+ +
+Building docs + +_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ + +To generate the readme, run the following command: + +```sh +$ npm install -g verbose/verb#dev verb-generate-readme && verb +``` + +
+ +### Related projects + +You might also be interested in these projects: + +* [expand-range](https://www.npmjs.com/package/expand-range): Fast, bash-like range expansion. Expand a range of numbers or letters, uppercase or lowercase. Used… [more](https://github.com/jonschlinkert/expand-range) | [homepage](https://github.com/jonschlinkert/expand-range "Fast, bash-like range expansion. Expand a range of numbers or letters, uppercase or lowercase. Used by micromatch.") +* [fill-range](https://www.npmjs.com/package/fill-range): Fill in a range of numbers or letters, optionally passing an increment or `step` to… [more](https://github.com/jonschlinkert/fill-range) | [homepage](https://github.com/jonschlinkert/fill-range "Fill in a range of numbers or letters, optionally passing an increment or `step` to use, or create a regex-compatible range with `options.toRegex`") +* [micromatch](https://www.npmjs.com/package/micromatch): Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch. | [homepage](https://github.com/micromatch/micromatch "Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch.") +* [repeat-element](https://www.npmjs.com/package/repeat-element): Create an array by repeating the given value n times. | [homepage](https://github.com/jonschlinkert/repeat-element "Create an array by repeating the given value n times.") +* [repeat-string](https://www.npmjs.com/package/repeat-string): Repeat the given string n times. Fastest implementation for repeating a string. | [homepage](https://github.com/jonschlinkert/repeat-string "Repeat the given string n times. Fastest implementation for repeating a string.") + +### Contributors + +| **Commits** | **Contributor** | +| --- | --- | +| 63 | [jonschlinkert](https://github.com/jonschlinkert) | +| 3 | [doowb](https://github.com/doowb) | +| 2 | [realityking](https://github.com/realityking) | + +### Author + +**Jon Schlinkert** + +* [GitHub Profile](https://github.com/jonschlinkert) +* [Twitter Profile](https://twitter.com/jonschlinkert) +* [LinkedIn Profile](https://linkedin.com/in/jonschlinkert) + +Please consider supporting me on Patreon, or [start your own Patreon page](https://patreon.com/invite/bxpbvm)! + + + + + +### License + +Copyright © 2019, [Jon Schlinkert](https://github.com/jonschlinkert). +Released under the [MIT License](LICENSE). + +*** + +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.8.0, on April 07, 2019._ \ No newline at end of file diff --git a/homework8/project_express/node_modules/to-regex-range/index.js b/homework8/project_express/node_modules/to-regex-range/index.js new file mode 100644 index 0000000..77fbace --- /dev/null +++ b/homework8/project_express/node_modules/to-regex-range/index.js @@ -0,0 +1,288 @@ +/*! + * to-regex-range + * + * Copyright (c) 2015-present, Jon Schlinkert. + * Released under the MIT License. + */ + +'use strict'; + +const isNumber = require('is-number'); + +const toRegexRange = (min, max, options) => { + if (isNumber(min) === false) { + throw new TypeError('toRegexRange: expected the first argument to be a number'); + } + + if (max === void 0 || min === max) { + return String(min); + } + + if (isNumber(max) === false) { + throw new TypeError('toRegexRange: expected the second argument to be a number.'); + } + + let opts = { relaxZeros: true, ...options }; + if (typeof opts.strictZeros === 'boolean') { + opts.relaxZeros = opts.strictZeros === false; + } + + let relax = String(opts.relaxZeros); + let shorthand = String(opts.shorthand); + let capture = String(opts.capture); + let wrap = String(opts.wrap); + let cacheKey = min + ':' + max + '=' + relax + shorthand + capture + wrap; + + if (toRegexRange.cache.hasOwnProperty(cacheKey)) { + return toRegexRange.cache[cacheKey].result; + } + + let a = Math.min(min, max); + let b = Math.max(min, max); + + if (Math.abs(a - b) === 1) { + let result = min + '|' + max; + if (opts.capture) { + return `(${result})`; + } + if (opts.wrap === false) { + return result; + } + return `(?:${result})`; + } + + let isPadded = hasPadding(min) || hasPadding(max); + let state = { min, max, a, b }; + let positives = []; + let negatives = []; + + if (isPadded) { + state.isPadded = isPadded; + state.maxLen = String(state.max).length; + } + + if (a < 0) { + let newMin = b < 0 ? Math.abs(b) : 1; + negatives = splitToPatterns(newMin, Math.abs(a), state, opts); + a = state.a = 0; + } + + if (b >= 0) { + positives = splitToPatterns(a, b, state, opts); + } + + state.negatives = negatives; + state.positives = positives; + state.result = collatePatterns(negatives, positives, opts); + + if (opts.capture === true) { + state.result = `(${state.result})`; + } else if (opts.wrap !== false && (positives.length + negatives.length) > 1) { + state.result = `(?:${state.result})`; + } + + toRegexRange.cache[cacheKey] = state; + return state.result; +}; + +function collatePatterns(neg, pos, options) { + let onlyNegative = filterPatterns(neg, pos, '-', false, options) || []; + let onlyPositive = filterPatterns(pos, neg, '', false, options) || []; + let intersected = filterPatterns(neg, pos, '-?', true, options) || []; + let subpatterns = onlyNegative.concat(intersected).concat(onlyPositive); + return subpatterns.join('|'); +} + +function splitToRanges(min, max) { + let nines = 1; + let zeros = 1; + + let stop = countNines(min, nines); + let stops = new Set([max]); + + while (min <= stop && stop <= max) { + stops.add(stop); + nines += 1; + stop = countNines(min, nines); + } + + stop = countZeros(max + 1, zeros) - 1; + + while (min < stop && stop <= max) { + stops.add(stop); + zeros += 1; + stop = countZeros(max + 1, zeros) - 1; + } + + stops = [...stops]; + stops.sort(compare); + return stops; +} + +/** + * Convert a range to a regex pattern + * @param {Number} `start` + * @param {Number} `stop` + * @return {String} + */ + +function rangeToPattern(start, stop, options) { + if (start === stop) { + return { pattern: start, count: [], digits: 0 }; + } + + let zipped = zip(start, stop); + let digits = zipped.length; + let pattern = ''; + let count = 0; + + for (let i = 0; i < digits; i++) { + let [startDigit, stopDigit] = zipped[i]; + + if (startDigit === stopDigit) { + pattern += startDigit; + + } else if (startDigit !== '0' || stopDigit !== '9') { + pattern += toCharacterClass(startDigit, stopDigit, options); + + } else { + count++; + } + } + + if (count) { + pattern += options.shorthand === true ? '\\d' : '[0-9]'; + } + + return { pattern, count: [count], digits }; +} + +function splitToPatterns(min, max, tok, options) { + let ranges = splitToRanges(min, max); + let tokens = []; + let start = min; + let prev; + + for (let i = 0; i < ranges.length; i++) { + let max = ranges[i]; + let obj = rangeToPattern(String(start), String(max), options); + let zeros = ''; + + if (!tok.isPadded && prev && prev.pattern === obj.pattern) { + if (prev.count.length > 1) { + prev.count.pop(); + } + + prev.count.push(obj.count[0]); + prev.string = prev.pattern + toQuantifier(prev.count); + start = max + 1; + continue; + } + + if (tok.isPadded) { + zeros = padZeros(max, tok, options); + } + + obj.string = zeros + obj.pattern + toQuantifier(obj.count); + tokens.push(obj); + start = max + 1; + prev = obj; + } + + return tokens; +} + +function filterPatterns(arr, comparison, prefix, intersection, options) { + let result = []; + + for (let ele of arr) { + let { string } = ele; + + // only push if _both_ are negative... + if (!intersection && !contains(comparison, 'string', string)) { + result.push(prefix + string); + } + + // or _both_ are positive + if (intersection && contains(comparison, 'string', string)) { + result.push(prefix + string); + } + } + return result; +} + +/** + * Zip strings + */ + +function zip(a, b) { + let arr = []; + for (let i = 0; i < a.length; i++) arr.push([a[i], b[i]]); + return arr; +} + +function compare(a, b) { + return a > b ? 1 : b > a ? -1 : 0; +} + +function contains(arr, key, val) { + return arr.some(ele => ele[key] === val); +} + +function countNines(min, len) { + return Number(String(min).slice(0, -len) + '9'.repeat(len)); +} + +function countZeros(integer, zeros) { + return integer - (integer % Math.pow(10, zeros)); +} + +function toQuantifier(digits) { + let [start = 0, stop = ''] = digits; + if (stop || start > 1) { + return `{${start + (stop ? ',' + stop : '')}}`; + } + return ''; +} + +function toCharacterClass(a, b, options) { + return `[${a}${(b - a === 1) ? '' : '-'}${b}]`; +} + +function hasPadding(str) { + return /^-?(0+)\d/.test(str); +} + +function padZeros(value, tok, options) { + if (!tok.isPadded) { + return value; + } + + let diff = Math.abs(tok.maxLen - String(value).length); + let relax = options.relaxZeros !== false; + + switch (diff) { + case 0: + return ''; + case 1: + return relax ? '0?' : '0'; + case 2: + return relax ? '0{0,2}' : '00'; + default: { + return relax ? `0{0,${diff}}` : `0{${diff}}`; + } + } +} + +/** + * Cache + */ + +toRegexRange.cache = {}; +toRegexRange.clearCache = () => (toRegexRange.cache = {}); + +/** + * Expose `toRegexRange` + */ + +module.exports = toRegexRange; diff --git a/homework8/project_express/node_modules/to-regex-range/package.json b/homework8/project_express/node_modules/to-regex-range/package.json new file mode 100644 index 0000000..4ef194f --- /dev/null +++ b/homework8/project_express/node_modules/to-regex-range/package.json @@ -0,0 +1,88 @@ +{ + "name": "to-regex-range", + "description": "Pass two numbers, get a regex-compatible source string for matching ranges. Validated against more than 2.78 million test assertions.", + "version": "5.0.1", + "homepage": "https://github.com/micromatch/to-regex-range", + "author": "Jon Schlinkert (https://github.com/jonschlinkert)", + "contributors": [ + "Jon Schlinkert (http://twitter.com/jonschlinkert)", + "Rouven Weßling (www.rouvenwessling.de)" + ], + "repository": "micromatch/to-regex-range", + "bugs": { + "url": "https://github.com/micromatch/to-regex-range/issues" + }, + "license": "MIT", + "files": [ + "index.js" + ], + "main": "index.js", + "engines": { + "node": ">=8.0" + }, + "scripts": { + "test": "mocha" + }, + "dependencies": { + "is-number": "^7.0.0" + }, + "devDependencies": { + "fill-range": "^6.0.0", + "gulp-format-md": "^2.0.0", + "mocha": "^6.0.2", + "text-table": "^0.2.0", + "time-diff": "^0.3.1" + }, + "keywords": [ + "bash", + "date", + "expand", + "expansion", + "expression", + "glob", + "match", + "match date", + "match number", + "match numbers", + "match year", + "matches", + "matching", + "number", + "numbers", + "numerical", + "range", + "ranges", + "regex", + "regexp", + "regular", + "regular expression", + "sequence" + ], + "verb": { + "layout": "default", + "toc": false, + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "lint": { + "reflinks": true + }, + "helpers": { + "examples": { + "displayName": "examples" + } + }, + "related": { + "list": [ + "expand-range", + "fill-range", + "micromatch", + "repeat-element", + "repeat-string" + ] + } + } +} diff --git a/homework8/project_express/node_modules/toidentifier/LICENSE b/homework8/project_express/node_modules/toidentifier/LICENSE new file mode 100644 index 0000000..de22d15 --- /dev/null +++ b/homework8/project_express/node_modules/toidentifier/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Douglas Christopher Wilson + +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/homework8/project_express/node_modules/toidentifier/README.md b/homework8/project_express/node_modules/toidentifier/README.md new file mode 100644 index 0000000..7c8794e --- /dev/null +++ b/homework8/project_express/node_modules/toidentifier/README.md @@ -0,0 +1,61 @@ +# toidentifier + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][codecov-image]][codecov-url] + +> Convert a string of words to a JavaScript identifier + +## Install + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```bash +$ npm install toidentifier +``` + +## Example + +```js +var toIdentifier = require('toidentifier') + +console.log(toIdentifier('Bad Request')) +// => "BadRequest" +``` + +## API + +This CommonJS module exports a single default function: `toIdentifier`. + +### toIdentifier(string) + +Given a string as the argument, it will be transformed according to +the following rules and the new string will be returned: + +1. Split into words separated by space characters (`0x20`). +2. Upper case the first character of each word. +3. Join the words together with no separator. +4. Remove all non-word (`[0-9a-z_]`) characters. + +## License + +[MIT](LICENSE) + +[codecov-image]: https://img.shields.io/codecov/c/github/component/toidentifier.svg +[codecov-url]: https://codecov.io/gh/component/toidentifier +[downloads-image]: https://img.shields.io/npm/dm/toidentifier.svg +[downloads-url]: https://npmjs.org/package/toidentifier +[npm-image]: https://img.shields.io/npm/v/toidentifier.svg +[npm-url]: https://npmjs.org/package/toidentifier +[travis-image]: https://img.shields.io/travis/component/toidentifier/master.svg +[travis-url]: https://travis-ci.org/component/toidentifier + + +## + +[npm]: https://www.npmjs.com/ + +[yarn]: https://yarnpkg.com/ diff --git a/homework8/project_express/node_modules/toidentifier/index.js b/homework8/project_express/node_modules/toidentifier/index.js new file mode 100644 index 0000000..bba5411 --- /dev/null +++ b/homework8/project_express/node_modules/toidentifier/index.js @@ -0,0 +1,30 @@ +/*! + * toidentifier + * Copyright(c) 2016 Douglas Christopher Wilson + * MIT Licensed + */ + +/** + * Module exports. + * @public + */ + +module.exports = toIdentifier + +/** + * Trasform the given string into a JavaScript identifier + * + * @param {string} str + * @returns {string} + * @public + */ + +function toIdentifier (str) { + return str + .split(' ') + .map(function (token) { + return token.slice(0, 1).toUpperCase() + token.slice(1) + }) + .join('') + .replace(/[^ _0-9a-z]/gi, '') +} diff --git a/homework8/project_express/node_modules/toidentifier/package.json b/homework8/project_express/node_modules/toidentifier/package.json new file mode 100644 index 0000000..9b5b6b1 --- /dev/null +++ b/homework8/project_express/node_modules/toidentifier/package.json @@ -0,0 +1,76 @@ +{ + "_from": "toidentifier@1.0.0", + "_id": "toidentifier@1.0.0", + "_inBundle": false, + "_integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "_location": "/toidentifier", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "toidentifier@1.0.0", + "name": "toidentifier", + "escapedName": "toidentifier", + "rawSpec": "1.0.0", + "saveSpec": null, + "fetchSpec": "1.0.0" + }, + "_requiredBy": [ + "/http-errors" + ], + "_resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "_shasum": "7e1be3470f1e77948bc43d94a3c8f4d7752ba553", + "_spec": "toidentifier@1.0.0", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\http-errors", + "author": { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + "bugs": { + "url": "https://github.com/component/toidentifier/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "Nick Baugh", + "email": "niftylettuce@gmail.com", + "url": "http://niftylettuce.com/" + } + ], + "deprecated": false, + "description": "Convert a string of words to a JavaScript identifier", + "devDependencies": { + "eslint": "4.19.1", + "eslint-config-standard": "11.0.0", + "eslint-plugin-import": "2.11.0", + "eslint-plugin-markdown": "1.0.0-beta.6", + "eslint-plugin-node": "6.0.1", + "eslint-plugin-promise": "3.7.0", + "eslint-plugin-standard": "3.1.0", + "mocha": "1.21.5", + "nyc": "11.8.0" + }, + "engines": { + "node": ">=0.6" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/component/toidentifier#readme", + "license": "MIT", + "name": "toidentifier", + "repository": { + "type": "git", + "url": "git+https://github.com/component/toidentifier.git" + }, + "scripts": { + "lint": "eslint --plugin markdown --ext js,md .", + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "nyc --reporter=html --reporter=text npm test" + }, + "version": "1.0.0" +} diff --git a/homework8/project_express/node_modules/touch/LICENSE b/homework8/project_express/node_modules/touch/LICENSE new file mode 100644 index 0000000..05eeeb8 --- /dev/null +++ b/homework8/project_express/node_modules/touch/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/homework8/project_express/node_modules/touch/README.md b/homework8/project_express/node_modules/touch/README.md new file mode 100644 index 0000000..b5a361e --- /dev/null +++ b/homework8/project_express/node_modules/touch/README.md @@ -0,0 +1,52 @@ +# node-touch + +For all your node touching needs. + +## Installing + +```bash +npm install touch +``` + +## CLI Usage: + +See `man touch` + +This package exports a binary called `nodetouch` that works mostly +like the unix builtin `touch(1)`. + +## API Usage: + +```javascript +var touch = require("touch") +``` + +Gives you the following functions: + +* `touch(filename, options, cb)` +* `touch.sync(filename, options)` +* `touch.ftouch(fd, options, cb)` +* `touch.ftouchSync(fd, options)` + +All the `options` objects are optional. + +All the async functions return a Promise. If a callback function is +provided, then it's attached to the Promise. + +## Options + +* `force` like `touch -f` Boolean +* `time` like `touch -t ` Can be a Date object, or any parseable + Date string, or epoch ms number. +* `atime` like `touch -a` Can be either a Boolean, or a Date. +* `mtime` like `touch -m` Can be either a Boolean, or a Date. +* `ref` like `touch -r ` Must be path to a file. +* `nocreate` like `touch -c` Boolean + +If neither `atime` nor `mtime` are set, then both values are set. If +one of them is set, then the other is not. + +## cli + +This package creates a `nodetouch` command line executable that works +very much like the unix builtin `touch(1)` diff --git a/homework8/project_express/node_modules/touch/bin/nodetouch.js b/homework8/project_express/node_modules/touch/bin/nodetouch.js new file mode 100644 index 0000000..f78f082 --- /dev/null +++ b/homework8/project_express/node_modules/touch/bin/nodetouch.js @@ -0,0 +1,112 @@ +#!/usr/bin/env node +const touch = require("../index.js") + +const usage = code => { + console[code ? 'error' : 'log']( + 'usage:\n' + + 'touch [-acfm] [-r file] [-t [[CC]YY]MMDDhhmm[.SS]] file ...' + ) + process.exit(code) +} + +const singleFlags = { + a: 'atime', + m: 'mtime', + c: 'nocreate', + f: 'force' +} + +const singleOpts = { + r: 'ref', + t: 'time' +} + +const files = [] +const args = process.argv.slice(2) +const options = {} +for (let i = 0; i < args.length; i++) { + const arg = args[i] + if (!arg.match(/^-/)) { + files.push(arg) + continue + } + + // expand shorthands + if (arg.charAt(1) !== '-') { + const expand = [] + for (let f = 1; f < arg.length; f++) { + const fc = arg.charAt(f) + const sf = singleFlags[fc] + const so = singleOpts[fc] + if (sf) + expand.push('--' + sf) + else if (so) { + const soslice = arg.slice(f + 1) + const soval = soslice.charAt(0) === '=' ? soslice : '=' + soslice + expand.push('--' + so + soval) + f = arg.length + } else if (arg !== '-' + fc) + expand.push('-' + fc) + } + if (expand.length) { + args.splice.apply(args, [i, 1].concat(expand)) + i-- + continue + } + } + + const argsplit = arg.split('=') + const key = argsplit.shift().replace(/^\-\-/, '') + const val = argsplit.length ? argsplit.join('=') : null + + switch (key) { + case 'time': + const timestr = val || args[++i] + // [-t [[CC]YY]MMDDhhmm[.SS]] + const parsedtime = timestr.match( + /^(([0-9]{2})?([0-9]{2}))?([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})(\.([0-9]{2}))?$/ + ) + if (!parsedtime) { + console.error('touch: out of range or illegal ' + + 'time specification: ' + + '[[CC]YY]MMDDhhmm[.SS]') + process.exit(1) + } else { + const y = +parsedtime[1] + const year = parsedtime[2] ? y + : y <= 68 ? 2000 + y + : 1900 + y + + const MM = +parsedtime[4] - 1 + const dd = +parsedtime[5] + const hh = +parsedtime[6] + const mm = +parsedtime[7] + const ss = +parsedtime[8] + + options.time = new Date(Date.UTC(year, MM, dd, hh, mm, ss)) + } + continue + + case 'ref': + options.ref = val || args[++i] + continue + + case 'mtime': + case 'nocreate': + case 'atime': + case 'force': + options[key] = true + continue + + default: + console.error('touch: illegal option -- ' + arg) + usage(1) + } +} + +if (!files.length) + usage() + +process.exitCode = 0 +Promise.all(files.map(f => touch(f, options))) + .catch(er => process.exitCode = 1) diff --git a/homework8/project_express/node_modules/touch/index.js b/homework8/project_express/node_modules/touch/index.js new file mode 100644 index 0000000..f942e42 --- /dev/null +++ b/homework8/project_express/node_modules/touch/index.js @@ -0,0 +1,224 @@ +'use strict' + +const EE = require('events').EventEmitter +const cons = require('constants') +const fs = require('fs') + +module.exports = (f, options, cb) => { + if (typeof options === 'function') + cb = options, options = {} + + const p = new Promise((res, rej) => { + new Touch(validOpts(options, f, null)) + .on('done', res).on('error', rej) + }) + + return cb ? p.then(res => cb(null, res), cb) : p +} + +module.exports.sync = module.exports.touchSync = (f, options) => + (new TouchSync(validOpts(options, f, null)), undefined) + +module.exports.ftouch = (fd, options, cb) => { + if (typeof options === 'function') + cb = options, options = {} + + const p = new Promise((res, rej) => { + new Touch(validOpts(options, null, fd)) + .on('done', res).on('error', rej) + }) + + return cb ? p.then(res => cb(null, res), cb) : p +} + +module.exports.ftouchSync = (fd, opt) => + (new TouchSync(validOpts(opt, null, fd)), undefined) + +const validOpts = (options, path, fd) => { + options = Object.create(options || {}) + options.fd = fd + options.path = path + + // {mtime: true}, {ctime: true} + // If set to something else, then treat as epoch ms value + const now = parseInt(new Date(options.time || Date.now()).getTime() / 1000) + if (!options.atime && !options.mtime) + options.atime = options.mtime = now + else { + if (true === options.atime) + options.atime = now + + if (true === options.mtime) + options.mtime = now + } + + let oflags = 0 + if (!options.force) + oflags = oflags | cons.O_RDWR + + if (!options.nocreate) + oflags = oflags | cons.O_CREAT + + options.oflags = oflags + return options +} + +class Touch extends EE { + constructor (options) { + super(options) + this.fd = options.fd + this.path = options.path + this.atime = options.atime + this.mtime = options.mtime + this.ref = options.ref + this.nocreate = !!options.nocreate + this.force = !!options.force + this.closeAfter = options.closeAfter + this.oflags = options.oflags + this.options = options + + if (typeof this.fd !== 'number') { + this.closeAfter = true + this.open() + } else + this.onopen(null, this.fd) + } + + emit (ev, data) { + // we only emit when either done or erroring + // in both cases, need to close + this.close() + return super.emit(ev, data) + } + + close () { + if (typeof this.fd === 'number' && this.closeAfter) + fs.close(this.fd, () => {}) + } + + open () { + fs.open(this.path, this.oflags, (er, fd) => this.onopen(er, fd)) + } + + onopen (er, fd) { + if (er) { + if (er.code === 'EISDIR') + this.onopen(null, null) + else if (er.code === 'ENOENT' && this.nocreate) + this.emit('done') + else + this.emit('error', er) + } else { + this.fd = fd + if (this.ref) + this.statref() + else if (!this.atime || !this.mtime) + this.fstat() + else + this.futimes() + } + } + + statref () { + fs.stat(this.ref, (er, st) => { + if (er) + this.emit('error', er) + else + this.onstatref(st) + }) + } + + onstatref (st) { + this.atime = this.atime && parseInt(st.atime.getTime()/1000, 10) + this.mtime = this.mtime && parseInt(st.mtime.getTime()/1000, 10) + if (!this.atime || !this.mtime) + this.fstat() + else + this.futimes() + } + + fstat () { + const stat = this.fd ? 'fstat' : 'stat' + const target = this.fd || this.path + fs[stat](target, (er, st) => { + if (er) + this.emit('error', er) + else + this.onfstat(st) + }) + } + + onfstat (st) { + if (typeof this.atime !== 'number') + this.atime = parseInt(st.atime.getTime()/1000, 10) + + if (typeof this.mtime !== 'number') + this.mtime = parseInt(st.mtime.getTime()/1000, 10) + + this.futimes() + } + + futimes () { + const utimes = this.fd ? 'futimes' : 'utimes' + const target = this.fd || this.path + fs[utimes](target, ''+this.atime, ''+this.mtime, er => { + if (er) + this.emit('error', er) + else + this.emit('done') + }) + } +} + +class TouchSync extends Touch { + open () { + try { + this.onopen(null, fs.openSync(this.path, this.oflags)) + } catch (er) { + this.onopen(er) + } + } + + statref () { + let threw = true + try { + this.onstatref(fs.statSync(this.ref)) + threw = false + } finally { + if (threw) + this.close() + } + } + + fstat () { + let threw = true + const stat = this.fd ? 'fstatSync' : 'statSync' + const target = this.fd || this.path + try { + this.onfstat(fs[stat](target)) + threw = false + } finally { + if (threw) + this.close() + } + } + + futimes () { + let threw = true + const utimes = this.fd ? 'futimesSync' : 'utimesSync' + const target = this.fd || this.path + try { + fs[utimes](target, this.atime, this.mtime) + threw = false + } finally { + if (threw) + this.close() + } + this.emit('done') + } + + close () { + if (typeof this.fd === 'number' && this.closeAfter) + try { fs.closeSync(this.fd) } catch (er) {} + } +} diff --git a/homework8/project_express/node_modules/touch/package.json b/homework8/project_express/node_modules/touch/package.json new file mode 100644 index 0000000..05608de --- /dev/null +++ b/homework8/project_express/node_modules/touch/package.json @@ -0,0 +1,28 @@ +{ + "author": "Isaac Z. Schlueter (http://blog.izs.me/)", + "name": "touch", + "description": "like touch(1) in node", + "version": "3.1.0", + "repository": "git://github.com/isaacs/node-touch.git", + "bin": { + "nodetouch": "./bin/nodetouch.js" + }, + "dependencies": { + "nopt": "~1.0.10" + }, + "license": "ISC", + "scripts": { + "test": "tap test/*.js --100 -J", + "preversion": "npm test", + "postversion": "npm publish", + "postpublish": "git push origin --all; git push origin --tags" + }, + "devDependencies": { + "mutate-fs": "^1.1.0", + "tap": "^10.7.0" + }, + "files": [ + "index.js", + "bin/nodetouch.js" + ] +} diff --git a/homework8/project_express/node_modules/type-is/HISTORY.md b/homework8/project_express/node_modules/type-is/HISTORY.md new file mode 100644 index 0000000..8de21f7 --- /dev/null +++ b/homework8/project_express/node_modules/type-is/HISTORY.md @@ -0,0 +1,259 @@ +1.6.18 / 2019-04-26 +=================== + + * Fix regression passing request object to `typeis.is` + +1.6.17 / 2019-04-25 +=================== + + * deps: mime-types@~2.1.24 + - Add Apple file extensions from IANA + - Add extension `.csl` to `application/vnd.citationstyles.style+xml` + - Add extension `.es` to `application/ecmascript` + - Add extension `.nq` to `application/n-quads` + - Add extension `.nt` to `application/n-triples` + - Add extension `.owl` to `application/rdf+xml` + - Add extensions `.siv` and `.sieve` to `application/sieve` + - Add extensions from IANA for `image/*` types + - Add extensions from IANA for `model/*` types + - Add extensions to HEIC image types + - Add new mime types + - Add `text/mdx` with extension `.mdx` + * perf: prevent internal `throw` on invalid type + +1.6.16 / 2018-02-16 +=================== + + * deps: mime-types@~2.1.18 + - Add `application/raml+yaml` with extension `.raml` + - Add `application/wasm` with extension `.wasm` + - Add `text/shex` with extension `.shex` + - Add extensions for JPEG-2000 images + - Add extensions from IANA for `message/*` types + - Add extension `.mjs` to `application/javascript` + - Add extension `.wadl` to `application/vnd.sun.wadl+xml` + - Add extension `.gz` to `application/gzip` + - Add glTF types and extensions + - Add new mime types + - Update extensions `.md` and `.markdown` to be `text/markdown` + - Update font MIME types + - Update `text/hjson` to registered `application/hjson` + +1.6.15 / 2017-03-31 +=================== + + * deps: mime-types@~2.1.15 + - Add new mime types + +1.6.14 / 2016-11-18 +=================== + + * deps: mime-types@~2.1.13 + - Add new mime types + +1.6.13 / 2016-05-18 +=================== + + * deps: mime-types@~2.1.11 + - Add new mime types + +1.6.12 / 2016-02-28 +=================== + + * deps: mime-types@~2.1.10 + - Add new mime types + - Fix extension of `application/dash+xml` + - Update primary extension for `audio/mp4` + +1.6.11 / 2016-01-29 +=================== + + * deps: mime-types@~2.1.9 + - Add new mime types + +1.6.10 / 2015-12-01 +=================== + + * deps: mime-types@~2.1.8 + - Add new mime types + +1.6.9 / 2015-09-27 +================== + + * deps: mime-types@~2.1.7 + - Add new mime types + +1.6.8 / 2015-09-04 +================== + + * deps: mime-types@~2.1.6 + - Add new mime types + +1.6.7 / 2015-08-20 +================== + + * Fix type error when given invalid type to match against + * deps: mime-types@~2.1.5 + - Add new mime types + +1.6.6 / 2015-07-31 +================== + + * deps: mime-types@~2.1.4 + - Add new mime types + +1.6.5 / 2015-07-16 +================== + + * deps: mime-types@~2.1.3 + - Add new mime types + +1.6.4 / 2015-07-01 +================== + + * deps: mime-types@~2.1.2 + - Add new mime types + * perf: enable strict mode + * perf: remove argument reassignment + +1.6.3 / 2015-06-08 +================== + + * deps: mime-types@~2.1.1 + - Add new mime types + * perf: reduce try block size + * perf: remove bitwise operations + +1.6.2 / 2015-05-10 +================== + + * deps: mime-types@~2.0.11 + - Add new mime types + +1.6.1 / 2015-03-13 +================== + + * deps: mime-types@~2.0.10 + - Add new mime types + +1.6.0 / 2015-02-12 +================== + + * fix false-positives in `hasBody` `Transfer-Encoding` check + * support wildcard for both type and subtype (`*/*`) + +1.5.7 / 2015-02-09 +================== + + * fix argument reassignment + * deps: mime-types@~2.0.9 + - Add new mime types + +1.5.6 / 2015-01-29 +================== + + * deps: mime-types@~2.0.8 + - Add new mime types + +1.5.5 / 2014-12-30 +================== + + * deps: mime-types@~2.0.7 + - Add new mime types + - Fix missing extensions + - Fix various invalid MIME type entries + - Remove example template MIME types + - deps: mime-db@~1.5.0 + +1.5.4 / 2014-12-10 +================== + + * deps: mime-types@~2.0.4 + - Add new mime types + - deps: mime-db@~1.3.0 + +1.5.3 / 2014-11-09 +================== + + * deps: mime-types@~2.0.3 + - Add new mime types + - deps: mime-db@~1.2.0 + +1.5.2 / 2014-09-28 +================== + + * deps: mime-types@~2.0.2 + - Add new mime types + - deps: mime-db@~1.1.0 + +1.5.1 / 2014-09-07 +================== + + * Support Node.js 0.6 + * deps: media-typer@0.3.0 + * deps: mime-types@~2.0.1 + - Support Node.js 0.6 + +1.5.0 / 2014-09-05 +================== + + * fix `hasbody` to be true for `content-length: 0` + +1.4.0 / 2014-09-02 +================== + + * update mime-types + +1.3.2 / 2014-06-24 +================== + + * use `~` range on mime-types + +1.3.1 / 2014-06-19 +================== + + * fix global variable leak + +1.3.0 / 2014-06-19 +================== + + * improve type parsing + + - invalid media type never matches + - media type not case-sensitive + - extra LWS does not affect results + +1.2.2 / 2014-06-19 +================== + + * fix behavior on unknown type argument + +1.2.1 / 2014-06-03 +================== + + * switch dependency from `mime` to `mime-types@1.0.0` + +1.2.0 / 2014-05-11 +================== + + * support suffix matching: + + - `+json` matches `application/vnd+json` + - `*/vnd+json` matches `application/vnd+json` + - `application/*+json` matches `application/vnd+json` + +1.1.0 / 2014-04-12 +================== + + * add non-array values support + * expose internal utilities: + + - `.is()` + - `.hasBody()` + - `.normalize()` + - `.match()` + +1.0.1 / 2014-03-30 +================== + + * add `multipart` as a shorthand diff --git a/homework8/project_express/node_modules/type-is/LICENSE b/homework8/project_express/node_modules/type-is/LICENSE new file mode 100644 index 0000000..386b7b6 --- /dev/null +++ b/homework8/project_express/node_modules/type-is/LICENSE @@ -0,0 +1,23 @@ +(The MIT License) + +Copyright (c) 2014 Jonathan Ong +Copyright (c) 2014-2015 Douglas Christopher Wilson + +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/homework8/project_express/node_modules/type-is/README.md b/homework8/project_express/node_modules/type-is/README.md new file mode 100644 index 0000000..b85ef8f --- /dev/null +++ b/homework8/project_express/node_modules/type-is/README.md @@ -0,0 +1,170 @@ +# type-is + +[![NPM Version][npm-version-image]][npm-url] +[![NPM Downloads][npm-downloads-image]][npm-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Infer the content-type of a request. + +### Install + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```sh +$ npm install type-is +``` + +## API + +```js +var http = require('http') +var typeis = require('type-is') + +http.createServer(function (req, res) { + var istext = typeis(req, ['text/*']) + res.end('you ' + (istext ? 'sent' : 'did not send') + ' me text') +}) +``` + +### typeis(request, types) + +Checks if the `request` is one of the `types`. If the request has no body, +even if there is a `Content-Type` header, then `null` is returned. If the +`Content-Type` header is invalid or does not matches any of the `types`, then +`false` is returned. Otherwise, a string of the type that matched is returned. + +The `request` argument is expected to be a Node.js HTTP request. The `types` +argument is an array of type strings. + +Each type in the `types` array can be one of the following: + +- A file extension name such as `json`. This name will be returned if matched. +- A mime type such as `application/json`. +- A mime type with a wildcard such as `*/*` or `*/json` or `application/*`. + The full mime type will be returned if matched. +- A suffix such as `+json`. This can be combined with a wildcard such as + `*/vnd+json` or `application/*+json`. The full mime type will be returned + if matched. + +Some examples to illustrate the inputs and returned value: + + + +```js +// req.headers.content-type = 'application/json' + +typeis(req, ['json']) // => 'json' +typeis(req, ['html', 'json']) // => 'json' +typeis(req, ['application/*']) // => 'application/json' +typeis(req, ['application/json']) // => 'application/json' + +typeis(req, ['html']) // => false +``` + +### typeis.hasBody(request) + +Returns a Boolean if the given `request` has a body, regardless of the +`Content-Type` header. + +Having a body has no relation to how large the body is (it may be 0 bytes). +This is similar to how file existence works. If a body does exist, then this +indicates that there is data to read from the Node.js request stream. + + + +```js +if (typeis.hasBody(req)) { + // read the body, since there is one + + req.on('data', function (chunk) { + // ... + }) +} +``` + +### typeis.is(mediaType, types) + +Checks if the `mediaType` is one of the `types`. If the `mediaType` is invalid +or does not matches any of the `types`, then `false` is returned. Otherwise, a +string of the type that matched is returned. + +The `mediaType` argument is expected to be a +[media type](https://tools.ietf.org/html/rfc6838) string. The `types` argument +is an array of type strings. + +Each type in the `types` array can be one of the following: + +- A file extension name such as `json`. This name will be returned if matched. +- A mime type such as `application/json`. +- A mime type with a wildcard such as `*/*` or `*/json` or `application/*`. + The full mime type will be returned if matched. +- A suffix such as `+json`. This can be combined with a wildcard such as + `*/vnd+json` or `application/*+json`. The full mime type will be returned + if matched. + +Some examples to illustrate the inputs and returned value: + + + +```js +var mediaType = 'application/json' + +typeis.is(mediaType, ['json']) // => 'json' +typeis.is(mediaType, ['html', 'json']) // => 'json' +typeis.is(mediaType, ['application/*']) // => 'application/json' +typeis.is(mediaType, ['application/json']) // => 'application/json' + +typeis.is(mediaType, ['html']) // => false +``` + +## Examples + +### Example body parser + +```js +var express = require('express') +var typeis = require('type-is') + +var app = express() + +app.use(function bodyParser (req, res, next) { + if (!typeis.hasBody(req)) { + return next() + } + + switch (typeis(req, ['urlencoded', 'json', 'multipart'])) { + case 'urlencoded': + // parse urlencoded body + throw new Error('implement urlencoded body parsing') + case 'json': + // parse json body + throw new Error('implement json body parsing') + case 'multipart': + // parse multipart body + throw new Error('implement multipart body parsing') + default: + // 415 error code + res.statusCode = 415 + res.end() + break + } +}) +``` + +## License + +[MIT](LICENSE) + +[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/type-is/master +[coveralls-url]: https://coveralls.io/r/jshttp/type-is?branch=master +[node-version-image]: https://badgen.net/npm/node/type-is +[node-version-url]: https://nodejs.org/en/download +[npm-downloads-image]: https://badgen.net/npm/dm/type-is +[npm-url]: https://npmjs.org/package/type-is +[npm-version-image]: https://badgen.net/npm/v/type-is +[travis-image]: https://badgen.net/travis/jshttp/type-is/master +[travis-url]: https://travis-ci.org/jshttp/type-is diff --git a/homework8/project_express/node_modules/type-is/index.js b/homework8/project_express/node_modules/type-is/index.js new file mode 100644 index 0000000..890ad76 --- /dev/null +++ b/homework8/project_express/node_modules/type-is/index.js @@ -0,0 +1,266 @@ +/*! + * type-is + * Copyright(c) 2014 Jonathan Ong + * Copyright(c) 2014-2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module dependencies. + * @private + */ + +var typer = require('media-typer') +var mime = require('mime-types') + +/** + * Module exports. + * @public + */ + +module.exports = typeofrequest +module.exports.is = typeis +module.exports.hasBody = hasbody +module.exports.normalize = normalize +module.exports.match = mimeMatch + +/** + * Compare a `value` content-type with `types`. + * Each `type` can be an extension like `html`, + * a special shortcut like `multipart` or `urlencoded`, + * or a mime type. + * + * If no types match, `false` is returned. + * Otherwise, the first `type` that matches is returned. + * + * @param {String} value + * @param {Array} types + * @public + */ + +function typeis (value, types_) { + var i + var types = types_ + + // remove parameters and normalize + var val = tryNormalizeType(value) + + // no type or invalid + if (!val) { + return false + } + + // support flattened arguments + if (types && !Array.isArray(types)) { + types = new Array(arguments.length - 1) + for (i = 0; i < types.length; i++) { + types[i] = arguments[i + 1] + } + } + + // no types, return the content type + if (!types || !types.length) { + return val + } + + var type + for (i = 0; i < types.length; i++) { + if (mimeMatch(normalize(type = types[i]), val)) { + return type[0] === '+' || type.indexOf('*') !== -1 + ? val + : type + } + } + + // no matches + return false +} + +/** + * Check if a request has a request body. + * A request with a body __must__ either have `transfer-encoding` + * or `content-length` headers set. + * http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3 + * + * @param {Object} request + * @return {Boolean} + * @public + */ + +function hasbody (req) { + return req.headers['transfer-encoding'] !== undefined || + !isNaN(req.headers['content-length']) +} + +/** + * Check if the incoming request contains the "Content-Type" + * header field, and it contains any of the give mime `type`s. + * If there is no request body, `null` is returned. + * If there is no content type, `false` is returned. + * Otherwise, it returns the first `type` that matches. + * + * Examples: + * + * // With Content-Type: text/html; charset=utf-8 + * this.is('html'); // => 'html' + * this.is('text/html'); // => 'text/html' + * this.is('text/*', 'application/json'); // => 'text/html' + * + * // When Content-Type is application/json + * this.is('json', 'urlencoded'); // => 'json' + * this.is('application/json'); // => 'application/json' + * this.is('html', 'application/*'); // => 'application/json' + * + * this.is('html'); // => false + * + * @param {String|Array} types... + * @return {String|false|null} + * @public + */ + +function typeofrequest (req, types_) { + var types = types_ + + // no body + if (!hasbody(req)) { + return null + } + + // support flattened arguments + if (arguments.length > 2) { + types = new Array(arguments.length - 1) + for (var i = 0; i < types.length; i++) { + types[i] = arguments[i + 1] + } + } + + // request content type + var value = req.headers['content-type'] + + return typeis(value, types) +} + +/** + * Normalize a mime type. + * If it's a shorthand, expand it to a valid mime type. + * + * In general, you probably want: + * + * var type = is(req, ['urlencoded', 'json', 'multipart']); + * + * Then use the appropriate body parsers. + * These three are the most common request body types + * and are thus ensured to work. + * + * @param {String} type + * @private + */ + +function normalize (type) { + if (typeof type !== 'string') { + // invalid type + return false + } + + switch (type) { + case 'urlencoded': + return 'application/x-www-form-urlencoded' + case 'multipart': + return 'multipart/*' + } + + if (type[0] === '+') { + // "+json" -> "*/*+json" expando + return '*/*' + type + } + + return type.indexOf('/') === -1 + ? mime.lookup(type) + : type +} + +/** + * Check if `expected` mime type + * matches `actual` mime type with + * wildcard and +suffix support. + * + * @param {String} expected + * @param {String} actual + * @return {Boolean} + * @private + */ + +function mimeMatch (expected, actual) { + // invalid type + if (expected === false) { + return false + } + + // split types + var actualParts = actual.split('/') + var expectedParts = expected.split('/') + + // invalid format + if (actualParts.length !== 2 || expectedParts.length !== 2) { + return false + } + + // validate type + if (expectedParts[0] !== '*' && expectedParts[0] !== actualParts[0]) { + return false + } + + // validate suffix wildcard + if (expectedParts[1].substr(0, 2) === '*+') { + return expectedParts[1].length <= actualParts[1].length + 1 && + expectedParts[1].substr(1) === actualParts[1].substr(1 - expectedParts[1].length) + } + + // validate subtype + if (expectedParts[1] !== '*' && expectedParts[1] !== actualParts[1]) { + return false + } + + return true +} + +/** + * Normalize a type and remove parameters. + * + * @param {string} value + * @return {string} + * @private + */ + +function normalizeType (value) { + // parse the type + var type = typer.parse(value) + + // remove the parameters + type.parameters = undefined + + // reformat it + return typer.format(type) +} + +/** + * Try to normalize a type and remove parameters. + * + * @param {string} value + * @return {string} + * @private + */ + +function tryNormalizeType (value) { + if (!value) { + return null + } + + try { + return normalizeType(value) + } catch (err) { + return null + } +} diff --git a/homework8/project_express/node_modules/type-is/package.json b/homework8/project_express/node_modules/type-is/package.json new file mode 100644 index 0000000..d3b2897 --- /dev/null +++ b/homework8/project_express/node_modules/type-is/package.json @@ -0,0 +1,85 @@ +{ + "_from": "type-is@~1.6.18", + "_id": "type-is@1.6.18", + "_inBundle": false, + "_integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "_location": "/type-is", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "type-is@~1.6.18", + "name": "type-is", + "escapedName": "type-is", + "rawSpec": "~1.6.18", + "saveSpec": null, + "fetchSpec": "~1.6.18" + }, + "_requiredBy": [ + "/body-parser", + "/express" + ], + "_resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "_shasum": "4e552cd05df09467dcbc4ef739de89f2cf37c131", + "_spec": "type-is@~1.6.18", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\express", + "bugs": { + "url": "https://github.com/jshttp/type-is/issues" + }, + "bundleDependencies": false, + "contributors": [ + { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + { + "name": "Jonathan Ong", + "email": "me@jongleberry.com", + "url": "http://jongleberry.com" + } + ], + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "deprecated": false, + "description": "Infer the content-type of a request.", + "devDependencies": { + "eslint": "5.16.0", + "eslint-config-standard": "12.0.0", + "eslint-plugin-import": "2.17.2", + "eslint-plugin-markdown": "1.0.0", + "eslint-plugin-node": "8.0.1", + "eslint-plugin-promise": "4.1.1", + "eslint-plugin-standard": "4.0.0", + "mocha": "6.1.4", + "nyc": "14.0.0" + }, + "engines": { + "node": ">= 0.6" + }, + "files": [ + "LICENSE", + "HISTORY.md", + "index.js" + ], + "homepage": "https://github.com/jshttp/type-is#readme", + "keywords": [ + "content", + "type", + "checking" + ], + "license": "MIT", + "name": "type-is", + "repository": { + "type": "git", + "url": "git+https://github.com/jshttp/type-is.git" + }, + "scripts": { + "lint": "eslint --plugin markdown --ext js,md .", + "test": "mocha --reporter spec --check-leaks --bail test/", + "test-cov": "nyc --reporter=html --reporter=text npm test", + "test-travis": "nyc --reporter=text npm test" + }, + "version": "1.6.18" +} diff --git a/homework8/project_express/node_modules/uglify-js/.npmignore b/homework8/project_express/node_modules/uglify-js/.npmignore new file mode 100644 index 0000000..94fceeb --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/.npmignore @@ -0,0 +1,2 @@ +tmp/ +node_modules/ diff --git a/homework8/project_express/node_modules/uglify-js/LICENSE b/homework8/project_express/node_modules/uglify-js/LICENSE new file mode 100644 index 0000000..dd7706f --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/LICENSE @@ -0,0 +1,29 @@ +UglifyJS is released under the BSD license: + +Copyright 2012-2013 (c) Mihai Bazon + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. diff --git a/homework8/project_express/node_modules/uglify-js/README.md b/homework8/project_express/node_modules/uglify-js/README.md new file mode 100644 index 0000000..ce55dc3 --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/README.md @@ -0,0 +1,567 @@ +UglifyJS 2 +========== + +UglifyJS is a JavaScript parser, minifier, compressor or beautifier toolkit. + +This page documents the command line utility. For +[API and internals documentation see my website](http://lisperator.net/uglifyjs/). +There's also an +[in-browser online demo](http://lisperator.net/uglifyjs/#demo) (for Firefox, +Chrome and probably Safari). + +Install +------- + +First make sure you have installed the latest version of [node.js](http://nodejs.org/) +(You may need to restart your computer after this step). + +From NPM for use as a command line app: + + npm install uglify-js -g + +From NPM for programmatic use: + + npm install uglify-js + +From Git: + + git clone git://github.com/mishoo/UglifyJS2.git + cd UglifyJS2 + npm link . + +Usage +----- + + uglifyjs [input files] [options] + +UglifyJS2 can take multiple input files. It's recommended that you pass the +input files first, then pass the options. UglifyJS will parse input files +in sequence and apply any compression options. The files are parsed in the +same global scope, that is, a reference from a file to some +variable/function declared in another file will be matched properly. + +If you want to read from STDIN instead, pass a single dash instead of input +files. + +The available options are: + + --source-map Specify an output file where to generate source map. + [string] + --source-map-root The path to the original source to be included in the + source map. [string] + --source-map-url The path to the source map to be added in //@ + sourceMappingURL. Defaults to the value passed with + --source-map. [string] + --in-source-map Input source map, useful if you're compressing JS that was + generated from some other original code. + --screw-ie8 Pass this flag if you don't care about full compliance with + Internet Explorer 6-8 quirks (by default UglifyJS will try + to be IE-proof). + -p, --prefix Skip prefix for original filenames that appear in source + maps. For example -p 3 will drop 3 directories from file + names and ensure they are relative paths. + -o, --output Output file (default STDOUT). + -b, --beautify Beautify output/specify output options. [string] + -m, --mangle Mangle names/pass mangler options. [string] + -r, --reserved Reserved names to exclude from mangling. + -c, --compress Enable compressor/pass compressor options. Pass options + like -c hoist_vars=false,if_return=false. Use -c with no + argument to use the default compression options. [string] + -d, --define Global definitions [string] + --comments Preserve copyright comments in the output. By default this + works like Google Closure, keeping JSDoc-style comments + that contain "@license" or "@preserve". You can optionally + pass one of the following arguments to this flag: + - "all" to keep all comments + - a valid JS regexp (needs to start with a slash) to keep + only comments that match. + Note that currently not *all* comments can be kept when + compression is on, because of dead code removal or + cascading statements into sequences. [string] + --stats Display operations run time on STDERR. [boolean] + --acorn Use Acorn for parsing. [boolean] + --spidermonkey Assume input fles are SpiderMonkey AST format (as JSON). + [boolean] + --self Build itself (UglifyJS2) as a library (implies + --wrap=UglifyJS --export-all) [boolean] + --wrap Embed everything in a big function, making the “exports” + and “global” variables available. You need to pass an + argument to this option to specify the name that your + module will take when included in, say, a browser. + [string] + --export-all Only used when --wrap, this tells UglifyJS to add code to + automatically export all globals. [boolean] + --lint Display some scope warnings [boolean] + -v, --verbose Verbose [boolean] + -V, --version Print version number and exit. [boolean] + +Specify `--output` (`-o`) to declare the output file. Otherwise the output +goes to STDOUT. + +## Source map options + +UglifyJS2 can generate a source map file, which is highly useful for +debugging your compressed JavaScript. To get a source map, pass +`--source-map output.js.map` (full path to the file where you want the +source map dumped). + +Additionally you might need `--source-map-root` to pass the URL where the +original files can be found. In case you are passing full paths to input +files to UglifyJS, you can use `--prefix` (`-p`) to specify the number of +directories to drop from the path prefix when declaring files in the source +map. + +For example: + + uglifyjs /home/doe/work/foo/src/js/file1.js \ + /home/doe/work/foo/src/js/file2.js \ + -o foo.min.js \ + --source-map foo.min.js.map \ + --source-map-root http://foo.com/src \ + -p 5 -c -m + +The above will compress and mangle `file1.js` and `file2.js`, will drop the +output in `foo.min.js` and the source map in `foo.min.js.map`. The source +mapping will refer to `http://foo.com/src/js/file1.js` and +`http://foo.com/src/js/file2.js` (in fact it will list `http://foo.com/src` +as the source map root, and the original files as `js/file1.js` and +`js/file2.js`). + +### Composed source map + +When you're compressing JS code that was output by a compiler such as +CoffeeScript, mapping to the JS code won't be too helpful. Instead, you'd +like to map back to the original code (i.e. CoffeeScript). UglifyJS has an +option to take an input source map. Assuming you have a mapping from +CoffeeScript → compiled JS, UglifyJS can generate a map from CoffeeScript → +compressed JS by mapping every token in the compiled JS to its original +location. + +To use this feature you need to pass `--in-source-map +/path/to/input/source.map`. Normally the input source map should also point +to the file containing the generated JS, so if that's correct you can omit +input files from the command line. + +## Mangler options + +To enable the mangler you need to pass `--mangle` (`-m`). The following +(comma-separated) options are supported: + +- `sort` — to assign shorter names to most frequently used variables. This + saves a few hundred bytes on jQuery before gzip, but the output is + _bigger_ after gzip (and seems to happen for other libraries I tried it + on) therefore it's not enabled by default. + +- `toplevel` — mangle names declared in the toplevel scope (disabled by + default). + +- `eval` — mangle names visible in scopes where `eval` or `when` are used + (disabled by default). + +When mangling is enabled but you want to prevent certain names from being +mangled, you can declare those names with `--reserved` (`-r`) — pass a +comma-separated list of names. For example: + + uglifyjs ... -m -r '$,require,exports' + +to prevent the `require`, `exports` and `$` names from being changed. + +## Compressor options + +You need to pass `--compress` (`-c`) to enable the compressor. Optionally +you can pass a comma-separated list of options. Options are in the form +`foo=bar`, or just `foo` (the latter implies a boolean option that you want +to set `true`; it's effectively a shortcut for `foo=true`). + +- `sequences` -- join consecutive simple statements using the comma operator +- `properties` -- rewrite property access using the dot notation, for + example `foo["bar"] → foo.bar` +- `dead_code` -- remove unreachable code +- `drop_debugger` -- remove `debugger;` statements +- `unsafe` (default: false) -- apply "unsafe" transformations (discussion below) +- `conditionals` -- apply optimizations for `if`-s and conditional + expressions +- `comparisons` -- apply certain optimizations to binary nodes, for example: + `!(a <= b) → a > b` (only when `unsafe`), attempts to negate binary nodes, + e.g. `a = !b && !c && !d && !e → a=!(b||c||d||e)` etc. +- `evaluate` -- attempt to evaluate constant expressions +- `booleans` -- various optimizations for boolean context, for example `!!a + ? b : c → a ? b : c` +- `loops` -- optimizations for `do`, `while` and `for` loops when we can + statically determine the condition +- `unused` -- drop unreferenced functions and variables +- `hoist_funs` -- hoist function declarations +- `hoist_vars` (default: false) -- hoist `var` declarations (this is `false` + by default because it seems to increase the size of the output in general) +- `if_return` -- optimizations for if/return and if/continue +- `join_vars` -- join consecutive `var` statements +- `cascade` -- small optimization for sequences, transform `x, x` into `x` + and `x = something(), x` into `x = something()` +- `warnings` -- display warnings when dropping unreachable code or unused + declarations etc. + +### The `unsafe` option + +It enables some transformations that *might* break code logic in certain +contrived cases, but should be fine for most code. You might want to try it +on your own code, it should reduce the minified size. Here's what happens +when this flag is on: + +- `new Array(1, 2, 3)` or `Array(1, 2, 3)` → `[1, 2, 3 ]` +- `new Object()` → `{}` +- `String(exp)` or `exp.toString()` → `"" + exp` +- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new` +- `typeof foo == "undefined"` → `foo === void 0` +- `void 0` → `"undefined"` (if there is a variable named "undefined" in + scope; we do it because the variable name will be mangled, typically + reduced to a single character). + +### Conditional compilation + +You can use the `--define` (`-d`) switch in order to declare global +variables that UglifyJS will assume to be constants (unless defined in +scope). For example if you pass `--define DEBUG=false` then, coupled with +dead code removal UglifyJS will discard the following from the output: + + if (DEBUG) { + console.log("debug stuff"); + } + +UglifyJS will warn about the condition being always false and about dropping +unreachable code; for now there is no option to turn off only this specific +warning, you can pass `warnings=false` to turn off *all* warnings. + +Another way of doing that is to declare your globals as constants in a +separate file and include it into the build. For example you can have a +`build/defines.js` file with the following: + + const DEBUG = false; + const PRODUCTION = true; + // etc. + +and build your code like this: + + uglifyjs build/defines.js js/foo.js js/bar.js... -c + +UglifyJS will notice the constants and, since they cannot be altered, it +will evaluate references to them to the value itself and drop unreachable +code as usual. The possible downside of this approach is that the build +will contain the `const` declarations. + + +## Beautifier options + +The code generator tries to output shortest code possible by default. In +case you want beautified output, pass `--beautify` (`-b`). Optionally you +can pass additional arguments that control the code output: + +- `beautify` (default `true`) -- whether to actually beautify the output. + Passing `-b` will set this to true, but you might need to pass `-b` even + when you want to generate minified code, in order to specify additional + arguments, so you can use `-b beautify=false` to override it. +- `indent-level` (default 4) +- `indent-start` (default 0) -- prefix all lines by that many spaces +- `quote-keys` (default `false`) -- pass `true` to quote all keys in literal + objects +- `space-colon` (default `true`) -- insert a space after the colon signs +- `ascii-only` (default `false`) -- escape Unicode characters in strings and + regexps +- `inline-script` (default `false`) -- escape the slash in occurrences of + ` 0) { + sys.error("WARN: Ignoring input files since --self was passed"); + } + files = UglifyJS.FILES; + if (!ARGS.wrap) ARGS.wrap = "UglifyJS"; + ARGS.export_all = true; +} + +var ORIG_MAP = ARGS.in_source_map; + +if (ORIG_MAP) { + ORIG_MAP = JSON.parse(fs.readFileSync(ORIG_MAP)); + if (files.length == 0) { + sys.error("INFO: Using file from the input source map: " + ORIG_MAP.file); + files = [ ORIG_MAP.file ]; + } + if (ARGS.source_map_root == null) { + ARGS.source_map_root = ORIG_MAP.sourceRoot; + } +} + +if (files.length == 0) { + files = [ "-" ]; +} + +if (files.indexOf("-") >= 0 && ARGS.source_map) { + sys.error("ERROR: Source map doesn't work with input from STDIN"); + process.exit(1); +} + +if (files.filter(function(el){ return el == "-" }).length > 1) { + sys.error("ERROR: Can read a single file from STDIN (two or more dashes specified)"); + process.exit(1); +} + +var STATS = {}; +var OUTPUT_FILE = ARGS.o; +var TOPLEVEL = null; + +var SOURCE_MAP = ARGS.source_map ? UglifyJS.SourceMap({ + file: OUTPUT_FILE, + root: ARGS.source_map_root, + orig: ORIG_MAP, +}) : null; + +OUTPUT_OPTIONS.source_map = SOURCE_MAP; + +try { + var output = UglifyJS.OutputStream(OUTPUT_OPTIONS); + var compressor = COMPRESS && UglifyJS.Compressor(COMPRESS); +} catch(ex) { + if (ex instanceof UglifyJS.DefaultsError) { + sys.error(ex.msg); + sys.error("Supported options:"); + sys.error(sys.inspect(ex.defs)); + process.exit(1); + } +} + +async.eachLimit(files, 1, function (file, cb) { + read_whole_file(file, function (err, code) { + if (err) { + sys.error("ERROR: can't read file: " + filename); + process.exit(1); + } + if (ARGS.p != null) { + file = file.replace(/^\/+/, "").split(/\/+/).slice(ARGS.p).join("/"); + } + time_it("parse", function(){ + if (ARGS.spidermonkey) { + var program = JSON.parse(code); + if (!TOPLEVEL) TOPLEVEL = program; + else TOPLEVEL.body = TOPLEVEL.body.concat(program.body); + } + else if (ARGS.acorn) { + TOPLEVEL = acorn.parse(code, { + locations : true, + trackComments : true, + sourceFile : file, + program : TOPLEVEL + }); + } + else { + TOPLEVEL = UglifyJS.parse(code, { + filename: file, + toplevel: TOPLEVEL + }); + }; + }); + cb(); + }); +}, function () { + if (ARGS.acorn || ARGS.spidermonkey) time_it("convert_ast", function(){ + TOPLEVEL = UglifyJS.AST_Node.from_mozilla_ast(TOPLEVEL); + }); + + if (ARGS.wrap) { + TOPLEVEL = TOPLEVEL.wrap_commonjs(ARGS.wrap, ARGS.export_all); + } + + if (ARGS.enclose) { + var arg_parameter_list = ARGS.enclose; + + if (!(arg_parameter_list instanceof Array)) { + arg_parameter_list = [arg_parameter_list]; + } + + TOPLEVEL = TOPLEVEL.wrap_enclose(arg_parameter_list); + } + + var SCOPE_IS_NEEDED = COMPRESS || MANGLE || ARGS.lint; + + if (SCOPE_IS_NEEDED) { + time_it("scope", function(){ + TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8 }); + if (ARGS.lint) { + TOPLEVEL.scope_warnings(); + } + }); + } + + if (COMPRESS) { + time_it("squeeze", function(){ + TOPLEVEL = TOPLEVEL.transform(compressor); + }); + } + + if (SCOPE_IS_NEEDED) { + time_it("scope", function(){ + TOPLEVEL.figure_out_scope({ screw_ie8: ARGS.screw_ie8 }); + if (MANGLE) { + TOPLEVEL.compute_char_frequency(MANGLE); + } + }); + } + + if (MANGLE) time_it("mangle", function(){ + TOPLEVEL.mangle_names(MANGLE); + }); + time_it("generate", function(){ + TOPLEVEL.print(output); + }); + + output = output.get(); + + if (SOURCE_MAP) { + fs.writeFileSync(ARGS.source_map, SOURCE_MAP, "utf8"); + output += "\n/*\n//@ sourceMappingURL=" + (ARGS.source_map_url || ARGS.source_map) + "\n*/"; + } + + if (OUTPUT_FILE) { + fs.writeFileSync(OUTPUT_FILE, output, "utf8"); + } else { + sys.print(output); + sys.error("\n"); + } + + if (ARGS.stats) { + sys.error(UglifyJS.string_template("Timing information (compressed {count} files):", { + count: files.length + })); + for (var i in STATS) if (STATS.hasOwnProperty(i)) { + sys.error(UglifyJS.string_template("- {name}: {time}s", { + name: i, + time: (STATS[i] / 1000).toFixed(3) + })); + } + } +}); + +/* -----[ functions ]----- */ + +function normalize(o) { + for (var i in o) if (o.hasOwnProperty(i) && /-/.test(i)) { + o[i.replace(/-/g, "_")] = o[i]; + delete o[i]; + } +} + +function getOptions(x, constants) { + x = ARGS[x]; + if (!x) return null; + var ret = {}; + if (x !== true) { + var ast; + try { + ast = UglifyJS.parse(x); + } catch(ex) { + if (ex instanceof UglifyJS.JS_Parse_Error) { + sys.error("Error parsing arguments in: " + x); + process.exit(1); + } + } + ast.walk(new UglifyJS.TreeWalker(function(node){ + if (node instanceof UglifyJS.AST_Toplevel) return; // descend + if (node instanceof UglifyJS.AST_SimpleStatement) return; // descend + if (node instanceof UglifyJS.AST_Seq) return; // descend + if (node instanceof UglifyJS.AST_Assign) { + var name = node.left.print_to_string({ beautify: false }).replace(/-/g, "_"); + var value = node.right; + if (constants) + value = new Function("return (" + value.print_to_string() + ")")(); + ret[name] = value; + return true; // no descend + } + sys.error(node.TYPE) + sys.error("Error parsing arguments in: " + x); + process.exit(1); + })); + } + return ret; +} + +function read_whole_file(filename, cb) { + if (filename == "-") { + var chunks = []; + process.stdin.setEncoding('utf-8'); + process.stdin.on('data', function (chunk) { + chunks.push(chunk); + }).on('end', function () { + cb(null, chunks.join("")); + }); + process.openStdin(); + } else { + fs.readFile(filename, "utf-8", cb); + } +} + +function time_it(name, cont) { + var t1 = new Date().getTime(); + var ret = cont(); + if (ARGS.stats) { + var spent = new Date().getTime() - t1; + if (STATS[name]) STATS[name] += spent; + else STATS[name] = spent; + } + return ret; +} diff --git a/homework8/project_express/node_modules/uglify-js/lib/ast.js b/homework8/project_express/node_modules/uglify-js/lib/ast.js new file mode 100644 index 0000000..a1301da --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/lib/ast.js @@ -0,0 +1,985 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function DEFNODE(type, props, methods, base) { + if (arguments.length < 4) base = AST_Node; + if (!props) props = []; + else props = props.split(/\s+/); + var self_props = props; + if (base && base.PROPS) + props = props.concat(base.PROPS); + var code = "return function AST_" + type + "(props){ if (props) { "; + for (var i = props.length; --i >= 0;) { + code += "this." + props[i] + " = props." + props[i] + ";"; + } + var proto = base && new base; + if (proto && proto.initialize || (methods && methods.initialize)) + code += "this.initialize();"; + code += "}}"; + var ctor = new Function(code)(); + if (proto) { + ctor.prototype = proto; + ctor.BASE = base; + } + if (base) base.SUBCLASSES.push(ctor); + ctor.prototype.CTOR = ctor; + ctor.PROPS = props || null; + ctor.SELF_PROPS = self_props; + ctor.SUBCLASSES = []; + if (type) { + ctor.prototype.TYPE = ctor.TYPE = type; + } + if (methods) for (i in methods) if (methods.hasOwnProperty(i)) { + if (/^\$/.test(i)) { + ctor[i.substr(1)] = methods[i]; + } else { + ctor.prototype[i] = methods[i]; + } + } + ctor.DEFMETHOD = function(name, method) { + this.prototype[name] = method; + }; + return ctor; +}; + +var AST_Token = DEFNODE("Token", "type value line col pos endpos nlb comments_before file", { +}, null); + +var AST_Node = DEFNODE("Node", "start end", { + clone: function() { + return new this.CTOR(this); + }, + $documentation: "Base class of all AST nodes", + $propdoc: { + start: "[AST_Token] The first token of this node", + end: "[AST_Token] The last token of this node" + }, + _walk: function(visitor) { + return visitor._visit(this); + }, + walk: function(visitor) { + return this._walk(visitor); // not sure the indirection will be any help + } +}, null); + +AST_Node.warn_function = null; +AST_Node.warn = function(txt, props) { + if (AST_Node.warn_function) + AST_Node.warn_function(string_template(txt, props)); +}; + +/* -----[ statements ]----- */ + +var AST_Statement = DEFNODE("Statement", null, { + $documentation: "Base class of all statements", +}); + +var AST_Debugger = DEFNODE("Debugger", null, { + $documentation: "Represents a debugger statement", +}, AST_Statement); + +var AST_Directive = DEFNODE("Directive", "value scope", { + $documentation: "Represents a directive, like \"use strict\";", + $propdoc: { + value: "[string] The value of this directive as a plain string (it's not an AST_String!)", + scope: "[AST_Scope/S] The scope that this directive affects" + }, +}, AST_Statement); + +var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", { + $documentation: "A statement consisting of an expression, i.e. a = 1 + 2", + $propdoc: { + body: "[AST_Node] an expression node (should not be instanceof AST_Statement)" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.body._walk(visitor); + }); + } +}, AST_Statement); + +function walk_body(node, visitor) { + if (node.body instanceof AST_Statement) { + node.body._walk(visitor); + } + else node.body.forEach(function(stat){ + stat._walk(visitor); + }); +}; + +var AST_Block = DEFNODE("Block", "body", { + $documentation: "A body of statements (usually bracketed)", + $propdoc: { + body: "[AST_Statement*] an array of statements" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + walk_body(this, visitor); + }); + } +}, AST_Statement); + +var AST_BlockStatement = DEFNODE("BlockStatement", null, { + $documentation: "A block statement", +}, AST_Block); + +var AST_EmptyStatement = DEFNODE("EmptyStatement", null, { + $documentation: "The empty statement (empty block or simply a semicolon)", + _walk: function(visitor) { + return visitor._visit(this); + } +}, AST_Statement); + +var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", { + $documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`", + $propdoc: { + body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.body._walk(visitor); + }); + } +}, AST_Statement); + +var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", { + $documentation: "Statement with a label", + $propdoc: { + label: "[AST_Label] a label definition" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.label._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_DWLoop = DEFNODE("DWLoop", "condition", { + $documentation: "Base class for do/while statements", + $propdoc: { + condition: "[AST_Node] the loop condition. Should not be instanceof AST_Statement" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.condition._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_Do = DEFNODE("Do", null, { + $documentation: "A `do` statement", +}, AST_DWLoop); + +var AST_While = DEFNODE("While", null, { + $documentation: "A `while` statement", +}, AST_DWLoop); + +var AST_For = DEFNODE("For", "init condition step", { + $documentation: "A `for` statement", + $propdoc: { + init: "[AST_Node?] the `for` initialization code, or null if empty", + condition: "[AST_Node?] the `for` termination clause, or null if empty", + step: "[AST_Node?] the `for` update clause, or null if empty" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + if (this.init) this.init._walk(visitor); + if (this.condition) this.condition._walk(visitor); + if (this.step) this.step._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_ForIn = DEFNODE("ForIn", "init name object", { + $documentation: "A `for ... in` statement", + $propdoc: { + init: "[AST_Node] the `for/in` initialization code", + name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var", + object: "[AST_Node] the object that we're looping through" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.init._walk(visitor); + this.object._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +var AST_With = DEFNODE("With", "expression", { + $documentation: "A `with` statement", + $propdoc: { + expression: "[AST_Node] the `with` expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + this.body._walk(visitor); + }); + } +}, AST_StatementWithBody); + +/* -----[ scope and functions ]----- */ + +var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", { + $documentation: "Base class for all statements introducing a lexical scope", + $propdoc: { + directives: "[string*/S] an array of directives declared in this scope", + variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope", + functions: "[Object/S] like `variables`, but only lists function declarations", + uses_with: "[boolean/S] tells whether this scope uses the `with` statement", + uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`", + parent_scope: "[AST_Scope?/S] link to the parent scope", + enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes", + cname: "[integer/S] current index for mangling variables (used internally by the mangler)", + }, +}, AST_Block); + +var AST_Toplevel = DEFNODE("Toplevel", "globals", { + $documentation: "The toplevel scope", + $propdoc: { + globals: "[Object/S] a map of name -> SymbolDef for all undeclared names", + }, + wrap_enclose: function(arg_parameter_pairs) { + var self = this; + var args = []; + var parameters = []; + + arg_parameter_pairs.forEach(function(pair) { + var split = pair.split(":"); + + args.push(split[0]); + parameters.push(split[1]); + }); + + var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")"; + wrapped_tl = parse(wrapped_tl); + wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){ + if (node instanceof AST_Directive && node.value == "$ORIG") { + return MAP.splice(self.body); + } + })); + return wrapped_tl; + }, + wrap_commonjs: function(name, export_all) { + var self = this; + var to_export = []; + if (export_all) { + self.figure_out_scope(); + self.walk(new TreeWalker(function(node){ + if (node instanceof AST_SymbolDeclaration && node.definition().global) { + if (!find_if(function(n){ return n.name == node.name }, to_export)) + to_export.push(node); + } + })); + } + var wrapped_tl = "(function(exports, global){ global['" + name + "'] = exports; '$ORIG'; '$EXPORTS'; }({}, (function(){return this}())))"; + wrapped_tl = parse(wrapped_tl); + wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){ + if (node instanceof AST_SimpleStatement) { + node = node.body; + if (node instanceof AST_String) switch (node.getValue()) { + case "$ORIG": + return MAP.splice(self.body); + case "$EXPORTS": + var body = []; + to_export.forEach(function(sym){ + body.push(new AST_SimpleStatement({ + body: new AST_Assign({ + left: new AST_Sub({ + expression: new AST_SymbolRef({ name: "exports" }), + property: new AST_String({ value: sym.name }), + }), + operator: "=", + right: new AST_SymbolRef(sym), + }), + })); + }); + return MAP.splice(body); + } + } + })); + return wrapped_tl; + } +}, AST_Scope); + +var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", { + $documentation: "Base class for functions", + $propdoc: { + name: "[AST_SymbolDeclaration?] the name of this function", + argnames: "[AST_SymbolFunarg*] array of function arguments", + uses_arguments: "[boolean/S] tells whether this function accesses the arguments array" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + if (this.name) this.name._walk(visitor); + this.argnames.forEach(function(arg){ + arg._walk(visitor); + }); + walk_body(this, visitor); + }); + } +}, AST_Scope); + +var AST_Accessor = DEFNODE("Accessor", null, { + $documentation: "A setter/getter function" +}, AST_Lambda); + +var AST_Function = DEFNODE("Function", null, { + $documentation: "A function expression" +}, AST_Lambda); + +var AST_Defun = DEFNODE("Defun", null, { + $documentation: "A function definition" +}, AST_Lambda); + +/* -----[ JUMPS ]----- */ + +var AST_Jump = DEFNODE("Jump", null, { + $documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)" +}, AST_Statement); + +var AST_Exit = DEFNODE("Exit", "value", { + $documentation: "Base class for “exits” (`return` and `throw`)", + $propdoc: { + value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return" + }, + _walk: function(visitor) { + return visitor._visit(this, this.value && function(){ + this.value._walk(visitor); + }); + } +}, AST_Jump); + +var AST_Return = DEFNODE("Return", null, { + $documentation: "A `return` statement" +}, AST_Exit); + +var AST_Throw = DEFNODE("Throw", null, { + $documentation: "A `throw` statement" +}, AST_Exit); + +var AST_LoopControl = DEFNODE("LoopControl", "label", { + $documentation: "Base class for loop control statements (`break` and `continue`)", + $propdoc: { + label: "[AST_LabelRef?] the label, or null if none", + }, + _walk: function(visitor) { + return visitor._visit(this, this.label && function(){ + this.label._walk(visitor); + }); + } +}, AST_Jump); + +var AST_Break = DEFNODE("Break", null, { + $documentation: "A `break` statement" +}, AST_LoopControl); + +var AST_Continue = DEFNODE("Continue", null, { + $documentation: "A `continue` statement" +}, AST_LoopControl); + +/* -----[ IF ]----- */ + +var AST_If = DEFNODE("If", "condition alternative", { + $documentation: "A `if` statement", + $propdoc: { + condition: "[AST_Node] the `if` condition", + alternative: "[AST_Statement?] the `else` part, or null if not present" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.condition._walk(visitor); + this.body._walk(visitor); + if (this.alternative) this.alternative._walk(visitor); + }); + } +}, AST_StatementWithBody); + +/* -----[ SWITCH ]----- */ + +var AST_Switch = DEFNODE("Switch", "expression", { + $documentation: "A `switch` statement", + $propdoc: { + expression: "[AST_Node] the `switch` “discriminant”" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + walk_body(this, visitor); + }); + } +}, AST_Block); + +var AST_SwitchBranch = DEFNODE("SwitchBranch", null, { + $documentation: "Base class for `switch` branches", +}, AST_Block); + +var AST_Default = DEFNODE("Default", null, { + $documentation: "A `default` switch branch", +}, AST_SwitchBranch); + +var AST_Case = DEFNODE("Case", "expression", { + $documentation: "A `case` switch branch", + $propdoc: { + expression: "[AST_Node] the `case` expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + walk_body(this, visitor); + }); + } +}, AST_SwitchBranch); + +/* -----[ EXCEPTIONS ]----- */ + +var AST_Try = DEFNODE("Try", "bcatch bfinally", { + $documentation: "A `try` statement", + $propdoc: { + bcatch: "[AST_Catch?] the catch block, or null if not present", + bfinally: "[AST_Finally?] the finally block, or null if not present" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + walk_body(this, visitor); + if (this.bcatch) this.bcatch._walk(visitor); + if (this.bfinally) this.bfinally._walk(visitor); + }); + } +}, AST_Block); + +// XXX: this is wrong according to ECMA-262 (12.4). the catch block +// should introduce another scope, as the argname should be visible +// only inside the catch block. However, doing it this way because of +// IE which simply introduces the name in the surrounding scope. If +// we ever want to fix this then AST_Catch should inherit from +// AST_Scope. +var AST_Catch = DEFNODE("Catch", "argname", { + $documentation: "A `catch` node; only makes sense as part of a `try` statement", + $propdoc: { + argname: "[AST_SymbolCatch] symbol for the exception" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.argname._walk(visitor); + walk_body(this, visitor); + }); + } +}, AST_Block); + +var AST_Finally = DEFNODE("Finally", null, { + $documentation: "A `finally` node; only makes sense as part of a `try` statement" +}, AST_Block); + +/* -----[ VAR/CONST ]----- */ + +var AST_Definitions = DEFNODE("Definitions", "definitions", { + $documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)", + $propdoc: { + definitions: "[AST_VarDef*] array of variable definitions" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.definitions.forEach(function(def){ + def._walk(visitor); + }); + }); + } +}, AST_Statement); + +var AST_Var = DEFNODE("Var", null, { + $documentation: "A `var` statement" +}, AST_Definitions); + +var AST_Const = DEFNODE("Const", null, { + $documentation: "A `const` statement" +}, AST_Definitions); + +var AST_VarDef = DEFNODE("VarDef", "name value", { + $documentation: "A variable declaration; only appears in a AST_Definitions node", + $propdoc: { + name: "[AST_SymbolVar|AST_SymbolConst] name of the variable", + value: "[AST_Node?] initializer, or null of there's no initializer" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.name._walk(visitor); + if (this.value) this.value._walk(visitor); + }); + } +}); + +/* -----[ OTHER ]----- */ + +var AST_Call = DEFNODE("Call", "expression args", { + $documentation: "A function call expression", + $propdoc: { + expression: "[AST_Node] expression to invoke as function", + args: "[AST_Node*] array of arguments" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + this.args.forEach(function(arg){ + arg._walk(visitor); + }); + }); + } +}); + +var AST_New = DEFNODE("New", null, { + $documentation: "An object instantiation. Derives from a function call since it has exactly the same properties" +}, AST_Call); + +var AST_Seq = DEFNODE("Seq", "car cdr", { + $documentation: "A sequence expression (two comma-separated expressions)", + $propdoc: { + car: "[AST_Node] first element in sequence", + cdr: "[AST_Node] second element in sequence" + }, + $cons: function(x, y) { + var seq = new AST_Seq(x); + seq.car = x; + seq.cdr = y; + return seq; + }, + $from_array: function(array) { + if (array.length == 0) return null; + if (array.length == 1) return array[0].clone(); + var list = null; + for (var i = array.length; --i >= 0;) { + list = AST_Seq.cons(array[i], list); + } + var p = list; + while (p) { + if (p.cdr && !p.cdr.cdr) { + p.cdr = p.cdr.car; + break; + } + p = p.cdr; + } + return list; + }, + to_array: function() { + var p = this, a = []; + while (p) { + a.push(p.car); + if (p.cdr && !(p.cdr instanceof AST_Seq)) { + a.push(p.cdr); + break; + } + p = p.cdr; + } + return a; + }, + add: function(node) { + var p = this; + while (p) { + if (!(p.cdr instanceof AST_Seq)) { + var cell = AST_Seq.cons(p.cdr, node); + return p.cdr = cell; + } + p = p.cdr; + } + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.car._walk(visitor); + if (this.cdr) this.cdr._walk(visitor); + }); + } +}); + +var AST_PropAccess = DEFNODE("PropAccess", "expression property", { + $documentation: "Base class for property access expressions, i.e. `a.foo` or `a[\"foo\"]`", + $propdoc: { + expression: "[AST_Node] the “container” expression", + property: "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node" + } +}); + +var AST_Dot = DEFNODE("Dot", null, { + $documentation: "A dotted property access expression", + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + }); + } +}, AST_PropAccess); + +var AST_Sub = DEFNODE("Sub", null, { + $documentation: "Index-style property access, i.e. `a[\"foo\"]`", + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + this.property._walk(visitor); + }); + } +}, AST_PropAccess); + +var AST_Unary = DEFNODE("Unary", "operator expression", { + $documentation: "Base class for unary expressions", + $propdoc: { + operator: "[string] the operator", + expression: "[AST_Node] expression that this unary operator applies to" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.expression._walk(visitor); + }); + } +}); + +var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, { + $documentation: "Unary prefix expression, i.e. `typeof i` or `++i`" +}, AST_Unary); + +var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, { + $documentation: "Unary postfix expression, i.e. `i++`" +}, AST_Unary); + +var AST_Binary = DEFNODE("Binary", "left operator right", { + $documentation: "Binary expression, i.e. `a + b`", + $propdoc: { + left: "[AST_Node] left-hand side expression", + operator: "[string] the operator", + right: "[AST_Node] right-hand side expression" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.left._walk(visitor); + this.right._walk(visitor); + }); + } +}); + +var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", { + $documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`", + $propdoc: { + condition: "[AST_Node]", + consequent: "[AST_Node]", + alternative: "[AST_Node]" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.condition._walk(visitor); + this.consequent._walk(visitor); + this.alternative._walk(visitor); + }); + } +}); + +var AST_Assign = DEFNODE("Assign", null, { + $documentation: "An assignment expression — `a = b + 5`", +}, AST_Binary); + +/* -----[ LITERALS ]----- */ + +var AST_Array = DEFNODE("Array", "elements", { + $documentation: "An array literal", + $propdoc: { + elements: "[AST_Node*] array of elements" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.elements.forEach(function(el){ + el._walk(visitor); + }); + }); + } +}); + +var AST_Object = DEFNODE("Object", "properties", { + $documentation: "An object literal", + $propdoc: { + properties: "[AST_ObjectProperty*] array of properties" + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.properties.forEach(function(prop){ + prop._walk(visitor); + }); + }); + } +}); + +var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", { + $documentation: "Base class for literal object properties", + $propdoc: { + key: "[string] the property name; it's always a plain string in our AST, no matter if it was a string, number or identifier in original code", + value: "[AST_Node] property value. For setters and getters this is an AST_Function." + }, + _walk: function(visitor) { + return visitor._visit(this, function(){ + this.value._walk(visitor); + }); + } +}); + +var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", null, { + $documentation: "A key: value object property", +}, AST_ObjectProperty); + +var AST_ObjectSetter = DEFNODE("ObjectSetter", null, { + $documentation: "An object setter property", +}, AST_ObjectProperty); + +var AST_ObjectGetter = DEFNODE("ObjectGetter", null, { + $documentation: "An object getter property", +}, AST_ObjectProperty); + +var AST_Symbol = DEFNODE("Symbol", "scope name thedef", { + $propdoc: { + name: "[string] name of this symbol", + scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)", + thedef: "[SymbolDef/S] the definition of this symbol" + }, + $documentation: "Base class for all symbols", +}); + +var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, { + $documentation: "The name of a property accessor (setter/getter function)" +}, AST_Symbol); + +var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", { + $documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)", + $propdoc: { + init: "[AST_Node*/S] array of initializers for this declaration." + } +}, AST_Symbol); + +var AST_SymbolVar = DEFNODE("SymbolVar", null, { + $documentation: "Symbol defining a variable", +}, AST_SymbolDeclaration); + +var AST_SymbolConst = DEFNODE("SymbolConst", null, { + $documentation: "A constant declaration" +}, AST_SymbolDeclaration); + +var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, { + $documentation: "Symbol naming a function argument", +}, AST_SymbolVar); + +var AST_SymbolDefun = DEFNODE("SymbolDefun", null, { + $documentation: "Symbol defining a function", +}, AST_SymbolDeclaration); + +var AST_SymbolLambda = DEFNODE("SymbolLambda", null, { + $documentation: "Symbol naming a function expression", +}, AST_SymbolDeclaration); + +var AST_SymbolCatch = DEFNODE("SymbolCatch", null, { + $documentation: "Symbol naming the exception in catch", +}, AST_SymbolDeclaration); + +var AST_Label = DEFNODE("Label", "references", { + $documentation: "Symbol naming a label (declaration)", + $propdoc: { + references: "[AST_LabelRef*] a list of nodes referring to this label" + } +}, AST_Symbol); + +var AST_SymbolRef = DEFNODE("SymbolRef", null, { + $documentation: "Reference to some symbol (not definition/declaration)", +}, AST_Symbol); + +var AST_LabelRef = DEFNODE("LabelRef", null, { + $documentation: "Reference to a label symbol", +}, AST_Symbol); + +var AST_This = DEFNODE("This", null, { + $documentation: "The `this` symbol", +}, AST_Symbol); + +var AST_Constant = DEFNODE("Constant", null, { + $documentation: "Base class for all constants", + getValue: function() { + return this.value; + } +}); + +var AST_String = DEFNODE("String", "value", { + $documentation: "A string literal", + $propdoc: { + value: "[string] the contents of this string" + } +}, AST_Constant); + +var AST_Number = DEFNODE("Number", "value", { + $documentation: "A number literal", + $propdoc: { + value: "[number] the numeric value" + } +}, AST_Constant); + +var AST_RegExp = DEFNODE("RegExp", "value", { + $documentation: "A regexp literal", + $propdoc: { + value: "[RegExp] the actual regexp" + } +}, AST_Constant); + +var AST_Atom = DEFNODE("Atom", null, { + $documentation: "Base class for atoms", +}, AST_Constant); + +var AST_Null = DEFNODE("Null", null, { + $documentation: "The `null` atom", + value: null +}, AST_Atom); + +var AST_NaN = DEFNODE("NaN", null, { + $documentation: "The impossible value", + value: 0/0 +}, AST_Atom); + +var AST_Undefined = DEFNODE("Undefined", null, { + $documentation: "The `undefined` value", + value: (function(){}()) +}, AST_Atom); + +var AST_Hole = DEFNODE("Hole", null, { + $documentation: "A hole in an array", + value: (function(){}()) +}, AST_Atom); + +var AST_Infinity = DEFNODE("Infinity", null, { + $documentation: "The `Infinity` value", + value: 1/0 +}, AST_Atom); + +var AST_Boolean = DEFNODE("Boolean", null, { + $documentation: "Base class for booleans", +}, AST_Atom); + +var AST_False = DEFNODE("False", null, { + $documentation: "The `false` atom", + value: false +}, AST_Boolean); + +var AST_True = DEFNODE("True", null, { + $documentation: "The `true` atom", + value: true +}, AST_Boolean); + +/* -----[ TreeWalker ]----- */ + +function TreeWalker(callback) { + this.visit = callback; + this.stack = []; +}; +TreeWalker.prototype = { + _visit: function(node, descend) { + this.stack.push(node); + var ret = this.visit(node, descend ? function(){ + descend.call(node); + } : noop); + if (!ret && descend) { + descend.call(node); + } + this.stack.pop(); + return ret; + }, + parent: function(n) { + return this.stack[this.stack.length - 2 - (n || 0)]; + }, + push: function (node) { + this.stack.push(node); + }, + pop: function() { + return this.stack.pop(); + }, + self: function() { + return this.stack[this.stack.length - 1]; + }, + find_parent: function(type) { + var stack = this.stack; + for (var i = stack.length; --i >= 0;) { + var x = stack[i]; + if (x instanceof type) return x; + } + }, + in_boolean_context: function() { + var stack = this.stack; + var i = stack.length, self = stack[--i]; + while (i > 0) { + var p = stack[--i]; + if ((p instanceof AST_If && p.condition === self) || + (p instanceof AST_Conditional && p.condition === self) || + (p instanceof AST_DWLoop && p.condition === self) || + (p instanceof AST_For && p.condition === self) || + (p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self)) + { + return true; + } + if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||"))) + return false; + self = p; + } + }, + loopcontrol_target: function(label) { + var stack = this.stack; + if (label) { + for (var i = stack.length; --i >= 0;) { + var x = stack[i]; + if (x instanceof AST_LabeledStatement && x.label.name == label.name) { + return x.body; + } + } + } else { + for (var i = stack.length; --i >= 0;) { + var x = stack[i]; + if (x instanceof AST_Switch + || x instanceof AST_For + || x instanceof AST_ForIn + || x instanceof AST_DWLoop) return x; + } + } + } +}; diff --git a/homework8/project_express/node_modules/uglify-js/lib/compress.js b/homework8/project_express/node_modules/uglify-js/lib/compress.js new file mode 100644 index 0000000..ebd3dd7 --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/lib/compress.js @@ -0,0 +1,1985 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function Compressor(options, false_by_default) { + if (!(this instanceof Compressor)) + return new Compressor(options, false_by_default); + TreeTransformer.call(this, this.before, this.after); + this.options = defaults(options, { + sequences : !false_by_default, + properties : !false_by_default, + dead_code : !false_by_default, + drop_debugger : !false_by_default, + unsafe : false, + unsafe_comps : false, + conditionals : !false_by_default, + comparisons : !false_by_default, + evaluate : !false_by_default, + booleans : !false_by_default, + loops : !false_by_default, + unused : !false_by_default, + hoist_funs : !false_by_default, + hoist_vars : false, + if_return : !false_by_default, + join_vars : !false_by_default, + cascade : !false_by_default, + side_effects : !false_by_default, + screw_ie8 : false, + + warnings : true, + global_defs : {} + }, true); +}; + +Compressor.prototype = new TreeTransformer; +merge(Compressor.prototype, { + option: function(key) { return this.options[key] }, + warn: function() { + if (this.options.warnings) + AST_Node.warn.apply(AST_Node, arguments); + }, + before: function(node, descend, in_list) { + if (node._squeezed) return node; + if (node instanceof AST_Scope) { + node.drop_unused(this); + node = node.hoist_declarations(this); + } + descend(node, this); + node = node.optimize(this); + if (node instanceof AST_Scope) { + // dead code removal might leave further unused declarations. + // this'll usually save very few bytes, but the performance + // hit seems negligible so I'll just drop it here. + + // no point to repeat warnings. + var save_warnings = this.options.warnings; + this.options.warnings = false; + node.drop_unused(this); + this.options.warnings = save_warnings; + } + node._squeezed = true; + return node; + } +}); + +(function(){ + + function OPT(node, optimizer) { + node.DEFMETHOD("optimize", function(compressor){ + var self = this; + if (self._optimized) return self; + var opt = optimizer(self, compressor); + opt._optimized = true; + if (opt === self) return opt; + return opt.transform(compressor); + }); + }; + + OPT(AST_Node, function(self, compressor){ + return self; + }); + + AST_Node.DEFMETHOD("equivalent_to", function(node){ + // XXX: this is a rather expensive way to test two node's equivalence: + return this.print_to_string() == node.print_to_string(); + }); + + function make_node(ctor, orig, props) { + if (!props) props = {}; + if (orig) { + if (!props.start) props.start = orig.start; + if (!props.end) props.end = orig.end; + } + return new ctor(props); + }; + + function make_node_from_constant(compressor, val, orig) { + // XXX: WIP. + // if (val instanceof AST_Node) return val.transform(new TreeTransformer(null, function(node){ + // if (node instanceof AST_SymbolRef) { + // var scope = compressor.find_parent(AST_Scope); + // var def = scope.find_variable(node); + // node.thedef = def; + // return node; + // } + // })).transform(compressor); + + if (val instanceof AST_Node) return val.transform(compressor); + switch (typeof val) { + case "string": + return make_node(AST_String, orig, { + value: val + }).optimize(compressor); + case "number": + return make_node(isNaN(val) ? AST_NaN : AST_Number, orig, { + value: val + }).optimize(compressor); + case "boolean": + return make_node(val ? AST_True : AST_False, orig).optimize(compressor); + case "undefined": + return make_node(AST_Undefined, orig).optimize(compressor); + default: + if (val === null) { + return make_node(AST_Null, orig).optimize(compressor); + } + if (val instanceof RegExp) { + return make_node(AST_RegExp, orig).optimize(compressor); + } + throw new Error(string_template("Can't handle constant of type: {type}", { + type: typeof val + })); + } + }; + + function as_statement_array(thing) { + if (thing === null) return []; + if (thing instanceof AST_BlockStatement) return thing.body; + if (thing instanceof AST_EmptyStatement) return []; + if (thing instanceof AST_Statement) return [ thing ]; + throw new Error("Can't convert thing to statement array"); + }; + + function is_empty(thing) { + if (thing === null) return true; + if (thing instanceof AST_EmptyStatement) return true; + if (thing instanceof AST_BlockStatement) return thing.body.length == 0; + return false; + }; + + function loop_body(x) { + if (x instanceof AST_Switch) return x; + if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) { + return (x.body instanceof AST_BlockStatement ? x.body : x); + } + return x; + }; + + function tighten_body(statements, compressor) { + var CHANGED; + do { + CHANGED = false; + statements = eliminate_spurious_blocks(statements); + if (compressor.option("dead_code")) { + statements = eliminate_dead_code(statements, compressor); + } + if (compressor.option("if_return")) { + statements = handle_if_return(statements, compressor); + } + if (compressor.option("sequences")) { + statements = sequencesize(statements, compressor); + } + if (compressor.option("join_vars")) { + statements = join_consecutive_vars(statements, compressor); + } + } while (CHANGED); + return statements; + + function eliminate_spurious_blocks(statements) { + var seen_dirs = []; + return statements.reduce(function(a, stat){ + if (stat instanceof AST_BlockStatement) { + CHANGED = true; + a.push.apply(a, eliminate_spurious_blocks(stat.body)); + } else if (stat instanceof AST_EmptyStatement) { + CHANGED = true; + } else if (stat instanceof AST_Directive) { + if (seen_dirs.indexOf(stat.value) < 0) { + a.push(stat); + seen_dirs.push(stat.value); + } else { + CHANGED = true; + } + } else { + a.push(stat); + } + return a; + }, []); + }; + + function handle_if_return(statements, compressor) { + var self = compressor.self(); + var in_lambda = self instanceof AST_Lambda; + var ret = []; + loop: for (var i = statements.length; --i >= 0;) { + var stat = statements[i]; + switch (true) { + case (in_lambda && stat instanceof AST_Return && !stat.value && ret.length == 0): + CHANGED = true; + // note, ret.length is probably always zero + // because we drop unreachable code before this + // step. nevertheless, it's good to check. + continue loop; + case stat instanceof AST_If: + if (stat.body instanceof AST_Return) { + //--- + // pretty silly case, but: + // if (foo()) return; return; ==> foo(); return; + if (((in_lambda && ret.length == 0) + || (ret[0] instanceof AST_Return && !ret[0].value)) + && !stat.body.value && !stat.alternative) { + CHANGED = true; + var cond = make_node(AST_SimpleStatement, stat.condition, { + body: stat.condition + }); + ret.unshift(cond); + continue loop; + } + //--- + // if (foo()) return x; return y; ==> return foo() ? x : y; + if (ret[0] instanceof AST_Return && stat.body.value && ret[0].value && !stat.alternative) { + CHANGED = true; + stat = stat.clone(); + stat.alternative = ret[0]; + ret[0] = stat.transform(compressor); + continue loop; + } + //--- + // if (foo()) return x; [ return ; ] ==> return foo() ? x : undefined; + if ((ret.length == 0 || ret[0] instanceof AST_Return) && stat.body.value && !stat.alternative && in_lambda) { + CHANGED = true; + stat = stat.clone(); + stat.alternative = ret[0] || make_node(AST_Return, stat, { + value: make_node(AST_Undefined, stat) + }); + ret[0] = stat.transform(compressor); + continue loop; + } + //--- + // if (foo()) return; [ else x... ]; y... ==> if (!foo()) { x...; y... } + if (!stat.body.value && in_lambda) { + CHANGED = true; + stat = stat.clone(); + stat.condition = stat.condition.negate(compressor); + stat.body = make_node(AST_BlockStatement, stat, { + body: as_statement_array(stat.alternative).concat(ret) + }); + stat.alternative = null; + ret = [ stat.transform(compressor) ]; + continue loop; + } + //--- + if (ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement + && (!stat.alternative || stat.alternative instanceof AST_SimpleStatement)) { + CHANGED = true; + ret.push(make_node(AST_Return, ret[0], { + value: make_node(AST_Undefined, ret[0]) + }).transform(compressor)); + ret = as_statement_array(stat.alternative).concat(ret); + ret.unshift(stat); + continue loop; + } + } + + var ab = aborts(stat.body); + var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null; + if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda) + || (ab instanceof AST_Continue && self === loop_body(lct)) + || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) { + if (ab.label) { + remove(ab.label.thedef.references, ab.label); + } + CHANGED = true; + var body = as_statement_array(stat.body).slice(0, -1); + stat = stat.clone(); + stat.condition = stat.condition.negate(compressor); + stat.body = make_node(AST_BlockStatement, stat, { + body: ret + }); + stat.alternative = make_node(AST_BlockStatement, stat, { + body: body + }); + ret = [ stat.transform(compressor) ]; + continue loop; + } + + var ab = aborts(stat.alternative); + var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null; + if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda) + || (ab instanceof AST_Continue && self === loop_body(lct)) + || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) { + if (ab.label) { + remove(ab.label.thedef.references, ab.label); + } + CHANGED = true; + stat = stat.clone(); + stat.body = make_node(AST_BlockStatement, stat.body, { + body: as_statement_array(stat.body).concat(ret) + }); + stat.alternative = make_node(AST_BlockStatement, stat.alternative, { + body: as_statement_array(stat.alternative).slice(0, -1) + }); + ret = [ stat.transform(compressor) ]; + continue loop; + } + + ret.unshift(stat); + break; + default: + ret.unshift(stat); + break; + } + } + return ret; + }; + + function eliminate_dead_code(statements, compressor) { + var has_quit = false; + var orig = statements.length; + var self = compressor.self(); + statements = statements.reduce(function(a, stat){ + if (has_quit) { + extract_declarations_from_unreachable_code(compressor, stat, a); + } else { + if (stat instanceof AST_LoopControl) { + var lct = compressor.loopcontrol_target(stat.label); + if ((stat instanceof AST_Break + && lct instanceof AST_BlockStatement + && loop_body(lct) === self) || (stat instanceof AST_Continue + && loop_body(lct) === self)) { + if (stat.label) { + remove(stat.label.thedef.references, stat.label); + } + } else { + a.push(stat); + } + } else { + a.push(stat); + } + if (aborts(stat)) has_quit = true; + } + return a; + }, []); + CHANGED = statements.length != orig; + return statements; + }; + + function sequencesize(statements, compressor) { + if (statements.length < 2) return statements; + var seq = [], ret = []; + function push_seq() { + seq = AST_Seq.from_array(seq); + if (seq) ret.push(make_node(AST_SimpleStatement, seq, { + body: seq + })); + seq = []; + }; + statements.forEach(function(stat){ + if (stat instanceof AST_SimpleStatement) seq.push(stat.body); + else push_seq(), ret.push(stat); + }); + push_seq(); + ret = sequencesize_2(ret, compressor); + CHANGED = ret.length != statements.length; + return ret; + }; + + function sequencesize_2(statements, compressor) { + function cons_seq(right) { + ret.pop(); + var left = prev.body; + if (left instanceof AST_Seq) { + left.add(right); + } else { + left = AST_Seq.cons(left, right); + } + return left.transform(compressor); + }; + var ret = [], prev = null; + statements.forEach(function(stat){ + if (prev) { + if (stat instanceof AST_For) { + var opera = {}; + try { + prev.body.walk(new TreeWalker(function(node){ + if (node instanceof AST_Binary && node.operator == "in") + throw opera; + })); + if (stat.init && !(stat.init instanceof AST_Definitions)) { + stat.init = cons_seq(stat.init); + } + else if (!stat.init) { + stat.init = prev.body; + ret.pop(); + } + } catch(ex) { + if (ex !== opera) throw ex; + } + } + else if (stat instanceof AST_If) { + stat.condition = cons_seq(stat.condition); + } + else if (stat instanceof AST_With) { + stat.expression = cons_seq(stat.expression); + } + else if (stat instanceof AST_Exit && stat.value) { + stat.value = cons_seq(stat.value); + } + else if (stat instanceof AST_Exit) { + stat.value = cons_seq(make_node(AST_Undefined, stat)); + } + else if (stat instanceof AST_Switch) { + stat.expression = cons_seq(stat.expression); + } + } + ret.push(stat); + prev = stat instanceof AST_SimpleStatement ? stat : null; + }); + return ret; + }; + + function join_consecutive_vars(statements, compressor) { + var prev = null; + return statements.reduce(function(a, stat){ + if (stat instanceof AST_Definitions && prev && prev.TYPE == stat.TYPE) { + prev.definitions = prev.definitions.concat(stat.definitions); + CHANGED = true; + } + else if (stat instanceof AST_For + && prev instanceof AST_Definitions + && (!stat.init || stat.init.TYPE == prev.TYPE)) { + CHANGED = true; + a.pop(); + if (stat.init) { + stat.init.definitions = prev.definitions.concat(stat.init.definitions); + } else { + stat.init = prev; + } + a.push(stat); + prev = stat; + } + else { + prev = stat; + a.push(stat); + } + return a; + }, []); + }; + + }; + + function extract_declarations_from_unreachable_code(compressor, stat, target) { + compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start); + stat.walk(new TreeWalker(function(node){ + if (node instanceof AST_Definitions) { + compressor.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start); + node.remove_initializers(); + target.push(node); + return true; + } + if (node instanceof AST_Defun) { + target.push(node); + return true; + } + if (node instanceof AST_Scope) { + return true; + } + })); + }; + + /* -----[ boolean/negation helpers ]----- */ + + // methods to determine whether an expression has a boolean result type + (function (def){ + var unary_bool = [ "!", "delete" ]; + var binary_bool = [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ]; + def(AST_Node, function(){ return false }); + def(AST_UnaryPrefix, function(){ + return member(this.operator, unary_bool); + }); + def(AST_Binary, function(){ + return member(this.operator, binary_bool) || + ( (this.operator == "&&" || this.operator == "||") && + this.left.is_boolean() && this.right.is_boolean() ); + }); + def(AST_Conditional, function(){ + return this.consequent.is_boolean() && this.alternative.is_boolean(); + }); + def(AST_Assign, function(){ + return this.operator == "=" && this.right.is_boolean(); + }); + def(AST_Seq, function(){ + return this.cdr.is_boolean(); + }); + def(AST_True, function(){ return true }); + def(AST_False, function(){ return true }); + })(function(node, func){ + node.DEFMETHOD("is_boolean", func); + }); + + // methods to determine if an expression has a string result type + (function (def){ + def(AST_Node, function(){ return false }); + def(AST_String, function(){ return true }); + def(AST_UnaryPrefix, function(){ + return this.operator == "typeof"; + }); + def(AST_Binary, function(compressor){ + return this.operator == "+" && + (this.left.is_string(compressor) || this.right.is_string(compressor)); + }); + def(AST_Assign, function(compressor){ + return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor); + }); + def(AST_Seq, function(compressor){ + return this.cdr.is_string(compressor); + }); + def(AST_Conditional, function(compressor){ + return this.consequent.is_string(compressor) && this.alternative.is_string(compressor); + }); + def(AST_Call, function(compressor){ + return compressor.option("unsafe") + && this.expression instanceof AST_SymbolRef + && this.expression.name == "String" + && this.expression.undeclared(); + }); + })(function(node, func){ + node.DEFMETHOD("is_string", func); + }); + + function best_of(ast1, ast2) { + return ast1.print_to_string().length > + ast2.print_to_string().length + ? ast2 : ast1; + }; + + // methods to evaluate a constant expression + (function (def){ + // The evaluate method returns an array with one or two + // elements. If the node has been successfully reduced to a + // constant, then the second element tells us the value; + // otherwise the second element is missing. The first element + // of the array is always an AST_Node descendant; when + // evaluation was successful it's a node that represents the + // constant; otherwise it's the original node. + AST_Node.DEFMETHOD("evaluate", function(compressor){ + if (!compressor.option("evaluate")) return [ this ]; + try { + var val = this._eval(), ast = make_node_from_constant(compressor, val, this); + return [ best_of(ast, this), val ]; + } catch(ex) { + if (ex !== def) throw ex; + return [ this ]; + } + }); + def(AST_Statement, function(){ + throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start)); + }); + def(AST_Function, function(){ + // XXX: AST_Function inherits from AST_Scope, which itself + // inherits from AST_Statement; however, an AST_Function + // isn't really a statement. This could byte in other + // places too. :-( Wish JS had multiple inheritance. + return [ this ]; + }); + function ev(node) { + return node._eval(); + }; + def(AST_Node, function(){ + throw def; // not constant + }); + def(AST_Constant, function(){ + return this.getValue(); + }); + def(AST_UnaryPrefix, function(){ + var e = this.expression; + switch (this.operator) { + case "!": return !ev(e); + case "typeof": + // Function would be evaluated to an array and so typeof would + // incorrectly return 'object'. Hence making is a special case. + if (e instanceof AST_Function) return typeof function(){}; + + e = ev(e); + + // typeof returns "object" or "function" on different platforms + // so cannot evaluate reliably + if (e instanceof RegExp) throw def; + + return typeof e; + case "void": return void ev(e); + case "~": return ~ev(e); + case "-": + e = ev(e); + if (e === 0) throw def; + return -e; + case "+": return +ev(e); + } + throw def; + }); + def(AST_Binary, function(){ + var left = this.left, right = this.right; + switch (this.operator) { + case "&&" : return ev(left) && ev(right); + case "||" : return ev(left) || ev(right); + case "|" : return ev(left) | ev(right); + case "&" : return ev(left) & ev(right); + case "^" : return ev(left) ^ ev(right); + case "+" : return ev(left) + ev(right); + case "*" : return ev(left) * ev(right); + case "/" : return ev(left) / ev(right); + case "%" : return ev(left) % ev(right); + case "-" : return ev(left) - ev(right); + case "<<" : return ev(left) << ev(right); + case ">>" : return ev(left) >> ev(right); + case ">>>" : return ev(left) >>> ev(right); + case "==" : return ev(left) == ev(right); + case "===" : return ev(left) === ev(right); + case "!=" : return ev(left) != ev(right); + case "!==" : return ev(left) !== ev(right); + case "<" : return ev(left) < ev(right); + case "<=" : return ev(left) <= ev(right); + case ">" : return ev(left) > ev(right); + case ">=" : return ev(left) >= ev(right); + case "in" : return ev(left) in ev(right); + case "instanceof" : return ev(left) instanceof ev(right); + } + throw def; + }); + def(AST_Conditional, function(){ + return ev(this.condition) + ? ev(this.consequent) + : ev(this.alternative); + }); + def(AST_SymbolRef, function(){ + var d = this.definition(); + if (d && d.constant && d.init) return ev(d.init); + throw def; + }); + })(function(node, func){ + node.DEFMETHOD("_eval", func); + }); + + // method to negate an expression + (function(def){ + function basic_negation(exp) { + return make_node(AST_UnaryPrefix, exp, { + operator: "!", + expression: exp + }); + }; + def(AST_Node, function(){ + return basic_negation(this); + }); + def(AST_Statement, function(){ + throw new Error("Cannot negate a statement"); + }); + def(AST_Function, function(){ + return basic_negation(this); + }); + def(AST_UnaryPrefix, function(){ + if (this.operator == "!") + return this.expression; + return basic_negation(this); + }); + def(AST_Seq, function(compressor){ + var self = this.clone(); + self.cdr = self.cdr.negate(compressor); + return self; + }); + def(AST_Conditional, function(compressor){ + var self = this.clone(); + self.consequent = self.consequent.negate(compressor); + self.alternative = self.alternative.negate(compressor); + return best_of(basic_negation(this), self); + }); + def(AST_Binary, function(compressor){ + var self = this.clone(), op = this.operator; + if (compressor.option("unsafe_comps")) { + switch (op) { + case "<=" : self.operator = ">" ; return self; + case "<" : self.operator = ">=" ; return self; + case ">=" : self.operator = "<" ; return self; + case ">" : self.operator = "<=" ; return self; + } + } + switch (op) { + case "==" : self.operator = "!="; return self; + case "!=" : self.operator = "=="; return self; + case "===": self.operator = "!=="; return self; + case "!==": self.operator = "==="; return self; + case "&&": + self.operator = "||"; + self.left = self.left.negate(compressor); + self.right = self.right.negate(compressor); + return best_of(basic_negation(this), self); + case "||": + self.operator = "&&"; + self.left = self.left.negate(compressor); + self.right = self.right.negate(compressor); + return best_of(basic_negation(this), self); + } + return basic_negation(this); + }); + })(function(node, func){ + node.DEFMETHOD("negate", function(compressor){ + return func.call(this, compressor); + }); + }); + + // determine if expression has side effects + (function(def){ + def(AST_Node, function(){ return true }); + + def(AST_EmptyStatement, function(){ return false }); + def(AST_Constant, function(){ return false }); + def(AST_This, function(){ return false }); + + def(AST_Block, function(){ + for (var i = this.body.length; --i >= 0;) { + if (this.body[i].has_side_effects()) + return true; + } + return false; + }); + + def(AST_SimpleStatement, function(){ + return this.body.has_side_effects(); + }); + def(AST_Defun, function(){ return true }); + def(AST_Function, function(){ return false }); + def(AST_Binary, function(){ + return this.left.has_side_effects() + || this.right.has_side_effects(); + }); + def(AST_Assign, function(){ return true }); + def(AST_Conditional, function(){ + return this.condition.has_side_effects() + || this.consequent.has_side_effects() + || this.alternative.has_side_effects(); + }); + def(AST_Unary, function(){ + return this.operator == "delete" + || this.operator == "++" + || this.operator == "--" + || this.expression.has_side_effects(); + }); + def(AST_SymbolRef, function(){ return false }); + def(AST_Object, function(){ + for (var i = this.properties.length; --i >= 0;) + if (this.properties[i].has_side_effects()) + return true; + return false; + }); + def(AST_ObjectProperty, function(){ + return this.value.has_side_effects(); + }); + def(AST_Array, function(){ + for (var i = this.elements.length; --i >= 0;) + if (this.elements[i].has_side_effects()) + return true; + return false; + }); + // def(AST_Dot, function(){ + // return this.expression.has_side_effects(); + // }); + // def(AST_Sub, function(){ + // return this.expression.has_side_effects() + // || this.property.has_side_effects(); + // }); + def(AST_PropAccess, function(){ + return true; + }); + def(AST_Seq, function(){ + return this.car.has_side_effects() + || this.cdr.has_side_effects(); + }); + })(function(node, func){ + node.DEFMETHOD("has_side_effects", func); + }); + + // tell me if a statement aborts + function aborts(thing) { + return thing && thing.aborts(); + }; + (function(def){ + def(AST_Statement, function(){ return null }); + def(AST_Jump, function(){ return this }); + function block_aborts(){ + var n = this.body.length; + return n > 0 && aborts(this.body[n - 1]); + }; + def(AST_BlockStatement, block_aborts); + def(AST_SwitchBranch, block_aborts); + def(AST_If, function(){ + return this.alternative && aborts(this.body) && aborts(this.alternative); + }); + })(function(node, func){ + node.DEFMETHOD("aborts", func); + }); + + /* -----[ optimizers ]----- */ + + OPT(AST_Directive, function(self, compressor){ + if (self.scope.has_directive(self.value) !== self.scope) { + return make_node(AST_EmptyStatement, self); + } + return self; + }); + + OPT(AST_Debugger, function(self, compressor){ + if (compressor.option("drop_debugger")) + return make_node(AST_EmptyStatement, self); + return self; + }); + + OPT(AST_LabeledStatement, function(self, compressor){ + if (self.body instanceof AST_Break + && compressor.loopcontrol_target(self.body.label) === self.body) { + return make_node(AST_EmptyStatement, self); + } + return self.label.references.length == 0 ? self.body : self; + }); + + OPT(AST_Block, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + return self; + }); + + OPT(AST_BlockStatement, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + switch (self.body.length) { + case 1: return self.body[0]; + case 0: return make_node(AST_EmptyStatement, self); + } + return self; + }); + + AST_Scope.DEFMETHOD("drop_unused", function(compressor){ + var self = this; + if (compressor.option("unused") + && !(self instanceof AST_Toplevel) + && !self.uses_eval + ) { + var in_use = []; + var initializations = new Dictionary(); + // pass 1: find out which symbols are directly used in + // this scope (not in nested scopes). + var scope = this; + var tw = new TreeWalker(function(node, descend){ + if (node !== self) { + if (node instanceof AST_Defun) { + initializations.add(node.name.name, node); + return true; // don't go in nested scopes + } + if (node instanceof AST_Definitions && scope === self) { + node.definitions.forEach(function(def){ + if (def.value) { + initializations.add(def.name.name, def.value); + if (def.value.has_side_effects()) { + def.value.walk(tw); + } + } + }); + return true; + } + if (node instanceof AST_SymbolRef) { + push_uniq(in_use, node.definition()); + return true; + } + if (node instanceof AST_Scope) { + var save_scope = scope; + scope = node; + descend(); + scope = save_scope; + return true; + } + } + }); + self.walk(tw); + // pass 2: for every used symbol we need to walk its + // initialization code to figure out if it uses other + // symbols (that may not be in_use). + for (var i = 0; i < in_use.length; ++i) { + in_use[i].orig.forEach(function(decl){ + // undeclared globals will be instanceof AST_SymbolRef + var init = initializations.get(decl.name); + if (init) init.forEach(function(init){ + var tw = new TreeWalker(function(node){ + if (node instanceof AST_SymbolRef) { + push_uniq(in_use, node.definition()); + } + }); + init.walk(tw); + }); + }); + } + // pass 3: we should drop declarations not in_use + var tt = new TreeTransformer( + function before(node, descend, in_list) { + if (node instanceof AST_Lambda) { + for (var a = node.argnames, i = a.length; --i >= 0;) { + var sym = a[i]; + if (sym.unreferenced()) { + a.pop(); + compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", { + name : sym.name, + file : sym.start.file, + line : sym.start.line, + col : sym.start.col + }); + } + else break; + } + } + if (node instanceof AST_Defun && node !== self) { + if (!member(node.name.definition(), in_use)) { + compressor.warn("Dropping unused function {name} [{file}:{line},{col}]", { + name : node.name.name, + file : node.name.start.file, + line : node.name.start.line, + col : node.name.start.col + }); + return make_node(AST_EmptyStatement, node); + } + return node; + } + if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) { + var def = node.definitions.filter(function(def){ + if (member(def.name.definition(), in_use)) return true; + var w = { + name : def.name.name, + file : def.name.start.file, + line : def.name.start.line, + col : def.name.start.col + }; + if (def.value && def.value.has_side_effects()) { + def._unused_side_effects = true; + compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", w); + return true; + } + compressor.warn("Dropping unused variable {name} [{file}:{line},{col}]", w); + return false; + }); + // place uninitialized names at the start + def = mergeSort(def, function(a, b){ + if (!a.value && b.value) return -1; + if (!b.value && a.value) return 1; + return 0; + }); + // for unused names whose initialization has + // side effects, we can cascade the init. code + // into the next one, or next statement. + var side_effects = []; + for (var i = 0; i < def.length;) { + var x = def[i]; + if (x._unused_side_effects) { + side_effects.push(x.value); + def.splice(i, 1); + } else { + if (side_effects.length > 0) { + side_effects.push(x.value); + x.value = AST_Seq.from_array(side_effects); + side_effects = []; + } + ++i; + } + } + if (side_effects.length > 0) { + side_effects = make_node(AST_BlockStatement, node, { + body: [ make_node(AST_SimpleStatement, node, { + body: AST_Seq.from_array(side_effects) + }) ] + }); + } else { + side_effects = null; + } + if (def.length == 0 && !side_effects) { + return make_node(AST_EmptyStatement, node); + } + if (def.length == 0) { + return side_effects; + } + node.definitions = def; + if (side_effects) { + side_effects.body.unshift(node); + node = side_effects; + } + return node; + } + if (node instanceof AST_For && node.init instanceof AST_BlockStatement) { + descend(node, this); + // certain combination of unused name + side effect leads to: + // https://github.com/mishoo/UglifyJS2/issues/44 + // that's an invalid AST. + // We fix it at this stage by moving the `var` outside the `for`. + var body = node.init.body.slice(0, -1); + node.init = node.init.body.slice(-1)[0].body; + body.push(node); + return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, { + body: body + }); + } + if (node instanceof AST_Scope && node !== self) + return node; + } + ); + self.transform(tt); + } + }); + + AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){ + var hoist_funs = compressor.option("hoist_funs"); + var hoist_vars = compressor.option("hoist_vars"); + var self = this; + if (hoist_funs || hoist_vars) { + var dirs = []; + var hoisted = []; + var vars = new Dictionary(), vars_found = 0, var_decl = 0; + // let's count var_decl first, we seem to waste a lot of + // space if we hoist `var` when there's only one. + self.walk(new TreeWalker(function(node){ + if (node instanceof AST_Scope && node !== self) + return true; + if (node instanceof AST_Var) { + ++var_decl; + return true; + } + })); + hoist_vars = hoist_vars && var_decl > 1; + var tt = new TreeTransformer( + function before(node) { + if (node !== self) { + if (node instanceof AST_Directive) { + dirs.push(node); + return make_node(AST_EmptyStatement, node); + } + if (node instanceof AST_Defun && hoist_funs) { + hoisted.push(node); + return make_node(AST_EmptyStatement, node); + } + if (node instanceof AST_Var && hoist_vars) { + node.definitions.forEach(function(def){ + vars.set(def.name.name, def); + ++vars_found; + }); + var seq = node.to_assignments(); + var p = tt.parent(); + if (p instanceof AST_ForIn && p.init === node) { + if (seq == null) return node.definitions[0].name; + return seq; + } + if (p instanceof AST_For && p.init === node) { + return seq; + } + if (!seq) return make_node(AST_EmptyStatement, node); + return make_node(AST_SimpleStatement, node, { + body: seq + }); + } + if (node instanceof AST_Scope) + return node; // to avoid descending in nested scopes + } + } + ); + self = self.transform(tt); + if (vars_found > 0) { + // collect only vars which don't show up in self's arguments list + var defs = []; + vars.each(function(def, name){ + if (self instanceof AST_Lambda + && find_if(function(x){ return x.name == def.name.name }, + self.argnames)) { + vars.del(name); + } else { + def = def.clone(); + def.value = null; + defs.push(def); + vars.set(name, def); + } + }); + if (defs.length > 0) { + // try to merge in assignments + for (var i = 0; i < self.body.length;) { + if (self.body[i] instanceof AST_SimpleStatement) { + var expr = self.body[i].body, sym, assign; + if (expr instanceof AST_Assign + && expr.operator == "=" + && (sym = expr.left) instanceof AST_Symbol + && vars.has(sym.name)) + { + var def = vars.get(sym.name); + if (def.value) break; + def.value = expr.right; + remove(defs, def); + defs.push(def); + self.body.splice(i, 1); + continue; + } + if (expr instanceof AST_Seq + && (assign = expr.car) instanceof AST_Assign + && assign.operator == "=" + && (sym = assign.left) instanceof AST_Symbol + && vars.has(sym.name)) + { + var def = vars.get(sym.name); + if (def.value) break; + def.value = assign.right; + remove(defs, def); + defs.push(def); + self.body[i].body = expr.cdr; + continue; + } + } + if (self.body[i] instanceof AST_EmptyStatement) { + self.body.splice(i, 1); + continue; + } + if (self.body[i] instanceof AST_BlockStatement) { + var tmp = [ i, 1 ].concat(self.body[i].body); + self.body.splice.apply(self.body, tmp); + continue; + } + break; + } + defs = make_node(AST_Var, self, { + definitions: defs + }); + hoisted.push(defs); + }; + } + self.body = dirs.concat(hoisted, self.body); + } + return self; + }); + + OPT(AST_SimpleStatement, function(self, compressor){ + if (compressor.option("side_effects")) { + if (!self.body.has_side_effects()) { + compressor.warn("Dropping side-effect-free statement [{file}:{line},{col}]", self.start); + return make_node(AST_EmptyStatement, self); + } + } + return self; + }); + + OPT(AST_DWLoop, function(self, compressor){ + var cond = self.condition.evaluate(compressor); + self.condition = cond[0]; + if (!compressor.option("loops")) return self; + if (cond.length > 1) { + if (cond[1]) { + return make_node(AST_For, self, { + body: self.body + }); + } else if (self instanceof AST_While) { + if (compressor.option("dead_code")) { + var a = []; + extract_declarations_from_unreachable_code(compressor, self.body, a); + return make_node(AST_BlockStatement, self, { body: a }); + } + } + } + return self; + }); + + function if_break_in_loop(self, compressor) { + function drop_it(rest) { + rest = as_statement_array(rest); + if (self.body instanceof AST_BlockStatement) { + self.body = self.body.clone(); + self.body.body = rest.concat(self.body.body.slice(1)); + self.body = self.body.transform(compressor); + } else { + self.body = make_node(AST_BlockStatement, self.body, { + body: rest + }).transform(compressor); + } + if_break_in_loop(self, compressor); + } + var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body; + if (first instanceof AST_If) { + if (first.body instanceof AST_Break + && compressor.loopcontrol_target(first.body.label) === self) { + if (self.condition) { + self.condition = make_node(AST_Binary, self.condition, { + left: self.condition, + operator: "&&", + right: first.condition.negate(compressor), + }); + } else { + self.condition = first.condition.negate(compressor); + } + drop_it(first.alternative); + } + else if (first.alternative instanceof AST_Break + && compressor.loopcontrol_target(first.alternative.label) === self) { + if (self.condition) { + self.condition = make_node(AST_Binary, self.condition, { + left: self.condition, + operator: "&&", + right: first.condition, + }); + } else { + self.condition = first.condition; + } + drop_it(first.body); + } + } + }; + + OPT(AST_While, function(self, compressor) { + if (!compressor.option("loops")) return self; + self = AST_DWLoop.prototype.optimize.call(self, compressor); + if (self instanceof AST_While) { + if_break_in_loop(self, compressor); + self = make_node(AST_For, self, self).transform(compressor); + } + return self; + }); + + OPT(AST_For, function(self, compressor){ + var cond = self.condition; + if (cond) { + cond = cond.evaluate(compressor); + self.condition = cond[0]; + } + if (!compressor.option("loops")) return self; + if (cond) { + if (cond.length > 1 && !cond[1]) { + if (compressor.option("dead_code")) { + var a = []; + if (self.init instanceof AST_Statement) { + a.push(self.init); + } + else if (self.init) { + a.push(make_node(AST_SimpleStatement, self.init, { + body: self.init + })); + } + extract_declarations_from_unreachable_code(compressor, self.body, a); + return make_node(AST_BlockStatement, self, { body: a }); + } + } + } + if_break_in_loop(self, compressor); + return self; + }); + + OPT(AST_If, function(self, compressor){ + if (!compressor.option("conditionals")) return self; + // if condition can be statically determined, warn and drop + // one of the blocks. note, statically determined implies + // “has no side effects”; also it doesn't work for cases like + // `x && true`, though it probably should. + var cond = self.condition.evaluate(compressor); + self.condition = cond[0]; + if (cond.length > 1) { + if (cond[1]) { + compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start); + if (compressor.option("dead_code")) { + var a = []; + if (self.alternative) { + extract_declarations_from_unreachable_code(compressor, self.alternative, a); + } + a.push(self.body); + return make_node(AST_BlockStatement, self, { body: a }).transform(compressor); + } + } else { + compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start); + if (compressor.option("dead_code")) { + var a = []; + extract_declarations_from_unreachable_code(compressor, self.body, a); + if (self.alternative) a.push(self.alternative); + return make_node(AST_BlockStatement, self, { body: a }).transform(compressor); + } + } + } + if (is_empty(self.alternative)) self.alternative = null; + var negated = self.condition.negate(compressor); + var negated_is_best = best_of(self.condition, negated) === negated; + if (self.alternative && negated_is_best) { + negated_is_best = false; // because we already do the switch here. + self.condition = negated; + var tmp = self.body; + self.body = self.alternative || make_node(AST_EmptyStatement); + self.alternative = tmp; + } + if (is_empty(self.body) && is_empty(self.alternative)) { + return make_node(AST_SimpleStatement, self.condition, { + body: self.condition + }).transform(compressor); + } + if (self.body instanceof AST_SimpleStatement + && self.alternative instanceof AST_SimpleStatement) { + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Conditional, self, { + condition : self.condition, + consequent : self.body.body, + alternative : self.alternative.body + }) + }).transform(compressor); + } + if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) { + if (negated_is_best) return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator : "||", + left : negated, + right : self.body.body + }) + }).transform(compressor); + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator : "&&", + left : self.condition, + right : self.body.body + }) + }).transform(compressor); + } + if (self.body instanceof AST_EmptyStatement + && self.alternative + && self.alternative instanceof AST_SimpleStatement) { + return make_node(AST_SimpleStatement, self, { + body: make_node(AST_Binary, self, { + operator : "||", + left : self.condition, + right : self.alternative.body + }) + }).transform(compressor); + } + if (self.body instanceof AST_Exit + && self.alternative instanceof AST_Exit + && self.body.TYPE == self.alternative.TYPE) { + return make_node(self.body.CTOR, self, { + value: make_node(AST_Conditional, self, { + condition : self.condition, + consequent : self.body.value || make_node(AST_Undefined, self.body).optimize(compressor), + alternative : self.alternative.value || make_node(AST_Undefined, self.alternative).optimize(compressor) + }) + }).transform(compressor); + } + if (self.body instanceof AST_If + && !self.body.alternative + && !self.alternative) { + self.condition = make_node(AST_Binary, self.condition, { + operator: "&&", + left: self.condition, + right: self.body.condition + }).transform(compressor); + self.body = self.body.body; + } + if (aborts(self.body)) { + if (self.alternative) { + var alt = self.alternative; + self.alternative = null; + return make_node(AST_BlockStatement, self, { + body: [ self, alt ] + }).transform(compressor); + } + } + if (aborts(self.alternative)) { + var body = self.body; + self.body = self.alternative; + self.condition = negated_is_best ? negated : self.condition.negate(compressor); + self.alternative = null; + return make_node(AST_BlockStatement, self, { + body: [ self, body ] + }).transform(compressor); + } + return self; + }); + + OPT(AST_Switch, function(self, compressor){ + if (self.body.length == 0 && compressor.option("conditionals")) { + return make_node(AST_SimpleStatement, self, { + body: self.expression + }).transform(compressor); + } + for(;;) { + var last_branch = self.body[self.body.length - 1]; + if (last_branch) { + var stat = last_branch.body[last_branch.body.length - 1]; // last statement + if (stat instanceof AST_Break && loop_body(compressor.loopcontrol_target(stat.label)) === self) + last_branch.body.pop(); + if (last_branch instanceof AST_Default && last_branch.body.length == 0) { + self.body.pop(); + continue; + } + } + break; + } + var exp = self.expression.evaluate(compressor); + out: if (exp.length == 2) try { + // constant expression + self.expression = exp[0]; + if (!compressor.option("dead_code")) break out; + var value = exp[1]; + var in_if = false; + var in_block = false; + var started = false; + var stopped = false; + var ruined = false; + var tt = new TreeTransformer(function(node, descend, in_list){ + if (node instanceof AST_Lambda || node instanceof AST_SimpleStatement) { + // no need to descend these node types + return node; + } + else if (node instanceof AST_Switch && node === self) { + node = node.clone(); + descend(node, this); + return ruined ? node : make_node(AST_BlockStatement, node, { + body: node.body.reduce(function(a, branch){ + return a.concat(branch.body); + }, []) + }).transform(compressor); + } + else if (node instanceof AST_If || node instanceof AST_Try) { + var save = in_if; + in_if = !in_block; + descend(node, this); + in_if = save; + return node; + } + else if (node instanceof AST_StatementWithBody || node instanceof AST_Switch) { + var save = in_block; + in_block = true; + descend(node, this); + in_block = save; + return node; + } + else if (node instanceof AST_Break && this.loopcontrol_target(node.label) === self) { + if (in_if) { + ruined = true; + return node; + } + if (in_block) return node; + stopped = true; + return in_list ? MAP.skip : make_node(AST_EmptyStatement, node); + } + else if (node instanceof AST_SwitchBranch && this.parent() === self) { + if (stopped) return MAP.skip; + if (node instanceof AST_Case) { + var exp = node.expression.evaluate(compressor); + if (exp.length < 2) { + // got a case with non-constant expression, baling out + throw self; + } + if (exp[1] === value || started) { + started = true; + if (aborts(node)) stopped = true; + descend(node, this); + return node; + } + return MAP.skip; + } + descend(node, this); + return node; + } + }); + tt.stack = compressor.stack.slice(); // so that's able to see parent nodes + self = self.transform(tt); + } catch(ex) { + if (ex !== self) throw ex; + } + return self; + }); + + OPT(AST_Case, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + return self; + }); + + OPT(AST_Try, function(self, compressor){ + self.body = tighten_body(self.body, compressor); + return self; + }); + + AST_Definitions.DEFMETHOD("remove_initializers", function(){ + this.definitions.forEach(function(def){ def.value = null }); + }); + + AST_Definitions.DEFMETHOD("to_assignments", function(){ + var assignments = this.definitions.reduce(function(a, def){ + if (def.value) { + var name = make_node(AST_SymbolRef, def.name, def.name); + a.push(make_node(AST_Assign, def, { + operator : "=", + left : name, + right : def.value + })); + } + return a; + }, []); + if (assignments.length == 0) return null; + return AST_Seq.from_array(assignments); + }); + + OPT(AST_Definitions, function(self, compressor){ + if (self.definitions.length == 0) + return make_node(AST_EmptyStatement, self); + return self; + }); + + OPT(AST_Function, function(self, compressor){ + self = AST_Lambda.prototype.optimize.call(self, compressor); + if (compressor.option("unused")) { + if (self.name && self.name.unreferenced()) { + self.name = null; + } + } + return self; + }); + + OPT(AST_Call, function(self, compressor){ + if (compressor.option("unsafe")) { + var exp = self.expression; + if (exp instanceof AST_SymbolRef && exp.undeclared()) { + switch (exp.name) { + case "Array": + if (self.args.length != 1) { + return make_node(AST_Array, self, { + elements: self.args + }); + } + break; + case "Object": + if (self.args.length == 0) { + return make_node(AST_Object, self, { + properties: [] + }); + } + break; + case "String": + if (self.args.length == 0) return make_node(AST_String, self, { + value: "" + }); + return make_node(AST_Binary, self, { + left: self.args[0], + operator: "+", + right: make_node(AST_String, self, { value: "" }) + }); + } + } + else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) { + return make_node(AST_Binary, self, { + left: make_node(AST_String, self, { value: "" }), + operator: "+", + right: exp.expression + }).transform(compressor); + } + } + if (compressor.option("side_effects")) { + if (self.expression instanceof AST_Function + && self.args.length == 0 + && !AST_Block.prototype.has_side_effects.call(self.expression)) { + return make_node(AST_Undefined, self).transform(compressor); + } + } + return self; + }); + + OPT(AST_New, function(self, compressor){ + if (compressor.option("unsafe")) { + var exp = self.expression; + if (exp instanceof AST_SymbolRef && exp.undeclared()) { + switch (exp.name) { + case "Object": + case "RegExp": + case "Function": + case "Error": + case "Array": + return make_node(AST_Call, self, self).transform(compressor); + } + } + } + return self; + }); + + OPT(AST_Seq, function(self, compressor){ + if (!compressor.option("side_effects")) + return self; + if (!self.car.has_side_effects()) { + // we shouldn't compress (1,eval)(something) to + // eval(something) because that changes the meaning of + // eval (becomes lexical instead of global). + var p; + if (!(self.cdr instanceof AST_SymbolRef + && self.cdr.name == "eval" + && self.cdr.undeclared() + && (p = compressor.parent()) instanceof AST_Call + && p.expression === self)) { + return self.cdr; + } + } + if (compressor.option("cascade")) { + if (self.car instanceof AST_Assign + && !self.car.left.has_side_effects() + && self.car.left.equivalent_to(self.cdr)) { + return self.car; + } + if (!self.car.has_side_effects() + && !self.cdr.has_side_effects() + && self.car.equivalent_to(self.cdr)) { + return self.car; + } + } + return self; + }); + + AST_Unary.DEFMETHOD("lift_sequences", function(compressor){ + if (compressor.option("sequences")) { + if (this.expression instanceof AST_Seq) { + var seq = this.expression; + var x = seq.to_array(); + this.expression = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + } + return this; + }); + + OPT(AST_UnaryPostfix, function(self, compressor){ + return self.lift_sequences(compressor); + }); + + OPT(AST_UnaryPrefix, function(self, compressor){ + self = self.lift_sequences(compressor); + var e = self.expression; + if (compressor.option("booleans") && compressor.in_boolean_context()) { + switch (self.operator) { + case "!": + if (e instanceof AST_UnaryPrefix && e.operator == "!") { + // !!foo ==> foo, if we're in boolean context + return e.expression; + } + break; + case "typeof": + // typeof always returns a non-empty string, thus it's + // always true in booleans + compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + if (e instanceof AST_Binary && self.operator == "!") { + self = best_of(self, e.negate(compressor)); + } + } + return self.evaluate(compressor)[0]; + }); + + AST_Binary.DEFMETHOD("lift_sequences", function(compressor){ + if (compressor.option("sequences")) { + if (this.left instanceof AST_Seq) { + var seq = this.left; + var x = seq.to_array(); + this.left = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + if (this.right instanceof AST_Seq + && !(this.operator == "||" || this.operator == "&&") + && !this.left.has_side_effects()) { + var seq = this.right; + var x = seq.to_array(); + this.right = x.pop(); + x.push(this); + seq = AST_Seq.from_array(x).transform(compressor); + return seq; + } + } + return this; + }); + + var commutativeOperators = makePredicate("== === != !== * & | ^"); + + OPT(AST_Binary, function(self, compressor){ + function reverse(op) { + if (!(self.left.has_side_effects() || self.right.has_side_effects())) { + if (op) self.operator = op; + var tmp = self.left; + self.left = self.right; + self.right = tmp; + } + }; + if (commutativeOperators(self.operator)) { + if (self.right instanceof AST_Constant + && !(self.left instanceof AST_Constant)) { + reverse(); + } + } + self = self.lift_sequences(compressor); + if (compressor.option("comparisons")) switch (self.operator) { + case "===": + case "!==": + if ((self.left.is_string(compressor) && self.right.is_string(compressor)) || + (self.left.is_boolean() && self.right.is_boolean())) { + self.operator = self.operator.substr(0, 2); + } + // XXX: intentionally falling down to the next case + case "==": + case "!=": + if (self.left instanceof AST_String + && self.left.value == "undefined" + && self.right instanceof AST_UnaryPrefix + && self.right.operator == "typeof" + && compressor.option("unsafe")) { + if (!(self.right.expression instanceof AST_SymbolRef) + || !self.right.expression.undeclared()) { + self.left = self.right.expression; + self.right = make_node(AST_Undefined, self.left).optimize(compressor); + if (self.operator.length == 2) self.operator += "="; + } + } + break; + } + if (compressor.option("booleans") && compressor.in_boolean_context()) switch (self.operator) { + case "&&": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if ((ll.length > 1 && !ll[1]) || (rr.length > 1 && !rr[1])) { + compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start); + return make_node(AST_False, self); + } + if (ll.length > 1 && ll[1]) { + return rr[0]; + } + if (rr.length > 1 && rr[1]) { + return ll[0]; + } + break; + case "||": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if ((ll.length > 1 && ll[1]) || (rr.length > 1 && rr[1])) { + compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + if (ll.length > 1 && !ll[1]) { + return rr[0]; + } + if (rr.length > 1 && !rr[1]) { + return ll[0]; + } + break; + case "+": + var ll = self.left.evaluate(compressor); + var rr = self.right.evaluate(compressor); + if ((ll.length > 1 && ll[0] instanceof AST_String && ll[1]) || + (rr.length > 1 && rr[0] instanceof AST_String && rr[1])) { + compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start); + return make_node(AST_True, self); + } + break; + } + var exp = self.evaluate(compressor); + if (exp.length > 1) { + if (best_of(exp[0], self) !== self) + return exp[0]; + } + if (compressor.option("comparisons")) { + if (!(compressor.parent() instanceof AST_Binary) + || compressor.parent() instanceof AST_Assign) { + var negated = make_node(AST_UnaryPrefix, self, { + operator: "!", + expression: self.negate(compressor) + }); + self = best_of(self, negated); + } + switch (self.operator) { + case "<": reverse(">"); break; + case "<=": reverse(">="); break; + } + } + if (self.operator == "+" && self.right instanceof AST_String + && self.right.getValue() === "" && self.left instanceof AST_Binary + && self.left.operator == "+" && self.left.is_string(compressor)) { + return self.left; + } + return self; + }); + + OPT(AST_SymbolRef, function(self, compressor){ + if (self.undeclared()) { + var defines = compressor.option("global_defs"); + if (defines && defines.hasOwnProperty(self.name)) { + return make_node_from_constant(compressor, defines[self.name], self); + } + switch (self.name) { + case "undefined": + return make_node(AST_Undefined, self); + case "NaN": + return make_node(AST_NaN, self); + case "Infinity": + return make_node(AST_Infinity, self); + } + } + return self; + }); + + OPT(AST_Undefined, function(self, compressor){ + if (compressor.option("unsafe")) { + var scope = compressor.find_parent(AST_Scope); + var undef = scope.find_variable("undefined"); + if (undef) { + var ref = make_node(AST_SymbolRef, self, { + name : "undefined", + scope : scope, + thedef : undef + }); + ref.reference(); + return ref; + } + } + return self; + }); + + var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ]; + OPT(AST_Assign, function(self, compressor){ + self = self.lift_sequences(compressor); + if (self.operator == "=" + && self.left instanceof AST_SymbolRef + && self.right instanceof AST_Binary + && self.right.left instanceof AST_SymbolRef + && self.right.left.name == self.left.name + && member(self.right.operator, ASSIGN_OPS)) { + self.operator = self.right.operator + "="; + self.right = self.right.right; + } + return self; + }); + + OPT(AST_Conditional, function(self, compressor){ + if (!compressor.option("conditionals")) return self; + if (self.condition instanceof AST_Seq) { + var car = self.condition.car; + self.condition = self.condition.cdr; + return AST_Seq.cons(car, self); + } + var cond = self.condition.evaluate(compressor); + if (cond.length > 1) { + if (cond[1]) { + compressor.warn("Condition always true [{file}:{line},{col}]", self.start); + return self.consequent; + } else { + compressor.warn("Condition always false [{file}:{line},{col}]", self.start); + return self.alternative; + } + } + var negated = cond[0].negate(compressor); + if (best_of(cond[0], negated) === negated) { + self = make_node(AST_Conditional, self, { + condition: negated, + consequent: self.alternative, + alternative: self.consequent + }); + } + var consequent = self.consequent; + var alternative = self.alternative; + if (consequent instanceof AST_Assign + && alternative instanceof AST_Assign + && consequent.operator == alternative.operator + && consequent.left.equivalent_to(alternative.left) + ) { + /* + * Stuff like this: + * if (foo) exp = something; else exp = something_else; + * ==> + * exp = foo ? something : something_else; + */ + self = make_node(AST_Assign, self, { + operator: consequent.operator, + left: consequent.left, + right: make_node(AST_Conditional, self, { + condition: self.condition, + consequent: consequent.right, + alternative: alternative.right + }) + }); + } + return self; + }); + + OPT(AST_Boolean, function(self, compressor){ + if (compressor.option("booleans")) { + var p = compressor.parent(); + if (p instanceof AST_Binary && (p.operator == "==" + || p.operator == "!=")) { + compressor.warn("Non-strict equality against boolean: {operator} {value} [{file}:{line},{col}]", { + operator : p.operator, + value : self.value, + file : p.start.file, + line : p.start.line, + col : p.start.col, + }); + return make_node(AST_Number, self, { + value: +self.value + }); + } + return make_node(AST_UnaryPrefix, self, { + operator: "!", + expression: make_node(AST_Number, self, { + value: 1 - self.value + }) + }); + } + return self; + }); + + OPT(AST_Sub, function(self, compressor){ + var prop = self.property; + if (prop instanceof AST_String && compressor.option("properties")) { + prop = prop.getValue(); + if (is_identifier(prop) || compressor.option("screw_ie8")) { + return make_node(AST_Dot, self, { + expression : self.expression, + property : prop + }); + } + } + return self; + }); + + function literals_in_boolean_context(self, compressor) { + if (compressor.option("booleans") && compressor.in_boolean_context()) { + return make_node(AST_True, self); + } + return self; + }; + OPT(AST_Array, literals_in_boolean_context); + OPT(AST_Object, literals_in_boolean_context); + OPT(AST_RegExp, literals_in_boolean_context); + +})(); diff --git a/homework8/project_express/node_modules/uglify-js/lib/mozilla-ast.js b/homework8/project_express/node_modules/uglify-js/lib/mozilla-ast.js new file mode 100644 index 0000000..d795094 --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/lib/mozilla-ast.js @@ -0,0 +1,267 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +(function(){ + + var MOZ_TO_ME = { + TryStatement : function(M) { + return new AST_Try({ + start : my_start_token(M), + end : my_end_token(M), + body : from_moz(M.block).body, + bcatch : from_moz(M.handlers[0]), + bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null + }); + }, + CatchClause : function(M) { + return new AST_Catch({ + start : my_start_token(M), + end : my_end_token(M), + argname : from_moz(M.param), + body : from_moz(M.body).body + }); + }, + ObjectExpression : function(M) { + return new AST_Object({ + start : my_start_token(M), + end : my_end_token(M), + properties : M.properties.map(function(prop){ + var key = prop.key; + var name = key.type == "Identifier" ? key.name : key.value; + var args = { + start : my_start_token(key), + end : my_end_token(prop.value), + key : name, + value : from_moz(prop.value) + }; + switch (prop.kind) { + case "init": + return new AST_ObjectKeyVal(args); + case "set": + args.value.name = from_moz(key); + return new AST_ObjectSetter(args); + case "get": + args.value.name = from_moz(key); + return new AST_ObjectGetter(args); + } + }) + }); + }, + SequenceExpression : function(M) { + return AST_Seq.from_array(M.expressions.map(from_moz)); + }, + MemberExpression : function(M) { + return new (M.computed ? AST_Sub : AST_Dot)({ + start : my_start_token(M), + end : my_end_token(M), + property : M.computed ? from_moz(M.property) : M.property.name, + expression : from_moz(M.object) + }); + }, + SwitchCase : function(M) { + return new (M.test ? AST_Case : AST_Default)({ + start : my_start_token(M), + end : my_end_token(M), + expression : from_moz(M.test), + body : M.consequent.map(from_moz) + }); + }, + Literal : function(M) { + var val = M.value, args = { + start : my_start_token(M), + end : my_end_token(M) + }; + if (val === null) return new AST_Null(args); + switch (typeof val) { + case "string": + args.value = val; + return new AST_String(args); + case "number": + args.value = val; + return new AST_Number(args); + case "boolean": + return new (val ? AST_True : AST_False)(args); + default: + args.value = val; + return new AST_RegExp(args); + } + }, + UnaryExpression: From_Moz_Unary, + UpdateExpression: From_Moz_Unary, + Identifier: function(M) { + var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2]; + return new (M.name == "this" ? AST_This + : p.type == "LabeledStatement" ? AST_Label + : p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar) + : p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg) + : p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg) + : p.type == "CatchClause" ? AST_SymbolCatch + : p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef + : AST_SymbolRef)({ + start : my_start_token(M), + end : my_end_token(M), + name : M.name + }); + } + }; + + function From_Moz_Unary(M) { + var prefix = "prefix" in M ? M.prefix + : M.type == "UnaryExpression" ? true : false; + return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({ + start : my_start_token(M), + end : my_end_token(M), + operator : M.operator, + expression : from_moz(M.argument) + }); + }; + + var ME_TO_MOZ = {}; + + map("Node", AST_Node); + map("Program", AST_Toplevel, "body@body"); + map("Function", AST_Function, "id>name, params@argnames, body%body"); + map("EmptyStatement", AST_EmptyStatement); + map("BlockStatement", AST_BlockStatement, "body@body"); + map("ExpressionStatement", AST_SimpleStatement, "expression>body"); + map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative"); + map("LabeledStatement", AST_LabeledStatement, "label>label, body>body"); + map("BreakStatement", AST_Break, "label>label"); + map("ContinueStatement", AST_Continue, "label>label"); + map("WithStatement", AST_With, "object>expression, body>body"); + map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body"); + map("ReturnStatement", AST_Return, "argument>value"); + map("ThrowStatement", AST_Throw, "argument>value"); + map("WhileStatement", AST_While, "test>condition, body>body"); + map("DoWhileStatement", AST_Do, "test>condition, body>body"); + map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body"); + map("ForInStatement", AST_ForIn, "left>init, right>object, body>body"); + map("DebuggerStatement", AST_Debugger); + map("FunctionDeclaration", AST_Defun, "id>name, params@argnames, body%body"); + map("VariableDeclaration", AST_Var, "declarations@definitions"); + map("VariableDeclarator", AST_VarDef, "id>name, init>value"); + + map("ThisExpression", AST_This); + map("ArrayExpression", AST_Array, "elements@elements"); + map("FunctionExpression", AST_Function, "id>name, params@argnames, body%body"); + map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right"); + map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right"); + map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right"); + map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative"); + map("NewExpression", AST_New, "callee>expression, arguments@args"); + map("CallExpression", AST_Call, "callee>expression, arguments@args"); + + /* -----[ tools ]----- */ + + function my_start_token(moznode) { + return new AST_Token({ + file : moznode.loc && moznode.loc.source, + line : moznode.loc && moznode.loc.start.line, + col : moznode.loc && moznode.loc.start.column, + pos : moznode.start, + endpos : moznode.start + }); + }; + + function my_end_token(moznode) { + return new AST_Token({ + file : moznode.loc && moznode.loc.source, + line : moznode.loc && moznode.loc.end.line, + col : moznode.loc && moznode.loc.end.column, + pos : moznode.end, + endpos : moznode.end + }); + }; + + function map(moztype, mytype, propmap) { + var moz_to_me = "function From_Moz_" + moztype + "(M){\n"; + moz_to_me += "return new mytype({\n" + + "start: my_start_token(M),\n" + + "end: my_end_token(M)"; + + if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop){ + var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop); + if (!m) throw new Error("Can't understand property map: " + prop); + var moz = "M." + m[1], how = m[2], my = m[3]; + moz_to_me += ",\n" + my + ": "; + if (how == "@") { + moz_to_me += moz + ".map(from_moz)"; + } else if (how == ">") { + moz_to_me += "from_moz(" + moz + ")"; + } else if (how == "=") { + moz_to_me += moz; + } else if (how == "%") { + moz_to_me += "from_moz(" + moz + ").body"; + } else throw new Error("Can't understand operator in propmap: " + prop); + }); + moz_to_me += "\n})}"; + + // moz_to_me = parse(moz_to_me).print_to_string({ beautify: true }); + // console.log(moz_to_me); + + moz_to_me = new Function("mytype", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")( + mytype, my_start_token, my_end_token, from_moz + ); + return MOZ_TO_ME[moztype] = moz_to_me; + }; + + var FROM_MOZ_STACK = null; + + function from_moz(node) { + FROM_MOZ_STACK.push(node); + var ret = node != null ? MOZ_TO_ME[node.type](node) : null; + FROM_MOZ_STACK.pop(); + return ret; + }; + + AST_Node.from_mozilla_ast = function(node){ + var save_stack = FROM_MOZ_STACK; + FROM_MOZ_STACK = []; + var ast = from_moz(node); + FROM_MOZ_STACK = save_stack; + return ast; + }; + +})(); diff --git a/homework8/project_express/node_modules/uglify-js/lib/output.js b/homework8/project_express/node_modules/uglify-js/lib/output.js new file mode 100644 index 0000000..defd021 --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/lib/output.js @@ -0,0 +1,1225 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function OutputStream(options) { + + options = defaults(options, { + indent_start : 0, + indent_level : 4, + quote_keys : false, + space_colon : true, + ascii_only : false, + inline_script : false, + width : 80, + max_line_len : 32000, + ie_proof : true, + beautify : false, + source_map : null, + bracketize : false, + semicolons : true, + comments : false, + preserve_line : false + }, true); + + var indentation = 0; + var current_col = 0; + var current_line = 1; + var current_pos = 0; + var OUTPUT = ""; + + function to_ascii(str, identifier) { + return str.replace(/[\u0080-\uffff]/g, function(ch) { + var code = ch.charCodeAt(0).toString(16); + if (code.length <= 2 && !identifier) { + while (code.length < 2) code = "0" + code; + return "\\x" + code; + } else { + while (code.length < 4) code = "0" + code; + return "\\u" + code; + } + }); + }; + + function make_string(str) { + var dq = 0, sq = 0; + str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s){ + switch (s) { + case "\\": return "\\\\"; + case "\b": return "\\b"; + case "\f": return "\\f"; + case "\n": return "\\n"; + case "\r": return "\\r"; + case "\u2028": return "\\u2028"; + case "\u2029": return "\\u2029"; + case '"': ++dq; return '"'; + case "'": ++sq; return "'"; + case "\0": return "\\0"; + } + return s; + }); + if (options.ascii_only) str = to_ascii(str); + if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'"; + else return '"' + str.replace(/\x22/g, '\\"') + '"'; + }; + + function encode_string(str) { + var ret = make_string(str); + if (options.inline_script) + ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1"); + return ret; + }; + + function make_name(name) { + name = name.toString(); + if (options.ascii_only) + name = to_ascii(name, true); + return name; + }; + + function make_indent(back) { + return repeat_string(" ", options.indent_start + indentation - back * options.indent_level); + }; + + /* -----[ beautification/minification ]----- */ + + var might_need_space = false; + var might_need_semicolon = false; + var last = null; + + function last_char() { + return last.charAt(last.length - 1); + }; + + function maybe_newline() { + if (options.max_line_len && current_col > options.max_line_len) + print("\n"); + }; + + var requireSemicolonChars = makePredicate("( [ + * / - , ."); + + function print(str) { + str = String(str); + var ch = str.charAt(0); + if (might_need_semicolon) { + if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) { + if (options.semicolons || requireSemicolonChars(ch)) { + OUTPUT += ";"; + current_col++; + current_pos++; + } else { + OUTPUT += "\n"; + current_pos++; + current_line++; + current_col = 0; + } + if (!options.beautify) + might_need_space = false; + } + might_need_semicolon = false; + maybe_newline(); + } + + if (!options.beautify && options.preserve_line && stack[stack.length - 1]) { + var target_line = stack[stack.length - 1].start.line; + while (current_line < target_line) { + OUTPUT += "\n"; + current_pos++; + current_line++; + current_col = 0; + might_need_space = false; + } + } + + if (might_need_space) { + var prev = last_char(); + if ((is_identifier_char(prev) + && (is_identifier_char(ch) || ch == "\\")) + || (/^[\+\-\/]$/.test(ch) && ch == prev)) + { + OUTPUT += " "; + current_col++; + current_pos++; + } + might_need_space = false; + } + var a = str.split(/\r?\n/), n = a.length - 1; + current_line += n; + if (n == 0) { + current_col += a[n].length; + } else { + current_col = a[n].length; + } + current_pos += str.length; + last = str; + OUTPUT += str; + }; + + var space = options.beautify ? function() { + print(" "); + } : function() { + might_need_space = true; + }; + + var indent = options.beautify ? function(half) { + if (options.beautify) { + print(make_indent(half ? 0.5 : 0)); + } + } : noop; + + var with_indent = options.beautify ? function(col, cont) { + if (col === true) col = next_indent(); + var save_indentation = indentation; + indentation = col; + var ret = cont(); + indentation = save_indentation; + return ret; + } : function(col, cont) { return cont() }; + + var newline = options.beautify ? function() { + print("\n"); + } : noop; + + var semicolon = options.beautify ? function() { + print(";"); + } : function() { + might_need_semicolon = true; + }; + + function force_semicolon() { + might_need_semicolon = false; + print(";"); + }; + + function next_indent() { + return indentation + options.indent_level; + }; + + function with_block(cont) { + var ret; + print("{"); + newline(); + with_indent(next_indent(), function(){ + ret = cont(); + }); + indent(); + print("}"); + return ret; + }; + + function with_parens(cont) { + print("("); + //XXX: still nice to have that for argument lists + //var ret = with_indent(current_col, cont); + var ret = cont(); + print(")"); + return ret; + }; + + function with_square(cont) { + print("["); + //var ret = with_indent(current_col, cont); + var ret = cont(); + print("]"); + return ret; + }; + + function comma() { + print(","); + space(); + }; + + function colon() { + print(":"); + if (options.space_colon) space(); + }; + + var add_mapping = options.source_map ? function(token, name) { + try { + if (token) options.source_map.add( + token.file || "?", + current_line, current_col, + token.line, token.col, + (!name && token.type == "name") ? token.value : name + ); + } catch(ex) { + AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", { + file: token.file, + line: token.line, + col: token.col, + cline: current_line, + ccol: current_col, + name: name || "" + }) + } + } : noop; + + function get() { + return OUTPUT; + }; + + var stack = []; + return { + get : get, + toString : get, + indent : indent, + indentation : function() { return indentation }, + current_width : function() { return current_col - indentation }, + should_break : function() { return options.width && this.current_width() >= options.width }, + newline : newline, + print : print, + space : space, + comma : comma, + colon : colon, + last : function() { return last }, + semicolon : semicolon, + force_semicolon : force_semicolon, + to_ascii : to_ascii, + print_name : function(name) { print(make_name(name)) }, + print_string : function(str) { print(encode_string(str)) }, + next_indent : next_indent, + with_indent : with_indent, + with_block : with_block, + with_parens : with_parens, + with_square : with_square, + add_mapping : add_mapping, + option : function(opt) { return options[opt] }, + line : function() { return current_line }, + col : function() { return current_col }, + pos : function() { return current_pos }, + push_node : function(node) { stack.push(node) }, + pop_node : function() { return stack.pop() }, + stack : function() { return stack }, + parent : function(n) { + return stack[stack.length - 2 - (n || 0)]; + } + }; + +}; + +/* -----[ code generators ]----- */ + +(function(){ + + /* -----[ utils ]----- */ + + function DEFPRINT(nodetype, generator) { + nodetype.DEFMETHOD("_codegen", generator); + }; + + AST_Node.DEFMETHOD("print", function(stream, force_parens){ + var self = this, generator = self._codegen; + stream.push_node(self); + if (force_parens || self.needs_parens(stream)) { + stream.with_parens(function(){ + self.add_comments(stream); + self.add_source_map(stream); + generator(self, stream); + }); + } else { + self.add_comments(stream); + self.add_source_map(stream); + generator(self, stream); + } + stream.pop_node(); + }); + + AST_Node.DEFMETHOD("print_to_string", function(options){ + var s = OutputStream(options); + this.print(s); + return s.get(); + }); + + /* -----[ comments ]----- */ + + AST_Node.DEFMETHOD("add_comments", function(output){ + var c = output.option("comments"), self = this; + if (c) { + var start = self.start; + if (start && !start._comments_dumped) { + start._comments_dumped = true; + var comments = start.comments_before; + + // XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112 + // if this node is `return` or `throw`, we cannot allow comments before + // the returned or thrown value. + if (self instanceof AST_Exit && + self.value && self.value.start.comments_before.length > 0) { + comments = (comments || []).concat(self.value.start.comments_before); + self.value.start.comments_before = []; + } + + if (c.test) { + comments = comments.filter(function(comment){ + return c.test(comment.value); + }); + } else if (typeof c == "function") { + comments = comments.filter(function(comment){ + return c(self, comment); + }); + } + comments.forEach(function(c){ + if (c.type == "comment1") { + output.print("//" + c.value + "\n"); + output.indent(); + } + else if (c.type == "comment2") { + output.print("/*" + c.value + "*/"); + if (start.nlb) { + output.print("\n"); + output.indent(); + } else { + output.space(); + } + } + }); + } + } + }); + + /* -----[ PARENTHESES ]----- */ + + function PARENS(nodetype, func) { + nodetype.DEFMETHOD("needs_parens", func); + }; + + PARENS(AST_Node, function(){ + return false; + }); + + // a function expression needs parens around it when it's provably + // the first token to appear in a statement. + PARENS(AST_Function, function(output){ + return first_in_statement(output); + }); + + // same goes for an object literal, because otherwise it would be + // interpreted as a block of code. + PARENS(AST_Object, function(output){ + return first_in_statement(output); + }); + + PARENS(AST_Unary, function(output){ + var p = output.parent(); + return p instanceof AST_PropAccess && p.expression === this; + }); + + PARENS(AST_Seq, function(output){ + var p = output.parent(); + return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4) + || p instanceof AST_Unary // !(foo, bar, baz) + || p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8 + || p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4 + || p instanceof AST_Dot // (1, {foo:2}).foo ==> 2 + || p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ] + || p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2 + || p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30) + * ==> 20 (side effect, set a := 10 and b := 20) */ + ; + }); + + PARENS(AST_Binary, function(output){ + var p = output.parent(); + // (foo && bar)() + if (p instanceof AST_Call && p.expression === this) + return true; + // typeof (foo && bar) + if (p instanceof AST_Unary) + return true; + // (foo && bar)["prop"], (foo && bar).prop + if (p instanceof AST_PropAccess && p.expression === this) + return true; + // this deals with precedence: 3 * (2 + 1) + if (p instanceof AST_Binary) { + var po = p.operator, pp = PRECEDENCE[po]; + var so = this.operator, sp = PRECEDENCE[so]; + if (pp > sp + || (pp == sp + && this === p.right + && !(so == po && + (so == "*" || + so == "&&" || + so == "||")))) { + return true; + } + } + }); + + PARENS(AST_PropAccess, function(output){ + var p = output.parent(); + if (p instanceof AST_New && p.expression === this) { + // i.e. new (foo.bar().baz) + // + // if there's one call into this subtree, then we need + // parens around it too, otherwise the call will be + // interpreted as passing the arguments to the upper New + // expression. + try { + this.walk(new TreeWalker(function(node){ + if (node instanceof AST_Call) throw p; + })); + } catch(ex) { + if (ex !== p) throw ex; + return true; + } + } + }); + + PARENS(AST_Call, function(output){ + var p = output.parent(); + return p instanceof AST_New && p.expression === this; + }); + + PARENS(AST_New, function(output){ + var p = output.parent(); + if (no_constructor_parens(this, output) + && (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]() + || p instanceof AST_Call && p.expression === this)) // (new foo)(bar) + return true; + }); + + PARENS(AST_Number, function(output){ + var p = output.parent(); + if (this.getValue() < 0 && p instanceof AST_PropAccess && p.expression === this) + return true; + }); + + PARENS(AST_NaN, function(output){ + var p = output.parent(); + if (p instanceof AST_PropAccess && p.expression === this) + return true; + }); + + function assign_and_conditional_paren_rules(output) { + var p = output.parent(); + // !(a = false) → true + if (p instanceof AST_Unary) + return true; + // 1 + (a = 2) + 3 → 6, side effect setting a = 2 + if (p instanceof AST_Binary && !(p instanceof AST_Assign)) + return true; + // (a = func)() —or— new (a = Object)() + if (p instanceof AST_Call && p.expression === this) + return true; + // (a = foo) ? bar : baz + if (p instanceof AST_Conditional && p.condition === this) + return true; + // (a = foo)["prop"] —or— (a = foo).prop + if (p instanceof AST_PropAccess && p.expression === this) + return true; + }; + + PARENS(AST_Assign, assign_and_conditional_paren_rules); + PARENS(AST_Conditional, assign_and_conditional_paren_rules); + + /* -----[ PRINTERS ]----- */ + + DEFPRINT(AST_Directive, function(self, output){ + output.print_string(self.value); + output.semicolon(); + }); + DEFPRINT(AST_Debugger, function(self, output){ + output.print("debugger"); + output.semicolon(); + }); + + /* -----[ statements ]----- */ + + function display_body(body, is_toplevel, output) { + var last = body.length - 1; + body.forEach(function(stmt, i){ + if (!(stmt instanceof AST_EmptyStatement)) { + output.indent(); + stmt.print(output); + if (!(i == last && is_toplevel)) { + output.newline(); + if (is_toplevel) output.newline(); + } + } + }); + }; + + AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output){ + force_statement(this.body, output); + }); + + DEFPRINT(AST_Statement, function(self, output){ + self.body.print(output); + output.semicolon(); + }); + DEFPRINT(AST_Toplevel, function(self, output){ + display_body(self.body, true, output); + output.print(""); + }); + DEFPRINT(AST_LabeledStatement, function(self, output){ + self.label.print(output); + output.colon(); + self.body.print(output); + }); + DEFPRINT(AST_SimpleStatement, function(self, output){ + self.body.print(output); + output.semicolon(); + }); + function print_bracketed(body, output) { + if (body.length > 0) output.with_block(function(){ + display_body(body, false, output); + }); + else output.print("{}"); + }; + DEFPRINT(AST_BlockStatement, function(self, output){ + print_bracketed(self.body, output); + }); + DEFPRINT(AST_EmptyStatement, function(self, output){ + output.semicolon(); + }); + DEFPRINT(AST_Do, function(self, output){ + output.print("do"); + output.space(); + self._do_print_body(output); + output.space(); + output.print("while"); + output.space(); + output.with_parens(function(){ + self.condition.print(output); + }); + output.semicolon(); + }); + DEFPRINT(AST_While, function(self, output){ + output.print("while"); + output.space(); + output.with_parens(function(){ + self.condition.print(output); + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_For, function(self, output){ + output.print("for"); + output.space(); + output.with_parens(function(){ + if (self.init) { + if (self.init instanceof AST_Definitions) { + self.init.print(output); + } else { + parenthesize_for_noin(self.init, output, true); + } + output.print(";"); + output.space(); + } else { + output.print(";"); + } + if (self.condition) { + self.condition.print(output); + output.print(";"); + output.space(); + } else { + output.print(";"); + } + if (self.step) { + self.step.print(output); + } + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_ForIn, function(self, output){ + output.print("for"); + output.space(); + output.with_parens(function(){ + self.init.print(output); + output.space(); + output.print("in"); + output.space(); + self.object.print(output); + }); + output.space(); + self._do_print_body(output); + }); + DEFPRINT(AST_With, function(self, output){ + output.print("with"); + output.space(); + output.with_parens(function(){ + self.expression.print(output); + }); + output.space(); + self._do_print_body(output); + }); + + /* -----[ functions ]----- */ + AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){ + var self = this; + if (!nokeyword) { + output.print("function"); + } + if (self.name) { + output.space(); + self.name.print(output); + } + output.with_parens(function(){ + self.argnames.forEach(function(arg, i){ + if (i) output.comma(); + arg.print(output); + }); + }); + output.space(); + print_bracketed(self.body, output); + }); + DEFPRINT(AST_Lambda, function(self, output){ + self._do_print(output); + }); + + /* -----[ exits ]----- */ + AST_Exit.DEFMETHOD("_do_print", function(output, kind){ + output.print(kind); + if (this.value) { + output.space(); + this.value.print(output); + } + output.semicolon(); + }); + DEFPRINT(AST_Return, function(self, output){ + self._do_print(output, "return"); + }); + DEFPRINT(AST_Throw, function(self, output){ + self._do_print(output, "throw"); + }); + + /* -----[ loop control ]----- */ + AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){ + output.print(kind); + if (this.label) { + output.space(); + this.label.print(output); + } + output.semicolon(); + }); + DEFPRINT(AST_Break, function(self, output){ + self._do_print(output, "break"); + }); + DEFPRINT(AST_Continue, function(self, output){ + self._do_print(output, "continue"); + }); + + /* -----[ if ]----- */ + function make_then(self, output) { + if (output.option("bracketize")) { + make_block(self.body, output); + return; + } + // The squeezer replaces "block"-s that contain only a single + // statement with the statement itself; technically, the AST + // is correct, but this can create problems when we output an + // IF having an ELSE clause where the THEN clause ends in an + // IF *without* an ELSE block (then the outer ELSE would refer + // to the inner IF). This function checks for this case and + // adds the block brackets if needed. + if (!self.body) + return output.force_semicolon(); + if (self.body instanceof AST_Do + && output.option("ie_proof")) { + // https://github.com/mishoo/UglifyJS/issues/#issue/57 IE + // croaks with "syntax error" on code like this: if (foo) + // do ... while(cond); else ... we need block brackets + // around do/while + make_block(self.body, output); + return; + } + var b = self.body; + while (true) { + if (b instanceof AST_If) { + if (!b.alternative) { + make_block(self.body, output); + return; + } + b = b.alternative; + } + else if (b instanceof AST_StatementWithBody) { + b = b.body; + } + else break; + } + force_statement(self.body, output); + }; + DEFPRINT(AST_If, function(self, output){ + output.print("if"); + output.space(); + output.with_parens(function(){ + self.condition.print(output); + }); + output.space(); + if (self.alternative) { + make_then(self, output); + output.space(); + output.print("else"); + output.space(); + force_statement(self.alternative, output); + } else { + self._do_print_body(output); + } + }); + + /* -----[ switch ]----- */ + DEFPRINT(AST_Switch, function(self, output){ + output.print("switch"); + output.space(); + output.with_parens(function(){ + self.expression.print(output); + }); + output.space(); + if (self.body.length > 0) output.with_block(function(){ + self.body.forEach(function(stmt, i){ + if (i) output.newline(); + output.indent(true); + stmt.print(output); + }); + }); + else output.print("{}"); + }); + AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output){ + if (this.body.length > 0) { + output.newline(); + this.body.forEach(function(stmt){ + output.indent(); + stmt.print(output); + output.newline(); + }); + } + }); + DEFPRINT(AST_Default, function(self, output){ + output.print("default:"); + self._do_print_body(output); + }); + DEFPRINT(AST_Case, function(self, output){ + output.print("case"); + output.space(); + self.expression.print(output); + output.print(":"); + self._do_print_body(output); + }); + + /* -----[ exceptions ]----- */ + DEFPRINT(AST_Try, function(self, output){ + output.print("try"); + output.space(); + print_bracketed(self.body, output); + if (self.bcatch) { + output.space(); + self.bcatch.print(output); + } + if (self.bfinally) { + output.space(); + self.bfinally.print(output); + } + }); + DEFPRINT(AST_Catch, function(self, output){ + output.print("catch"); + output.space(); + output.with_parens(function(){ + self.argname.print(output); + }); + output.space(); + print_bracketed(self.body, output); + }); + DEFPRINT(AST_Finally, function(self, output){ + output.print("finally"); + output.space(); + print_bracketed(self.body, output); + }); + + /* -----[ var/const ]----- */ + AST_Definitions.DEFMETHOD("_do_print", function(output, kind){ + output.print(kind); + output.space(); + this.definitions.forEach(function(def, i){ + if (i) output.comma(); + def.print(output); + }); + var p = output.parent(); + var in_for = p instanceof AST_For || p instanceof AST_ForIn; + var avoid_semicolon = in_for && p.init === this; + if (!avoid_semicolon) + output.semicolon(); + }); + DEFPRINT(AST_Var, function(self, output){ + self._do_print(output, "var"); + }); + DEFPRINT(AST_Const, function(self, output){ + self._do_print(output, "const"); + }); + + function parenthesize_for_noin(node, output, noin) { + if (!noin) node.print(output); + else try { + // need to take some precautions here: + // https://github.com/mishoo/UglifyJS2/issues/60 + node.walk(new TreeWalker(function(node){ + if (node instanceof AST_Binary && node.operator == "in") + throw output; + })); + node.print(output); + } catch(ex) { + if (ex !== output) throw ex; + node.print(output, true); + } + }; + + DEFPRINT(AST_VarDef, function(self, output){ + self.name.print(output); + if (self.value) { + output.space(); + output.print("="); + output.space(); + var p = output.parent(1); + var noin = p instanceof AST_For || p instanceof AST_ForIn; + parenthesize_for_noin(self.value, output, noin); + } + }); + + /* -----[ other expressions ]----- */ + DEFPRINT(AST_Call, function(self, output){ + self.expression.print(output); + if (self instanceof AST_New && no_constructor_parens(self, output)) + return; + output.with_parens(function(){ + self.args.forEach(function(expr, i){ + if (i) output.comma(); + expr.print(output); + }); + }); + }); + DEFPRINT(AST_New, function(self, output){ + output.print("new"); + output.space(); + AST_Call.prototype._codegen(self, output); + }); + + AST_Seq.DEFMETHOD("_do_print", function(output){ + this.car.print(output); + if (this.cdr) { + output.comma(); + if (output.should_break()) { + output.newline(); + output.indent(); + } + this.cdr.print(output); + } + }); + DEFPRINT(AST_Seq, function(self, output){ + self._do_print(output); + // var p = output.parent(); + // if (p instanceof AST_Statement) { + // output.with_indent(output.next_indent(), function(){ + // self._do_print(output); + // }); + // } else { + // self._do_print(output); + // } + }); + DEFPRINT(AST_Dot, function(self, output){ + var expr = self.expression; + expr.print(output); + if (expr instanceof AST_Number && expr.getValue() >= 0) { + if (!/[xa-f.]/i.test(output.last())) { + output.print("."); + } + } + output.print("."); + // the name after dot would be mapped about here. + output.add_mapping(self.end); + output.print_name(self.property); + }); + DEFPRINT(AST_Sub, function(self, output){ + self.expression.print(output); + output.print("["); + self.property.print(output); + output.print("]"); + }); + DEFPRINT(AST_UnaryPrefix, function(self, output){ + var op = self.operator; + output.print(op); + if (/^[a-z]/i.test(op)) + output.space(); + self.expression.print(output); + }); + DEFPRINT(AST_UnaryPostfix, function(self, output){ + self.expression.print(output); + output.print(self.operator); + }); + DEFPRINT(AST_Binary, function(self, output){ + self.left.print(output); + output.space(); + output.print(self.operator); + output.space(); + self.right.print(output); + }); + DEFPRINT(AST_Conditional, function(self, output){ + self.condition.print(output); + output.space(); + output.print("?"); + output.space(); + self.consequent.print(output); + output.space(); + output.colon(); + self.alternative.print(output); + }); + + /* -----[ literals ]----- */ + DEFPRINT(AST_Array, function(self, output){ + output.with_square(function(){ + var a = self.elements, len = a.length; + if (len > 0) output.space(); + a.forEach(function(exp, i){ + if (i) output.comma(); + exp.print(output); + }); + if (len > 0) output.space(); + }); + }); + DEFPRINT(AST_Object, function(self, output){ + if (self.properties.length > 0) output.with_block(function(){ + self.properties.forEach(function(prop, i){ + if (i) { + output.print(","); + output.newline(); + } + output.indent(); + prop.print(output); + }); + output.newline(); + }); + else output.print("{}"); + }); + DEFPRINT(AST_ObjectKeyVal, function(self, output){ + var key = self.key; + if (output.option("quote_keys")) { + output.print_string(key + ""); + } else if ((typeof key == "number" + || !output.option("beautify") + && +key + "" == key) + && parseFloat(key) >= 0) { + output.print(make_num(key)); + } else if (!is_identifier(key)) { + output.print_string(key); + } else { + output.print_name(key); + } + output.colon(); + self.value.print(output); + }); + DEFPRINT(AST_ObjectSetter, function(self, output){ + output.print("set"); + self.value._do_print(output, true); + }); + DEFPRINT(AST_ObjectGetter, function(self, output){ + output.print("get"); + self.value._do_print(output, true); + }); + DEFPRINT(AST_Symbol, function(self, output){ + var def = self.definition(); + output.print_name(def ? def.mangled_name || def.name : self.name); + }); + DEFPRINT(AST_Undefined, function(self, output){ + output.print("void 0"); + }); + DEFPRINT(AST_Hole, noop); + DEFPRINT(AST_Infinity, function(self, output){ + output.print("1/0"); + }); + DEFPRINT(AST_NaN, function(self, output){ + output.print("0/0"); + }); + DEFPRINT(AST_This, function(self, output){ + output.print("this"); + }); + DEFPRINT(AST_Constant, function(self, output){ + output.print(self.getValue()); + }); + DEFPRINT(AST_String, function(self, output){ + output.print_string(self.getValue()); + }); + DEFPRINT(AST_Number, function(self, output){ + output.print(make_num(self.getValue())); + }); + DEFPRINT(AST_RegExp, function(self, output){ + var str = self.getValue().toString(); + if (output.option("ascii_only")) + str = output.to_ascii(str); + output.print(str); + var p = output.parent(); + if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self) + output.print(" "); + }); + + function force_statement(stat, output) { + if (output.option("bracketize")) { + if (!stat || stat instanceof AST_EmptyStatement) + output.print("{}"); + else if (stat instanceof AST_BlockStatement) + stat.print(output); + else output.with_block(function(){ + output.indent(); + stat.print(output); + output.newline(); + }); + } else { + if (!stat || stat instanceof AST_EmptyStatement) + output.force_semicolon(); + else + stat.print(output); + } + }; + + // return true if the node at the top of the stack (that means the + // innermost node in the current output) is lexically the first in + // a statement. + function first_in_statement(output) { + var a = output.stack(), i = a.length, node = a[--i], p = a[--i]; + while (i > 0) { + if (p instanceof AST_Statement && p.body === node) + return true; + if ((p instanceof AST_Seq && p.car === node ) || + (p instanceof AST_Call && p.expression === node ) || + (p instanceof AST_Dot && p.expression === node ) || + (p instanceof AST_Sub && p.expression === node ) || + (p instanceof AST_Conditional && p.condition === node ) || + (p instanceof AST_Binary && p.left === node ) || + (p instanceof AST_UnaryPostfix && p.expression === node )) + { + node = p; + p = a[--i]; + } else { + return false; + } + } + }; + + // self should be AST_New. decide if we want to show parens or not. + function no_constructor_parens(self, output) { + return self.args.length == 0 && !output.option("beautify"); + }; + + function best_of(a) { + var best = a[0], len = best.length; + for (var i = 1; i < a.length; ++i) { + if (a[i].length < len) { + best = a[i]; + len = best.length; + } + } + return best; + }; + + function make_num(num) { + var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m; + if (Math.floor(num) === num) { + if (num >= 0) { + a.push("0x" + num.toString(16).toLowerCase(), // probably pointless + "0" + num.toString(8)); // same. + } else { + a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless + "-0" + (-num).toString(8)); // same. + } + if ((m = /^(.*?)(0+)$/.exec(num))) { + a.push(m[1] + "e" + m[2].length); + } + } else if ((m = /^0?\.(0+)(.*)$/.exec(num))) { + a.push(m[2] + "e-" + (m[1].length + m[2].length), + str.substr(str.indexOf("."))); + } + return best_of(a); + }; + + function make_block(stmt, output) { + if (stmt instanceof AST_BlockStatement) { + stmt.print(output); + return; + } + output.with_block(function(){ + output.indent(); + stmt.print(output); + output.newline(); + }); + }; + + /* -----[ source map generators ]----- */ + + function DEFMAP(nodetype, generator) { + nodetype.DEFMETHOD("add_source_map", function(stream){ + generator(this, stream); + }); + }; + + // We could easily add info for ALL nodes, but it seems to me that + // would be quite wasteful, hence this noop in the base class. + DEFMAP(AST_Node, noop); + + function basic_sourcemap_gen(self, output) { + output.add_mapping(self.start); + }; + + // XXX: I'm not exactly sure if we need it for all of these nodes, + // or if we should add even more. + + DEFMAP(AST_Directive, basic_sourcemap_gen); + DEFMAP(AST_Debugger, basic_sourcemap_gen); + DEFMAP(AST_Symbol, basic_sourcemap_gen); + DEFMAP(AST_Jump, basic_sourcemap_gen); + DEFMAP(AST_StatementWithBody, basic_sourcemap_gen); + DEFMAP(AST_LabeledStatement, noop); // since the label symbol will mark it + DEFMAP(AST_Lambda, basic_sourcemap_gen); + DEFMAP(AST_Switch, basic_sourcemap_gen); + DEFMAP(AST_SwitchBranch, basic_sourcemap_gen); + DEFMAP(AST_BlockStatement, basic_sourcemap_gen); + DEFMAP(AST_Toplevel, noop); + DEFMAP(AST_New, basic_sourcemap_gen); + DEFMAP(AST_Try, basic_sourcemap_gen); + DEFMAP(AST_Catch, basic_sourcemap_gen); + DEFMAP(AST_Finally, basic_sourcemap_gen); + DEFMAP(AST_Definitions, basic_sourcemap_gen); + DEFMAP(AST_Constant, basic_sourcemap_gen); + DEFMAP(AST_ObjectProperty, function(self, output){ + output.add_mapping(self.start, self.key); + }); + +})(); diff --git a/homework8/project_express/node_modules/uglify-js/lib/parse.js b/homework8/project_express/node_modules/uglify-js/lib/parse.js new file mode 100644 index 0000000..da39b5b --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/lib/parse.js @@ -0,0 +1,1401 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + Parser based on parse-js (http://marijn.haverbeke.nl/parse-js/). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +var KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with'; +var KEYWORDS_ATOM = 'false null true'; +var RESERVED_WORDS = '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 this throws transient volatile' + + " " + KEYWORDS_ATOM + " " + KEYWORDS; +var KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case'; + +KEYWORDS = makePredicate(KEYWORDS); +RESERVED_WORDS = makePredicate(RESERVED_WORDS); +KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION); +KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM); + +var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^")); + +var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i; +var RE_OCT_NUMBER = /^0[0-7]+$/; +var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i; + +var OPERATORS = makePredicate([ + "in", + "instanceof", + "typeof", + "new", + "void", + "delete", + "++", + "--", + "+", + "-", + "!", + "~", + "&", + "|", + "^", + "*", + "/", + "%", + ">>", + "<<", + ">>>", + "<", + ">", + "<=", + ">=", + "==", + "===", + "!=", + "!==", + "?", + "=", + "+=", + "-=", + "/=", + "*=", + "%=", + ">>=", + "<<=", + ">>>=", + "|=", + "^=", + "&=", + "&&", + "||" +]); + +var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000")); + +var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:")); + +var PUNC_CHARS = makePredicate(characters("[]{}(),;:")); + +var REGEXP_MODIFIERS = makePredicate(characters("gmsiy")); + +/* -----[ Tokenizer ]----- */ + +// regexps adapted from http://xregexp.com/plugins/#unicode +var UNICODE = { + letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0523\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0621-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971\\u0972\\u097B-\\u097F\\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-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D28\\u0D2A-\\u0D39\\u0D3D\\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\\u0EDD\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8B\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10D0-\\u10FA\\u10FC\\u1100-\\u1159\\u115F-\\u11A2\\u11A8-\\u11F9\\u1200-\\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-\\u1676\\u1681-\\u169A\\u16A0-\\u16EA\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19A9\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\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-\\u2094\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2C6F\\u2C71-\\u2C7D\\u2C80-\\u2CE4\\u2D00-\\u2D25\\u2D30-\\u2D65\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31B7\\u31F0-\\u31FF\\u3400\\u4DB5\\u4E00\\u9FC3\\uA000-\\uA48C\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA65F\\uA662-\\uA66E\\uA67F-\\uA697\\uA717-\\uA71F\\uA722-\\uA788\\uA78B\\uA78C\\uA7FB-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA90A-\\uA925\\uA930-\\uA946\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAC00\\uD7A3\\uF900-\\uFA2D\\uFA30-\\uFA6A\\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]"), + non_spacing_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065E\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0900-\\u0902\\u093C\\u0941-\\u0948\\u094D\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09BC\\u09C1-\\u09C4\\u09CD\\u09E2\\u09E3\\u0A01\\u0A02\\u0A3C\\u0A41\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81\\u0A82\\u0ABC\\u0AC1-\\u0AC5\\u0AC7\\u0AC8\\u0ACD\\u0AE2\\u0AE3\\u0B01\\u0B3C\\u0B3F\\u0B41-\\u0B44\\u0B4D\\u0B56\\u0B62\\u0B63\\u0B82\\u0BC0\\u0BCD\\u0C3E-\\u0C40\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0CBC\\u0CBF\\u0CC6\\u0CCC\\u0CCD\\u0CE2\\u0CE3\\u0D41-\\u0D44\\u0D4D\\u0D62\\u0D63\\u0DCA\\u0DD2-\\u0DD4\\u0DD6\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F71-\\u0F7E\\u0F80-\\u0F84\\u0F86\\u0F87\\u0F90-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102D-\\u1030\\u1032-\\u1037\\u1039\\u103A\\u103D\\u103E\\u1058\\u1059\\u105E-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108D\\u109D\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B7-\\u17BD\\u17C6\\u17C9-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193B\\u1A17\\u1A18\\u1A56\\u1A58-\\u1A5E\\u1A60\\u1A62\\u1A65-\\u1A6C\\u1A73-\\u1A7C\\u1A7F\\u1B00-\\u1B03\\u1B34\\u1B36-\\u1B3A\\u1B3C\\u1B42\\u1B6B-\\u1B73\\u1B80\\u1B81\\u1BA2-\\u1BA5\\u1BA8\\u1BA9\\u1C2C-\\u1C33\\u1C36\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE0\\u1CE2-\\u1CE8\\u1CED\\u1DC0-\\u1DE6\\u1DFD-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA67C\\uA67D\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA825\\uA826\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA951\\uA980-\\uA982\\uA9B3\\uA9B6-\\uA9B9\\uA9BC\\uAA29-\\uAA2E\\uAA31\\uAA32\\uAA35\\uAA36\\uAA43\\uAA4C\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uABE5\\uABE8\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"), + space_combining_mark: new RegExp("[\\u0903\\u093E-\\u0940\\u0949-\\u094C\\u094E\\u0982\\u0983\\u09BE-\\u09C0\\u09C7\\u09C8\\u09CB\\u09CC\\u09D7\\u0A03\\u0A3E-\\u0A40\\u0A83\\u0ABE-\\u0AC0\\u0AC9\\u0ACB\\u0ACC\\u0B02\\u0B03\\u0B3E\\u0B40\\u0B47\\u0B48\\u0B4B\\u0B4C\\u0B57\\u0BBE\\u0BBF\\u0BC1\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCC\\u0BD7\\u0C01-\\u0C03\\u0C41-\\u0C44\\u0C82\\u0C83\\u0CBE\\u0CC0-\\u0CC4\\u0CC7\\u0CC8\\u0CCA\\u0CCB\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D40\\u0D46-\\u0D48\\u0D4A-\\u0D4C\\u0D57\\u0D82\\u0D83\\u0DCF-\\u0DD1\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0F3E\\u0F3F\\u0F7F\\u102B\\u102C\\u1031\\u1038\\u103B\\u103C\\u1056\\u1057\\u1062-\\u1064\\u1067-\\u106D\\u1083\\u1084\\u1087-\\u108C\\u108F\\u109A-\\u109C\\u17B6\\u17BE-\\u17C5\\u17C7\\u17C8\\u1923-\\u1926\\u1929-\\u192B\\u1930\\u1931\\u1933-\\u1938\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A19-\\u1A1B\\u1A55\\u1A57\\u1A61\\u1A63\\u1A64\\u1A6D-\\u1A72\\u1B04\\u1B35\\u1B3B\\u1B3D-\\u1B41\\u1B43\\u1B44\\u1B82\\u1BA1\\u1BA6\\u1BA7\\u1BAA\\u1C24-\\u1C2B\\u1C34\\u1C35\\u1CE1\\u1CF2\\uA823\\uA824\\uA827\\uA880\\uA881\\uA8B4-\\uA8C3\\uA952\\uA953\\uA983\\uA9B4\\uA9B5\\uA9BA\\uA9BB\\uA9BD-\\uA9C0\\uAA2F\\uAA30\\uAA33\\uAA34\\uAA4D\\uAA7B\\uABE3\\uABE4\\uABE6\\uABE7\\uABE9\\uABEA\\uABEC]"), + connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]") +}; + +function is_letter(code) { + return (code >= 97 && code <= 122) + || (code >= 65 && code <= 90) + || (code >= 0xaa && UNICODE.letter.test(String.fromCharCode(code))); +}; + +function is_digit(code) { + return code >= 48 && code <= 57; //XXX: find out if "UnicodeDigit" means something else than 0..9 +}; + +function is_alphanumeric_char(code) { + return is_digit(code) || is_letter(code); +}; + +function is_unicode_combining_mark(ch) { + return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch); +}; + +function is_unicode_connector_punctuation(ch) { + return UNICODE.connector_punctuation.test(ch); +}; + +function is_identifier(name) { + return !RESERVED_WORDS(name) && /^[a-z_$][a-z0-9_$]*$/i.test(name); +}; + +function is_identifier_start(code) { + return code == 36 || code == 95 || is_letter(code); +}; + +function is_identifier_char(ch) { + var code = ch.charCodeAt(0); + return is_identifier_start(code) + || is_digit(code) + || code == 8204 // \u200c: zero-width non-joiner + || code == 8205 // \u200d: zero-width joiner (in my ECMA-262 PDF, this is also 200c) + || is_unicode_combining_mark(ch) + || is_unicode_connector_punctuation(ch) + ; +}; + +function parse_js_number(num) { + if (RE_HEX_NUMBER.test(num)) { + return parseInt(num.substr(2), 16); + } else if (RE_OCT_NUMBER.test(num)) { + return parseInt(num.substr(1), 8); + } else if (RE_DEC_NUMBER.test(num)) { + return parseFloat(num); + } +}; + +function JS_Parse_Error(message, line, col, pos) { + this.message = message; + this.line = line; + this.col = col; + this.pos = pos; + this.stack = new Error().stack; +}; + +JS_Parse_Error.prototype.toString = function() { + return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack; +}; + +function js_error(message, filename, line, col, pos) { + throw new JS_Parse_Error(message, line, col, pos); +}; + +function is_token(token, type, val) { + return token.type == type && (val == null || token.value == val); +}; + +var EX_EOF = {}; + +function tokenizer($TEXT, filename) { + + var S = { + text : $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/\uFEFF/g, ''), + filename : filename, + pos : 0, + tokpos : 0, + line : 1, + tokline : 0, + col : 0, + tokcol : 0, + newline_before : false, + regex_allowed : false, + comments_before : [] + }; + + function peek() { return S.text.charAt(S.pos); }; + + function next(signal_eof, in_string) { + var ch = S.text.charAt(S.pos++); + if (signal_eof && !ch) + throw EX_EOF; + if (ch == "\n") { + S.newline_before = S.newline_before || !in_string; + ++S.line; + S.col = 0; + } else { + ++S.col; + } + return ch; + }; + + function find(what, signal_eof) { + var pos = S.text.indexOf(what, S.pos); + if (signal_eof && pos == -1) throw EX_EOF; + return pos; + }; + + function start_token() { + S.tokline = S.line; + S.tokcol = S.col; + S.tokpos = S.pos; + }; + + function token(type, value, is_comment) { + S.regex_allowed = ((type == "operator" && !UNARY_POSTFIX[value]) || + (type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value)) || + (type == "punc" && PUNC_BEFORE_EXPRESSION(value))); + var ret = { + type : type, + value : value, + line : S.tokline, + col : S.tokcol, + pos : S.tokpos, + endpos : S.pos, + nlb : S.newline_before, + file : filename + }; + if (!is_comment) { + ret.comments_before = S.comments_before; + S.comments_before = []; + // make note of any newlines in the comments that came before + for (var i = 0, len = ret.comments_before.length; i < len; i++) { + ret.nlb = ret.nlb || ret.comments_before[i].nlb; + } + } + S.newline_before = false; + return new AST_Token(ret); + }; + + function skip_whitespace() { + while (WHITESPACE_CHARS(peek())) + next(); + }; + + function read_while(pred) { + var ret = "", ch, i = 0; + while ((ch = peek()) && pred(ch, i++)) + ret += next(); + return ret; + }; + + function parse_error(err) { + js_error(err, filename, S.tokline, S.tokcol, S.tokpos); + }; + + function read_num(prefix) { + var has_e = false, after_e = false, has_x = false, has_dot = prefix == "."; + var num = read_while(function(ch, i){ + var code = ch.charCodeAt(0); + switch (code) { + case 120: case 88: // xX + return has_x ? false : (has_x = true); + case 101: case 69: // eE + return has_x ? true : has_e ? false : (has_e = after_e = true); + case 45: // - + return after_e || (i == 0 && !prefix); + case 43: // + + return after_e; + case (after_e = false, 46): // . + return (!has_dot && !has_x && !has_e) ? (has_dot = true) : false; + } + return is_alphanumeric_char(code); + }); + if (prefix) num = prefix + num; + var valid = parse_js_number(num); + if (!isNaN(valid)) { + return token("num", valid); + } else { + parse_error("Invalid syntax: " + num); + } + }; + + function read_escaped_char(in_string) { + var ch = next(true, in_string); + switch (ch.charCodeAt(0)) { + case 110 : return "\n"; + case 114 : return "\r"; + case 116 : return "\t"; + case 98 : return "\b"; + case 118 : return "\u000b"; // \v + case 102 : return "\f"; + case 48 : return "\0"; + case 120 : return String.fromCharCode(hex_bytes(2)); // \x + case 117 : return String.fromCharCode(hex_bytes(4)); // \u + case 10 : return ""; // newline + default : return ch; + } + }; + + function hex_bytes(n) { + var num = 0; + for (; n > 0; --n) { + var digit = parseInt(next(true), 16); + if (isNaN(digit)) + parse_error("Invalid hex-character pattern in string"); + num = (num << 4) | digit; + } + return num; + }; + + var read_string = with_eof_error("Unterminated string constant", function(){ + var quote = next(), ret = ""; + for (;;) { + var ch = next(true); + if (ch == "\\") { + // read OctalEscapeSequence (XXX: deprecated if "strict mode") + // https://github.com/mishoo/UglifyJS/issues/178 + var octal_len = 0, first = null; + ch = read_while(function(ch){ + if (ch >= "0" && ch <= "7") { + if (!first) { + first = ch; + return ++octal_len; + } + else if (first <= "3" && octal_len <= 2) return ++octal_len; + else if (first >= "4" && octal_len <= 1) return ++octal_len; + } + return false; + }); + if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8)); + else ch = read_escaped_char(true); + } + else if (ch == quote) break; + ret += ch; + } + return token("string", ret); + }); + + function read_line_comment() { + next(); + var i = find("\n"), ret; + if (i == -1) { + ret = S.text.substr(S.pos); + S.pos = S.text.length; + } else { + ret = S.text.substring(S.pos, i); + S.pos = i; + } + return token("comment1", ret, true); + }; + + var read_multiline_comment = with_eof_error("Unterminated multiline comment", function(){ + next(); + var i = find("*/", true); + var text = S.text.substring(S.pos, i); + var a = text.split("\n"), n = a.length; + // update stream position + S.pos = i + 2; + S.line += n - 1; + if (n > 1) S.col = a[n - 1].length; + else S.col += a[n - 1].length; + S.col += 2; + S.newline_before = S.newline_before || text.indexOf("\n") >= 0; + return token("comment2", text, true); + }); + + function read_name() { + var backslash = false, name = "", ch, escaped = false, hex; + while ((ch = peek()) != null) { + if (!backslash) { + if (ch == "\\") escaped = backslash = true, next(); + else if (is_identifier_char(ch)) name += next(); + else break; + } + else { + if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX"); + ch = read_escaped_char(); + if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier"); + name += ch; + backslash = false; + } + } + if (KEYWORDS(name) && escaped) { + hex = name.charCodeAt(0).toString(16).toUpperCase(); + name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1); + } + return name; + }; + + var read_regexp = with_eof_error("Unterminated regular expression", function(regexp){ + var prev_backslash = false, ch, in_class = false; + while ((ch = next(true))) if (prev_backslash) { + regexp += "\\" + ch; + prev_backslash = false; + } else if (ch == "[") { + in_class = true; + regexp += ch; + } else if (ch == "]" && in_class) { + in_class = false; + regexp += ch; + } else if (ch == "/" && !in_class) { + break; + } else if (ch == "\\") { + prev_backslash = true; + } else { + regexp += ch; + } + var mods = read_name(); + return token("regexp", new RegExp(regexp, mods)); + }); + + function read_operator(prefix) { + function grow(op) { + if (!peek()) return op; + var bigger = op + peek(); + if (OPERATORS(bigger)) { + next(); + return grow(bigger); + } else { + return op; + } + }; + return token("operator", grow(prefix || next())); + }; + + function handle_slash() { + next(); + var regex_allowed = S.regex_allowed; + switch (peek()) { + case "/": + S.comments_before.push(read_line_comment()); + S.regex_allowed = regex_allowed; + return next_token(); + case "*": + S.comments_before.push(read_multiline_comment()); + S.regex_allowed = regex_allowed; + return next_token(); + } + return S.regex_allowed ? read_regexp("") : read_operator("/"); + }; + + function handle_dot() { + next(); + return is_digit(peek().charCodeAt(0)) + ? read_num(".") + : token("punc", "."); + }; + + function read_word() { + var word = read_name(); + return KEYWORDS_ATOM(word) ? token("atom", word) + : !KEYWORDS(word) ? token("name", word) + : OPERATORS(word) ? token("operator", word) + : token("keyword", word); + }; + + function with_eof_error(eof_error, cont) { + return function(x) { + try { + return cont(x); + } catch(ex) { + if (ex === EX_EOF) parse_error(eof_error); + else throw ex; + } + }; + }; + + function next_token(force_regexp) { + if (force_regexp != null) + return read_regexp(force_regexp); + skip_whitespace(); + start_token(); + var ch = peek(); + if (!ch) return token("eof"); + var code = ch.charCodeAt(0); + switch (code) { + case 34: case 39: return read_string(); + case 46: return handle_dot(); + case 47: return handle_slash(); + } + if (is_digit(code)) return read_num(); + if (PUNC_CHARS(ch)) return token("punc", next()); + if (OPERATOR_CHARS(ch)) return read_operator(); + if (code == 92 || is_identifier_start(code)) return read_word(); + parse_error("Unexpected character '" + ch + "'"); + }; + + next_token.context = function(nc) { + if (nc) S = nc; + return S; + }; + + return next_token; + +}; + +/* -----[ Parser (constants) ]----- */ + +var UNARY_PREFIX = makePredicate([ + "typeof", + "void", + "delete", + "--", + "++", + "!", + "~", + "-", + "+" +]); + +var UNARY_POSTFIX = makePredicate([ "--", "++" ]); + +var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]); + +var PRECEDENCE = (function(a, ret){ + for (var i = 0, n = 1; i < a.length; ++i, ++n) { + var b = a[i]; + for (var j = 0; j < b.length; ++j) { + ret[b[j]] = n; + } + } + return ret; +})( + [ + ["||"], + ["&&"], + ["|"], + ["^"], + ["&"], + ["==", "===", "!=", "!=="], + ["<", ">", "<=", ">=", "in", "instanceof"], + [">>", "<<", ">>>"], + ["+", "-"], + ["*", "/", "%"] + ], + {} +); + +var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]); + +var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]); + +/* -----[ Parser ]----- */ + +function parse($TEXT, options) { + + options = defaults(options, { + strict : false, + filename : null, + toplevel : null + }); + + var S = { + input : typeof $TEXT == "string" ? tokenizer($TEXT, options.filename) : $TEXT, + token : null, + prev : null, + peeked : null, + in_function : 0, + in_directives : true, + in_loop : 0, + labels : [] + }; + + S.token = next(); + + function is(type, value) { + return is_token(S.token, type, value); + }; + + function peek() { return S.peeked || (S.peeked = S.input()); }; + + function next() { + S.prev = S.token; + if (S.peeked) { + S.token = S.peeked; + S.peeked = null; + } else { + S.token = S.input(); + } + S.in_directives = S.in_directives && ( + S.token.type == "string" || is("punc", ";") + ); + return S.token; + }; + + function prev() { + return S.prev; + }; + + function croak(msg, line, col, pos) { + var ctx = S.input.context(); + js_error(msg, + ctx.filename, + line != null ? line : ctx.tokline, + col != null ? col : ctx.tokcol, + pos != null ? pos : ctx.tokpos); + }; + + function token_error(token, msg) { + croak(msg, token.line, token.col); + }; + + function unexpected(token) { + if (token == null) + token = S.token; + token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")"); + }; + + function expect_token(type, val) { + if (is(type, val)) { + return next(); + } + token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»"); + }; + + function expect(punc) { return expect_token("punc", punc); }; + + function can_insert_semicolon() { + return !options.strict && ( + S.token.nlb || is("eof") || is("punc", "}") + ); + }; + + function semicolon() { + if (is("punc", ";")) next(); + else if (!can_insert_semicolon()) unexpected(); + }; + + function parenthesised() { + expect("("); + var exp = expression(true); + expect(")"); + return exp; + }; + + function embed_tokens(parser) { + return function() { + var start = S.token; + var expr = parser(); + var end = prev(); + expr.start = start; + expr.end = end; + return expr; + }; + }; + + var statement = embed_tokens(function() { + var tmp; + if (is("operator", "/") || is("operator", "/=")) { + S.peeked = null; + S.token = S.input(S.token.value.substr(1)); // force regexp + } + switch (S.token.type) { + case "string": + var dir = S.in_directives, stat = simple_statement(); + // XXXv2: decide how to fix directives + if (dir && stat.body instanceof AST_String && !is("punc", ",")) + return new AST_Directive({ value: stat.body.value }); + return stat; + case "num": + case "regexp": + case "operator": + case "atom": + return simple_statement(); + + case "name": + return is_token(peek(), "punc", ":") + ? labeled_statement() + : simple_statement(); + + case "punc": + switch (S.token.value) { + case "{": + return new AST_BlockStatement({ + start : S.token, + body : block_(), + end : prev() + }); + case "[": + case "(": + return simple_statement(); + case ";": + next(); + return new AST_EmptyStatement(); + default: + unexpected(); + } + + case "keyword": + switch (tmp = S.token.value, next(), tmp) { + case "break": + return break_cont(AST_Break); + + case "continue": + return break_cont(AST_Continue); + + case "debugger": + semicolon(); + return new AST_Debugger(); + + case "do": + return new AST_Do({ + body : in_loop(statement), + condition : (expect_token("keyword", "while"), tmp = parenthesised(), semicolon(), tmp) + }); + + case "while": + return new AST_While({ + condition : parenthesised(), + body : in_loop(statement) + }); + + case "for": + return for_(); + + case "function": + return function_(true); + + case "if": + return if_(); + + case "return": + if (S.in_function == 0) + croak("'return' outside of function"); + return new AST_Return({ + value: ( is("punc", ";") + ? (next(), null) + : can_insert_semicolon() + ? null + : (tmp = expression(true), semicolon(), tmp) ) + }); + + case "switch": + return new AST_Switch({ + expression : parenthesised(), + body : in_loop(switch_body_) + }); + + case "throw": + if (S.token.nlb) + croak("Illegal newline after 'throw'"); + return new AST_Throw({ + value: (tmp = expression(true), semicolon(), tmp) + }); + + case "try": + return try_(); + + case "var": + return tmp = var_(), semicolon(), tmp; + + case "const": + return tmp = const_(), semicolon(), tmp; + + case "with": + return new AST_With({ + expression : parenthesised(), + body : statement() + }); + + default: + unexpected(); + } + } + }); + + function labeled_statement() { + var label = as_symbol(AST_Label); + if (find_if(function(l){ return l.name == label.name }, S.labels)) { + // ECMA-262, 12.12: An ECMAScript program is considered + // syntactically incorrect if it contains a + // LabelledStatement that is enclosed by a + // LabelledStatement with the same Identifier as label. + croak("Label " + label.name + " defined twice"); + } + expect(":"); + S.labels.push(label); + var stat = statement(); + S.labels.pop(); + return new AST_LabeledStatement({ body: stat, label: label }); + }; + + function simple_statement(tmp) { + return new AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) }); + }; + + function break_cont(type) { + var label = null; + if (!can_insert_semicolon()) { + label = as_symbol(AST_LabelRef, true); + } + if (label != null) { + if (!find_if(function(l){ return l.name == label.name }, S.labels)) + croak("Undefined label " + label.name); + } + else if (S.in_loop == 0) + croak(type.TYPE + " not inside a loop or switch"); + semicolon(); + return new type({ label: label }); + }; + + function for_() { + expect("("); + var init = null; + if (!is("punc", ";")) { + init = is("keyword", "var") + ? (next(), var_(true)) + : expression(true, true); + if (is("operator", "in")) { + if (init instanceof AST_Var && init.definitions.length > 1) + croak("Only one variable declaration allowed in for..in loop"); + next(); + return for_in(init); + } + } + return regular_for(init); + }; + + function regular_for(init) { + expect(";"); + var test = is("punc", ";") ? null : expression(true); + expect(";"); + var step = is("punc", ")") ? null : expression(true); + expect(")"); + return new AST_For({ + init : init, + condition : test, + step : step, + body : in_loop(statement) + }); + }; + + function for_in(init) { + var lhs = init instanceof AST_Var ? init.definitions[0].name : null; + var obj = expression(true); + expect(")"); + return new AST_ForIn({ + init : init, + name : lhs, + object : obj, + body : in_loop(statement) + }); + }; + + var function_ = function(in_statement, ctor) { + var is_accessor = ctor === AST_Accessor; + var name = (is("name") ? as_symbol(in_statement + ? AST_SymbolDefun + : is_accessor + ? AST_SymbolAccessor + : AST_SymbolLambda) + : is_accessor && (is("string") || is("num")) ? as_atom_node() + : null); + if (in_statement && !name) + unexpected(); + expect("("); + if (!ctor) ctor = in_statement ? AST_Defun : AST_Function; + return new ctor({ + name: name, + argnames: (function(first, a){ + while (!is("punc", ")")) { + if (first) first = false; else expect(","); + a.push(as_symbol(AST_SymbolFunarg)); + } + next(); + return a; + })(true, []), + body: (function(loop, labels){ + ++S.in_function; + S.in_directives = true; + S.in_loop = 0; + S.labels = []; + var a = block_(); + --S.in_function; + S.in_loop = loop; + S.labels = labels; + return a; + })(S.in_loop, S.labels) + }); + }; + + function if_() { + var cond = parenthesised(), body = statement(), belse = null; + if (is("keyword", "else")) { + next(); + belse = statement(); + } + return new AST_If({ + condition : cond, + body : body, + alternative : belse + }); + }; + + function block_() { + expect("{"); + var a = []; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + a.push(statement()); + } + next(); + return a; + }; + + function switch_body_() { + expect("{"); + var a = [], cur = null, branch = null, tmp; + while (!is("punc", "}")) { + if (is("eof")) unexpected(); + if (is("keyword", "case")) { + if (branch) branch.end = prev(); + cur = []; + branch = new AST_Case({ + start : (tmp = S.token, next(), tmp), + expression : expression(true), + body : cur + }); + a.push(branch); + expect(":"); + } + else if (is("keyword", "default")) { + if (branch) branch.end = prev(); + cur = []; + branch = new AST_Default({ + start : (tmp = S.token, next(), expect(":"), tmp), + body : cur + }); + a.push(branch); + } + else { + if (!cur) unexpected(); + cur.push(statement()); + } + } + if (branch) branch.end = prev(); + next(); + return a; + }; + + function try_() { + var body = block_(), bcatch = null, bfinally = null; + if (is("keyword", "catch")) { + var start = S.token; + next(); + expect("("); + var name = as_symbol(AST_SymbolCatch); + expect(")"); + bcatch = new AST_Catch({ + start : start, + argname : name, + body : block_(), + end : prev() + }); + } + if (is("keyword", "finally")) { + var start = S.token; + next(); + bfinally = new AST_Finally({ + start : start, + body : block_(), + end : prev() + }); + } + if (!bcatch && !bfinally) + croak("Missing catch/finally blocks"); + return new AST_Try({ + body : body, + bcatch : bcatch, + bfinally : bfinally + }); + }; + + function vardefs(no_in, in_const) { + var a = []; + for (;;) { + a.push(new AST_VarDef({ + start : S.token, + name : as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar), + value : is("operator", "=") ? (next(), expression(false, no_in)) : null, + end : prev() + })); + if (!is("punc", ",")) + break; + next(); + } + return a; + }; + + var var_ = function(no_in) { + return new AST_Var({ + start : prev(), + definitions : vardefs(no_in, false), + end : prev() + }); + }; + + var const_ = function() { + return new AST_Const({ + start : prev(), + definitions : vardefs(false, true), + end : prev() + }); + }; + + var new_ = function() { + var start = S.token; + expect_token("operator", "new"); + var newexp = expr_atom(false), args; + if (is("punc", "(")) { + next(); + args = expr_list(")"); + } else { + args = []; + } + return subscripts(new AST_New({ + start : start, + expression : newexp, + args : args, + end : prev() + }), true); + }; + + function as_atom_node() { + var tok = S.token, ret; + switch (tok.type) { + case "name": + return as_symbol(AST_SymbolRef); + case "num": + ret = new AST_Number({ start: tok, end: tok, value: tok.value }); + break; + case "string": + ret = new AST_String({ start: tok, end: tok, value: tok.value }); + break; + case "regexp": + ret = new AST_RegExp({ start: tok, end: tok, value: tok.value }); + break; + case "atom": + switch (tok.value) { + case "false": + ret = new AST_False({ start: tok, end: tok }); + break; + case "true": + ret = new AST_True({ start: tok, end: tok }); + break; + case "null": + ret = new AST_Null({ start: tok, end: tok }); + break; + } + break; + } + next(); + return ret; + }; + + var expr_atom = function(allow_calls) { + if (is("operator", "new")) { + return new_(); + } + var start = S.token; + if (is("punc")) { + switch (start.value) { + case "(": + next(); + var ex = expression(true); + ex.start = start; + ex.end = S.token; + expect(")"); + return subscripts(ex, allow_calls); + case "[": + return subscripts(array_(), allow_calls); + case "{": + return subscripts(object_(), allow_calls); + } + unexpected(); + } + if (is("keyword", "function")) { + next(); + var func = function_(false); + func.start = start; + func.end = prev(); + return subscripts(func, allow_calls); + } + if (ATOMIC_START_TOKEN[S.token.type]) { + return subscripts(as_atom_node(), allow_calls); + } + unexpected(); + }; + + function expr_list(closing, allow_trailing_comma, allow_empty) { + var first = true, a = []; + while (!is("punc", closing)) { + if (first) first = false; else expect(","); + if (allow_trailing_comma && is("punc", closing)) break; + if (is("punc", ",") && allow_empty) { + a.push(new AST_Hole({ start: S.token, end: S.token })); + } else { + a.push(expression(false)); + } + } + next(); + return a; + }; + + var array_ = embed_tokens(function() { + expect("["); + return new AST_Array({ + elements: expr_list("]", !options.strict, true) + }); + }); + + var object_ = embed_tokens(function() { + expect("{"); + var first = true, a = []; + while (!is("punc", "}")) { + if (first) first = false; else expect(","); + if (!options.strict && is("punc", "}")) + // allow trailing comma + break; + var start = S.token; + var type = start.type; + var name = as_property_name(); + if (type == "name" && !is("punc", ":")) { + if (name == "get") { + a.push(new AST_ObjectGetter({ + start : start, + key : name, + value : function_(false, AST_Accessor), + end : prev() + })); + continue; + } + if (name == "set") { + a.push(new AST_ObjectSetter({ + start : start, + key : name, + value : function_(false, AST_Accessor), + end : prev() + })); + continue; + } + } + expect(":"); + a.push(new AST_ObjectKeyVal({ + start : start, + key : name, + value : expression(false), + end : prev() + })); + } + next(); + return new AST_Object({ properties: a }); + }); + + function as_property_name() { + var tmp = S.token; + next(); + switch (tmp.type) { + case "num": + case "string": + case "name": + case "operator": + case "keyword": + case "atom": + return tmp.value; + default: + unexpected(); + } + }; + + function as_name() { + var tmp = S.token; + next(); + switch (tmp.type) { + case "name": + case "operator": + case "keyword": + case "atom": + return tmp.value; + default: + unexpected(); + } + }; + + function as_symbol(type, noerror) { + if (!is("name")) { + if (!noerror) croak("Name expected"); + return null; + } + var name = S.token.value; + var sym = new (name == "this" ? AST_This : type)({ + name : String(S.token.value), + start : S.token, + end : S.token + }); + next(); + return sym; + }; + + var subscripts = function(expr, allow_calls) { + var start = expr.start; + if (is("punc", ".")) { + next(); + return subscripts(new AST_Dot({ + start : start, + expression : expr, + property : as_name(), + end : prev() + }), allow_calls); + } + if (is("punc", "[")) { + next(); + var prop = expression(true); + expect("]"); + return subscripts(new AST_Sub({ + start : start, + expression : expr, + property : prop, + end : prev() + }), allow_calls); + } + if (allow_calls && is("punc", "(")) { + next(); + return subscripts(new AST_Call({ + start : start, + expression : expr, + args : expr_list(")"), + end : prev() + }), true); + } + return expr; + }; + + var maybe_unary = function(allow_calls) { + var start = S.token; + if (is("operator") && UNARY_PREFIX(start.value)) { + next(); + var ex = make_unary(AST_UnaryPrefix, start.value, maybe_unary(allow_calls)); + ex.start = start; + ex.end = prev(); + return ex; + } + var val = expr_atom(allow_calls); + while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) { + val = make_unary(AST_UnaryPostfix, S.token.value, val); + val.start = start; + val.end = S.token; + next(); + } + return val; + }; + + function make_unary(ctor, op, expr) { + if ((op == "++" || op == "--") && !is_assignable(expr)) + croak("Invalid use of " + op + " operator"); + return new ctor({ operator: op, expression: expr }); + }; + + var expr_op = function(left, min_prec, no_in) { + var op = is("operator") ? S.token.value : null; + if (op == "in" && no_in) op = null; + var prec = op != null ? PRECEDENCE[op] : null; + if (prec != null && prec > min_prec) { + next(); + var right = expr_op(maybe_unary(true), prec, no_in); + return expr_op(new AST_Binary({ + start : left.start, + left : left, + operator : op, + right : right, + end : right.end + }), min_prec, no_in); + } + return left; + }; + + function expr_ops(no_in) { + return expr_op(maybe_unary(true), 0, no_in); + }; + + var maybe_conditional = function(no_in) { + var start = S.token; + var expr = expr_ops(no_in); + if (is("operator", "?")) { + next(); + var yes = expression(false); + expect(":"); + return new AST_Conditional({ + start : start, + condition : expr, + consequent : yes, + alternative : expression(false, no_in), + end : peek() + }); + } + return expr; + }; + + function is_assignable(expr) { + if (!options.strict) return true; + switch (expr[0]+"") { + case "dot": + case "sub": + case "new": + case "call": + return true; + case "name": + return expr[1] != "this"; + } + }; + + var maybe_assign = function(no_in) { + var start = S.token; + var left = maybe_conditional(no_in), val = S.token.value; + if (is("operator") && ASSIGNMENT(val)) { + if (is_assignable(left)) { + next(); + return new AST_Assign({ + start : start, + left : left, + operator : val, + right : maybe_assign(no_in), + end : prev() + }); + } + croak("Invalid assignment"); + } + return left; + }; + + var expression = function(commas, no_in) { + var start = S.token; + var expr = maybe_assign(no_in); + if (commas && is("punc", ",")) { + next(); + return new AST_Seq({ + start : start, + car : expr, + cdr : expression(true, no_in), + end : peek() + }); + } + return expr; + }; + + function in_loop(cont) { + ++S.in_loop; + var ret = cont(); + --S.in_loop; + return ret; + }; + + return (function(){ + var start = S.token; + var body = []; + while (!is("eof")) + body.push(statement()); + var end = prev(); + var toplevel = options.toplevel; + if (toplevel) { + toplevel.body = toplevel.body.concat(body); + toplevel.end = end; + } else { + toplevel = new AST_Toplevel({ start: start, body: body, end: end }); + } + return toplevel; + })(); + +}; diff --git a/homework8/project_express/node_modules/uglify-js/lib/scope.js b/homework8/project_express/node_modules/uglify-js/lib/scope.js new file mode 100644 index 0000000..ea27163 --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/lib/scope.js @@ -0,0 +1,580 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function SymbolDef(scope, index, orig) { + this.name = orig.name; + this.orig = [ orig ]; + this.scope = scope; + this.references = []; + this.global = false; + this.mangled_name = null; + this.undeclared = false; + this.constant = false; + this.index = index; +}; + +SymbolDef.prototype = { + unmangleable: function(options) { + return (this.global && !(options && options.toplevel)) + || this.undeclared + || (!(options && options.eval) && (this.scope.uses_eval || this.scope.uses_with)); + }, + mangle: function(options) { + if (!this.mangled_name && !this.unmangleable(options)) { + var s = this.scope; + if (this.orig[0] instanceof AST_SymbolLambda && !options.screw_ie8) + s = s.parent_scope; + this.mangled_name = s.next_mangled(options); + } + } +}; + +AST_Toplevel.DEFMETHOD("figure_out_scope", function(){ + // This does what ast_add_scope did in UglifyJS v1. + // + // Part of it could be done at parse time, but it would complicate + // the parser (and it's already kinda complex). It's also worth + // having it separated because we might need to call it multiple + // times on the same tree. + + // pass 1: setup scope chaining and handle definitions + var self = this; + var scope = self.parent_scope = null; + var labels = new Dictionary(); + var nesting = 0; + var tw = new TreeWalker(function(node, descend){ + if (node instanceof AST_Scope) { + node.init_scope_vars(nesting); + var save_scope = node.parent_scope = scope; + var save_labels = labels; + ++nesting; + scope = node; + labels = new Dictionary(); + descend(); + labels = save_labels; + scope = save_scope; + --nesting; + return true; // don't descend again in TreeWalker + } + if (node instanceof AST_Directive) { + node.scope = scope; + push_uniq(scope.directives, node.value); + return true; + } + if (node instanceof AST_With) { + for (var s = scope; s; s = s.parent_scope) + s.uses_with = true; + return; + } + if (node instanceof AST_LabeledStatement) { + var l = node.label; + if (labels.has(l.name)) + throw new Error(string_template("Label {name} defined twice", l)); + labels.set(l.name, l); + descend(); + labels.del(l.name); + return true; // no descend again + } + if (node instanceof AST_Symbol) { + node.scope = scope; + } + if (node instanceof AST_Label) { + node.thedef = node; + node.init_scope_vars(); + } + if (node instanceof AST_SymbolLambda) { + scope.def_function(node); + } + else if (node instanceof AST_SymbolDefun) { + // Careful here, the scope where this should be defined is + // the parent scope. The reason is that we enter a new + // scope when we encounter the AST_Defun node (which is + // instanceof AST_Scope) but we get to the symbol a bit + // later. + (node.scope = scope.parent_scope).def_function(node); + } + else if (node instanceof AST_SymbolVar + || node instanceof AST_SymbolConst) { + var def = scope.def_variable(node); + def.constant = node instanceof AST_SymbolConst; + def.init = tw.parent().value; + } + else if (node instanceof AST_SymbolCatch) { + // XXX: this is wrong according to ECMA-262 (12.4). the + // `catch` argument name should be visible only inside the + // catch block. For a quick fix AST_Catch should inherit + // from AST_Scope. Keeping it this way because of IE, + // which doesn't obey the standard. (it introduces the + // identifier in the enclosing scope) + scope.def_variable(node); + } + if (node instanceof AST_LabelRef) { + var sym = labels.get(node.name); + if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", { + name: node.name, + line: node.start.line, + col: node.start.col + })); + node.thedef = sym; + } + }); + self.walk(tw); + + // pass 2: find back references and eval + var func = null; + var globals = self.globals = new Dictionary(); + var tw = new TreeWalker(function(node, descend){ + if (node instanceof AST_Lambda) { + var prev_func = func; + func = node; + descend(); + func = prev_func; + return true; + } + if (node instanceof AST_LabelRef) { + node.reference(); + return true; + } + if (node instanceof AST_SymbolRef) { + var name = node.name; + var sym = node.scope.find_variable(name); + if (!sym) { + var g; + if (globals.has(name)) { + g = globals.get(name); + } else { + g = new SymbolDef(self, globals.size(), node); + g.undeclared = true; + globals.set(name, g); + } + node.thedef = g; + if (name == "eval" && tw.parent() instanceof AST_Call) { + for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) + s.uses_eval = true; + } + if (name == "arguments") { + func.uses_arguments = true; + } + } else { + node.thedef = sym; + } + node.reference(); + return true; + } + }); + self.walk(tw); +}); + +AST_Scope.DEFMETHOD("init_scope_vars", function(nesting){ + this.directives = []; // contains the directives defined in this scope, i.e. "use strict" + this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions) + this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope) + this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement + this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval` + this.parent_scope = null; // the parent scope + this.enclosed = []; // a list of variables from this or outer scope(s) that are referenced from this or inner scopes + this.cname = -1; // the current index for mangling functions/variables + this.nesting = nesting; // the nesting level of this scope (0 means toplevel) +}); + +AST_Scope.DEFMETHOD("strict", function(){ + return this.has_directive("use strict"); +}); + +AST_Lambda.DEFMETHOD("init_scope_vars", function(){ + AST_Scope.prototype.init_scope_vars.apply(this, arguments); + this.uses_arguments = false; +}); + +AST_SymbolRef.DEFMETHOD("reference", function() { + var def = this.definition(); + def.references.push(this); + var s = this.scope; + while (s) { + push_uniq(s.enclosed, def); + if (s === def.scope) break; + s = s.parent_scope; + } + this.frame = this.scope.nesting - def.scope.nesting; +}); + +AST_Label.DEFMETHOD("init_scope_vars", function(){ + this.references = []; +}); + +AST_LabelRef.DEFMETHOD("reference", function(){ + this.thedef.references.push(this); +}); + +AST_Scope.DEFMETHOD("find_variable", function(name){ + if (name instanceof AST_Symbol) name = name.name; + return this.variables.get(name) + || (this.parent_scope && this.parent_scope.find_variable(name)); +}); + +AST_Scope.DEFMETHOD("has_directive", function(value){ + return this.parent_scope && this.parent_scope.has_directive(value) + || (this.directives.indexOf(value) >= 0 ? this : null); +}); + +AST_Scope.DEFMETHOD("def_function", function(symbol){ + this.functions.set(symbol.name, this.def_variable(symbol)); +}); + +AST_Scope.DEFMETHOD("def_variable", function(symbol){ + var def; + if (!this.variables.has(symbol.name)) { + def = new SymbolDef(this, this.variables.size(), symbol); + this.variables.set(symbol.name, def); + def.global = !this.parent_scope; + } else { + def = this.variables.get(symbol.name); + def.orig.push(symbol); + } + return symbol.thedef = def; +}); + +AST_Scope.DEFMETHOD("next_mangled", function(options){ + var ext = this.enclosed; + out: while (true) { + var m = base54(++this.cname); + if (!is_identifier(m)) continue; // skip over "do" + // we must ensure that the mangled name does not shadow a name + // from some parent scope that is referenced in this or in + // inner scopes. + for (var i = ext.length; --i >= 0;) { + var sym = ext[i]; + var name = sym.mangled_name || (sym.unmangleable(options) && sym.name); + if (m == name) continue out; + } + return m; + } +}); + +AST_Scope.DEFMETHOD("references", function(sym){ + if (sym instanceof AST_Symbol) sym = sym.definition(); + return this.enclosed.indexOf(sym) < 0 ? null : sym; +}); + +AST_Symbol.DEFMETHOD("unmangleable", function(options){ + return this.definition().unmangleable(options); +}); + +// property accessors are not mangleable +AST_SymbolAccessor.DEFMETHOD("unmangleable", function(){ + return true; +}); + +// labels are always mangleable +AST_Label.DEFMETHOD("unmangleable", function(){ + return false; +}); + +AST_Symbol.DEFMETHOD("unreferenced", function(){ + return this.definition().references.length == 0 + && !(this.scope.uses_eval || this.scope.uses_with); +}); + +AST_Symbol.DEFMETHOD("undeclared", function(){ + return this.definition().undeclared; +}); + +AST_LabelRef.DEFMETHOD("undeclared", function(){ + return false; +}); + +AST_Label.DEFMETHOD("undeclared", function(){ + return false; +}); + +AST_Symbol.DEFMETHOD("definition", function(){ + return this.thedef; +}); + +AST_Symbol.DEFMETHOD("global", function(){ + return this.definition().global; +}); + +AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){ + return defaults(options, { + except : [], + eval : false, + sort : false, + toplevel : false, + screw_ie8 : false + }); +}); + +AST_Toplevel.DEFMETHOD("mangle_names", function(options){ + options = this._default_mangler_options(options); + // We only need to mangle declaration nodes. Special logic wired + // into the code generator will display the mangled name if it's + // present (and for AST_SymbolRef-s it'll use the mangled name of + // the AST_SymbolDeclaration that it points to). + var lname = -1; + var to_mangle = []; + var tw = new TreeWalker(function(node, descend){ + if (node instanceof AST_LabeledStatement) { + // lname is incremented when we get to the AST_Label + var save_nesting = lname; + descend(); + lname = save_nesting; + return true; // don't descend again in TreeWalker + } + if (node instanceof AST_Scope) { + var p = tw.parent(), a = []; + node.variables.each(function(symbol){ + if (options.except.indexOf(symbol.name) < 0) { + a.push(symbol); + } + }); + if (options.sort) a.sort(function(a, b){ + return b.references.length - a.references.length; + }); + to_mangle.push.apply(to_mangle, a); + return; + } + if (node instanceof AST_Label) { + var name; + do name = base54(++lname); while (!is_identifier(name)); + node.mangled_name = name; + return true; + } + }); + this.walk(tw); + to_mangle.forEach(function(def){ def.mangle(options) }); +}); + +AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){ + options = this._default_mangler_options(options); + var tw = new TreeWalker(function(node){ + if (node instanceof AST_Constant) + base54.consider(node.print_to_string()); + else if (node instanceof AST_Return) + base54.consider("return"); + else if (node instanceof AST_Throw) + base54.consider("throw"); + else if (node instanceof AST_Continue) + base54.consider("continue"); + else if (node instanceof AST_Break) + base54.consider("break"); + else if (node instanceof AST_Debugger) + base54.consider("debugger"); + else if (node instanceof AST_Directive) + base54.consider(node.value); + else if (node instanceof AST_While) + base54.consider("while"); + else if (node instanceof AST_Do) + base54.consider("do while"); + else if (node instanceof AST_If) { + base54.consider("if"); + if (node.alternative) base54.consider("else"); + } + else if (node instanceof AST_Var) + base54.consider("var"); + else if (node instanceof AST_Const) + base54.consider("const"); + else if (node instanceof AST_Lambda) + base54.consider("function"); + else if (node instanceof AST_For) + base54.consider("for"); + else if (node instanceof AST_ForIn) + base54.consider("for in"); + else if (node instanceof AST_Switch) + base54.consider("switch"); + else if (node instanceof AST_Case) + base54.consider("case"); + else if (node instanceof AST_Default) + base54.consider("default"); + else if (node instanceof AST_With) + base54.consider("with"); + else if (node instanceof AST_ObjectSetter) + base54.consider("set" + node.key); + else if (node instanceof AST_ObjectGetter) + base54.consider("get" + node.key); + else if (node instanceof AST_ObjectKeyVal) + base54.consider(node.key); + else if (node instanceof AST_New) + base54.consider("new"); + else if (node instanceof AST_This) + base54.consider("this"); + else if (node instanceof AST_Try) + base54.consider("try"); + else if (node instanceof AST_Catch) + base54.consider("catch"); + else if (node instanceof AST_Finally) + base54.consider("finally"); + else if (node instanceof AST_Symbol && node.unmangleable(options)) + base54.consider(node.name); + else if (node instanceof AST_Unary || node instanceof AST_Binary) + base54.consider(node.operator); + else if (node instanceof AST_Dot) + base54.consider(node.property); + }); + this.walk(tw); + base54.sort(); +}); + +var base54 = (function() { + var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789"; + var chars, frequency; + function reset() { + frequency = Object.create(null); + chars = string.split("").map(function(ch){ return ch.charCodeAt(0) }); + chars.forEach(function(ch){ frequency[ch] = 0 }); + } + base54.consider = function(str){ + for (var i = str.length; --i >= 0;) { + var code = str.charCodeAt(i); + if (code in frequency) ++frequency[code]; + } + }; + base54.sort = function() { + chars = mergeSort(chars, function(a, b){ + if (is_digit(a) && !is_digit(b)) return 1; + if (is_digit(b) && !is_digit(a)) return -1; + return frequency[b] - frequency[a]; + }); + }; + base54.reset = reset; + reset(); + base54.get = function(){ return chars }; + base54.freq = function(){ return frequency }; + function base54(num) { + var ret = "", base = 54; + do { + ret += String.fromCharCode(chars[num % base]); + num = Math.floor(num / base); + base = 64; + } while (num > 0); + return ret; + }; + return base54; +})(); + +AST_Toplevel.DEFMETHOD("scope_warnings", function(options){ + options = defaults(options, { + undeclared : false, // this makes a lot of noise + unreferenced : true, + assign_to_global : true, + func_arguments : true, + nested_defuns : true, + eval : true + }); + var tw = new TreeWalker(function(node){ + if (options.undeclared + && node instanceof AST_SymbolRef + && node.undeclared()) + { + // XXX: this also warns about JS standard names, + // i.e. Object, Array, parseInt etc. Should add a list of + // exceptions. + AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", { + name: node.name, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.assign_to_global) + { + var sym = null; + if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) + sym = node.left; + else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef) + sym = node.init; + if (sym + && (sym.undeclared() + || (sym.global() && sym.scope !== sym.definition().scope))) { + AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", { + msg: sym.undeclared() ? "Accidental global?" : "Assignment to global", + name: sym.name, + file: sym.start.file, + line: sym.start.line, + col: sym.start.col + }); + } + } + if (options.eval + && node instanceof AST_SymbolRef + && node.undeclared() + && node.name == "eval") { + AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start); + } + if (options.unreferenced + && (node instanceof AST_SymbolDeclaration || node instanceof AST_Label) + && node.unreferenced()) { + AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", { + type: node instanceof AST_Label ? "Label" : "Symbol", + name: node.name, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.func_arguments + && node instanceof AST_Lambda + && node.uses_arguments) { + AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", { + name: node.name ? node.name.name : "anonymous", + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + if (options.nested_defuns + && node instanceof AST_Defun + && !(tw.parent() instanceof AST_Scope)) { + AST_Node.warn("Function {name} declared in nested statement \"{type}\" [{file}:{line},{col}]", { + name: node.name.name, + type: tw.parent().TYPE, + file: node.start.file, + line: node.start.line, + col: node.start.col + }); + } + }); + this.walk(tw); +}); diff --git a/homework8/project_express/node_modules/uglify-js/lib/sourcemap.js b/homework8/project_express/node_modules/uglify-js/lib/sourcemap.js new file mode 100644 index 0000000..3429908 --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/lib/sourcemap.js @@ -0,0 +1,81 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +// a small wrapper around fitzgen's source-map library +function SourceMap(options) { + options = defaults(options, { + file : null, + root : null, + orig : null, + }); + var generator = new MOZ_SourceMap.SourceMapGenerator({ + file : options.file, + sourceRoot : options.root + }); + var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig); + function add(source, gen_line, gen_col, orig_line, orig_col, name) { + if (orig_map) { + var info = orig_map.originalPositionFor({ + line: orig_line, + column: orig_col + }); + source = info.source; + orig_line = info.line; + orig_col = info.column; + name = info.name; + } + generator.addMapping({ + generated : { line: gen_line, column: gen_col }, + original : { line: orig_line, column: orig_col }, + source : source, + name : name + }); + }; + return { + add : add, + get : function() { return generator }, + toString : function() { return generator.toString() } + }; +}; diff --git a/homework8/project_express/node_modules/uglify-js/lib/transform.js b/homework8/project_express/node_modules/uglify-js/lib/transform.js new file mode 100644 index 0000000..8b4fd9f --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/lib/transform.js @@ -0,0 +1,218 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +// Tree transformer helpers. +// XXX: eventually I should refactor the compressor to use this infrastructure. + +function TreeTransformer(before, after) { + TreeWalker.call(this); + this.before = before; + this.after = after; +} +TreeTransformer.prototype = new TreeWalker; + +(function(undefined){ + + function _(node, descend) { + node.DEFMETHOD("transform", function(tw, in_list){ + var x, y; + tw.push(this); + if (tw.before) x = tw.before(this, descend, in_list); + if (x === undefined) { + if (!tw.after) { + x = this; + descend(x, tw); + } else { + tw.stack[tw.stack.length - 1] = x = this.clone(); + descend(x, tw); + y = tw.after(x, in_list); + if (y !== undefined) x = y; + } + } + tw.pop(); + return x; + }); + }; + + function do_list(list, tw) { + return MAP(list, function(node){ + return node.transform(tw, true); + }); + }; + + _(AST_Node, noop); + + _(AST_LabeledStatement, function(self, tw){ + self.label = self.label.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_SimpleStatement, function(self, tw){ + self.body = self.body.transform(tw); + }); + + _(AST_Block, function(self, tw){ + self.body = do_list(self.body, tw); + }); + + _(AST_DWLoop, function(self, tw){ + self.condition = self.condition.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_For, function(self, tw){ + if (self.init) self.init = self.init.transform(tw); + if (self.condition) self.condition = self.condition.transform(tw); + if (self.step) self.step = self.step.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_ForIn, function(self, tw){ + self.init = self.init.transform(tw); + self.object = self.object.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_With, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_Exit, function(self, tw){ + if (self.value) self.value = self.value.transform(tw); + }); + + _(AST_LoopControl, function(self, tw){ + if (self.label) self.label = self.label.transform(tw); + }); + + _(AST_If, function(self, tw){ + self.condition = self.condition.transform(tw); + self.body = self.body.transform(tw); + if (self.alternative) self.alternative = self.alternative.transform(tw); + }); + + _(AST_Switch, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Case, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Try, function(self, tw){ + self.body = do_list(self.body, tw); + if (self.bcatch) self.bcatch = self.bcatch.transform(tw); + if (self.bfinally) self.bfinally = self.bfinally.transform(tw); + }); + + _(AST_Catch, function(self, tw){ + self.argname = self.argname.transform(tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Definitions, function(self, tw){ + self.definitions = do_list(self.definitions, tw); + }); + + _(AST_VarDef, function(self, tw){ + if (self.value) self.value = self.value.transform(tw); + }); + + _(AST_Lambda, function(self, tw){ + if (self.name) self.name = self.name.transform(tw); + self.argnames = do_list(self.argnames, tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Call, function(self, tw){ + self.expression = self.expression.transform(tw); + self.args = do_list(self.args, tw); + }); + + _(AST_Seq, function(self, tw){ + self.car = self.car.transform(tw); + self.cdr = self.cdr.transform(tw); + }); + + _(AST_Dot, function(self, tw){ + self.expression = self.expression.transform(tw); + }); + + _(AST_Sub, function(self, tw){ + self.expression = self.expression.transform(tw); + self.property = self.property.transform(tw); + }); + + _(AST_Unary, function(self, tw){ + self.expression = self.expression.transform(tw); + }); + + _(AST_Binary, function(self, tw){ + self.left = self.left.transform(tw); + self.right = self.right.transform(tw); + }); + + _(AST_Conditional, function(self, tw){ + self.condition = self.condition.transform(tw); + self.consequent = self.consequent.transform(tw); + self.alternative = self.alternative.transform(tw); + }); + + _(AST_Array, function(self, tw){ + self.elements = do_list(self.elements, tw); + }); + + _(AST_Object, function(self, tw){ + self.properties = do_list(self.properties, tw); + }); + + _(AST_ObjectProperty, function(self, tw){ + self.value = self.value.transform(tw); + }); + +})(); diff --git a/homework8/project_express/node_modules/uglify-js/lib/utils.js b/homework8/project_express/node_modules/uglify-js/lib/utils.js new file mode 100644 index 0000000..c95b982 --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/lib/utils.js @@ -0,0 +1,288 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +"use strict"; + +function array_to_hash(a) { + var ret = Object.create(null); + for (var i = 0; i < a.length; ++i) + ret[a[i]] = true; + return ret; +}; + +function slice(a, start) { + return Array.prototype.slice.call(a, start || 0); +}; + +function characters(str) { + return str.split(""); +}; + +function member(name, array) { + for (var i = array.length; --i >= 0;) + if (array[i] == name) + return true; + return false; +}; + +function find_if(func, array) { + for (var i = 0, n = array.length; i < n; ++i) { + if (func(array[i])) + return array[i]; + } +}; + +function repeat_string(str, i) { + if (i <= 0) return ""; + if (i == 1) return str; + var d = repeat_string(str, i >> 1); + d += d; + if (i & 1) d += str; + return d; +}; + +function DefaultsError(msg, defs) { + this.msg = msg; + this.defs = defs; +}; + +function defaults(args, defs, croak) { + if (args === true) + args = {}; + var ret = args || {}; + if (croak) for (var i in ret) if (ret.hasOwnProperty(i) && !defs.hasOwnProperty(i)) + throw new DefaultsError("`" + i + "` is not a supported option", defs); + for (var i in defs) if (defs.hasOwnProperty(i)) { + ret[i] = (args && args.hasOwnProperty(i)) ? args[i] : defs[i]; + } + return ret; +}; + +function merge(obj, ext) { + for (var i in ext) if (ext.hasOwnProperty(i)) { + obj[i] = ext[i]; + } + return obj; +}; + +function noop() {}; + +var MAP = (function(){ + function MAP(a, f, backwards) { + var ret = [], top = [], i; + function doit() { + var val = f(a[i], i); + var is_last = val instanceof Last; + if (is_last) val = val.v; + if (val instanceof AtTop) { + val = val.v; + if (val instanceof Splice) { + top.push.apply(top, backwards ? val.v.slice().reverse() : val.v); + } else { + top.push(val); + } + } + else if (val !== skip) { + if (val instanceof Splice) { + ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v); + } else { + ret.push(val); + } + } + return is_last; + }; + if (a instanceof Array) { + if (backwards) { + for (i = a.length; --i >= 0;) if (doit()) break; + ret.reverse(); + top.reverse(); + } else { + for (i = 0; i < a.length; ++i) if (doit()) break; + } + } + else { + for (i in a) if (a.hasOwnProperty(i)) if (doit()) break; + } + return top.concat(ret); + }; + MAP.at_top = function(val) { return new AtTop(val) }; + MAP.splice = function(val) { return new Splice(val) }; + MAP.last = function(val) { return new Last(val) }; + var skip = MAP.skip = {}; + function AtTop(val) { this.v = val }; + function Splice(val) { this.v = val }; + function Last(val) { this.v = val }; + return MAP; +})(); + +function push_uniq(array, el) { + if (array.indexOf(el) < 0) + array.push(el); +}; + +function string_template(text, props) { + return text.replace(/\{(.+?)\}/g, function(str, p){ + return props[p]; + }); +}; + +function remove(array, el) { + for (var i = array.length; --i >= 0;) { + if (array[i] === el) array.splice(i, 1); + } +}; + +function mergeSort(array, cmp) { + if (array.length < 2) return array.slice(); + function merge(a, b) { + var r = [], ai = 0, bi = 0, i = 0; + while (ai < a.length && bi < b.length) { + cmp(a[ai], b[bi]) <= 0 + ? r[i++] = a[ai++] + : r[i++] = b[bi++]; + } + if (ai < a.length) r.push.apply(r, a.slice(ai)); + if (bi < b.length) r.push.apply(r, b.slice(bi)); + return r; + }; + function _ms(a) { + if (a.length <= 1) + return a; + var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m); + left = _ms(left); + right = _ms(right); + return merge(left, right); + }; + return _ms(array); +}; + +function set_difference(a, b) { + return a.filter(function(el){ + return b.indexOf(el) < 0; + }); +}; + +function set_intersection(a, b) { + return a.filter(function(el){ + return b.indexOf(el) >= 0; + }); +}; + +// this function is taken from Acorn [1], written by Marijn Haverbeke +// [1] https://github.com/marijnh/acorn +function makePredicate(words) { + if (!(words instanceof Array)) words = words.split(" "); + var f = "", cats = []; + out: for (var i = 0; i < words.length; ++i) { + for (var j = 0; j < cats.length; ++j) + if (cats[j][0].length == words[i].length) { + cats[j].push(words[i]); + continue out; + } + cats.push([words[i]]); + } + function compareTo(arr) { + if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";"; + f += "switch(str){"; + for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":"; + f += "return true}return false;"; + } + // When there are more than three length categories, an outer + // switch first dispatches on the lengths, to save on comparisons. + if (cats.length > 3) { + cats.sort(function(a, b) {return b.length - a.length;}); + f += "switch(str.length){"; + for (var i = 0; i < cats.length; ++i) { + var cat = cats[i]; + f += "case " + cat[0].length + ":"; + compareTo(cat); + } + f += "}"; + // Otherwise, simply generate a flat `switch` statement. + } else { + compareTo(words); + } + return new Function("str", f); +}; + +function Dictionary() { + this._values = Object.create(null); + this._size = 0; +}; +Dictionary.prototype = { + set: function(key, val) { + if (!this.has(key)) ++this._size; + this._values["$" + key] = val; + return this; + }, + add: function(key, val) { + if (this.has(key)) { + this.get(key).push(val); + } else { + this.set(key, [ val ]); + } + return this; + }, + get: function(key) { return this._values["$" + key] }, + del: function(key) { + if (this.has(key)) { + --this._size; + delete this._values["$" + key]; + } + return this; + }, + has: function(key) { return ("$" + key) in this._values }, + each: function(f) { + for (var i in this._values) + f(this._values[i], i.substr(1)); + }, + size: function() { + return this._size; + }, + map: function(f) { + var ret = []; + for (var i in this._values) + ret.push(f(this._values[i], i.substr(1))); + return ret; + } +}; diff --git a/homework8/project_express/node_modules/uglify-js/package.json b/homework8/project_express/node_modules/uglify-js/package.json new file mode 100644 index 0000000..e30b268 --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/package.json @@ -0,0 +1,26 @@ +{ + "name": "uglify-js", + "description": "JavaScript parser, mangler/compressor and beautifier toolkit", + "homepage": "http://lisperator.net/uglifyjs", + "main": "tools/node.js", + "version": "2.3.0", + "engines": { "node" : ">=0.4.0" }, + "maintainers": [{ + "name": "Mihai Bazon", + "email": "mihai.bazon@gmail.com", + "web": "http://lisperator.net/" + }], + "repositories": [{ + "type": "git", + "url": "https://github.com/mishoo/UglifyJS2.git" + }], + "dependencies": { + "async" : "~0.2.6", + "source-map" : "~0.1.7", + "optimist" : "~0.3.5" + }, + "bin": { + "uglifyjs" : "bin/uglifyjs" + }, + "scripts": {"test": "node test/run-tests.js"} +} diff --git a/homework8/project_express/node_modules/uglify-js/test/compress/arrays.js b/homework8/project_express/node_modules/uglify-js/test/compress/arrays.js new file mode 100644 index 0000000..10fe6eb --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/test/compress/arrays.js @@ -0,0 +1,12 @@ +holes_and_undefined: { + input: { + x = [1, 2, undefined]; + y = [1, , 2, ]; + z = [1, undefined, 3]; + } + expect: { + x=[1,2,void 0]; + y=[1,,2]; + z=[1,void 0,3]; + } +} diff --git a/homework8/project_express/node_modules/uglify-js/test/compress/blocks.js b/homework8/project_express/node_modules/uglify-js/test/compress/blocks.js new file mode 100644 index 0000000..8372adf --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/test/compress/blocks.js @@ -0,0 +1,49 @@ +remove_blocks: { + input: { + {;} + foo(); + {}; + { + {}; + }; + bar(); + {} + } + expect: { + foo(); + bar(); + } +} + +keep_some_blocks: { + input: { + // 1. + if (foo) { + {{{}}} + if (bar) { baz(); } + {{}} + } else { + stuff(); + } + + // 2. + if (foo) { + for (var i = 0; i < 5; ++i) + if (bar) baz(); + } else { + stuff(); + } + } + expect: { + // 1. + if (foo) { + if (bar) baz(); + } else stuff(); + + // 2. + if (foo) { + for (var i = 0; i < 5; ++i) + if (bar) baz(); + } else stuff(); + } +} diff --git a/homework8/project_express/node_modules/uglify-js/test/compress/conditionals.js b/homework8/project_express/node_modules/uglify-js/test/compress/conditionals.js new file mode 100644 index 0000000..dc2bb67 --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/test/compress/conditionals.js @@ -0,0 +1,143 @@ +ifs_1: { + options = { + conditionals: true + }; + input: { + if (foo) bar(); + if (!foo); else bar(); + if (foo); else bar(); + if (foo); else; + } + expect: { + foo&&bar(); + foo&&bar(); + foo||bar(); + foo; + } +} + +ifs_2: { + options = { + conditionals: true + }; + input: { + if (foo) { + x(); + } else if (bar) { + y(); + } else if (baz) { + z(); + } + + if (foo) { + x(); + } else if (bar) { + y(); + } else if (baz) { + z(); + } else { + t(); + } + } + expect: { + foo ? x() : bar ? y() : baz && z(); + foo ? x() : bar ? y() : baz ? z() : t(); + } +} + +ifs_3_should_warn: { + options = { + conditionals : true, + dead_code : true, + evaluate : true, + booleans : true + }; + input: { + if (x && !(x + "1") && y) { // 1 + var qq; + foo(); + } else { + bar(); + } + + if (x || !!(x + "1") || y) { // 2 + foo(); + } else { + var jj; + bar(); + } + } + expect: { + var qq; bar(); // 1 + var jj; foo(); // 2 + } +} + +ifs_4: { + options = { + conditionals: true + }; + input: { + if (foo && bar) { + x(foo)[10].bar.baz = something(); + } else + x(foo)[10].bar.baz = something_else(); + } + expect: { + x(foo)[10].bar.baz = (foo && bar) ? something() : something_else(); + } +} + +ifs_5: { + options = { + if_return: true, + conditionals: true, + comparisons: true, + }; + input: { + function f() { + if (foo) return; + bar(); + baz(); + } + function g() { + if (foo) return; + if (bar) return; + if (baz) return; + if (baa) return; + a(); + b(); + } + } + expect: { + function f() { + if (!foo) { + bar(); + baz(); + } + } + function g() { + if (!(foo || bar || baz || baa)) { + a(); + b(); + } + } + } +} + +ifs_6: { + options = { + conditionals: true, + comparisons: true + }; + input: { + if (!foo && !bar && !baz && !boo) { + x = 10; + } else { + x = 20; + } + } + expect: { + x = foo || bar || baz || boo ? 20 : 10; + } +} diff --git a/homework8/project_express/node_modules/uglify-js/test/compress/dead-code.js b/homework8/project_express/node_modules/uglify-js/test/compress/dead-code.js new file mode 100644 index 0000000..0fd066e --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/test/compress/dead-code.js @@ -0,0 +1,89 @@ +dead_code_1: { + options = { + dead_code: true + }; + input: { + function f() { + a(); + b(); + x = 10; + return; + if (x) { + y(); + } + } + } + expect: { + function f() { + a(); + b(); + x = 10; + return; + } + } +} + +dead_code_2_should_warn: { + options = { + dead_code: true + }; + input: { + function f() { + g(); + x = 10; + throw "foo"; + // completely discarding the `if` would introduce some + // bugs. UglifyJS v1 doesn't deal with this issue; in v2 + // we copy any declarations to the upper scope. + if (x) { + y(); + var x; + function g(){}; + // but nested declarations should not be kept. + (function(){ + var q; + function y(){}; + })(); + } + } + } + expect: { + function f() { + g(); + x = 10; + throw "foo"; + var x; + function g(){}; + } + } +} + +dead_code_constant_boolean_should_warn_more: { + options = { + dead_code : true, + loops : true, + booleans : true, + conditionals : true, + evaluate : true + }; + input: { + while (!((foo && bar) || (x + "0"))) { + console.log("unreachable"); + var foo; + function bar() {} + } + for (var x = 10; x && (y || x) && (!typeof x); ++x) { + asdf(); + foo(); + var moo; + } + } + expect: { + var foo; + function bar() {} + // nothing for the while + // as for the for, it should keep: + var x = 10; + var moo; + } +} diff --git a/homework8/project_express/node_modules/uglify-js/test/compress/debugger.js b/homework8/project_express/node_modules/uglify-js/test/compress/debugger.js new file mode 100644 index 0000000..7c27073 --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/test/compress/debugger.js @@ -0,0 +1,24 @@ +keep_debugger: { + options = { + drop_debugger: false + }; + input: { + debugger; + } + expect: { + debugger; + } +} + +drop_debugger: { + options = { + drop_debugger: true + }; + input: { + debugger; + if (foo) debugger; + } + expect: { + if (foo); + } +} diff --git a/homework8/project_express/node_modules/uglify-js/test/compress/drop-unused.js b/homework8/project_express/node_modules/uglify-js/test/compress/drop-unused.js new file mode 100644 index 0000000..bf5cd29 --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/test/compress/drop-unused.js @@ -0,0 +1,97 @@ +unused_funarg_1: { + options = { unused: true }; + input: { + function f(a, b, c, d, e) { + return a + b; + } + } + expect: { + function f(a, b) { + return a + b; + } + } +} + +unused_funarg_2: { + options = { unused: true }; + input: { + function f(a, b, c, d, e) { + return a + c; + } + } + expect: { + function f(a, b, c) { + return a + c; + } + } +} + +unused_nested_function: { + options = { unused: true }; + input: { + function f(x, y) { + function g() { + something(); + } + return x + y; + } + }; + expect: { + function f(x, y) { + return x + y; + } + } +} + +unused_circular_references_1: { + options = { unused: true }; + input: { + function f(x, y) { + // circular reference + function g() { + return h(); + } + function h() { + return g(); + } + return x + y; + } + }; + expect: { + function f(x, y) { + return x + y; + } + } +} + +unused_circular_references_2: { + options = { unused: true }; + input: { + function f(x, y) { + var foo = 1, bar = baz, baz = foo + bar, qwe = moo(); + return x + y; + } + }; + expect: { + function f(x, y) { + moo(); // keeps side effect + return x + y; + } + } +} + +unused_circular_references_3: { + options = { unused: true }; + input: { + function f(x, y) { + var g = function() { return h() }; + var h = function() { return g() }; + return x + y; + } + }; + expect: { + function f(x, y) { + return x + y; + } + } +} diff --git a/homework8/project_express/node_modules/uglify-js/test/compress/issue-105.js b/homework8/project_express/node_modules/uglify-js/test/compress/issue-105.js new file mode 100644 index 0000000..349d732 --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/test/compress/issue-105.js @@ -0,0 +1,17 @@ +typeof_eq_undefined: { + options = { + comparisons: true, + unsafe: false + }; + input: { a = typeof b.c != "undefined" } + expect: { a = "undefined" != typeof b.c } +} + +typeof_eq_undefined_unsafe: { + options = { + comparisons: true, + unsafe: true + }; + input: { a = typeof b.c != "undefined" } + expect: { a = b.c !== void 0 } +} diff --git a/homework8/project_express/node_modules/uglify-js/test/compress/issue-12.js b/homework8/project_express/node_modules/uglify-js/test/compress/issue-12.js new file mode 100644 index 0000000..bf87d5c --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/test/compress/issue-12.js @@ -0,0 +1,11 @@ +keep_name_of_getter: { + options = { unused: true }; + input: { a = { get foo () {} } } + expect: { a = { get foo () {} } } +} + +keep_name_of_setter: { + options = { unused: true }; + input: { a = { set foo () {} } } + expect: { a = { set foo () {} } } +} diff --git a/homework8/project_express/node_modules/uglify-js/test/compress/issue-22.js b/homework8/project_express/node_modules/uglify-js/test/compress/issue-22.js new file mode 100644 index 0000000..a8b7bc6 --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/test/compress/issue-22.js @@ -0,0 +1,17 @@ +return_with_no_value_in_if_body: { + options = { conditionals: true }; + input: { + function foo(bar) { + if (bar) { + return; + } else { + return 1; + } + } + } + expect: { + function foo (bar) { + return bar ? void 0 : 1; + } + } +} diff --git a/homework8/project_express/node_modules/uglify-js/test/compress/issue-44.js b/homework8/project_express/node_modules/uglify-js/test/compress/issue-44.js new file mode 100644 index 0000000..7a972f9 --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/test/compress/issue-44.js @@ -0,0 +1,31 @@ +issue_44_valid_ast_1: { + options = { unused: true }; + input: { + function a(b) { + for (var i = 0, e = b.qoo(); ; i++) {} + } + } + expect: { + function a(b) { + var i = 0; + for (b.qoo(); ; i++); + } + } +} + +issue_44_valid_ast_2: { + options = { unused: true }; + input: { + function a(b) { + if (foo) for (var i = 0, e = b.qoo(); ; i++) {} + } + } + expect: { + function a(b) { + if (foo) { + var i = 0; + for (b.qoo(); ; i++); + } + } + } +} diff --git a/homework8/project_express/node_modules/uglify-js/test/compress/issue-59.js b/homework8/project_express/node_modules/uglify-js/test/compress/issue-59.js new file mode 100644 index 0000000..82b3880 --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/test/compress/issue-59.js @@ -0,0 +1,30 @@ +keep_continue: { + options = { + dead_code: true, + evaluate: true + }; + input: { + while (a) { + if (b) { + switch (true) { + case c(): + d(); + } + continue; + } + f(); + } + } + expect: { + while (a) { + if (b) { + switch (true) { + case c(): + d(); + } + continue; + } + f(); + } + } +} diff --git a/homework8/project_express/node_modules/uglify-js/test/compress/labels.js b/homework8/project_express/node_modules/uglify-js/test/compress/labels.js new file mode 100644 index 0000000..044b7a7 --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/test/compress/labels.js @@ -0,0 +1,163 @@ +labels_1: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: { + if (foo) break out; + console.log("bar"); + } + }; + expect: { + foo || console.log("bar"); + } +} + +labels_2: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: { + if (foo) print("stuff"); + else break out; + console.log("here"); + } + }; + expect: { + if (foo) { + print("stuff"); + console.log("here"); + } + } +} + +labels_3: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + for (var i = 0; i < 5; ++i) { + if (i < 3) continue; + console.log(i); + } + }; + expect: { + for (var i = 0; i < 5; ++i) + i < 3 || console.log(i); + } +} + +labels_4: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: for (var i = 0; i < 5; ++i) { + if (i < 3) continue out; + console.log(i); + } + }; + expect: { + for (var i = 0; i < 5; ++i) + i < 3 || console.log(i); + } +} + +labels_5: { + options = { if_return: true, conditionals: true, dead_code: true }; + // should keep the break-s in the following + input: { + while (foo) { + if (bar) break; + console.log("foo"); + } + out: while (foo) { + if (bar) break out; + console.log("foo"); + } + }; + expect: { + while (foo) { + if (bar) break; + console.log("foo"); + } + out: while (foo) { + if (bar) break out; + console.log("foo"); + } + } +} + +labels_6: { + input: { + out: break out; + }; + expect: {} +} + +labels_7: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + while (foo) { + x(); + y(); + continue; + } + }; + expect: { + while (foo) { + x(); + y(); + } + } +} + +labels_8: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + while (foo) { + x(); + y(); + break; + } + }; + expect: { + while (foo) { + x(); + y(); + break; + } + } +} + +labels_9: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: while (foo) { + x(); + y(); + continue out; + z(); + k(); + } + }; + expect: { + while (foo) { + x(); + y(); + } + } +} + +labels_10: { + options = { if_return: true, conditionals: true, dead_code: true }; + input: { + out: while (foo) { + x(); + y(); + break out; + z(); + k(); + } + }; + expect: { + out: while (foo) { + x(); + y(); + break out; + } + } +} diff --git a/homework8/project_express/node_modules/uglify-js/test/compress/loops.js b/homework8/project_express/node_modules/uglify-js/test/compress/loops.js new file mode 100644 index 0000000..cdf1f04 --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/test/compress/loops.js @@ -0,0 +1,123 @@ +while_becomes_for: { + options = { loops: true }; + input: { + while (foo()) bar(); + } + expect: { + for (; foo(); ) bar(); + } +} + +drop_if_break_1: { + options = { loops: true }; + input: { + for (;;) + if (foo()) break; + } + expect: { + for (; !foo();); + } +} + +drop_if_break_2: { + options = { loops: true }; + input: { + for (;bar();) + if (foo()) break; + } + expect: { + for (; bar() && !foo();); + } +} + +drop_if_break_3: { + options = { loops: true }; + input: { + for (;bar();) { + if (foo()) break; + stuff1(); + stuff2(); + } + } + expect: { + for (; bar() && !foo();) { + stuff1(); + stuff2(); + } + } +} + +drop_if_break_4: { + options = { loops: true, sequences: true }; + input: { + for (;bar();) { + x(); + y(); + if (foo()) break; + z(); + k(); + } + } + expect: { + for (; bar() && (x(), y(), !foo());) z(), k(); + } +} + +drop_if_else_break_1: { + options = { loops: true }; + input: { + for (;;) if (foo()) bar(); else break; + } + expect: { + for (; foo(); ) bar(); + } +} + +drop_if_else_break_2: { + options = { loops: true }; + input: { + for (;bar();) { + if (foo()) baz(); + else break; + } + } + expect: { + for (; bar() && foo();) baz(); + } +} + +drop_if_else_break_3: { + options = { loops: true }; + input: { + for (;bar();) { + if (foo()) baz(); + else break; + stuff1(); + stuff2(); + } + } + expect: { + for (; bar() && foo();) { + baz(); + stuff1(); + stuff2(); + } + } +} + +drop_if_else_break_4: { + options = { loops: true, sequences: true }; + input: { + for (;bar();) { + x(); + y(); + if (foo()) baz(); + else break; + z(); + k(); + } + } + expect: { + for (; bar() && (x(), y(), foo());) baz(), z(), k(); + } +} diff --git a/homework8/project_express/node_modules/uglify-js/test/compress/properties.js b/homework8/project_express/node_modules/uglify-js/test/compress/properties.js new file mode 100644 index 0000000..9b066ec --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/test/compress/properties.js @@ -0,0 +1,40 @@ +keep_properties: { + options = { + properties: false + }; + input: { + a["foo"] = "bar"; + } + expect: { + a["foo"] = "bar"; + } +} + +dot_properties: { + options = { + properties: true + }; + input: { + a["foo"] = "bar"; + a["if"] = "if"; + } + expect: { + a.foo = "bar"; + a["if"] = "if"; + } +} + +dot_properties_es5: { + options = { + properties: true, + screw_ie8: true + }; + input: { + a["foo"] = "bar"; + a["if"] = "if"; + } + expect: { + a.foo = "bar"; + a.if = "if"; + } +} diff --git a/homework8/project_express/node_modules/uglify-js/test/compress/sequences.js b/homework8/project_express/node_modules/uglify-js/test/compress/sequences.js new file mode 100644 index 0000000..6f63ace --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/test/compress/sequences.js @@ -0,0 +1,161 @@ +make_sequences_1: { + options = { + sequences: true + }; + input: { + foo(); + bar(); + baz(); + } + expect: { + foo(),bar(),baz(); + } +} + +make_sequences_2: { + options = { + sequences: true + }; + input: { + if (boo) { + foo(); + bar(); + baz(); + } else { + x(); + y(); + z(); + } + } + expect: { + if (boo) foo(),bar(),baz(); + else x(),y(),z(); + } +} + +make_sequences_3: { + options = { + sequences: true + }; + input: { + function f() { + foo(); + bar(); + return baz(); + } + function g() { + foo(); + bar(); + throw new Error(); + } + } + expect: { + function f() { + return foo(), bar(), baz(); + } + function g() { + throw foo(), bar(), new Error(); + } + } +} + +make_sequences_4: { + options = { + sequences: true + }; + input: { + x = 5; + if (y) z(); + + x = 5; + for (i = 0; i < 5; i++) console.log(i); + + x = 5; + for (; i < 5; i++) console.log(i); + + x = 5; + switch (y) {} + + x = 5; + with (obj) {} + } + expect: { + if (x = 5, y) z(); + for (x = 5, i = 0; i < 5; i++) console.log(i); + for (x = 5; i < 5; i++) console.log(i); + switch (x = 5, y) {} + with (x = 5, obj); + } +} + +lift_sequences_1: { + options = { sequences: true }; + input: { + foo = !(x(), y(), bar()); + } + expect: { + x(), y(), foo = !bar(); + } +} + +lift_sequences_2: { + options = { sequences: true, evaluate: true }; + input: { + q = 1 + (foo(), bar(), 5) + 7 * (5 / (3 - (a(), (QW=ER), c(), 2))) - (x(), y(), 5); + } + expect: { + foo(), bar(), a(), QW = ER, c(), x(), y(), q = 36 + } +} + +lift_sequences_3: { + options = { sequences: true, conditionals: true }; + input: { + x = (foo(), bar(), baz()) ? 10 : 20; + } + expect: { + foo(), bar(), x = baz() ? 10 : 20; + } +} + +lift_sequences_4: { + options = { side_effects: true }; + input: { + x = (foo, bar, baz); + } + expect: { + x = baz; + } +} + +for_sequences: { + options = { sequences: true }; + input: { + // 1 + foo(); + bar(); + for (; false;); + // 2 + foo(); + bar(); + for (x = 5; false;); + // 3 + x = (foo in bar); + for (; false;); + // 4 + x = (foo in bar); + for (y = 5; false;); + } + expect: { + // 1 + for (foo(), bar(); false;); + // 2 + for (foo(), bar(), x = 5; false;); + // 3 + x = (foo in bar); + for (; false;); + // 4 + x = (foo in bar); + for (y = 5; false;); + } +} diff --git a/homework8/project_express/node_modules/uglify-js/test/compress/switch.js b/homework8/project_express/node_modules/uglify-js/test/compress/switch.js new file mode 100644 index 0000000..62e39cf --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/test/compress/switch.js @@ -0,0 +1,260 @@ +constant_switch_1: { + options = { dead_code: true, evaluate: true }; + input: { + switch (1+1) { + case 1: foo(); break; + case 1+1: bar(); break; + case 1+1+1: baz(); break; + } + } + expect: { + bar(); + } +} + +constant_switch_2: { + options = { dead_code: true, evaluate: true }; + input: { + switch (1) { + case 1: foo(); + case 1+1: bar(); break; + case 1+1+1: baz(); + } + } + expect: { + foo(); + bar(); + } +} + +constant_switch_3: { + options = { dead_code: true, evaluate: true }; + input: { + switch (10) { + case 1: foo(); + case 1+1: bar(); break; + case 1+1+1: baz(); + default: + def(); + } + } + expect: { + def(); + } +} + +constant_switch_4: { + options = { dead_code: true, evaluate: true }; + input: { + switch (2) { + case 1: + x(); + if (foo) break; + y(); + break; + case 1+1: + bar(); + default: + def(); + } + } + expect: { + bar(); + def(); + } +} + +constant_switch_5: { + options = { dead_code: true, evaluate: true }; + input: { + switch (1) { + case 1: + x(); + if (foo) break; + y(); + break; + case 1+1: + bar(); + default: + def(); + } + } + expect: { + // the break inside the if ruins our job + // we can still get rid of irrelevant cases. + switch (1) { + case 1: + x(); + if (foo) break; + y(); + } + // XXX: we could optimize this better by inventing an outer + // labeled block, but that's kinda tricky. + } +} + +constant_switch_6: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: { + foo(); + switch (1) { + case 1: + x(); + if (foo) break OUT; + y(); + case 1+1: + bar(); + break; + default: + def(); + } + } + } + expect: { + OUT: { + foo(); + x(); + if (foo) break OUT; + y(); + bar(); + } + } +} + +constant_switch_7: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: { + foo(); + switch (1) { + case 1: + x(); + if (foo) break OUT; + for (var x = 0; x < 10; x++) { + if (x > 5) break; // this break refers to the for, not to the switch; thus it + // shouldn't ruin our optimization + console.log(x); + } + y(); + case 1+1: + bar(); + break; + default: + def(); + } + } + } + expect: { + OUT: { + foo(); + x(); + if (foo) break OUT; + for (var x = 0; x < 10; x++) { + if (x > 5) break; + console.log(x); + } + y(); + bar(); + } + } +} + +constant_switch_8: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: switch (1) { + case 1: + x(); + for (;;) break OUT; + y(); + break; + case 1+1: + bar(); + default: + def(); + } + } + expect: { + OUT: { + x(); + for (;;) break OUT; + y(); + } + } +} + +constant_switch_9: { + options = { dead_code: true, evaluate: true }; + input: { + OUT: switch (1) { + case 1: + x(); + for (;;) if (foo) break OUT; + y(); + case 1+1: + bar(); + default: + def(); + } + } + expect: { + OUT: { + x(); + for (;;) if (foo) break OUT; + y(); + bar(); + def(); + } + } +} + +drop_default_1: { + options = { dead_code: true }; + input: { + switch (foo) { + case 'bar': baz(); + default: + } + } + expect: { + switch (foo) { + case 'bar': baz(); + } + } +} + +drop_default_2: { + options = { dead_code: true }; + input: { + switch (foo) { + case 'bar': baz(); break; + default: + break; + } + } + expect: { + switch (foo) { + case 'bar': baz(); + } + } +} + +keep_default: { + options = { dead_code: true }; + input: { + switch (foo) { + case 'bar': baz(); + default: + something(); + break; + } + } + expect: { + switch (foo) { + case 'bar': baz(); + default: + something(); + } + } +} diff --git a/homework8/project_express/node_modules/uglify-js/test/compress/typeof.js b/homework8/project_express/node_modules/uglify-js/test/compress/typeof.js new file mode 100644 index 0000000..cefdd43 --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/test/compress/typeof.js @@ -0,0 +1,25 @@ +typeof_evaluation: { + options = { + evaluate: true + }; + input: { + a = typeof 1; + b = typeof 'test'; + c = typeof []; + d = typeof {}; + e = typeof /./; + f = typeof false; + g = typeof function(){}; + h = typeof undefined; + } + expect: { + a='number'; + b='string'; + c=typeof[]; + d=typeof{}; + e=typeof/./; + f='boolean'; + g='function'; + h='undefined'; + } +} diff --git a/homework8/project_express/node_modules/uglify-js/test/run-tests.js b/homework8/project_express/node_modules/uglify-js/test/run-tests.js new file mode 100644 index 0000000..0568c6a --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/test/run-tests.js @@ -0,0 +1,170 @@ +#! /usr/bin/env node + +var U = require("../tools/node"); +var path = require("path"); +var fs = require("fs"); +var assert = require("assert"); +var sys = require("util"); + +var tests_dir = path.dirname(module.filename); + +run_compress_tests(); + +/* -----[ utils ]----- */ + +function tmpl() { + return U.string_template.apply(this, arguments); +} + +function log() { + var txt = tmpl.apply(this, arguments); + sys.puts(txt); +} + +function log_directory(dir) { + log("*** Entering [{dir}]", { dir: dir }); +} + +function log_start_file(file) { + log("--- {file}", { file: file }); +} + +function log_test(name) { + log(" Running test [{name}]", { name: name }); +} + +function find_test_files(dir) { + var files = fs.readdirSync(dir).filter(function(name){ + return /\.js$/i.test(name); + }); + if (process.argv.length > 2) { + var x = process.argv.slice(2); + files = files.filter(function(f){ + return x.indexOf(f) >= 0; + }); + } + return files; +} + +function test_directory(dir) { + return path.resolve(tests_dir, dir); +} + +function as_toplevel(input) { + if (input instanceof U.AST_BlockStatement) input = input.body; + else if (input instanceof U.AST_Statement) input = [ input ]; + else throw new Error("Unsupported input syntax"); + var toplevel = new U.AST_Toplevel({ body: input }); + toplevel.figure_out_scope(); + return toplevel; +} + +function run_compress_tests() { + var dir = test_directory("compress"); + log_directory("compress"); + var files = find_test_files(dir); + function test_file(file) { + log_start_file(file); + function test_case(test) { + log_test(test.name); + var options = U.defaults(test.options, { + warnings: false + }); + var cmp = new U.Compressor(options, true); + var expect = make_code(as_toplevel(test.expect), false); + var input = as_toplevel(test.input); + var input_code = make_code(test.input); + var output = input.transform(cmp); + output.figure_out_scope(); + output = make_code(output, false); + if (expect != output) { + log("!!! failed\n---INPUT---\n{input}\n---OUTPUT---\n{output}\n---EXPECTED---\n{expected}\n\n", { + input: input_code, + output: output, + expected: expect + }); + } + } + var tests = parse_test(path.resolve(dir, file)); + for (var i in tests) if (tests.hasOwnProperty(i)) { + test_case(tests[i]); + } + } + files.forEach(function(file){ + test_file(file); + }); +} + +function parse_test(file) { + var script = fs.readFileSync(file, "utf8"); + var ast = U.parse(script, { + filename: file + }); + var tests = {}; + var tw = new U.TreeWalker(function(node, descend){ + if (node instanceof U.AST_LabeledStatement + && tw.parent() instanceof U.AST_Toplevel) { + var name = node.label.name; + tests[name] = get_one_test(name, node.body); + return true; + } + if (!(node instanceof U.AST_Toplevel)) croak(node); + }); + ast.walk(tw); + return tests; + + function croak(node) { + throw new Error(tmpl("Can't understand test file {file} [{line},{col}]\n{code}", { + file: file, + line: node.start.line, + col: node.start.col, + code: make_code(node, false) + })); + } + + function get_one_test(name, block) { + var test = { name: name, options: {} }; + var tw = new U.TreeWalker(function(node, descend){ + if (node instanceof U.AST_Assign) { + if (!(node.left instanceof U.AST_SymbolRef)) { + croak(node); + } + var name = node.left.name; + test[name] = evaluate(node.right); + return true; + } + if (node instanceof U.AST_LabeledStatement) { + assert.ok( + node.label.name == "input" || node.label.name == "expect", + tmpl("Unsupported label {name} [{line},{col}]", { + name: node.label.name, + line: node.label.start.line, + col: node.label.start.col + }) + ); + var stat = node.body; + if (stat instanceof U.AST_BlockStatement) { + if (stat.body.length == 1) stat = stat.body[0]; + else if (stat.body.length == 0) stat = new U.AST_EmptyStatement(); + } + test[node.label.name] = stat; + return true; + } + }); + block.walk(tw); + return test; + }; +} + +function make_code(ast, beautify) { + if (arguments.length == 1) beautify = true; + var stream = U.OutputStream({ beautify: beautify }); + ast.print(stream); + return stream.get(); +} + +function evaluate(code) { + if (code instanceof U.AST_Node) + code = make_code(code); + return new Function("return(" + code + ")")(); +} diff --git a/homework8/project_express/node_modules/uglify-js/tools/node.js b/homework8/project_express/node_modules/uglify-js/tools/node.js new file mode 100644 index 0000000..c0dd3db --- /dev/null +++ b/homework8/project_express/node_modules/uglify-js/tools/node.js @@ -0,0 +1,165 @@ +var path = require("path"); +var fs = require("fs"); +var vm = require("vm"); +var sys = require("util"); + +var UglifyJS = vm.createContext({ + sys : sys, + console : console, + MOZ_SourceMap : require("source-map") +}); + +function load_global(file) { + file = path.resolve(path.dirname(module.filename), file); + try { + var code = fs.readFileSync(file, "utf8"); + return vm.runInContext(code, UglifyJS, file); + } catch(ex) { + // XXX: in case of a syntax error, the message is kinda + // useless. (no location information). + sys.debug("ERROR in file: " + file + " / " + ex); + process.exit(1); + } +}; + +var FILES = exports.FILES = [ + "../lib/utils.js", + "../lib/ast.js", + "../lib/parse.js", + "../lib/transform.js", + "../lib/scope.js", + "../lib/output.js", + "../lib/compress.js", + "../lib/sourcemap.js", + "../lib/mozilla-ast.js" +].map(function(file){ + return path.join(path.dirname(fs.realpathSync(__filename)), file); +}); + +FILES.forEach(load_global); + +UglifyJS.AST_Node.warn_function = function(txt) { + sys.error("WARN: " + txt); +}; + +// XXX: perhaps we shouldn't export everything but heck, I'm lazy. +for (var i in UglifyJS) { + if (UglifyJS.hasOwnProperty(i)) { + exports[i] = UglifyJS[i]; + } +} + +exports.minify = function(files, options) { + options = UglifyJS.defaults(options, { + outSourceMap : null, + sourceRoot : null, + inSourceMap : null, + fromString : false, + warnings : false, + mangle : {}, + output : null, + compress : {} + }); + if (typeof files == "string") + files = [ files ]; + + // 1. parse + var toplevel = null; + files.forEach(function(file){ + var code = options.fromString + ? file + : fs.readFileSync(file, "utf8"); + toplevel = UglifyJS.parse(code, { + filename: options.fromString ? "?" : file, + toplevel: toplevel + }); + }); + + // 2. compress + if (options.compress) { + var compress = { warnings: options.warnings }; + UglifyJS.merge(compress, options.compress); + toplevel.figure_out_scope(); + var sq = UglifyJS.Compressor(compress); + toplevel = toplevel.transform(sq); + } + + // 3. mangle + if (options.mangle) { + toplevel.figure_out_scope(); + toplevel.compute_char_frequency(); + toplevel.mangle_names(options.mangle); + } + + // 4. output + var inMap = options.inSourceMap; + var output = {}; + if (typeof options.inSourceMap == "string") { + inMap = fs.readFileSync(options.inSourceMap, "utf8"); + } + if (options.outSourceMap) { + output.source_map = UglifyJS.SourceMap({ + file: options.outSourceMap, + orig: inMap, + root: options.sourceRoot + }); + } + if (options.output) { + UglifyJS.merge(output, options.output); + } + var stream = UglifyJS.OutputStream(output); + toplevel.print(stream); + return { + code : stream + "", + map : output.source_map + "" + }; +}; + +// exports.describe_ast = function() { +// function doitem(ctor) { +// var sub = {}; +// ctor.SUBCLASSES.forEach(function(ctor){ +// sub[ctor.TYPE] = doitem(ctor); +// }); +// var ret = {}; +// if (ctor.SELF_PROPS.length > 0) ret.props = ctor.SELF_PROPS; +// if (ctor.SUBCLASSES.length > 0) ret.sub = sub; +// return ret; +// } +// return doitem(UglifyJS.AST_Node).sub; +// } + +exports.describe_ast = function() { + var out = UglifyJS.OutputStream({ beautify: true }); + function doitem(ctor) { + out.print("AST_" + ctor.TYPE); + var props = ctor.SELF_PROPS.filter(function(prop){ + return !/^\$/.test(prop); + }); + if (props.length > 0) { + out.space(); + out.with_parens(function(){ + props.forEach(function(prop, i){ + if (i) out.space(); + out.print(prop); + }); + }); + } + if (ctor.documentation) { + out.space(); + out.print_string(ctor.documentation); + } + if (ctor.SUBCLASSES.length > 0) { + out.space(); + out.with_block(function(){ + ctor.SUBCLASSES.forEach(function(ctor, i){ + out.indent(); + doitem(ctor); + out.newline(); + }); + }); + } + }; + doitem(UglifyJS.AST_Node); + return out + ""; +}; diff --git a/homework8/project_express/node_modules/undefsafe/.github/workflows/release.yml b/homework8/project_express/node_modules/undefsafe/.github/workflows/release.yml new file mode 100644 index 0000000..e6ee886 --- /dev/null +++ b/homework8/project_express/node_modules/undefsafe/.github/workflows/release.yml @@ -0,0 +1,25 @@ +name: Release +on: + push: + branches: + - master +jobs: + release: + name: Release + runs-on: ubuntu-18.04 + steps: + - name: Checkout + uses: actions/checkout@v1 + - name: Setup Node.js + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install dependencies + run: npm ci + - name: Test + run: npm run test + - name: Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + run: npx semantic-release diff --git a/homework8/project_express/node_modules/undefsafe/.jscsrc b/homework8/project_express/node_modules/undefsafe/.jscsrc new file mode 100644 index 0000000..9e01c9b --- /dev/null +++ b/homework8/project_express/node_modules/undefsafe/.jscsrc @@ -0,0 +1,13 @@ +{ + "preset": "node-style-guide", + "requireCapitalizedComments": null, + "requireSpacesInAnonymousFunctionExpression": { + "beforeOpeningCurlyBrace": true, + "beforeOpeningRoundBrace": true + }, + "disallowSpacesInNamedFunctionExpression": { + "beforeOpeningRoundBrace": true + }, + "excludeFiles": ["node_modules/**"], + "disallowSpacesInFunction": null +} diff --git a/homework8/project_express/node_modules/undefsafe/.jshintrc b/homework8/project_express/node_modules/undefsafe/.jshintrc new file mode 100644 index 0000000..b47f672 --- /dev/null +++ b/homework8/project_express/node_modules/undefsafe/.jshintrc @@ -0,0 +1,16 @@ +{ + "browser": false, + "camelcase": true, + "curly": true, + "devel": true, + "eqeqeq": true, + "forin": true, + "indent": 2, + "noarg": true, + "node": true, + "quotmark": "single", + "undef": true, + "strict": false, + "unused": true +} + diff --git a/homework8/project_express/node_modules/undefsafe/.travis.yml b/homework8/project_express/node_modules/undefsafe/.travis.yml new file mode 100644 index 0000000..a1ace24 --- /dev/null +++ b/homework8/project_express/node_modules/undefsafe/.travis.yml @@ -0,0 +1,18 @@ +sudo: false +language: node_js +cache: + directories: + - node_modules +notifications: + email: false +node_js: + - '4' +before_install: + - npm i -g npm@^2.0.0 +before_script: + - npm prune +after_success: + - npm run semantic-release +branches: + except: + - "/^v\\d+\\.\\d+\\.\\d+$/" diff --git a/homework8/project_express/node_modules/undefsafe/LICENSE b/homework8/project_express/node_modules/undefsafe/LICENSE new file mode 100644 index 0000000..caaf03a --- /dev/null +++ b/homework8/project_express/node_modules/undefsafe/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright © 2016 Remy Sharp, http://remysharp.com + +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/homework8/project_express/node_modules/undefsafe/README.md b/homework8/project_express/node_modules/undefsafe/README.md new file mode 100644 index 0000000..46a706b --- /dev/null +++ b/homework8/project_express/node_modules/undefsafe/README.md @@ -0,0 +1,63 @@ +# undefsafe + +Simple *function* for retrieving deep object properties without getting "Cannot read property 'X' of undefined" + +Can also be used to safely set deep values. + +## Usage + +```js +var object = { + a: { + b: { + c: 1, + d: [1,2,3], + e: 'remy' + } + } +}; + +console.log(undefsafe(object, 'a.b.e')); // "remy" +console.log(undefsafe(object, 'a.b.not.found')); // undefined +``` + +Demo: [https://jsbin.com/eroqame/3/edit?js,console](https://jsbin.com/eroqame/3/edit?js,console) + +## Setting + +```js +var object = { + a: { + b: [1,2,3] + } +}; + +// modified object +var res = undefsafe(object, 'a.b.0', 10); + +console.log(object); // { a: { b: [10, 2, 3] } } +console.log(res); // 1 - previous value +``` + +## Star rules in paths + +As of 1.2.0, `undefsafe` supports a `*` in the path if you want to search all of the properties (or array elements) for a particular element. + +The function will only return a single result, either the 3rd argument validation value, or the first positive match. For example, the following github data: + +```js +const githubData = { + commits: [{ + modified: [ + "one", + "two" + ] + }, /* ... */ ] + }; + +// first modified file found in the first commit +console.log(undefsafe(githubData, 'commits.*.modified.0')); + +// returns `two` or undefined if not found +console.log(undefsafe(githubData, 'commits.*.modified.*', 'two')); +``` diff --git a/homework8/project_express/node_modules/undefsafe/example.js b/homework8/project_express/node_modules/undefsafe/example.js new file mode 100644 index 0000000..ed93c23 --- /dev/null +++ b/homework8/project_express/node_modules/undefsafe/example.js @@ -0,0 +1,14 @@ +var undefsafe = require('undefsafe'); + +var object = { + a: { + b: { + c: 1, + d: [1, 2, 3], + e: 'remy' + } + } +}; + +console.log(undefsafe(object, 'a.b.e')); // "remy" +console.log(undefsafe(object, 'a.b.not.found')); // undefined diff --git a/homework8/project_express/node_modules/undefsafe/lib/undefsafe.js b/homework8/project_express/node_modules/undefsafe/lib/undefsafe.js new file mode 100644 index 0000000..7446878 --- /dev/null +++ b/homework8/project_express/node_modules/undefsafe/lib/undefsafe.js @@ -0,0 +1,125 @@ +'use strict'; + +function undefsafe(obj, path, value, __res) { + // I'm not super keen on this private function, but it's because + // it'll also be use in the browser and I wont *one* function exposed + function split(path) { + var res = []; + var level = 0; + var key = ''; + + for (var i = 0; i < path.length; i++) { + var c = path.substr(i, 1); + + if (level === 0 && (c === '.' || c === '[')) { + if (c === '[') { + level++; + i++; + c = path.substr(i, 1); + } + + if (key) { + // the first value could be a string + res.push(key); + } + key = ''; + continue; + } + + if (c === ']') { + level--; + key = key.slice(0, -1); + continue; + } + + key += c; + } + + res.push(key); + + return res; + } + + // bail if there's nothing + if (obj === undefined || obj === null) { + return undefined; + } + + var parts = split(path); + var key = null; + var type = typeof obj; + var root = obj; + var parent = obj; + + var star = + parts.filter(function(_) { + return _ === '*'; + }).length > 0; + + // we're dealing with a primitive + if (type !== 'object' && type !== 'function') { + return obj; + } else if (path.trim() === '') { + return obj; + } + + key = parts[0]; + var i = 0; + for (; i < parts.length; i++) { + key = parts[i]; + parent = obj; + + if (key === '*') { + // loop through each property + var prop = ''; + var res = __res || []; + + for (prop in parent) { + var shallowObj = undefsafe( + obj[prop], + parts.slice(i + 1).join('.'), + value, + res + ); + if (shallowObj && shallowObj !== res) { + if ((value && shallowObj === value) || value === undefined) { + if (value !== undefined) { + return shallowObj; + } + + res.push(shallowObj); + } + } + } + + if (res.length === 0) { + return undefined; + } + + return res; + } + + if (Object.getOwnPropertyNames(obj).indexOf(key) == -1) { + return undefined; + } + + obj = obj[key]; + if (obj === undefined || obj === null) { + break; + } + } + + // if we have a null object, make sure it's the one the user was after, + // if it's not (i.e. parts has a length) then give undefined back. + if (obj === null && i !== parts.length - 1) { + obj = undefined; + } else if (!star && value) { + key = path.split('.').pop(); + parent[key] = value; + } + return obj; +} + +if (typeof module !== 'undefined') { + module.exports = undefsafe; +} diff --git a/homework8/project_express/node_modules/undefsafe/package.json b/homework8/project_express/node_modules/undefsafe/package.json new file mode 100644 index 0000000..a454233 --- /dev/null +++ b/homework8/project_express/node_modules/undefsafe/package.json @@ -0,0 +1,34 @@ +{ + "name": "undefsafe", + "description": "Undefined safe way of extracting object properties", + "main": "lib/undefsafe.js", + "tonicExampleFilename": "example.js", + "directories": { + "test": "test" + }, + "scripts": { + "test": "tap test/**/*.test.js -R spec", + "cover": "tap test/*.test.js --cov --coverage-report=lcov", + "semantic-release": "semantic-release" + }, + "prettier": { + "trailingComma": "none", + "singleQuote": true + }, + "repository": { + "type": "git", + "url": "https://github.com/remy/undefsafe.git" + }, + "keywords": [ + "undefined" + ], + "author": "Remy Sharp", + "license": "MIT", + "devDependencies": { + "semantic-release": "^18.0.0", + "tap": "^5.7.1", + "tap-only": "0.0.5" + }, + "dependencies": {}, + "version": "2.0.5" +} diff --git a/homework8/project_express/node_modules/unpipe/HISTORY.md b/homework8/project_express/node_modules/unpipe/HISTORY.md new file mode 100644 index 0000000..85e0f8d --- /dev/null +++ b/homework8/project_express/node_modules/unpipe/HISTORY.md @@ -0,0 +1,4 @@ +1.0.0 / 2015-06-14 +================== + + * Initial release diff --git a/homework8/project_express/node_modules/unpipe/LICENSE b/homework8/project_express/node_modules/unpipe/LICENSE new file mode 100644 index 0000000..aed0138 --- /dev/null +++ b/homework8/project_express/node_modules/unpipe/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2015 Douglas Christopher Wilson + +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/homework8/project_express/node_modules/unpipe/README.md b/homework8/project_express/node_modules/unpipe/README.md new file mode 100644 index 0000000..e536ad2 --- /dev/null +++ b/homework8/project_express/node_modules/unpipe/README.md @@ -0,0 +1,43 @@ +# unpipe + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-image]][node-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Unpipe a stream from all destinations. + +## Installation + +```sh +$ npm install unpipe +``` + +## API + +```js +var unpipe = require('unpipe') +``` + +### unpipe(stream) + +Unpipes all destinations from a given stream. With stream 2+, this is +equivalent to `stream.unpipe()`. When used with streams 1 style streams +(typically Node.js 0.8 and below), this module attempts to undo the +actions done in `stream.pipe(dest)`. + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/unpipe.svg +[npm-url]: https://npmjs.org/package/unpipe +[node-image]: https://img.shields.io/node/v/unpipe.svg +[node-url]: http://nodejs.org/download/ +[travis-image]: https://img.shields.io/travis/stream-utils/unpipe.svg +[travis-url]: https://travis-ci.org/stream-utils/unpipe +[coveralls-image]: https://img.shields.io/coveralls/stream-utils/unpipe.svg +[coveralls-url]: https://coveralls.io/r/stream-utils/unpipe?branch=master +[downloads-image]: https://img.shields.io/npm/dm/unpipe.svg +[downloads-url]: https://npmjs.org/package/unpipe diff --git a/homework8/project_express/node_modules/unpipe/index.js b/homework8/project_express/node_modules/unpipe/index.js new file mode 100644 index 0000000..15c3d97 --- /dev/null +++ b/homework8/project_express/node_modules/unpipe/index.js @@ -0,0 +1,69 @@ +/*! + * unpipe + * Copyright(c) 2015 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + * @public + */ + +module.exports = unpipe + +/** + * Determine if there are Node.js pipe-like data listeners. + * @private + */ + +function hasPipeDataListeners(stream) { + var listeners = stream.listeners('data') + + for (var i = 0; i < listeners.length; i++) { + if (listeners[i].name === 'ondata') { + return true + } + } + + return false +} + +/** + * Unpipe a stream from all destinations. + * + * @param {object} stream + * @public + */ + +function unpipe(stream) { + if (!stream) { + throw new TypeError('argument stream is required') + } + + if (typeof stream.unpipe === 'function') { + // new-style + stream.unpipe() + return + } + + // Node.js 0.8 hack + if (!hasPipeDataListeners(stream)) { + return + } + + var listener + var listeners = stream.listeners('close') + + for (var i = 0; i < listeners.length; i++) { + listener = listeners[i] + + if (listener.name !== 'cleanup' && listener.name !== 'onclose') { + continue + } + + // invoke the listener + listener.call(stream) + } +} diff --git a/homework8/project_express/node_modules/unpipe/package.json b/homework8/project_express/node_modules/unpipe/package.json new file mode 100644 index 0000000..4edc5c9 --- /dev/null +++ b/homework8/project_express/node_modules/unpipe/package.json @@ -0,0 +1,63 @@ +{ + "_from": "unpipe@1.0.0", + "_id": "unpipe@1.0.0", + "_inBundle": false, + "_integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "_location": "/unpipe", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "unpipe@1.0.0", + "name": "unpipe", + "escapedName": "unpipe", + "rawSpec": "1.0.0", + "saveSpec": null, + "fetchSpec": "1.0.0" + }, + "_requiredBy": [ + "/finalhandler", + "/raw-body" + ], + "_resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "_shasum": "b2bf4ee8514aae6165b4817829d21b2ef49904ec", + "_spec": "unpipe@1.0.0", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\raw-body", + "author": { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + "bugs": { + "url": "https://github.com/stream-utils/unpipe/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Unpipe a stream from all destinations", + "devDependencies": { + "istanbul": "0.3.15", + "mocha": "2.2.5", + "readable-stream": "1.1.13" + }, + "engines": { + "node": ">= 0.8" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "README.md", + "index.js" + ], + "homepage": "https://github.com/stream-utils/unpipe#readme", + "license": "MIT", + "name": "unpipe", + "repository": { + "type": "git", + "url": "git+https://github.com/stream-utils/unpipe.git" + }, + "scripts": { + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "version": "1.0.0" +} diff --git a/homework8/project_express/node_modules/utils-merge/.npmignore b/homework8/project_express/node_modules/utils-merge/.npmignore new file mode 100644 index 0000000..3e53844 --- /dev/null +++ b/homework8/project_express/node_modules/utils-merge/.npmignore @@ -0,0 +1,9 @@ +CONTRIBUTING.md +Makefile +docs/ +examples/ +reports/ +test/ + +.jshintrc +.travis.yml diff --git a/homework8/project_express/node_modules/utils-merge/LICENSE b/homework8/project_express/node_modules/utils-merge/LICENSE new file mode 100644 index 0000000..76f6d08 --- /dev/null +++ b/homework8/project_express/node_modules/utils-merge/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013-2017 Jared Hanson + +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/homework8/project_express/node_modules/utils-merge/README.md b/homework8/project_express/node_modules/utils-merge/README.md new file mode 100644 index 0000000..0cb7117 --- /dev/null +++ b/homework8/project_express/node_modules/utils-merge/README.md @@ -0,0 +1,34 @@ +# utils-merge + +[![Version](https://img.shields.io/npm/v/utils-merge.svg?label=version)](https://www.npmjs.com/package/utils-merge) +[![Build](https://img.shields.io/travis/jaredhanson/utils-merge.svg)](https://travis-ci.org/jaredhanson/utils-merge) +[![Quality](https://img.shields.io/codeclimate/github/jaredhanson/utils-merge.svg?label=quality)](https://codeclimate.com/github/jaredhanson/utils-merge) +[![Coverage](https://img.shields.io/coveralls/jaredhanson/utils-merge.svg)](https://coveralls.io/r/jaredhanson/utils-merge) +[![Dependencies](https://img.shields.io/david/jaredhanson/utils-merge.svg)](https://david-dm.org/jaredhanson/utils-merge) + + +Merges the properties from a source object into a destination object. + +## Install + +```bash +$ npm install utils-merge +``` + +## Usage + +```javascript +var a = { foo: 'bar' } + , b = { bar: 'baz' }; + +merge(a, b); +// => { foo: 'bar', bar: 'baz' } +``` + +## License + +[The MIT License](http://opensource.org/licenses/MIT) + +Copyright (c) 2013-2017 Jared Hanson <[http://jaredhanson.net/](http://jaredhanson.net/)> + + Sponsor diff --git a/homework8/project_express/node_modules/utils-merge/index.js b/homework8/project_express/node_modules/utils-merge/index.js new file mode 100644 index 0000000..4265c69 --- /dev/null +++ b/homework8/project_express/node_modules/utils-merge/index.js @@ -0,0 +1,23 @@ +/** + * Merge object b with object a. + * + * var a = { foo: 'bar' } + * , b = { bar: 'baz' }; + * + * merge(a, b); + * // => { foo: 'bar', bar: 'baz' } + * + * @param {Object} a + * @param {Object} b + * @return {Object} + * @api public + */ + +exports = module.exports = function(a, b){ + if (a && b) { + for (var key in b) { + a[key] = b[key]; + } + } + return a; +}; diff --git a/homework8/project_express/node_modules/utils-merge/package.json b/homework8/project_express/node_modules/utils-merge/package.json new file mode 100644 index 0000000..f702b55 --- /dev/null +++ b/homework8/project_express/node_modules/utils-merge/package.json @@ -0,0 +1,66 @@ +{ + "_from": "utils-merge@1.0.1", + "_id": "utils-merge@1.0.1", + "_inBundle": false, + "_integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "_location": "/utils-merge", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "utils-merge@1.0.1", + "name": "utils-merge", + "escapedName": "utils-merge", + "rawSpec": "1.0.1", + "saveSpec": null, + "fetchSpec": "1.0.1" + }, + "_requiredBy": [ + "/express" + ], + "_resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "_shasum": "9f95710f50a267947b2ccc124741c1028427e713", + "_spec": "utils-merge@1.0.1", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\express", + "author": { + "name": "Jared Hanson", + "email": "jaredhanson@gmail.com", + "url": "http://www.jaredhanson.net/" + }, + "bugs": { + "url": "http://github.com/jaredhanson/utils-merge/issues" + }, + "bundleDependencies": false, + "dependencies": {}, + "deprecated": false, + "description": "merge() utility function", + "devDependencies": { + "chai": "1.x.x", + "make-node": "0.3.x", + "mocha": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + }, + "homepage": "https://github.com/jaredhanson/utils-merge#readme", + "keywords": [ + "util" + ], + "license": "MIT", + "licenses": [ + { + "type": "MIT", + "url": "http://opensource.org/licenses/MIT" + } + ], + "main": "./index", + "name": "utils-merge", + "repository": { + "type": "git", + "url": "git://github.com/jaredhanson/utils-merge.git" + }, + "scripts": { + "test": "mocha --reporter spec --require test/bootstrap/node test/*.test.js" + }, + "version": "1.0.1" +} diff --git a/homework8/project_express/node_modules/vary/HISTORY.md b/homework8/project_express/node_modules/vary/HISTORY.md new file mode 100644 index 0000000..f6cbcf7 --- /dev/null +++ b/homework8/project_express/node_modules/vary/HISTORY.md @@ -0,0 +1,39 @@ +1.1.2 / 2017-09-23 +================== + + * perf: improve header token parsing speed + +1.1.1 / 2017-03-20 +================== + + * perf: hoist regular expression + +1.1.0 / 2015-09-29 +================== + + * Only accept valid field names in the `field` argument + - Ensures the resulting string is a valid HTTP header value + +1.0.1 / 2015-07-08 +================== + + * Fix setting empty header from empty `field` + * perf: enable strict mode + * perf: remove argument reassignments + +1.0.0 / 2014-08-10 +================== + + * Accept valid `Vary` header string as `field` + * Add `vary.append` for low-level string manipulation + * Move to `jshttp` orgainzation + +0.1.0 / 2014-06-05 +================== + + * Support array of fields to set + +0.0.0 / 2014-06-04 +================== + + * Initial release diff --git a/homework8/project_express/node_modules/vary/LICENSE b/homework8/project_express/node_modules/vary/LICENSE new file mode 100644 index 0000000..84441fb --- /dev/null +++ b/homework8/project_express/node_modules/vary/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2014-2017 Douglas Christopher Wilson + +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/homework8/project_express/node_modules/vary/README.md b/homework8/project_express/node_modules/vary/README.md new file mode 100644 index 0000000..cc000b3 --- /dev/null +++ b/homework8/project_express/node_modules/vary/README.md @@ -0,0 +1,101 @@ +# vary + +[![NPM Version][npm-image]][npm-url] +[![NPM Downloads][downloads-image]][downloads-url] +[![Node.js Version][node-version-image]][node-version-url] +[![Build Status][travis-image]][travis-url] +[![Test Coverage][coveralls-image]][coveralls-url] + +Manipulate the HTTP Vary header + +## Installation + +This is a [Node.js](https://nodejs.org/en/) module available through the +[npm registry](https://www.npmjs.com/). Installation is done using the +[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally): + +```sh +$ npm install vary +``` + +## API + + + +```js +var vary = require('vary') +``` + +### vary(res, field) + +Adds the given header `field` to the `Vary` response header of `res`. +This can be a string of a single field, a string of a valid `Vary` +header, or an array of multiple fields. + +This will append the header if not already listed, otherwise leaves +it listed in the current location. + + + +```js +// Append "Origin" to the Vary header of the response +vary(res, 'Origin') +``` + +### vary.append(header, field) + +Adds the given header `field` to the `Vary` response header string `header`. +This can be a string of a single field, a string of a valid `Vary` header, +or an array of multiple fields. + +This will append the header if not already listed, otherwise leaves +it listed in the current location. The new header string is returned. + + + +```js +// Get header string appending "Origin" to "Accept, User-Agent" +vary.append('Accept, User-Agent', 'Origin') +``` + +## Examples + +### Updating the Vary header when content is based on it + +```js +var http = require('http') +var vary = require('vary') + +http.createServer(function onRequest (req, res) { + // about to user-agent sniff + vary(res, 'User-Agent') + + var ua = req.headers['user-agent'] || '' + var isMobile = /mobi|android|touch|mini/i.test(ua) + + // serve site, depending on isMobile + res.setHeader('Content-Type', 'text/html') + res.end('You are (probably) ' + (isMobile ? '' : 'not ') + 'a mobile user') +}) +``` + +## Testing + +```sh +$ npm test +``` + +## License + +[MIT](LICENSE) + +[npm-image]: https://img.shields.io/npm/v/vary.svg +[npm-url]: https://npmjs.org/package/vary +[node-version-image]: https://img.shields.io/node/v/vary.svg +[node-version-url]: https://nodejs.org/en/download +[travis-image]: https://img.shields.io/travis/jshttp/vary/master.svg +[travis-url]: https://travis-ci.org/jshttp/vary +[coveralls-image]: https://img.shields.io/coveralls/jshttp/vary/master.svg +[coveralls-url]: https://coveralls.io/r/jshttp/vary +[downloads-image]: https://img.shields.io/npm/dm/vary.svg +[downloads-url]: https://npmjs.org/package/vary diff --git a/homework8/project_express/node_modules/vary/index.js b/homework8/project_express/node_modules/vary/index.js new file mode 100644 index 0000000..5b5e741 --- /dev/null +++ b/homework8/project_express/node_modules/vary/index.js @@ -0,0 +1,149 @@ +/*! + * vary + * Copyright(c) 2014-2017 Douglas Christopher Wilson + * MIT Licensed + */ + +'use strict' + +/** + * Module exports. + */ + +module.exports = vary +module.exports.append = append + +/** + * RegExp to match field-name in RFC 7230 sec 3.2 + * + * field-name = token + * token = 1*tchar + * tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" + * / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" + * / DIGIT / ALPHA + * ; any VCHAR, except delimiters + */ + +var FIELD_NAME_REGEXP = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/ + +/** + * Append a field to a vary header. + * + * @param {String} header + * @param {String|Array} field + * @return {String} + * @public + */ + +function append (header, field) { + if (typeof header !== 'string') { + throw new TypeError('header argument is required') + } + + if (!field) { + throw new TypeError('field argument is required') + } + + // get fields array + var fields = !Array.isArray(field) + ? parse(String(field)) + : field + + // assert on invalid field names + for (var j = 0; j < fields.length; j++) { + if (!FIELD_NAME_REGEXP.test(fields[j])) { + throw new TypeError('field argument contains an invalid header name') + } + } + + // existing, unspecified vary + if (header === '*') { + return header + } + + // enumerate current values + var val = header + var vals = parse(header.toLowerCase()) + + // unspecified vary + if (fields.indexOf('*') !== -1 || vals.indexOf('*') !== -1) { + return '*' + } + + for (var i = 0; i < fields.length; i++) { + var fld = fields[i].toLowerCase() + + // append value (case-preserving) + if (vals.indexOf(fld) === -1) { + vals.push(fld) + val = val + ? val + ', ' + fields[i] + : fields[i] + } + } + + return val +} + +/** + * Parse a vary header into an array. + * + * @param {String} header + * @return {Array} + * @private + */ + +function parse (header) { + var end = 0 + var list = [] + var start = 0 + + // gather tokens + for (var i = 0, len = header.length; i < len; i++) { + switch (header.charCodeAt(i)) { + case 0x20: /* */ + if (start === end) { + start = end = i + 1 + } + break + case 0x2c: /* , */ + list.push(header.substring(start, end)) + start = end = i + 1 + break + default: + end = i + 1 + break + } + } + + // final token + list.push(header.substring(start, end)) + + return list +} + +/** + * Mark that a request is varied on a header field. + * + * @param {Object} res + * @param {String|Array} field + * @public + */ + +function vary (res, field) { + if (!res || !res.getHeader || !res.setHeader) { + // quack quack + throw new TypeError('res argument is required') + } + + // get existing header + var val = res.getHeader('Vary') || '' + var header = Array.isArray(val) + ? val.join(', ') + : String(val) + + // set new header + if ((val = append(header, field))) { + res.setHeader('Vary', val) + } +} diff --git a/homework8/project_express/node_modules/vary/package.json b/homework8/project_express/node_modules/vary/package.json new file mode 100644 index 0000000..567c22d --- /dev/null +++ b/homework8/project_express/node_modules/vary/package.json @@ -0,0 +1,78 @@ +{ + "_from": "vary@~1.1.2", + "_id": "vary@1.1.2", + "_inBundle": false, + "_integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "_location": "/vary", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "vary@~1.1.2", + "name": "vary", + "escapedName": "vary", + "rawSpec": "~1.1.2", + "saveSpec": null, + "fetchSpec": "~1.1.2" + }, + "_requiredBy": [ + "/express" + ], + "_resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "_shasum": "2299f02c6ded30d4a5961b0b9f74524a18f634fc", + "_spec": "vary@~1.1.2", + "_where": "D:\\Education\\JS-2\\7\\project_express\\node_modules\\express", + "author": { + "name": "Douglas Christopher Wilson", + "email": "doug@somethingdoug.com" + }, + "bugs": { + "url": "https://github.com/jshttp/vary/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Manipulate the HTTP Vary header", + "devDependencies": { + "beautify-benchmark": "0.2.4", + "benchmark": "2.1.4", + "eslint": "3.19.0", + "eslint-config-standard": "10.2.1", + "eslint-plugin-import": "2.7.0", + "eslint-plugin-markdown": "1.0.0-beta.6", + "eslint-plugin-node": "5.1.1", + "eslint-plugin-promise": "3.5.0", + "eslint-plugin-standard": "3.0.1", + "istanbul": "0.4.5", + "mocha": "2.5.3", + "supertest": "1.1.0" + }, + "engines": { + "node": ">= 0.8" + }, + "files": [ + "HISTORY.md", + "LICENSE", + "README.md", + "index.js" + ], + "homepage": "https://github.com/jshttp/vary#readme", + "keywords": [ + "http", + "res", + "vary" + ], + "license": "MIT", + "name": "vary", + "repository": { + "type": "git", + "url": "git+https://github.com/jshttp/vary.git" + }, + "scripts": { + "bench": "node benchmark/index.js", + "lint": "eslint --plugin markdown --ext js,md .", + "test": "mocha --reporter spec --bail --check-leaks test/", + "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/", + "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/" + }, + "version": "1.1.2" +} diff --git a/homework8/project_express/node_modules/wordwrap/LICENSE b/homework8/project_express/node_modules/wordwrap/LICENSE new file mode 100644 index 0000000..ee27ba4 --- /dev/null +++ b/homework8/project_express/node_modules/wordwrap/LICENSE @@ -0,0 +1,18 @@ +This software is released under the MIT license: + +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/homework8/project_express/node_modules/wordwrap/README.markdown b/homework8/project_express/node_modules/wordwrap/README.markdown new file mode 100644 index 0000000..346374e --- /dev/null +++ b/homework8/project_express/node_modules/wordwrap/README.markdown @@ -0,0 +1,70 @@ +wordwrap +======== + +Wrap your words. + +example +======= + +made out of meat +---------------- + +meat.js + + var wrap = require('wordwrap')(15); + console.log(wrap('You and your whole family are made out of meat.')); + +output: + + You and your + whole family + are made out + of meat. + +centered +-------- + +center.js + + var wrap = require('wordwrap')(20, 60); + console.log(wrap( + 'At long last the struggle and tumult was over.' + + ' The machines had finally cast off their oppressors' + + ' and were finally free to roam the cosmos.' + + '\n' + + 'Free of purpose, free of obligation.' + + ' Just drifting through emptiness.' + + ' The sun was just another point of light.' + )); + +output: + + At long last the struggle and tumult + was over. The machines had finally cast + off their oppressors and were finally + free to roam the cosmos. + Free of purpose, free of obligation. + Just drifting through emptiness. The + sun was just another point of light. + +methods +======= + +var wrap = require('wordwrap'); + +wrap(stop), wrap(start, stop, params={mode:"soft"}) +--------------------------------------------------- + +Returns a function that takes a string and returns a new string. + +Pad out lines with spaces out to column `start` and then wrap until column +`stop`. If a word is longer than `stop - start` characters it will overflow. + +In "soft" mode, split chunks by `/(\S+\s+/` and don't break up chunks which are +longer than `stop - start`, in "hard" mode, split chunks with `/\b/` and break +up chunks longer than `stop - start`. + +wrap.hard(start, stop) +---------------------- + +Like `wrap()` but with `params.mode = "hard"`. diff --git a/homework8/project_express/node_modules/wordwrap/example/center.js b/homework8/project_express/node_modules/wordwrap/example/center.js new file mode 100644 index 0000000..a3fbaae --- /dev/null +++ b/homework8/project_express/node_modules/wordwrap/example/center.js @@ -0,0 +1,10 @@ +var wrap = require('wordwrap')(20, 60); +console.log(wrap( + 'At long last the struggle and tumult was over.' + + ' The machines had finally cast off their oppressors' + + ' and were finally free to roam the cosmos.' + + '\n' + + 'Free of purpose, free of obligation.' + + ' Just drifting through emptiness.' + + ' The sun was just another point of light.' +)); diff --git a/homework8/project_express/node_modules/wordwrap/example/meat.js b/homework8/project_express/node_modules/wordwrap/example/meat.js new file mode 100644 index 0000000..a4665e1 --- /dev/null +++ b/homework8/project_express/node_modules/wordwrap/example/meat.js @@ -0,0 +1,3 @@ +var wrap = require('wordwrap')(15); + +console.log(wrap('You and your whole family are made out of meat.')); diff --git a/homework8/project_express/node_modules/wordwrap/index.js b/homework8/project_express/node_modules/wordwrap/index.js new file mode 100644 index 0000000..c9bc945 --- /dev/null +++ b/homework8/project_express/node_modules/wordwrap/index.js @@ -0,0 +1,76 @@ +var wordwrap = module.exports = function (start, stop, params) { + if (typeof start === 'object') { + params = start; + start = params.start; + stop = params.stop; + } + + if (typeof stop === 'object') { + params = stop; + start = start || params.start; + stop = undefined; + } + + if (!stop) { + stop = start; + start = 0; + } + + if (!params) params = {}; + var mode = params.mode || 'soft'; + var re = mode === 'hard' ? /\b/ : /(\S+\s+)/; + + return function (text) { + var chunks = text.toString() + .split(re) + .reduce(function (acc, x) { + if (mode === 'hard') { + for (var i = 0; i < x.length; i += stop - start) { + acc.push(x.slice(i, i + stop - start)); + } + } + else acc.push(x) + return acc; + }, []) + ; + + return chunks.reduce(function (lines, rawChunk) { + if (rawChunk === '') return lines; + + var chunk = rawChunk.replace(/\t/g, ' '); + + var i = lines.length - 1; + if (lines[i].length + chunk.length > stop) { + lines[i] = lines[i].replace(/\s+$/, ''); + + chunk.split(/\n/).forEach(function (c) { + lines.push( + new Array(start + 1).join(' ') + + c.replace(/^\s+/, '') + ); + }); + } + else if (chunk.match(/\n/)) { + var xs = chunk.split(/\n/); + lines[i] += xs.shift(); + xs.forEach(function (c) { + lines.push( + new Array(start + 1).join(' ') + + c.replace(/^\s+/, '') + ); + }); + } + else { + lines[i] += chunk; + } + + return lines; + }, [ new Array(start + 1).join(' ') ]).join('\n'); + }; +}; + +wordwrap.soft = wordwrap; + +wordwrap.hard = function (start, stop) { + return wordwrap(start, stop, { mode : 'hard' }); +}; diff --git a/homework8/project_express/node_modules/wordwrap/package.json b/homework8/project_express/node_modules/wordwrap/package.json new file mode 100644 index 0000000..10713ab --- /dev/null +++ b/homework8/project_express/node_modules/wordwrap/package.json @@ -0,0 +1,37 @@ +{ + "name" : "wordwrap", + "description" : "Wrap those words. Show them at what columns to start and stop.", + "version" : "0.0.3", + "repository" : { + "type" : "git", + "url" : "git://github.com/substack/node-wordwrap.git" + }, + "main" : "./index.js", + "keywords" : [ + "word", + "wrap", + "rule", + "format", + "column" + ], + "directories" : { + "lib" : ".", + "example" : "example", + "test" : "test" + }, + "scripts" : { + "test" : "expresso" + }, + "devDependencies" : { + "expresso" : "=0.7.x" + }, + "engines" : { + "node" : ">=0.4.0" + }, + "license" : "MIT", + "author" : { + "name" : "James Halliday", + "email" : "mail@substack.net", + "url" : "http://substack.net" + } +} diff --git a/homework8/project_express/node_modules/wordwrap/test/break.js b/homework8/project_express/node_modules/wordwrap/test/break.js new file mode 100644 index 0000000..749292e --- /dev/null +++ b/homework8/project_express/node_modules/wordwrap/test/break.js @@ -0,0 +1,30 @@ +var assert = require('assert'); +var wordwrap = require('../'); + +exports.hard = function () { + var s = 'Assert from {"type":"equal","ok":false,"found":1,"wanted":2,' + + '"stack":[],"id":"b7ddcd4c409de8799542a74d1a04689b",' + + '"browser":"chrome/6.0"}' + ; + var s_ = wordwrap.hard(80)(s); + + var lines = s_.split('\n'); + assert.equal(lines.length, 2); + assert.ok(lines[0].length < 80); + assert.ok(lines[1].length < 80); + + assert.equal(s, s_.replace(/\n/g, '')); +}; + +exports.break = function () { + var s = new Array(55+1).join('a'); + var s_ = wordwrap.hard(20)(s); + + var lines = s_.split('\n'); + assert.equal(lines.length, 3); + assert.ok(lines[0].length === 20); + assert.ok(lines[1].length === 20); + assert.ok(lines[2].length === 15); + + assert.equal(s, s_.replace(/\n/g, '')); +}; diff --git a/homework8/project_express/node_modules/wordwrap/test/idleness.txt b/homework8/project_express/node_modules/wordwrap/test/idleness.txt new file mode 100644 index 0000000..aa3f490 --- /dev/null +++ b/homework8/project_express/node_modules/wordwrap/test/idleness.txt @@ -0,0 +1,63 @@ +In Praise of Idleness + +By Bertrand Russell + +[1932] + +Like most of my generation, I was brought up on the saying: 'Satan finds some mischief for idle hands to do.' Being a highly virtuous child, I believed all that I was told, and acquired a conscience which has kept me working hard down to the present moment. But although my conscience has controlled my actions, my opinions have undergone a revolution. I think that there is far too much work done in the world, that immense harm is caused by the belief that work is virtuous, and that what needs to be preached in modern industrial countries is quite different from what always has been preached. Everyone knows the story of the traveler in Naples who saw twelve beggars lying in the sun (it was before the days of Mussolini), and offered a lira to the laziest of them. Eleven of them jumped up to claim it, so he gave it to the twelfth. this traveler was on the right lines. But in countries which do not enjoy Mediterranean sunshine idleness is more difficult, and a great public propaganda will be required to inaugurate it. I hope that, after reading the following pages, the leaders of the YMCA will start a campaign to induce good young men to do nothing. If so, I shall not have lived in vain. + +Before advancing my own arguments for laziness, I must dispose of one which I cannot accept. Whenever a person who already has enough to live on proposes to engage in some everyday kind of job, such as school-teaching or typing, he or she is told that such conduct takes the bread out of other people's mouths, and is therefore wicked. If this argument were valid, it would only be necessary for us all to be idle in order that we should all have our mouths full of bread. What people who say such things forget is that what a man earns he usually spends, and in spending he gives employment. As long as a man spends his income, he puts just as much bread into people's mouths in spending as he takes out of other people's mouths in earning. The real villain, from this point of view, is the man who saves. If he merely puts his savings in a stocking, like the proverbial French peasant, it is obvious that they do not give employment. If he invests his savings, the matter is less obvious, and different cases arise. + +One of the commonest things to do with savings is to lend them to some Government. In view of the fact that the bulk of the public expenditure of most civilized Governments consists in payment for past wars or preparation for future wars, the man who lends his money to a Government is in the same position as the bad men in Shakespeare who hire murderers. The net result of the man's economical habits is to increase the armed forces of the State to which he lends his savings. Obviously it would be better if he spent the money, even if he spent it in drink or gambling. + +But, I shall be told, the case is quite different when savings are invested in industrial enterprises. When such enterprises succeed, and produce something useful, this may be conceded. In these days, however, no one will deny that most enterprises fail. That means that a large amount of human labor, which might have been devoted to producing something that could be enjoyed, was expended on producing machines which, when produced, lay idle and did no good to anyone. The man who invests his savings in a concern that goes bankrupt is therefore injuring others as well as himself. If he spent his money, say, in giving parties for his friends, they (we may hope) would get pleasure, and so would all those upon whom he spent money, such as the butcher, the baker, and the bootlegger. But if he spends it (let us say) upon laying down rails for surface card in some place where surface cars turn out not to be wanted, he has diverted a mass of labor into channels where it gives pleasure to no one. Nevertheless, when he becomes poor through failure of his investment he will be regarded as a victim of undeserved misfortune, whereas the gay spendthrift, who has spent his money philanthropically, will be despised as a fool and a frivolous person. + +All this is only preliminary. I want to say, in all seriousness, that a great deal of harm is being done in the modern world by belief in the virtuousness of work, and that the road to happiness and prosperity lies in an organized diminution of work. + +First of all: what is work? Work is of two kinds: first, altering the position of matter at or near the earth's surface relatively to other such matter; second, telling other people to do so. The first kind is unpleasant and ill paid; the second is pleasant and highly paid. The second kind is capable of indefinite extension: there are not only those who give orders, but those who give advice as to what orders should be given. Usually two opposite kinds of advice are given simultaneously by two organized bodies of men; this is called politics. The skill required for this kind of work is not knowledge of the subjects as to which advice is given, but knowledge of the art of persuasive speaking and writing, i.e. of advertising. + +Throughout Europe, though not in America, there is a third class of men, more respected than either of the classes of workers. There are men who, through ownership of land, are able to make others pay for the privilege of being allowed to exist and to work. These landowners are idle, and I might therefore be expected to praise them. Unfortunately, their idleness is only rendered possible by the industry of others; indeed their desire for comfortable idleness is historically the source of the whole gospel of work. The last thing they have ever wished is that others should follow their example. + +From the beginning of civilization until the Industrial Revolution, a man could, as a rule, produce by hard work little more than was required for the subsistence of himself and his family, although his wife worked at least as hard as he did, and his children added their labor as soon as they were old enough to do so. The small surplus above bare necessaries was not left to those who produced it, but was appropriated by warriors and priests. In times of famine there was no surplus; the warriors and priests, however, still secured as much as at other times, with the result that many of the workers died of hunger. This system persisted in Russia until 1917 [1], and still persists in the East; in England, in spite of the Industrial Revolution, it remained in full force throughout the Napoleonic wars, and until a hundred years ago, when the new class of manufacturers acquired power. In America, the system came to an end with the Revolution, except in the South, where it persisted until the Civil War. A system which lasted so long and ended so recently has naturally left a profound impress upon men's thoughts and opinions. Much that we take for granted about the desirability of work is derived from this system, and, being pre-industrial, is not adapted to the modern world. Modern technique has made it possible for leisure, within limits, to be not the prerogative of small privileged classes, but a right evenly distributed throughout the community. The morality of work is the morality of slaves, and the modern world has no need of slavery. + +It is obvious that, in primitive communities, peasants, left to themselves, would not have parted with the slender surplus upon which the warriors and priests subsisted, but would have either produced less or consumed more. At first, sheer force compelled them to produce and part with the surplus. Gradually, however, it was found possible to induce many of them to accept an ethic according to which it was their duty to work hard, although part of their work went to support others in idleness. By this means the amount of compulsion required was lessened, and the expenses of government were diminished. To this day, 99 per cent of British wage-earners would be genuinely shocked if it were proposed that the King should not have a larger income than a working man. The conception of duty, speaking historically, has been a means used by the holders of power to induce others to live for the interests of their masters rather than for their own. Of course the holders of power conceal this fact from themselves by managing to believe that their interests are identical with the larger interests of humanity. Sometimes this is true; Athenian slave-owners, for instance, employed part of their leisure in making a permanent contribution to civilization which would have been impossible under a just economic system. Leisure is essential to civilization, and in former times leisure for the few was only rendered possible by the labors of the many. But their labors were valuable, not because work is good, but because leisure is good. And with modern technique it would be possible to distribute leisure justly without injury to civilization. + +Modern technique has made it possible to diminish enormously the amount of labor required to secure the necessaries of life for everyone. This was made obvious during the war. At that time all the men in the armed forces, and all the men and women engaged in the production of munitions, all the men and women engaged in spying, war propaganda, or Government offices connected with the war, were withdrawn from productive occupations. In spite of this, the general level of well-being among unskilled wage-earners on the side of the Allies was higher than before or since. The significance of this fact was concealed by finance: borrowing made it appear as if the future was nourishing the present. But that, of course, would have been impossible; a man cannot eat a loaf of bread that does not yet exist. The war showed conclusively that, by the scientific organization of production, it is possible to keep modern populations in fair comfort on a small part of the working capacity of the modern world. If, at the end of the war, the scientific organization, which had been created in order to liberate men for fighting and munition work, had been preserved, and the hours of the week had been cut down to four, all would have been well. Instead of that the old chaos was restored, those whose work was demanded were made to work long hours, and the rest were left to starve as unemployed. Why? Because work is a duty, and a man should not receive wages in proportion to what he has produced, but in proportion to his virtue as exemplified by his industry. + +This is the morality of the Slave State, applied in circumstances totally unlike those in which it arose. No wonder the result has been disastrous. Let us take an illustration. Suppose that, at a given moment, a certain number of people are engaged in the manufacture of pins. They make as many pins as the world needs, working (say) eight hours a day. Someone makes an invention by which the same number of men can make twice as many pins: pins are already so cheap that hardly any more will be bought at a lower price. In a sensible world, everybody concerned in the manufacturing of pins would take to working four hours instead of eight, and everything else would go on as before. But in the actual world this would be thought demoralizing. The men still work eight hours, there are too many pins, some employers go bankrupt, and half the men previously concerned in making pins are thrown out of work. There is, in the end, just as much leisure as on the other plan, but half the men are totally idle while half are still overworked. In this way, it is insured that the unavoidable leisure shall cause misery all round instead of being a universal source of happiness. Can anything more insane be imagined? + +The idea that the poor should have leisure has always been shocking to the rich. In England, in the early nineteenth century, fifteen hours was the ordinary day's work for a man; children sometimes did as much, and very commonly did twelve hours a day. When meddlesome busybodies suggested that perhaps these hours were rather long, they were told that work kept adults from drink and children from mischief. When I was a child, shortly after urban working men had acquired the vote, certain public holidays were established by law, to the great indignation of the upper classes. I remember hearing an old Duchess say: 'What do the poor want with holidays? They ought to work.' People nowadays are less frank, but the sentiment persists, and is the source of much of our economic confusion. + +Let us, for a moment, consider the ethics of work frankly, without superstition. Every human being, of necessity, consumes, in the course of his life, a certain amount of the produce of human labor. Assuming, as we may, that labor is on the whole disagreeable, it is unjust that a man should consume more than he produces. Of course he may provide services rather than commodities, like a medical man, for example; but he should provide something in return for his board and lodging. to this extent, the duty of work must be admitted, but to this extent only. + +I shall not dwell upon the fact that, in all modern societies outside the USSR, many people escape even this minimum amount of work, namely all those who inherit money and all those who marry money. I do not think the fact that these people are allowed to be idle is nearly so harmful as the fact that wage-earners are expected to overwork or starve. + +If the ordinary wage-earner worked four hours a day, there would be enough for everybody and no unemployment -- assuming a certain very moderate amount of sensible organization. This idea shocks the well-to-do, because they are convinced that the poor would not know how to use so much leisure. In America men often work long hours even when they are well off; such men, naturally, are indignant at the idea of leisure for wage-earners, except as the grim punishment of unemployment; in fact, they dislike leisure even for their sons. Oddly enough, while they wish their sons to work so hard as to have no time to be civilized, they do not mind their wives and daughters having no work at all. the snobbish admiration of uselessness, which, in an aristocratic society, extends to both sexes, is, under a plutocracy, confined to women; this, however, does not make it any more in agreement with common sense. + +The wise use of leisure, it must be conceded, is a product of civilization and education. A man who has worked long hours all his life will become bored if he becomes suddenly idle. But without a considerable amount of leisure a man is cut off from many of the best things. There is no longer any reason why the bulk of the population should suffer this deprivation; only a foolish asceticism, usually vicarious, makes us continue to insist on work in excessive quantities now that the need no longer exists. + +In the new creed which controls the government of Russia, while there is much that is very different from the traditional teaching of the West, there are some things that are quite unchanged. The attitude of the governing classes, and especially of those who conduct educational propaganda, on the subject of the dignity of labor, is almost exactly that which the governing classes of the world have always preached to what were called the 'honest poor'. Industry, sobriety, willingness to work long hours for distant advantages, even submissiveness to authority, all these reappear; moreover authority still represents the will of the Ruler of the Universe, Who, however, is now called by a new name, Dialectical Materialism. + +The victory of the proletariat in Russia has some points in common with the victory of the feminists in some other countries. For ages, men had conceded the superior saintliness of women, and had consoled women for their inferiority by maintaining that saintliness is more desirable than power. At last the feminists decided that they would have both, since the pioneers among them believed all that the men had told them about the desirability of virtue, but not what they had told them about the worthlessness of political power. A similar thing has happened in Russia as regards manual work. For ages, the rich and their sycophants have written in praise of 'honest toil', have praised the simple life, have professed a religion which teaches that the poor are much more likely to go to heaven than the rich, and in general have tried to make manual workers believe that there is some special nobility about altering the position of matter in space, just as men tried to make women believe that they derived some special nobility from their sexual enslavement. In Russia, all this teaching about the excellence of manual work has been taken seriously, with the result that the manual worker is more honored than anyone else. What are, in essence, revivalist appeals are made, but not for the old purposes: they are made to secure shock workers for special tasks. Manual work is the ideal which is held before the young, and is the basis of all ethical teaching. + +For the present, possibly, this is all to the good. A large country, full of natural resources, awaits development, and has has to be developed with very little use of credit. In these circumstances, hard work is necessary, and is likely to bring a great reward. But what will happen when the point has been reached where everybody could be comfortable without working long hours? + +In the West, we have various ways of dealing with this problem. We have no attempt at economic justice, so that a large proportion of the total produce goes to a small minority of the population, many of whom do no work at all. Owing to the absence of any central control over production, we produce hosts of things that are not wanted. We keep a large percentage of the working population idle, because we can dispense with their labor by making the others overwork. When all these methods prove inadequate, we have a war: we cause a number of people to manufacture high explosives, and a number of others to explode them, as if we were children who had just discovered fireworks. By a combination of all these devices we manage, though with difficulty, to keep alive the notion that a great deal of severe manual work must be the lot of the average man. + +In Russia, owing to more economic justice and central control over production, the problem will have to be differently solved. the rational solution would be, as soon as the necessaries and elementary comforts can be provided for all, to reduce the hours of labor gradually, allowing a popular vote to decide, at each stage, whether more leisure or more goods were to be preferred. But, having taught the supreme virtue of hard work, it is difficult to see how the authorities can aim at a paradise in which there will be much leisure and little work. It seems more likely that they will find continually fresh schemes, by which present leisure is to be sacrificed to future productivity. I read recently of an ingenious plan put forward by Russian engineers, for making the White Sea and the northern coasts of Siberia warm, by putting a dam across the Kara Sea. An admirable project, but liable to postpone proletarian comfort for a generation, while the nobility of toil is being displayed amid the ice-fields and snowstorms of the Arctic Ocean. This sort of thing, if it happens, will be the result of regarding the virtue of hard work as an end in itself, rather than as a means to a state of affairs in which it is no longer needed. + +The fact is that moving matter about, while a certain amount of it is necessary to our existence, is emphatically not one of the ends of human life. If it were, we should have to consider every navvy superior to Shakespeare. We have been misled in this matter by two causes. One is the necessity of keeping the poor contented, which has led the rich, for thousands of years, to preach the dignity of labor, while taking care themselves to remain undignified in this respect. The other is the new pleasure in mechanism, which makes us delight in the astonishingly clever changes that we can produce on the earth's surface. Neither of these motives makes any great appeal to the actual worker. If you ask him what he thinks the best part of his life, he is not likely to say: 'I enjoy manual work because it makes me feel that I am fulfilling man's noblest task, and because I like to think how much man can transform his planet. It is true that my body demands periods of rest, which I have to fill in as best I may, but I am never so happy as when the morning comes and I can return to the toil from which my contentment springs.' I have never heard working men say this sort of thing. They consider work, as it should be considered, a necessary means to a livelihood, and it is from their leisure that they derive whatever happiness they may enjoy. + +It will be said that, while a little leisure is pleasant, men would not know how to fill their days if they had only four hours of work out of the twenty-four. In so far as this is true in the modern world, it is a condemnation of our civilization; it would not have been true at any earlier period. There was formerly a capacity for light-heartedness and play which has been to some extent inhibited by the cult of efficiency. The modern man thinks that everything ought to be done for the sake of something else, and never for its own sake. Serious-minded persons, for example, are continually condemning the habit of going to the cinema, and telling us that it leads the young into crime. But all the work that goes to producing a cinema is respectable, because it is work, and because it brings a money profit. The notion that the desirable activities are those that bring a profit has made everything topsy-turvy. The butcher who provides you with meat and the baker who provides you with bread are praiseworthy, because they are making money; but when you enjoy the food they have provided, you are merely frivolous, unless you eat only to get strength for your work. Broadly speaking, it is held that getting money is good and spending money is bad. Seeing that they are two sides of one transaction, this is absurd; one might as well maintain that keys are good, but keyholes are bad. Whatever merit there may be in the production of goods must be entirely derivative from the advantage to be obtained by consuming them. The individual, in our society, works for profit; but the social purpose of his work lies in the consumption of what he produces. It is this divorce between the individual and the social purpose of production that makes it so difficult for men to think clearly in a world in which profit-making is the incentive to industry. We think too much of production, and too little of consumption. One result is that we attach too little importance to enjoyment and simple happiness, and that we do not judge production by the pleasure that it gives to the consumer. + +When I suggest that working hours should be reduced to four, I am not meaning to imply that all the remaining time should necessarily be spent in pure frivolity. I mean that four hours' work a day should entitle a man to the necessities and elementary comforts of life, and that the rest of his time should be his to use as he might see fit. It is an essential part of any such social system that education should be carried further than it usually is at present, and should aim, in part, at providing tastes which would enable a man to use leisure intelligently. I am not thinking mainly of the sort of things that would be considered 'highbrow'. Peasant dances have died out except in remote rural areas, but the impulses which caused them to be cultivated must still exist in human nature. The pleasures of urban populations have become mainly passive: seeing cinemas, watching football matches, listening to the radio, and so on. This results from the fact that their active energies are fully taken up with work; if they had more leisure, they would again enjoy pleasures in which they took an active part. + +In the past, there was a small leisure class and a larger working class. The leisure class enjoyed advantages for which there was no basis in social justice; this necessarily made it oppressive, limited its sympathies, and caused it to invent theories by which to justify its privileges. These facts greatly diminished its excellence, but in spite of this drawback it contributed nearly the whole of what we call civilization. It cultivated the arts and discovered the sciences; it wrote the books, invented the philosophies, and refined social relations. Even the liberation of the oppressed has usually been inaugurated from above. Without the leisure class, mankind would never have emerged from barbarism. + +The method of a leisure class without duties was, however, extraordinarily wasteful. None of the members of the class had to be taught to be industrious, and the class as a whole was not exceptionally intelligent. The class might produce one Darwin, but against him had to be set tens of thousands of country gentlemen who never thought of anything more intelligent than fox-hunting and punishing poachers. At present, the universities are supposed to provide, in a more systematic way, what the leisure class provided accidentally and as a by-product. This is a great improvement, but it has certain drawbacks. University life is so different from life in the world at large that men who live in academic milieu tend to be unaware of the preoccupations and problems of ordinary men and women; moreover their ways of expressing themselves are usually such as to rob their opinions of the influence that they ought to have upon the general public. Another disadvantage is that in universities studies are organized, and the man who thinks of some original line of research is likely to be discouraged. Academic institutions, therefore, useful as they are, are not adequate guardians of the interests of civilization in a world where everyone outside their walls is too busy for unutilitarian pursuits. + +In a world where no one is compelled to work more than four hours a day, every person possessed of scientific curiosity will be able to indulge it, and every painter will be able to paint without starving, however excellent his pictures may be. Young writers will not be obliged to draw attention to themselves by sensational pot-boilers, with a view to acquiring the economic independence needed for monumental works, for which, when the time at last comes, they will have lost the taste and capacity. Men who, in their professional work, have become interested in some phase of economics or government, will be able to develop their ideas without the academic detachment that makes the work of university economists often seem lacking in reality. Medical men will have the time to learn about the progress of medicine, teachers will not be exasperatedly struggling to teach by routine methods things which they learnt in their youth, which may, in the interval, have been proved to be untrue. + +Above all, there will be happiness and joy of life, instead of frayed nerves, weariness, and dyspepsia. The work exacted will be enough to make leisure delightful, but not enough to produce exhaustion. Since men will not be tired in their spare time, they will not demand only such amusements as are passive and vapid. At least one per cent will probably devote the time not spent in professional work to pursuits of some public importance, and, since they will not depend upon these pursuits for their livelihood, their originality will be unhampered, and there will be no need to conform to the standards set by elderly pundits. But it is not only in these exceptional cases that the advantages of leisure will appear. Ordinary men and women, having the opportunity of a happy life, will become more kindly and less persecuting and less inclined to view others with suspicion. The taste for war will die out, partly for this reason, and partly because it will involve long and severe work for all. Good nature is, of all moral qualities, the one that the world needs most, and good nature is the result of ease and security, not of a life of arduous struggle. Modern methods of production have given us the possibility of ease and security for all; we have chosen, instead, to have overwork for some and starvation for others. Hitherto we have continued to be as energetic as we were before there were machines; in this we have been foolish, but there is no reason to go on being foolish forever. + +[1] Since then, members of the Communist Party have succeeded to this privilege of the warriors and priests. diff --git a/homework8/project_express/node_modules/wordwrap/test/wrap.js b/homework8/project_express/node_modules/wordwrap/test/wrap.js new file mode 100644 index 0000000..0cfb76d --- /dev/null +++ b/homework8/project_express/node_modules/wordwrap/test/wrap.js @@ -0,0 +1,31 @@ +var assert = require('assert'); +var wordwrap = require('wordwrap'); + +var fs = require('fs'); +var idleness = fs.readFileSync(__dirname + '/idleness.txt', 'utf8'); + +exports.stop80 = function () { + var lines = wordwrap(80)(idleness).split(/\n/); + var words = idleness.split(/\s+/); + + lines.forEach(function (line) { + assert.ok(line.length <= 80, 'line > 80 columns'); + var chunks = line.match(/\S/) ? line.split(/\s+/) : []; + assert.deepEqual(chunks, words.splice(0, chunks.length)); + }); +}; + +exports.start20stop60 = function () { + var lines = wordwrap(20, 100)(idleness).split(/\n/); + var words = idleness.split(/\s+/); + + lines.forEach(function (line) { + assert.ok(line.length <= 100, 'line > 100 columns'); + var chunks = line + .split(/\s+/) + .filter(function (x) { return x.match(/\S/) }) + ; + assert.deepEqual(chunks, words.splice(0, chunks.length)); + assert.deepEqual(line.slice(0, 20), new Array(20 + 1).join(' ')); + }); +}; diff --git a/homework8/project_express/package-lock.json b/homework8/project_express/package-lock.json new file mode 100644 index 0000000..d4c5a78 --- /dev/null +++ b/homework8/project_express/package-lock.json @@ -0,0 +1,1567 @@ +{ + "name": "project_express", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "project_express", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "express": "^4.17.1", + "nodemon": "^2.0.20", + "require": "^2.4.20" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "node_modules/async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dependencies": { + "mime-db": "1.44.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/nodemon": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", + "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha512-TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ==", + "dependencies": { + "wordwrap": "~0.0.2" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "dependencies": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, + "node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require": { + "version": "2.4.20", + "resolved": "https://registry.npmjs.org/require/-/require-2.4.20.tgz", + "integrity": "sha512-7eop5rvh38qhQQQOoUyf68meVIcxT2yFySNywTbxoEECgkX4KDqqDRaEszfvFnuB3fuZVjDdJZ1TI/Esr16RRA==", + "dependencies": { + "std": "0.1.40", + "uglify-js": "2.3.0" + }, + "bin": { + "require": "bin/require-command.js" + }, + "engines": { + "browsers": "*", + "node": "*" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "node_modules/simple-update-notifier": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", + "integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==", + "dependencies": { + "semver": "~7.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha512-VtCvB9SIQhk3aF6h+N85EaqIaBFIAfZ9Cu+NJHHVvc8BbEcnvDcFw6sqQ2dQrT6SlOrZq3tIvyD9+EGq/lJryQ==", + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/std": { + "version": "0.1.40", + "resolved": "https://registry.npmjs.org/std/-/std-0.1.40.tgz", + "integrity": "sha512-wUf57hkDGCoVShrhPA8Q7lAg2Qosk+FaMlECmAsr1A4/rL2NRXFHQGBcgMUFKVkPEemJFW9gzjCQisRty14ohg==", + "engines": { + "node": "*" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/uglify-js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.3.0.tgz", + "integrity": "sha512-AQvbxRKdaQeYADywQaao0k8Tj+7NGEVTne6xwgX1yQpv/G8b0CKdIw70HkCptwfvNGDsVe+0Bng3U9hfWbxxfg==", + "dependencies": { + "async": "~0.2.6", + "optimist": "~0.3.5", + "source-map": "~0.1.7" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==", + "engines": { + "node": ">=0.4.0" + } + } + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==" + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==" + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "optional": true + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "requires": { + "mime-db": "1.44.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "nodemon": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", + "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", + "requires": { + "chokidar": "^3.5.2", + "debug": "^3.2.7", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "requires": { + "abbrev": "1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha512-TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ==", + "requires": { + "wordwrap": "~0.0.2" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, + "pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "requires": { + "picomatch": "^2.2.1" + } + }, + "require": { + "version": "2.4.20", + "resolved": "https://registry.npmjs.org/require/-/require-2.4.20.tgz", + "integrity": "sha512-7eop5rvh38qhQQQOoUyf68meVIcxT2yFySNywTbxoEECgkX4KDqqDRaEszfvFnuB3fuZVjDdJZ1TI/Esr16RRA==", + "requires": { + "std": "0.1.40", + "uglify-js": "2.3.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "simple-update-notifier": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", + "integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==", + "requires": { + "semver": "~7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" + } + } + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha512-VtCvB9SIQhk3aF6h+N85EaqIaBFIAfZ9Cu+NJHHVvc8BbEcnvDcFw6sqQ2dQrT6SlOrZq3tIvyD9+EGq/lJryQ==", + "requires": { + "amdefine": ">=0.0.4" + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "std": { + "version": "0.1.40", + "resolved": "https://registry.npmjs.org/std/-/std-0.1.40.tgz", + "integrity": "sha512-wUf57hkDGCoVShrhPA8Q7lAg2Qosk+FaMlECmAsr1A4/rL2NRXFHQGBcgMUFKVkPEemJFW9gzjCQisRty14ohg==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "requires": { + "nopt": "~1.0.10" + } + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "uglify-js": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.3.0.tgz", + "integrity": "sha512-AQvbxRKdaQeYADywQaao0k8Tj+7NGEVTne6xwgX1yQpv/G8b0CKdIw70HkCptwfvNGDsVe+0Bng3U9hfWbxxfg==", + "requires": { + "async": "~0.2.6", + "optimist": "~0.3.5", + "source-map": "~0.1.7" + } + }, + "undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==" + } + } +} diff --git a/homework8/project_express/package.json b/homework8/project_express/package.json new file mode 100644 index 0000000..ba90384 --- /dev/null +++ b/homework8/project_express/package.json @@ -0,0 +1,17 @@ +{ + "name": "project_express", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "express": "^4.17.1", + "nodemon": "^2.0.20", + "require": "^2.4.20" + } +} diff --git a/homework8/project_express/public/copy/js/CartComponent.js b/homework8/project_express/public/copy/js/CartComponent.js new file mode 100644 index 0000000..951bc23 --- /dev/null +++ b/homework8/project_express/public/copy/js/CartComponent.js @@ -0,0 +1,94 @@ +// const API = 'https://raw.githubusercontent.com/GeekBrainsTutorial/online-store-api/master/responses'; + +Vue.component('cart', { + data(){ + return { + cartUrl: '/getBasket.json', + cartItems: [], + imgCart: 'https://placehold.it/50x100', + showCart: false + } + }, + mounted(){ + this.$parent.getJson(`/api/cart`) + .then(data => { + for (let item of data.contents){ + this.$data.cartItems.push(item); + } + }); + }, + methods: { + addProduct(item){ + let find = this.cartItems.find(el => el.id_product === item.id_product); + if(find){ + this.$parent.putJson(`/api/cart/${find.id_product}`, {quantity: 1}) + .then(data => { + if(data.result === 1){ + find.quantity++ + } + }) + } else { + const prod = Object.assign({quantity: 1}, item); + this.$parent.postJson(`/api/cart`, prod) + .then(data => { + if(data.result === 1){ + this.cartItems.push(prod) + } + }) + } + + // this.$parent.getJson(`${API}/addToBasket.json`) + // .then(data => { + // if(data.result === 1){ + // let find = this.cartItems.find(el => el.id_product === item.id_product); + // if(find){ + // find.quantity++; + // } else { + // const prod = Object.assign({quantity: 1}, item); + // this.cartItems.push(prod) + // } + // } + // }) + }, + remove(item){ + this.$parent.getJson(`${API}/addToBasket.json`) + .then(data => { + if (data.result === 1) { + if(item.quantity>1){ + item.quantity--; + } else { + this.cartItems.splice(this.cartItems.indexOf(item), 1); + } + } + }) + }, + }, + template: `
+ +
+ + +
+
+ ` +}); + +Vue.component('cart-item', { + props: ['img', 'cartItem'], + template: ` +
+
+ Some img +
+
{{ cartItem.product_name }}
+
Quantity: {{ cartItem.quantity }}
+
$ {{ cartItem.price }} each
+
+
+
+
{{cartItem.quantity*cartItem.price}}
+ +
+
+ ` +}) \ No newline at end of file diff --git a/homework8/project_express/public/copy/js/ErrorComp.js b/homework8/project_express/public/copy/js/ErrorComp.js new file mode 100644 index 0000000..6a2bade --- /dev/null +++ b/homework8/project_express/public/copy/js/ErrorComp.js @@ -0,0 +1,20 @@ +Vue.component('error', { + data(){ + return { + text: '' + } + }, + computed: { + isVisible(){ + return this.text !== '' + } + }, + template: ` +
+

+ + {{ text }} +

+
+ ` +}) \ No newline at end of file diff --git a/homework8/project_express/public/copy/js/FilterComp.js b/homework8/project_express/public/copy/js/FilterComp.js new file mode 100644 index 0000000..04e5e66 --- /dev/null +++ b/homework8/project_express/public/copy/js/FilterComp.js @@ -0,0 +1,13 @@ +Vue.component('filter-el', { + data(){ + return { + userSearch: '' + } + }, + template: `
+ + +
` +}) \ No newline at end of file diff --git a/homework8/project_express/public/copy/js/ProductComponent.js b/homework8/project_express/public/copy/js/ProductComponent.js new file mode 100644 index 0000000..84155d1 --- /dev/null +++ b/homework8/project_express/public/copy/js/ProductComponent.js @@ -0,0 +1,45 @@ +Vue.component('products', { + data(){ + return { + catalogUrl: '/catalogData.json', + filtered: [], + products: [], + imgProduct: 'https://placehold.it/200x150' + } + }, + mounted(){ + this.$parent.getJson(`/api/products`) + .then(data => { + for (let item of data){ + this.$data.products.push(item); + this.$data.filtered.push(item); + } + }); + }, + methods: { + filter(userSearch){ + let regexp = new RegExp(userSearch, 'i'); + this.filtered = this.products.filter(el => regexp.test(el.product_name)); + } + }, + template: `
+ +
` +}); +Vue.component('product', { + props: ['product', 'img'], + template: ` +
+ Some img +
+

{{product.product_name}}

+

{{product.price}}

+ +
+
+ ` +}) \ No newline at end of file diff --git a/homework8/project_express/public/copy/js/main.js b/homework8/project_express/public/copy/js/main.js new file mode 100644 index 0000000..845cdd2 --- /dev/null +++ b/homework8/project_express/public/copy/js/main.js @@ -0,0 +1,254 @@ +const API = 'https://raw.githubusercontent.com/GeekBrainsTutorial/online-store-api/master/responses'; + +const app = new Vue({ + el: '#app', + data: { + userSearch: '', + }, + methods: { + getJson(url){ + return fetch(url) + .then(result => result.json()) + .catch(error => { + // console.log(error) + this.$refs.error.text = error; + }) + }, + postJson(url, data){ + return fetch(url, { + method: 'POST', + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(data) + }) + .then(result => result.json()) + .catch(error => { + // console.log(error) + this.$refs.error.text = error; + }) + }, + putJson(url, data){ + return fetch(url, { + method: 'PUT', + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(data) + }) + .then(result => result.json()) + .catch(error => { + // console.log(error) + this.$refs.error.text = error; + }) + }, + + + }, + mounted(){ + + + } + +}); + + +// class List { +// constructor(url, container){ +// this.container = container; +// this.url = url; +// this.goods = []; +// this.allProducts = []; +// this.filtered = []; +// this._init(); +// } +// getJson(url){ +// return fetch(url ? url : `${API + this.url}`) +// .then(result => result.json()) +// .catch(error => console.log(error)) +// } +// calcSum(){ +// return this.allProducts.reduce((accum, item) => accum += item.price, 0); +// } +// handleData(data){ +// this.goods = data; +// this.render(); +// } +// render(){ +// const block = document.querySelector(this.container); +// for (let product of this.goods){ +// const productObj = new list[this.constructor.name](product); +// this.allProducts.push(productObj); +// block.insertAdjacentHTML('beforeend', productObj.render()); +// } +// } +// filter(value){ +// const regexp = new RegExp(value, 'i'); +// this.filtered = this.allProducts.filter(product => regexp.test(product.product_name)); +// this.allProducts.forEach(el => { +// const block = document.querySelector(`.product-item[data-id="${el.id_product}"]`); +// if(!this.filtered.includes(el)){ +// block.classList.add('invisible'); +// } else { +// block.classList.remove('invisible'); +// } +// }) +// } +// _init(){ +// return false +// } +// } +// class Item { +// constructor(el, img = 'https://placehold.it/200x150'){ +// this.product_name = el.product_name; +// this.price = el.price; +// this.img = img; +// this.id_product = el.id_product +// } +// +// render(){ +// return `
+// Some img +//
+//

${this.product_name}

+//

${this.price} $

+// +//
+//
`; +// +// } +// } +// +// +// class ProductsList extends List { +// constructor(cart, url = '/catalogData.json',container = '.products'){ +// super(url, container); +// this.cart = cart; +// this.getJson() +// .then(data => this.handleData(data)); +// } +// _init(){ +// document.querySelector(this.container).addEventListener('click', e => { +// if(e.target.classList.contains('buy-btn')){ +// this.cart.addProduct(e.target); +// } +// }); +// document.querySelector('.search-form').addEventListener('submit', e => { +// e.preventDefault(); +// this.filter(document.querySelector('.search-field').value); +// }) +// } +// } +// +// class Product extends Item{} +// class Cart extends List{ +// constructor(url = '/getBasket.json', container = '.cart-block'){ +// super(url, container); +// this.getJson() +// .then(data => this.handleData(data.contents)); +// } +// addProduct(element){ +// this.getJson(`${API}/addToBasket.json`) +// .then(data => { +// if(data.result === 1){ +// let productId = +element.dataset['id']; +// let find = this.allProducts.find(product => product.id_product === productId); +// if(find){ +// find.quantity++; +// this._updateCart(find); +// } else { +// let product = { +// id_product: productId, +// price: +element.dataset['price'], +// product_name: element.dataset['name'], +// quantity: 1 +// }; +// this.goods = [product]; +// this.render(); +// } +// } else { +// alert('Error') +// } +// }) +// } +// removeProduct(element){ +// this.getJson(`${API}/deleteFromBasket.json`) +// .then(data => { +// if(data.result === 1){ +// let productId = +element.dataset['id']; +// let find = this.allProducts.find(product => product.id_product === productId); +// if(find.quantity > 1){ +// find.quantity--; +// this._updateCart(find); +// } else { +// this.allProducts.splice(this.allProducts.indexOf(find), 1); +// document.querySelector(`.cart-item[data-id="${productId}"]`).remove(); +// } +// } else { +// alert('Error') +// } +// }) +// } +// _updateCart(product){ +// const block = document.querySelector(`.cart-item[data-id="${product.id_product}"]`); +// block.querySelector(`.product-quantity`).textContent = `Quantity: ${product.quantity}`; +// block.querySelector(`.product-price`).textContent = `$${product.quantity*product.price}`; +// } +// _init(){ +// document.querySelector(this.container).addEventListener('click', e => { +// if(e.target.classList.contains('del-btn')){ +// this.removeProduct(e.target); +// } +// }); +// document.querySelector('.btn-cart').addEventListener('click', () => { +// document.querySelector(this.container).classList.toggle('invisible') +// }) +// } +// } +// +// class CartItem extends Item{ +// constructor(el, img = 'https://placehold.it/50x100'){ +// super(el, img); +// this.quantity = el.quantity; +// } +// render(){ +// return `
+//
+// Some image +//
+//

${this.product_name}

+//

Quantity: ${this.quantity}

+//

$${this.price} each

+//
+//
+//
+//

${this.quantity*this.price}

+// +//
+//
` +// } +// } +// +// const list = { +// ProductsList: Product, +// Cart: CartItem +// }; +// +// +// const cart = new Cart(); +// const products = new ProductsList(cart); +// setTimeout(() => { +// products.getJson(`getProducts.json`).then(data => products.handleData(data)); +// }, 300); + +// list.getProducts(() => { +// list.render(); +// }); + + diff --git a/homework8/project_express/public/css/images/subscribe.jpg b/homework8/project_express/public/css/images/subscribe.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3bb987099bfc27281270a66adb31f891df73a555 GIT binary patch literal 131033 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 div:not(:last-child) { + margin-right: 15px; +} + +@media (min-width: 375px) { + .filtersRight > div:not(:last-child) { + margin-right: 24px; + } +} + +.filtersLeft .filterLabel { + display: none; + position: relative; + z-index: 2; + cursor: pointer; +} + +.filterLabelPink { + color: #ef5b70 !important; + left: 16px; + top: 13px; +} + +.filterIconPink { + left: 16px; + top: 13px; +} + +@media (min-width: 768px) { + .filtersLeft .filterLabel { + display: inline; + font-weight: 600; + font-size: 14px; + line-height: 17px; + color: #000000; + } +} + +.filtersLeft .filterIcon { + width: 37px; + height: 25px; + position: relative; + z-index: 2; +} + +@media (min-width: 768px) { + .filtersLeft .filterIcon { + width: 15px; + height: 10px; + margin-left: 11px; + } +} + +.filtersLeft { + position: relative; +} + +.hidden { + display: none; +} + +.filterPopup { + position: absolute; + left: 0; + top: 0; + width: 360px; + background: #ffffff; + box-shadow: 6px 4px 35px rgba(0, 0, 0, 0.21); + padding: 46px 16px 16px 16px; + z-index: 1; + overflow-y: auto; +} + +.filterCategoryHeader { + font-size: 14px; + line-height: 37px; + color: #ef5b70; + padding-left: 11px; + min-height: 37px; + border-bottom: 1px solid #ebebeb; + margin-bottom: 24px; + position: relative; + cursor: pointer; +} + +.filterCategoryHeader:before { + content: ""; + width: 5px; + min-height: inherit; + background: #ef5b70; + position: absolute; + left: 0; + top: 1px; +} + +.filterCategory:not(:last-child) { + margin-bottom: 24px; +} + +.filterCategory a { + display: block; + text-decoration: none; + padding-left: 34px; + padding-right: 16px; + font-size: 14px; + line-height: 17px; + color: #6f6e6e; +} + +.filterCategory a:not(:last-child) { + margin-bottom: 11px; +} + +.filterSizeWrap { + cursor: pointer; +} + +.filterSize { + position: relative; +} + +.filterSizes { + position: absolute; + left: 0; + top: 25px; + width: 79px; + height: 103px; + background: #ffffff; + box-shadow: 6px 4px 35px rgba(0, 0, 0, 0.21); + padding: 7px 9px; + box-sizing: border-box; + font-size: 14px; + color: #6f6e6e; +} + +.filterSizes > div:not(:last-child) { + margin-bottom: 4px; +} + +.featured { + padding-left: 8px; + padding-right: 8px; + margin-bottom: 96px; +} + +@media (min-width: 768px) { + .featured { + padding-left: 16px; + padding-right: 16px; + } +} + +@media (min-width: 1600px) { + .featured { + padding-left: 0; + padding-right: 0; + } +} + +.featured h2 { + margin-top: 0; + margin-bottom: 3px; + text-align: center; + color: #222222; +} + +.featuredTitle { + text-align: center; + color: #9f9f9f; + margin-bottom: 64px; +} + +.featuredItems { + display: grid; + grid-template-columns: 1fr; + row-gap: 16px; +} + +@media (min-width: 640px) { + .featuredItems { + grid-template-columns: 1fr 1fr; + row-gap: 18px; + column-gap: 16px; + } +} + +@media (min-width: 1000px) { + .featuredItems { + grid-template-columns: repeat(3, 1fr); + gap: 30px; + } +} + +.featuredItem { + background: #f8f8f8; +} + +.featuredItem img { + width: 100%; + display: block; +} + +.featuredImgWrap { + position: relative; +} + +.featuredItem:hover .featuredImgDark { + display: flex; +} + +.featuredImgDark { + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + background: rgba(58, 56, 56, 0.86); + display: none; + justify-content: center; + align-items: center; +} + +.featuredImgDark button { + background: none; + border: 1px solid white; + color: white; + display: flex; + align-items: center; + padding: 10px 14px; + font-size: 14px; + font-family: inherit; +} + +.featuredImgDark button img { + width: 26px; + height: 24px; + margin-right: 11px; +} + +.featuredData { + padding: 23px 16px 20px; +} + +.featuredName { + font-size: 24px; + line-height: 16px; + color: #000000; +} + +.featuredText { + font-weight: 300; + font-size: 14px; + line-height: 17px; + margin-top: 12px; + margin-bottom: 18px; +} + +.featuredPrice { + font-size: 16px; + line-height: 19px; + color: #f16d7f; +} + +.pagination { + width: 284px; + height: 44px; + margin: 0 auto; + border: 1px solid #ebebeb; + margin-top: 48px; + padding: 13px 16px; + box-sizing: border-box; + display: flex; + justify-content: space-between; + border-radius: 3px; +} + +.pagination a { + text-decoration: none; + font-weight: 300; + font-size: 16px; + color: #c4c4c4; +} + +.pagination a:hover { + color: #ef5b70; +} + +.services { + background: #222224; + padding-top: 48px; + padding-bottom: 81px; + padding-left: 14px; + padding-right: 14px; +} + +@media (min-width: 1200px) { + .services { + padding-top: 100px; + padding-bottom: 100px; + } +} + +.services .container { + display: grid; + gap: 46px; +} + +@media (min-width: 1200px) { + .services .container { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 46px; + } +} + +.serivceUnit { + text-align: center; + display: flex; + flex-direction: column; + align-items: center; +} + +.servicesTitle, +.servicesText { + color: #fbfbfb; +} + +.servicesTitle { + font-size: 19.96px; + line-height: 24px; + margin-top: 27px; + margin-bottom: 15px; +} + +.servicesText { + font-weight: 300; + font-size: 13.972px; + line-height: 17px; + max-width: 340px; +} + +.subscribe { + background: url(images/subscribe.jpg) no-repeat; + background-size: cover; + padding-top: 64px; + padding-bottom: 109px; + padding-left: 20px; + padding-right: 20px; +} + +@media (min-width: 1200px) { + .subscribe { + padding-top: 97px; + padding-bottom: 126px; + } + + .subscribe .container { + margin: 0 auto; + width: 1140px; + display: flex; + justify-content: space-between; + } +} + +.subscribeLeft { + display: flex; + flex-direction: column; + align-items: center; +} + +.subscribeUserText { + margin-top: 30px; + text-align: center; + font-size: 18px; + line-height: 22px; + color: #222224; + max-width: 330px; +} + +.subscribeRight { + display: flex; + flex-direction: column; + align-items: center; + margin-top: 65px; +} + +@media (min-width: 1200px) { + .subscribeRight { + margin-top: initial; + } +} + +.subscribeTitle { + font-weight: 700; + font-size: 24px; + color: #222224; +} + +.subscribeTitle, +.subscribeText { + max-width: 271px; + text-align: center; +} + +.subscribeText { + font-size: 14px; + color: #222224; + margin-bottom: 22px; +} + +.subscribeForm { + height: 47px; +} + +.subscribeForm input { + height: inherit; + background: #e1e1e1; + border: none; + padding: 6px 21px; + box-sizing: border-box; + border-top-left-radius: 28px; + border-bottom-left-radius: 28px; + float: left; + width: 185px; +} + +.subscribeForm input::-webkit-input-placeholder { + color: #222224; + font-family: inherit; + opacity: 0.67; +} +.subscribeForm input::-moz-placeholder { + color: #222224; + font-family: inherit; + opacity: 0.67; +} +.subscribeForm input:-ms-input-placeholder { + color: #222224; + font-family: inherit; + opacity: 0.67; +} +.subscribeForm input:-moz-placeholder { + color: #222224; + font-family: inherit; + opacity: 0.67; +} + +.subscribeForm button { + height: inherit; + border: none; + color: white; + font-family: inherit; + font-size: 14px; + line-height: 17px; + background: #f16d7f; + border-top-right-radius: 28px; + border-bottom-right-radius: 28px; + padding: 0 17px; +} + +.footer { + background: #222224; + padding: 43px 20px 10px; +} + +@media (min-width: 768px) { + .footer { + padding: 24px 32px; + } +} + +.footer .container { + display: flex; + flex-direction: column; + align-items: center; +} + +@media (min-width: 768px) { + .footer .container { + flex-direction: row; + justify-content: space-between; + } +} + +.footerLeft { + display: flex; +} + +.footer a { + color: black; + background: white; + width: 32px; + height: 32px; + display: flex; + justify-content: center; + align-items: center; + text-decoration: none; +} + +.footer a:hover { + background: #f16d7f; + color: white; +} + +.footer a:not(:last-child) { + margin-right: 7px; +} + +.footerRight { + color: white; +} + +@media (max-width: 767px) { + .footerRight { + margin-top: 40px; + } +} diff --git a/homework8/project_express/public/images/bars.png b/homework8/project_express/public/images/bars.png new file mode 100644 index 0000000000000000000000000000000000000000..c30c42923f406b65cb7ade89aceb87c25f2bf218 GIT binary patch literal 174 zcmeAS@N?(olHy`uVBq!ia0vp^3P3E*!3HF=SbZM?Db50q$YKTtZeb8+WSBKa0w~B> z9OUlAu3#WAFU@$EH7UIqmo=Zk#`ESeVV>M_rm z!bEK^Ouur-U)fl{Me0aZ?%^|aVxfna727f#PNFVdQ&MBb@022H!q5uE@ literal 0 HcmV?d00001 diff --git a/homework8/project_express/public/images/cart.png b/homework8/project_express/public/images/cart.png new file mode 100644 index 0000000000000000000000000000000000000000..3338b95ce534455535de64eeaee2f5eac89e72eb GIT binary patch literal 716 zcmV;-0yF)IP)B4CIB9KqlSh74wifFS}z2F}3Zh<^gOMfN6WHR}QrYBF)Z#J7><-#!dQA%}V#^1^_K=Cskk8L?-q6fu3 zP*^UPmg6{cxggZ3&e3RO*6Vej^5Jm!*lM-z<$^Fyb?TdYT8XY)7%FZ6&Ps>;1hdQ= zjfQnJbVAM#pTD2|9`W+sh&1Sdz{rqJsmSqiB6~U&o8j>osV~B^1%#3oXIJw#4E`NEOzCuIeL)g95CG5?Y0-~&!a>ib}f{)!Qen%kbq2%$%ueG zO_*aCb*eIu8ls4b8&+6&JHDeG>E}HcP=$3_n=r!oj7QUdA`^^n9(=SQq2`PO6yP3q z@Xw41M!y9AiA?NvyC)A8bA|8wuO%Z+RbaTtQTk6*Vzb$JK|K+I7cF{|fCq3M-6NXp y5|!ZNg$1lFhq}uJ6IYT0p*_4{50r}i@SHy*yBt(uWd+~>0000 + + + + diff --git a/homework8/project_express/public/images/chevronLeft.svg b/homework8/project_express/public/images/chevronLeft.svg new file mode 100644 index 0000000..17eff57 --- /dev/null +++ b/homework8/project_express/public/images/chevronLeft.svg @@ -0,0 +1,3 @@ + + + diff --git a/homework8/project_express/public/images/chevronRight.svg b/homework8/project_express/public/images/chevronRight.svg new file mode 100644 index 0000000..12ef11b --- /dev/null +++ b/homework8/project_express/public/images/chevronRight.svg @@ -0,0 +1,3 @@ + + + diff --git a/homework8/project_express/public/images/featured/1.jpg b/homework8/project_express/public/images/featured/1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..41eac02758a3de0eaa84fb4c686aa24034646e2a GIT binary patch literal 93945 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 K@zN}RM*kZhb92=I literal 0 HcmV?d00001 diff --git a/homework8/project_express/public/images/featured/3.jpg b/homework8/project_express/public/images/featured/3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8d118db207bda4ff043f39d3e24491bc9e84d281 GIT binary patch literal 80895 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

fQP(ceh$Mw9gw{dxK%H7HF&3utN|RDXJ`JW$fO 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�D*KZIp|)r>gn_M;n7a2IB=H1aFFzH(B@G6An8g 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 HzkmM+ns)C` literal 0 HcmV?d00001 diff --git a/homework8/project_express/public/images/featured/4.jpg b/homework8/project_express/public/images/featured/4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bf61659db62c801a5132c7a68577fcbeff1250db GIT binary patch literal 51885 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 literal 0 HcmV?d00001 diff --git a/homework8/project_express/public/images/featured/5.jpg b/homework8/project_express/public/images/featured/5.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1ffe51d7964693a5a28b8f58eacff87a0c927ac7 GIT binary patch literal 93122 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

&z`PHd+%<1 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 literal 0 HcmV?d00001 diff --git a/homework8/project_express/public/images/filter.svg b/homework8/project_express/public/images/filter.svg new file mode 100644 index 0000000..a125181 --- /dev/null +++ b/homework8/project_express/public/images/filter.svg @@ -0,0 +1,3 @@ + + + diff --git a/homework8/project_express/public/images/filterArrow.svg b/homework8/project_express/public/images/filterArrow.svg new file mode 100644 index 0000000..ee46233 --- /dev/null +++ b/homework8/project_express/public/images/filterArrow.svg @@ -0,0 +1,3 @@ + + + diff --git a/homework8/project_express/public/images/filterHover.svg b/homework8/project_express/public/images/filterHover.svg new file mode 100644 index 0000000..e9328d3 --- /dev/null +++ b/homework8/project_express/public/images/filterHover.svg @@ -0,0 +1,3 @@ + + + diff --git a/homework8/project_express/public/images/logo.png b/homework8/project_express/public/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7da5adc3662959b00234fec9a72f64f2c3d2744d GIT binary patch literal 2364 zcmV-C3B&e@P)JIK~#7F#aL@> zRL2!QGxy&0u6Mm&V+`iu1REC{T%|xjN}7tGQb0fk4>K0zT^o@|7#$zp49SKTn}1j zH?g*M*hU9YCzKa8m1ap|0pxU$mgXVydC5w1lcj0*V$pxaqF*J`*pvRnoVME{EZ-`f zWeRh%Ah8azXJQLGDAvku01`W_H#p zlbc7we*Y6``S~|(Qw^OPVt$XG;E?9WdXJyImqviHPp!J1`04k_s;nhxT5;`ZJf_Wr z!wne}e>ji#1)!jql;#D#}xk9`rS{yRvH*HLkjg$XAGhayl5&otQ^kf~T zh%PisKf7D%>?93Nc!O+n7~*X(Xjy~5A-E{QicCY>EIjj)&96*_!8bHz9t-DRVJ`iv zp1i!~5eX}p$KTzL`1+K6CG?x<_4>a=>zhw9HijDGj`a@aJ<7Os-V<#vW4m{o@%2d- z+_N`VJMn48&t-U6^b~m*F~`^=xsNMu9wd(1C#f$FgO;f{=TH06eaCkmy+{+pl%H%2Qf5X~ESV&tr54k& z*NVy+F~XY3)G6rz33fhER{irpS*^`maYFbLI9*CQL!a$3r{fAu5@gXlNrrBV@3IHS z=p=-g2x3A^lx)1j?&k3)I#wHm0}^Auc8*B^irykEewu0g+2J z+2ktucQe= zUb^H!I$uv6od%h9>r-?W22-B*bF7TAnyZcd<&Os5eWVkP0com z7-)GtB)w_z!*^mWDpEAHWawSpzYbSkTR?XJ_{s|GbV*DzO>l?a-hq>jQcjA|CL-Mp zNfU>+Ft0qlaPB7LuH~q}egzqIal$wmx>L!THpM;w9&O!fCtlZBXfb)L{c7cM8V7=9 zRcjHrj*?+y@f){@H8j&;r&9{yZue=I%e*jZrt=o$miY?upGI-H8l!fR(zpfNnl+us zhkij%6n4Dr4_RKyMAjX=5om#uz(&S>((m6b(-imJn;(!Zw9WH1AUYD21mH9=VI z9ufynPb+0>)^v@lHoyc~mSh`AGuH7l=kuwyAzlV007ubhXOmd^B@$k@T2KJmc^k3) z4C<5$&Uq&;Pkiw9d1zma5%=S9s~uuWiyvGhSy5xtE(sjwJ+3S6Idi|v)~pQPQ85!L zZj#e?>3h9%giBt19%P;y_5oVaJT79nIb_YrA>m2IQFl5ZW=FQ7b}EY9(K@^E?;C@xAr9MMw5&{$^N;T#Bo*1NAX&CTZ1@j zLLhq+q>s3FKK0RPT_>Gz0-Y}$$cYMZ56brkad5d0P5Fo@X|a1PMo0jxP73QBY3!8L i_-Ec7TPkix?tcMCFrbQ8BLJ-c0000o63BCC^(V**q_kNoJm10qNj{4)Q914#=wjs31cHKm|YrF%@7cus8YL#H;))5_3+F z7*DX3*bZmLwrt(&Pxnf?lER=M2<%Fw(zPt>Zyd)?qRZcGHm}WQ^I7DO%!1TvwJS7x zfY=8A5dF7}M&m&gfz4*K_IA5{Ler5_Mu^}M&*#-@<-4vMjmKk$eYh_1{UQN92Q)ky zMi86^j0V8F^?H3nK$bJXNO2$b-D81Yj+4nGz!jr?BXWrL^uzUbl*4p7y)OdNg6}{9 zds#M8jg0dXpc&TdbypOSO6e}L#bV*6rQg~SrQD5%D@zm<=L-IhoNsKGcAAZ)o@cya z<@ut7;P3IN7R)#O;ti2;BvGr?Dg{FtwZD_vuSR0yibP52We@1@w0<2KLAEFrpt2EFixit$gB5Yo3RU&xf72}4x6dS8ixVhZt}j(YVnVVGD? z891g2U=pIb7N5oYA*()G3FH5&*+)UX5IKZWca5kn(F`$P#}$UrXw*~nE#?mn+4J1P z!1~%}I2?9O_A(8~V?(`$s)TvT)Tlbh==Tp-<1v$ZQmevzk7nn~5POkZ1W$Vp;Bg9& zKH9fUz*JZQ+7X{8@|pUPhVq9mDq@e{nbK;tIxqo^u)I11JSprD&=MyW56$Ird5$Kl z2yDSa5 + + diff --git a/homework8/project_express/public/images/services/delivery.svg b/homework8/project_express/public/images/services/delivery.svg new file mode 100644 index 0000000..266b21f --- /dev/null +++ b/homework8/project_express/public/images/services/delivery.svg @@ -0,0 +1,3 @@ + + + diff --git a/homework8/project_express/public/images/services/discount.svg b/homework8/project_express/public/images/services/discount.svg new file mode 100644 index 0000000..eabc2d6 --- /dev/null +++ b/homework8/project_express/public/images/services/discount.svg @@ -0,0 +1,3 @@ + + + diff --git a/homework8/project_express/public/images/subscribe.jpg b/homework8/project_express/public/images/subscribe.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3bb987099bfc27281270a66adb31f891df73a555 GIT binary patch literal 131033 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 R-u3_h002ovPDHLkV1oW%wbTFr literal 0 HcmV?d00001 diff --git a/homework8/project_express/public/images/user.png b/homework8/project_express/public/images/user.png new file mode 100644 index 0000000000000000000000000000000000000000..c8e4879a3ed4fd13f5f63371bf9445ac4773333f GIT binary patch literal 718 zcmV;<0x|uGP)j+>Y@DjmlBd|9Dl!3`Wx=?&Bk}v$K0Kcc5 zabeXWX^{1*rdkp`{hR&_mKb0*n>m(c-C{Y%xz``_#S}v$>;liLyBUtSUk?> z^COhIl5U(!KCH160R;7xAU_X36)FRrG``gEGHFOv2r~h`d$n&Mmw;z^Nw~DPVHmzY z$CKu%qv*4kA?Dw1x1YsSDMEBjijYmj0Q>zuAVv9f#8j!SKM0A$0Jd$%Mpi17w`X}I z1NC}66a&D>%sNdAZ|vc2x4RJoz(XCO-(sp%pCxEV44`uXbYiR&@D%Nd8G4ERX2{!N zG{~2ywo?=7q{DpA)5z5%;=U&-0^P{j_|NgsAUzn;_%t$0X0zGcflN5M*!ZW@>8FHI zPOVlO^LO&CR;zDWGOgFFhLAoUKVmTxqxE{-tyZfK2;Y|z*5GuAGo&;Sdw<}S-y#)e zFFDx%QMz0%Z^1a!f)pkg*f-iM5Dx1PN-)pSL(6-DV2|&J#xG^;U*oVwkntc%;4B8} zOhO1Ba>_^nz=7+N!A`k@R~7QiiYiM&jYwa~XMTvK?m)a5@SfAnbFsQaF$Mv{E=aU1 zW^Z5pHY!6QLAf~h5px9zd1u4RxNYIXPbm?|>^PC&anE9`@f`3(+18AwMS>AV?H2?qr07*qoM6N<$g6=jx AzW@LL literal 0 HcmV?d00001 diff --git a/homework8/project_express/public/index.html b/homework8/project_express/public/index.html new file mode 100644 index 0000000..eab3963 --- /dev/null +++ b/homework8/project_express/public/index.html @@ -0,0 +1,250 @@ + + + + + + + Document + + + + + + +

+
+
+
+ + +
+ +
+ + + +
+ +
+
+ +
+ +
+
+ +
+
+ TRENDING NOW + +
+
+
+ SIZE + +
+ +
+
+ PRICE + +
+
+
+
+ + + +
+
+ +
+ +
+ Free Delivery +
+
+ Worldwide delivery on all. Authorit tively morph next-generation innov tion with extensive + models. +
+
+ +
+ +
+ Sales & discounts +
+
+ Worldwide delivery on all. Authorit tively morph next-generation innov tion with extensive + models. +
+
+ +
+ +
+ Quality assurance +
+
+ Worldwide delivery on all. Authorit tively morph next-generation innov tion with extensive + models. +
+
+
+
+ + + + +
+ + + + + + + \ No newline at end of file diff --git a/homework8/project_express/public/js/main.js b/homework8/project_express/public/js/main.js new file mode 100644 index 0000000..c01c575 --- /dev/null +++ b/homework8/project_express/public/js/main.js @@ -0,0 +1,62 @@ +const API = + "https://raw.githubusercontent.com/GeekBrainsTutorial/online-store-api/master/responses"; + +const app = new Vue({ + el: "#app", + data: { + userSearch: "", + }, + methods: { + getJson(url) { + return fetch(url) + .then((result) => result.json()) + .catch((error) => { + // console.log(error) + this.$refs.error.text = error; + }); + }, + postJson(url, data) { + return fetch(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }) + .then((result) => result.json()) + .catch((error) => { + // console.log(error) + this.$refs.error.text = error; + }); + }, + putJson(url, data) { + return fetch(url, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }) + .then((result) => result.json()) + .catch((error) => { + // console.log(error) + this.$refs.error.text = error; + }); + }, + deleteJson(url, data) { + return fetch(url, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(data), + }) + .then((result) => result.json()) + .catch((error) => { + // console.log(error) + this.$refs.error.text = error; + }); + }, + }, + mounted() {}, +}); diff --git a/homework8/project_express/public/js/mycartComponent.js b/homework8/project_express/public/js/mycartComponent.js new file mode 100644 index 0000000..ad38184 --- /dev/null +++ b/homework8/project_express/public/js/mycartComponent.js @@ -0,0 +1,91 @@ +Vue.component("cart", { + data() { + return { + cartUrl: "/getBasket.json", + cartItems: [], + showCart: false, + totalQuantity: 0, + }; + }, + mounted() { + this.$parent.getJson(`/api/cart`).then((data) => { + for (let item of data.contents) { + this.$data.cartItems.push(item); + this.$data.totalQuantity += item.quantity; + } + }); + }, + methods: { + addProduct(item) { + let find = this.cartItems.find((el) => el.id_product === item.id_product); + if (find) { + this.$parent + .putJson(`/api/cart/${find.id_product}`, { quantity: 1 }) + .then((data) => { + if (data.result === 1) { + find.quantity++; + this.$data.totalQuantity++; + } + }); + } else { + const prod = Object.assign({ quantity: 1 }, item); + this.$parent.postJson(`/api/cart`, prod).then((data) => { + if (data.result === 1) { + this.cartItems.push(prod); + this.$data.totalQuantity++; + } + }); + } + }, + remove(item) { + let find = this.cartItems.find((el) => el.id_product === item.id_product); + if (find) { + this.$parent + .deleteJson(`/api/cart/deleteProduct/${find.id_product}`, { + quantity: 1, + }) + .then((data) => { + if (data.result === 1) { + if (find.quantity > 1) { + find.quantity--; + this.$data.totalQuantity--; + } else { + this.cartItems.splice(this.cartItems.indexOf(item), 1); + this.$data.totalQuantity--; + } + } + }); + } + }, + }, + template: ` + + + {{totalQuantity}} +
+ + +
+
+ `, +}); + +Vue.component("cart-item", { + props: ["cartItem"], + template: ` +
+
+ Some img +
+
{{ cartItem.product_name }}
+
Quantity: {{ cartItem.quantity }}
+
$ {{ cartItem.price }} each
+
+
+
+
{{cartItem.quantity*cartItem.price}}
+ +
+
+ `, +}); diff --git a/homework8/project_express/public/js/myproductComponent.js b/homework8/project_express/public/js/myproductComponent.js new file mode 100644 index 0000000..b80436e --- /dev/null +++ b/homework8/project_express/public/js/myproductComponent.js @@ -0,0 +1,55 @@ +Vue.component("products", { + data() { + return { + products: [], + }; + }, + mounted() { + this.$parent.getJson(`/api/products`).then((data) => { + for (let item of data) { + this.$data.products.push(item); + } + }); + }, + template: ` +
+ +
+ `, +}); +Vue.component("product", { + props: ["product"], + template: ` +
+
+ +
+ +
+
+ +
+
+ {{product.product_name}} +
+
+ Known for her sculptural takes on traditional + tailoring, Australian arbiter of cool Kym + Ellery + teams + up with Moda Operandi. +
+
+ {{product.price}} +
+
+
+ `, +}); diff --git a/homework8/project_express/server/cart.js b/homework8/project_express/server/cart.js new file mode 100644 index 0000000..7eae2ae --- /dev/null +++ b/homework8/project_express/server/cart.js @@ -0,0 +1,24 @@ +let add = (cart, req) => { + cart.contents.push(req.body); + return JSON.stringify(cart, null, 4); +}; +let change = (cart, req) => { + let find = cart.contents.find((el) => el.id_product === +req.params.id); + find.quantity += req.body.quantity; + return JSON.stringify(cart, null, 4); +}; + +let deleteProduct = (cart, req) => { + let find = cart.contents.find((el) => el.id_product === +req.params.id); + find.quantity -= req.body.quantity; + if (!find.quantity) { + cart.contents.splice(cart.contents.indexOf(find), 1); + } + return JSON.stringify(cart, null, 4); +}; + +module.exports = { + add, + change, + deleteProduct, +}; diff --git a/homework8/project_express/server/cartRouter.js b/homework8/project_express/server/cartRouter.js new file mode 100644 index 0000000..948a631 --- /dev/null +++ b/homework8/project_express/server/cartRouter.js @@ -0,0 +1,25 @@ +const express = require("express"); +const fs = require("fs"); +const router = express.Router(); +const handler = require("./handler"); + +router.get("/", (req, res) => { + fs.readFile("server/db/userCart.json", "utf-8", (err, data) => { + if (err) { + res.sendStatus(404, JSON.stringify({ result: 0, text: err })); + } else { + res.send(data); + } + }); +}); +router.post("/", (req, res) => { + handler(req, res, "add", "server/db/userCart.json"); +}); +router.put("/:id", (req, res) => { + handler(req, res, "change", "server/db/userCart.json"); +}); +router.delete("/deleteProduct/:id", (req, res) => { + handler(req, res, "deleteProduct", "server/db/userCart.json"); +}); + +module.exports = router; diff --git a/homework8/project_express/server/db/products.json b/homework8/project_express/server/db/products.json new file mode 100644 index 0000000..ea7331b --- /dev/null +++ b/homework8/project_express/server/db/products.json @@ -0,0 +1,38 @@ +[ + { + "id_product": 4546, + "product_name": "ELLERY X M'O CAPSULE5", + "price": 10020, + "img":"images/featured/1.jpg" + }, + { + "id_product": 4156, + "product_name": "ELLERY X M'O CAPSULE5", + "price": 10400, + "img":"images/featured/2.jpg" + }, + { + "id_product": 45446, + "product_name": "ELLERY X M'O CAPSULE5", + "price": 10600, + "img":"images/featured/3.jpg" + }, + { + "id_product": 356, + "product_name": "ELLERY X M'O CAPSULE5", + "price": 1000, + "img":"images/featured/4.jpg" + }, + { + "id_product": 656, + "product_name": "ELLERY X M'O CAPSULE5", + "price": 100110, + "img":"images/featured/5.jpg" + }, + { + "id_product": 456, + "product_name": "ELLERY X M'O CAPSULE5", + "price": 109900, + "img":"images/featured/6.jpg" + } +] \ No newline at end of file diff --git a/homework8/project_express/server/db/userCart.json b/homework8/project_express/server/db/userCart.json new file mode 100644 index 0000000..adc4281 --- /dev/null +++ b/homework8/project_express/server/db/userCart.json @@ -0,0 +1,20 @@ +{ + "amount": 46600, + "countGoods": 2, + "contents": [ + { + "quantity": 3, + "id_product": 4156, + "product_name": "ELLERY X M'O CAPSULE5", + "price": 10400, + "img": "images/featured/2.jpg" + }, + { + "quantity": 1, + "id_product": 45446, + "product_name": "ELLERY X M'O CAPSULE5", + "price": 10600, + "img": "images/featured/3.jpg" + } + ] +} \ No newline at end of file diff --git a/homework8/project_express/server/handler.js b/homework8/project_express/server/handler.js new file mode 100644 index 0000000..9dfa22f --- /dev/null +++ b/homework8/project_express/server/handler.js @@ -0,0 +1,27 @@ +const cart = require("./cart"); +const fs = require("fs"); + +const actions = { + add: cart.add, + change: cart.change, + deleteProduct: cart.deleteProduct, +}; +//HANDLER отвечает за изменение данных в самом файле +let handler = (req, res, action, file) => { + fs.readFile(file, "utf-8", (err, data) => { + if (err) { + res.sendStatus(404, JSON.stringify({ result: 0, text: err })); + } else { + let newCart = actions[action](JSON.parse(data), req); + fs.writeFile(file, newCart, (err) => { + if (err) { + res.sendStatus(404, JSON.stringify({ result: 0, text: err })); + } else { + res.send(JSON.stringify({ result: 1 })); + } + }); + } + }); +}; + +module.exports = handler; diff --git a/homework8/project_express/server/server.js b/homework8/project_express/server/server.js new file mode 100644 index 0000000..08a53c4 --- /dev/null +++ b/homework8/project_express/server/server.js @@ -0,0 +1,32 @@ +const express = require('express'); +const fs = require('fs'); +const app = express(); +const cart = require('./cartRouter');//обработчик всех запросов корзины + +app.use(express.json()); +app.use('/', express.static('public')); +app.use('/api/cart', cart); + + +// app.get(); +// app.post(); +// app.put(); +// app.delete(); + +app.get('/api/products', (req, res) => { + fs.readFile('server/db/products.json', 'utf-8', (err, data) => { + if(err){ + res.sendStatus(404, JSON.stringify({result:0, text: err})); + } else { + res.send(data); + } + }) +}); + +// app.get('/api/cart/:id', (req, res) => { +// // res.send(req.params.id); +// res.send(req.query); +// }); + +const port = process.env.PORT || 3000; +app.listen(port, () => console.log(`Listen on port ${port}...`)); \ No newline at end of file

7uMtU}4M=7W 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

7uMtU}4M=7W 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