From f2f9c490eff797fb15bc1c37c2fdcebe376b7939 Mon Sep 17 00:00:00 2001 From: Dletta Date: Thu, 10 Jan 2019 22:40:51 -0800 Subject: [PATCH] nearley and cgif.ne. Not sure how to use it yet --- Wumpus/wumpus.html | 7 + nearlygram/CGIF.ne | 3 + nearlygram/cgif.js | 21 + node_modules/.bin/nearley-railroad | 1 + node_modules/.bin/nearley-test | 1 + node_modules/.bin/nearley-unparse | 1 + node_modules/.bin/nearleyc | 1 + node_modules/.bin/semver | 1 + node_modules/commander/CHANGELOG.md | 396 +++++ node_modules/commander/LICENSE | 22 + node_modules/commander/Readme.md | 417 +++++ node_modules/commander/index.js | 1227 +++++++++++++++ node_modules/commander/package.json | 70 + node_modules/commander/typings/index.d.ts | 309 ++++ node_modules/discontinuous-range/.npmignore | 28 + node_modules/discontinuous-range/.travis.yml | 4 + node_modules/discontinuous-range/LICENSE | 21 + node_modules/discontinuous-range/README.md | 23 + node_modules/discontinuous-range/index.js | 144 ++ node_modules/discontinuous-range/package.json | 55 + .../discontinuous-range/test/main-test.js | 96 ++ node_modules/moo/LICENSE | 29 + node_modules/moo/README.md | 361 +++++ node_modules/moo/moo.js | 462 ++++++ node_modules/moo/package.json | 68 + node_modules/nearley/LICENSE.txt | 21 + node_modules/nearley/README.md | 65 + node_modules/nearley/bin/nearley-railroad.js | 121 ++ node_modules/nearley/bin/nearley-test.js | 61 + node_modules/nearley/bin/nearley-unparse.js | 26 + node_modules/nearley/bin/nearleyc.js | 38 + node_modules/nearley/builtin/cow.ne | 2 + node_modules/nearley/builtin/number.ne | 51 + .../nearley/builtin/postprocessors.ne | 36 + node_modules/nearley/builtin/string.ne | 26 + node_modules/nearley/builtin/whitespace.ne | 5 + node_modules/nearley/lib/compile.js | 307 ++++ node_modules/nearley/lib/generate.js | 226 +++ node_modules/nearley/lib/lint.js | 29 + .../lib/nearley-language-bootstrapped.js | 155 ++ .../lib/nearley-language-bootstrapped.ne | 126 ++ node_modules/nearley/lib/nearley.js | 390 +++++ node_modules/nearley/lib/stream.js | 18 + node_modules/nearley/lib/unparse.js | 139 ++ node_modules/nearley/package.json | 92 ++ node_modules/railroad-diagrams/.gitattributes | 22 + node_modules/railroad-diagrams/.npmignore | 163 ++ node_modules/railroad-diagrams/README.md | 86 ++ .../railroad-diagrams/css-example.py-js | 183 +++ node_modules/railroad-diagrams/example.html | 141 ++ node_modules/railroad-diagrams/generator.html | 59 + node_modules/railroad-diagrams/package.json | 50 + .../railroad-diagrams/railroad-diagrams.css | 23 + .../railroad-diagrams/railroad-diagrams.js | 524 +++++++ .../railroad-diagrams/railroad_diagrams.py | 427 ++++++ node_modules/randexp/LICENSE | 19 + node_modules/randexp/README.md | 134 ++ node_modules/randexp/lib/randexp.js | 245 +++ node_modules/randexp/package.json | 79 + node_modules/ret/LICENSE | 19 + node_modules/ret/README.md | 183 +++ node_modules/ret/lib/index.js | 282 ++++ node_modules/ret/lib/positions.js | 17 + node_modules/ret/lib/sets.js | 82 + node_modules/ret/lib/types.js | 10 + node_modules/ret/lib/util.js | 111 ++ node_modules/ret/package.json | 67 + node_modules/semver/LICENSE | 15 + node_modules/semver/README.md | 399 +++++ node_modules/semver/bin/semver | 153 ++ node_modules/semver/package.json | 54 + node_modules/semver/range.bnf | 16 + node_modules/semver/semver.js | 1352 +++++++++++++++++ package-lock.json | 59 + package.json | 30 + 75 files changed, 10706 insertions(+) create mode 100644 nearlygram/CGIF.ne create mode 100644 nearlygram/cgif.js create mode 120000 node_modules/.bin/nearley-railroad create mode 120000 node_modules/.bin/nearley-test create mode 120000 node_modules/.bin/nearley-unparse create mode 120000 node_modules/.bin/nearleyc create mode 120000 node_modules/.bin/semver create mode 100644 node_modules/commander/CHANGELOG.md create mode 100644 node_modules/commander/LICENSE create mode 100644 node_modules/commander/Readme.md create mode 100644 node_modules/commander/index.js create mode 100644 node_modules/commander/package.json create mode 100644 node_modules/commander/typings/index.d.ts create mode 100644 node_modules/discontinuous-range/.npmignore create mode 100644 node_modules/discontinuous-range/.travis.yml create mode 100644 node_modules/discontinuous-range/LICENSE create mode 100644 node_modules/discontinuous-range/README.md create mode 100644 node_modules/discontinuous-range/index.js create mode 100644 node_modules/discontinuous-range/package.json create mode 100644 node_modules/discontinuous-range/test/main-test.js create mode 100644 node_modules/moo/LICENSE create mode 100644 node_modules/moo/README.md create mode 100644 node_modules/moo/moo.js create mode 100644 node_modules/moo/package.json create mode 100644 node_modules/nearley/LICENSE.txt create mode 100644 node_modules/nearley/README.md create mode 100755 node_modules/nearley/bin/nearley-railroad.js create mode 100755 node_modules/nearley/bin/nearley-test.js create mode 100755 node_modules/nearley/bin/nearley-unparse.js create mode 100755 node_modules/nearley/bin/nearleyc.js create mode 100644 node_modules/nearley/builtin/cow.ne create mode 100644 node_modules/nearley/builtin/number.ne create mode 100644 node_modules/nearley/builtin/postprocessors.ne create mode 100644 node_modules/nearley/builtin/string.ne create mode 100644 node_modules/nearley/builtin/whitespace.ne create mode 100644 node_modules/nearley/lib/compile.js create mode 100644 node_modules/nearley/lib/generate.js create mode 100644 node_modules/nearley/lib/lint.js create mode 100644 node_modules/nearley/lib/nearley-language-bootstrapped.js create mode 100644 node_modules/nearley/lib/nearley-language-bootstrapped.ne create mode 100644 node_modules/nearley/lib/nearley.js create mode 100644 node_modules/nearley/lib/stream.js create mode 100644 node_modules/nearley/lib/unparse.js create mode 100644 node_modules/nearley/package.json create mode 100644 node_modules/railroad-diagrams/.gitattributes create mode 100644 node_modules/railroad-diagrams/.npmignore create mode 100644 node_modules/railroad-diagrams/README.md create mode 100644 node_modules/railroad-diagrams/css-example.py-js create mode 100644 node_modules/railroad-diagrams/example.html create mode 100644 node_modules/railroad-diagrams/generator.html create mode 100644 node_modules/railroad-diagrams/package.json create mode 100644 node_modules/railroad-diagrams/railroad-diagrams.css create mode 100644 node_modules/railroad-diagrams/railroad-diagrams.js create mode 100644 node_modules/railroad-diagrams/railroad_diagrams.py create mode 100644 node_modules/randexp/LICENSE create mode 100644 node_modules/randexp/README.md create mode 100644 node_modules/randexp/lib/randexp.js create mode 100644 node_modules/randexp/package.json create mode 100644 node_modules/ret/LICENSE create mode 100644 node_modules/ret/README.md create mode 100644 node_modules/ret/lib/index.js create mode 100644 node_modules/ret/lib/positions.js create mode 100644 node_modules/ret/lib/sets.js create mode 100644 node_modules/ret/lib/types.js create mode 100644 node_modules/ret/lib/util.js create mode 100644 node_modules/ret/package.json create mode 100644 node_modules/semver/LICENSE create mode 100644 node_modules/semver/README.md create mode 100755 node_modules/semver/bin/semver create mode 100644 node_modules/semver/package.json create mode 100644 node_modules/semver/range.bnf create mode 100644 node_modules/semver/semver.js create mode 100644 package-lock.json create mode 100644 package.json diff --git a/Wumpus/wumpus.html b/Wumpus/wumpus.html index 2605085..64a35b3 100644 --- a/Wumpus/wumpus.html +++ b/Wumpus/wumpus.html @@ -12,6 +12,7 @@ var gun = new Gun(); + @@ -19,8 +20,10 @@ + diff --git a/nearlygram/CGIF.ne b/nearlygram/CGIF.ne new file mode 100644 index 0000000..f2e079e --- /dev/null +++ b/nearlygram/CGIF.ne @@ -0,0 +1,3 @@ +Concept -> "[" Type "]" +Type -> String +String -> [a-zA-Z]:+ diff --git a/nearlygram/cgif.js b/nearlygram/cgif.js new file mode 100644 index 0000000..41ee07e --- /dev/null +++ b/nearlygram/cgif.js @@ -0,0 +1,21 @@ +// Generated automatically by nearley, version 2.16.0 +// http://github.com/Hardmath123/nearley +(function () { +function id(x) { return x[0]; } +var grammar = { + Lexer: undefined, + ParserRules: [ + {"name": "Concept", "symbols": [{"literal":"["}, "Type", {"literal":"]"}]}, + {"name": "Type", "symbols": ["String"]}, + {"name": "String$ebnf$1", "symbols": [/[a-zA-Z]/]}, + {"name": "String$ebnf$1", "symbols": ["String$ebnf$1", /[a-zA-Z]/], "postprocess": function arrpush(d) {return d[0].concat([d[1]]);}}, + {"name": "String", "symbols": ["String$ebnf$1"]} +] + , ParserStart: "Concept" +} +if (typeof module !== 'undefined'&& typeof module.exports !== 'undefined') { + module.exports = grammar; +} else { + window.grammar = grammar; +} +})(); diff --git a/node_modules/.bin/nearley-railroad b/node_modules/.bin/nearley-railroad new file mode 120000 index 0000000..ad2a755 --- /dev/null +++ b/node_modules/.bin/nearley-railroad @@ -0,0 +1 @@ +../nearley/bin/nearley-railroad.js \ No newline at end of file diff --git a/node_modules/.bin/nearley-test b/node_modules/.bin/nearley-test new file mode 120000 index 0000000..cdf56ab --- /dev/null +++ b/node_modules/.bin/nearley-test @@ -0,0 +1 @@ +../nearley/bin/nearley-test.js \ No newline at end of file diff --git a/node_modules/.bin/nearley-unparse b/node_modules/.bin/nearley-unparse new file mode 120000 index 0000000..e01f9d3 --- /dev/null +++ b/node_modules/.bin/nearley-unparse @@ -0,0 +1 @@ +../nearley/bin/nearley-unparse.js \ No newline at end of file diff --git a/node_modules/.bin/nearleyc b/node_modules/.bin/nearleyc new file mode 120000 index 0000000..a3a4324 --- /dev/null +++ b/node_modules/.bin/nearleyc @@ -0,0 +1 @@ +../nearley/bin/nearleyc.js \ No newline at end of file diff --git a/node_modules/.bin/semver b/node_modules/.bin/semver new file mode 120000 index 0000000..317eb29 --- /dev/null +++ b/node_modules/.bin/semver @@ -0,0 +1 @@ +../semver/bin/semver \ No newline at end of file diff --git a/node_modules/commander/CHANGELOG.md b/node_modules/commander/CHANGELOG.md new file mode 100644 index 0000000..fd4f69c --- /dev/null +++ b/node_modules/commander/CHANGELOG.md @@ -0,0 +1,396 @@ + +2.19.0 / 2018-10-02 +================== + + * Removed newline after Options and Commands headers (#864) + * Bugfix - Error output (#862) + * Fix to change default value to string (#856) + +2.18.0 / 2018-09-07 +================== + + * Standardize help output (#853) + * chmod 644 travis.yml (#851) + * add support for execute typescript subcommand via ts-node (#849) + +2.17.1 / 2018-08-07 +================== + + * Fix bug in command emit (#844) + +2.17.0 / 2018-08-03 +================== + + * fixed newline output after help information (#833) + * Fix to emit the action even without command (#778) + * npm update (#823) + +2.16.0 / 2018-06-29 +================== + + * Remove Makefile and `test/run` (#821) + * Make 'npm test' run on Windows (#820) + * Add badge to display install size (#807) + * chore: cache node_modules (#814) + * chore: remove Node.js 4 (EOL), add Node.js 10 (#813) + * fixed typo in readme (#812) + * Fix types (#804) + * Update eslint to resolve vulnerabilities in lodash (#799) + * updated readme with custom event listeners. (#791) + * fix tests (#794) + +2.15.0 / 2018-03-07 +================== + + * Update downloads badge to point to graph of downloads over time instead of duplicating link to npm + * Arguments description + +2.14.1 / 2018-02-07 +================== + + * Fix typing of help function + +2.14.0 / 2018-02-05 +================== + + * only register the option:version event once + * Fixes issue #727: Passing empty string for option on command is set to undefined + * enable eqeqeq rule + * resolves #754 add linter configuration to project + * resolves #560 respect custom name for version option + * document how to override the version flag + * document using options per command + +2.13.0 / 2018-01-09 +================== + + * Do not print default for --no- + * remove trailing spaces in command help + * Update CI's Node.js to LTS and latest version + * typedefs: Command and Option types added to commander namespace + +2.12.2 / 2017-11-28 +================== + + * fix: typings are not shipped + +2.12.1 / 2017-11-23 +================== + + * Move @types/node to dev dependency + +2.12.0 / 2017-11-22 +================== + + * add attributeName() method to Option objects + * Documentation updated for options with --no prefix + * typings: `outputHelp` takes a string as the first parameter + * typings: use overloads + * feat(typings): update to match js api + * Print default value in option help + * Fix translation error + * Fail when using same command and alias (#491) + * feat(typings): add help callback + * fix bug when description is add after command with options (#662) + * Format js code + * Rename History.md to CHANGELOG.md (#668) + * feat(typings): add typings to support TypeScript (#646) + * use current node + +2.11.0 / 2017-07-03 +================== + + * Fix help section order and padding (#652) + * feature: support for signals to subcommands (#632) + * Fixed #37, --help should not display first (#447) + * Fix translation errors. (#570) + * Add package-lock.json + * Remove engines + * Upgrade package version + * Prefix events to prevent conflicts between commands and options (#494) + * Removing dependency on graceful-readlink + * Support setting name in #name function and make it chainable + * Add .vscode directory to .gitignore (Visual Studio Code metadata) + * Updated link to ruby commander in readme files + +2.10.0 / 2017-06-19 +================== + + * Update .travis.yml. drop support for older node.js versions. + * Fix require arguments in README.md + * On SemVer you do not start from 0.0.1 + * Add missing semi colon in readme + * Add save param to npm install + * node v6 travis test + * Update Readme_zh-CN.md + * Allow literal '--' to be passed-through as an argument + * Test subcommand alias help + * link build badge to master branch + * Support the alias of Git style sub-command + * added keyword commander for better search result on npm + * Fix Sub-Subcommands + * test node.js stable + * Fixes TypeError when a command has an option called `--description` + * Update README.md to make it beginner friendly and elaborate on the difference between angled and square brackets. + * Add chinese Readme file + +2.9.0 / 2015-10-13 +================== + + * Add option `isDefault` to set default subcommand #415 @Qix- + * Add callback to allow filtering or post-processing of help text #434 @djulien + * Fix `undefined` text in help information close #414 #416 @zhiyelee + +2.8.1 / 2015-04-22 +================== + + * Back out `support multiline description` Close #396 #397 + +2.8.0 / 2015-04-07 +================== + + * Add `process.execArg` support, execution args like `--harmony` will be passed to sub-commands #387 @DigitalIO @zhiyelee + * Fix bug in Git-style sub-commands #372 @zhiyelee + * Allow commands to be hidden from help #383 @tonylukasavage + * When git-style sub-commands are in use, yet none are called, display help #382 @claylo + * Add ability to specify arguments syntax for top-level command #258 @rrthomas + * Support multiline descriptions #208 @zxqfox + +2.7.1 / 2015-03-11 +================== + + * Revert #347 (fix collisions when option and first arg have same name) which causes a bug in #367. + +2.7.0 / 2015-03-09 +================== + + * Fix git-style bug when installed globally. Close #335 #349 @zhiyelee + * Fix collisions when option and first arg have same name. Close #346 #347 @tonylukasavage + * Add support for camelCase on `opts()`. Close #353 @nkzawa + * Add node.js 0.12 and io.js to travis.yml + * Allow RegEx options. #337 @palanik + * Fixes exit code when sub-command failing. Close #260 #332 @pirelenito + * git-style `bin` files in $PATH make sense. Close #196 #327 @zhiyelee + +2.6.0 / 2014-12-30 +================== + + * added `Command#allowUnknownOption` method. Close #138 #318 @doozr @zhiyelee + * Add application description to the help msg. Close #112 @dalssoft + +2.5.1 / 2014-12-15 +================== + + * fixed two bugs incurred by variadic arguments. Close #291 @Quentin01 #302 @zhiyelee + +2.5.0 / 2014-10-24 +================== + + * add support for variadic arguments. Closes #277 @whitlockjc + +2.4.0 / 2014-10-17 +================== + + * fixed a bug on executing the coercion function of subcommands option. Closes #270 + * added `Command.prototype.name` to retrieve command name. Closes #264 #266 @tonylukasavage + * added `Command.prototype.opts` to retrieve all the options as a simple object of key-value pairs. Closes #262 @tonylukasavage + * fixed a bug on subcommand name. Closes #248 @jonathandelgado + * fixed function normalize doesn’t honor option terminator. Closes #216 @abbr + +2.3.0 / 2014-07-16 +================== + + * add command alias'. Closes PR #210 + * fix: Typos. Closes #99 + * fix: Unused fs module. Closes #217 + +2.2.0 / 2014-03-29 +================== + + * add passing of previous option value + * fix: support subcommands on windows. Closes #142 + * Now the defaultValue passed as the second argument of the coercion function. + +2.1.0 / 2013-11-21 +================== + + * add: allow cflag style option params, unit test, fixes #174 + +2.0.0 / 2013-07-18 +================== + + * remove input methods (.prompt, .confirm, etc) + +1.3.2 / 2013-07-18 +================== + + * add support for sub-commands to co-exist with the original command + +1.3.1 / 2013-07-18 +================== + + * add quick .runningCommand hack so you can opt-out of other logic when running a sub command + +1.3.0 / 2013-07-09 +================== + + * add EACCES error handling + * fix sub-command --help + +1.2.0 / 2013-06-13 +================== + + * allow "-" hyphen as an option argument + * support for RegExp coercion + +1.1.1 / 2012-11-20 +================== + + * add more sub-command padding + * fix .usage() when args are present. Closes #106 + +1.1.0 / 2012-11-16 +================== + + * add git-style executable subcommand support. Closes #94 + +1.0.5 / 2012-10-09 +================== + + * fix `--name` clobbering. Closes #92 + * fix examples/help. Closes #89 + +1.0.4 / 2012-09-03 +================== + + * add `outputHelp()` method. + +1.0.3 / 2012-08-30 +================== + + * remove invalid .version() defaulting + +1.0.2 / 2012-08-24 +================== + + * add `--foo=bar` support [arv] + * fix password on node 0.8.8. Make backward compatible with 0.6 [focusaurus] + +1.0.1 / 2012-08-03 +================== + + * fix issue #56 + * fix tty.setRawMode(mode) was moved to tty.ReadStream#setRawMode() (i.e. process.stdin.setRawMode()) + +1.0.0 / 2012-07-05 +================== + + * add support for optional option descriptions + * add defaulting of `.version()` to package.json's version + +0.6.1 / 2012-06-01 +================== + + * Added: append (yes or no) on confirmation + * Added: allow node.js v0.7.x + +0.6.0 / 2012-04-10 +================== + + * Added `.prompt(obj, callback)` support. Closes #49 + * Added default support to .choose(). Closes #41 + * Fixed the choice example + +0.5.1 / 2011-12-20 +================== + + * Fixed `password()` for recent nodes. Closes #36 + +0.5.0 / 2011-12-04 +================== + + * Added sub-command option support [itay] + +0.4.3 / 2011-12-04 +================== + + * Fixed custom help ordering. Closes #32 + +0.4.2 / 2011-11-24 +================== + + * Added travis support + * Fixed: line-buffered input automatically trimmed. Closes #31 + +0.4.1 / 2011-11-18 +================== + + * Removed listening for "close" on --help + +0.4.0 / 2011-11-15 +================== + + * Added support for `--`. Closes #24 + +0.3.3 / 2011-11-14 +================== + + * Fixed: wait for close event when writing help info [Jerry Hamlet] + +0.3.2 / 2011-11-01 +================== + + * Fixed long flag definitions with values [felixge] + +0.3.1 / 2011-10-31 +================== + + * Changed `--version` short flag to `-V` from `-v` + * Changed `.version()` so it's configurable [felixge] + +0.3.0 / 2011-10-31 +================== + + * Added support for long flags only. Closes #18 + +0.2.1 / 2011-10-24 +================== + + * "node": ">= 0.4.x < 0.7.0". Closes #20 + +0.2.0 / 2011-09-26 +================== + + * Allow for defaults that are not just boolean. Default peassignment only occurs for --no-*, optional, and required arguments. [Jim Isaacs] + +0.1.0 / 2011-08-24 +================== + + * Added support for custom `--help` output + +0.0.5 / 2011-08-18 +================== + + * Changed: when the user enters nothing prompt for password again + * Fixed issue with passwords beginning with numbers [NuckChorris] + +0.0.4 / 2011-08-15 +================== + + * Fixed `Commander#args` + +0.0.3 / 2011-08-15 +================== + + * Added default option value support + +0.0.2 / 2011-08-15 +================== + + * Added mask support to `Command#password(str[, mask], fn)` + * Added `Command#password(str, fn)` + +0.0.1 / 2010-01-03 +================== + + * Initial release diff --git a/node_modules/commander/LICENSE b/node_modules/commander/LICENSE new file mode 100644 index 0000000..10f997a --- /dev/null +++ b/node_modules/commander/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2011 TJ Holowaychuk + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/node_modules/commander/Readme.md b/node_modules/commander/Readme.md new file mode 100644 index 0000000..a2a1547 --- /dev/null +++ b/node_modules/commander/Readme.md @@ -0,0 +1,417 @@ +# Commander.js + + +[![Build Status](https://api.travis-ci.org/tj/commander.js.svg?branch=master)](http://travis-ci.org/tj/commander.js) +[![NPM Version](http://img.shields.io/npm/v/commander.svg?style=flat)](https://www.npmjs.org/package/commander) +[![NPM Downloads](https://img.shields.io/npm/dm/commander.svg?style=flat)](https://npmcharts.com/compare/commander?minimal=true) +[![Install Size](https://packagephobia.now.sh/badge?p=commander)](https://packagephobia.now.sh/result?p=commander) +[![Join the chat at https://gitter.im/tj/commander.js](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/tj/commander.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + + The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/commander-rb/commander). + [API documentation](http://tj.github.com/commander.js/) + + +## Installation + + $ npm install commander --save + +## Option parsing + +Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('commander'); + +program + .version('0.1.0') + .option('-p, --peppers', 'Add peppers') + .option('-P, --pineapple', 'Add pineapple') + .option('-b, --bbq-sauce', 'Add bbq sauce') + .option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble') + .parse(process.argv); + +console.log('you ordered a pizza with:'); +if (program.peppers) console.log(' - peppers'); +if (program.pineapple) console.log(' - pineapple'); +if (program.bbqSauce) console.log(' - bbq'); +console.log(' - %s cheese', program.cheese); +``` + +Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as "--template-engine" are camel-cased, becoming `program.templateEngine` etc. + +Note that multi-word options starting with `--no` prefix negate the boolean value of the following word. For example, `--no-sauce` sets the value of `program.sauce` to false. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('commander'); + +program + .option('--no-sauce', 'Remove sauce') + .parse(process.argv); + +console.log('you ordered a pizza'); +if (program.sauce) console.log(' with sauce'); +else console.log(' without sauce'); +``` + +## Version option + +Calling the `version` implicitly adds the `-V` and `--version` options to the command. +When either of these options is present, the command prints the version number and exits. + + $ ./examples/pizza -V + 0.0.1 + +If you want your program to respond to the `-v` option instead of the `-V` option, simply pass custom flags to the `version` method using the same syntax as the `option` method. + +```js +program + .version('0.0.1', '-v, --version') +``` + +The version flags can be named anything, but the long option is required. + +## Command-specific options + +You can attach options to a command. + +```js +#!/usr/bin/env node + +var program = require('commander'); + +program + .command('rm ') + .option('-r, --recursive', 'Remove recursively') + .action(function (dir, cmd) { + console.log('remove ' + dir + (cmd.recursive ? ' recursively' : '')) + }) + +program.parse(process.argv) +``` + +A command's options are validated when the command is used. Any unknown options will be reported as an error. However, if an action-based command does not define an action, then the options are not validated. + +## Coercion + +```js +function range(val) { + return val.split('..').map(Number); +} + +function list(val) { + return val.split(','); +} + +function collect(val, memo) { + memo.push(val); + return memo; +} + +function increaseVerbosity(v, total) { + return total + 1; +} + +program + .version('0.1.0') + .usage('[options] ') + .option('-i, --integer ', 'An integer argument', parseInt) + .option('-f, --float ', 'A float argument', parseFloat) + .option('-r, --range ..', 'A range', range) + .option('-l, --list ', 'A list', list) + .option('-o, --optional [value]', 'An optional value') + .option('-c, --collect [value]', 'A repeatable value', collect, []) + .option('-v, --verbose', 'A value that can be increased', increaseVerbosity, 0) + .parse(process.argv); + +console.log(' int: %j', program.integer); +console.log(' float: %j', program.float); +console.log(' optional: %j', program.optional); +program.range = program.range || []; +console.log(' range: %j..%j', program.range[0], program.range[1]); +console.log(' list: %j', program.list); +console.log(' collect: %j', program.collect); +console.log(' verbosity: %j', program.verbose); +console.log(' args: %j', program.args); +``` + +## Regular Expression +```js +program + .version('0.1.0') + .option('-s --size ', 'Pizza size', /^(large|medium|small)$/i, 'medium') + .option('-d --drink [drink]', 'Drink', /^(coke|pepsi|izze)$/i) + .parse(process.argv); + +console.log(' size: %j', program.size); +console.log(' drink: %j', program.drink); +``` + +## Variadic arguments + + The last argument of a command can be variadic, and only the last argument. To make an argument variadic you have to + append `...` to the argument name. Here is an example: + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('commander'); + +program + .version('0.1.0') + .command('rmdir [otherDirs...]') + .action(function (dir, otherDirs) { + console.log('rmdir %s', dir); + if (otherDirs) { + otherDirs.forEach(function (oDir) { + console.log('rmdir %s', oDir); + }); + } + }); + +program.parse(process.argv); +``` + + An `Array` is used for the value of a variadic argument. This applies to `program.args` as well as the argument passed + to your action as demonstrated above. + +## Specify the argument syntax + +```js +#!/usr/bin/env node + +var program = require('commander'); + +program + .version('0.1.0') + .arguments(' [env]') + .action(function (cmd, env) { + cmdValue = cmd; + envValue = env; + }); + +program.parse(process.argv); + +if (typeof cmdValue === 'undefined') { + console.error('no command given!'); + process.exit(1); +} +console.log('command:', cmdValue); +console.log('environment:', envValue || "no environment given"); +``` +Angled brackets (e.g. ``) indicate required input. Square brackets (e.g. `[env]`) indicate optional input. + +## Git-style sub-commands + +```js +// file: ./examples/pm +var program = require('commander'); + +program + .version('0.1.0') + .command('install [name]', 'install one or more packages') + .command('search [query]', 'search with optional query') + .command('list', 'list packages installed', {isDefault: true}) + .parse(process.argv); +``` + +When `.command()` is invoked with a description argument, no `.action(callback)` should be called to handle sub-commands, otherwise there will be an error. This tells commander that you're going to use separate executables for sub-commands, much like `git(1)` and other popular tools. +The commander will try to search the executables in the directory of the entry script (like `./examples/pm`) with the name `program-command`, like `pm-install`, `pm-search`. + +Options can be passed with the call to `.command()`. Specifying `true` for `opts.noHelp` will remove the subcommand from the generated help output. Specifying `true` for `opts.isDefault` will run the subcommand if no other subcommand is specified. + +If the program is designed to be installed globally, make sure the executables have proper modes, like `755`. + +### `--harmony` + +You can enable `--harmony` option in two ways: +* Use `#! /usr/bin/env node --harmony` in the sub-commands scripts. Note some os version don’t support this pattern. +* Use the `--harmony` option when call the command, like `node --harmony examples/pm publish`. The `--harmony` option will be preserved when spawning sub-command process. + +## Automated --help + + The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free: + +``` +$ ./examples/pizza --help +Usage: pizza [options] + +An application for pizzas ordering + +Options: + -h, --help output usage information + -V, --version output the version number + -p, --peppers Add peppers + -P, --pineapple Add pineapple + -b, --bbq Add bbq sauce + -c, --cheese Add the specified type of cheese [marble] + -C, --no-cheese You do not want any cheese +``` + +## Custom help + + You can display arbitrary `-h, --help` information + by listening for "--help". Commander will automatically + exit once you are done so that the remainder of your program + does not execute causing undesired behaviors, for example + in the following executable "stuff" will not output when + `--help` is used. + +```js +#!/usr/bin/env node + +/** + * Module dependencies. + */ + +var program = require('commander'); + +program + .version('0.1.0') + .option('-f, --foo', 'enable some foo') + .option('-b, --bar', 'enable some bar') + .option('-B, --baz', 'enable some baz'); + +// must be before .parse() since +// node's emit() is immediate + +program.on('--help', function(){ + console.log('') + console.log('Examples:'); + console.log(' $ custom-help --help'); + console.log(' $ custom-help -h'); +}); + +program.parse(process.argv); + +console.log('stuff'); +``` + +Yields the following help output when `node script-name.js -h` or `node script-name.js --help` are run: + +``` +Usage: custom-help [options] + +Options: + -h, --help output usage information + -V, --version output the version number + -f, --foo enable some foo + -b, --bar enable some bar + -B, --baz enable some baz + +Examples: + $ custom-help --help + $ custom-help -h +``` + +## .outputHelp(cb) + +Output help information without exiting. +Optional callback cb allows post-processing of help text before it is displayed. + +If you want to display help by default (e.g. if no command was provided), you can use something like: + +```js +var program = require('commander'); +var colors = require('colors'); + +program + .version('0.1.0') + .command('getstream [url]', 'get stream URL') + .parse(process.argv); + +if (!process.argv.slice(2).length) { + program.outputHelp(make_red); +} + +function make_red(txt) { + return colors.red(txt); //display the help text in red on the console +} +``` + +## .help(cb) + + Output help information and exit immediately. + Optional callback cb allows post-processing of help text before it is displayed. + + +## Custom event listeners + You can execute custom actions by listening to command and option events. + +```js +program.on('option:verbose', function () { + process.env.VERBOSE = this.verbose; +}); + +// error on unknown commands +program.on('command:*', function () { + console.error('Invalid command: %s\nSee --help for a list of available commands.', program.args.join(' ')); + process.exit(1); +}); +``` + +## Examples + +```js +var program = require('commander'); + +program + .version('0.1.0') + .option('-C, --chdir ', 'change the working directory') + .option('-c, --config ', 'set config path. defaults to ./deploy.conf') + .option('-T, --no-tests', 'ignore test hook'); + +program + .command('setup [env]') + .description('run setup commands for all envs') + .option("-s, --setup_mode [mode]", "Which setup mode to use") + .action(function(env, options){ + var mode = options.setup_mode || "normal"; + env = env || 'all'; + console.log('setup for %s env(s) with %s mode', env, mode); + }); + +program + .command('exec ') + .alias('ex') + .description('execute the given remote cmd') + .option("-e, --exec_mode ", "Which exec mode to use") + .action(function(cmd, options){ + console.log('exec "%s" using %s mode', cmd, options.exec_mode); + }).on('--help', function() { + console.log(''); + console.log('Examples:'); + console.log(''); + console.log(' $ deploy exec sequential'); + console.log(' $ deploy exec async'); + }); + +program + .command('*') + .action(function(env){ + console.log('deploying "%s"', env); + }); + +program.parse(process.argv); +``` + +More Demos can be found in the [examples](https://github.com/tj/commander.js/tree/master/examples) directory. + +## License + +MIT diff --git a/node_modules/commander/index.js b/node_modules/commander/index.js new file mode 100644 index 0000000..bf039c9 --- /dev/null +++ b/node_modules/commander/index.js @@ -0,0 +1,1227 @@ +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter; +var spawn = require('child_process').spawn; +var path = require('path'); +var dirname = path.dirname; +var basename = path.basename; +var fs = require('fs'); + +/** + * Inherit `Command` from `EventEmitter.prototype`. + */ + +require('util').inherits(Command, EventEmitter); + +/** + * Expose the root command. + */ + +exports = module.exports = new Command(); + +/** + * Expose `Command`. + */ + +exports.Command = Command; + +/** + * Expose `Option`. + */ + +exports.Option = Option; + +/** + * Initialize a new `Option` with the given `flags` and `description`. + * + * @param {String} flags + * @param {String} description + * @api public + */ + +function Option(flags, description) { + this.flags = flags; + this.required = flags.indexOf('<') >= 0; + this.optional = flags.indexOf('[') >= 0; + this.bool = flags.indexOf('-no-') === -1; + flags = flags.split(/[ ,|]+/); + if (flags.length > 1 && !/^[[<]/.test(flags[1])) this.short = flags.shift(); + this.long = flags.shift(); + this.description = description || ''; +} + +/** + * Return option name. + * + * @return {String} + * @api private + */ + +Option.prototype.name = function() { + return this.long + .replace('--', '') + .replace('no-', ''); +}; + +/** + * Return option name, in a camelcase format that can be used + * as a object attribute key. + * + * @return {String} + * @api private + */ + +Option.prototype.attributeName = function() { + return camelcase(this.name()); +}; + +/** + * Check if `arg` matches the short or long flag. + * + * @param {String} arg + * @return {Boolean} + * @api private + */ + +Option.prototype.is = function(arg) { + return this.short === arg || this.long === arg; +}; + +/** + * Initialize a new `Command`. + * + * @param {String} name + * @api public + */ + +function Command(name) { + this.commands = []; + this.options = []; + this._execs = {}; + this._allowUnknownOption = false; + this._args = []; + this._name = name || ''; +} + +/** + * Add command `name`. + * + * The `.action()` callback is invoked when the + * command `name` is specified via __ARGV__, + * and the remaining arguments are applied to the + * function for access. + * + * When the `name` is "*" an un-matched command + * will be passed as the first arg, followed by + * the rest of __ARGV__ remaining. + * + * Examples: + * + * program + * .version('0.0.1') + * .option('-C, --chdir ', 'change the working directory') + * .option('-c, --config ', 'set config path. defaults to ./deploy.conf') + * .option('-T, --no-tests', 'ignore test hook') + * + * program + * .command('setup') + * .description('run remote setup commands') + * .action(function() { + * console.log('setup'); + * }); + * + * program + * .command('exec ') + * .description('run the given remote command') + * .action(function(cmd) { + * console.log('exec "%s"', cmd); + * }); + * + * program + * .command('teardown [otherDirs...]') + * .description('run teardown commands') + * .action(function(dir, otherDirs) { + * console.log('dir "%s"', dir); + * if (otherDirs) { + * otherDirs.forEach(function (oDir) { + * console.log('dir "%s"', oDir); + * }); + * } + * }); + * + * program + * .command('*') + * .description('deploy the given env') + * .action(function(env) { + * console.log('deploying "%s"', env); + * }); + * + * program.parse(process.argv); + * + * @param {String} name + * @param {String} [desc] for git-style sub-commands + * @return {Command} the new command + * @api public + */ + +Command.prototype.command = function(name, desc, opts) { + if (typeof desc === 'object' && desc !== null) { + opts = desc; + desc = null; + } + opts = opts || {}; + var args = name.split(/ +/); + var cmd = new Command(args.shift()); + + if (desc) { + cmd.description(desc); + this.executables = true; + this._execs[cmd._name] = true; + if (opts.isDefault) this.defaultExecutable = cmd._name; + } + cmd._noHelp = !!opts.noHelp; + this.commands.push(cmd); + cmd.parseExpectedArgs(args); + cmd.parent = this; + + if (desc) return this; + return cmd; +}; + +/** + * Define argument syntax for the top-level command. + * + * @api public + */ + +Command.prototype.arguments = function(desc) { + return this.parseExpectedArgs(desc.split(/ +/)); +}; + +/** + * Add an implicit `help [cmd]` subcommand + * which invokes `--help` for the given command. + * + * @api private + */ + +Command.prototype.addImplicitHelpCommand = function() { + this.command('help [cmd]', 'display help for [cmd]'); +}; + +/** + * Parse expected `args`. + * + * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`. + * + * @param {Array} args + * @return {Command} for chaining + * @api public + */ + +Command.prototype.parseExpectedArgs = function(args) { + if (!args.length) return; + var self = this; + args.forEach(function(arg) { + var argDetails = { + required: false, + name: '', + variadic: false + }; + + switch (arg[0]) { + case '<': + argDetails.required = true; + argDetails.name = arg.slice(1, -1); + break; + case '[': + argDetails.name = arg.slice(1, -1); + break; + } + + if (argDetails.name.length > 3 && argDetails.name.slice(-3) === '...') { + argDetails.variadic = true; + argDetails.name = argDetails.name.slice(0, -3); + } + if (argDetails.name) { + self._args.push(argDetails); + } + }); + return this; +}; + +/** + * Register callback `fn` for the command. + * + * Examples: + * + * program + * .command('help') + * .description('display verbose help') + * .action(function() { + * // output help here + * }); + * + * @param {Function} fn + * @return {Command} for chaining + * @api public + */ + +Command.prototype.action = function(fn) { + var self = this; + var listener = function(args, unknown) { + // Parse any so-far unknown options + args = args || []; + unknown = unknown || []; + + var parsed = self.parseOptions(unknown); + + // Output help if necessary + outputHelpIfNecessary(self, parsed.unknown); + + // If there are still any unknown options, then we simply + // die, unless someone asked for help, in which case we give it + // to them, and then we die. + if (parsed.unknown.length > 0) { + self.unknownOption(parsed.unknown[0]); + } + + // Leftover arguments need to be pushed back. Fixes issue #56 + if (parsed.args.length) args = parsed.args.concat(args); + + self._args.forEach(function(arg, i) { + if (arg.required && args[i] == null) { + self.missingArgument(arg.name); + } else if (arg.variadic) { + if (i !== self._args.length - 1) { + self.variadicArgNotLast(arg.name); + } + + args[i] = args.splice(i); + } + }); + + // Always append ourselves to the end of the arguments, + // to make sure we match the number of arguments the user + // expects + if (self._args.length) { + args[self._args.length] = self; + } else { + args.push(self); + } + + fn.apply(self, args); + }; + var parent = this.parent || this; + var name = parent === this ? '*' : this._name; + parent.on('command:' + name, listener); + if (this._alias) parent.on('command:' + this._alias, listener); + return this; +}; + +/** + * Define option with `flags`, `description` and optional + * coercion `fn`. + * + * The `flags` string should contain both the short and long flags, + * separated by comma, a pipe or space. The following are all valid + * all will output this way when `--help` is used. + * + * "-p, --pepper" + * "-p|--pepper" + * "-p --pepper" + * + * Examples: + * + * // simple boolean defaulting to false + * program.option('-p, --pepper', 'add pepper'); + * + * --pepper + * program.pepper + * // => Boolean + * + * // simple boolean defaulting to true + * program.option('-C, --no-cheese', 'remove cheese'); + * + * program.cheese + * // => true + * + * --no-cheese + * program.cheese + * // => false + * + * // required argument + * program.option('-C, --chdir ', 'change the working directory'); + * + * --chdir /tmp + * program.chdir + * // => "/tmp" + * + * // optional argument + * program.option('-c, --cheese [type]', 'add cheese [marble]'); + * + * @param {String} flags + * @param {String} description + * @param {Function|*} [fn] or default + * @param {*} [defaultValue] + * @return {Command} for chaining + * @api public + */ + +Command.prototype.option = function(flags, description, fn, defaultValue) { + var self = this, + option = new Option(flags, description), + oname = option.name(), + name = option.attributeName(); + + // default as 3rd arg + if (typeof fn !== 'function') { + if (fn instanceof RegExp) { + var regex = fn; + fn = function(val, def) { + var m = regex.exec(val); + return m ? m[0] : def; + }; + } else { + defaultValue = fn; + fn = null; + } + } + + // preassign default value only for --no-*, [optional], or + if (!option.bool || option.optional || option.required) { + // when --no-* we make sure default is true + if (!option.bool) defaultValue = true; + // preassign only if we have a default + if (defaultValue !== undefined) { + self[name] = defaultValue; + option.defaultValue = defaultValue; + } + } + + // register the option + this.options.push(option); + + // when it's passed assign the value + // and conditionally invoke the callback + this.on('option:' + oname, function(val) { + // coercion + if (val !== null && fn) { + val = fn(val, self[name] === undefined ? defaultValue : self[name]); + } + + // unassigned or bool + if (typeof self[name] === 'boolean' || typeof self[name] === 'undefined') { + // if no value, bool true, and we have a default, then use it! + if (val == null) { + self[name] = option.bool + ? defaultValue || true + : false; + } else { + self[name] = val; + } + } else if (val !== null) { + // reassign + self[name] = val; + } + }); + + return this; +}; + +/** + * Allow unknown options on the command line. + * + * @param {Boolean} arg if `true` or omitted, no error will be thrown + * for unknown options. + * @api public + */ +Command.prototype.allowUnknownOption = function(arg) { + this._allowUnknownOption = arguments.length === 0 || arg; + return this; +}; + +/** + * Parse `argv`, settings options and invoking commands when defined. + * + * @param {Array} argv + * @return {Command} for chaining + * @api public + */ + +Command.prototype.parse = function(argv) { + // implicit help + if (this.executables) this.addImplicitHelpCommand(); + + // store raw args + this.rawArgs = argv; + + // guess name + this._name = this._name || basename(argv[1], '.js'); + + // github-style sub-commands with no sub-command + if (this.executables && argv.length < 3 && !this.defaultExecutable) { + // this user needs help + argv.push('--help'); + } + + // process argv + var parsed = this.parseOptions(this.normalize(argv.slice(2))); + var args = this.args = parsed.args; + + var result = this.parseArgs(this.args, parsed.unknown); + + // executable sub-commands + var name = result.args[0]; + + var aliasCommand = null; + // check alias of sub commands + if (name) { + aliasCommand = this.commands.filter(function(command) { + return command.alias() === name; + })[0]; + } + + if (this._execs[name] && typeof this._execs[name] !== 'function') { + return this.executeSubCommand(argv, args, parsed.unknown); + } else if (aliasCommand) { + // is alias of a subCommand + args[0] = aliasCommand._name; + return this.executeSubCommand(argv, args, parsed.unknown); + } else if (this.defaultExecutable) { + // use the default subcommand + args.unshift(this.defaultExecutable); + return this.executeSubCommand(argv, args, parsed.unknown); + } + + return result; +}; + +/** + * Execute a sub-command executable. + * + * @param {Array} argv + * @param {Array} args + * @param {Array} unknown + * @api private + */ + +Command.prototype.executeSubCommand = function(argv, args, unknown) { + args = args.concat(unknown); + + if (!args.length) this.help(); + if (args[0] === 'help' && args.length === 1) this.help(); + + // --help + if (args[0] === 'help') { + args[0] = args[1]; + args[1] = '--help'; + } + + // executable + var f = argv[1]; + // name of the subcommand, link `pm-install` + var bin = basename(f, path.extname(f)) + '-' + args[0]; + + // In case of globally installed, get the base dir where executable + // subcommand file should be located at + var baseDir, + link = fs.lstatSync(f).isSymbolicLink() ? fs.readlinkSync(f) : f; + + // when symbolink is relative path + if (link !== f && link.charAt(0) !== '/') { + link = path.join(dirname(f), link); + } + baseDir = dirname(link); + + // prefer local `./` to bin in the $PATH + var localBin = path.join(baseDir, bin); + + // whether bin file is a js script with explicit `.js` or `.ts` extension + var isExplicitJS = false; + if (exists(localBin + '.js')) { + bin = localBin + '.js'; + isExplicitJS = true; + } else if (exists(localBin + '.ts')) { + bin = localBin + '.ts'; + isExplicitJS = true; + } else if (exists(localBin)) { + bin = localBin; + } + + args = args.slice(1); + + var proc; + if (process.platform !== 'win32') { + if (isExplicitJS) { + args.unshift(bin); + // add executable arguments to spawn + args = (process.execArgv || []).concat(args); + + proc = spawn(process.argv[0], args, { stdio: 'inherit', customFds: [0, 1, 2] }); + } else { + proc = spawn(bin, args, { stdio: 'inherit', customFds: [0, 1, 2] }); + } + } else { + args.unshift(bin); + proc = spawn(process.execPath, args, { stdio: 'inherit' }); + } + + var signals = ['SIGUSR1', 'SIGUSR2', 'SIGTERM', 'SIGINT', 'SIGHUP']; + signals.forEach(function(signal) { + process.on(signal, function() { + if (proc.killed === false && proc.exitCode === null) { + proc.kill(signal); + } + }); + }); + proc.on('close', process.exit.bind(process)); + proc.on('error', function(err) { + if (err.code === 'ENOENT') { + console.error('error: %s(1) does not exist, try --help', bin); + } else if (err.code === 'EACCES') { + console.error('error: %s(1) not executable. try chmod or run with root', bin); + } + process.exit(1); + }); + + // Store the reference to the child process + this.runningCommand = proc; +}; + +/** + * Normalize `args`, splitting joined short flags. For example + * the arg "-abc" is equivalent to "-a -b -c". + * This also normalizes equal sign and splits "--abc=def" into "--abc def". + * + * @param {Array} args + * @return {Array} + * @api private + */ + +Command.prototype.normalize = function(args) { + var ret = [], + arg, + lastOpt, + index; + + for (var i = 0, len = args.length; i < len; ++i) { + arg = args[i]; + if (i > 0) { + lastOpt = this.optionFor(args[i - 1]); + } + + if (arg === '--') { + // Honor option terminator + ret = ret.concat(args.slice(i)); + break; + } else if (lastOpt && lastOpt.required) { + ret.push(arg); + } else if (arg.length > 1 && arg[0] === '-' && arg[1] !== '-') { + arg.slice(1).split('').forEach(function(c) { + ret.push('-' + c); + }); + } else if (/^--/.test(arg) && ~(index = arg.indexOf('='))) { + ret.push(arg.slice(0, index), arg.slice(index + 1)); + } else { + ret.push(arg); + } + } + + return ret; +}; + +/** + * Parse command `args`. + * + * When listener(s) are available those + * callbacks are invoked, otherwise the "*" + * event is emitted and those actions are invoked. + * + * @param {Array} args + * @return {Command} for chaining + * @api private + */ + +Command.prototype.parseArgs = function(args, unknown) { + var name; + + if (args.length) { + name = args[0]; + if (this.listeners('command:' + name).length) { + this.emit('command:' + args.shift(), args, unknown); + } else { + this.emit('command:*', args); + } + } else { + outputHelpIfNecessary(this, unknown); + + // If there were no args and we have unknown options, + // then they are extraneous and we need to error. + if (unknown.length > 0) { + this.unknownOption(unknown[0]); + } + if (this.commands.length === 0 && + this._args.filter(function(a) { return a.required }).length === 0) { + this.emit('command:*'); + } + } + + return this; +}; + +/** + * Return an option matching `arg` if any. + * + * @param {String} arg + * @return {Option} + * @api private + */ + +Command.prototype.optionFor = function(arg) { + for (var i = 0, len = this.options.length; i < len; ++i) { + if (this.options[i].is(arg)) { + return this.options[i]; + } + } +}; + +/** + * Parse options from `argv` returning `argv` + * void of these options. + * + * @param {Array} argv + * @return {Array} + * @api public + */ + +Command.prototype.parseOptions = function(argv) { + var args = [], + len = argv.length, + literal, + option, + arg; + + var unknownOptions = []; + + // parse options + for (var i = 0; i < len; ++i) { + arg = argv[i]; + + // literal args after -- + if (literal) { + args.push(arg); + continue; + } + + if (arg === '--') { + literal = true; + continue; + } + + // find matching Option + option = this.optionFor(arg); + + // option is defined + if (option) { + // requires arg + if (option.required) { + arg = argv[++i]; + if (arg == null) return this.optionMissingArgument(option); + this.emit('option:' + option.name(), arg); + // optional arg + } else if (option.optional) { + arg = argv[i + 1]; + if (arg == null || (arg[0] === '-' && arg !== '-')) { + arg = null; + } else { + ++i; + } + this.emit('option:' + option.name(), arg); + // bool + } else { + this.emit('option:' + option.name()); + } + continue; + } + + // looks like an option + if (arg.length > 1 && arg[0] === '-') { + unknownOptions.push(arg); + + // If the next argument looks like it might be + // an argument for this option, we pass it on. + // If it isn't, then it'll simply be ignored + if ((i + 1) < argv.length && argv[i + 1][0] !== '-') { + unknownOptions.push(argv[++i]); + } + continue; + } + + // arg + args.push(arg); + } + + return { args: args, unknown: unknownOptions }; +}; + +/** + * Return an object containing options as key-value pairs + * + * @return {Object} + * @api public + */ +Command.prototype.opts = function() { + var result = {}, + len = this.options.length; + + for (var i = 0; i < len; i++) { + var key = this.options[i].attributeName(); + result[key] = key === this._versionOptionName ? this._version : this[key]; + } + return result; +}; + +/** + * Argument `name` is missing. + * + * @param {String} name + * @api private + */ + +Command.prototype.missingArgument = function(name) { + console.error("error: missing required argument `%s'", name); + process.exit(1); +}; + +/** + * `Option` is missing an argument, but received `flag` or nothing. + * + * @param {String} option + * @param {String} flag + * @api private + */ + +Command.prototype.optionMissingArgument = function(option, flag) { + if (flag) { + console.error("error: option `%s' argument missing, got `%s'", option.flags, flag); + } else { + console.error("error: option `%s' argument missing", option.flags); + } + process.exit(1); +}; + +/** + * Unknown option `flag`. + * + * @param {String} flag + * @api private + */ + +Command.prototype.unknownOption = function(flag) { + if (this._allowUnknownOption) return; + console.error("error: unknown option `%s'", flag); + process.exit(1); +}; + +/** + * Variadic argument with `name` is not the last argument as required. + * + * @param {String} name + * @api private + */ + +Command.prototype.variadicArgNotLast = function(name) { + console.error("error: variadic arguments must be last `%s'", name); + process.exit(1); +}; + +/** + * Set the program version to `str`. + * + * This method auto-registers the "-V, --version" flag + * which will print the version number when passed. + * + * @param {String} str + * @param {String} [flags] + * @return {Command} for chaining + * @api public + */ + +Command.prototype.version = function(str, flags) { + if (arguments.length === 0) return this._version; + this._version = str; + flags = flags || '-V, --version'; + var versionOption = new Option(flags, 'output the version number'); + this._versionOptionName = versionOption.long.substr(2) || 'version'; + this.options.push(versionOption); + this.on('option:' + this._versionOptionName, function() { + process.stdout.write(str + '\n'); + process.exit(0); + }); + return this; +}; + +/** + * Set the description to `str`. + * + * @param {String} str + * @param {Object} argsDescription + * @return {String|Command} + * @api public + */ + +Command.prototype.description = function(str, argsDescription) { + if (arguments.length === 0) return this._description; + this._description = str; + this._argsDescription = argsDescription; + return this; +}; + +/** + * Set an alias for the command + * + * @param {String} alias + * @return {String|Command} + * @api public + */ + +Command.prototype.alias = function(alias) { + var command = this; + if (this.commands.length !== 0) { + command = this.commands[this.commands.length - 1]; + } + + if (arguments.length === 0) return command._alias; + + if (alias === command._name) throw new Error('Command alias can\'t be the same as its name'); + + command._alias = alias; + return this; +}; + +/** + * Set / get the command usage `str`. + * + * @param {String} str + * @return {String|Command} + * @api public + */ + +Command.prototype.usage = function(str) { + var args = this._args.map(function(arg) { + return humanReadableArgName(arg); + }); + + var usage = '[options]' + + (this.commands.length ? ' [command]' : '') + + (this._args.length ? ' ' + args.join(' ') : ''); + + if (arguments.length === 0) return this._usage || usage; + this._usage = str; + + return this; +}; + +/** + * Get or set the name of the command + * + * @param {String} str + * @return {String|Command} + * @api public + */ + +Command.prototype.name = function(str) { + if (arguments.length === 0) return this._name; + this._name = str; + return this; +}; + +/** + * Return prepared commands. + * + * @return {Array} + * @api private + */ + +Command.prototype.prepareCommands = function() { + return this.commands.filter(function(cmd) { + return !cmd._noHelp; + }).map(function(cmd) { + var args = cmd._args.map(function(arg) { + return humanReadableArgName(arg); + }).join(' '); + + return [ + cmd._name + + (cmd._alias ? '|' + cmd._alias : '') + + (cmd.options.length ? ' [options]' : '') + + (args ? ' ' + args : ''), + cmd._description + ]; + }); +}; + +/** + * Return the largest command length. + * + * @return {Number} + * @api private + */ + +Command.prototype.largestCommandLength = function() { + var commands = this.prepareCommands(); + return commands.reduce(function(max, command) { + return Math.max(max, command[0].length); + }, 0); +}; + +/** + * Return the largest option length. + * + * @return {Number} + * @api private + */ + +Command.prototype.largestOptionLength = function() { + var options = [].slice.call(this.options); + options.push({ + flags: '-h, --help' + }); + return options.reduce(function(max, option) { + return Math.max(max, option.flags.length); + }, 0); +}; + +/** + * Return the largest arg length. + * + * @return {Number} + * @api private + */ + +Command.prototype.largestArgLength = function() { + return this._args.reduce(function(max, arg) { + return Math.max(max, arg.name.length); + }, 0); +}; + +/** + * Return the pad width. + * + * @return {Number} + * @api private + */ + +Command.prototype.padWidth = function() { + var width = this.largestOptionLength(); + if (this._argsDescription && this._args.length) { + if (this.largestArgLength() > width) { + width = this.largestArgLength(); + } + } + + if (this.commands && this.commands.length) { + if (this.largestCommandLength() > width) { + width = this.largestCommandLength(); + } + } + + return width; +}; + +/** + * Return help for options. + * + * @return {String} + * @api private + */ + +Command.prototype.optionHelp = function() { + var width = this.padWidth(); + + // Append the help information + return this.options.map(function(option) { + return pad(option.flags, width) + ' ' + option.description + + ((option.bool && option.defaultValue !== undefined) ? ' (default: ' + JSON.stringify(option.defaultValue) + ')' : ''); + }).concat([pad('-h, --help', width) + ' ' + 'output usage information']) + .join('\n'); +}; + +/** + * Return command help documentation. + * + * @return {String} + * @api private + */ + +Command.prototype.commandHelp = function() { + if (!this.commands.length) return ''; + + var commands = this.prepareCommands(); + var width = this.padWidth(); + + return [ + 'Commands:', + commands.map(function(cmd) { + var desc = cmd[1] ? ' ' + cmd[1] : ''; + return (desc ? pad(cmd[0], width) : cmd[0]) + desc; + }).join('\n').replace(/^/gm, ' '), + '' + ].join('\n'); +}; + +/** + * Return program help documentation. + * + * @return {String} + * @api private + */ + +Command.prototype.helpInformation = function() { + var desc = []; + if (this._description) { + desc = [ + this._description, + '' + ]; + + var argsDescription = this._argsDescription; + if (argsDescription && this._args.length) { + var width = this.padWidth(); + desc.push('Arguments:'); + desc.push(''); + this._args.forEach(function(arg) { + desc.push(' ' + pad(arg.name, width) + ' ' + argsDescription[arg.name]); + }); + desc.push(''); + } + } + + var cmdName = this._name; + if (this._alias) { + cmdName = cmdName + '|' + this._alias; + } + var usage = [ + 'Usage: ' + cmdName + ' ' + this.usage(), + '' + ]; + + var cmds = []; + var commandHelp = this.commandHelp(); + if (commandHelp) cmds = [commandHelp]; + + var options = [ + 'Options:', + '' + this.optionHelp().replace(/^/gm, ' '), + '' + ]; + + return usage + .concat(desc) + .concat(options) + .concat(cmds) + .join('\n'); +}; + +/** + * Output help information for this command + * + * @api public + */ + +Command.prototype.outputHelp = function(cb) { + if (!cb) { + cb = function(passthru) { + return passthru; + }; + } + process.stdout.write(cb(this.helpInformation())); + this.emit('--help'); +}; + +/** + * Output help information and exit. + * + * @api public + */ + +Command.prototype.help = function(cb) { + this.outputHelp(cb); + process.exit(); +}; + +/** + * Camel-case the given `flag` + * + * @param {String} flag + * @return {String} + * @api private + */ + +function camelcase(flag) { + return flag.split('-').reduce(function(str, word) { + return str + word[0].toUpperCase() + word.slice(1); + }); +} + +/** + * Pad `str` to `width`. + * + * @param {String} str + * @param {Number} width + * @return {String} + * @api private + */ + +function pad(str, width) { + var len = Math.max(0, width - str.length); + return str + Array(len + 1).join(' '); +} + +/** + * Output help information if necessary + * + * @param {Command} command to output help for + * @param {Array} array of options to search for -h or --help + * @api private + */ + +function outputHelpIfNecessary(cmd, options) { + options = options || []; + for (var i = 0; i < options.length; i++) { + if (options[i] === '--help' || options[i] === '-h') { + cmd.outputHelp(); + process.exit(0); + } + } +} + +/** + * Takes an argument an returns its human readable equivalent for help usage. + * + * @param {Object} arg + * @return {String} + * @api private + */ + +function humanReadableArgName(arg) { + var nameOutput = arg.name + (arg.variadic === true ? '...' : ''); + + return arg.required + ? '<' + nameOutput + '>' + : '[' + nameOutput + ']'; +} + +// for versions before node v0.8 when there weren't `fs.existsSync` +function exists(file) { + try { + if (fs.statSync(file).isFile()) { + return true; + } + } catch (e) { + return false; + } +} diff --git a/node_modules/commander/package.json b/node_modules/commander/package.json new file mode 100644 index 0000000..0f4b9c2 --- /dev/null +++ b/node_modules/commander/package.json @@ -0,0 +1,70 @@ +{ + "_from": "commander@^2.19.0", + "_id": "commander@2.19.0", + "_inBundle": false, + "_integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "_location": "/commander", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "commander@^2.19.0", + "name": "commander", + "escapedName": "commander", + "rawSpec": "^2.19.0", + "saveSpec": null, + "fetchSpec": "^2.19.0" + }, + "_requiredBy": [ + "/nearley" + ], + "_resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "_shasum": "f6198aa84e5b83c46054b94ddedbfed5ee9ff12a", + "_spec": "commander@^2.19.0", + "_where": "/Users/dletta/Documents/GitHub/conceptGraph/node_modules/nearley", + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca" + }, + "bugs": { + "url": "https://github.com/tj/commander.js/issues" + }, + "bundleDependencies": false, + "dependencies": {}, + "deprecated": false, + "description": "the complete solution for node.js command-line programs", + "devDependencies": { + "@types/node": "^10.11.3", + "eslint": "^5.6.1", + "should": "^13.2.3", + "sinon": "^6.3.4", + "standard": "^12.0.1", + "ts-node": "^7.0.1", + "typescript": "^2.9.2" + }, + "files": [ + "index.js", + "typings/index.d.ts" + ], + "homepage": "https://github.com/tj/commander.js#readme", + "keywords": [ + "commander", + "command", + "option", + "parser" + ], + "license": "MIT", + "main": "index", + "name": "commander", + "repository": { + "type": "git", + "url": "git+https://github.com/tj/commander.js.git" + }, + "scripts": { + "lint": "eslint index.js", + "test": "node test/run.js && npm run test-typings", + "test-typings": "tsc -p tsconfig.json" + }, + "typings": "typings/index.d.ts", + "version": "2.19.0" +} diff --git a/node_modules/commander/typings/index.d.ts b/node_modules/commander/typings/index.d.ts new file mode 100644 index 0000000..312b056 --- /dev/null +++ b/node_modules/commander/typings/index.d.ts @@ -0,0 +1,309 @@ +// Type definitions for commander 2.11 +// Project: https://github.com/visionmedia/commander.js +// Definitions by: Alan Agius , Marcelo Dezem , vvakame , Jules Randolph +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +declare namespace local { + + class Option { + flags: string; + required: boolean; + optional: boolean; + bool: boolean; + short?: string; + long: string; + description: string; + + /** + * Initialize a new `Option` with the given `flags` and `description`. + * + * @param {string} flags + * @param {string} [description] + */ + constructor(flags: string, description?: string); + } + + class Command extends NodeJS.EventEmitter { + [key: string]: any; + + args: string[]; + + /** + * Initialize a new `Command`. + * + * @param {string} [name] + */ + constructor(name?: string); + + /** + * Set the program version to `str`. + * + * This method auto-registers the "-V, --version" flag + * which will print the version number when passed. + * + * @param {string} str + * @param {string} [flags] + * @returns {Command} for chaining + */ + version(str: string, flags?: string): Command; + + /** + * Add command `name`. + * + * The `.action()` callback is invoked when the + * command `name` is specified via __ARGV__, + * and the remaining arguments are applied to the + * function for access. + * + * When the `name` is "*" an un-matched command + * will be passed as the first arg, followed by + * the rest of __ARGV__ remaining. + * + * @example + * program + * .version('0.0.1') + * .option('-C, --chdir ', 'change the working directory') + * .option('-c, --config ', 'set config path. defaults to ./deploy.conf') + * .option('-T, --no-tests', 'ignore test hook') + * + * program + * .command('setup') + * .description('run remote setup commands') + * .action(function() { + * console.log('setup'); + * }); + * + * program + * .command('exec ') + * .description('run the given remote command') + * .action(function(cmd) { + * console.log('exec "%s"', cmd); + * }); + * + * program + * .command('teardown [otherDirs...]') + * .description('run teardown commands') + * .action(function(dir, otherDirs) { + * console.log('dir "%s"', dir); + * if (otherDirs) { + * otherDirs.forEach(function (oDir) { + * console.log('dir "%s"', oDir); + * }); + * } + * }); + * + * program + * .command('*') + * .description('deploy the given env') + * .action(function(env) { + * console.log('deploying "%s"', env); + * }); + * + * program.parse(process.argv); + * + * @param {string} name + * @param {string} [desc] for git-style sub-commands + * @param {CommandOptions} [opts] command options + * @returns {Command} the new command + */ + command(name: string, desc?: string, opts?: commander.CommandOptions): Command; + + /** + * Define argument syntax for the top-level command. + * + * @param {string} desc + * @returns {Command} for chaining + */ + arguments(desc: string): Command; + + /** + * Parse expected `args`. + * + * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`. + * + * @param {string[]} args + * @returns {Command} for chaining + */ + parseExpectedArgs(args: string[]): Command; + + /** + * Register callback `fn` for the command. + * + * @example + * program + * .command('help') + * .description('display verbose help') + * .action(function() { + * // output help here + * }); + * + * @param {(...args: any[]) => void} fn + * @returns {Command} for chaining + */ + action(fn: (...args: any[]) => void): Command; + + /** + * Define option with `flags`, `description` and optional + * coercion `fn`. + * + * The `flags` string should contain both the short and long flags, + * separated by comma, a pipe or space. The following are all valid + * all will output this way when `--help` is used. + * + * "-p, --pepper" + * "-p|--pepper" + * "-p --pepper" + * + * @example + * // simple boolean defaulting to false + * program.option('-p, --pepper', 'add pepper'); + * + * --pepper + * program.pepper + * // => Boolean + * + * // simple boolean defaulting to true + * program.option('-C, --no-cheese', 'remove cheese'); + * + * program.cheese + * // => true + * + * --no-cheese + * program.cheese + * // => false + * + * // required argument + * program.option('-C, --chdir ', 'change the working directory'); + * + * --chdir /tmp + * program.chdir + * // => "/tmp" + * + * // optional argument + * program.option('-c, --cheese [type]', 'add cheese [marble]'); + * + * @param {string} flags + * @param {string} [description] + * @param {((arg1: any, arg2: any) => void) | RegExp} [fn] function or default + * @param {*} [defaultValue] + * @returns {Command} for chaining + */ + option(flags: string, description?: string, fn?: ((arg1: any, arg2: any) => void) | RegExp, defaultValue?: any): Command; + option(flags: string, description?: string, defaultValue?: any): Command; + + /** + * Allow unknown options on the command line. + * + * @param {boolean} [arg] if `true` or omitted, no error will be thrown for unknown options. + * @returns {Command} for chaining + */ + allowUnknownOption(arg?: boolean): Command; + + /** + * Parse `argv`, settings options and invoking commands when defined. + * + * @param {string[]} argv + * @returns {Command} for chaining + */ + parse(argv: string[]): Command; + + /** + * Parse options from `argv` returning `argv` void of these options. + * + * @param {string[]} argv + * @returns {ParseOptionsResult} + */ + parseOptions(argv: string[]): commander.ParseOptionsResult; + + /** + * Return an object containing options as key-value pairs + * + * @returns {{[key: string]: any}} + */ + opts(): { [key: string]: any }; + + /** + * Set the description to `str`. + * + * @param {string} str + * @return {(Command | string)} + */ + description(str: string): Command; + description(): string; + + /** + * Set an alias for the command. + * + * @param {string} alias + * @return {(Command | string)} + */ + alias(alias: string): Command; + alias(): string; + + /** + * Set or get the command usage. + * + * @param {string} str + * @return {(Command | string)} + */ + usage(str: string): Command; + usage(): string; + + /** + * Set the name of the command. + * + * @param {string} str + * @return {Command} + */ + name(str: string): Command; + + /** + * Get the name of the command. + * + * @return {string} + */ + name(): string; + + /** + * Output help information for this command. + * + * @param {(str: string) => string} [cb] + */ + outputHelp(cb?: (str: string) => string): void; + + /** Output help information and exit. + * + * @param {(str: string) => string} [cb] + */ + help(cb?: (str: string) => string): never; + } + +} + +declare namespace commander { + + type Command = local.Command + + type Option = local.Option + + interface CommandOptions { + noHelp?: boolean; + isDefault?: boolean; + } + + interface ParseOptionsResult { + args: string[]; + unknown: string[]; + } + + interface CommanderStatic extends Command { + Command: typeof local.Command; + Option: typeof local.Option; + CommandOptions: CommandOptions; + ParseOptionsResult: ParseOptionsResult; + } + +} + +declare const commander: commander.CommanderStatic; +export = commander; diff --git a/node_modules/discontinuous-range/.npmignore b/node_modules/discontinuous-range/.npmignore new file mode 100644 index 0000000..59d842b --- /dev/null +++ b/node_modules/discontinuous-range/.npmignore @@ -0,0 +1,28 @@ +# Logs +logs +*.log + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directory +# Commenting this out is preferred by some people, see +# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- +node_modules + +# Users Environment Variables +.lock-wscript diff --git a/node_modules/discontinuous-range/.travis.yml b/node_modules/discontinuous-range/.travis.yml new file mode 100644 index 0000000..18ae2d8 --- /dev/null +++ b/node_modules/discontinuous-range/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - "0.11" + - "0.10" diff --git a/node_modules/discontinuous-range/LICENSE b/node_modules/discontinuous-range/LICENSE new file mode 100644 index 0000000..afe05c7 --- /dev/null +++ b/node_modules/discontinuous-range/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 David Tudury + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/discontinuous-range/README.md b/node_modules/discontinuous-range/README.md new file mode 100644 index 0000000..543fb30 --- /dev/null +++ b/node_modules/discontinuous-range/README.md @@ -0,0 +1,23 @@ +discontinuous-range +=================== + +``` +DiscontinuousRange(1, 10).subtract(4, 6); // [ 1-3, 7-10 ] +``` + + [![Build Status](https://travis-ci.org/dtudury/discontinuous-range.png)](https://travis-ci.org/dtudury/discontinuous-range) + +this is a pretty simple module, but it exists to service another project +so this'll be pretty lacking documentation. +reading the test to see how this works may help. otherwise, here's an example +that I think pretty much sums it up + + +###Example +``` +var all_numbers = new DiscontinuousRange(1, 100); +var bad_numbers = DiscontinuousRange(13).add(8).add(60,80); +var good_numbers = all_numbers.clone().subtract(bad_numbers); +console.log(good_numbers.toString()); //[ 1-7, 9-12, 14-59, 81-100 ] +var random_good_number = good_numbers.index(Math.floor(Math.random() * good_numbers.length)); +``` diff --git a/node_modules/discontinuous-range/index.js b/node_modules/discontinuous-range/index.js new file mode 100644 index 0000000..7ac7749 --- /dev/null +++ b/node_modules/discontinuous-range/index.js @@ -0,0 +1,144 @@ +//protected helper class +function _SubRange(low, high) { + this.low = low; + this.high = high; + this.length = 1 + high - low; +} + +_SubRange.prototype.overlaps = function (range) { + return !(this.high < range.low || this.low > range.high); +}; + +_SubRange.prototype.touches = function (range) { + return !(this.high + 1 < range.low || this.low - 1 > range.high); +}; + +//returns inclusive combination of _SubRanges as a _SubRange +_SubRange.prototype.add = function (range) { + return this.touches(range) && new _SubRange(Math.min(this.low, range.low), Math.max(this.high, range.high)); +}; + +//returns subtraction of _SubRanges as an array of _SubRanges (there's a case where subtraction divides it in 2) +_SubRange.prototype.subtract = function (range) { + if (!this.overlaps(range)) return false; + if (range.low <= this.low && range.high >= this.high) return []; + if (range.low > this.low && range.high < this.high) return [new _SubRange(this.low, range.low - 1), new _SubRange(range.high + 1, this.high)]; + if (range.low <= this.low) return [new _SubRange(range.high + 1, this.high)]; + return [new _SubRange(this.low, range.low - 1)]; +}; + +_SubRange.prototype.toString = function () { + if (this.low == this.high) return this.low.toString(); + return this.low + '-' + this.high; +}; + +_SubRange.prototype.clone = function () { + return new _SubRange(this.low, this.high); +}; + + + + +function DiscontinuousRange(a, b) { + if (this instanceof DiscontinuousRange) { + this.ranges = []; + this.length = 0; + if (a !== undefined) this.add(a, b); + } else { + return new DiscontinuousRange(a, b); + } +} + +function _update_length(self) { + self.length = self.ranges.reduce(function (previous, range) {return previous + range.length}, 0); +} + +DiscontinuousRange.prototype.add = function (a, b) { + var self = this; + function _add(subrange) { + var new_ranges = []; + var i = 0; + while (i < self.ranges.length && !subrange.touches(self.ranges[i])) { + new_ranges.push(self.ranges[i].clone()); + i++; + } + while (i < self.ranges.length && subrange.touches(self.ranges[i])) { + subrange = subrange.add(self.ranges[i]); + i++; + } + new_ranges.push(subrange); + while (i < self.ranges.length) { + new_ranges.push(self.ranges[i].clone()); + i++; + } + self.ranges = new_ranges; + _update_length(self); + } + + if (a instanceof DiscontinuousRange) { + a.ranges.forEach(_add); + } else { + if (a instanceof _SubRange) { + _add(a); + } else { + if (b === undefined) b = a; + _add(new _SubRange(a, b)); + } + } + return this; +}; + +DiscontinuousRange.prototype.subtract = function (a, b) { + var self = this; + function _subtract(subrange) { + var new_ranges = []; + var i = 0; + while (i < self.ranges.length && !subrange.overlaps(self.ranges[i])) { + new_ranges.push(self.ranges[i].clone()); + i++; + } + while (i < self.ranges.length && subrange.overlaps(self.ranges[i])) { + new_ranges = new_ranges.concat(self.ranges[i].subtract(subrange)); + i++; + } + while (i < self.ranges.length) { + new_ranges.push(self.ranges[i].clone()); + i++; + } + self.ranges = new_ranges; + _update_length(self); + } + if (a instanceof DiscontinuousRange) { + a.ranges.forEach(_subtract); + } else { + if (a instanceof _SubRange) { + _subtract(a); + } else { + if (b === undefined) b = a; + _subtract(new _SubRange(a, b)); + } + } + return this; +}; + + +DiscontinuousRange.prototype.index = function (index) { + var i = 0; + while (i < this.ranges.length && this.ranges[i].length <= index) { + index -= this.ranges[i].length; + i++; + } + if (i >= this.ranges.length) return null; + return this.ranges[i].low + index; +}; + + +DiscontinuousRange.prototype.toString = function () { + return '[ ' + this.ranges.join(', ') + ' ]' +}; + +DiscontinuousRange.prototype.clone = function () { + return new DiscontinuousRange(this); +}; + +module.exports = DiscontinuousRange; diff --git a/node_modules/discontinuous-range/package.json b/node_modules/discontinuous-range/package.json new file mode 100644 index 0000000..001b5a3 --- /dev/null +++ b/node_modules/discontinuous-range/package.json @@ -0,0 +1,55 @@ +{ + "_from": "discontinuous-range@1.0.0", + "_id": "discontinuous-range@1.0.0", + "_inBundle": false, + "_integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=", + "_location": "/discontinuous-range", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "discontinuous-range@1.0.0", + "name": "discontinuous-range", + "escapedName": "discontinuous-range", + "rawSpec": "1.0.0", + "saveSpec": null, + "fetchSpec": "1.0.0" + }, + "_requiredBy": [ + "/randexp" + ], + "_resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "_shasum": "e38331f0844bba49b9a9cb71c771585aab1bc65a", + "_spec": "discontinuous-range@1.0.0", + "_where": "/Users/dletta/Documents/GitHub/conceptGraph/node_modules/randexp", + "author": { + "name": "David Tudury", + "email": "david.tudury@gmail.com" + }, + "bugs": { + "url": "https://github.com/dtudury/discontinuous-range/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "for adding, subtracting, and indexing discontinuous ranges of numbers", + "devDependencies": { + "mocha": "^1.21.4" + }, + "homepage": "https://github.com/dtudury/discontinuous-range", + "keywords": [ + "discontinuous", + "range", + "set" + ], + "license": "MIT", + "main": "index.js", + "name": "discontinuous-range", + "repository": { + "type": "git", + "url": "git+https://github.com/dtudury/discontinuous-range.git" + }, + "scripts": { + "test": "./node_modules/mocha/bin/mocha -R spec test/*-test.js" + }, + "version": "1.0.0" +} diff --git a/node_modules/discontinuous-range/test/main-test.js b/node_modules/discontinuous-range/test/main-test.js new file mode 100644 index 0000000..c4b394f --- /dev/null +++ b/node_modules/discontinuous-range/test/main-test.js @@ -0,0 +1,96 @@ +var assert = require('assert'); + +var DRange = require('../index.js'); + +describe('add sets', function() { + it('should allow adding numbers', function () { + var drange = DRange(5); + assert.equal('[ 5 ]', drange.toString()); + drange.add(6); + assert.equal('[ 5-6 ]', drange.toString()); + drange.add(8); + assert.equal('[ 5-6, 8 ]', drange.toString()); + drange.add(7); + assert.equal('[ 5-8 ]', drange.toString()); + assert.equal(drange.length, 4); + }); + it('should allow adding ranges of numbers', function () { + var drange = DRange(1,5); + assert.equal('[ 1-5 ]', drange.toString()); + drange.add(6,10); + assert.equal('[ 1-10 ]', drange.toString()); + drange.add(15,20); + assert.equal('[ 1-10, 15-20 ]', drange.toString()); + drange.add(0,14); + assert.equal('[ 0-20 ]', drange.toString()); + assert.equal(drange.length, 21); + }); + it('should allow adding another DiscontinuousRange', function () { + var drange = DRange(1,5); + drange.add(15,20); + var erange = DRange(6); + erange.add(17, 30); + drange.add(erange); + assert.equal('[ 1-6, 15-30 ]', drange.toString()); + assert.equal(drange.length, 22); + }); +}); + +describe('subtract sets', function() { + it('should allow subtracting numbers', function () { + var drange = DRange(1, 10); + drange.subtract(5); + assert.equal('[ 1-4, 6-10 ]', drange.toString()); + drange.subtract(7); + assert.equal('[ 1-4, 6, 8-10 ]', drange.toString()); + drange.subtract(6); + assert.equal('[ 1-4, 8-10 ]', drange.toString()); + assert.equal(drange.length, 7); + }); + it('should allow subtracting ranges of numbers', function () { + var drange = DRange(1, 100); + drange.subtract(5, 15); + assert.equal('[ 1-4, 16-100 ]', drange.toString()); + drange.subtract(90, 200); + assert.equal('[ 1-4, 16-89 ]', drange.toString()); + assert.equal(drange.length, 78); + }); + it('should allow subtracting another DiscontinuousRange', function () { + var drange = DRange(0,100); + var erange = DRange(6); + erange.add(17, 30); + drange.subtract(erange); + assert.equal('[ 0-5, 7-16, 31-100 ]', drange.toString()); + assert.equal(drange.length, 86); + }); +}); + + +describe('index sets', function() { + it('should appropriately retrieve numbers in range by index', function () { + var drange = DRange(0, 9); + drange.add(20, 29); + drange.add(40, 49); + assert.equal(drange.index(5), 5); + assert.equal(drange.index(15), 25); + assert.equal(drange.index(25), 45); + assert.equal(drange.length, 30); + }); +}); + +describe('clone sets', function() { + it('should be able to clone a DiscontinuousRange that doesn\'t affect the original', function () { + var drange = DRange(0, 9); + var erange = drange.clone(); + erange.subtract(5); + assert.equal('[ 0-9 ]', drange.toString()); + assert.equal('[ 0-4, 6-9 ]', erange.toString()); + }); +}); + +var all_numbers = new DRange(1, 100); +var bad_numbers = DRange(13).add(8).add(60,80); +var good_numbers = all_numbers.clone().subtract(bad_numbers); +console.log(good_numbers.toString()); +var random_good_number = good_numbers.index(Math.floor(Math.random() * good_numbers.length)); +console.log(random_good_number); diff --git a/node_modules/moo/LICENSE b/node_modules/moo/LICENSE new file mode 100644 index 0000000..3810d82 --- /dev/null +++ b/node_modules/moo/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2017, Tim Radvan (tjvr) +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 copyright holder 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 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/node_modules/moo/README.md b/node_modules/moo/README.md new file mode 100644 index 0000000..e2a4eb1 --- /dev/null +++ b/node_modules/moo/README.md @@ -0,0 +1,361 @@ +![](cow.png) + +Moo! +==== + +Moo is a highly-optimised tokenizer/lexer generator. Use it to tokenize your strings, before parsing 'em with a parser like [nearley](https://github.com/hardmath123/nearley) or whatever else you're into. + +* [Fast](#is-it-fast) +* [Convenient](#usage) +* uses [Regular Expressions](#on-regular-expressions) +* tracks [Line Numbers](#line-numbers) +* handles [Keywords](#keywords) +* supports [States](#states) +* custom [Errors](#errors) +* is even [Iterable](#iteration) +* has no dependencies +* <3KB gzipped +* Moo! + +Is it fast? +----------- + +Yup! Flying-cows-and-singed-steak fast. + +Moo is the fastest JS tokenizer around. It's **~2–10x** faster than most other tokenizers; it's a **couple orders of magnitude** faster than some of the slower ones. + +Define your tokens **using regular expressions**. Moo will compile 'em down to a **single RegExp for performance**. It uses the new ES6 **sticky flag** where possible to make things faster; otherwise it falls back to an almost-as-efficient workaround. (For more than you ever wanted to know about this, read [adventures in the land of substrings and RegExps](http://mrale.ph/blog/2016/11/23/making-less-dart-faster.html).) + +You _might_ be able to go faster still by writing your lexer by hand rather than using RegExps, but that's icky. + +Oh, and it [avoids parsing RegExps by itself](https://hackernoon.com/the-madness-of-parsing-real-world-javascript-regexps-d9ee336df983#.2l8qu3l76). Because that would be horrible. + + +Usage +----- + +First, you need to do the needful: `$ npm install moo`, or whatever will ship this code to your computer. Alternatively, grab the `moo.js` file by itself and slap it into your web page via a ` + +

IDENT

+
+ +
+

FUNCTION

+ +

AT-KEYWORD

+ +

HASH

+ +

STRING

+ +

URL

+ +

NUMBER

+ +

DIMENSION

+ +

PERCENTAGE

+ +

UNICODE-RANGE

+ +

COMMENT

+ +

CDO

+ +

CDC

+ diff --git a/node_modules/railroad-diagrams/generator.html b/node_modules/railroad-diagrams/generator.html new file mode 100644 index 0000000..2e85f09 --- /dev/null +++ b/node_modules/railroad-diagrams/generator.html @@ -0,0 +1,59 @@ + +Railroad Diagram Generator + + + +
+ + + + \ No newline at end of file diff --git a/node_modules/railroad-diagrams/package.json b/node_modules/railroad-diagrams/package.json new file mode 100644 index 0000000..6d6361d --- /dev/null +++ b/node_modules/railroad-diagrams/package.json @@ -0,0 +1,50 @@ +{ + "_from": "railroad-diagrams@^1.0.0", + "_id": "railroad-diagrams@1.0.0", + "_inBundle": false, + "_integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=", + "_location": "/railroad-diagrams", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "railroad-diagrams@^1.0.0", + "name": "railroad-diagrams", + "escapedName": "railroad-diagrams", + "rawSpec": "^1.0.0", + "saveSpec": null, + "fetchSpec": "^1.0.0" + }, + "_requiredBy": [ + "/nearley" + ], + "_resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "_shasum": "eb7e6267548ddedfb899c1b90e57374559cddb7e", + "_spec": "railroad-diagrams@^1.0.0", + "_where": "/Users/dletta/Documents/GitHub/conceptGraph/node_modules/nearley", + "author": { + "name": "Tab Atkins Jr." + }, + "bugs": { + "url": "https://github.com/tabatkins/railroad-diagrams/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "A small JS+SVG library for drawing railroad syntax diagrams.", + "homepage": "https://github.com/tabatkins/railroad-diagrams", + "keywords": [ + "railroad", + "syntax", + "diagrams", + "grammar", + "svg" + ], + "license": "CC0-1.0", + "main": "railroad-diagrams.js", + "name": "railroad-diagrams", + "repository": { + "type": "git", + "url": "git+https://github.com/tabatkins/railroad-diagrams.git" + }, + "version": "1.0.0" +} diff --git a/node_modules/railroad-diagrams/railroad-diagrams.css b/node_modules/railroad-diagrams/railroad-diagrams.css new file mode 100644 index 0000000..0b20004 --- /dev/null +++ b/node_modules/railroad-diagrams/railroad-diagrams.css @@ -0,0 +1,23 @@ +svg.railroad-diagram { + background-color: hsl(30,20%,95%); +} +svg.railroad-diagram path { + stroke-width: 3; + stroke: black; + fill: rgba(0,0,0,0); +} +svg.railroad-diagram text { + font: bold 14px monospace; + text-anchor: middle; +} +svg.railroad-diagram text.label { + text-anchor: start; +} +svg.railroad-diagram text.comment { + font: italic 12px monospace; +} +svg.railroad-diagram rect { + stroke-width: 3; + stroke: black; + fill: hsl(120,100%,90%); +} diff --git a/node_modules/railroad-diagrams/railroad-diagrams.js b/node_modules/railroad-diagrams/railroad-diagrams.js new file mode 100644 index 0000000..afc4541 --- /dev/null +++ b/node_modules/railroad-diagrams/railroad-diagrams.js @@ -0,0 +1,524 @@ +/* +Railroad Diagrams +by Tab Atkins Jr. (and others) +http://xanthir.com +http://twitter.com/tabatkins +http://github.com/tabatkins/railroad-diagrams + +This document and all associated files in the github project are licensed under CC0: http://creativecommons.org/publicdomain/zero/1.0/ +This means you can reuse, remix, or otherwise appropriate this project for your own use WITHOUT RESTRICTION. +(The actual legal meaning can be found at the above link.) +Don't ask me for permission to use any part of this project, JUST USE IT. +I would appreciate attribution, but that is not required by the license. +*/ + +/* +This file uses a module pattern to avoid leaking names into the global scope. +The only accidental leakage is the name "temp". +The exported names can be found at the bottom of this file; +simply change the names in the array of strings to change what they are called in your application. + +As well, several configuration constants are passed into the module function at the bottom of this file. +At runtime, these constants can be found on the Diagram class. +*/ + +(function(options) { + function subclassOf(baseClass, superClass) { + baseClass.prototype = Object.create(superClass.prototype); + baseClass.prototype.$super = superClass.prototype; + } + + function unnull(/* children */) { + return [].slice.call(arguments).reduce(function(sofar, x) { return sofar !== undefined ? sofar : x; }); + } + + function determineGaps(outer, inner) { + var diff = outer - inner; + switch(Diagram.INTERNAL_ALIGNMENT) { + case 'left': return [0, diff]; break; + case 'right': return [diff, 0]; break; + case 'center': + default: return [diff/2, diff/2]; break; + } + } + + function wrapString(value) { + return ((typeof value) == 'string') ? new Terminal(value) : value; + } + + + function SVG(name, attrs, text) { + attrs = attrs || {}; + text = text || ''; + var el = document.createElementNS("http://www.w3.org/2000/svg",name); + for(var attr in attrs) { + el.setAttribute(attr, attrs[attr]); + } + el.textContent = text; + return el; + } + + function FakeSVG(tagName, attrs, text){ + if(!(this instanceof FakeSVG)) return new FakeSVG(tagName, attrs, text); + if(text) this.children = text; + else this.children = []; + this.tagName = tagName; + this.attrs = unnull(attrs, {}); + return this; + }; + FakeSVG.prototype.format = function(x, y, width) { + // Virtual + }; + FakeSVG.prototype.addTo = function(parent) { + if(parent instanceof FakeSVG) { + parent.children.push(this); + return this; + } else { + var svg = this.toSVG(); + parent.appendChild(svg); + return svg; + } + }; + FakeSVG.prototype.escapeString = function(string) { + // Escape markdown and HTML special characters + return string.replace(/[*_\`\[\]<&]/g, function(charString) { + return '&#' + charString.charCodeAt(0) + ';'; + }); + }; + FakeSVG.prototype.toSVG = function() { + var el = SVG(this.tagName, this.attrs); + if(typeof this.children == 'string') { + el.innerHTML = FakeSVG.prototype.escapeString(this.children); + } else { + this.children.forEach(function(e) { + el.appendChild(e.toSVG()); + }); + } + return el; + }; + FakeSVG.prototype.toString = function() { + var str = '<' + this.tagName; + var group = this.tagName == "g" || this.tagName == "svg"; + for(var attr in this.attrs) { + str += ' ' + attr + '="' + (this.attrs[attr]+'').replace(/&/g, '&').replace(/"/g, '"') + '"'; + } + str += '>'; + if(group) str += "\n"; + if(typeof this.children == 'string') { + str += FakeSVG.prototype.escapeString(this.children); + } else { + this.children.forEach(function(e) { + str += e; + }); + } + str += '\n'; + return str; + } + + function Path(x,y) { + if(!(this instanceof Path)) return new Path(x,y); + FakeSVG.call(this, 'path'); + this.attrs.d = "M"+x+' '+y; + } + subclassOf(Path, FakeSVG); + Path.prototype.m = function(x,y) { + this.attrs.d += 'm'+x+' '+y; + return this; + } + Path.prototype.h = function(val) { + this.attrs.d += 'h'+val; + return this; + } + Path.prototype.right = Path.prototype.h; + Path.prototype.left = function(val) { return this.h(-val); } + Path.prototype.v = function(val) { + this.attrs.d += 'v'+val; + return this; + } + Path.prototype.down = Path.prototype.v; + Path.prototype.up = function(val) { return this.v(-val); } + Path.prototype.arc = function(sweep){ + var x = Diagram.ARC_RADIUS; + var y = Diagram.ARC_RADIUS; + if(sweep[0] == 'e' || sweep[1] == 'w') { + x *= -1; + } + if(sweep[0] == 's' || sweep[1] == 'n') { + y *= -1; + } + if(sweep == 'ne' || sweep == 'es' || sweep == 'sw' || sweep == 'wn') { + var cw = 1; + } else { + var cw = 0; + } + this.attrs.d += "a"+Diagram.ARC_RADIUS+" "+Diagram.ARC_RADIUS+" 0 0 "+cw+' '+x+' '+y; + return this; + } + Path.prototype.format = function() { + // All paths in this library start/end horizontally. + // The extra .5 ensures a minor overlap, so there's no seams in bad rasterizers. + this.attrs.d += 'h.5'; + return this; + } + + function Diagram(items) { + if(!(this instanceof Diagram)) return new Diagram([].slice.call(arguments)); + FakeSVG.call(this, 'svg', {class: Diagram.DIAGRAM_CLASS}); + this.items = items.map(wrapString); + this.items.unshift(new Start); + this.items.push(new End); + this.width = this.items.reduce(function(sofar, el) { return sofar + el.width + (el.needsSpace?20:0)}, 0)+1; + this.up = Math.max.apply(null, this.items.map(function (x) { return x.up; })); + this.down = Math.max.apply(null, this.items.map(function (x) { return x.down; })); + this.formatted = false; + } + subclassOf(Diagram, FakeSVG); + for(var option in options) { + Diagram[option] = options[option]; + } + Diagram.prototype.format = function(paddingt, paddingr, paddingb, paddingl) { + paddingt = unnull(paddingt, 20); + paddingr = unnull(paddingr, paddingt, 20); + paddingb = unnull(paddingb, paddingt, 20); + paddingl = unnull(paddingl, paddingr, 20); + var x = paddingl; + var y = paddingt; + y += this.up; + var g = FakeSVG('g', Diagram.STROKE_ODD_PIXEL_LENGTH ? {transform:'translate(.5 .5)'} : {}); + for(var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + if(item.needsSpace) { + Path(x,y).h(10).addTo(g); + x += 10; + } + item.format(x, y, item.width).addTo(g); + x += item.width; + if(item.needsSpace) { + Path(x,y).h(10).addTo(g); + x += 10; + } + } + this.attrs.width = this.width + paddingl + paddingr; + this.attrs.height = this.up + this.down + paddingt + paddingb; + this.attrs.viewBox = "0 0 " + this.attrs.width + " " + this.attrs.height; + g.addTo(this); + this.formatted = true; + return this; + } + Diagram.prototype.addTo = function(parent) { + var scriptTag = document.getElementsByTagName('script'); + scriptTag = scriptTag[scriptTag.length - 1]; + var parentTag = scriptTag.parentNode; + parent = parent || parentTag; + return this.$super.addTo.call(this, parent); + } + Diagram.prototype.toSVG = function() { + if (!this.formatted) { + this.format(); + } + return this.$super.toSVG.call(this); + } + Diagram.prototype.toString = function() { + if (!this.formatted) { + this.format(); + } + return this.$super.toString.call(this); + } + + function ComplexDiagram() { + var diagram = new Diagram([].slice.call(arguments)); + var items = diagram.items; + items.shift(); + items.pop(); + items.unshift(new Start(false)); + items.push(new End(false)); + diagram.items = items; + return diagram; + } + + function Sequence(items) { + if(!(this instanceof Sequence)) return new Sequence([].slice.call(arguments)); + FakeSVG.call(this, 'g'); + this.items = items.map(wrapString); + this.width = this.items.reduce(function(sofar, el) { return sofar + el.width + (el.needsSpace?20:0)}, 0); + this.up = this.items.reduce(function(sofar,el) { return Math.max(sofar, el.up)}, 0); + this.down = this.items.reduce(function(sofar,el) { return Math.max(sofar, el.down)}, 0); + } + subclassOf(Sequence, FakeSVG); + Sequence.prototype.format = function(x,y,width) { + // Hook up the two sides if this is narrower than its stated width. + var gaps = determineGaps(width, this.width); + Path(x,y).h(gaps[0]).addTo(this); + Path(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this); + x += gaps[0]; + + for(var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + if(item.needsSpace) { + Path(x,y).h(10).addTo(this); + x += 10; + } + item.format(x, y, item.width).addTo(this); + x += item.width; + if(item.needsSpace) { + Path(x,y).h(10).addTo(this); + x += 10; + } + } + return this; + } + + function Choice(normal, items) { + if(!(this instanceof Choice)) return new Choice(normal, [].slice.call(arguments,1)); + FakeSVG.call(this, 'g'); + if( typeof normal !== "number" || normal !== Math.floor(normal) ) { + throw new TypeError("The first argument of Choice() must be an integer."); + } else if(normal < 0 || normal >= items.length) { + throw new RangeError("The first argument of Choice() must be an index for one of the items."); + } else { + this.normal = normal; + } + this.items = items.map(wrapString); + this.width = this.items.reduce(function(sofar, el){return Math.max(sofar, el.width)},0) + Diagram.ARC_RADIUS*4; + this.up = this.down = 0; + for(var i = 0; i < this.items.length; i++) { + var item = this.items[i]; + if(i < normal) { this.up += Math.max(Diagram.ARC_RADIUS,item.up + item.down + Diagram.VERTICAL_SEPARATION); } + if(i == normal) { this.up += Math.max(Diagram.ARC_RADIUS, item.up); this.down += Math.max(Diagram.ARC_RADIUS, item.down); } + if(i > normal) { this.down += Math.max(Diagram.ARC_RADIUS,Diagram.VERTICAL_SEPARATION + item.up + item.down); } + } + } + subclassOf(Choice, FakeSVG); + Choice.prototype.format = function(x,y,width) { + // Hook up the two sides if this is narrower than its stated width. + var gaps = determineGaps(width, this.width); + Path(x,y).h(gaps[0]).addTo(this); + Path(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this); + x += gaps[0]; + + var last = this.items.length -1; + var innerWidth = this.width - Diagram.ARC_RADIUS*4; + + // Do the elements that curve above + for(var i = this.normal - 1; i >= 0; i--) { + var item = this.items[i]; + if( i == this.normal - 1 ) { + var distanceFromY = Math.max(Diagram.ARC_RADIUS*2, this.items[i+1].up + Diagram.VERTICAL_SEPARATION + item.down); + } + Path(x,y).arc('se').up(distanceFromY - Diagram.ARC_RADIUS*2).arc('wn').addTo(this); + item.format(x+Diagram.ARC_RADIUS*2,y - distanceFromY,innerWidth).addTo(this); + Path(x+Diagram.ARC_RADIUS*2+innerWidth, y-distanceFromY).arc('ne').down(distanceFromY - Diagram.ARC_RADIUS*2).arc('ws').addTo(this); + distanceFromY += Math.max(Diagram.ARC_RADIUS, item.up + Diagram.VERTICAL_SEPARATION + (i == 0 ? 0 : this.items[i-1].down)); + } + + // Do the straight-line path. + Path(x,y).right(Diagram.ARC_RADIUS*2).addTo(this); + this.items[this.normal].format(x+Diagram.ARC_RADIUS*2, y, innerWidth).addTo(this); + Path(x+Diagram.ARC_RADIUS*2+innerWidth, y).right(Diagram.ARC_RADIUS*2).addTo(this); + + // Do the elements that curve below + for(var i = this.normal+1; i <= last; i++) { + var item = this.items[i]; + if( i == this.normal + 1 ) { + var distanceFromY = Math.max(Diagram.ARC_RADIUS*2, this.items[i-1].down + Diagram.VERTICAL_SEPARATION + item.up); + } + Path(x,y).arc('ne').down(distanceFromY - Diagram.ARC_RADIUS*2).arc('ws').addTo(this); + item.format(x+Diagram.ARC_RADIUS*2, y+distanceFromY, innerWidth).addTo(this); + Path(x+Diagram.ARC_RADIUS*2+innerWidth, y+distanceFromY).arc('se').up(distanceFromY - Diagram.ARC_RADIUS*2).arc('wn').addTo(this); + distanceFromY += Math.max(Diagram.ARC_RADIUS, item.down + Diagram.VERTICAL_SEPARATION + (i == last ? 0 : this.items[i+1].up)); + } + + return this; + } + + function Optional(item, skip) { + if( skip === undefined ) + return Choice(1, Skip(), item); + else if ( skip === "skip" ) + return Choice(0, Skip(), item); + else + throw "Unknown value for Optional()'s 'skip' argument."; + } + + function OneOrMore(item, rep) { + if(!(this instanceof OneOrMore)) return new OneOrMore(item, rep); + FakeSVG.call(this, 'g'); + rep = rep || (new Skip); + this.item = wrapString(item); + this.rep = wrapString(rep); + this.width = Math.max(this.item.width, this.rep.width) + Diagram.ARC_RADIUS*2; + this.up = this.item.up; + this.down = Math.max(Diagram.ARC_RADIUS*2, this.item.down + Diagram.VERTICAL_SEPARATION + this.rep.up + this.rep.down); + } + subclassOf(OneOrMore, FakeSVG); + OneOrMore.prototype.needsSpace = true; + OneOrMore.prototype.format = function(x,y,width) { + // Hook up the two sides if this is narrower than its stated width. + var gaps = determineGaps(width, this.width); + Path(x,y).h(gaps[0]).addTo(this); + Path(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this); + x += gaps[0]; + + // Draw item + Path(x,y).right(Diagram.ARC_RADIUS).addTo(this); + this.item.format(x+Diagram.ARC_RADIUS,y,this.width-Diagram.ARC_RADIUS*2).addTo(this); + Path(x+this.width-Diagram.ARC_RADIUS,y).right(Diagram.ARC_RADIUS).addTo(this); + + // Draw repeat arc + var distanceFromY = Math.max(Diagram.ARC_RADIUS*2, this.item.down+Diagram.VERTICAL_SEPARATION+this.rep.up); + Path(x+Diagram.ARC_RADIUS,y).arc('nw').down(distanceFromY-Diagram.ARC_RADIUS*2).arc('ws').addTo(this); + this.rep.format(x+Diagram.ARC_RADIUS, y+distanceFromY, this.width - Diagram.ARC_RADIUS*2).addTo(this); + Path(x+this.width-Diagram.ARC_RADIUS, y+distanceFromY).arc('se').up(distanceFromY-Diagram.ARC_RADIUS*2).arc('en').addTo(this); + + return this; + } + + function ZeroOrMore(item, rep, skip) { + return Optional(OneOrMore(item, rep), skip); + } + + function Start(simpleType) { + if(!(this instanceof Start)) return new Start(); + FakeSVG.call(this, 'path'); + this.width = 20; + this.up = 10; + this.down = 10; + this.simpleType = simpleType; + } + subclassOf(Start, FakeSVG); + Start.prototype.format = function(x,y) { + if (this.simpleType === false) { + this.attrs.d = 'M '+x+' '+(y-10)+' v 20 m 0 -10 h 20.5'; + } else { + this.attrs.d = 'M '+x+' '+(y-10)+' v 20 m 10 -20 v 20 m -10 -10 h 20.5'; + } + return this; + } + + function End(simpleType) { + if(!(this instanceof End)) return new End(); + FakeSVG.call(this, 'path'); + this.width = 20; + this.up = 10; + this.down = 10; + this.simpleType = simpleType; + } + subclassOf(End, FakeSVG); + End.prototype.format = function(x,y) { + if (this.simpleType === false) { + this.attrs.d = 'M '+x+' '+y+' h 20 m 0 -10 v 20'; + } else { + this.attrs.d = 'M '+x+' '+y+' h 20 m -10 -10 v 20 m 10 -20 v 20'; + } + return this; + } + + function Terminal(text) { + if(!(this instanceof Terminal)) return new Terminal(text); + FakeSVG.call(this, 'g'); + this.text = text; + this.width = text.length * 8 + 20; /* Assume that each char is .5em, and that the em is 16px */ + this.up = 11; + this.down = 11; + } + subclassOf(Terminal, FakeSVG); + Terminal.prototype.needsSpace = true; + Terminal.prototype.format = function(x, y, width) { + // Hook up the two sides if this is narrower than its stated width. + var gaps = determineGaps(width, this.width); + Path(x,y).h(gaps[0]).addTo(this); + Path(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this); + x += gaps[0]; + + FakeSVG('rect', {x:x, y:y-11, width:this.width, height:this.up+this.down, rx:10, ry:10}).addTo(this); + FakeSVG('text', {x:x+this.width/2, y:y+4}, this.text).addTo(this); + return this; + } + + function NonTerminal(text) { + if(!(this instanceof NonTerminal)) return new NonTerminal(text); + FakeSVG.call(this, 'g'); + this.text = text; + this.width = text.length * 8 + 20; + this.up = 11; + this.down = 11; + } + subclassOf(NonTerminal, FakeSVG); + NonTerminal.prototype.needsSpace = true; + NonTerminal.prototype.format = function(x, y, width) { + // Hook up the two sides if this is narrower than its stated width. + var gaps = determineGaps(width, this.width); + Path(x,y).h(gaps[0]).addTo(this); + Path(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this); + x += gaps[0]; + + FakeSVG('rect', {x:x, y:y-11, width:this.width, height:this.up+this.down}).addTo(this); + FakeSVG('text', {x:x+this.width/2, y:y+4}, this.text).addTo(this); + return this; + } + + function Comment(text) { + if(!(this instanceof Comment)) return new Comment(text); + FakeSVG.call(this, 'g'); + this.text = text; + this.width = text.length * 7 + 10; + this.up = 11; + this.down = 11; + } + subclassOf(Comment, FakeSVG); + Comment.prototype.needsSpace = true; + Comment.prototype.format = function(x, y, width) { + // Hook up the two sides if this is narrower than its stated width. + var gaps = determineGaps(width, this.width); + Path(x,y).h(gaps[0]).addTo(this); + Path(x+gaps[0]+this.width,y).h(gaps[1]).addTo(this); + x += gaps[0]; + + FakeSVG('text', {x:x+this.width/2, y:y+5, class:'comment'}, this.text).addTo(this); + return this; + } + + function Skip() { + if(!(this instanceof Skip)) return new Skip(); + FakeSVG.call(this, 'g'); + this.width = 0; + this.up = 0; + this.down = 0; + } + subclassOf(Skip, FakeSVG); + Skip.prototype.format = function(x, y, width) { + Path(x,y).right(width).addTo(this); + return this; + } + + var root; + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + root = {}; + define([], function() { + return root; + }); + } else if (typeof exports === 'object') { + // CommonJS for node + root = exports; + } else { + // Browser globals (root is window) + root = this; + } + + var temp = [Diagram, ComplexDiagram, Sequence, Choice, Optional, OneOrMore, ZeroOrMore, Terminal, NonTerminal, Comment, Skip]; + /* + These are the names that the internal classes are exported as. + If you would like different names, adjust them here. + */ + ['Diagram', 'ComplexDiagram', 'Sequence', 'Choice', 'Optional', 'OneOrMore', 'ZeroOrMore', 'Terminal', 'NonTerminal', 'Comment', 'Skip'] + .forEach(function(e,i) { root[e] = temp[i]; }); +}).call(this, + { + VERTICAL_SEPARATION: 8, + ARC_RADIUS: 10, + DIAGRAM_CLASS: 'railroad-diagram', + STROKE_ODD_PIXEL_LENGTH: true, + INTERNAL_ALIGNMENT: 'center', + } +); diff --git a/node_modules/railroad-diagrams/railroad_diagrams.py b/node_modules/railroad-diagrams/railroad_diagrams.py new file mode 100644 index 0000000..7d53003 --- /dev/null +++ b/node_modules/railroad-diagrams/railroad_diagrams.py @@ -0,0 +1,427 @@ +# Display constants +VERTICAL_SEPARATION = 8 +ARC_RADIUS = 10 +DIAGRAM_CLASS = 'railroad-diagram' +TRANSLATE_HALF_PIXEL = True +INTERNAL_ALIGNMENT = 'center' +DEBUG=False + +# Assume a monospace font with each char .5em wide, and the em is 16px +CHARACTER_ADVANCE = 8 + +def e(text): + return str(text).replace('&', '&').replace('"', '"').replace('<', '<') + +def determineGaps(outer, inner): + diff = outer - inner + if INTERNAL_ALIGNMENT == 'left': + return 0, diff + elif INTERNAL_ALIGNMENT == 'right': + return diff, 0 + else: + return diff/2, diff/2 + + + +class DiagramItem(object): + def __init__(self, name, attrs=None, text=None): + self.name = name + self.attrs = attrs or {} + self.children = [text] if text else [] + self.needsSpace = False + + def format(self, x, y, width): + raise NotImplementedError # Virtual + + def addTo(self, parent): + parent.children.append(self) + return self + + def writeSvg(self, write): + write('<{0}'.format(self.name)) + for name, value in sorted(self.attrs.items()): + write(' {0}="{1}"'.format(name, e(value))) + write('>\n') + for child in self.children: + if isinstance(child, DiagramItem): + child.writeSvg(write) + else: + write(e(child)) + write(''.format(self.name)) + + +class Path(DiagramItem): + def __init__(self, x, y): + DiagramItem.__init__(self, 'path', {'d': 'M%s %s' % (x, y)}) + + def m(self, x, y): + self.attrs['d'] += 'm{0} {1}'.format(x,y) + return self + + def h(self, val): + self.attrs['d'] += 'h{0}'.format(val) + return self + + right = h + + def left(self, val): + return self.h(-val) + + def v(self, val): + self.attrs['d'] += 'v{0}'.format(val) + return self + + down = v + + def up(self, val): + return self.v(-val) + + def arc(self, sweep): + x = ARC_RADIUS + y = ARC_RADIUS + if sweep[0] == 'e' or sweep[1] == 'w': + x *= -1 + if sweep[0] == 's' or sweep[1] == 'n': + y *= -1 + cw = 1 if sweep == 'ne' or sweep == 'es' or sweep == 'sw' or sweep == 'wn' else 0 + self.attrs['d'] += 'a{0} {0} 0 0 {1} {2} {3}'.format(ARC_RADIUS, cw, x, y) + return self + + + def format(self): + self.attrs['d'] += 'h.5' + return self + + +def wrapString(value): + return value if isinstance(value, DiagramItem) else Terminal(value) + + +class Diagram(DiagramItem): + def __init__(self, *items): + DiagramItem.__init__(self, 'svg', {'class': DIAGRAM_CLASS}) + self.items = [Start()] + [wrapString(item) for item in items] + [End()] + self.width = 1 + sum(item.width + (20 if item.needsSpace else 0) + for item in self.items) + self.up = max(item.up for item in self.items) + self.down = max(item.down for item in self.items) + self.formatted = False + + def format(self, paddingTop=20, paddingRight=None, paddingBottom=None, paddingLeft=None): + if paddingRight is None: + paddingRight = paddingTop + if paddingBottom is None: + paddingBottom = paddingTop + if paddingLeft is None: + paddingLeft = paddingRight + x = paddingLeft + y = paddingTop + self.up + g = DiagramItem('g') + if TRANSLATE_HALF_PIXEL: + g.attrs['transform'] = 'translate(.5 .5)' + for item in self.items: + if item.needsSpace: + Path(x, y).h(10).addTo(g) + x += 10 + item.format(x, y, item.width).addTo(g) + x += item.width + if item.needsSpace: + Path(x, y).h(10).addTo(g) + x += 10 + self.attrs['width'] = self.width + paddingLeft + paddingRight + self.attrs['height'] = self.up + self.down + paddingTop + paddingBottom + self.attrs['viewBox'] = "0 0 {width} {height}".format(**self.attrs) + g.addTo(self) + self.formatted = True + return self + + + def writeSvg(self, write): + if not self.formatted: + self.format() + return DiagramItem.writeSvg(self, write) + + +class Sequence(DiagramItem): + def __init__(self, *items): + DiagramItem.__init__(self, 'g') + self.items = [wrapString(item) for item in items] + self.width = sum(item.width + (20 if item.needsSpace else 0) + for item in self.items) + self.up = max(item.up for item in self.items) + self.down = max(item.down for item in self.items) + if DEBUG: + self.attrs['data-updown'] = "{0} {1}".format(self.up, self.down) + self.attrs['data-type'] = "sequence" + + def format(self, x, y, width): + leftGap, rightGap = determineGaps(width, self.width) + Path(x, y).h(leftGap).addTo(self) + Path(x+leftGap+self.width, y).h(rightGap).addTo(self) + x += leftGap + for item in self.items: + if item.needsSpace: + Path(x, y).h(10).addTo(self) + x += 10 + item.format(x, y, item.width).addTo(self) + x += item.width + if item.needsSpace: + Path(x, y).h(10).addTo(self) + x += 10 + return self + + +class Choice(DiagramItem): + def __init__(self, default, *items): + DiagramItem.__init__(self, 'g') + assert default < len(items) + self.default = default + self.items = [wrapString(item) for item in items] + self.width = ARC_RADIUS * 4 + max(item.width for item in self.items) + self.up = 0 + self.down = 0 + for i, item in enumerate(self.items): + if i < default: + self.up += max(ARC_RADIUS, item.up + item.down + VERTICAL_SEPARATION) + elif i == default: + self.up += max(ARC_RADIUS, item.up) + self.down += max(ARC_RADIUS, item.down) + else: + assert i > default + self.down += max(ARC_RADIUS, VERTICAL_SEPARATION + item.up + item.down) + if DEBUG: + self.attrs['data-updown'] = "{0} {1}".format(self.up, self.down) + self.attrs['data-type'] = "choice" + + def format(self, x, y, width): + leftGap, rightGap = determineGaps(width, self.width) + + # Hook up the two sides if self is narrower than its stated width. + Path(x, y).h(leftGap).addTo(self) + Path(x + leftGap + self.width, y).h(rightGap).addTo(self) + x += leftGap + + last = len(self.items) - 1 + innerWidth = self.width - ARC_RADIUS * 4 + + # Do the elements that curve above + above = self.items[:self.default] + if above: + distanceFromY = max( + ARC_RADIUS * 2, + self.items[self.default].up + + VERTICAL_SEPARATION + + self.items[self.default - 1].down) + for i, item in list(enumerate(above))[::-1]: + Path(x, y).arc('se').up(distanceFromY - ARC_RADIUS * 2).arc('wn').addTo(self) + item.format(x + ARC_RADIUS * 2, y - distanceFromY, innerWidth).addTo(self) + Path(x + ARC_RADIUS * 2 + innerWidth, y - distanceFromY).arc('ne') \ + .down(distanceFromY - ARC_RADIUS*2).arc('ws').addTo(self) + distanceFromY += max( + ARC_RADIUS, + item.up + + VERTICAL_SEPARATION + + (self.items[i - 1].down if i > 0 else 0)) + + # Do the straight-line path. + Path(x, y).right(ARC_RADIUS * 2).addTo(self) + self.items[self.default].format(x + ARC_RADIUS * 2, y, innerWidth).addTo(self) + Path(x + ARC_RADIUS * 2 + innerWidth, y).right(ARC_RADIUS * 2).addTo(self) + + # Do the elements that curve below + below = self.items[self.default + 1:] + for i, item in enumerate(below): + if i == 0: + distanceFromY = max( + ARC_RADIUS * 2, + self.items[self.default].down + + VERTICAL_SEPARATION + + item.up) + Path(x, y).arc('ne').down(distanceFromY - ARC_RADIUS * 2).arc('ws').addTo(self) + item.format(x + ARC_RADIUS * 2, y + distanceFromY, innerWidth).addTo(self) + Path(x + ARC_RADIUS * 2 + innerWidth, y + distanceFromY).arc('se') \ + .up(distanceFromY - ARC_RADIUS * 2).arc('wn').addTo(self) + distanceFromY += max( + ARC_RADIUS, + item.down + + VERTICAL_SEPARATION + + (below[i + 1].up if i+1 < len(below) else 0)) + return self + + +def Optional(item, skip=False): + return Choice(0 if skip else 1, Skip(), item) + + +class OneOrMore(DiagramItem): + def __init__(self, item, repeat=None): + DiagramItem.__init__(self, 'g') + repeat = repeat or Skip() + self.item = wrapString(item) + self.rep = wrapString(repeat) + self.width = max(self.item.width, self.rep.width) + ARC_RADIUS * 2 + self.up = self.item.up + self.down = max( + ARC_RADIUS * 2, + self.item.down + VERTICAL_SEPARATION + self.rep.up + self.rep.down) + self.needsSpace = True + if DEBUG: + self.attrs['data-updown'] = "{0} {1}".format(self.up, self.down) + self.attrs['data-type'] = "oneormore" + + def format(self, x, y, width): + leftGap, rightGap = determineGaps(width, self.width) + + # Hook up the two sides if self is narrower than its stated width. + Path(x, y).h(leftGap).addTo(self) + Path(x + leftGap + self.width, y).h(rightGap).addTo(self) + x += leftGap + + # Draw item + Path(x, y).right(ARC_RADIUS).addTo(self) + self.item.format(x + ARC_RADIUS, y, self.width - ARC_RADIUS * 2).addTo(self) + Path(x + self.width - ARC_RADIUS, y).right(ARC_RADIUS).addTo(self) + + # Draw repeat arc + distanceFromY = max(ARC_RADIUS*2, self.item.down + VERTICAL_SEPARATION + self.rep.up) + Path(x + ARC_RADIUS, y).arc('nw').down(distanceFromY - ARC_RADIUS * 2) \ + .arc('ws').addTo(self) + self.rep.format(x + ARC_RADIUS, y + distanceFromY, self.width - ARC_RADIUS*2).addTo(self) + Path(x + self.width - ARC_RADIUS, y + distanceFromY).arc('se') \ + .up(distanceFromY - ARC_RADIUS * 2).arc('en').addTo(self) + + return self + + +def ZeroOrMore(item, repeat=None): + result = Optional(OneOrMore(item, repeat)) + return result + + +class Start(DiagramItem): + def __init__(self): + DiagramItem.__init__(self, 'path') + self.width = 20 + self.up = 10 + self.down = 10 + if DEBUG: + self.attrs['data-updown'] = "{0} {1}".format(self.up, self.down) + self.attrs['data-type'] = "start" + + def format(self, x, y, _width): + self.attrs['d'] = 'M {0} {1} v 20 m 10 -20 v 20 m -10 -10 h 20.5'.format(x, y - 10) + return self + + +class End(DiagramItem): + def __init__(self): + DiagramItem.__init__(self, 'path') + self.width = 20 + self.up = 10 + self.down = 10 + if DEBUG: + self.attrs['data-updown'] = "{0} {1}".format(self.up, self.down) + self.attrs['data-type'] = "end" + + def format(self, x, y, _width): + self.attrs['d'] = 'M {0} {1} h 20 m -10 -10 v 20 m 10 -20 v 20'.format(x, y) + return self + + +class Terminal(DiagramItem): + def __init__(self, text): + DiagramItem.__init__(self, 'g') + self.text = text + self.width = len(text) * CHARACTER_ADVANCE + 20 + self.up = 11 + self.down = 11 + self.needsSpace = True + if DEBUG: + self.attrs['data-updown'] = "{0} {1}".format(self.up, self.down) + self.attrs['data-type'] = "terminal" + + def format(self, x, y, width): + leftGap, rightGap = determineGaps(width, self.width) + + # Hook up the two sides if self is narrower than its stated width. + Path(x, y).h(leftGap).addTo(self) + Path(x + leftGap + self.width, y).h(rightGap).addTo(self) + + DiagramItem('rect', {'x': x + leftGap, 'y': y - 11, 'width': self.width, + 'height': self.up + self.down, 'rx': 10, 'ry': 10}).addTo(self) + DiagramItem('text', {'x': x + width / 2, 'y': y + 4}, self.text).addTo(self) + return self + + +class NonTerminal(DiagramItem): + def __init__(self, text): + DiagramItem.__init__(self, 'g') + self.text = text + self.width = len(text) * CHARACTER_ADVANCE + 20 + self.up = 11 + self.down = 11 + self.needsSpace = True + if DEBUG: + self.attrs['data-updown'] = "{0} {1}".format(self.up, self.down) + self.attrs['data-type'] = "non-terminal" + + def format(self, x, y, width): + leftGap, rightGap = determineGaps(width, self.width) + + # Hook up the two sides if self is narrower than its stated width. + Path(x, y).h(leftGap).addTo(self) + Path(x + leftGap + self.width, y).h(rightGap).addTo(self) + + DiagramItem('rect', {'x': x + leftGap, 'y': y - 11, 'width': self.width, + 'height': self.up + self.down}).addTo(self) + DiagramItem('text', {'x': x + width / 2, 'y': y + 4}, self.text).addTo(self) + return self + + +class Comment(DiagramItem): + def __init__(self, text): + DiagramItem.__init__(self, 'g') + self.text = text + self.width = len(text) * 7 + 10 + self.up = 11 + self.down = 11 + self.needsSpace = True + if DEBUG: + self.attrs['data-updown'] = "{0} {1}".format(self.up, self.down) + self.attrs['data-type'] = "comment" + + def format(self, x, y, width): + leftGap, rightGap = determineGaps(width, self.width) + + # Hook up the two sides if self is narrower than its stated width. + Path(x, y).h(leftGap).addTo(self) + Path(x + leftGap + self.width, y).h(rightGap).addTo(self) + + DiagramItem('text', {'x': x + width / 2, 'y': y + 5, 'class': 'comment'}, self.text).addTo(self) + return self + + +class Skip(DiagramItem): + def __init__(self): + DiagramItem.__init__(self, 'g') + self.width = 0 + self.up = 0 + self.down = 0 + if DEBUG: + self.attrs['data-updown'] = "{0} {1}".format(self.up, self.down) + self.attrs['data-type'] = "skip" + + def format(self, x, y, width): + Path(x, y).right(width).addTo(self) + return self + + +if __name__ == '__main__': + def add(name, diagram): + sys.stdout.write('

{0}

\n'.format(e(name))) + diagram.writeSvg(sys.stdout.write) + sys.stdout.write('\n') + + import sys + sys.stdout.write("Test") + exec(open('css-example.py-js').read()) diff --git a/node_modules/randexp/LICENSE b/node_modules/randexp/LICENSE new file mode 100644 index 0000000..b351ee8 --- /dev/null +++ b/node_modules/randexp/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2011 by Roly Fentanes + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/randexp/README.md b/node_modules/randexp/README.md new file mode 100644 index 0000000..ac30c62 --- /dev/null +++ b/node_modules/randexp/README.md @@ -0,0 +1,134 @@ +# randexp.js + +randexp will generate a random string that matches a given RegExp Javascript object. + +[![Build Status](https://secure.travis-ci.org/fent/randexp.js.svg)](http://travis-ci.org/fent/randexp.js) +[![Dependency Status](https://david-dm.org/fent/randexp.js.svg)](https://david-dm.org/fent/randexp.js) +[![codecov](https://codecov.io/gh/fent/randexp.js/branch/master/graph/badge.svg)](https://codecov.io/gh/fent/randexp.js) + +# Usage + +```js +var RandExp = require('randexp'); + +// supports grouping and piping +new RandExp(/hello+ (world|to you)/).gen(); +// => hellooooooooooooooooooo world + +// sets and ranges and references +new RandExp(/<([a-z]\w{0,20})>foo<\1>/).gen(); +// => foo + +// wildcard +new RandExp(/random stuff: .+/).gen(); +// => random stuff: l3m;Hf9XYbI [YPaxV>U*4-_F!WXQh9>;rH3i l!8.zoh?[utt1OWFQrE ^~8zEQm]~tK + +// ignore case +new RandExp(/xxx xtreme dragon warrior xxx/i).gen(); +// => xxx xtReME dRAGON warRiOR xXX + +// dynamic regexp shortcut +new RandExp('(sun|mon|tue|wednes|thurs|fri|satur)day', 'i'); +// is the same as +new RandExp(new RegExp('(sun|mon|tue|wednes|thurs|fri|satur)day', 'i')); +``` + +If you're only going to use `gen()` once with a regexp and want slightly shorter syntax for it + +```js +var randexp = require('randexp').randexp; + +randexp(/[1-6]/); // 4 +randexp('great|good( job)?|excellent'); // great +``` + +If you miss the old syntax + +```js +require('randexp').sugar(); + +/yes|no|maybe|i don't know/.gen(); // maybe +``` + +# Motivation + +Regular expressions are used in every language, every programmer is familiar with them. Regex can be used to easily express complex strings. What better way to generate a random string than with a language you can use to express the string you want? + +Thanks to [String-Random](http://search.cpan.org/~steve/String-Random-0.22/lib/String/Random.pm) for giving me the idea to make this in the first place and [randexp](https://github.com/benburkert/randexp) for the sweet `.gen()` syntax. + +# Default Range + +The default generated character range includes printable ASCII. In order to add or remove characters, +a `defaultRange` attribute is exposed. you can `subtract(from, to)` and `add(from, to)` +```js +var randexp = new RandExp(/random stuff: .+/); +randexp.defaultRange.subtract(32, 126); +randexp.defaultRange.add(0, 65535); +randexp.gen(); +// => random stuff: 湐箻ໜ䫴␩⶛㳸長���邓蕲뤀쑡篷皇硬剈궦佔칗븛뀃匫鴔事좍ﯣ⭼ꝏ䭍詳蒂䥂뽭 +``` + +# Custom PRNG + +The default randomness is provided by `Math.random()`. If you need to use a seedable or cryptographic PRNG, you +can override `RandExp.prototype.randInt` or `randexp.randInt` (where `randexp` is an instance of `RandExp`). `randInt(from, to)` accepts an inclusive range and returns a randomly selected +number within that range. + +# Infinite Repetitionals + +Repetitional tokens such as `*`, `+`, and `{3,}` have an infinite max range. In this case, randexp looks at its min and adds 100 to it to get a useable max value. If you want to use another int other than 100 you can change the `max` property in `RandExp.prototype` or the RandExp instance. + +```js +var randexp = new RandExp(/no{1,}/); +randexp.max = 1000000; +``` + +With `RandExp.sugar()` + +```js +var regexp = /(hi)*/; +regexp.max = 1000000; +``` + +# Bad Regular Expressions + +There are some regular expressions which can never match any string. + +* Ones with badly placed positionals such as `/a^/` and `/$c/m`. Randexp will ignore positional tokens. + +* Back references to non-existing groups like `/(a)\1\2/`. Randexp will ignore those references, returning an empty string for them. If the group exists only after the reference is used such as in `/\1 (hey)/`, it will too be ignored. + +* Custom negated character sets with two sets inside that cancel each other out. Example: `/[^\w\W]/`. If you give this to randexp, it will return an empty string for this set since it can't match anything. + + +# Projects based on randexp.js + + +## JSON-Schema Faker + +Use generators to populate JSON Schema samples. See: [jsf on github](https://github.com/json-schema-faker/json-schema-faker/) and [jsf demo page](http://json-schema-faker.js.org/). + + +# Install + +### Node.js + + npm install randexp + +### Browser + +Download the [minified version](https://github.com/fent/randexp.js/releases) from the latest release. + + +# Tests + +Tests are written with [mocha](https://mochajs.org) + +```bash +npm test +``` + + +# License + +MIT diff --git a/node_modules/randexp/lib/randexp.js b/node_modules/randexp/lib/randexp.js new file mode 100644 index 0000000..6dcbd7a --- /dev/null +++ b/node_modules/randexp/lib/randexp.js @@ -0,0 +1,245 @@ +var ret = require('ret'); +var DRange = require('discontinuous-range'); +var types = ret.types; + + +/** + * If code is alphabetic, converts to other case. + * If not alphabetic, returns back code. + * + * @param {Number} code + * @return {Number} + */ +function toOtherCase(code) { + return code + (97 <= code && code <= 122 ? -32 : + 65 <= code && code <= 90 ? 32 : 0); +} + + +/** + * Randomly returns a true or false value. + * + * @return {Boolean} + */ +function randBool() { + return !this.randInt(0, 1); +} + + +/** + * Randomly selects and returns a value from the array. + * + * @param {Array.} arr + * @return {Object} + */ +function randSelect(arr) { + if (arr instanceof DRange) { + return arr.index(this.randInt(0, arr.length - 1)); + } + return arr[this.randInt(0, arr.length - 1)]; +} + + +/** + * expands a token to a DiscontinuousRange of characters which has a + * length and an index function (for random selecting) + * + * @param {Object} token + * @return {DiscontinuousRange} + */ +function expand(token) { + if (token.type === ret.types.CHAR) { + return new DRange(token.value); + } else if (token.type === ret.types.RANGE) { + return new DRange(token.from, token.to); + } else { + var drange = new DRange(); + for (var i = 0; i < token.set.length; i++) { + var subrange = expand.call(this, token.set[i]); + drange.add(subrange); + if (this.ignoreCase) { + for (var j = 0; j < subrange.length; j++) { + var code = subrange.index(j); + var otherCaseCode = toOtherCase(code); + if (code !== otherCaseCode) { + drange.add(otherCaseCode); + } + } + } + } + if (token.not) { + return this.defaultRange.clone().subtract(drange); + } else { + return drange; + } + } +} + + +/** + * Checks if some custom properties have been set for this regexp. + * + * @param {RandExp} randexp + * @param {RegExp} regexp + */ +function checkCustom(randexp, regexp) { + if (typeof regexp.max === 'number') { + randexp.max = regexp.max; + } + if (regexp.defaultRange instanceof DRange) { + randexp.defaultRange = regexp.defaultRange; + } + if (typeof regexp.randInt === 'function') { + randexp.randInt = regexp.randInt; + } +} + + +/** + * @constructor + * @param {RegExp|String} regexp + * @param {String} m + */ +var RandExp = module.exports = function(regexp, m) { + this.defaultRange = this.defaultRange.clone(); + if (regexp instanceof RegExp) { + this.ignoreCase = regexp.ignoreCase; + this.multiline = regexp.multiline; + checkCustom(this, regexp); + regexp = regexp.source; + + } else if (typeof regexp === 'string') { + this.ignoreCase = m && m.indexOf('i') !== -1; + this.multiline = m && m.indexOf('m') !== -1; + } else { + throw new Error('Expected a regexp or string'); + } + + this.tokens = ret(regexp); +}; + + +// When a repetitional token has its max set to Infinite, +// randexp won't actually generate a random amount between min and Infinite +// instead it will see Infinite as min + 100. +RandExp.prototype.max = 100; + + +// Generates the random string. +RandExp.prototype.gen = function() { + return gen.call(this, this.tokens, []); +}; + + +// Enables use of randexp with a shorter call. +RandExp.randexp = function(regexp, m) { + var randexp; + if (regexp._randexp === undefined) { + randexp = new RandExp(regexp, m); + regexp._randexp = randexp; + } else { + randexp = regexp._randexp; + } + checkCustom(randexp, regexp); + return randexp.gen(); +}; + + +// This enables sugary /regexp/.gen syntax. +RandExp.sugar = function() { + /* jshint freeze:false */ + RegExp.prototype.gen = function() { + return RandExp.randexp(this); + }; +}; + +// This allows expanding to include additional characters +// for instance: RandExp.defaultRange.add(0, 65535); +RandExp.prototype.defaultRange = new DRange(32, 126); + + +/** + * Randomly generates and returns a number between a and b (inclusive). + * + * @param {Number} a + * @param {Number} b + * @return {Number} + */ +RandExp.prototype.randInt = function(a, b) { + return a + Math.floor(Math.random() * (1 + b - a)); +}; + + +/** + * Generate random string modeled after given tokens. + * + * @param {Object} token + * @param {Array.} groups + * @return {String} + */ +function gen(token, groups) { + var stack, str, n, i, l; + + switch (token.type) { + + + case types.ROOT: + case types.GROUP: + // Ignore lookaheads for now. + if (token.followedBy || token.notFollowedBy) { return ''; } + + // Insert placeholder until group string is generated. + if (token.remember && token.groupNumber === undefined) { + token.groupNumber = groups.push(null) - 1; + } + + stack = token.options ? + randSelect.call(this, token.options) : token.stack; + + str = ''; + for (i = 0, l = stack.length; i < l; i++) { + str += gen.call(this, stack[i], groups); + } + + if (token.remember) { + groups[token.groupNumber] = str; + } + return str; + + + case types.POSITION: + // Do nothing for now. + return ''; + + + case types.SET: + var expandedSet = expand.call(this, token); + if (!expandedSet.length) { return ''; } + return String.fromCharCode(randSelect.call(this, expandedSet)); + + + case types.REPETITION: + // Randomly generate number between min and max. + n = this.randInt(token.min, + token.max === Infinity ? token.min + this.max : token.max); + + str = ''; + for (i = 0; i < n; i++) { + str += gen.call(this, token.value, groups); + } + + return str; + + + case types.REFERENCE: + return groups[token.value - 1] || ''; + + + case types.CHAR: + var code = this.ignoreCase && randBool.call(this) ? + toOtherCase(token.value) : token.value; + return String.fromCharCode(code); + } +} + + diff --git a/node_modules/randexp/package.json b/node_modules/randexp/package.json new file mode 100644 index 0000000..18204f5 --- /dev/null +++ b/node_modules/randexp/package.json @@ -0,0 +1,79 @@ +{ + "_from": "randexp@0.4.6", + "_id": "randexp@0.4.6", + "_inBundle": false, + "_integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "_location": "/randexp", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "randexp@0.4.6", + "name": "randexp", + "escapedName": "randexp", + "rawSpec": "0.4.6", + "saveSpec": null, + "fetchSpec": "0.4.6" + }, + "_requiredBy": [ + "/nearley" + ], + "_resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "_shasum": "e986ad5e5e31dae13ddd6f7b3019aa7c87f60ca3", + "_spec": "randexp@0.4.6", + "_where": "/Users/dletta/Documents/GitHub/conceptGraph/node_modules/nearley", + "author": { + "name": "Roly Fentanes", + "url": "https://github.com/fent" + }, + "bugs": { + "url": "https://github.com/fent/randexp.js/issues" + }, + "bundleDependencies": false, + "dependencies": { + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" + }, + "deprecated": false, + "description": "Create random strings that match a given regular expression.", + "devDependencies": { + "browserify": "^14.0.0", + "gulp": "^3.9.0", + "gulp-header": "^1.7.1", + "gulp-insert": "^0.5.0", + "gulp-uglify": "^3.0.0", + "istanbul": "*", + "mocha": "*", + "vinyl-buffer": "^1.0.0", + "vinyl-source-stream": "^1.1.0" + }, + "directories": { + "lib": "./lib" + }, + "engines": { + "node": ">=0.12" + }, + "files": [ + "lib" + ], + "homepage": "http://fent.github.io/randexp.js/", + "keywords": [ + "regex", + "regexp", + "regular expression", + "random", + "test" + ], + "license": "MIT", + "main": "./lib/randexp.js", + "name": "randexp", + "repository": { + "type": "git", + "url": "git://github.com/fent/randexp.js.git" + }, + "scripts": { + "test": "istanbul cover node_modules/.bin/_mocha -- test/*-test.js", + "version": "gulp build && git add build" + }, + "version": "0.4.6" +} diff --git a/node_modules/ret/LICENSE b/node_modules/ret/LICENSE new file mode 100644 index 0000000..b351ee8 --- /dev/null +++ b/node_modules/ret/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2011 by Roly Fentanes + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/node_modules/ret/README.md b/node_modules/ret/README.md new file mode 100644 index 0000000..28563e1 --- /dev/null +++ b/node_modules/ret/README.md @@ -0,0 +1,183 @@ +# Regular Expression Tokenizer + +Tokenizes strings that represent a regular expressions. + +[![Build Status](https://secure.travis-ci.org/fent/ret.js.svg)](http://travis-ci.org/fent/ret.js) +[![Dependency Status](https://david-dm.org/fent/ret.js.svg)](https://david-dm.org/fent/ret.js) +[![codecov](https://codecov.io/gh/fent/ret.js/branch/master/graph/badge.svg)](https://codecov.io/gh/fent/ret.js) + +# Usage + +```js +var ret = require('ret'); + +var tokens = ret(/foo|bar/.source); +``` + +`tokens` will contain the following object + +```js +{ + "type": ret.types.ROOT + "options": [ + [ { "type": ret.types.CHAR, "value", 102 }, + { "type": ret.types.CHAR, "value", 111 }, + { "type": ret.types.CHAR, "value", 111 } ], + [ { "type": ret.types.CHAR, "value", 98 }, + { "type": ret.types.CHAR, "value", 97 }, + { "type": ret.types.CHAR, "value", 114 } ] + ] +} +``` + +# Token Types + +`ret.types` is a collection of the various token types exported by ret. + +### ROOT + +Only used in the root of the regexp. This is needed due to the posibility of the root containing a pipe `|` character. In that case, the token will have an `options` key that will be an array of arrays of tokens. If not, it will contain a `stack` key that is an array of tokens. + +```js +{ + "type": ret.types.ROOT, + "stack": [token1, token2...], +} +``` + +```js +{ + "type": ret.types.ROOT, + "options" [ + [token1, token2...], + [othertoken1, othertoken2...] + ... + ], +} +``` + +### GROUP + +Groups contain tokens that are inside of a parenthesis. If the group begins with `?` followed by another character, it's a special type of group. A ':' tells the group not to be remembered when `exec` is used. '=' means the previous token matches only if followed by this group, and '!' means the previous token matches only if NOT followed. + +Like root, it can contain an `options` key instead of `stack` if there is a pipe. + +```js +{ + "type": ret.types.GROUP, + "remember" true, + "followedBy": false, + "notFollowedBy": false, + "stack": [token1, token2...], +} +``` + +```js +{ + "type": ret.types.GROUP, + "remember" true, + "followedBy": false, + "notFollowedBy": false, + "options" [ + [token1, token2...], + [othertoken1, othertoken2...] + ... + ], +} +``` + +### POSITION + +`\b`, `\B`, `^`, and `$` specify positions in the regexp. + +```js +{ + "type": ret.types.POSITION, + "value": "^", +} +``` + +### SET + +Contains a key `set` specifying what tokens are allowed and a key `not` specifying if the set should be negated. A set can contain other sets, ranges, and characters. + +```js +{ + "type": ret.types.SET, + "set": [token1, token2...], + "not": false, +} +``` + +### RANGE + +Used in set tokens to specify a character range. `from` and `to` are character codes. + +```js +{ + "type": ret.types.RANGE, + "from": 97, + "to": 122, +} +``` + +### REPETITION + +```js +{ + "type": ret.types.REPETITION, + "min": 0, + "max": Infinity, + "value": token, +} +``` + +### REFERENCE + +References a group token. `value` is 1-9. + +```js +{ + "type": ret.types.REFERENCE, + "value": 1, +} +``` + +### CHAR + +Represents a single character token. `value` is the character code. This might seem a bit cluttering instead of concatenating characters together. But since repetition tokens only repeat the last token and not the last clause like the pipe, it's simpler to do it this way. + +```js +{ + "type": ret.types.CHAR, + "value": 123, +} +``` + +## Errors + +ret.js will throw errors if given a string with an invalid regular expression. All possible errors are + +* Invalid group. When a group with an immediate `?` character is followed by an invalid character. It can only be followed by `!`, `=`, or `:`. Example: `/(?_abc)/` +* Nothing to repeat. Thrown when a repetitional token is used as the first token in the current clause, as in right in the beginning of the regexp or group, or right after a pipe. Example: `/foo|?bar/`, `/{1,3}foo|bar/`, `/foo(+bar)/` +* Unmatched ). A group was not opened, but was closed. Example: `/hello)2u/` +* Unterminated group. A group was not closed. Example: `/(1(23)4/` +* Unterminated character class. A custom character set was not closed. Example: `/[abc/` + + +# Install + + npm install ret + + +# Tests + +Tests are written with [vows](http://vowsjs.org/) + +```bash +npm test +``` + +# License + +MIT diff --git a/node_modules/ret/lib/index.js b/node_modules/ret/lib/index.js new file mode 100644 index 0000000..0e151c3 --- /dev/null +++ b/node_modules/ret/lib/index.js @@ -0,0 +1,282 @@ +var util = require('./util'); +var types = require('./types'); +var sets = require('./sets'); +var positions = require('./positions'); + + +module.exports = function(regexpStr) { + var i = 0, l, c, + start = { type: types.ROOT, stack: []}, + + // Keep track of last clause/group and stack. + lastGroup = start, + last = start.stack, + groupStack = []; + + + var repeatErr = function(i) { + util.error(regexpStr, 'Nothing to repeat at column ' + (i - 1)); + }; + + // Decode a few escaped characters. + var str = util.strToChars(regexpStr); + l = str.length; + + // Iterate through each character in string. + while (i < l) { + c = str[i++]; + + switch (c) { + // Handle escaped characters, inclues a few sets. + case '\\': + c = str[i++]; + + switch (c) { + case 'b': + last.push(positions.wordBoundary()); + break; + + case 'B': + last.push(positions.nonWordBoundary()); + break; + + case 'w': + last.push(sets.words()); + break; + + case 'W': + last.push(sets.notWords()); + break; + + case 'd': + last.push(sets.ints()); + break; + + case 'D': + last.push(sets.notInts()); + break; + + case 's': + last.push(sets.whitespace()); + break; + + case 'S': + last.push(sets.notWhitespace()); + break; + + default: + // Check if c is integer. + // In which case it's a reference. + if (/\d/.test(c)) { + last.push({ type: types.REFERENCE, value: parseInt(c, 10) }); + + // Escaped character. + } else { + last.push({ type: types.CHAR, value: c.charCodeAt(0) }); + } + } + + break; + + + // Positionals. + case '^': + last.push(positions.begin()); + break; + + case '$': + last.push(positions.end()); + break; + + + // Handle custom sets. + case '[': + // Check if this class is 'anti' i.e. [^abc]. + var not; + if (str[i] === '^') { + not = true; + i++; + } else { + not = false; + } + + // Get all the characters in class. + var classTokens = util.tokenizeClass(str.slice(i), regexpStr); + + // Increase index by length of class. + i += classTokens[1]; + last.push({ + type: types.SET, + set: classTokens[0], + not: not, + }); + + break; + + + // Class of any character except \n. + case '.': + last.push(sets.anyChar()); + break; + + + // Push group onto stack. + case '(': + // Create group. + var group = { + type: types.GROUP, + stack: [], + remember: true, + }; + + c = str[i]; + + // If if this is a special kind of group. + if (c === '?') { + c = str[i + 1]; + i += 2; + + // Match if followed by. + if (c === '=') { + group.followedBy = true; + + // Match if not followed by. + } else if (c === '!') { + group.notFollowedBy = true; + + } else if (c !== ':') { + util.error(regexpStr, + 'Invalid group, character \'' + c + + '\' after \'?\' at column ' + (i - 1)); + } + + group.remember = false; + } + + // Insert subgroup into current group stack. + last.push(group); + + // Remember the current group for when the group closes. + groupStack.push(lastGroup); + + // Make this new group the current group. + lastGroup = group; + last = group.stack; + break; + + + // Pop group out of stack. + case ')': + if (groupStack.length === 0) { + util.error(regexpStr, 'Unmatched ) at column ' + (i - 1)); + } + lastGroup = groupStack.pop(); + + // Check if this group has a PIPE. + // To get back the correct last stack. + last = lastGroup.options ? + lastGroup.options[lastGroup.options.length - 1] : lastGroup.stack; + break; + + + // Use pipe character to give more choices. + case '|': + // Create array where options are if this is the first PIPE + // in this clause. + if (!lastGroup.options) { + lastGroup.options = [lastGroup.stack]; + delete lastGroup.stack; + } + + // Create a new stack and add to options for rest of clause. + var stack = []; + lastGroup.options.push(stack); + last = stack; + break; + + + // Repetition. + // For every repetition, remove last element from last stack + // then insert back a RANGE object. + // This design is chosen because there could be more than + // one repetition symbols in a regex i.e. `a?+{2,3}`. + case '{': + var rs = /^(\d+)(,(\d+)?)?\}/.exec(str.slice(i)), min, max; + if (rs !== null) { + if (last.length === 0) { + repeatErr(i); + } + min = parseInt(rs[1], 10); + max = rs[2] ? rs[3] ? parseInt(rs[3], 10) : Infinity : min; + i += rs[0].length; + + last.push({ + type: types.REPETITION, + min: min, + max: max, + value: last.pop(), + }); + } else { + last.push({ + type: types.CHAR, + value: 123, + }); + } + break; + + case '?': + if (last.length === 0) { + repeatErr(i); + } + last.push({ + type: types.REPETITION, + min: 0, + max: 1, + value: last.pop(), + }); + break; + + case '+': + if (last.length === 0) { + repeatErr(i); + } + last.push({ + type: types.REPETITION, + min: 1, + max: Infinity, + value: last.pop(), + }); + break; + + case '*': + if (last.length === 0) { + repeatErr(i); + } + last.push({ + type: types.REPETITION, + min: 0, + max: Infinity, + value: last.pop(), + }); + break; + + + // Default is a character that is not `\[](){}?+*^$`. + default: + last.push({ + type: types.CHAR, + value: c.charCodeAt(0), + }); + } + + } + + // Check if any groups have not been closed. + if (groupStack.length !== 0) { + util.error(regexpStr, 'Unterminated group'); + } + + return start; +}; + +module.exports.types = types; diff --git a/node_modules/ret/lib/positions.js b/node_modules/ret/lib/positions.js new file mode 100644 index 0000000..80677ee --- /dev/null +++ b/node_modules/ret/lib/positions.js @@ -0,0 +1,17 @@ +var types = require('./types'); + +exports.wordBoundary = function() { + return { type: types.POSITION, value: 'b' }; +}; + +exports.nonWordBoundary = function() { + return { type: types.POSITION, value: 'B' }; +}; + +exports.begin = function() { + return { type: types.POSITION, value: '^' }; +}; + +exports.end = function() { + return { type: types.POSITION, value: '$' }; +}; diff --git a/node_modules/ret/lib/sets.js b/node_modules/ret/lib/sets.js new file mode 100644 index 0000000..5fb6be5 --- /dev/null +++ b/node_modules/ret/lib/sets.js @@ -0,0 +1,82 @@ +var types = require('./types'); + +var INTS = function() { + return [{ type: types.RANGE , from: 48, to: 57 }]; +}; + +var WORDS = function() { + return [ + { type: types.CHAR, value: 95 }, + { type: types.RANGE, from: 97, to: 122 }, + { type: types.RANGE, from: 65, to: 90 } + ].concat(INTS()); +}; + +var WHITESPACE = function() { + return [ + { type: types.CHAR, value: 9 }, + { type: types.CHAR, value: 10 }, + { type: types.CHAR, value: 11 }, + { type: types.CHAR, value: 12 }, + { type: types.CHAR, value: 13 }, + { type: types.CHAR, value: 32 }, + { type: types.CHAR, value: 160 }, + { type: types.CHAR, value: 5760 }, + { type: types.CHAR, value: 6158 }, + { type: types.CHAR, value: 8192 }, + { type: types.CHAR, value: 8193 }, + { type: types.CHAR, value: 8194 }, + { type: types.CHAR, value: 8195 }, + { type: types.CHAR, value: 8196 }, + { type: types.CHAR, value: 8197 }, + { type: types.CHAR, value: 8198 }, + { type: types.CHAR, value: 8199 }, + { type: types.CHAR, value: 8200 }, + { type: types.CHAR, value: 8201 }, + { type: types.CHAR, value: 8202 }, + { type: types.CHAR, value: 8232 }, + { type: types.CHAR, value: 8233 }, + { type: types.CHAR, value: 8239 }, + { type: types.CHAR, value: 8287 }, + { type: types.CHAR, value: 12288 }, + { type: types.CHAR, value: 65279 } + ]; +}; + +var NOTANYCHAR = function() { + return [ + { type: types.CHAR, value: 10 }, + { type: types.CHAR, value: 13 }, + { type: types.CHAR, value: 8232 }, + { type: types.CHAR, value: 8233 }, + ]; +}; + +// Predefined class objects. +exports.words = function() { + return { type: types.SET, set: WORDS(), not: false }; +}; + +exports.notWords = function() { + return { type: types.SET, set: WORDS(), not: true }; +}; + +exports.ints = function() { + return { type: types.SET, set: INTS(), not: false }; +}; + +exports.notInts = function() { + return { type: types.SET, set: INTS(), not: true }; +}; + +exports.whitespace = function() { + return { type: types.SET, set: WHITESPACE(), not: false }; +}; + +exports.notWhitespace = function() { + return { type: types.SET, set: WHITESPACE(), not: true }; +}; + +exports.anyChar = function() { + return { type: types.SET, set: NOTANYCHAR(), not: true }; +}; diff --git a/node_modules/ret/lib/types.js b/node_modules/ret/lib/types.js new file mode 100644 index 0000000..9484145 --- /dev/null +++ b/node_modules/ret/lib/types.js @@ -0,0 +1,10 @@ +module.exports = { + ROOT : 0, + GROUP : 1, + POSITION : 2, + SET : 3, + RANGE : 4, + REPETITION : 5, + REFERENCE : 6, + CHAR : 7, +}; diff --git a/node_modules/ret/lib/util.js b/node_modules/ret/lib/util.js new file mode 100644 index 0000000..97d8cf5 --- /dev/null +++ b/node_modules/ret/lib/util.js @@ -0,0 +1,111 @@ +var types = require('./types'); +var sets = require('./sets'); + + +// All of these are private and only used by randexp. +// It's assumed that they will always be called with the correct input. + +var CTRL = '@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ ?'; +var SLSH = { '0': 0, 't': 9, 'n': 10, 'v': 11, 'f': 12, 'r': 13 }; + +/** + * Finds character representations in str and convert all to + * their respective characters + * + * @param {String} str + * @return {String} + */ +exports.strToChars = function(str) { + /* jshint maxlen: false */ + var chars_regex = /(\[\\b\])|(\\)?\\(?:u([A-F0-9]{4})|x([A-F0-9]{2})|(0?[0-7]{2})|c([@A-Z\[\\\]\^?])|([0tnvfr]))/g; + str = str.replace(chars_regex, function(s, b, lbs, a16, b16, c8, dctrl, eslsh) { + if (lbs) { + return s; + } + + var code = b ? 8 : + a16 ? parseInt(a16, 16) : + b16 ? parseInt(b16, 16) : + c8 ? parseInt(c8, 8) : + dctrl ? CTRL.indexOf(dctrl) : + SLSH[eslsh]; + + var c = String.fromCharCode(code); + + // Escape special regex characters. + if (/[\[\]{}\^$.|?*+()]/.test(c)) { + c = '\\' + c; + } + + return c; + }); + + return str; +}; + + +/** + * turns class into tokens + * reads str until it encounters a ] not preceeded by a \ + * + * @param {String} str + * @param {String} regexpStr + * @return {Array., Number>} + */ +exports.tokenizeClass = function(str, regexpStr) { + /* jshint maxlen: false */ + var tokens = []; + var regexp = /\\(?:(w)|(d)|(s)|(W)|(D)|(S))|((?:(?:\\)(.)|([^\]\\]))-(?:\\)?([^\]]))|(\])|(?:\\)?(.)/g; + var rs, c; + + + while ((rs = regexp.exec(str)) != null) { + if (rs[1]) { + tokens.push(sets.words()); + + } else if (rs[2]) { + tokens.push(sets.ints()); + + } else if (rs[3]) { + tokens.push(sets.whitespace()); + + } else if (rs[4]) { + tokens.push(sets.notWords()); + + } else if (rs[5]) { + tokens.push(sets.notInts()); + + } else if (rs[6]) { + tokens.push(sets.notWhitespace()); + + } else if (rs[7]) { + tokens.push({ + type: types.RANGE, + from: (rs[8] || rs[9]).charCodeAt(0), + to: rs[10].charCodeAt(0), + }); + + } else if (c = rs[12]) { + tokens.push({ + type: types.CHAR, + value: c.charCodeAt(0), + }); + + } else { + return [tokens, regexp.lastIndex]; + } + } + + exports.error(regexpStr, 'Unterminated character class'); +}; + + +/** + * Shortcut to throw errors. + * + * @param {String} regexp + * @param {String} msg + */ +exports.error = function(regexp, msg) { + throw new SyntaxError('Invalid regular expression: /' + regexp + '/: ' + msg); +}; diff --git a/node_modules/ret/package.json b/node_modules/ret/package.json new file mode 100644 index 0000000..0da2d07 --- /dev/null +++ b/node_modules/ret/package.json @@ -0,0 +1,67 @@ +{ + "_from": "ret@~0.1.10", + "_id": "ret@0.1.15", + "_inBundle": false, + "_integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "_location": "/ret", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "ret@~0.1.10", + "name": "ret", + "escapedName": "ret", + "rawSpec": "~0.1.10", + "saveSpec": null, + "fetchSpec": "~0.1.10" + }, + "_requiredBy": [ + "/randexp" + ], + "_resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "_shasum": "b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc", + "_spec": "ret@~0.1.10", + "_where": "/Users/dletta/Documents/GitHub/conceptGraph/node_modules/randexp", + "author": { + "name": "Roly Fentanes", + "url": "https://github.com/fent" + }, + "bugs": { + "url": "https://github.com/fent/ret.js/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Tokenizes a string that represents a regular expression.", + "devDependencies": { + "istanbul": "*", + "vows": "*" + }, + "directories": { + "lib": "./lib" + }, + "engines": { + "node": ">=0.12" + }, + "files": [ + "lib" + ], + "homepage": "https://github.com/fent/ret.js#readme", + "keywords": [ + "regex", + "regexp", + "regular expression", + "parser", + "tokenizer" + ], + "license": "MIT", + "main": "./lib/index.js", + "name": "ret", + "repository": { + "type": "git", + "url": "git://github.com/fent/ret.js.git" + }, + "scripts": { + "test": "istanbul cover vows -- --spec test/*-test.js" + }, + "version": "0.1.15" +} diff --git a/node_modules/semver/LICENSE b/node_modules/semver/LICENSE new file mode 100644 index 0000000..19129e3 --- /dev/null +++ b/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/node_modules/semver/README.md b/node_modules/semver/README.md new file mode 100644 index 0000000..e0edbb7 --- /dev/null +++ b/node_modules/semver/README.md @@ -0,0 +1,399 @@ +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.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 http://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. + +#### 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. + +### 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. +* `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 `Integer.MAX_SAFE_INTEGER || (2**53 - 1)`; +higher value components are invalid (`9999999999999999.4.7.4` is likely invalid). diff --git a/node_modules/semver/bin/semver b/node_modules/semver/bin/semver new file mode 100755 index 0000000..9100ed4 --- /dev/null +++ b/node_modules/semver/bin/semver @@ -0,0 +1,153 @@ +#!/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) + , versions = [] + , range = [] + , gt = [] + , lt = [] + , eq = [] + , inc = null + , version = require("../package.json").version + , loose = false + , includePrerelease = false + , coerce = false + , identifier = undefined + , semver = require("../semver") + , reverse = false + , options = {} + +main() + +function main () { + if (!argv.length) return help() + while (argv.length) { + var a = argv.shift() + var i = a.indexOf('=') + if (i !== -1) { + a = a.slice(0, i) + argv.unshift(a.slice(i + 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 http://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/node_modules/semver/package.json b/node_modules/semver/package.json new file mode 100644 index 0000000..0a35e1b --- /dev/null +++ b/node_modules/semver/package.json @@ -0,0 +1,54 @@ +{ + "_from": "semver@^5.4.1", + "_id": "semver@5.6.0", + "_inBundle": false, + "_integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "_location": "/semver", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "semver@^5.4.1", + "name": "semver", + "escapedName": "semver", + "rawSpec": "^5.4.1", + "saveSpec": null, + "fetchSpec": "^5.4.1" + }, + "_requiredBy": [ + "/nearley" + ], + "_resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "_shasum": "7e74256fbaa49c75aa7c7a205cc22799cac80004", + "_spec": "semver@^5.4.1", + "_where": "/Users/dletta/Documents/GitHub/conceptGraph/node_modules/nearley", + "bin": { + "semver": "./bin/semver" + }, + "bugs": { + "url": "https://github.com/npm/node-semver/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "The semantic version parser used by npm.", + "devDependencies": { + "tap": "^12.0.1" + }, + "files": [ + "bin", + "range.bnf", + "semver.js" + ], + "homepage": "https://github.com/npm/node-semver#readme", + "license": "ISC", + "main": "semver.js", + "name": "semver", + "repository": { + "type": "git", + "url": "git+https://github.com/npm/node-semver.git" + }, + "scripts": { + "test": "tap test/*.js --cov -J" + }, + "version": "5.6.0" +} diff --git a/node_modules/semver/range.bnf b/node_modules/semver/range.bnf new file mode 100644 index 0000000..d4c6ae0 --- /dev/null +++ b/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/node_modules/semver/semver.js b/node_modules/semver/semver.js new file mode 100644 index 0000000..0cc5735 --- /dev/null +++ b/node_modules/semver/semver.js @@ -0,0 +1,1352 @@ +exports = module.exports = SemVer; + +// The debug function is excluded entirely from the minified version. +/* nomin */ var debug; +/* nomin */ if (typeof process === 'object' && + /* nomin */ process.env && + /* nomin */ process.env.NODE_DEBUG && + /* nomin */ /\bsemver\b/i.test(process.env.NODE_DEBUG)) + /* nomin */ debug = function() { + /* nomin */ var args = Array.prototype.slice.call(arguments, 0); + /* nomin */ args.unshift('SEMVER'); + /* nomin */ console.log.apply(console, args); + /* nomin */ }; +/* nomin */ else + /* nomin */ 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 || 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); + if (v1.prerelease.length || v2.prerelease.length) { + for (var key in v1) { + if (key === 'major' || key === 'minor' || key === 'patch') { + if (v1[key] !== v2[key]) { + return 'pre'+key; + } + } + } + return 'prerelease'; + } + for (var key in v1) { + if (key === 'major' || key === 'minor' || key === 'patch') { + if (v1[key] !== v2[key]) { + return key; + } + } + } + } +} + +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 (anum && !bnum) ? -1 : + (bnum && !anum) ? 1 : + a < b ? -1 : + a > b ? 1 : + 0; +} + +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) { + var ret; + switch (op) { + case '===': + if (typeof a === 'object') a = a.version; + if (typeof b === 'object') b = b.version; + ret = a === b; + break; + case '!==': + if (typeof a === 'object') a = a.version; + if (typeof b === 'object') b = b.version; + ret = a !== b; + break; + case '': case '=': case '==': ret = eq(a, b, loose); break; + case '!=': ret = neq(a, b, loose); break; + case '>': ret = gt(a, b, loose); break; + case '>=': ret = gte(a, b, loose); break; + case '<': ret = lt(a, b, loose); break; + case '<=': ret = lte(a, b, loose); break; + default: throw new TypeError('Invalid operator: ' + op); + } + return ret; +} + +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) { + if (!options || typeof options !== 'object') + options = { loose: !!options, includePrerelease: false } + 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); + if (pr.charAt(0) !== '-') + 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); + if (!options || typeof options !== 'object') + options = { loose: !!options, includePrerelease: false } + 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 (pr.charAt(0) !== '-') + 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(); + if (!options || typeof options !== 'object') + options = { loose: !!options, includePrerelease: false } + 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) { + // replace X with 0 + if (xm) + m = 0; + if (xp) + 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 if (xp) { + 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 (!options) + options = {} + + 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 (var 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.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] || '0') + '.' + (match[2] || '0') + '.' + (match[3] || '0')); +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..96442d1 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,59 @@ +{ + "name": "conceptgraph", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==" + }, + "discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=" + }, + "moo": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.4.3.tgz", + "integrity": "sha512-gFD2xGCl8YFgGHsqJ9NKRVdwlioeW3mI1iqfLNYQOv0+6JRwG58Zk9DIGQgyIaffSYaO1xsKnMaYzzNr1KyIAw==" + }, + "nearley": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.16.0.tgz", + "integrity": "sha512-Tr9XD3Vt/EujXbZBv6UAHYoLUSMQAxSsTnm9K3koXzjzNWY195NqALeyrzLZBKzAkL3gl92BcSogqrHjD8QuUg==", + "requires": { + "commander": "^2.19.0", + "moo": "^0.4.3", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6", + "semver": "^5.4.1" + } + }, + "railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=" + }, + "randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "requires": { + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..8463f1b --- /dev/null +++ b/package.json @@ -0,0 +1,30 @@ +{ + "name": "conceptgraph", + "version": "1.0.0", + "description": "Conceptual Graphs in Javascript", + "main": "main.js", + "directories": { + "lib": "lib" + }, + "dependencies": { + "nearley": "^2.16.0" + }, + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Dletta/conceptGraph.git" + }, + "keywords": [ + "concept", + "graphs" + ], + "author": "Jachen Duschletta, Jacob Friedman, Levi Roberts", + "license": "MIT", + "bugs": { + "url": "https://github.com/Dletta/conceptGraph/issues" + }, + "homepage": "https://github.com/Dletta/conceptGraph#readme" +}