Aperçu

node_modules Ajv logo

 

Ajv JSON schema validator

The fastest JSON validator for Node.js and browser.

Supports JSON Schema draft-04/06/07/2019-09/2020-12 (draft-04 support requires ajv-draft-04 package) and JSON Type Definition RFC8927.

build npm npm downloads Coverage Status SimpleX Gitter GitHub Sponsors

Ajv sponsors#

Mozilla

Microsoft

RetoolTideliftSimpleX

Contributing#

More than 100 people contributed to Ajv, and we would love to have you join the development. We welcome implementing new features that will benefit many users and ideas to improve our documentation.

Please review Contributing guidelines and Code components.

Documentation#

All documentation is available on the Ajv website.

Some useful site links:

Please sponsor Ajv development#

Since I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!

Your continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.

Please sponsor Ajv via:

Thank you.

Open Collective sponsors#

Performance#

Ajv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.

Currently Ajv is the fastest and the most standard compliant validator according to these benchmarks:

Performance of different validators by json-schema-benchmark:

performance

Features#

Install#

To install version 8:

npm install ajv

Getting started#

Try it in the Node.js REPL: https://runkit.com/npm/ajv

In JavaScript:

// or ESM/TypeScript import
import Ajv from "ajv"
// Node.js require:
const Ajv = require("ajv")
 
const ajv = new Ajv() // options can be passed, e.g. {allErrors: true}
 
const schema = {
  type: "object",
  properties: {
    foo: {type: "integer"},
    bar: {type: "string"},
  },
  required: ["foo"],
  additionalProperties: false,
}
 
const data = {
  foo: 1,
  bar: "abc",
}
 
const validate = ajv.compile(schema)
const valid = validate(data)
if (!valid) console.log(validate.errors)

Learn how to use Ajv and see more examples in the Guide: getting started

Changes history#

See https://github.com/ajv-validator/ajv/releases

Please note: Changes in version 8.0.0

Version 7.0.0

Version 6.0.0.

Code of conduct#

Please review and follow the Code of conduct.

Please report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.

Security contact#

To report a security vulnerability, please use the Tidelift security contact. Tidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.

Open-source software support#

Ajv is a part of Tidelift subscription - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.

License#

MIT # ajv-formats

JSON Schema formats for Ajv

Build Status npm Gitter GitHub Sponsors

Usage#

// ESM/TypeScript import
import Ajv from "ajv"
import addFormats from "ajv-formats"
// Node.js require:
const Ajv = require("ajv")
const addFormats = require("ajv-formats")
 
const ajv = new Ajv()
addFormats(ajv)

Formats#

The package defines these formats:

See regular expressions used for format validation and the sources that were used in formats.ts.

Please note: JSON Schema draft-07 also defines formats iri, iri-reference, idn-hostname and idn-email for URLs, hostnames and emails with international characters. These formats are available in ajv-formats-draft2019 plugin.

Keywords to compare values: formatMaximum / formatMinimum and formatExclusiveMaximum / formatExclusiveMinimum#

These keywords allow to define minimum/maximum constraints when the format keyword defines ordering (compare function in format definition).

These keywords are added to ajv instance when ajv-formats is used without options or with option keywords: true.

These keywords apply only to strings. If the data is not a string, the validation succeeds.

The value of keywords formatMaximum/formatMinimum and formatExclusiveMaximum/formatExclusiveMinimum should be a string or $data reference. This value is the maximum (minimum) allowed value for the data to be valid as determined by format keyword. If format keyword is not present schema compilation will throw exception.

When these keyword are added, they also add comparison functions to formats "date", "time" and "date-time". User-defined formats also can have comparison functions. See addFormat method.

require("ajv-formats")(ajv)
 
const schema = {
  type: "string",
  format: "date",
  formatMinimum: "2016-02-06",
  formatExclusiveMaximum: "2016-12-27",
}
 
const validDataList = ["2016-02-06", "2016-12-26"]
 
const invalidDataList = ["2016-02-05", "2016-12-27", "abc"]

Options#

Options can be passed via the second parameter. Options value can be

  1. The list of format names that will be added to ajv instance:
addFormats(ajv, ["date", "time"])

Please note: when ajv encounters an undefined format it throws exception (unless ajv instance was configured with strict: false option). To allow specific undefined formats they have to be passed to ajv instance via formats option with true value:

const ajv = new Ajv((formats: {date: true, time: true})) // to ignore "date" and "time" formats in schemas.
  1. Format validation mode (default is "full") with optional list of format names and keywords option to add additional format comparison keywords:
addFormats(ajv, {mode: "fast"})

or

addFormats(ajv, {mode: "fast", formats: ["date", "time"], keywords: true})

In "fast" mode the following formats are simplified: "date", "time", "date-time", "iso-time", "iso-date-time", "uri", "uri-reference", "email". For example, "date", "time" and "date-time" do not validate ranges in "fast" mode, only string structure, and other formats have simplified regular expressions.

Tests#

npm install
git submodule update --init
npm test

License#

MIT # ajv-formats-draft2019

An AJV plugin adding support for draft2019 formats missing from AJV.

Currently, iri, iri-reference, idn-email, idn-hostname, and duration formats are supported. duration was added in draft 2019. The uuid format was added in draft2019, but is already supported by the ajv-formats package.

Node.js CI

Using international formats with pre-draft2019 JSON schemas#

The idn-email and idn-hostname formats are implemented per RFC 1123, however earlier JSON schemas specify RFC 1034. This is probably just fine, but you have been warned...

Installation#

npm install --save ajv-formats-draft2019

Usage#

The default export is an apply function that patches an existing instance of ajv.

const Ajv = require('ajv');
const apply = require('ajv-formats-draft2019');
const ajv = new Ajv();
apply(ajv); // returns ajv instance, allowing chaining
 
let schema = {
  type: 'string',
  format: 'idn-email',
};
ajv.validate(schema, 'квіточка@пошта.укр'); // returns true

The apply function also accepts a second optional parameter to specify which formats to add to the ajv instance.

const Ajv = require('ajv');
const apply = require('ajv-formats-draft2019');
const ajv = new Ajv();
 
// Install only the idn-email and iri formats
apply(ajv, { formats: ['idn-email', 'iri'] });

The module also provides an alternate entrypoint ajv-formats-draft2019/formats that works with the ajv constructor to add the formats to new instances.

const Ajv = require('ajv');
const formats = require('ajv-formats-draft2019/formats');
const ajv = new Ajv({ formats });
 
let schema = {
  type: 'string',
  format: 'idn-email',
};
ajv.validate(schema, 'квіточка@пошта.укр'); // returns true

Using the ajv-formats-draft2019/formats entry point also allows cherry picking formats. Note the approach below only works for formats that don't contain a hypen - in the name. This approach may yield smaller packed bundles since it allows tree-shaking to remove unwanted validators and related dependencies.

const Ajv = require('ajv');
const { duration, iri } = require('ajv-formats-draft2019/formats');
const ajv = new Ajv({ formats: { duration, iri } });

International formats#

The library also provides an idn export to load only the international formats (ie. iri, iri-reference, idn-hostname and idn-email).

const Ajv = require('ajv');
const formats = require('ajv-formats-draft2019/idn');
const ajv = new Ajv({ formats });

Formats#

iri#

The string is parsed with 'uri-js' and the scheme is checked against the list of known IANA schemes. If it's a 'mailto' schemes, all of the to: addresses are validated, otherwise we check there IRI includes a path and is an absolute reference.

iri-reference#

All valid IRIs are valid. Fragments must have a valid path and of type "relative", "same-document" or "uri". If there is a scheme, it must be valid.

Validating a IRI references is challenging since the syntax is so permissive. Basically, any URL-safe string is a valid IRI syntactically. I struggled to find negative test cases when writing the unit tests for IRI-references. Consider:

  • google.com is NOT a valid IRI because it does not include a scheme.
  • file.txt is a valid IRI-reference
  • /this:that is a valid IRI-reference
  • this:that is a NOT a valid IRI-reference

idn-email#

smtp-address-parser is used to check the validity of the email.

idn-hostname#

The hostname is converted to ascii with punycode and checked for a valid tld.

duration#

The string is checked against a regex.

Releases#

v1.6.1#

  • Updated schemes dependency, adding support for modbus+tcp and mqtt in URIs.

v1.6.0#

  • Fix tests to work with AJV v7+ and how ajv is exported, rather than changes to this library.

v1.5.0#

  • Upgrade dependencies

v1.4.4#

  • The last release that's compatible with Node 8.

  • Fixed a bug when validated mailto: IRIs. 2.20.3 / 2019-10-11 ==================

    • Support Node.js 0.10 (Revert #1059)
    • Ran "npm unpublish commander@2.20.2". There is no 2.20.2.

2.20.1 / 2019-09-29#

  • Improve executable subcommand tracking
  • Update dev dependencies

2.20.0 / 2019-04-02#

  • fix: resolve symbolic links completely when hunting for subcommands (#935)
  • Update index.d.ts (#930)
  • Update Readme.md (#924)
  • Remove --save option as it isn't required anymore (#918)
  • Add link to the license file (#900)
  • Added example of receiving args from options (#858)
  • Added missing semicolon (#882)
  • Add extension to .eslintrc (#876)

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 # Commander.js

Build Status NPM Version NPM Downloads Install Size Join the chat at https://gitter.im/tj/commander.js

The complete solution for node.js command-line interfaces, inspired by Ruby's commander.
API documentation

Installation#

$ npm install commander

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.

#!/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.

#!/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');

To get string arguments from options you will need to use angle brackets <> for required inputs or square brackets [] for optional inputs.

e.g. .option('-m --myarg [myVar]', 'my super cool description')

Then to access the input if it was passed in.

e.g. var myInput = program.myarg

NOTE: If you pass a argument without using brackets the example above will return true and not the value passed in.

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.

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.

#!/usr/bin/env node
 
var program = require('commander');
 
program
  .command('rm <dir>')
  .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#

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] <file ...>')
  .option('-i, --integer <n>', 'An integer argument', parseInt)
  .option('-f, --float <n>', 'A float argument', parseFloat)
  .option('-r, --range <a>..<b>', 'A range', range)
  .option('-l, --list <items>', '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#

program
  .version('0.1.0')
  .option('-s --size <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:

#!/usr/bin/env node
 
/**
 * Module dependencies.
 */
 
var program = require('commander');
 
program
  .version('0.1.0')
  .command('rmdir <dir> [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#

#!/usr/bin/env node
 
var program = require('commander');
 
program
  .version('0.1.0')
  .arguments('<cmd> [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. <cmd>) indicate required input. Square brackets (e.g. [env]) indicate optional input.

Git-style sub-commands#

// 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 <type>  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.

#!/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:

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.

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#

var program = require('commander');
 
program
  .version('0.1.0')
  .option('-C, --chdir <path>', 'change the working directory')
  .option('-c, --config <path>', '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 <cmd>')
  .alias('ex')
  .description('execute the given remote cmd')
  .option("-e, --exec_mode <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 directory.

License#

MIT discontinuous-range#

DiscontinuousRange(1, 10).subtract(4, 6); // [ 1-3, 7-10 ]

Build Status

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));

3.0.2 / 2018-07-19#

  • [Fix] Prevent merging __proto__ property (#48)
  • [Dev Deps] update eslint, @ljharb/eslint-config, tape
  • [Tests] up to node v10.7, v9.11, v8.11, v7.10, v6.14, v4.9; use nvm install-latest-npm

3.0.1 / 2017-04-27#

  • [Fix] deep extending should work with a non-object (#46)
  • [Dev Deps] update tape, eslint, @ljharb/eslint-config
  • [Tests] up to node v7.9, v6.10, v4.8; improve matrix
  • [Docs] Switch from vb.teelaun.ch to versionbadg.es for the npm version badge SVG.
  • [Docs] Add example to readme (#34)

3.0.0 / 2015-07-01#

  • [Possible breaking change] Use global "strict" directive (#32)
  • [Tests] int is an ES3 reserved word
  • [Tests] Test up to io.js v2.3
  • [Tests] Add npm run eslint
  • [Dev Deps] Update covert, jscs

2.0.1 / 2015-04-25#

  • Use an inline isArray check, for ES3 browsers. (#27)
  • Some old browsers fail when an identifier is toString
  • Test latest node and io.js versions on travis-ci; speed up builds
  • Add license info to package.json (#25)
  • Update tape, jscs
  • Adding a CHANGELOG

2.0.0 / 2014-10-01#

  • Increase code coverage to 100%; run code coverage as part of tests
  • Add npm run lint; Run linter as part of tests
  • Remove nodeType and setInterval checks in isPlainObject
  • Updating tape, jscs, covert
  • General style and README cleanup

1.3.0 / 2014-06-20#

  • Add component.json for browser support (#18)
  • Use SVG for badges in README (#16)
  • Updating tape, covert
  • Updating travis-ci to work with multiple node versions
  • Fix deep === false bug (returning target as {}) (#14)
  • Fixing constructor checks in isPlainObject
  • Adding additional test coverage
  • Adding npm run coverage
  • Add LICENSE (#13)
  • Adding a warning about false, per #11
  • General style and whitespace cleanup

1.2.1 / 2013-09-14#

  • Fixing hasOwnProperty bugs that would only have shown up in specific browsers. Fixes #8
  • Updating tape

1.2.0 / 2013-09-02#

  • Updating the README: add badges
  • Adding a missing variable reference.
  • Using tape instead of buster for tests; add more tests (#7)
  • Adding node 0.10 to Travis CI (#6)
  • Enabling "npm test" and cleaning up package.json (#5)
  • Add Travis CI.

1.1.3 / 2012-12-06#

  • Added unit tests.
  • Ensure extend function is named. (Looks nicer in a stack trace.)
  • README cleanup.

1.1.1 / 2012-11-07#

  • README cleanup.
  • Added installation instructions.
  • Added a missing semicolon

1.0.0 / 2012-04-08#

  • Initial commit

Build Status dependency status dev dependency status

extend() for Node.js Version Badge#

node-extend is a port of the classic extend() method from jQuery. It behaves as you expect. It is simple, tried and true.

Notes:

  • Since Node.js >= 4, Object.assign now offers the same functionality natively (but without the "deep copy" option). See ECMAScript 2015 (ES6) in Node.js.
  • Some native implementations of Object.assign in both Node.js and many browsers (since NPM modules are for the browser too) may not be fully spec-compliant. Check object.assign module for a compliant candidate.

Installation#

This package is available on npm as: extend

npm install extend

Usage#

Syntax: extend ( [deep], target, object1, [objectN] )

Extend one object with one or more others, returning the modified object.

Example:

var extend = require('extend');
extend(targetObject, object1, object2);

Keep in mind that the target object will be modified, and will be returned from extend().

If a boolean true is specified as the first argument, extend performs a deep copy, recursively copying any objects it finds. Otherwise, the copy will share structure with the original object(s). Undefined properties are not copied. However, properties inherited from the object's prototype will be copied over. Warning: passing false as the first argument is not supported.

Arguments#

  • deep Boolean (optional) If set, the merge becomes recursive (i.e. deep copy).
  • target Object The object to extend.
  • object1 Object The object that will be merged into the first.
  • objectN Object (Optional) More objects to merge into the first.

License#

node-extend is licensed under the MIT License.

Acknowledgements#

All credit to the jQuery authors for perfecting this amazing utility.

Ported to Node.js by Stefan Thomas with contributions by Jonathan Buchanan and Jordan Harband.

# fast-deep-equal The fastest deep equal with ES6 Map, Set and Typed arrays support.

Build Status npm Coverage Status

Install#

npm install fast-deep-equal

Features#

  • ES5 compatible
  • works in node.js (8+) and browsers (IE9+)
  • checks equality of Date and RegExp objects by value.

ES6 equal (require('fast-deep-equal/es6')) also supports:

  • Maps
  • Sets
  • Typed arrays

Usage#

var equal = require('fast-deep-equal');
console.log(equal({foo: 'bar'}, {foo: 'bar'})); // true

To support ES6 Maps, Sets and Typed arrays equality use:

var equal = require('fast-deep-equal/es6');
console.log(equal(Int16Array([1, 2]), Int16Array([1, 2]))); // true

To use with React (avoiding the traversal of React elements' _owner property that contains circular references and is not needed when comparing the elements - borrowed from react-fast-compare):

var equal = require('fast-deep-equal/react');
var equal = require('fast-deep-equal/es6/react');

Performance benchmark#

Node.js v12.6.0:

fast-deep-equal x 261,950 ops/sec ±0.52% (89 runs sampled)
fast-deep-equal/es6 x 212,991 ops/sec ±0.34% (92 runs sampled)
fast-equals x 230,957 ops/sec ±0.83% (85 runs sampled)
nano-equal x 187,995 ops/sec ±0.53% (88 runs sampled)
shallow-equal-fuzzy x 138,302 ops/sec ±0.49% (90 runs sampled)
underscore.isEqual x 74,423 ops/sec ±0.38% (89 runs sampled)
lodash.isEqual x 36,637 ops/sec ±0.72% (90 runs sampled)
deep-equal x 2,310 ops/sec ±0.37% (90 runs sampled)
deep-eql x 35,312 ops/sec ±0.67% (91 runs sampled)
ramda.equals x 12,054 ops/sec ±0.40% (91 runs sampled)
util.isDeepStrictEqual x 46,440 ops/sec ±0.43% (90 runs sampled)
assert.deepStrictEqual x 456 ops/sec ±0.71% (88 runs sampled)

The fastest is fast-deep-equal

To run benchmark (requires node.js 6+):

npm run benchmark

Please note: this benchmark runs against the available test cases. To choose the most performant library for your application, it is recommended to benchmark against your data and to NOT expect this benchmark to reflect the performance difference in your application.

Enterprise support#

fast-deep-equal package is a part of Tidelift enterprise subscription - it provides a centralised commercial support to open-source software users, in addition to the support provided by software maintainers.

Security contact#

To report a security vulnerability, please use the Tidelift security contact. Tidelift will coordinate the fix and disclosure. Please do NOT report security vulnerability via GitHub issues.

License#

MIT # fast-uri

NPM version CI neostandard javascript style

Dependency-free RFC 3986 URI toolbox.

Usage#

Options#

All of the above functions can accept an additional options argument that is an object that can contain one or more of the following properties:

  • scheme (string) Indicates the scheme that the URI should be treated as, overriding the URI's normal scheme parsing behavior.

  • reference (string) If set to "suffix", it indicates that the URI is in the suffix format and the parser will use the option's scheme property to determine the URI's scheme.

  • tolerant (boolean, false) If set to true, the parser will relax URI resolving rules.

  • absolutePath (boolean, false) If set to true, the serializer will not resolve a relative path component.

  • unicodeSupport (boolean, false) If set to true, the parser will unescape non-ASCII characters in the parsed output as per RFC 3987.

  • domainHost (boolean, false) If set to true, the library will treat the host component as a domain name, and convert IDNs (International Domain Names) as per RFC 5891.

Parse#

const uri = require('fast-uri')
uri.parse('uri://user:pass@example.com:123/one/two.three?q1=a1&q2=a2#body')
// Output
{
  scheme: "uri",
  userinfo: "user:pass",
  host: "example.com",
  port: 123,
  path: "/one/two.three",
  query: "q1=a1&q2=a2",
  fragment: "body"
}

Serialize#

const uri = require('fast-uri')
uri.serialize({scheme: "http", host: "example.com", fragment: "footer"})
// Output
"http://example.com/#footer"
 

Resolve#

const uri = require('fast-uri')
uri.resolve("uri://a/b/c/d?q", "../../g")
// Output
"uri://a/g"

Equal#

const uri = require('fast-uri')
uri.equal("example://a/b/c/%7Bfoo%7D", "eXAMPLE://a/./b/../b/%63/%7bfoo%7d")
// Output
true

Scheme supports#

fast-uri supports inserting custom scheme-dependent processing rules. Currently, fast-uri has built-in support for the following schemes:

Benchmarks#

fast-uri benchmark
┌─────────┬──────────────────────────────────────────┬──────────────────┬──────────────────┬────────────────────────┬────────────────────────┬─────────┐
│ (index) │ Task name                                │ Latency avg (ns) │ Latency med (ns) │ Throughput avg (ops/s) │ Throughput med (ops/s) │ Samples │
├─────────┼──────────────────────────────────────────┼──────────────────┼──────────────────┼────────────────────────┼────────────────────────┼─────────┤
│ 0       │ 'fast-uri: parse domain'                 │ '951.31 ± 0.75%' │ '875.00 ± 11.00' │ '1122538 ± 0.01%'      │ '1142857 ± 14550'      │ 1051187 │
│ 1       │ 'fast-uri: parse IPv4'                   │ '443.44 ± 0.22%' │ '406.00 ± 3.00'  │ '2422762 ± 0.01%'      │ '2463054 ± 18335'      │ 2255105 │
│ 2       │ 'fast-uri: parse IPv6'                   │ '1241.6 ± 1.74%' │ '1131.0 ± 30.00' │ '875177 ± 0.02%'       │ '884173 ± 24092'       │ 805399  │
│ 3       │ 'fast-uri: parse URN'                    │ '689.19 ± 4.29%' │ '618.00 ± 9.00'  │ '1598373 ± 0.01%'      │ '1618123 ± 23913'      │ 1450972 │
│ 4       │ 'fast-uri: parse URN uuid'               │ '1025.4 ± 2.02%' │ '921.00 ± 19.00' │ '1072419 ± 0.02%'      │ '1085776 ± 22871'      │ 975236  │
│ 5       │ 'fast-uri: serialize uri'                │ '1028.5 ± 0.53%' │ '933.00 ± 43.00' │ '1063310 ± 0.02%'      │ '1071811 ± 50523'      │ 972249  │
│ 6       │ 'fast-uri: serialize long uri with dots' │ '1805.1 ± 0.52%' │ '1627.0 ± 17.00' │ '602620 ± 0.02%'       │ '614628 ± 6490'        │ 553997  │
│ 7       │ 'fast-uri: serialize IPv6'               │ '2569.4 ± 2.69%' │ '2302.0 ± 21.00' │ '426080 ± 0.03%'       │ '434405 ± 3999'        │ 389194  │
│ 8       │ 'fast-uri: serialize ws'                 │ '979.39 ± 0.43%' │ '882.00 ± 8.00'  │ '1111665 ± 0.02%'      │ '1133787 ± 10378'      │ 1021045 │
│ 9       │ 'fast-uri: resolve'                      │ '2208.2 ± 1.08%' │ '1980.0 ± 24.00' │ '495001 ± 0.03%'       │ '505051 ± 6049'        │ 452848  │
└─────────┴──────────────────────────────────────────┴──────────────────┴──────────────────┴────────────────────────┴────────────────────────┴─────────┘
uri-js benchmark
┌─────────┬───────────────────────────────────────┬──────────────────┬──────────────────┬────────────────────────┬────────────────────────┬─────────┐
│ (index) │ Task name                             │ Latency avg (ns) │ Latency med (ns) │ Throughput avg (ops/s) │ Throughput med (ops/s) │ Samples │
├─────────┼───────────────────────────────────────┼──────────────────┼──────────────────┼────────────────────────┼────────────────────────┼─────────┤
│ 0       │ 'urijs: parse domain'                 │ '3618.3 ± 0.43%' │ '3314.0 ± 33.00' │ '294875 ± 0.04%'       │ '301750 ± 2975'        │ 276375  │
│ 1       │ 'urijs: parse IPv4'                   │ '4024.1 ± 0.41%' │ '3751.0 ± 25.00' │ '261981 ± 0.04%'       │ '266596 ± 1789'        │ 248506  │
│ 2       │ 'urijs: parse IPv6'                   │ '5417.2 ± 0.46%' │ '4968.0 ± 43.00' │ '196023 ± 0.05%'       │ '201288 ± 1727'        │ 184598  │
│ 3       │ 'urijs: parse URN'                    │ '1324.2 ± 0.23%' │ '1229.0 ± 17.00' │ '801535 ± 0.02%'       │ '813670 ± 11413'       │ 755185  │
│ 4       │ 'urijs: parse URN uuid'               │ '1822.0 ± 3.08%' │ '1655.0 ± 15.00' │ '594433 ± 0.02%'       │ '604230 ± 5427'        │ 548843  │
│ 5       │ 'urijs: serialize uri'                │ '4196.8 ± 0.36%' │ '3908.0 ± 27.00' │ '251146 ± 0.04%'       │ '255885 ± 1756'        │ 238276  │
│ 6       │ 'urijs: serialize long uri with dots' │ '8331.0 ± 1.30%' │ '7658.0 ± 72.00' │ '126440 ± 0.07%'       │ '130582 ± 1239'        │ 120034  │
│ 7       │ 'urijs: serialize IPv6'               │ '5685.5 ± 0.30%' │ '5366.0 ± 33.00' │ '182632 ± 0.05%'       │ '186359 ± 1153'        │ 175886  │
│ 8       │ 'urijs: serialize ws'                 │ '4159.3 ± 0.20%' │ '3899.0 ± 28.00' │ '250459 ± 0.04%'       │ '256476 ± 1855'        │ 240423  │
│ 9       │ 'urijs: resolve'                      │ '6729.9 ± 0.39%' │ '6261.0 ± 37.00' │ '156361 ± 0.06%'       │ '159719 ± 949'         │ 148591  │
└─────────┴───────────────────────────────────────┴──────────────────┴──────────────────┴────────────────────────┴────────────────────────┴─────────┘
WHATWG URL benchmark
┌─────────┬────────────────────────────┬──────────────────┬──────────────────┬────────────────────────┬────────────────────────┬─────────┐
│ (index) │ Task name                  │ Latency avg (ns) │ Latency med (ns) │ Throughput avg (ops/s) │ Throughput med (ops/s) │ Samples │
├─────────┼────────────────────────────┼──────────────────┼──────────────────┼────────────────────────┼────────────────────────┼─────────┤
│ 0       │ 'WHATWG URL: parse domain' │ '475.22 ± 0.20%' │ '444.00 ± 5.00'  │ '2217599 ± 0.01%'      │ '2252252 ± 25652'      │ 2104289 │
│ 1       │ 'WHATWG URL: parse URN'    │ '384.78 ± 0.85%' │ '350.00 ± 5.00'  │ '2809071 ± 0.01%'      │ '2857143 ± 41408'      │ 2598885 │
└─────────┴────────────────────────────┴──────────────────┴──────────────────┴────────────────────────┴────────────────────────┴─────────┘

TODO#

  • Support MailTo
  • Be 100% iso compatible with uri-js

License#

Licensed under BSD-3-Clause. # json-schema-traverse Traverse JSON Schema passing each schema object to callback

build npm coverage

Install#

npm install json-schema-traverse

Usage#

const traverse = require('json-schema-traverse');
const schema = {
  properties: {
    foo: {type: 'string'},
    bar: {type: 'integer'}
  }
};
 
traverse(schema, {cb});
// cb is called 3 times with:
// 1. root schema
// 2. {type: 'string'}
// 3. {type: 'integer'}
 
// Or:
 
traverse(schema, {cb: {pre, post}});
// pre is called 3 times with:
// 1. root schema
// 2. {type: 'string'}
// 3. {type: 'integer'}
//
// post is called 3 times with:
// 1. {type: 'string'}
// 2. {type: 'integer'}
// 3. root schema
 

Callback function cb is called for each schema object (not including draft-06 boolean schemas), including the root schema, in pre-order traversal. Schema references ($ref) are not resolved, they are passed as is. Alternatively, you can pass a {pre, post} object as cb, and then pre will be called before traversing child elements, and post will be called after all child elements have been traversed.

Callback is passed these parameters:

  • schema: the current schema object
  • JSON pointer: from the root schema to the current schema object
  • root schema: the schema passed to traverse object
  • parent JSON pointer: from the root schema to the parent schema object (see below)
  • parent keyword: the keyword inside which this schema appears (e.g. properties, anyOf, etc.)
  • parent schema: not necessarily parent object/array; in the example above the parent schema for {type: 'string'} is the root schema
  • index/property: index or property name in the array/object containing multiple schemas; in the example above for {type: 'string'} the property name is 'foo'

Traverse objects in all unknown keywords#

const traverse = require('json-schema-traverse');
const schema = {
  mySchema: {
    minimum: 1,
    maximum: 2
  }
};
 
traverse(schema, {allKeys: true, cb});
// cb is called 2 times with:
// 1. root schema
// 2. mySchema

Without option allKeys: true callback will be called only with root schema.

Enterprise support#

json-schema-traverse package is a part of Tidelift enterprise subscription - it provides a centralised commercial support to open-source software users, in addition to the support provided by software maintainers.

Security contact#

To report a security vulnerability, please use the Tidelift security contact. Tidelift will coordinate the fix and disclosure. Please do NOT report security vulnerability via GitHub issues.

License#

MIT 

Moo!#

Moo is a highly-optimised tokenizer/lexer generator. Use it to tokenize your strings, before parsing 'em with a parser like nearley or whatever else you're into.

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.)

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. 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 <script> tag; moo is completely standalone.

Then you can start roasting your very own lexer/tokenizer:

    const moo = require('moo')
 
    let lexer = moo.compile({
      WS:      /[ \t]+/,
      comment: /\/\/.*?$/,
      number:  /0|[1-9][0-9]*/,
      string:  /"(?:\\["\\]|[^\n"\\])*"/,
      lparen:  '(',
      rparen:  ')',
      keyword: ['while', 'if', 'else', 'moo', 'cows'],
      NL:      { match: /\n/, lineBreaks: true },
    })

And now throw some text at it:

    lexer.reset('while (10) cows\nmoo')
    lexer.next() // -> { type: 'keyword', value: 'while' }
    lexer.next() // -> { type: 'WS', value: ' ' }
    lexer.next() // -> { type: 'lparen', value: '(' }
    lexer.next() // -> { type: 'number', value: '10' }
    // ...

When you reach the end of Moo's internal buffer, next() will return undefined. You can always reset() it and feed it more data when that happens.

On Regular Expressions#

RegExps are nifty for making tokenizers, but they can be a bit of a pain. Here are some things to be aware of:

  • You often want to use non-greedy quantifiers: e.g. *? instead of *. Otherwise your tokens will be longer than you expect:

    let lexer = moo.compile({
      string: /".*"/,   // greedy quantifier *
      // ...
    })
     
    lexer.reset('"foo" "bar"')
    lexer.next() // -> { type: 'string', value: 'foo" "bar' }

    Better:

    let lexer = moo.compile({
      string: /".*?"/,   // non-greedy quantifier *?
      // ...
    })
     
    lexer.reset('"foo" "bar"')
    lexer.next() // -> { type: 'string', value: 'foo' }
    lexer.next() // -> { type: 'space', value: ' ' }
    lexer.next() // -> { type: 'string', value: 'bar' }
  • The order of your rules matters. Earlier ones will take precedence.

    moo.compile({
        identifier:  /[a-z0-9]+/,
        number:  /[0-9]+/,
    }).reset('42').next() // -> { type: 'identifier', value: '42' }
     
    moo.compile({
        number:  /[0-9]+/,
        identifier:  /[a-z0-9]+/,
    }).reset('42').next() // -> { type: 'number', value: '42' }
  • Moo uses multiline RegExps. This has a few quirks: for example, the dot /./ doesn't include newlines. Use [^] instead if you want to match newlines too.

  • Since an excluding character ranges like /[^ ]/ (which matches anything but a space) will include newlines, you have to be careful not to include them by accident! In particular, the whitespace metacharacter \s includes newlines.

Line Numbers#

Moo tracks detailed information about the input for you.

It will track line numbers, as long as you apply the lineBreaks: true option to any rules which might contain newlines. Moo will try to warn you if you forget to do this.

Note that this is false by default, for performance reasons: counting the number of lines in a matched token has a small cost. For optimal performance, only match newlines inside a dedicated token:

    newline: {match: '\n', lineBreaks: true},

Token Info#

Token objects (returned from next()) have the following attributes:

  • type: the name of the group, as passed to compile.
  • text: the string that was matched.
  • value: the string that was matched, transformed by your value function (if any).
  • offset: the number of bytes from the start of the buffer where the match starts.
  • lineBreaks: the number of line breaks found in the match. (Always zero if this rule has lineBreaks: false.)
  • line: the line number of the beginning of the match, starting from 1.
  • col: the column where the match begins, starting from 1.

Value vs. Text#

The value is the same as the text, unless you provide a value transform.

const moo = require('moo')
 
const lexer = moo.compile({
  ws: /[ \t]+/,
  string: {match: /"(?:\\["\\]|[^\n"\\])*"/, value: s => s.slice(1, -1)},
})
 
lexer.reset('"test"')
lexer.next() /* { value: 'test', text: '"test"', ... } */

Reset#

Calling reset() on your lexer will empty its internal buffer, and set the line, column, and offset counts back to their initial value.

If you don't want this, you can save() the state, and later pass it as the second argument to reset() to explicitly control the internal state of the lexer.

    lexer.reset('some line\n')
    let info = lexer.save() // -> { line: 10 }
    lexer.next() // -> { line: 10 }
    lexer.next() // -> { line: 11 }
    // ...
    lexer.reset('a different line\n', info)
    lexer.next() // -> { line: 10 }

Keywords#

Moo makes it convenient to define literals.

    moo.compile({
      lparen:  '(',
      rparen:  ')',
      keyword: ['while', 'if', 'else', 'moo', 'cows'],
    })

It'll automatically compile them into regular expressions, escaping them where necessary.

Keywords should be written using the keywords transform.

    moo.compile({
      IDEN: {match: /[a-zA-Z]+/, type: moo.keywords({
        KW: ['while', 'if', 'else', 'moo', 'cows'],
      })},
      SPACE: {match: /\s+/, lineBreaks: true},
    })

Why?#

You need to do this to ensure the longest match principle applies, even in edge cases.

Imagine trying to parse the input className with the following rules:

    keyword: ['class'],
    identifier: /[a-zA-Z]+/,

You'll get two tokens — ['class', 'Name'] -- which is not what you want! If you swap the order of the rules, you'll fix this example; but now you'll lex class wrong (as an identifier).

The keywords helper checks matches against the list of keywords; if any of them match, it uses the type 'keyword' instead of 'identifier' (for this example).

Keyword Types#

Keywords can also have individual types.

    let lexer = moo.compile({
      name: {match: /[a-zA-Z]+/, type: moo.keywords({
        'kw-class': 'class',
        'kw-def': 'def',
        'kw-if': 'if',
      })},
      // ...
    })
    lexer.reset('def foo')
    lexer.next() // -> { type: 'kw-def', value: 'def' }
    lexer.next() // space
    lexer.next() // -> { type: 'name', value: 'foo' }

You can use Object.fromEntries to easily construct keyword objects:

Object.fromEntries(['class', 'def', 'if'].map(k => ['kw-' + k, k]))

States#

Moo allows you to define multiple lexer states. Each state defines its own separate set of token rules. Your lexer will start off in the first state given to moo.states({}).

Rules can be annotated with next, push, and pop, to change the current state after that token is matched. A "stack" of past states is kept, which is used by push and pop.

  • next: 'bar' moves to the state named bar. (The stack is not changed.)
  • push: 'bar' moves to the state named bar, and pushes the old state onto the stack.
  • pop: 1 removes one state from the top of the stack, and moves to that state. (Only 1 is supported.)

Only rules from the current state can be matched. You need to copy your rule into all the states you want it to be matched in.

For example, to tokenize JS-style string interpolation such as a${{c: d}}e, you might use:

    let lexer = moo.states({
      main: {
        strstart: {match: '`', push: 'lit'},
        ident:    /\w+/,
        lbrace:   {match: '{', push: 'main'},
        rbrace:   {match: '}', pop: 1},
        colon:    ':',
        space:    {match: /\s+/, lineBreaks: true},
      },
      lit: {
        interp:   {match: '${', push: 'main'},
        escape:   /\\./,
        strend:   {match: '`', pop: 1},
        const:    {match: /(?:[^$`]|\$(?!\{))+/, lineBreaks: true},
      },
    })
    // <= `a${{c: d}}e`
    // => strstart const interp lbrace ident colon space ident rbrace rbrace const strend

The rbrace rule is annotated with pop, so it moves from the main state into either lit or main, depending on the stack.

Errors#

If none of your rules match, Moo will throw an Error; since it doesn't know what else to do.

If you prefer, you can have moo return an error token instead of throwing an exception. The error token will contain the whole of the rest of the buffer.

    moo.compile({
      // ...
      myError: moo.error,
    })
 
    moo.reset('invalid')
    moo.next() // -> { type: 'myError', value: 'invalid', text: 'invalid', offset: 0, lineBreaks: 0, line: 1, col: 1 }
    moo.next() // -> undefined

You can have a token type that both matches tokens and contains error values.

    moo.compile({
      // ...
      myError: {match: /[\$?`]/, error: true},
    })

Formatting errors#

If you want to throw an error from your parser, you might find formatError helpful. Call it with the offending token:

throw new Error(lexer.formatError(token, "invalid syntax"))

It returns a string with a pretty error message.

Error: invalid syntax at line 2 col 15:

  totally valid `syntax`
                ^

Iteration#

Iterators: we got 'em.

    for (let here of lexer) {
      // here = { type: 'number', value: '123', ... }
    }

Create an array of tokens.

    let tokens = Array.from(lexer);

Use itt's iteration tools with Moo.

    for (let [here, next] of itt(lexer).lookahead()) { // pass a number if you need more tokens
      // enjoy!
    }

Transform#

Moo doesn't allow capturing groups, but you can supply a transform function, value(), which will be called on the value before storing it in the Token object.

    moo.compile({
      STRING: [
        {match: /"""[^]*?"""/, lineBreaks: true, value: x => x.slice(3, -3)},
        {match: /"(?:\\["\\rn]|[^"\\])*?"/, lineBreaks: true, value: x => x.slice(1, -1)},
        {match: /'(?:\\['\\rn]|[^'\\])*?'/, lineBreaks: true, value: x => x.slice(1, -1)},
      ],
      // ...
    })

Contributing#

Do check the FAQ.

Before submitting an issue, remember...

# nearley ↗️ JS.ORG npm version

nearley is a simple, fast and powerful parsing toolkit. It consists of:

  1. A powerful, modular DSL for describing languages
  2. An efficient, lightweight Earley parser
  3. Loads of tools, editor plug-ins, and other goodies!

nearley is a streaming parser with support for catching errors gracefully and providing all parsings for ambiguous grammars. It is compatible with a variety of lexers (we recommend moo). It comes with tools for creating tests, railroad diagrams and fuzzers from your grammars, and has support for a variety of editors and platforms. It works in both node and the browser.

Unlike most other parser generators, nearley can handle any grammar you can define in BNF (and more!). In particular, while most existing JS parsers such as PEGjs and Jison choke on certain grammars (e.g. left recursive ones), nearley handles them easily and efficiently by using the Earley parsing algorithm.

nearley is used by a wide variety of projects:

nearley is an npm staff pick.

Documentation#

Please visit our website https://nearley.js.org to get started! You will find a tutorial, detailed reference documents, and links to several real-world examples to get inspired.

Contributing#

Please read this document before working on nearley. If you are interested in contributing but unsure where to start, take a look at the issues labeled "up for grabs" on the issue tracker, or message a maintainer (@kach or @tjvr on Github).

nearley is MIT licensed.

A big thanks to Nathan Dinsmore for teaching me how to Earley, Aria Stewart for helping structure nearley into a mature module, and Robin Windels for bootstrapping the grammar. Additionally, Jacob Edelman wrote an experimental JavaScript parser with nearley and contributed ideas for EBNF support. Joshua T. Corbin refactored the compiler to be much, much prettier. Bojidar Marinov implemented postprocessors-in-other-languages. Shachar Itzhaky fixed a subtle bug with nullables.

Citing nearley#

If you are citing nearley in academic work, please use the following BibTeX entry.

@misc{nearley,
    author = "Kartik Chandra and Tim Radvan",
    title  = "{nearley}: a parsing toolkit for {JavaScript}",
    year   = {2014},
    doi    = {10.5281/zenodo.3897993},
    url    = {https://github.com/kach/nearley}
}

# Punycode.js punycode on npm

Punycode.js is a robust Punycode converter that fully complies to RFC 3492 and RFC 5891.

This JavaScript library is the result of comparing, optimizing and documenting different open-source implementations of the Punycode algorithm:

This project was bundled with Node.js from v0.6.2+ until v7 (soft-deprecated).

This project provides a CommonJS module that uses ES2015+ features and JavaScript module, which work in modern Node.js versions and browsers. For the old Punycode.js version that offers the same functionality in a UMD build with support for older pre-ES2015 runtimes, including Rhino, Ringo, and Narwhal, see v1.4.1.

Installation#

Via npm:

npm install punycode --save

In Node.js:

⚠️ Note that userland modules don't hide core modules. For example, require('punycode') still imports the deprecated core module even if you executed npm install punycode. Use require('punycode/') to import userland modules rather than core modules.

const punycode = require('punycode/');

API#

punycode.decode(string)#

Converts a Punycode string of ASCII symbols to a string of Unicode symbols.

// decode domain name parts
punycode.decode('maana-pta'); // 'mañana'
punycode.decode('--dqo34k'); // '☃-⌘'

punycode.encode(string)#

Converts a string of Unicode symbols to a Punycode string of ASCII symbols.

// encode domain name parts
punycode.encode('mañana'); // 'maana-pta'
punycode.encode('☃-⌘'); // '--dqo34k'

punycode.toUnicode(input)#

Converts a Punycode string representing a domain name or an email address to Unicode. Only the Punycoded parts of the input will be converted, i.e. it doesn’t matter if you call it on a string that has already been converted to Unicode.

// decode domain names
punycode.toUnicode('xn--maana-pta.com');
// → 'mañana.com'
punycode.toUnicode('xn----dqo34k.com');
// → '☃-⌘.com'
 
// decode email addresses
punycode.toUnicode('джумла@xn--p-8sbkgc5ag7bhce.xn--ba-lmcq');
// → 'джумла@джpумлатест.bрфa'

punycode.toASCII(input)#

Converts a lowercased Unicode string representing a domain name or an email address to Punycode. Only the non-ASCII parts of the input will be converted, i.e. it doesn’t matter if you call it with a domain that’s already in ASCII.

// encode domain names
punycode.toASCII('mañana.com');
// → 'xn--maana-pta.com'
punycode.toASCII('☃-⌘.com');
// → 'xn----dqo34k.com'
 
// encode email addresses
punycode.toASCII('джумла@джpумлатест.bрфa');
// → 'джумла@xn--p-8sbkgc5ag7bhce.xn--ba-lmcq'

punycode.ucs2#

punycode.ucs2.decode(string)#

Creates an array containing the numeric code point values of each Unicode symbol in the string. While JavaScript uses UCS-2 internally, this function will convert a pair of surrogate halves (each of which UCS-2 exposes as separate characters) into a single code point, matching UTF-16.

punycode.ucs2.decode('abc');
// → [0x61, 0x62, 0x63]
// surrogate pair for U+1D306 TETRAGRAM FOR CENTRE:
punycode.ucs2.decode('\uD834\uDF06');
// → [0x1D306]

punycode.ucs2.encode(codePoints)#

Creates a string based on an array of numeric code point values.

punycode.ucs2.encode([0x61, 0x62, 0x63]);
// → 'abc'
punycode.ucs2.encode([0x1D306]);
// → '\uD834\uDF06'

punycode.version#

A string representing the current Punycode.js version number.

For maintainers#

How to publish a new release#

  1. On the main branch, bump the version number in package.json:

    npm version patch -m 'Release v%s'

    Instead of patch, use minor or major as needed.

    Note that this produces a Git commit + tag.

  2. Push the release commit and tag:

    git push && git push --tags

    Our CI then automatically publishes the new release to npm, under both the punycode and punycode.js names.

Author#

twitter/mathias
Mathias Bynens

License#

Punycode.js is available under the MIT license. Railroad-diagram Generator#

This is a small js library for generating railroad diagrams (like what JSON.org uses) using SVG.

Railroad diagrams are a way of visually representing a grammar in a form that is more readable than using regular expressions or BNF. I think (though I haven't given it a lot of thought yet) that if it's easy to write a context-free grammar for the language, the corresponding railroad diagram will be easy as well.

There are several railroad-diagram generators out there, but none of them had the visual appeal I wanted. Here's an example of how they look! And here's an online generator for you to play with and get SVG code from!

The library now exists in a Python port as well! See the information further down.

Details#

To use the library, just include the js and css files, and then call the Diagram() function. Its arguments are the components of the diagram (Diagram is a special form of Sequence). An alternative to Diagram() is ComplexDiagram() which is used to describe a complex type diagram. Components are either leaves or containers.

The leaves:

  • Terminal(text) or a bare string - represents literal text
  • NonTerminal(text) - represents an instruction or another production
  • Comment(text) - a comment
  • Skip() - an empty line

The containers:

  • Sequence(children) - like simple concatenation in a regex
  • Choice(index, children) - like | in a regex. The index argument specifies which child is the "normal" choice and should go in the middle
  • Optional(child, skip) - like ? in a regex. A shorthand for Choice(1, [Skip(), child]). If the optional skip parameter has the value "skip", it instead puts the Skip() in the straight-line path, for when the "normal" behavior is to omit the item.
  • OneOrMore(child, repeat) - like + in a regex. The 'repeat' argument is optional, and specifies something that must go between the repetitions.
  • ZeroOrMore(child, repeat, skip) - like * in a regex. A shorthand for Optional(OneOrMore(child, repeat)). The optional skip parameter is identical to Optional().

For convenience, each component can be called with or without new. If called without new, the container components become n-ary; that is, you can say either new Sequence([A, B]) or just Sequence(A,B).

After constructing a Diagram, call .format(...padding) on it, specifying 0-4 padding values (just like CSS) for some additional "breathing space" around the diagram (the paddings default to 20px).

The result can either be .toString()'d for the markup, or .toSVG()'d for an <svg> element, which can then be immediately inserted to the document. As a convenience, Diagram also has an .addTo(element) method, which immediately converts it to SVG and appends it to the referenced element with default paddings. element defaults to document.body.

Options#

There are a few options you can tweak, at the bottom of the file. Just tweak either until the diagram looks like what you want. You can also change the CSS file - feel free to tweak to your heart's content. Note, though, that if you change the text sizes in the CSS, you'll have to go adjust the metrics for the leaf nodes as well.

  • VERTICAL_SEPARATION - sets the minimum amount of vertical separation between two items. Note that the stroke width isn't counted when computing the separation; this shouldn't be relevant unless you have a very small separation or very large stroke width.
  • ARC_RADIUS - the radius of the arcs used in the branching containers like Choice. This has a relatively large effect on the size of non-trivial diagrams. Both tight and loose values look good, depending on what you're going for.
  • DIAGRAM_CLASS - the class set on the root <svg> element of each diagram, for use in the CSS stylesheet.
  • STROKE_ODD_PIXEL_LENGTH - the default stylesheet uses odd pixel lengths for 'stroke'. Due to rasterization artifacts, they look best when the item has been translated half a pixel in both directions. If you change the styling to use a stroke with even pixel lengths, you'll want to set this variable to false.
  • INTERNAL_ALIGNMENT - when some branches of a container are narrower than others, this determines how they're aligned in the extra space. Defaults to "center", but can be set to "left" or "right".

Caveats#

At this early stage, the generator is feature-complete and works as intended, but still has several TODOs:

  • The font-sizes are hard-coded right now, and the font handling in general is very dumb - I'm just guessing at some metrics that are probably "good enough" rather than measuring things properly.

Python Port#

In addition to the canonical JS version, the library now exists as a Python library as well.

Using it is basically identical. The config variables are globals in the file, and so may be adjusted either manually or via tweaking from inside your program.

The main difference from the JS port is how you extract the string from the Diagram. You'll find a writeSvg(writerFunc) method on Diagram, which takes a callback of one argument and passes it the string form of the diagram. For example, it can be used like Diagram(...).writeSvg(sys.stdout.write) to write to stdout. Note: the callback will be called multiple times as it builds up the string, not just once with the whole thing. If you need it all at once, consider something like a StringIO as an easy way to collect it into a single string.

License#

This document and all associated files in the github project are licensed under CC0 . 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. # randexp.js

randexp will generate a random string that matches a given RegExp Javascript object.

Build Status Dependency Status codecov

Usage#

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();
// => <m5xhdg>foo<m5xhdg>
 
// 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

var randexp = require('randexp').randexp;
 
randexp(/[1-6]/); // 4
randexp('great|good( job)?|excellent'); // great

If you miss the old syntax

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 for giving me the idea to make this in the first place and 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)

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.

var randexp = new RandExp(/no{1,}/);
randexp.max = 1000000;

With RandExp.sugar()

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 and jsf demo page.

Install#

Node.js#

npm install randexp

Browser#

Download the minified version from the latest release.

Tests#

Tests are written with mocha

npm test

License#

MIT # require-from-string Build Status

Load module from string in Node.

Install#

$ npm install --save require-from-string

Usage#

var requireFromString = require('require-from-string');
 
requireFromString('module.exports = 1');
//=> 1

API#

requireFromString(code, [filename], [options])#

code#

Required
Type: string

Module code.

filename#

Type: string
Default: ''

Optional filename.

options#

Type: object

appendPaths#

Type: Array

List of paths, that will be appended to module paths. Useful, when you want to be able require modules from these paths.

prependPaths#

Type: Array

Same as appendPaths, but paths will be prepended.

License#

MIT © Vsevolod Strukchinsky # Regular Expression Tokenizer

Tokenizes strings that represent a regular expressions.

Build Status Dependency Status codecov

Usage#

var ret = require('ret');
 
var tokens = ret(/foo|bar/.source);

tokens will contain the following object

{
  "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.

{
  "type": ret.types.ROOT,
  "stack": [token1, token2...],
}
{
  "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.

{
  "type": ret.types.GROUP,
  "remember" true,
  "followedBy": false,
  "notFollowedBy": false,
  "stack": [token1, token2...],
}
{
  "type": ret.types.GROUP,
  "remember" true,
  "followedBy": false,
  "notFollowedBy": false,
  "options" [
    [token1, token2...],
    [othertoken1, othertoken2...]
    ...
  ],
}

POSITION#

\b, \B, ^, and $ specify positions in the regexp.

{
  "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.

{
  "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.

{
  "type": ret.types.RANGE,
  "from": 97,
  "to": 122,
}

REPETITION#

{
  "type": ret.types.REPETITION,
  "min": 0,
  "max": Infinity,
  "value": token,
}

REFERENCE#

References a group token. value is 1-9.

{
  "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.

{
  "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

npm test

License#

MIT Schemes#

NPM version Build Status Coverage Status Dependency Status

A javascript object map of official iana.org Uniform Resource Identifier (URI) Schemes and crowd sourced unofficial schemes.

This can be used to look up the rfc's for the corresponding schemes or check a schemes validity based on of it exists in the list of not.

Usage#

var schemes = require('schemes');
 
schemes.permanent[0]; // {
                      //   "scheme": "aaa",
                      //   "description": "Diameter Protocol",
                      //   "reference": [
                      //     {
                      //       "type": "rfc",
                      //       "href": "http://www.iana.org/go/rfc6733"
                      //     }
                      //   ]
                      // }
 
schemes.provisional[0]; // {
                        //   "scheme": "acr",
                        //   "description": "acr",
                        //   "reference": [],
                        //   "template": "http://www.iana.org/assignments/uri-schemes/prov/acr"
                        // }
 
schemes.historical[0]; // {
                       //   "scheme": "fax",
                       //   "description": "fax",
                       //   "reference": [
                       //     {
                       //       "type": "rfc",
                       //       "href": "http://www.iana.org/go/rfc2806"
                       //     },
                       //     {
                       //       "type": "rfc",
                       //       "href": "http://www.iana.org/go/rfc3966"
                       //     }
                       //   ]
                       // }
 
schemes.unofficial[0]; // {
                       //   "scheme": "android-app"
                       // }
 
schemes.allByName; // {
                   //   'aaa': { ... } // scheme object
                   //   'aaas': { ... } // scheme object
                   //   'about': { ... } // scheme object
                   //   'acap': { ... } // scheme object
                   //   'acct': { ... } // scheme object
                   //   'cap': { ... } // scheme object
                   //   'cid': { ... } // scheme object
                   //   'coap': { ... } // scheme object
                   //   'coaps': { ... } // scheme object
                   //   'crid': { ... } // scheme object
                   //   ...
                   // }

Contributing#

Part of this module is auto generated from iana official lists, but the unofficial ones are not. If you find that a specific scheme is missing from these lists, please submit a pull request that adds it to the unofficial schemes list.

License#

(The MIT License)

Copyright (c) 2015 Peter Müller munter@fumle.dk

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. # smtp-address-parser

Parse an SMTP (RFC-5321) address.

https://nodei.co/npm/smtp-address-parser.png?downloads=true&downloadRank=true&stars=true

Some notes#

** Changes in version 1.1.0: **

** Domains are now checked beyond RFC-5321 syntax only **

Domain names must be fully qualified; that is with at least two labels. The top-level domain must have at least two octets.

** Length limitations are now checked **

Total length limit of an address is 986 octets; based on a 1,000 octet SMTP line length.

See https://tools.ietf.org/html/rfc1035 section 2.3.4. Size limits:

Domain names are limited to 255 octets, when encoded with a length byte before each label, and including the top-level zero length label. So, the effctive limit with interstitial dots is 253 octets.

Labels within a domain name are limited to 63 octets.

The above are limits of the DNS protocol, not any particular implementation.

RFC-5321 section 4.5.3.1. “Size Limits and Minimums” still says:

“To the maximum extent possible, implementation techniques that impose no limits on the length of these objects should be used.” 

Updated