Bump packages to fix linter

This commit is contained in:
Henry Mercer 2023-01-18 20:50:03 +00:00
parent ed9506bbaf
commit 0a11e3fdd9
6063 changed files with 378752 additions and 306784 deletions

View file

@ -1 +0,0 @@
../js-yaml/bin/js-yaml.js

View file

@ -1,185 +0,0 @@
1.0.10 / 2018-02-15
------------------
- Use .concat instead of + for arrays, #122.
1.0.9 / 2016-09-29
------------------
- Rerelease after 1.0.8 - deps cleanup.
1.0.8 / 2016-09-29
------------------
- Maintenance (deps bump, fix node 6.5+ tests, coverage report).
1.0.7 / 2016-03-17
------------------
- Teach `addArgument` to accept string arg names. #97, @tomxtobin.
1.0.6 / 2016-02-06
------------------
- Maintenance: moved to eslint & updated CS.
1.0.5 / 2016-02-05
------------------
- Removed lodash dependency to significantly reduce install size.
Thanks to @mourner.
1.0.4 / 2016-01-17
------------------
- Maintenance: lodash update to 4.0.0.
1.0.3 / 2015-10-27
------------------
- Fix parse `=` in args: `--examplepath="C:\myfolder\env=x64"`. #84, @CatWithApple.
1.0.2 / 2015-03-22
------------------
- Relaxed lodash version dependency.
1.0.1 / 2015-02-20
------------------
- Changed dependencies to be compatible with ancient nodejs.
1.0.0 / 2015-02-19
------------------
- Maintenance release.
- Replaced `underscore` with `lodash`.
- Bumped version to 1.0.0 to better reflect semver meaning.
- HISTORY.md -> CHANGELOG.md
0.1.16 / 2013-12-01
-------------------
- Maintenance release. Updated dependencies and docs.
0.1.15 / 2013-05-13
-------------------
- Fixed #55, @trebor89
0.1.14 / 2013-05-12
-------------------
- Fixed #62, @maxtaco
0.1.13 / 2013-04-08
-------------------
- Added `.npmignore` to reduce package size
0.1.12 / 2013-02-10
-------------------
- Fixed conflictHandler (#46), @hpaulj
0.1.11 / 2013-02-07
-------------------
- Multiple bugfixes, @hpaulj
- Added 70+ tests (ported from python), @hpaulj
- Added conflictHandler, @applepicke
- Added fromfilePrefixChar, @hpaulj
0.1.10 / 2012-12-30
-------------------
- Added [mutual exclusion](http://docs.python.org/dev/library/argparse.html#mutual-exclusion)
support, thanks to @hpaulj
- Fixed options check for `storeConst` & `appendConst` actions, thanks to @hpaulj
0.1.9 / 2012-12-27
------------------
- Fixed option dest interferens with other options (issue #23), thanks to @hpaulj
- Fixed default value behavior with `*` positionals, thanks to @hpaulj
- Improve `getDefault()` behavior, thanks to @hpaulj
- Imrove negative argument parsing, thanks to @hpaulj
0.1.8 / 2012-12-01
------------------
- Fixed parser parents (issue #19), thanks to @hpaulj
- Fixed negative argument parse (issue #20), thanks to @hpaulj
0.1.7 / 2012-10-14
------------------
- Fixed 'choices' argument parse (issue #16)
- Fixed stderr output (issue #15)
0.1.6 / 2012-09-09
------------------
- Fixed check for conflict of options (thanks to @tomxtobin)
0.1.5 / 2012-09-03
------------------
- Fix parser #setDefaults method (thanks to @tomxtobin)
0.1.4 / 2012-07-30
------------------
- Fixed pseudo-argument support (thanks to @CGamesPlay)
- Fixed addHelp default (should be true), if not set (thanks to @benblank)
0.1.3 / 2012-06-27
------------------
- Fixed formatter api name: Formatter -> HelpFormatter
0.1.2 / 2012-05-29
------------------
- Added basic tests
- Removed excess whitespace in help
- Fixed error reporting, when parcer with subcommands
called with empty arguments
0.1.1 / 2012-05-23
------------------
- Fixed line wrapping in help formatter
- Added better error reporting on invalid arguments
0.1.0 / 2012-05-16
------------------
- First release.

View file

@ -1,21 +0,0 @@
(The MIT License)
Copyright (C) 2012 by Vitaly Puzrin
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.

View file

@ -1,257 +0,0 @@
argparse
========
[![Build Status](https://secure.travis-ci.org/nodeca/argparse.svg?branch=master)](http://travis-ci.org/nodeca/argparse)
[![NPM version](https://img.shields.io/npm/v/argparse.svg)](https://www.npmjs.org/package/argparse)
CLI arguments parser for node.js. Javascript port of python's
[argparse](http://docs.python.org/dev/library/argparse.html) module
(original version 3.2). That's a full port, except some very rare options,
recorded in issue tracker.
**NB. Difference with original.**
- Method names changed to camelCase. See [generated docs](http://nodeca.github.com/argparse/).
- Use `defaultValue` instead of `default`.
- Use `argparse.Const.REMAINDER` instead of `argparse.REMAINDER`, and
similarly for constant values `OPTIONAL`, `ZERO_OR_MORE`, and `ONE_OR_MORE`
(aliases for `nargs` values `'?'`, `'*'`, `'+'`, respectively), and
`SUPPRESS`.
Example
=======
test.js file:
```javascript
#!/usr/bin/env node
'use strict';
var ArgumentParser = require('../lib/argparse').ArgumentParser;
var parser = new ArgumentParser({
version: '0.0.1',
addHelp:true,
description: 'Argparse example'
});
parser.addArgument(
[ '-f', '--foo' ],
{
help: 'foo bar'
}
);
parser.addArgument(
[ '-b', '--bar' ],
{
help: 'bar foo'
}
);
parser.addArgument(
'--baz',
{
help: 'baz bar'
}
);
var args = parser.parseArgs();
console.dir(args);
```
Display help:
```
$ ./test.js -h
usage: example.js [-h] [-v] [-f FOO] [-b BAR] [--baz BAZ]
Argparse example
Optional arguments:
-h, --help Show this help message and exit.
-v, --version Show program's version number and exit.
-f FOO, --foo FOO foo bar
-b BAR, --bar BAR bar foo
--baz BAZ baz bar
```
Parse arguments:
```
$ ./test.js -f=3 --bar=4 --baz 5
{ foo: '3', bar: '4', baz: '5' }
```
More [examples](https://github.com/nodeca/argparse/tree/master/examples).
ArgumentParser objects
======================
```
new ArgumentParser({parameters hash});
```
Creates a new ArgumentParser object.
**Supported params:**
- ```description``` - Text to display before the argument help.
- ```epilog``` - Text to display after the argument help.
- ```addHelp``` - Add a -h/help option to the parser. (default: true)
- ```argumentDefault``` - Set the global default value for arguments. (default: null)
- ```parents``` - A list of ArgumentParser objects whose arguments should also be included.
- ```prefixChars``` - The set of characters that prefix optional arguments. (default: -)
- ```formatterClass``` - A class for customizing the help output.
- ```prog``` - The name of the program (default: `path.basename(process.argv[1])`)
- ```usage``` - The string describing the program usage (default: generated)
- ```conflictHandler``` - Usually unnecessary, defines strategy for resolving conflicting optionals.
**Not supported yet**
- ```fromfilePrefixChars``` - The set of characters that prefix files from which additional arguments should be read.
Details in [original ArgumentParser guide](http://docs.python.org/dev/library/argparse.html#argumentparser-objects)
addArgument() method
====================
```
ArgumentParser.addArgument(name or flag or [name] or [flags...], {options})
```
Defines how a single command-line argument should be parsed.
- ```name or flag or [name] or [flags...]``` - Either a positional name
(e.g., `'foo'`), a single option (e.g., `'-f'` or `'--foo'`), an array
of a single positional name (e.g., `['foo']`), or an array of options
(e.g., `['-f', '--foo']`).
Options:
- ```action``` - The basic type of action to be taken when this argument is encountered at the command line.
- ```nargs```- The number of command-line arguments that should be consumed.
- ```constant``` - A constant value required by some action and nargs selections.
- ```defaultValue``` - The value produced if the argument is absent from the command line.
- ```type``` - The type to which the command-line argument should be converted.
- ```choices``` - A container of the allowable values for the argument.
- ```required``` - Whether or not the command-line option may be omitted (optionals only).
- ```help``` - A brief description of what the argument does.
- ```metavar``` - A name for the argument in usage messages.
- ```dest``` - The name of the attribute to be added to the object returned by parseArgs().
Details in [original add_argument guide](http://docs.python.org/dev/library/argparse.html#the-add-argument-method)
Action (some details)
================
ArgumentParser objects associate command-line arguments with actions.
These actions can do just about anything with the command-line arguments associated
with them, though most actions simply add an attribute to the object returned by
parseArgs(). The action keyword argument specifies how the command-line arguments
should be handled. The supported actions are:
- ```store``` - Just stores the arguments value. This is the default action.
- ```storeConst``` - Stores value, specified by the const keyword argument.
(Note that the const keyword argument defaults to the rather unhelpful None.)
The 'storeConst' action is most commonly used with optional arguments, that
specify some sort of flag.
- ```storeTrue``` and ```storeFalse``` - Stores values True and False
respectively. These are special cases of 'storeConst'.
- ```append``` - Stores a list, and appends each argument value to the list.
This is useful to allow an option to be specified multiple times.
- ```appendConst``` - Stores a list, and appends value, specified by the
const keyword argument to the list. (Note, that the const keyword argument defaults
is None.) The 'appendConst' action is typically used when multiple arguments need
to store constants to the same list.
- ```count``` - Counts the number of times a keyword argument occurs. For example,
used for increasing verbosity levels.
- ```help``` - Prints a complete help message for all the options in the current
parser and then exits. By default a help action is automatically added to the parser.
See ArgumentParser for details of how the output is created.
- ```version``` - Prints version information and exit. Expects a `version=`
keyword argument in the addArgument() call.
Details in [original action guide](http://docs.python.org/dev/library/argparse.html#action)
Sub-commands
============
ArgumentParser.addSubparsers()
Many programs split their functionality into a number of sub-commands, for
example, the svn program can invoke sub-commands like `svn checkout`, `svn update`,
and `svn commit`. Splitting up functionality this way can be a particularly good
idea when a program performs several different functions which require different
kinds of command-line arguments. `ArgumentParser` supports creation of such
sub-commands with `addSubparsers()` method. The `addSubparsers()` method is
normally called with no arguments and returns an special action object.
This object has a single method `addParser()`, which takes a command name and
any `ArgumentParser` constructor arguments, and returns an `ArgumentParser` object
that can be modified as usual.
Example:
sub_commands.js
```javascript
#!/usr/bin/env node
'use strict';
var ArgumentParser = require('../lib/argparse').ArgumentParser;
var parser = new ArgumentParser({
version: '0.0.1',
addHelp:true,
description: 'Argparse examples: sub-commands',
});
var subparsers = parser.addSubparsers({
title:'subcommands',
dest:"subcommand_name"
});
var bar = subparsers.addParser('c1', {addHelp:true});
bar.addArgument(
[ '-f', '--foo' ],
{
action: 'store',
help: 'foo3 bar3'
}
);
var bar = subparsers.addParser(
'c2',
{aliases:['co'], addHelp:true}
);
bar.addArgument(
[ '-b', '--bar' ],
{
action: 'store',
type: 'int',
help: 'foo3 bar3'
}
);
var args = parser.parseArgs();
console.dir(args);
```
Details in [original sub-commands guide](http://docs.python.org/dev/library/argparse.html#sub-commands)
Contributors
============
- [Eugene Shkuropat](https://github.com/shkuropat)
- [Paul Jacobson](https://github.com/hpaulj)
[others](https://github.com/nodeca/argparse/graphs/contributors)
License
=======
Copyright (c) 2012 [Vitaly Puzrin](https://github.com/puzrin).
Released under the MIT license. See
[LICENSE](https://github.com/nodeca/argparse/blob/master/LICENSE) for details.

View file

@ -1,3 +0,0 @@
'use strict';
module.exports = require('./lib/argparse');

View file

@ -1,146 +0,0 @@
/**
* class Action
*
* Base class for all actions
* Do not call in your code, use this class only for inherits your own action
*
* Information about how to convert command line strings to Javascript objects.
* Action objects are used by an ArgumentParser to represent the information
* needed to parse a single argument from one or more strings from the command
* line. The keyword arguments to the Action constructor are also all attributes
* of Action instances.
*
* ##### Allowed keywords:
*
* - `store`
* - `storeConstant`
* - `storeTrue`
* - `storeFalse`
* - `append`
* - `appendConstant`
* - `count`
* - `help`
* - `version`
*
* Information about action options see [[Action.new]]
*
* See also [original guide](http://docs.python.org/dev/library/argparse.html#action)
*
**/
'use strict';
// Constants
var c = require('./const');
/**
* new Action(options)
*
* Base class for all actions. Used only for inherits
*
*
* ##### Options:
*
* - `optionStrings` A list of command-line option strings for the action.
* - `dest` Attribute to hold the created object(s)
* - `nargs` The number of command-line arguments that should be consumed.
* By default, one argument will be consumed and a single value will be
* produced.
* - `constant` Default value for an action with no value.
* - `defaultValue` The value to be produced if the option is not specified.
* - `type` Cast to 'string'|'int'|'float'|'complex'|function (string). If
* None, 'string'.
* - `choices` The choices available.
* - `required` True if the action must always be specified at the command
* line.
* - `help` The help describing the argument.
* - `metavar` The name to be used for the option's argument with the help
* string. If None, the 'dest' value will be used as the name.
*
* ##### nargs supported values:
*
* - `N` (an integer) consumes N arguments (and produces a list)
* - `?` consumes zero or one arguments
* - `*` consumes zero or more arguments (and produces a list)
* - `+` consumes one or more arguments (and produces a list)
*
* Note: that the difference between the default and nargs=1 is that with the
* default, a single value will be produced, while with nargs=1, a list
* containing a single value will be produced.
**/
var Action = module.exports = function Action(options) {
options = options || {};
this.optionStrings = options.optionStrings || [];
this.dest = options.dest;
this.nargs = typeof options.nargs !== 'undefined' ? options.nargs : null;
this.constant = typeof options.constant !== 'undefined' ? options.constant : null;
this.defaultValue = options.defaultValue;
this.type = typeof options.type !== 'undefined' ? options.type : null;
this.choices = typeof options.choices !== 'undefined' ? options.choices : null;
this.required = typeof options.required !== 'undefined' ? options.required : false;
this.help = typeof options.help !== 'undefined' ? options.help : null;
this.metavar = typeof options.metavar !== 'undefined' ? options.metavar : null;
if (!(this.optionStrings instanceof Array)) {
throw new Error('optionStrings should be an array');
}
if (typeof this.required !== 'undefined' && typeof this.required !== 'boolean') {
throw new Error('required should be a boolean');
}
};
/**
* Action#getName -> String
*
* Tells action name
**/
Action.prototype.getName = function () {
if (this.optionStrings.length > 0) {
return this.optionStrings.join('/');
} else if (this.metavar !== null && this.metavar !== c.SUPPRESS) {
return this.metavar;
} else if (typeof this.dest !== 'undefined' && this.dest !== c.SUPPRESS) {
return this.dest;
}
return null;
};
/**
* Action#isOptional -> Boolean
*
* Return true if optional
**/
Action.prototype.isOptional = function () {
return !this.isPositional();
};
/**
* Action#isPositional -> Boolean
*
* Return true if positional
**/
Action.prototype.isPositional = function () {
return (this.optionStrings.length === 0);
};
/**
* Action#call(parser, namespace, values, optionString) -> Void
* - parser (ArgumentParser): current parser
* - namespace (Namespace): namespace for output data
* - values (Array): parsed values
* - optionString (Array): input option string(not parsed)
*
* Call the action. Should be implemented in inherited classes
*
* ##### Example
*
* ActionCount.prototype.call = function (parser, namespace, values, optionString) {
* namespace.set(this.dest, (namespace[this.dest] || 0) + 1);
* };
*
**/
Action.prototype.call = function () {
throw new Error('.call() not defined');// Not Implemented error
};

View file

@ -1,53 +0,0 @@
/*:nodoc:*
* class ActionAppend
*
* This action stores a list, and appends each argument value to the list.
* This is useful to allow an option to be specified multiple times.
* This class inherided from [[Action]]
*
**/
'use strict';
var util = require('util');
var Action = require('../action');
// Constants
var c = require('../const');
/*:nodoc:*
* new ActionAppend(options)
* - options (object): options hash see [[Action.new]]
*
* Note: options.nargs should be optional for constants
* and more then zero for other
**/
var ActionAppend = module.exports = function ActionAppend(options) {
options = options || {};
if (this.nargs <= 0) {
throw new Error('nargs for append actions must be > 0; if arg ' +
'strings are not supplying the value to append, ' +
'the append const action may be more appropriate');
}
if (!!this.constant && this.nargs !== c.OPTIONAL) {
throw new Error('nargs must be OPTIONAL to supply const');
}
Action.call(this, options);
};
util.inherits(ActionAppend, Action);
/*:nodoc:*
* ActionAppend#call(parser, namespace, values, optionString) -> Void
* - parser (ArgumentParser): current parser
* - namespace (Namespace): namespace for output data
* - values (Array): parsed values
* - optionString (Array): input option string(not parsed)
*
* Call the action. Save result in namespace object
**/
ActionAppend.prototype.call = function (parser, namespace, values) {
var items = (namespace[this.dest] || []).slice();
items.push(values);
namespace.set(this.dest, items);
};

View file

@ -1,47 +0,0 @@
/*:nodoc:*
* class ActionAppendConstant
*
* This stores a list, and appends the value specified by
* the const keyword argument to the list.
* (Note that the const keyword argument defaults to null.)
* The 'appendConst' action is typically useful when multiple
* arguments need to store constants to the same list.
*
* This class inherited from [[Action]]
**/
'use strict';
var util = require('util');
var Action = require('../../action');
/*:nodoc:*
* new ActionAppendConstant(options)
* - options (object): options hash see [[Action.new]]
*
**/
var ActionAppendConstant = module.exports = function ActionAppendConstant(options) {
options = options || {};
options.nargs = 0;
if (typeof options.constant === 'undefined') {
throw new Error('constant option is required for appendAction');
}
Action.call(this, options);
};
util.inherits(ActionAppendConstant, Action);
/*:nodoc:*
* ActionAppendConstant#call(parser, namespace, values, optionString) -> Void
* - parser (ArgumentParser): current parser
* - namespace (Namespace): namespace for output data
* - values (Array): parsed values
* - optionString (Array): input option string(not parsed)
*
* Call the action. Save result in namespace object
**/
ActionAppendConstant.prototype.call = function (parser, namespace) {
var items = [].concat(namespace[this.dest] || []);
items.push(this.constant);
namespace.set(this.dest, items);
};

View file

@ -1,40 +0,0 @@
/*:nodoc:*
* class ActionCount
*
* This counts the number of times a keyword argument occurs.
* For example, this is useful for increasing verbosity levels
*
* This class inherided from [[Action]]
*
**/
'use strict';
var util = require('util');
var Action = require('../action');
/*:nodoc:*
* new ActionCount(options)
* - options (object): options hash see [[Action.new]]
*
**/
var ActionCount = module.exports = function ActionCount(options) {
options = options || {};
options.nargs = 0;
Action.call(this, options);
};
util.inherits(ActionCount, Action);
/*:nodoc:*
* ActionCount#call(parser, namespace, values, optionString) -> Void
* - parser (ArgumentParser): current parser
* - namespace (Namespace): namespace for output data
* - values (Array): parsed values
* - optionString (Array): input option string(not parsed)
*
* Call the action. Save result in namespace object
**/
ActionCount.prototype.call = function (parser, namespace) {
namespace.set(this.dest, (namespace[this.dest] || 0) + 1);
};

View file

@ -1,47 +0,0 @@
/*:nodoc:*
* class ActionHelp
*
* Support action for printing help
* This class inherided from [[Action]]
**/
'use strict';
var util = require('util');
var Action = require('../action');
// Constants
var c = require('../const');
/*:nodoc:*
* new ActionHelp(options)
* - options (object): options hash see [[Action.new]]
*
**/
var ActionHelp = module.exports = function ActionHelp(options) {
options = options || {};
if (options.defaultValue !== null) {
options.defaultValue = options.defaultValue;
} else {
options.defaultValue = c.SUPPRESS;
}
options.dest = (options.dest !== null ? options.dest : c.SUPPRESS);
options.nargs = 0;
Action.call(this, options);
};
util.inherits(ActionHelp, Action);
/*:nodoc:*
* ActionHelp#call(parser, namespace, values, optionString)
* - parser (ArgumentParser): current parser
* - namespace (Namespace): namespace for output data
* - values (Array): parsed values
* - optionString (Array): input option string(not parsed)
*
* Print help and exit
**/
ActionHelp.prototype.call = function (parser) {
parser.printHelp();
parser.exit();
};

View file

@ -1,50 +0,0 @@
/*:nodoc:*
* class ActionStore
*
* This action just stores the arguments value. This is the default action.
*
* This class inherited from [[Action]]
*
**/
'use strict';
var util = require('util');
var Action = require('../action');
// Constants
var c = require('../const');
/*:nodoc:*
* new ActionStore(options)
* - options (object): options hash see [[Action.new]]
*
**/
var ActionStore = module.exports = function ActionStore(options) {
options = options || {};
if (this.nargs <= 0) {
throw new Error('nargs for store actions must be > 0; if you ' +
'have nothing to store, actions such as store ' +
'true or store const may be more appropriate');
}
if (typeof this.constant !== 'undefined' && this.nargs !== c.OPTIONAL) {
throw new Error('nargs must be OPTIONAL to supply const');
}
Action.call(this, options);
};
util.inherits(ActionStore, Action);
/*:nodoc:*
* ActionStore#call(parser, namespace, values, optionString) -> Void
* - parser (ArgumentParser): current parser
* - namespace (Namespace): namespace for output data
* - values (Array): parsed values
* - optionString (Array): input option string(not parsed)
*
* Call the action. Save result in namespace object
**/
ActionStore.prototype.call = function (parser, namespace, values) {
namespace.set(this.dest, values);
};

View file

@ -1,43 +0,0 @@
/*:nodoc:*
* class ActionStoreConstant
*
* This action stores the value specified by the const keyword argument.
* (Note that the const keyword argument defaults to the rather unhelpful null.)
* The 'store_const' action is most commonly used with optional
* arguments that specify some sort of flag.
*
* This class inherited from [[Action]]
**/
'use strict';
var util = require('util');
var Action = require('../../action');
/*:nodoc:*
* new ActionStoreConstant(options)
* - options (object): options hash see [[Action.new]]
*
**/
var ActionStoreConstant = module.exports = function ActionStoreConstant(options) {
options = options || {};
options.nargs = 0;
if (typeof options.constant === 'undefined') {
throw new Error('constant option is required for storeAction');
}
Action.call(this, options);
};
util.inherits(ActionStoreConstant, Action);
/*:nodoc:*
* ActionStoreConstant#call(parser, namespace, values, optionString) -> Void
* - parser (ArgumentParser): current parser
* - namespace (Namespace): namespace for output data
* - values (Array): parsed values
* - optionString (Array): input option string(not parsed)
*
* Call the action. Save result in namespace object
**/
ActionStoreConstant.prototype.call = function (parser, namespace) {
namespace.set(this.dest, this.constant);
};

View file

@ -1,27 +0,0 @@
/*:nodoc:*
* class ActionStoreFalse
*
* This action store the values False respectively.
* This is special cases of 'storeConst'
*
* This class inherited from [[Action]]
**/
'use strict';
var util = require('util');
var ActionStoreConstant = require('./constant');
/*:nodoc:*
* new ActionStoreFalse(options)
* - options (object): hash of options see [[Action.new]]
*
**/
var ActionStoreFalse = module.exports = function ActionStoreFalse(options) {
options = options || {};
options.constant = false;
options.defaultValue = options.defaultValue !== null ? options.defaultValue : true;
ActionStoreConstant.call(this, options);
};
util.inherits(ActionStoreFalse, ActionStoreConstant);

View file

@ -1,26 +0,0 @@
/*:nodoc:*
* class ActionStoreTrue
*
* This action store the values True respectively.
* This isspecial cases of 'storeConst'
*
* This class inherited from [[Action]]
**/
'use strict';
var util = require('util');
var ActionStoreConstant = require('./constant');
/*:nodoc:*
* new ActionStoreTrue(options)
* - options (object): options hash see [[Action.new]]
*
**/
var ActionStoreTrue = module.exports = function ActionStoreTrue(options) {
options = options || {};
options.constant = true;
options.defaultValue = options.defaultValue !== null ? options.defaultValue : false;
ActionStoreConstant.call(this, options);
};
util.inherits(ActionStoreTrue, ActionStoreConstant);

View file

@ -1,149 +0,0 @@
/** internal
* class ActionSubparsers
*
* Support the creation of such sub-commands with the addSubparsers()
*
* This class inherited from [[Action]]
**/
'use strict';
var util = require('util');
var format = require('util').format;
var Action = require('../action');
// Constants
var c = require('../const');
// Errors
var argumentErrorHelper = require('../argument/error');
/*:nodoc:*
* new ChoicesPseudoAction(name, help)
*
* Create pseudo action for correct help text
*
**/
function ChoicesPseudoAction(name, help) {
var options = {
optionStrings: [],
dest: name,
help: help
};
Action.call(this, options);
}
util.inherits(ChoicesPseudoAction, Action);
/**
* new ActionSubparsers(options)
* - options (object): options hash see [[Action.new]]
*
**/
function ActionSubparsers(options) {
options = options || {};
options.dest = options.dest || c.SUPPRESS;
options.nargs = c.PARSER;
this.debug = (options.debug === true);
this._progPrefix = options.prog;
this._parserClass = options.parserClass;
this._nameParserMap = {};
this._choicesActions = [];
options.choices = this._nameParserMap;
Action.call(this, options);
}
util.inherits(ActionSubparsers, Action);
/*:nodoc:*
* ActionSubparsers#addParser(name, options) -> ArgumentParser
* - name (string): sub-command name
* - options (object): see [[ArgumentParser.new]]
*
* Note:
* addParser supports an additional aliases option,
* which allows multiple strings to refer to the same subparser.
* This example, like svn, aliases co as a shorthand for checkout
*
**/
ActionSubparsers.prototype.addParser = function (name, options) {
var parser;
var self = this;
options = options || {};
options.debug = (this.debug === true);
// set program from the existing prefix
if (!options.prog) {
options.prog = this._progPrefix + ' ' + name;
}
var aliases = options.aliases || [];
// create a pseudo-action to hold the choice help
if (!!options.help || typeof options.help === 'string') {
var help = options.help;
delete options.help;
var choiceAction = new ChoicesPseudoAction(name, help);
this._choicesActions.push(choiceAction);
}
// create the parser and add it to the map
parser = new this._parserClass(options);
this._nameParserMap[name] = parser;
// make parser available under aliases also
aliases.forEach(function (alias) {
self._nameParserMap[alias] = parser;
});
return parser;
};
ActionSubparsers.prototype._getSubactions = function () {
return this._choicesActions;
};
/*:nodoc:*
* ActionSubparsers#call(parser, namespace, values, optionString) -> Void
* - parser (ArgumentParser): current parser
* - namespace (Namespace): namespace for output data
* - values (Array): parsed values
* - optionString (Array): input option string(not parsed)
*
* Call the action. Parse input aguments
**/
ActionSubparsers.prototype.call = function (parser, namespace, values) {
var parserName = values[0];
var argStrings = values.slice(1);
// set the parser name if requested
if (this.dest !== c.SUPPRESS) {
namespace[this.dest] = parserName;
}
// select the parser
if (this._nameParserMap[parserName]) {
parser = this._nameParserMap[parserName];
} else {
throw argumentErrorHelper(format(
'Unknown parser "%s" (choices: [%s]).',
parserName,
Object.keys(this._nameParserMap).join(', ')
));
}
// parse all the remaining options into the namespace
parser.parseArgs(argStrings, namespace);
};
module.exports = ActionSubparsers;

View file

@ -1,47 +0,0 @@
/*:nodoc:*
* class ActionVersion
*
* Support action for printing program version
* This class inherited from [[Action]]
**/
'use strict';
var util = require('util');
var Action = require('../action');
//
// Constants
//
var c = require('../const');
/*:nodoc:*
* new ActionVersion(options)
* - options (object): options hash see [[Action.new]]
*
**/
var ActionVersion = module.exports = function ActionVersion(options) {
options = options || {};
options.defaultValue = (options.defaultValue ? options.defaultValue : c.SUPPRESS);
options.dest = (options.dest || c.SUPPRESS);
options.nargs = 0;
this.version = options.version;
Action.call(this, options);
};
util.inherits(ActionVersion, Action);
/*:nodoc:*
* ActionVersion#call(parser, namespace, values, optionString) -> Void
* - parser (ArgumentParser): current parser
* - namespace (Namespace): namespace for output data
* - values (Array): parsed values
* - optionString (Array): input option string(not parsed)
*
* Print version and exit
**/
ActionVersion.prototype.call = function (parser) {
var version = this.version || parser.version;
var formatter = parser._getFormatter();
formatter.addText(version);
parser.exit(0, formatter.formatHelp());
};

View file

@ -1,482 +0,0 @@
/** internal
* class ActionContainer
*
* Action container. Parent for [[ArgumentParser]] and [[ArgumentGroup]]
**/
'use strict';
var format = require('util').format;
// Constants
var c = require('./const');
var $$ = require('./utils');
//Actions
var ActionHelp = require('./action/help');
var ActionAppend = require('./action/append');
var ActionAppendConstant = require('./action/append/constant');
var ActionCount = require('./action/count');
var ActionStore = require('./action/store');
var ActionStoreConstant = require('./action/store/constant');
var ActionStoreTrue = require('./action/store/true');
var ActionStoreFalse = require('./action/store/false');
var ActionVersion = require('./action/version');
var ActionSubparsers = require('./action/subparsers');
// Errors
var argumentErrorHelper = require('./argument/error');
/**
* new ActionContainer(options)
*
* Action container. Parent for [[ArgumentParser]] and [[ArgumentGroup]]
*
* ##### Options:
*
* - `description` -- A description of what the program does
* - `prefixChars` -- Characters that prefix optional arguments
* - `argumentDefault` -- The default value for all arguments
* - `conflictHandler` -- The conflict handler to use for duplicate arguments
**/
var ActionContainer = module.exports = function ActionContainer(options) {
options = options || {};
this.description = options.description;
this.argumentDefault = options.argumentDefault;
this.prefixChars = options.prefixChars || '';
this.conflictHandler = options.conflictHandler;
// set up registries
this._registries = {};
// register actions
this.register('action', null, ActionStore);
this.register('action', 'store', ActionStore);
this.register('action', 'storeConst', ActionStoreConstant);
this.register('action', 'storeTrue', ActionStoreTrue);
this.register('action', 'storeFalse', ActionStoreFalse);
this.register('action', 'append', ActionAppend);
this.register('action', 'appendConst', ActionAppendConstant);
this.register('action', 'count', ActionCount);
this.register('action', 'help', ActionHelp);
this.register('action', 'version', ActionVersion);
this.register('action', 'parsers', ActionSubparsers);
// raise an exception if the conflict handler is invalid
this._getHandler();
// action storage
this._actions = [];
this._optionStringActions = {};
// groups
this._actionGroups = [];
this._mutuallyExclusiveGroups = [];
// defaults storage
this._defaults = {};
// determines whether an "option" looks like a negative number
// -1, -1.5 -5e+4
this._regexpNegativeNumber = new RegExp('^[-]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$');
// whether or not there are any optionals that look like negative
// numbers -- uses a list so it can be shared and edited
this._hasNegativeNumberOptionals = [];
};
// Groups must be required, then ActionContainer already defined
var ArgumentGroup = require('./argument/group');
var MutuallyExclusiveGroup = require('./argument/exclusive');
//
// Registration methods
//
/**
* ActionContainer#register(registryName, value, object) -> Void
* - registryName (String) : object type action|type
* - value (string) : keyword
* - object (Object|Function) : handler
*
* Register handlers
**/
ActionContainer.prototype.register = function (registryName, value, object) {
this._registries[registryName] = this._registries[registryName] || {};
this._registries[registryName][value] = object;
};
ActionContainer.prototype._registryGet = function (registryName, value, defaultValue) {
if (arguments.length < 3) {
defaultValue = null;
}
return this._registries[registryName][value] || defaultValue;
};
//
// Namespace default accessor methods
//
/**
* ActionContainer#setDefaults(options) -> Void
* - options (object):hash of options see [[Action.new]]
*
* Set defaults
**/
ActionContainer.prototype.setDefaults = function (options) {
options = options || {};
for (var property in options) {
if ($$.has(options, property)) {
this._defaults[property] = options[property];
}
}
// if these defaults match any existing arguments, replace the previous
// default on the object with the new one
this._actions.forEach(function (action) {
if ($$.has(options, action.dest)) {
action.defaultValue = options[action.dest];
}
});
};
/**
* ActionContainer#getDefault(dest) -> Mixed
* - dest (string): action destination
*
* Return action default value
**/
ActionContainer.prototype.getDefault = function (dest) {
var result = $$.has(this._defaults, dest) ? this._defaults[dest] : null;
this._actions.forEach(function (action) {
if (action.dest === dest && $$.has(action, 'defaultValue')) {
result = action.defaultValue;
}
});
return result;
};
//
// Adding argument actions
//
/**
* ActionContainer#addArgument(args, options) -> Object
* - args (String|Array): argument key, or array of argument keys
* - options (Object): action objects see [[Action.new]]
*
* #### Examples
* - addArgument([ '-f', '--foo' ], { action: 'store', defaultValue: 1, ... })
* - addArgument([ 'bar' ], { action: 'store', nargs: 1, ... })
* - addArgument('--baz', { action: 'store', nargs: 1, ... })
**/
ActionContainer.prototype.addArgument = function (args, options) {
args = args;
options = options || {};
if (typeof args === 'string') {
args = [ args ];
}
if (!Array.isArray(args)) {
throw new TypeError('addArgument first argument should be a string or an array');
}
if (typeof options !== 'object' || Array.isArray(options)) {
throw new TypeError('addArgument second argument should be a hash');
}
// if no positional args are supplied or only one is supplied and
// it doesn't look like an option string, parse a positional argument
if (!args || args.length === 1 && this.prefixChars.indexOf(args[0][0]) < 0) {
if (args && !!options.dest) {
throw new Error('dest supplied twice for positional argument');
}
options = this._getPositional(args, options);
// otherwise, we're adding an optional argument
} else {
options = this._getOptional(args, options);
}
// if no default was supplied, use the parser-level default
if (typeof options.defaultValue === 'undefined') {
var dest = options.dest;
if ($$.has(this._defaults, dest)) {
options.defaultValue = this._defaults[dest];
} else if (typeof this.argumentDefault !== 'undefined') {
options.defaultValue = this.argumentDefault;
}
}
// create the action object, and add it to the parser
var ActionClass = this._popActionClass(options);
if (typeof ActionClass !== 'function') {
throw new Error(format('Unknown action "%s".', ActionClass));
}
var action = new ActionClass(options);
// throw an error if the action type is not callable
var typeFunction = this._registryGet('type', action.type, action.type);
if (typeof typeFunction !== 'function') {
throw new Error(format('"%s" is not callable', typeFunction));
}
return this._addAction(action);
};
/**
* ActionContainer#addArgumentGroup(options) -> ArgumentGroup
* - options (Object): hash of options see [[ArgumentGroup.new]]
*
* Create new arguments groups
**/
ActionContainer.prototype.addArgumentGroup = function (options) {
var group = new ArgumentGroup(this, options);
this._actionGroups.push(group);
return group;
};
/**
* ActionContainer#addMutuallyExclusiveGroup(options) -> ArgumentGroup
* - options (Object): {required: false}
*
* Create new mutual exclusive groups
**/
ActionContainer.prototype.addMutuallyExclusiveGroup = function (options) {
var group = new MutuallyExclusiveGroup(this, options);
this._mutuallyExclusiveGroups.push(group);
return group;
};
ActionContainer.prototype._addAction = function (action) {
var self = this;
// resolve any conflicts
this._checkConflict(action);
// add to actions list
this._actions.push(action);
action.container = this;
// index the action by any option strings it has
action.optionStrings.forEach(function (optionString) {
self._optionStringActions[optionString] = action;
});
// set the flag if any option strings look like negative numbers
action.optionStrings.forEach(function (optionString) {
if (optionString.match(self._regexpNegativeNumber)) {
if (!self._hasNegativeNumberOptionals.some(Boolean)) {
self._hasNegativeNumberOptionals.push(true);
}
}
});
// return the created action
return action;
};
ActionContainer.prototype._removeAction = function (action) {
var actionIndex = this._actions.indexOf(action);
if (actionIndex >= 0) {
this._actions.splice(actionIndex, 1);
}
};
ActionContainer.prototype._addContainerActions = function (container) {
// collect groups by titles
var titleGroupMap = {};
this._actionGroups.forEach(function (group) {
if (titleGroupMap[group.title]) {
throw new Error(format('Cannot merge actions - two groups are named "%s".', group.title));
}
titleGroupMap[group.title] = group;
});
// map each action to its group
var groupMap = {};
function actionHash(action) {
// unique (hopefully?) string suitable as dictionary key
return action.getName();
}
container._actionGroups.forEach(function (group) {
// if a group with the title exists, use that, otherwise
// create a new group matching the container's group
if (!titleGroupMap[group.title]) {
titleGroupMap[group.title] = this.addArgumentGroup({
title: group.title,
description: group.description
});
}
// map the actions to their new group
group._groupActions.forEach(function (action) {
groupMap[actionHash(action)] = titleGroupMap[group.title];
});
}, this);
// add container's mutually exclusive groups
// NOTE: if add_mutually_exclusive_group ever gains title= and
// description= then this code will need to be expanded as above
var mutexGroup;
container._mutuallyExclusiveGroups.forEach(function (group) {
mutexGroup = this.addMutuallyExclusiveGroup({
required: group.required
});
// map the actions to their new mutex group
group._groupActions.forEach(function (action) {
groupMap[actionHash(action)] = mutexGroup;
});
}, this); // forEach takes a 'this' argument
// add all actions to this container or their group
container._actions.forEach(function (action) {
var key = actionHash(action);
if (groupMap[key]) {
groupMap[key]._addAction(action);
} else {
this._addAction(action);
}
});
};
ActionContainer.prototype._getPositional = function (dest, options) {
if (Array.isArray(dest)) {
dest = dest[0];
}
// make sure required is not specified
if (options.required) {
throw new Error('"required" is an invalid argument for positionals.');
}
// mark positional arguments as required if at least one is
// always required
if (options.nargs !== c.OPTIONAL && options.nargs !== c.ZERO_OR_MORE) {
options.required = true;
}
if (options.nargs === c.ZERO_OR_MORE && typeof options.defaultValue === 'undefined') {
options.required = true;
}
// return the keyword arguments with no option strings
options.dest = dest;
options.optionStrings = [];
return options;
};
ActionContainer.prototype._getOptional = function (args, options) {
var prefixChars = this.prefixChars;
var optionStrings = [];
var optionStringsLong = [];
// determine short and long option strings
args.forEach(function (optionString) {
// error on strings that don't start with an appropriate prefix
if (prefixChars.indexOf(optionString[0]) < 0) {
throw new Error(format('Invalid option string "%s": must start with a "%s".',
optionString,
prefixChars
));
}
// strings starting with two prefix characters are long options
optionStrings.push(optionString);
if (optionString.length > 1 && prefixChars.indexOf(optionString[1]) >= 0) {
optionStringsLong.push(optionString);
}
});
// infer dest, '--foo-bar' -> 'foo_bar' and '-x' -> 'x'
var dest = options.dest || null;
delete options.dest;
if (!dest) {
var optionStringDest = optionStringsLong.length ? optionStringsLong[0] : optionStrings[0];
dest = $$.trimChars(optionStringDest, this.prefixChars);
if (dest.length === 0) {
throw new Error(
format('dest= is required for options like "%s"', optionStrings.join(', '))
);
}
dest = dest.replace(/-/g, '_');
}
// return the updated keyword arguments
options.dest = dest;
options.optionStrings = optionStrings;
return options;
};
ActionContainer.prototype._popActionClass = function (options, defaultValue) {
defaultValue = defaultValue || null;
var action = (options.action || defaultValue);
delete options.action;
var actionClass = this._registryGet('action', action, action);
return actionClass;
};
ActionContainer.prototype._getHandler = function () {
var handlerString = this.conflictHandler;
var handlerFuncName = '_handleConflict' + $$.capitalize(handlerString);
var func = this[handlerFuncName];
if (typeof func === 'undefined') {
var msg = 'invalid conflict resolution value: ' + handlerString;
throw new Error(msg);
} else {
return func;
}
};
ActionContainer.prototype._checkConflict = function (action) {
var optionStringActions = this._optionStringActions;
var conflictOptionals = [];
// find all options that conflict with this option
// collect pairs, the string, and an existing action that it conflicts with
action.optionStrings.forEach(function (optionString) {
var conflOptional = optionStringActions[optionString];
if (typeof conflOptional !== 'undefined') {
conflictOptionals.push([ optionString, conflOptional ]);
}
});
if (conflictOptionals.length > 0) {
var conflictHandler = this._getHandler();
conflictHandler.call(this, action, conflictOptionals);
}
};
ActionContainer.prototype._handleConflictError = function (action, conflOptionals) {
var conflicts = conflOptionals.map(function (pair) { return pair[0]; });
conflicts = conflicts.join(', ');
throw argumentErrorHelper(
action,
format('Conflicting option string(s): %s', conflicts)
);
};
ActionContainer.prototype._handleConflictResolve = function (action, conflOptionals) {
// remove all conflicting options
var self = this;
conflOptionals.forEach(function (pair) {
var optionString = pair[0];
var conflictingAction = pair[1];
// remove the conflicting option string
var i = conflictingAction.optionStrings.indexOf(optionString);
if (i >= 0) {
conflictingAction.optionStrings.splice(i, 1);
}
delete self._optionStringActions[optionString];
// if the option now has no option string, remove it from the
// container holding it
if (conflictingAction.optionStrings.length === 0) {
conflictingAction.container._removeAction(conflictingAction);
}
});
};

View file

@ -1,14 +0,0 @@
'use strict';
module.exports.ArgumentParser = require('./argument_parser.js');
module.exports.Namespace = require('./namespace');
module.exports.Action = require('./action');
module.exports.HelpFormatter = require('./help/formatter.js');
module.exports.Const = require('./const.js');
module.exports.ArgumentDefaultsHelpFormatter =
require('./help/added_formatters.js').ArgumentDefaultsHelpFormatter;
module.exports.RawDescriptionHelpFormatter =
require('./help/added_formatters.js').RawDescriptionHelpFormatter;
module.exports.RawTextHelpFormatter =
require('./help/added_formatters.js').RawTextHelpFormatter;

View file

@ -1,50 +0,0 @@
'use strict';
var format = require('util').format;
var ERR_CODE = 'ARGError';
/*:nodoc:*
* argumentError(argument, message) -> TypeError
* - argument (Object): action with broken argument
* - message (String): error message
*
* Error format helper. An error from creating or using an argument
* (optional or positional). The string value of this exception
* is the message, augmented with information
* about the argument that caused it.
*
* #####Example
*
* var argumentErrorHelper = require('./argument/error');
* if (conflictOptionals.length > 0) {
* throw argumentErrorHelper(
* action,
* format('Conflicting option string(s): %s', conflictOptionals.join(', '))
* );
* }
*
**/
module.exports = function (argument, message) {
var argumentName = null;
var errMessage;
var err;
if (argument.getName) {
argumentName = argument.getName();
} else {
argumentName = '' + argument;
}
if (!argumentName) {
errMessage = message;
} else {
errMessage = format('argument "%s": %s', argumentName, message);
}
err = new TypeError(errMessage);
err.code = ERR_CODE;
return err;
};

View file

@ -1,54 +0,0 @@
/** internal
* class MutuallyExclusiveGroup
*
* Group arguments.
* By default, ArgumentParser groups command-line arguments
* into positional arguments and optional arguments
* when displaying help messages. When there is a better
* conceptual grouping of arguments than this default one,
* appropriate groups can be created using the addArgumentGroup() method
*
* This class inherited from [[ArgumentContainer]]
**/
'use strict';
var util = require('util');
var ArgumentGroup = require('./group');
/**
* new MutuallyExclusiveGroup(container, options)
* - container (object): main container
* - options (object): options.required -> true/false
*
* `required` could be an argument itself, but making it a property of
* the options argument is more consistent with the JS adaptation of the Python)
**/
var MutuallyExclusiveGroup = module.exports = function MutuallyExclusiveGroup(container, options) {
var required;
options = options || {};
required = options.required || false;
ArgumentGroup.call(this, container);
this.required = required;
};
util.inherits(MutuallyExclusiveGroup, ArgumentGroup);
MutuallyExclusiveGroup.prototype._addAction = function (action) {
var msg;
if (action.required) {
msg = 'mutually exclusive arguments must be optional';
throw new Error(msg);
}
action = this._container._addAction(action);
this._groupActions.push(action);
return action;
};
MutuallyExclusiveGroup.prototype._removeAction = function (action) {
this._container._removeAction(action);
this._groupActions.remove(action);
};

View file

@ -1,75 +0,0 @@
/** internal
* class ArgumentGroup
*
* Group arguments.
* By default, ArgumentParser groups command-line arguments
* into positional arguments and optional arguments
* when displaying help messages. When there is a better
* conceptual grouping of arguments than this default one,
* appropriate groups can be created using the addArgumentGroup() method
*
* This class inherited from [[ArgumentContainer]]
**/
'use strict';
var util = require('util');
var ActionContainer = require('../action_container');
/**
* new ArgumentGroup(container, options)
* - container (object): main container
* - options (object): hash of group options
*
* #### options
* - **prefixChars** group name prefix
* - **argumentDefault** default argument value
* - **title** group title
* - **description** group description
*
**/
var ArgumentGroup = module.exports = function ArgumentGroup(container, options) {
options = options || {};
// add any missing keyword arguments by checking the container
options.conflictHandler = (options.conflictHandler || container.conflictHandler);
options.prefixChars = (options.prefixChars || container.prefixChars);
options.argumentDefault = (options.argumentDefault || container.argumentDefault);
ActionContainer.call(this, options);
// group attributes
this.title = options.title;
this._groupActions = [];
// share most attributes with the container
this._container = container;
this._registries = container._registries;
this._actions = container._actions;
this._optionStringActions = container._optionStringActions;
this._defaults = container._defaults;
this._hasNegativeNumberOptionals = container._hasNegativeNumberOptionals;
this._mutuallyExclusiveGroups = container._mutuallyExclusiveGroups;
};
util.inherits(ArgumentGroup, ActionContainer);
ArgumentGroup.prototype._addAction = function (action) {
// Parent add action
action = ActionContainer.prototype._addAction.call(this, action);
this._groupActions.push(action);
return action;
};
ArgumentGroup.prototype._removeAction = function (action) {
// Parent remove action
ActionContainer.prototype._removeAction.call(this, action);
var actionIndex = this._groupActions.indexOf(action);
if (actionIndex >= 0) {
this._groupActions.splice(actionIndex, 1);
}
};

File diff suppressed because it is too large Load diff

View file

@ -1,21 +0,0 @@
//
// Constants
//
'use strict';
module.exports.EOL = '\n';
module.exports.SUPPRESS = '==SUPPRESS==';
module.exports.OPTIONAL = '?';
module.exports.ZERO_OR_MORE = '*';
module.exports.ONE_OR_MORE = '+';
module.exports.PARSER = 'A...';
module.exports.REMAINDER = '...';
module.exports._UNRECOGNIZED_ARGS_ATTR = '_unrecognized_args';

View file

@ -1,87 +0,0 @@
'use strict';
var util = require('util');
// Constants
var c = require('../const');
var $$ = require('../utils');
var HelpFormatter = require('./formatter.js');
/**
* new RawDescriptionHelpFormatter(options)
* new ArgumentParser({formatterClass: argparse.RawDescriptionHelpFormatter, ...})
*
* Help message formatter which adds default values to argument help.
*
* Only the name of this class is considered a public API. All the methods
* provided by the class are considered an implementation detail.
**/
function ArgumentDefaultsHelpFormatter(options) {
HelpFormatter.call(this, options);
}
util.inherits(ArgumentDefaultsHelpFormatter, HelpFormatter);
ArgumentDefaultsHelpFormatter.prototype._getHelpString = function (action) {
var help = action.help;
if (action.help.indexOf('%(defaultValue)s') === -1) {
if (action.defaultValue !== c.SUPPRESS) {
var defaulting_nargs = [ c.OPTIONAL, c.ZERO_OR_MORE ];
if (action.isOptional() || (defaulting_nargs.indexOf(action.nargs) >= 0)) {
help += ' (default: %(defaultValue)s)';
}
}
}
return help;
};
module.exports.ArgumentDefaultsHelpFormatter = ArgumentDefaultsHelpFormatter;
/**
* new RawDescriptionHelpFormatter(options)
* new ArgumentParser({formatterClass: argparse.RawDescriptionHelpFormatter, ...})
*
* Help message formatter which retains any formatting in descriptions.
*
* Only the name of this class is considered a public API. All the methods
* provided by the class are considered an implementation detail.
**/
function RawDescriptionHelpFormatter(options) {
HelpFormatter.call(this, options);
}
util.inherits(RawDescriptionHelpFormatter, HelpFormatter);
RawDescriptionHelpFormatter.prototype._fillText = function (text, width, indent) {
var lines = text.split('\n');
lines = lines.map(function (line) {
return $$.trimEnd(indent + line);
});
return lines.join('\n');
};
module.exports.RawDescriptionHelpFormatter = RawDescriptionHelpFormatter;
/**
* new RawTextHelpFormatter(options)
* new ArgumentParser({formatterClass: argparse.RawTextHelpFormatter, ...})
*
* Help message formatter which retains formatting of all help text.
*
* Only the name of this class is considered a public API. All the methods
* provided by the class are considered an implementation detail.
**/
function RawTextHelpFormatter(options) {
RawDescriptionHelpFormatter.call(this, options);
}
util.inherits(RawTextHelpFormatter, RawDescriptionHelpFormatter);
RawTextHelpFormatter.prototype._splitLines = function (text) {
return text.split('\n');
};
module.exports.RawTextHelpFormatter = RawTextHelpFormatter;

View file

@ -1,795 +0,0 @@
/**
* class HelpFormatter
*
* Formatter for generating usage messages and argument help strings. Only the
* name of this class is considered a public API. All the methods provided by
* the class are considered an implementation detail.
*
* Do not call in your code, use this class only for inherits your own forvatter
*
* ToDo add [additonal formatters][1]
*
* [1]:http://docs.python.org/dev/library/argparse.html#formatter-class
**/
'use strict';
var sprintf = require('sprintf-js').sprintf;
// Constants
var c = require('../const');
var $$ = require('../utils');
/*:nodoc:* internal
* new Support(parent, heding)
* - parent (object): parent section
* - heading (string): header string
*
**/
function Section(parent, heading) {
this._parent = parent;
this._heading = heading;
this._items = [];
}
/*:nodoc:* internal
* Section#addItem(callback) -> Void
* - callback (array): tuple with function and args
*
* Add function for single element
**/
Section.prototype.addItem = function (callback) {
this._items.push(callback);
};
/*:nodoc:* internal
* Section#formatHelp(formatter) -> string
* - formatter (HelpFormatter): current formatter
*
* Form help section string
*
**/
Section.prototype.formatHelp = function (formatter) {
var itemHelp, heading;
// format the indented section
if (this._parent) {
formatter._indent();
}
itemHelp = this._items.map(function (item) {
var obj, func, args;
obj = formatter;
func = item[0];
args = item[1];
return func.apply(obj, args);
});
itemHelp = formatter._joinParts(itemHelp);
if (this._parent) {
formatter._dedent();
}
// return nothing if the section was empty
if (!itemHelp) {
return '';
}
// add the heading if the section was non-empty
heading = '';
if (this._heading && this._heading !== c.SUPPRESS) {
var currentIndent = formatter.currentIndent;
heading = $$.repeat(' ', currentIndent) + this._heading + ':' + c.EOL;
}
// join the section-initialize newline, the heading and the help
return formatter._joinParts([ c.EOL, heading, itemHelp, c.EOL ]);
};
/**
* new HelpFormatter(options)
*
* #### Options:
* - `prog`: program name
* - `indentIncriment`: indent step, default value 2
* - `maxHelpPosition`: max help position, default value = 24
* - `width`: line width
*
**/
var HelpFormatter = module.exports = function HelpFormatter(options) {
options = options || {};
this._prog = options.prog;
this._maxHelpPosition = options.maxHelpPosition || 24;
this._width = (options.width || ((process.env.COLUMNS || 80) - 2));
this._currentIndent = 0;
this._indentIncriment = options.indentIncriment || 2;
this._level = 0;
this._actionMaxLength = 0;
this._rootSection = new Section(null);
this._currentSection = this._rootSection;
this._whitespaceMatcher = new RegExp('\\s+', 'g');
this._longBreakMatcher = new RegExp(c.EOL + c.EOL + c.EOL + '+', 'g');
};
HelpFormatter.prototype._indent = function () {
this._currentIndent += this._indentIncriment;
this._level += 1;
};
HelpFormatter.prototype._dedent = function () {
this._currentIndent -= this._indentIncriment;
this._level -= 1;
if (this._currentIndent < 0) {
throw new Error('Indent decreased below 0.');
}
};
HelpFormatter.prototype._addItem = function (func, args) {
this._currentSection.addItem([ func, args ]);
};
//
// Message building methods
//
/**
* HelpFormatter#startSection(heading) -> Void
* - heading (string): header string
*
* Start new help section
*
* See alse [code example][1]
*
* ##### Example
*
* formatter.startSection(actionGroup.title);
* formatter.addText(actionGroup.description);
* formatter.addArguments(actionGroup._groupActions);
* formatter.endSection();
*
**/
HelpFormatter.prototype.startSection = function (heading) {
this._indent();
var section = new Section(this._currentSection, heading);
var func = section.formatHelp.bind(section);
this._addItem(func, [ this ]);
this._currentSection = section;
};
/**
* HelpFormatter#endSection -> Void
*
* End help section
*
* ##### Example
*
* formatter.startSection(actionGroup.title);
* formatter.addText(actionGroup.description);
* formatter.addArguments(actionGroup._groupActions);
* formatter.endSection();
**/
HelpFormatter.prototype.endSection = function () {
this._currentSection = this._currentSection._parent;
this._dedent();
};
/**
* HelpFormatter#addText(text) -> Void
* - text (string): plain text
*
* Add plain text into current section
*
* ##### Example
*
* formatter.startSection(actionGroup.title);
* formatter.addText(actionGroup.description);
* formatter.addArguments(actionGroup._groupActions);
* formatter.endSection();
*
**/
HelpFormatter.prototype.addText = function (text) {
if (text && text !== c.SUPPRESS) {
this._addItem(this._formatText, [ text ]);
}
};
/**
* HelpFormatter#addUsage(usage, actions, groups, prefix) -> Void
* - usage (string): usage text
* - actions (array): actions list
* - groups (array): groups list
* - prefix (string): usage prefix
*
* Add usage data into current section
*
* ##### Example
*
* formatter.addUsage(this.usage, this._actions, []);
* return formatter.formatHelp();
*
**/
HelpFormatter.prototype.addUsage = function (usage, actions, groups, prefix) {
if (usage !== c.SUPPRESS) {
this._addItem(this._formatUsage, [ usage, actions, groups, prefix ]);
}
};
/**
* HelpFormatter#addArgument(action) -> Void
* - action (object): action
*
* Add argument into current section
*
* Single variant of [[HelpFormatter#addArguments]]
**/
HelpFormatter.prototype.addArgument = function (action) {
if (action.help !== c.SUPPRESS) {
var self = this;
// find all invocations
var invocations = [ this._formatActionInvocation(action) ];
var invocationLength = invocations[0].length;
var actionLength;
if (action._getSubactions) {
this._indent();
action._getSubactions().forEach(function (subaction) {
var invocationNew = self._formatActionInvocation(subaction);
invocations.push(invocationNew);
invocationLength = Math.max(invocationLength, invocationNew.length);
});
this._dedent();
}
// update the maximum item length
actionLength = invocationLength + this._currentIndent;
this._actionMaxLength = Math.max(this._actionMaxLength, actionLength);
// add the item to the list
this._addItem(this._formatAction, [ action ]);
}
};
/**
* HelpFormatter#addArguments(actions) -> Void
* - actions (array): actions list
*
* Mass add arguments into current section
*
* ##### Example
*
* formatter.startSection(actionGroup.title);
* formatter.addText(actionGroup.description);
* formatter.addArguments(actionGroup._groupActions);
* formatter.endSection();
*
**/
HelpFormatter.prototype.addArguments = function (actions) {
var self = this;
actions.forEach(function (action) {
self.addArgument(action);
});
};
//
// Help-formatting methods
//
/**
* HelpFormatter#formatHelp -> string
*
* Format help
*
* ##### Example
*
* formatter.addText(this.epilog);
* return formatter.formatHelp();
*
**/
HelpFormatter.prototype.formatHelp = function () {
var help = this._rootSection.formatHelp(this);
if (help) {
help = help.replace(this._longBreakMatcher, c.EOL + c.EOL);
help = $$.trimChars(help, c.EOL) + c.EOL;
}
return help;
};
HelpFormatter.prototype._joinParts = function (partStrings) {
return partStrings.filter(function (part) {
return (part && part !== c.SUPPRESS);
}).join('');
};
HelpFormatter.prototype._formatUsage = function (usage, actions, groups, prefix) {
if (!prefix && typeof prefix !== 'string') {
prefix = 'usage: ';
}
actions = actions || [];
groups = groups || [];
// if usage is specified, use that
if (usage) {
usage = sprintf(usage, { prog: this._prog });
// if no optionals or positionals are available, usage is just prog
} else if (!usage && actions.length === 0) {
usage = this._prog;
// if optionals and positionals are available, calculate usage
} else if (!usage) {
var prog = this._prog;
var optionals = [];
var positionals = [];
var actionUsage;
var textWidth;
// split optionals from positionals
actions.forEach(function (action) {
if (action.isOptional()) {
optionals.push(action);
} else {
positionals.push(action);
}
});
// build full usage string
actionUsage = this._formatActionsUsage([].concat(optionals, positionals), groups);
usage = [ prog, actionUsage ].join(' ');
// wrap the usage parts if it's too long
textWidth = this._width - this._currentIndent;
if ((prefix.length + usage.length) > textWidth) {
// break usage into wrappable parts
var regexpPart = new RegExp('\\(.*?\\)+|\\[.*?\\]+|\\S+', 'g');
var optionalUsage = this._formatActionsUsage(optionals, groups);
var positionalUsage = this._formatActionsUsage(positionals, groups);
var optionalParts = optionalUsage.match(regexpPart);
var positionalParts = positionalUsage.match(regexpPart) || [];
if (optionalParts.join(' ') !== optionalUsage) {
throw new Error('assert "optionalParts.join(\' \') === optionalUsage"');
}
if (positionalParts.join(' ') !== positionalUsage) {
throw new Error('assert "positionalParts.join(\' \') === positionalUsage"');
}
// helper for wrapping lines
/*eslint-disable func-style*/ // node 0.10 compat
var _getLines = function (parts, indent, prefix) {
var lines = [];
var line = [];
var lineLength = prefix ? prefix.length - 1 : indent.length - 1;
parts.forEach(function (part) {
if (lineLength + 1 + part.length > textWidth) {
lines.push(indent + line.join(' '));
line = [];
lineLength = indent.length - 1;
}
line.push(part);
lineLength += part.length + 1;
});
if (line) {
lines.push(indent + line.join(' '));
}
if (prefix) {
lines[0] = lines[0].substr(indent.length);
}
return lines;
};
var lines, indent, parts;
// if prog is short, follow it with optionals or positionals
if (prefix.length + prog.length <= 0.75 * textWidth) {
indent = $$.repeat(' ', (prefix.length + prog.length + 1));
if (optionalParts) {
lines = [].concat(
_getLines([ prog ].concat(optionalParts), indent, prefix),
_getLines(positionalParts, indent)
);
} else if (positionalParts) {
lines = _getLines([ prog ].concat(positionalParts), indent, prefix);
} else {
lines = [ prog ];
}
// if prog is long, put it on its own line
} else {
indent = $$.repeat(' ', prefix.length);
parts = optionalParts.concat(positionalParts);
lines = _getLines(parts, indent);
if (lines.length > 1) {
lines = [].concat(
_getLines(optionalParts, indent),
_getLines(positionalParts, indent)
);
}
lines = [ prog ].concat(lines);
}
// join lines into usage
usage = lines.join(c.EOL);
}
}
// prefix with 'usage:'
return prefix + usage + c.EOL + c.EOL;
};
HelpFormatter.prototype._formatActionsUsage = function (actions, groups) {
// find group indices and identify actions in groups
var groupActions = [];
var inserts = [];
var self = this;
groups.forEach(function (group) {
var end;
var i;
var start = actions.indexOf(group._groupActions[0]);
if (start >= 0) {
end = start + group._groupActions.length;
//if (actions.slice(start, end) === group._groupActions) {
if ($$.arrayEqual(actions.slice(start, end), group._groupActions)) {
group._groupActions.forEach(function (action) {
groupActions.push(action);
});
if (!group.required) {
if (inserts[start]) {
inserts[start] += ' [';
} else {
inserts[start] = '[';
}
inserts[end] = ']';
} else {
if (inserts[start]) {
inserts[start] += ' (';
} else {
inserts[start] = '(';
}
inserts[end] = ')';
}
for (i = start + 1; i < end; i += 1) {
inserts[i] = '|';
}
}
}
});
// collect all actions format strings
var parts = [];
actions.forEach(function (action, actionIndex) {
var part;
var optionString;
var argsDefault;
var argsString;
// suppressed arguments are marked with None
// remove | separators for suppressed arguments
if (action.help === c.SUPPRESS) {
parts.push(null);
if (inserts[actionIndex] === '|') {
inserts.splice(actionIndex, actionIndex);
} else if (inserts[actionIndex + 1] === '|') {
inserts.splice(actionIndex + 1, actionIndex + 1);
}
// produce all arg strings
} else if (!action.isOptional()) {
part = self._formatArgs(action, action.dest);
// if it's in a group, strip the outer []
if (groupActions.indexOf(action) >= 0) {
if (part[0] === '[' && part[part.length - 1] === ']') {
part = part.slice(1, -1);
}
}
// add the action string to the list
parts.push(part);
// produce the first way to invoke the option in brackets
} else {
optionString = action.optionStrings[0];
// if the Optional doesn't take a value, format is: -s or --long
if (action.nargs === 0) {
part = '' + optionString;
// if the Optional takes a value, format is: -s ARGS or --long ARGS
} else {
argsDefault = action.dest.toUpperCase();
argsString = self._formatArgs(action, argsDefault);
part = optionString + ' ' + argsString;
}
// make it look optional if it's not required or in a group
if (!action.required && groupActions.indexOf(action) < 0) {
part = '[' + part + ']';
}
// add the action string to the list
parts.push(part);
}
});
// insert things at the necessary indices
for (var i = inserts.length - 1; i >= 0; --i) {
if (inserts[i] !== null) {
parts.splice(i, 0, inserts[i]);
}
}
// join all the action items with spaces
var text = parts.filter(function (part) {
return !!part;
}).join(' ');
// clean up separators for mutually exclusive groups
text = text.replace(/([\[(]) /g, '$1'); // remove spaces
text = text.replace(/ ([\])])/g, '$1');
text = text.replace(/\[ *\]/g, ''); // remove empty groups
text = text.replace(/\( *\)/g, '');
text = text.replace(/\(([^|]*)\)/g, '$1'); // remove () from single action groups
text = text.trim();
// return the text
return text;
};
HelpFormatter.prototype._formatText = function (text) {
text = sprintf(text, { prog: this._prog });
var textWidth = this._width - this._currentIndent;
var indentIncriment = $$.repeat(' ', this._currentIndent);
return this._fillText(text, textWidth, indentIncriment) + c.EOL + c.EOL;
};
HelpFormatter.prototype._formatAction = function (action) {
var self = this;
var helpText;
var helpLines;
var parts;
var indentFirst;
// determine the required width and the entry label
var helpPosition = Math.min(this._actionMaxLength + 2, this._maxHelpPosition);
var helpWidth = this._width - helpPosition;
var actionWidth = helpPosition - this._currentIndent - 2;
var actionHeader = this._formatActionInvocation(action);
// no help; start on same line and add a final newline
if (!action.help) {
actionHeader = $$.repeat(' ', this._currentIndent) + actionHeader + c.EOL;
// short action name; start on the same line and pad two spaces
} else if (actionHeader.length <= actionWidth) {
actionHeader = $$.repeat(' ', this._currentIndent) +
actionHeader +
' ' +
$$.repeat(' ', actionWidth - actionHeader.length);
indentFirst = 0;
// long action name; start on the next line
} else {
actionHeader = $$.repeat(' ', this._currentIndent) + actionHeader + c.EOL;
indentFirst = helpPosition;
}
// collect the pieces of the action help
parts = [ actionHeader ];
// if there was help for the action, add lines of help text
if (action.help) {
helpText = this._expandHelp(action);
helpLines = this._splitLines(helpText, helpWidth);
parts.push($$.repeat(' ', indentFirst) + helpLines[0] + c.EOL);
helpLines.slice(1).forEach(function (line) {
parts.push($$.repeat(' ', helpPosition) + line + c.EOL);
});
// or add a newline if the description doesn't end with one
} else if (actionHeader.charAt(actionHeader.length - 1) !== c.EOL) {
parts.push(c.EOL);
}
// if there are any sub-actions, add their help as well
if (action._getSubactions) {
this._indent();
action._getSubactions().forEach(function (subaction) {
parts.push(self._formatAction(subaction));
});
this._dedent();
}
// return a single string
return this._joinParts(parts);
};
HelpFormatter.prototype._formatActionInvocation = function (action) {
if (!action.isOptional()) {
var format_func = this._metavarFormatter(action, action.dest);
var metavars = format_func(1);
return metavars[0];
}
var parts = [];
var argsDefault;
var argsString;
// if the Optional doesn't take a value, format is: -s, --long
if (action.nargs === 0) {
parts = parts.concat(action.optionStrings);
// if the Optional takes a value, format is: -s ARGS, --long ARGS
} else {
argsDefault = action.dest.toUpperCase();
argsString = this._formatArgs(action, argsDefault);
action.optionStrings.forEach(function (optionString) {
parts.push(optionString + ' ' + argsString);
});
}
return parts.join(', ');
};
HelpFormatter.prototype._metavarFormatter = function (action, metavarDefault) {
var result;
if (action.metavar || action.metavar === '') {
result = action.metavar;
} else if (action.choices) {
var choices = action.choices;
if (typeof choices === 'string') {
choices = choices.split('').join(', ');
} else if (Array.isArray(choices)) {
choices = choices.join(',');
} else {
choices = Object.keys(choices).join(',');
}
result = '{' + choices + '}';
} else {
result = metavarDefault;
}
return function (size) {
if (Array.isArray(result)) {
return result;
}
var metavars = [];
for (var i = 0; i < size; i += 1) {
metavars.push(result);
}
return metavars;
};
};
HelpFormatter.prototype._formatArgs = function (action, metavarDefault) {
var result;
var metavars;
var buildMetavar = this._metavarFormatter(action, metavarDefault);
switch (action.nargs) {
/*eslint-disable no-undefined*/
case undefined:
case null:
metavars = buildMetavar(1);
result = '' + metavars[0];
break;
case c.OPTIONAL:
metavars = buildMetavar(1);
result = '[' + metavars[0] + ']';
break;
case c.ZERO_OR_MORE:
metavars = buildMetavar(2);
result = '[' + metavars[0] + ' [' + metavars[1] + ' ...]]';
break;
case c.ONE_OR_MORE:
metavars = buildMetavar(2);
result = '' + metavars[0] + ' [' + metavars[1] + ' ...]';
break;
case c.REMAINDER:
result = '...';
break;
case c.PARSER:
metavars = buildMetavar(1);
result = metavars[0] + ' ...';
break;
default:
metavars = buildMetavar(action.nargs);
result = metavars.join(' ');
}
return result;
};
HelpFormatter.prototype._expandHelp = function (action) {
var params = { prog: this._prog };
Object.keys(action).forEach(function (actionProperty) {
var actionValue = action[actionProperty];
if (actionValue !== c.SUPPRESS) {
params[actionProperty] = actionValue;
}
});
if (params.choices) {
if (typeof params.choices === 'string') {
params.choices = params.choices.split('').join(', ');
} else if (Array.isArray(params.choices)) {
params.choices = params.choices.join(', ');
} else {
params.choices = Object.keys(params.choices).join(', ');
}
}
return sprintf(this._getHelpString(action), params);
};
HelpFormatter.prototype._splitLines = function (text, width) {
var lines = [];
var delimiters = [ ' ', '.', ',', '!', '?' ];
var re = new RegExp('[' + delimiters.join('') + '][^' + delimiters.join('') + ']*$');
text = text.replace(/[\n\|\t]/g, ' ');
text = text.trim();
text = text.replace(this._whitespaceMatcher, ' ');
// Wraps the single paragraph in text (a string) so every line
// is at most width characters long.
text.split(c.EOL).forEach(function (line) {
if (width >= line.length) {
lines.push(line);
return;
}
var wrapStart = 0;
var wrapEnd = width;
var delimiterIndex = 0;
while (wrapEnd <= line.length) {
if (wrapEnd !== line.length && delimiters.indexOf(line[wrapEnd] < -1)) {
delimiterIndex = (re.exec(line.substring(wrapStart, wrapEnd)) || {}).index;
wrapEnd = wrapStart + delimiterIndex + 1;
}
lines.push(line.substring(wrapStart, wrapEnd));
wrapStart = wrapEnd;
wrapEnd += width;
}
if (wrapStart < line.length) {
lines.push(line.substring(wrapStart, wrapEnd));
}
});
return lines;
};
HelpFormatter.prototype._fillText = function (text, width, indent) {
var lines = this._splitLines(text, width);
lines = lines.map(function (line) {
return indent + line;
});
return lines.join(c.EOL);
};
HelpFormatter.prototype._getHelpString = function (action) {
return action.help;
};

View file

@ -1,76 +0,0 @@
/**
* class Namespace
*
* Simple object for storing attributes. Implements equality by attribute names
* and values, and provides a simple string representation.
*
* See also [original guide][1]
*
* [1]:http://docs.python.org/dev/library/argparse.html#the-namespace-object
**/
'use strict';
var $$ = require('./utils');
/**
* new Namespace(options)
* - options(object): predefined propertis for result object
*
**/
var Namespace = module.exports = function Namespace(options) {
$$.extend(this, options);
};
/**
* Namespace#isset(key) -> Boolean
* - key (string|number): property name
*
* Tells whenever `namespace` contains given `key` or not.
**/
Namespace.prototype.isset = function (key) {
return $$.has(this, key);
};
/**
* Namespace#set(key, value) -> self
* -key (string|number|object): propery name
* -value (mixed): new property value
*
* Set the property named key with value.
* If key object then set all key properties to namespace object
**/
Namespace.prototype.set = function (key, value) {
if (typeof (key) === 'object') {
$$.extend(this, key);
} else {
this[key] = value;
}
return this;
};
/**
* Namespace#get(key, defaultValue) -> mixed
* - key (string|number): property name
* - defaultValue (mixed): default value
*
* Return the property key or defaulValue if not set
**/
Namespace.prototype.get = function (key, defaultValue) {
return !this[key] ? defaultValue : this[key];
};
/**
* Namespace#unset(key, defaultValue) -> mixed
* - key (string|number): property name
* - defaultValue (mixed): default value
*
* Return data[key](and delete it) or defaultValue
**/
Namespace.prototype.unset = function (key, defaultValue) {
var value = this[key];
if (value !== null) {
delete this[key];
return value;
}
return defaultValue;
};

View file

@ -1,57 +0,0 @@
'use strict';
exports.repeat = function (str, num) {
var result = '';
for (var i = 0; i < num; i++) { result += str; }
return result;
};
exports.arrayEqual = function (a, b) {
if (a.length !== b.length) { return false; }
for (var i = 0; i < a.length; i++) {
if (a[i] !== b[i]) { return false; }
}
return true;
};
exports.trimChars = function (str, chars) {
var start = 0;
var end = str.length - 1;
while (chars.indexOf(str.charAt(start)) >= 0) { start++; }
while (chars.indexOf(str.charAt(end)) >= 0) { end--; }
return str.slice(start, end + 1);
};
exports.capitalize = function (str) {
return str.charAt(0).toUpperCase() + str.slice(1);
};
exports.arrayUnion = function () {
var result = [];
for (var i = 0, values = {}; i < arguments.length; i++) {
var arr = arguments[i];
for (var j = 0; j < arr.length; j++) {
if (!values[arr[j]]) {
values[arr[j]] = true;
result.push(arr[j]);
}
}
}
return result;
};
function has(obj, key) {
return Object.prototype.hasOwnProperty.call(obj, key);
}
exports.has = has;
exports.extend = function (dest, src) {
for (var i in src) {
if (has(src, i)) { dest[i] = src[i]; }
}
};
exports.trimEnd = function (str) {
return str.replace(/\s+$/g, '');
};

View file

@ -1,34 +0,0 @@
{
"name": "argparse",
"description": "Very powerful CLI arguments parser. Native port of argparse - python's options parsing library",
"version": "1.0.10",
"keywords": [
"cli",
"parser",
"argparse",
"option",
"args"
],
"contributors": [
"Eugene Shkuropat",
"Paul Jacobson"
],
"files": [
"index.js",
"lib/"
],
"license": "MIT",
"repository": "nodeca/argparse",
"scripts": {
"test": "make test"
},
"dependencies": {
"sprintf-js": "~1.0.2"
},
"devDependencies": {
"eslint": "^2.13.1",
"istanbul": "^0.4.5",
"mocha": "^3.1.0",
"ndoc": "^5.0.1"
}
}

View file

@ -1,54 +0,0 @@
# 1.0.0 - 2016-01-07
- Removed: unused speed test
- Added: Automatic routing between previously unsupported conversions
([#27](https://github.com/Qix-/color-convert/pull/27))
- Removed: `xxx2xxx()` and `xxx2xxxRaw()` functions
([#27](https://github.com/Qix-/color-convert/pull/27))
- Removed: `convert()` class
([#27](https://github.com/Qix-/color-convert/pull/27))
- Changed: all functions to lookup dictionary
([#27](https://github.com/Qix-/color-convert/pull/27))
- Changed: `ansi` to `ansi256`
([#27](https://github.com/Qix-/color-convert/pull/27))
- Fixed: argument grouping for functions requiring only one argument
([#27](https://github.com/Qix-/color-convert/pull/27))
# 0.6.0 - 2015-07-23
- Added: methods to handle
[ANSI](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) 16/256 colors:
- rgb2ansi16
- rgb2ansi
- hsl2ansi16
- hsl2ansi
- hsv2ansi16
- hsv2ansi
- hwb2ansi16
- hwb2ansi
- cmyk2ansi16
- cmyk2ansi
- keyword2ansi16
- keyword2ansi
- ansi162rgb
- ansi162hsl
- ansi162hsv
- ansi162hwb
- ansi162cmyk
- ansi162keyword
- ansi2rgb
- ansi2hsl
- ansi2hsv
- ansi2hwb
- ansi2cmyk
- ansi2keyword
([#18](https://github.com/harthur/color-convert/pull/18))
# 0.5.3 - 2015-06-02
- Fixed: hsl2hsv does not return `NaN` anymore when using `[0,0,0]`
([#15](https://github.com/harthur/color-convert/issues/15))
---
Check out commit logs for older releases

View file

@ -1,21 +0,0 @@
Copyright (c) 2011-2016 Heather Arthur <fayearthur@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -1,68 +0,0 @@
# color-convert
[![Build Status](https://travis-ci.org/Qix-/color-convert.svg?branch=master)](https://travis-ci.org/Qix-/color-convert)
Color-convert is a color conversion library for JavaScript and node.
It converts all ways between `rgb`, `hsl`, `hsv`, `hwb`, `cmyk`, `ansi`, `ansi16`, `hex` strings, and CSS `keyword`s (will round to closest):
```js
var convert = require('color-convert');
convert.rgb.hsl(140, 200, 100); // [96, 48, 59]
convert.keyword.rgb('blue'); // [0, 0, 255]
var rgbChannels = convert.rgb.channels; // 3
var cmykChannels = convert.cmyk.channels; // 4
var ansiChannels = convert.ansi16.channels; // 1
```
# Install
```console
$ npm install color-convert
```
# API
Simply get the property of the _from_ and _to_ conversion that you're looking for.
All functions have a rounded and unrounded variant. By default, return values are rounded. To get the unrounded (raw) results, simply tack on `.raw` to the function.
All 'from' functions have a hidden property called `.channels` that indicates the number of channels the function expects (not including alpha).
```js
var convert = require('color-convert');
// Hex to LAB
convert.hex.lab('DEADBF'); // [ 76, 21, -2 ]
convert.hex.lab.raw('DEADBF'); // [ 75.56213190997677, 20.653827952644754, -2.290532499330533 ]
// RGB to CMYK
convert.rgb.cmyk(167, 255, 4); // [ 35, 0, 98, 0 ]
convert.rgb.cmyk.raw(167, 255, 4); // [ 34.509803921568626, 0, 98.43137254901961, 0 ]
```
### Arrays
All functions that accept multiple arguments also support passing an array.
Note that this does **not** apply to functions that convert from a color that only requires one value (e.g. `keyword`, `ansi256`, `hex`, etc.)
```js
var convert = require('color-convert');
convert.rgb.hex(123, 45, 67); // '7B2D43'
convert.rgb.hex([123, 45, 67]); // '7B2D43'
```
## Routing
Conversions that don't have an _explicitly_ defined conversion (in [conversions.js](conversions.js)), but can be converted by means of sub-conversions (e.g. XYZ -> **RGB** -> CMYK), are automatically routed together. This allows just about any color model supported by `color-convert` to be converted to any other model, so long as a sub-conversion path exists. This is also true for conversions requiring more than one step in between (e.g. LCH -> **LAB** -> **XYZ** -> **RGB** -> Hex).
Keep in mind that extensive conversions _may_ result in a loss of precision, and exist only to be complete. For a list of "direct" (single-step) conversions, see [conversions.js](conversions.js).
# Contribute
If there is a new model you would like to support, or want to add a direct conversion between two existing models, please send us a pull request.
# License
Copyright &copy; 2011-2016, Heather Arthur and Josh Junon. Licensed under the [MIT License](LICENSE).

View file

@ -1,839 +0,0 @@
/* MIT license */
/* eslint-disable no-mixed-operators */
const cssKeywords = require('color-name');
// NOTE: conversions should only return primitive values (i.e. arrays, or
// values that give correct `typeof` results).
// do not use box values types (i.e. Number(), String(), etc.)
const reverseKeywords = {};
for (const key of Object.keys(cssKeywords)) {
reverseKeywords[cssKeywords[key]] = key;
}
const convert = {
rgb: {channels: 3, labels: 'rgb'},
hsl: {channels: 3, labels: 'hsl'},
hsv: {channels: 3, labels: 'hsv'},
hwb: {channels: 3, labels: 'hwb'},
cmyk: {channels: 4, labels: 'cmyk'},
xyz: {channels: 3, labels: 'xyz'},
lab: {channels: 3, labels: 'lab'},
lch: {channels: 3, labels: 'lch'},
hex: {channels: 1, labels: ['hex']},
keyword: {channels: 1, labels: ['keyword']},
ansi16: {channels: 1, labels: ['ansi16']},
ansi256: {channels: 1, labels: ['ansi256']},
hcg: {channels: 3, labels: ['h', 'c', 'g']},
apple: {channels: 3, labels: ['r16', 'g16', 'b16']},
gray: {channels: 1, labels: ['gray']}
};
module.exports = convert;
// Hide .channels and .labels properties
for (const model of Object.keys(convert)) {
if (!('channels' in convert[model])) {
throw new Error('missing channels property: ' + model);
}
if (!('labels' in convert[model])) {
throw new Error('missing channel labels property: ' + model);
}
if (convert[model].labels.length !== convert[model].channels) {
throw new Error('channel and label counts mismatch: ' + model);
}
const {channels, labels} = convert[model];
delete convert[model].channels;
delete convert[model].labels;
Object.defineProperty(convert[model], 'channels', {value: channels});
Object.defineProperty(convert[model], 'labels', {value: labels});
}
convert.rgb.hsl = function (rgb) {
const r = rgb[0] / 255;
const g = rgb[1] / 255;
const b = rgb[2] / 255;
const min = Math.min(r, g, b);
const max = Math.max(r, g, b);
const delta = max - min;
let h;
let s;
if (max === min) {
h = 0;
} else if (r === max) {
h = (g - b) / delta;
} else if (g === max) {
h = 2 + (b - r) / delta;
} else if (b === max) {
h = 4 + (r - g) / delta;
}
h = Math.min(h * 60, 360);
if (h < 0) {
h += 360;
}
const l = (min + max) / 2;
if (max === min) {
s = 0;
} else if (l <= 0.5) {
s = delta / (max + min);
} else {
s = delta / (2 - max - min);
}
return [h, s * 100, l * 100];
};
convert.rgb.hsv = function (rgb) {
let rdif;
let gdif;
let bdif;
let h;
let s;
const r = rgb[0] / 255;
const g = rgb[1] / 255;
const b = rgb[2] / 255;
const v = Math.max(r, g, b);
const diff = v - Math.min(r, g, b);
const diffc = function (c) {
return (v - c) / 6 / diff + 1 / 2;
};
if (diff === 0) {
h = 0;
s = 0;
} else {
s = diff / v;
rdif = diffc(r);
gdif = diffc(g);
bdif = diffc(b);
if (r === v) {
h = bdif - gdif;
} else if (g === v) {
h = (1 / 3) + rdif - bdif;
} else if (b === v) {
h = (2 / 3) + gdif - rdif;
}
if (h < 0) {
h += 1;
} else if (h > 1) {
h -= 1;
}
}
return [
h * 360,
s * 100,
v * 100
];
};
convert.rgb.hwb = function (rgb) {
const r = rgb[0];
const g = rgb[1];
let b = rgb[2];
const h = convert.rgb.hsl(rgb)[0];
const w = 1 / 255 * Math.min(r, Math.min(g, b));
b = 1 - 1 / 255 * Math.max(r, Math.max(g, b));
return [h, w * 100, b * 100];
};
convert.rgb.cmyk = function (rgb) {
const r = rgb[0] / 255;
const g = rgb[1] / 255;
const b = rgb[2] / 255;
const k = Math.min(1 - r, 1 - g, 1 - b);
const c = (1 - r - k) / (1 - k) || 0;
const m = (1 - g - k) / (1 - k) || 0;
const y = (1 - b - k) / (1 - k) || 0;
return [c * 100, m * 100, y * 100, k * 100];
};
function comparativeDistance(x, y) {
/*
See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance
*/
return (
((x[0] - y[0]) ** 2) +
((x[1] - y[1]) ** 2) +
((x[2] - y[2]) ** 2)
);
}
convert.rgb.keyword = function (rgb) {
const reversed = reverseKeywords[rgb];
if (reversed) {
return reversed;
}
let currentClosestDistance = Infinity;
let currentClosestKeyword;
for (const keyword of Object.keys(cssKeywords)) {
const value = cssKeywords[keyword];
// Compute comparative distance
const distance = comparativeDistance(rgb, value);
// Check if its less, if so set as closest
if (distance < currentClosestDistance) {
currentClosestDistance = distance;
currentClosestKeyword = keyword;
}
}
return currentClosestKeyword;
};
convert.keyword.rgb = function (keyword) {
return cssKeywords[keyword];
};
convert.rgb.xyz = function (rgb) {
let r = rgb[0] / 255;
let g = rgb[1] / 255;
let b = rgb[2] / 255;
// Assume sRGB
r = r > 0.04045 ? (((r + 0.055) / 1.055) ** 2.4) : (r / 12.92);
g = g > 0.04045 ? (((g + 0.055) / 1.055) ** 2.4) : (g / 12.92);
b = b > 0.04045 ? (((b + 0.055) / 1.055) ** 2.4) : (b / 12.92);
const x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805);
const y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722);
const z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505);
return [x * 100, y * 100, z * 100];
};
convert.rgb.lab = function (rgb) {
const xyz = convert.rgb.xyz(rgb);
let x = xyz[0];
let y = xyz[1];
let z = xyz[2];
x /= 95.047;
y /= 100;
z /= 108.883;
x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116);
y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116);
z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116);
const l = (116 * y) - 16;
const a = 500 * (x - y);
const b = 200 * (y - z);
return [l, a, b];
};
convert.hsl.rgb = function (hsl) {
const h = hsl[0] / 360;
const s = hsl[1] / 100;
const l = hsl[2] / 100;
let t2;
let t3;
let val;
if (s === 0) {
val = l * 255;
return [val, val, val];
}
if (l < 0.5) {
t2 = l * (1 + s);
} else {
t2 = l + s - l * s;
}
const t1 = 2 * l - t2;
const rgb = [0, 0, 0];
for (let i = 0; i < 3; i++) {
t3 = h + 1 / 3 * -(i - 1);
if (t3 < 0) {
t3++;
}
if (t3 > 1) {
t3--;
}
if (6 * t3 < 1) {
val = t1 + (t2 - t1) * 6 * t3;
} else if (2 * t3 < 1) {
val = t2;
} else if (3 * t3 < 2) {
val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
} else {
val = t1;
}
rgb[i] = val * 255;
}
return rgb;
};
convert.hsl.hsv = function (hsl) {
const h = hsl[0];
let s = hsl[1] / 100;
let l = hsl[2] / 100;
let smin = s;
const lmin = Math.max(l, 0.01);
l *= 2;
s *= (l <= 1) ? l : 2 - l;
smin *= lmin <= 1 ? lmin : 2 - lmin;
const v = (l + s) / 2;
const sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s);
return [h, sv * 100, v * 100];
};
convert.hsv.rgb = function (hsv) {
const h = hsv[0] / 60;
const s = hsv[1] / 100;
let v = hsv[2] / 100;
const hi = Math.floor(h) % 6;
const f = h - Math.floor(h);
const p = 255 * v * (1 - s);
const q = 255 * v * (1 - (s * f));
const t = 255 * v * (1 - (s * (1 - f)));
v *= 255;
switch (hi) {
case 0:
return [v, t, p];
case 1:
return [q, v, p];
case 2:
return [p, v, t];
case 3:
return [p, q, v];
case 4:
return [t, p, v];
case 5:
return [v, p, q];
}
};
convert.hsv.hsl = function (hsv) {
const h = hsv[0];
const s = hsv[1] / 100;
const v = hsv[2] / 100;
const vmin = Math.max(v, 0.01);
let sl;
let l;
l = (2 - s) * v;
const lmin = (2 - s) * vmin;
sl = s * vmin;
sl /= (lmin <= 1) ? lmin : 2 - lmin;
sl = sl || 0;
l /= 2;
return [h, sl * 100, l * 100];
};
// http://dev.w3.org/csswg/css-color/#hwb-to-rgb
convert.hwb.rgb = function (hwb) {
const h = hwb[0] / 360;
let wh = hwb[1] / 100;
let bl = hwb[2] / 100;
const ratio = wh + bl;
let f;
// Wh + bl cant be > 1
if (ratio > 1) {
wh /= ratio;
bl /= ratio;
}
const i = Math.floor(6 * h);
const v = 1 - bl;
f = 6 * h - i;
if ((i & 0x01) !== 0) {
f = 1 - f;
}
const n = wh + f * (v - wh); // Linear interpolation
let r;
let g;
let b;
/* eslint-disable max-statements-per-line,no-multi-spaces */
switch (i) {
default:
case 6:
case 0: r = v; g = n; b = wh; break;
case 1: r = n; g = v; b = wh; break;
case 2: r = wh; g = v; b = n; break;
case 3: r = wh; g = n; b = v; break;
case 4: r = n; g = wh; b = v; break;
case 5: r = v; g = wh; b = n; break;
}
/* eslint-enable max-statements-per-line,no-multi-spaces */
return [r * 255, g * 255, b * 255];
};
convert.cmyk.rgb = function (cmyk) {
const c = cmyk[0] / 100;
const m = cmyk[1] / 100;
const y = cmyk[2] / 100;
const k = cmyk[3] / 100;
const r = 1 - Math.min(1, c * (1 - k) + k);
const g = 1 - Math.min(1, m * (1 - k) + k);
const b = 1 - Math.min(1, y * (1 - k) + k);
return [r * 255, g * 255, b * 255];
};
convert.xyz.rgb = function (xyz) {
const x = xyz[0] / 100;
const y = xyz[1] / 100;
const z = xyz[2] / 100;
let r;
let g;
let b;
r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986);
g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415);
b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570);
// Assume sRGB
r = r > 0.0031308
? ((1.055 * (r ** (1.0 / 2.4))) - 0.055)
: r * 12.92;
g = g > 0.0031308
? ((1.055 * (g ** (1.0 / 2.4))) - 0.055)
: g * 12.92;
b = b > 0.0031308
? ((1.055 * (b ** (1.0 / 2.4))) - 0.055)
: b * 12.92;
r = Math.min(Math.max(0, r), 1);
g = Math.min(Math.max(0, g), 1);
b = Math.min(Math.max(0, b), 1);
return [r * 255, g * 255, b * 255];
};
convert.xyz.lab = function (xyz) {
let x = xyz[0];
let y = xyz[1];
let z = xyz[2];
x /= 95.047;
y /= 100;
z /= 108.883;
x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116);
y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116);
z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116);
const l = (116 * y) - 16;
const a = 500 * (x - y);
const b = 200 * (y - z);
return [l, a, b];
};
convert.lab.xyz = function (lab) {
const l = lab[0];
const a = lab[1];
const b = lab[2];
let x;
let y;
let z;
y = (l + 16) / 116;
x = a / 500 + y;
z = y - b / 200;
const y2 = y ** 3;
const x2 = x ** 3;
const z2 = z ** 3;
y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787;
x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787;
z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787;
x *= 95.047;
y *= 100;
z *= 108.883;
return [x, y, z];
};
convert.lab.lch = function (lab) {
const l = lab[0];
const a = lab[1];
const b = lab[2];
let h;
const hr = Math.atan2(b, a);
h = hr * 360 / 2 / Math.PI;
if (h < 0) {
h += 360;
}
const c = Math.sqrt(a * a + b * b);
return [l, c, h];
};
convert.lch.lab = function (lch) {
const l = lch[0];
const c = lch[1];
const h = lch[2];
const hr = h / 360 * 2 * Math.PI;
const a = c * Math.cos(hr);
const b = c * Math.sin(hr);
return [l, a, b];
};
convert.rgb.ansi16 = function (args, saturation = null) {
const [r, g, b] = args;
let value = saturation === null ? convert.rgb.hsv(args)[2] : saturation; // Hsv -> ansi16 optimization
value = Math.round(value / 50);
if (value === 0) {
return 30;
}
let ansi = 30
+ ((Math.round(b / 255) << 2)
| (Math.round(g / 255) << 1)
| Math.round(r / 255));
if (value === 2) {
ansi += 60;
}
return ansi;
};
convert.hsv.ansi16 = function (args) {
// Optimization here; we already know the value and don't need to get
// it converted for us.
return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]);
};
convert.rgb.ansi256 = function (args) {
const r = args[0];
const g = args[1];
const b = args[2];
// We use the extended greyscale palette here, with the exception of
// black and white. normal palette only has 4 greyscale shades.
if (r === g && g === b) {
if (r < 8) {
return 16;
}
if (r > 248) {
return 231;
}
return Math.round(((r - 8) / 247) * 24) + 232;
}
const ansi = 16
+ (36 * Math.round(r / 255 * 5))
+ (6 * Math.round(g / 255 * 5))
+ Math.round(b / 255 * 5);
return ansi;
};
convert.ansi16.rgb = function (args) {
let color = args % 10;
// Handle greyscale
if (color === 0 || color === 7) {
if (args > 50) {
color += 3.5;
}
color = color / 10.5 * 255;
return [color, color, color];
}
const mult = (~~(args > 50) + 1) * 0.5;
const r = ((color & 1) * mult) * 255;
const g = (((color >> 1) & 1) * mult) * 255;
const b = (((color >> 2) & 1) * mult) * 255;
return [r, g, b];
};
convert.ansi256.rgb = function (args) {
// Handle greyscale
if (args >= 232) {
const c = (args - 232) * 10 + 8;
return [c, c, c];
}
args -= 16;
let rem;
const r = Math.floor(args / 36) / 5 * 255;
const g = Math.floor((rem = args % 36) / 6) / 5 * 255;
const b = (rem % 6) / 5 * 255;
return [r, g, b];
};
convert.rgb.hex = function (args) {
const integer = ((Math.round(args[0]) & 0xFF) << 16)
+ ((Math.round(args[1]) & 0xFF) << 8)
+ (Math.round(args[2]) & 0xFF);
const string = integer.toString(16).toUpperCase();
return '000000'.substring(string.length) + string;
};
convert.hex.rgb = function (args) {
const match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);
if (!match) {
return [0, 0, 0];
}
let colorString = match[0];
if (match[0].length === 3) {
colorString = colorString.split('').map(char => {
return char + char;
}).join('');
}
const integer = parseInt(colorString, 16);
const r = (integer >> 16) & 0xFF;
const g = (integer >> 8) & 0xFF;
const b = integer & 0xFF;
return [r, g, b];
};
convert.rgb.hcg = function (rgb) {
const r = rgb[0] / 255;
const g = rgb[1] / 255;
const b = rgb[2] / 255;
const max = Math.max(Math.max(r, g), b);
const min = Math.min(Math.min(r, g), b);
const chroma = (max - min);
let grayscale;
let hue;
if (chroma < 1) {
grayscale = min / (1 - chroma);
} else {
grayscale = 0;
}
if (chroma <= 0) {
hue = 0;
} else
if (max === r) {
hue = ((g - b) / chroma) % 6;
} else
if (max === g) {
hue = 2 + (b - r) / chroma;
} else {
hue = 4 + (r - g) / chroma;
}
hue /= 6;
hue %= 1;
return [hue * 360, chroma * 100, grayscale * 100];
};
convert.hsl.hcg = function (hsl) {
const s = hsl[1] / 100;
const l = hsl[2] / 100;
const c = l < 0.5 ? (2.0 * s * l) : (2.0 * s * (1.0 - l));
let f = 0;
if (c < 1.0) {
f = (l - 0.5 * c) / (1.0 - c);
}
return [hsl[0], c * 100, f * 100];
};
convert.hsv.hcg = function (hsv) {
const s = hsv[1] / 100;
const v = hsv[2] / 100;
const c = s * v;
let f = 0;
if (c < 1.0) {
f = (v - c) / (1 - c);
}
return [hsv[0], c * 100, f * 100];
};
convert.hcg.rgb = function (hcg) {
const h = hcg[0] / 360;
const c = hcg[1] / 100;
const g = hcg[2] / 100;
if (c === 0.0) {
return [g * 255, g * 255, g * 255];
}
const pure = [0, 0, 0];
const hi = (h % 1) * 6;
const v = hi % 1;
const w = 1 - v;
let mg = 0;
/* eslint-disable max-statements-per-line */
switch (Math.floor(hi)) {
case 0:
pure[0] = 1; pure[1] = v; pure[2] = 0; break;
case 1:
pure[0] = w; pure[1] = 1; pure[2] = 0; break;
case 2:
pure[0] = 0; pure[1] = 1; pure[2] = v; break;
case 3:
pure[0] = 0; pure[1] = w; pure[2] = 1; break;
case 4:
pure[0] = v; pure[1] = 0; pure[2] = 1; break;
default:
pure[0] = 1; pure[1] = 0; pure[2] = w;
}
/* eslint-enable max-statements-per-line */
mg = (1.0 - c) * g;
return [
(c * pure[0] + mg) * 255,
(c * pure[1] + mg) * 255,
(c * pure[2] + mg) * 255
];
};
convert.hcg.hsv = function (hcg) {
const c = hcg[1] / 100;
const g = hcg[2] / 100;
const v = c + g * (1.0 - c);
let f = 0;
if (v > 0.0) {
f = c / v;
}
return [hcg[0], f * 100, v * 100];
};
convert.hcg.hsl = function (hcg) {
const c = hcg[1] / 100;
const g = hcg[2] / 100;
const l = g * (1.0 - c) + 0.5 * c;
let s = 0;
if (l > 0.0 && l < 0.5) {
s = c / (2 * l);
} else
if (l >= 0.5 && l < 1.0) {
s = c / (2 * (1 - l));
}
return [hcg[0], s * 100, l * 100];
};
convert.hcg.hwb = function (hcg) {
const c = hcg[1] / 100;
const g = hcg[2] / 100;
const v = c + g * (1.0 - c);
return [hcg[0], (v - c) * 100, (1 - v) * 100];
};
convert.hwb.hcg = function (hwb) {
const w = hwb[1] / 100;
const b = hwb[2] / 100;
const v = 1 - b;
const c = v - w;
let g = 0;
if (c < 1) {
g = (v - c) / (1 - c);
}
return [hwb[0], c * 100, g * 100];
};
convert.apple.rgb = function (apple) {
return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255];
};
convert.rgb.apple = function (rgb) {
return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535];
};
convert.gray.rgb = function (args) {
return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255];
};
convert.gray.hsl = function (args) {
return [0, 0, args[0]];
};
convert.gray.hsv = convert.gray.hsl;
convert.gray.hwb = function (gray) {
return [0, 100, gray[0]];
};
convert.gray.cmyk = function (gray) {
return [0, 0, 0, gray[0]];
};
convert.gray.lab = function (gray) {
return [gray[0], 0, 0];
};
convert.gray.hex = function (gray) {
const val = Math.round(gray[0] / 100 * 255) & 0xFF;
const integer = (val << 16) + (val << 8) + val;
const string = integer.toString(16).toUpperCase();
return '000000'.substring(string.length) + string;
};
convert.rgb.gray = function (rgb) {
const val = (rgb[0] + rgb[1] + rgb[2]) / 3;
return [val / 255 * 100];
};

View file

@ -1,81 +0,0 @@
const conversions = require('./conversions');
const route = require('./route');
const convert = {};
const models = Object.keys(conversions);
function wrapRaw(fn) {
const wrappedFn = function (...args) {
const arg0 = args[0];
if (arg0 === undefined || arg0 === null) {
return arg0;
}
if (arg0.length > 1) {
args = arg0;
}
return fn(args);
};
// Preserve .conversion property if there is one
if ('conversion' in fn) {
wrappedFn.conversion = fn.conversion;
}
return wrappedFn;
}
function wrapRounded(fn) {
const wrappedFn = function (...args) {
const arg0 = args[0];
if (arg0 === undefined || arg0 === null) {
return arg0;
}
if (arg0.length > 1) {
args = arg0;
}
const result = fn(args);
// We're assuming the result is an array here.
// see notice in conversions.js; don't use box types
// in conversion functions.
if (typeof result === 'object') {
for (let len = result.length, i = 0; i < len; i++) {
result[i] = Math.round(result[i]);
}
}
return result;
};
// Preserve .conversion property if there is one
if ('conversion' in fn) {
wrappedFn.conversion = fn.conversion;
}
return wrappedFn;
}
models.forEach(fromModel => {
convert[fromModel] = {};
Object.defineProperty(convert[fromModel], 'channels', {value: conversions[fromModel].channels});
Object.defineProperty(convert[fromModel], 'labels', {value: conversions[fromModel].labels});
const routes = route(fromModel);
const routeModels = Object.keys(routes);
routeModels.forEach(toModel => {
const fn = routes[toModel];
convert[fromModel][toModel] = wrapRounded(fn);
convert[fromModel][toModel].raw = wrapRaw(fn);
});
});
module.exports = convert;

View file

@ -1,48 +0,0 @@
{
"name": "color-convert",
"description": "Plain color conversion functions",
"version": "2.0.1",
"author": "Heather Arthur <fayearthur@gmail.com>",
"license": "MIT",
"repository": "Qix-/color-convert",
"scripts": {
"pretest": "xo",
"test": "node test/basic.js"
},
"engines": {
"node": ">=7.0.0"
},
"keywords": [
"color",
"colour",
"convert",
"converter",
"conversion",
"rgb",
"hsl",
"hsv",
"hwb",
"cmyk",
"ansi",
"ansi16"
],
"files": [
"index.js",
"conversions.js",
"route.js"
],
"xo": {
"rules": {
"default-case": 0,
"no-inline-comments": 0,
"operator-linebreak": 0
}
},
"devDependencies": {
"chalk": "^2.4.2",
"xo": "^0.24.0"
},
"dependencies": {
"color-name": "~1.1.4"
}
}

View file

@ -1,97 +0,0 @@
const conversions = require('./conversions');
/*
This function routes a model to all other models.
all functions that are routed have a property `.conversion` attached
to the returned synthetic function. This property is an array
of strings, each with the steps in between the 'from' and 'to'
color models (inclusive).
conversions that are not possible simply are not included.
*/
function buildGraph() {
const graph = {};
// https://jsperf.com/object-keys-vs-for-in-with-closure/3
const models = Object.keys(conversions);
for (let len = models.length, i = 0; i < len; i++) {
graph[models[i]] = {
// http://jsperf.com/1-vs-infinity
// micro-opt, but this is simple.
distance: -1,
parent: null
};
}
return graph;
}
// https://en.wikipedia.org/wiki/Breadth-first_search
function deriveBFS(fromModel) {
const graph = buildGraph();
const queue = [fromModel]; // Unshift -> queue -> pop
graph[fromModel].distance = 0;
while (queue.length) {
const current = queue.pop();
const adjacents = Object.keys(conversions[current]);
for (let len = adjacents.length, i = 0; i < len; i++) {
const adjacent = adjacents[i];
const node = graph[adjacent];
if (node.distance === -1) {
node.distance = graph[current].distance + 1;
node.parent = current;
queue.unshift(adjacent);
}
}
}
return graph;
}
function link(from, to) {
return function (args) {
return to(from(args));
};
}
function wrapConversion(toModel, graph) {
const path = [graph[toModel].parent, toModel];
let fn = conversions[graph[toModel].parent][toModel];
let cur = graph[toModel].parent;
while (graph[cur].parent) {
path.unshift(graph[cur].parent);
fn = link(conversions[graph[cur].parent][cur], fn);
cur = graph[cur].parent;
}
fn.conversion = path;
return fn;
}
module.exports = function (fromModel) {
const graph = deriveBFS(fromModel);
const conversion = {};
const models = Object.keys(graph);
for (let len = models.length, i = 0; i < len; i++) {
const toModel = models[i];
const node = graph[toModel];
if (node.parent === null) {
// No possible conversion, or this node is the source model.
continue;
}
conversion[toModel] = wrapConversion(toModel, graph);
}
return conversion;
};

View file

@ -1,11 +0,0 @@
A JSON with color names and its values. Based on http://dev.w3.org/csswg/css-color/#named-colors.
[![NPM](https://nodei.co/npm/color-name.png?mini=true)](https://nodei.co/npm/color-name/)
```js
var colors = require('color-name');
colors.red //[255,0,0]
```
<a href="LICENSE"><img src="https://upload.wikimedia.org/wikipedia/commons/0/0c/MIT_logo.svg" width="120"/></a>

View file

@ -1,152 +0,0 @@
'use strict'
module.exports = {
"aliceblue": [240, 248, 255],
"antiquewhite": [250, 235, 215],
"aqua": [0, 255, 255],
"aquamarine": [127, 255, 212],
"azure": [240, 255, 255],
"beige": [245, 245, 220],
"bisque": [255, 228, 196],
"black": [0, 0, 0],
"blanchedalmond": [255, 235, 205],
"blue": [0, 0, 255],
"blueviolet": [138, 43, 226],
"brown": [165, 42, 42],
"burlywood": [222, 184, 135],
"cadetblue": [95, 158, 160],
"chartreuse": [127, 255, 0],
"chocolate": [210, 105, 30],
"coral": [255, 127, 80],
"cornflowerblue": [100, 149, 237],
"cornsilk": [255, 248, 220],
"crimson": [220, 20, 60],
"cyan": [0, 255, 255],
"darkblue": [0, 0, 139],
"darkcyan": [0, 139, 139],
"darkgoldenrod": [184, 134, 11],
"darkgray": [169, 169, 169],
"darkgreen": [0, 100, 0],
"darkgrey": [169, 169, 169],
"darkkhaki": [189, 183, 107],
"darkmagenta": [139, 0, 139],
"darkolivegreen": [85, 107, 47],
"darkorange": [255, 140, 0],
"darkorchid": [153, 50, 204],
"darkred": [139, 0, 0],
"darksalmon": [233, 150, 122],
"darkseagreen": [143, 188, 143],
"darkslateblue": [72, 61, 139],
"darkslategray": [47, 79, 79],
"darkslategrey": [47, 79, 79],
"darkturquoise": [0, 206, 209],
"darkviolet": [148, 0, 211],
"deeppink": [255, 20, 147],
"deepskyblue": [0, 191, 255],
"dimgray": [105, 105, 105],
"dimgrey": [105, 105, 105],
"dodgerblue": [30, 144, 255],
"firebrick": [178, 34, 34],
"floralwhite": [255, 250, 240],
"forestgreen": [34, 139, 34],
"fuchsia": [255, 0, 255],
"gainsboro": [220, 220, 220],
"ghostwhite": [248, 248, 255],
"gold": [255, 215, 0],
"goldenrod": [218, 165, 32],
"gray": [128, 128, 128],
"green": [0, 128, 0],
"greenyellow": [173, 255, 47],
"grey": [128, 128, 128],
"honeydew": [240, 255, 240],
"hotpink": [255, 105, 180],
"indianred": [205, 92, 92],
"indigo": [75, 0, 130],
"ivory": [255, 255, 240],
"khaki": [240, 230, 140],
"lavender": [230, 230, 250],
"lavenderblush": [255, 240, 245],
"lawngreen": [124, 252, 0],
"lemonchiffon": [255, 250, 205],
"lightblue": [173, 216, 230],
"lightcoral": [240, 128, 128],
"lightcyan": [224, 255, 255],
"lightgoldenrodyellow": [250, 250, 210],
"lightgray": [211, 211, 211],
"lightgreen": [144, 238, 144],
"lightgrey": [211, 211, 211],
"lightpink": [255, 182, 193],
"lightsalmon": [255, 160, 122],
"lightseagreen": [32, 178, 170],
"lightskyblue": [135, 206, 250],
"lightslategray": [119, 136, 153],
"lightslategrey": [119, 136, 153],
"lightsteelblue": [176, 196, 222],
"lightyellow": [255, 255, 224],
"lime": [0, 255, 0],
"limegreen": [50, 205, 50],
"linen": [250, 240, 230],
"magenta": [255, 0, 255],
"maroon": [128, 0, 0],
"mediumaquamarine": [102, 205, 170],
"mediumblue": [0, 0, 205],
"mediumorchid": [186, 85, 211],
"mediumpurple": [147, 112, 219],
"mediumseagreen": [60, 179, 113],
"mediumslateblue": [123, 104, 238],
"mediumspringgreen": [0, 250, 154],
"mediumturquoise": [72, 209, 204],
"mediumvioletred": [199, 21, 133],
"midnightblue": [25, 25, 112],
"mintcream": [245, 255, 250],
"mistyrose": [255, 228, 225],
"moccasin": [255, 228, 181],
"navajowhite": [255, 222, 173],
"navy": [0, 0, 128],
"oldlace": [253, 245, 230],
"olive": [128, 128, 0],
"olivedrab": [107, 142, 35],
"orange": [255, 165, 0],
"orangered": [255, 69, 0],
"orchid": [218, 112, 214],
"palegoldenrod": [238, 232, 170],
"palegreen": [152, 251, 152],
"paleturquoise": [175, 238, 238],
"palevioletred": [219, 112, 147],
"papayawhip": [255, 239, 213],
"peachpuff": [255, 218, 185],
"peru": [205, 133, 63],
"pink": [255, 192, 203],
"plum": [221, 160, 221],
"powderblue": [176, 224, 230],
"purple": [128, 0, 128],
"rebeccapurple": [102, 51, 153],
"red": [255, 0, 0],
"rosybrown": [188, 143, 143],
"royalblue": [65, 105, 225],
"saddlebrown": [139, 69, 19],
"salmon": [250, 128, 114],
"sandybrown": [244, 164, 96],
"seagreen": [46, 139, 87],
"seashell": [255, 245, 238],
"sienna": [160, 82, 45],
"silver": [192, 192, 192],
"skyblue": [135, 206, 235],
"slateblue": [106, 90, 205],
"slategray": [112, 128, 144],
"slategrey": [112, 128, 144],
"snow": [255, 250, 250],
"springgreen": [0, 255, 127],
"steelblue": [70, 130, 180],
"tan": [210, 180, 140],
"teal": [0, 128, 128],
"thistle": [216, 191, 216],
"tomato": [255, 99, 71],
"turquoise": [64, 224, 208],
"violet": [238, 130, 238],
"wheat": [245, 222, 179],
"white": [255, 255, 255],
"whitesmoke": [245, 245, 245],
"yellow": [255, 255, 0],
"yellowgreen": [154, 205, 50]
};

View file

@ -1,28 +0,0 @@
{
"name": "color-name",
"version": "1.1.4",
"description": "A list of color names and its values",
"main": "index.js",
"files": [
"index.js"
],
"scripts": {
"test": "node test.js"
},
"repository": {
"type": "git",
"url": "git@github.com:colorjs/color-name.git"
},
"keywords": [
"color-name",
"color",
"color-keyword",
"keyword"
],
"author": "DY <dfcreative@gmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/colorjs/color-name/issues"
},
"homepage": "https://github.com/colorjs/color-name"
}

22
node_modules/eslint/node_modules/eslint-scope/LICENSE generated vendored Normal file
View file

@ -0,0 +1,22 @@
Copyright JS Foundation and other contributors, https://js.foundation
Copyright (C) 2012-2013 Yusuke Suzuki (twitter: @Constellation) and other contributors.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 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 <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,66 @@
# ESLint Scope
ESLint Scope is the [ECMAScript](http://www.ecma-international.org/publications/standards/Ecma-262.htm) scope analyzer used in ESLint. It is a fork of [escope](http://github.com/estools/escope).
## Install
```
npm i eslint-scope --save
```
## 📖 Usage
To use in an ESM file:
```js
import * as eslintScope from 'eslint-scope';
```
To use in a CommonJS file:
```js
const eslintScope = require('eslint-scope');
```
Example:
```js
import * as eslintScope from 'eslint-scope';
import * as espree from 'espree';
import estraverse from 'estraverse';
const ast = espree.parse(code, { range: true });
const scopeManager = eslintScope.analyze(ast);
const currentScope = scopeManager.acquire(ast); // global scope
estraverse.traverse(ast, {
enter (node, parent) {
// do stuff
if (/Function/.test(node.type)) {
currentScope = scopeManager.acquire(node); // get current function scope
}
},
leave(node, parent) {
if (/Function/.test(node.type)) {
currentScope = currentScope.upper; // set to parent scope
}
// do stuff
}
});
```
## Contributing
Issues and pull requests will be triaged and responded to as quickly as possible. We operate under the [ESLint Contributor Guidelines](http://eslint.org/docs/developer-guide/contributing), so please be sure to read them before contributing. If you're not sure where to dig in, check out the [issues](https://github.com/eslint/eslint-scope/issues).
## Build Commands
* `npm test` - run all linting and tests
* `npm run lint` - run all linting
## License
ESLint Scope is licensed under a permissive BSD 2-clause license.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,85 @@
/*
Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 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 <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import Variable from "./variable.js";
/**
* @constructor Definition
*/
class Definition {
constructor(type, name, node, parent, index, kind) {
/**
* @member {string} Definition#type - type of the occurrence (e.g. "Parameter", "Variable", ...).
*/
this.type = type;
/**
* @member {espree.Identifier} Definition#name - the identifier AST node of the occurrence.
*/
this.name = name;
/**
* @member {espree.Node} Definition#node - the enclosing node of the identifier.
*/
this.node = node;
/**
* @member {espree.Node?} Definition#parent - the enclosing statement node of the identifier.
*/
this.parent = parent;
/**
* @member {number?} Definition#index - the index in the declaration statement.
*/
this.index = index;
/**
* @member {string?} Definition#kind - the kind of the declaration statement.
*/
this.kind = kind;
}
}
/**
* @constructor ParameterDefinition
*/
class ParameterDefinition extends Definition {
constructor(name, node, index, rest) {
super(Variable.Parameter, name, node, null, index, null);
/**
* Whether the parameter definition is a part of a rest parameter.
* @member {boolean} ParameterDefinition#rest
*/
this.rest = rest;
}
}
export {
ParameterDefinition,
Definition
};
/* vim: set sw=4 ts=4 et tw=80 : */

View file

@ -0,0 +1,172 @@
/*
Copyright (C) 2012-2014 Yusuke Suzuki <utatane.tea@gmail.com>
Copyright (C) 2013 Alex Seville <hi@alexanderseville.com>
Copyright (C) 2014 Thiago de Arruda <tpadilha84@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 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 <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Escope (<a href="http://github.com/estools/escope">escope</a>) is an <a
* href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMAScript</a>
* scope analyzer extracted from the <a
* href="http://github.com/estools/esmangle">esmangle project</a/>.
* <p>
* <em>escope</em> finds lexical scopes in a source program, i.e. areas of that
* program where different occurrences of the same identifier refer to the same
* variable. With each scope the contained variables are collected, and each
* identifier reference in code is linked to its corresponding variable (if
* possible).
* <p>
* <em>escope</em> works on a syntax tree of the parsed source code which has
* to adhere to the <a
* href="https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API">
* Mozilla Parser API</a>. E.g. <a href="https://github.com/eslint/espree">espree</a> is a parser
* that produces such syntax trees.
* <p>
* The main interface is the {@link analyze} function.
* @module escope
*/
/* eslint no-underscore-dangle: ["error", { "allow": ["__currentScope"] }] */
import assert from "assert";
import ScopeManager from "./scope-manager.js";
import Referencer from "./referencer.js";
import Reference from "./reference.js";
import Variable from "./variable.js";
import eslintScopeVersion from "./version.js";
/**
* Set the default options
* @returns {Object} options
*/
function defaultOptions() {
return {
optimistic: false,
directive: false,
nodejsScope: false,
impliedStrict: false,
sourceType: "script", // one of ['script', 'module', 'commonjs']
ecmaVersion: 5,
childVisitorKeys: null,
fallback: "iteration"
};
}
/**
* Preform deep update on option object
* @param {Object} target Options
* @param {Object} override Updates
* @returns {Object} Updated options
*/
function updateDeeply(target, override) {
/**
* Is hash object
* @param {Object} value Test value
* @returns {boolean} Result
*/
function isHashObject(value) {
return typeof value === "object" && value instanceof Object && !(value instanceof Array) && !(value instanceof RegExp);
}
for (const key in override) {
if (Object.prototype.hasOwnProperty.call(override, key)) {
const val = override[key];
if (isHashObject(val)) {
if (isHashObject(target[key])) {
updateDeeply(target[key], val);
} else {
target[key] = updateDeeply({}, val);
}
} else {
target[key] = val;
}
}
}
return target;
}
/**
* Main interface function. Takes an Espree syntax tree and returns the
* analyzed scopes.
* @function analyze
* @param {espree.Tree} tree Abstract Syntax Tree
* @param {Object} providedOptions Options that tailor the scope analysis
* @param {boolean} [providedOptions.optimistic=false] the optimistic flag
* @param {boolean} [providedOptions.directive=false] the directive flag
* @param {boolean} [providedOptions.ignoreEval=false] whether to check 'eval()' calls
* @param {boolean} [providedOptions.nodejsScope=false] whether the whole
* script is executed under node.js environment. When enabled, escope adds
* a function scope immediately following the global scope.
* @param {boolean} [providedOptions.impliedStrict=false] implied strict mode
* (if ecmaVersion >= 5).
* @param {string} [providedOptions.sourceType='script'] the source type of the script. one of 'script', 'module', and 'commonjs'
* @param {number} [providedOptions.ecmaVersion=5] which ECMAScript version is considered
* @param {Object} [providedOptions.childVisitorKeys=null] Additional known visitor keys. See [esrecurse](https://github.com/estools/esrecurse)'s the `childVisitorKeys` option.
* @param {string} [providedOptions.fallback='iteration'] A kind of the fallback in order to encounter with unknown node. See [esrecurse](https://github.com/estools/esrecurse)'s the `fallback` option.
* @returns {ScopeManager} ScopeManager
*/
function analyze(tree, providedOptions) {
const options = updateDeeply(defaultOptions(), providedOptions);
const scopeManager = new ScopeManager(options);
const referencer = new Referencer(options, scopeManager);
referencer.visit(tree);
assert(scopeManager.__currentScope === null, "currentScope should be null.");
return scopeManager;
}
export {
/** @name module:escope.version */
eslintScopeVersion as version,
/** @name module:escope.Reference */
Reference,
/** @name module:escope.Variable */
Variable,
/** @name module:escope.ScopeManager */
ScopeManager,
/** @name module:escope.Referencer */
Referencer,
analyze
};
/** @name module:escope.Definition */
export { Definition } from "./definition.js";
/** @name module:escope.PatternVisitor */
export { default as PatternVisitor } from "./pattern-visitor.js";
/** @name module:escope.Scope */
export { Scope } from "./scope.js";
/* vim: set sw=4 ts=4 et tw=80 : */

View file

@ -0,0 +1,153 @@
/*
Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 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 <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* eslint-disable no-undefined */
import estraverse from "estraverse";
import esrecurse from "esrecurse";
const { Syntax } = estraverse;
/**
* Get last array element
* @param {Array} xs array
* @returns {any} Last elment
*/
function getLast(xs) {
return xs[xs.length - 1] || null;
}
class PatternVisitor extends esrecurse.Visitor {
static isPattern(node) {
const nodeType = node.type;
return (
nodeType === Syntax.Identifier ||
nodeType === Syntax.ObjectPattern ||
nodeType === Syntax.ArrayPattern ||
nodeType === Syntax.SpreadElement ||
nodeType === Syntax.RestElement ||
nodeType === Syntax.AssignmentPattern
);
}
constructor(options, rootPattern, callback) {
super(null, options);
this.rootPattern = rootPattern;
this.callback = callback;
this.assignments = [];
this.rightHandNodes = [];
this.restElements = [];
}
Identifier(pattern) {
const lastRestElement = getLast(this.restElements);
this.callback(pattern, {
topLevel: pattern === this.rootPattern,
rest: lastRestElement !== null && lastRestElement !== undefined && lastRestElement.argument === pattern,
assignments: this.assignments
});
}
Property(property) {
// Computed property's key is a right hand node.
if (property.computed) {
this.rightHandNodes.push(property.key);
}
// If it's shorthand, its key is same as its value.
// If it's shorthand and has its default value, its key is same as its value.left (the value is AssignmentPattern).
// If it's not shorthand, the name of new variable is its value's.
this.visit(property.value);
}
ArrayPattern(pattern) {
for (let i = 0, iz = pattern.elements.length; i < iz; ++i) {
const element = pattern.elements[i];
this.visit(element);
}
}
AssignmentPattern(pattern) {
this.assignments.push(pattern);
this.visit(pattern.left);
this.rightHandNodes.push(pattern.right);
this.assignments.pop();
}
RestElement(pattern) {
this.restElements.push(pattern);
this.visit(pattern.argument);
this.restElements.pop();
}
MemberExpression(node) {
// Computed property's key is a right hand node.
if (node.computed) {
this.rightHandNodes.push(node.property);
}
// the object is only read, write to its property.
this.rightHandNodes.push(node.object);
}
//
// ForInStatement.left and AssignmentExpression.left are LeftHandSideExpression.
// By spec, LeftHandSideExpression is Pattern or MemberExpression.
// (see also: https://github.com/estree/estree/pull/20#issuecomment-74584758)
// But espree 2.0 parses to ArrayExpression, ObjectExpression, etc...
//
SpreadElement(node) {
this.visit(node.argument);
}
ArrayExpression(node) {
node.elements.forEach(this.visit, this);
}
AssignmentExpression(node) {
this.assignments.push(node);
this.visit(node.left);
this.rightHandNodes.push(node.right);
this.assignments.pop();
}
CallExpression(node) {
// arguments are right hand nodes.
node.arguments.forEach(a => {
this.rightHandNodes.push(a);
});
this.visit(node.callee);
}
}
export default PatternVisitor;
/* vim: set sw=4 ts=4 et tw=80 : */

View file

@ -0,0 +1,166 @@
/*
Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 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 <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
const READ = 0x1;
const WRITE = 0x2;
const RW = READ | WRITE;
/**
* A Reference represents a single occurrence of an identifier in code.
* @constructor Reference
*/
class Reference {
constructor(ident, scope, flag, writeExpr, maybeImplicitGlobal, partial, init) {
/**
* Identifier syntax node.
* @member {espreeIdentifier} Reference#identifier
*/
this.identifier = ident;
/**
* Reference to the enclosing Scope.
* @member {Scope} Reference#from
*/
this.from = scope;
/**
* Whether the reference comes from a dynamic scope (such as 'eval',
* 'with', etc.), and may be trapped by dynamic scopes.
* @member {boolean} Reference#tainted
*/
this.tainted = false;
/**
* The variable this reference is resolved with.
* @member {Variable} Reference#resolved
*/
this.resolved = null;
/**
* The read-write mode of the reference. (Value is one of {@link
* Reference.READ}, {@link Reference.RW}, {@link Reference.WRITE}).
* @member {number} Reference#flag
* @private
*/
this.flag = flag;
if (this.isWrite()) {
/**
* If reference is writeable, this is the tree being written to it.
* @member {espreeNode} Reference#writeExpr
*/
this.writeExpr = writeExpr;
/**
* Whether the Reference might refer to a partial value of writeExpr.
* @member {boolean} Reference#partial
*/
this.partial = partial;
/**
* Whether the Reference is to write of initialization.
* @member {boolean} Reference#init
*/
this.init = init;
}
this.__maybeImplicitGlobal = maybeImplicitGlobal;
}
/**
* Whether the reference is static.
* @function Reference#isStatic
* @returns {boolean} static
*/
isStatic() {
return !this.tainted && this.resolved && this.resolved.scope.isStatic();
}
/**
* Whether the reference is writeable.
* @function Reference#isWrite
* @returns {boolean} write
*/
isWrite() {
return !!(this.flag & Reference.WRITE);
}
/**
* Whether the reference is readable.
* @function Reference#isRead
* @returns {boolean} read
*/
isRead() {
return !!(this.flag & Reference.READ);
}
/**
* Whether the reference is read-only.
* @function Reference#isReadOnly
* @returns {boolean} read only
*/
isReadOnly() {
return this.flag === Reference.READ;
}
/**
* Whether the reference is write-only.
* @function Reference#isWriteOnly
* @returns {boolean} write only
*/
isWriteOnly() {
return this.flag === Reference.WRITE;
}
/**
* Whether the reference is read-write.
* @function Reference#isReadWrite
* @returns {boolean} read write
*/
isReadWrite() {
return this.flag === Reference.RW;
}
}
/**
* @constant Reference.READ
* @private
*/
Reference.READ = READ;
/**
* @constant Reference.WRITE
* @private
*/
Reference.WRITE = WRITE;
/**
* @constant Reference.RW
* @private
*/
Reference.RW = RW;
export default Reference;
/* vim: set sw=4 ts=4 et tw=80 : */

View file

@ -0,0 +1,654 @@
/*
Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 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 <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* eslint-disable no-underscore-dangle */
/* eslint-disable no-undefined */
import estraverse from "estraverse";
import esrecurse from "esrecurse";
import Reference from "./reference.js";
import Variable from "./variable.js";
import PatternVisitor from "./pattern-visitor.js";
import { Definition, ParameterDefinition } from "./definition.js";
import assert from "assert";
const { Syntax } = estraverse;
/**
* Traverse identifier in pattern
* @param {Object} options options
* @param {pattern} rootPattern root pattern
* @param {Refencer} referencer referencer
* @param {callback} callback callback
* @returns {void}
*/
function traverseIdentifierInPattern(options, rootPattern, referencer, callback) {
// Call the callback at left hand identifier nodes, and Collect right hand nodes.
const visitor = new PatternVisitor(options, rootPattern, callback);
visitor.visit(rootPattern);
// Process the right hand nodes recursively.
if (referencer !== null && referencer !== undefined) {
visitor.rightHandNodes.forEach(referencer.visit, referencer);
}
}
// Importing ImportDeclaration.
// http://people.mozilla.org/~jorendorff/es6-draft.html#sec-moduledeclarationinstantiation
// https://github.com/estree/estree/blob/master/es6.md#importdeclaration
// FIXME: Now, we don't create module environment, because the context is
// implementation dependent.
class Importer extends esrecurse.Visitor {
constructor(declaration, referencer) {
super(null, referencer.options);
this.declaration = declaration;
this.referencer = referencer;
}
visitImport(id, specifier) {
this.referencer.visitPattern(id, pattern => {
this.referencer.currentScope().__define(pattern,
new Definition(
Variable.ImportBinding,
pattern,
specifier,
this.declaration,
null,
null
));
});
}
ImportNamespaceSpecifier(node) {
const local = (node.local || node.id);
if (local) {
this.visitImport(local, node);
}
}
ImportDefaultSpecifier(node) {
const local = (node.local || node.id);
this.visitImport(local, node);
}
ImportSpecifier(node) {
const local = (node.local || node.id);
if (node.name) {
this.visitImport(node.name, node);
} else {
this.visitImport(local, node);
}
}
}
// Referencing variables and creating bindings.
class Referencer extends esrecurse.Visitor {
constructor(options, scopeManager) {
super(null, options);
this.options = options;
this.scopeManager = scopeManager;
this.parent = null;
this.isInnerMethodDefinition = false;
}
currentScope() {
return this.scopeManager.__currentScope;
}
close(node) {
while (this.currentScope() && node === this.currentScope().block) {
this.scopeManager.__currentScope = this.currentScope().__close(this.scopeManager);
}
}
pushInnerMethodDefinition(isInnerMethodDefinition) {
const previous = this.isInnerMethodDefinition;
this.isInnerMethodDefinition = isInnerMethodDefinition;
return previous;
}
popInnerMethodDefinition(isInnerMethodDefinition) {
this.isInnerMethodDefinition = isInnerMethodDefinition;
}
referencingDefaultValue(pattern, assignments, maybeImplicitGlobal, init) {
const scope = this.currentScope();
assignments.forEach(assignment => {
scope.__referencing(
pattern,
Reference.WRITE,
assignment.right,
maybeImplicitGlobal,
pattern !== assignment.left,
init
);
});
}
visitPattern(node, options, callback) {
let visitPatternOptions = options;
let visitPatternCallback = callback;
if (typeof options === "function") {
visitPatternCallback = options;
visitPatternOptions = { processRightHandNodes: false };
}
traverseIdentifierInPattern(
this.options,
node,
visitPatternOptions.processRightHandNodes ? this : null,
visitPatternCallback
);
}
visitFunction(node) {
let i, iz;
// FunctionDeclaration name is defined in upper scope
// NOTE: Not referring variableScope. It is intended.
// Since
// in ES5, FunctionDeclaration should be in FunctionBody.
// in ES6, FunctionDeclaration should be block scoped.
if (node.type === Syntax.FunctionDeclaration) {
// id is defined in upper scope
this.currentScope().__define(node.id,
new Definition(
Variable.FunctionName,
node.id,
node,
null,
null,
null
));
}
// FunctionExpression with name creates its special scope;
// FunctionExpressionNameScope.
if (node.type === Syntax.FunctionExpression && node.id) {
this.scopeManager.__nestFunctionExpressionNameScope(node);
}
// Consider this function is in the MethodDefinition.
this.scopeManager.__nestFunctionScope(node, this.isInnerMethodDefinition);
const that = this;
/**
* Visit pattern callback
* @param {pattern} pattern pattern
* @param {Object} info info
* @returns {void}
*/
function visitPatternCallback(pattern, info) {
that.currentScope().__define(pattern,
new ParameterDefinition(
pattern,
node,
i,
info.rest
));
that.referencingDefaultValue(pattern, info.assignments, null, true);
}
// Process parameter declarations.
for (i = 0, iz = node.params.length; i < iz; ++i) {
this.visitPattern(node.params[i], { processRightHandNodes: true }, visitPatternCallback);
}
// if there's a rest argument, add that
if (node.rest) {
this.visitPattern({
type: "RestElement",
argument: node.rest
}, pattern => {
this.currentScope().__define(pattern,
new ParameterDefinition(
pattern,
node,
node.params.length,
true
));
});
}
// In TypeScript there are a number of function-like constructs which have no body,
// so check it exists before traversing
if (node.body) {
// Skip BlockStatement to prevent creating BlockStatement scope.
if (node.body.type === Syntax.BlockStatement) {
this.visitChildren(node.body);
} else {
this.visit(node.body);
}
}
this.close(node);
}
visitClass(node) {
if (node.type === Syntax.ClassDeclaration) {
this.currentScope().__define(node.id,
new Definition(
Variable.ClassName,
node.id,
node,
null,
null,
null
));
}
this.visit(node.superClass);
this.scopeManager.__nestClassScope(node);
if (node.id) {
this.currentScope().__define(node.id,
new Definition(
Variable.ClassName,
node.id,
node
));
}
this.visit(node.body);
this.close(node);
}
visitProperty(node) {
let previous;
if (node.computed) {
this.visit(node.key);
}
const isMethodDefinition = node.type === Syntax.MethodDefinition;
if (isMethodDefinition) {
previous = this.pushInnerMethodDefinition(true);
}
this.visit(node.value);
if (isMethodDefinition) {
this.popInnerMethodDefinition(previous);
}
}
visitForIn(node) {
if (node.left.type === Syntax.VariableDeclaration && node.left.kind !== "var") {
this.scopeManager.__nestForScope(node);
}
if (node.left.type === Syntax.VariableDeclaration) {
this.visit(node.left);
this.visitPattern(node.left.declarations[0].id, pattern => {
this.currentScope().__referencing(pattern, Reference.WRITE, node.right, null, true, true);
});
} else {
this.visitPattern(node.left, { processRightHandNodes: true }, (pattern, info) => {
let maybeImplicitGlobal = null;
if (!this.currentScope().isStrict) {
maybeImplicitGlobal = {
pattern,
node
};
}
this.referencingDefaultValue(pattern, info.assignments, maybeImplicitGlobal, false);
this.currentScope().__referencing(pattern, Reference.WRITE, node.right, maybeImplicitGlobal, true, false);
});
}
this.visit(node.right);
this.visit(node.body);
this.close(node);
}
visitVariableDeclaration(variableTargetScope, type, node, index) {
const decl = node.declarations[index];
const init = decl.init;
this.visitPattern(decl.id, { processRightHandNodes: true }, (pattern, info) => {
variableTargetScope.__define(
pattern,
new Definition(
type,
pattern,
decl,
node,
index,
node.kind
)
);
this.referencingDefaultValue(pattern, info.assignments, null, true);
if (init) {
this.currentScope().__referencing(pattern, Reference.WRITE, init, null, !info.topLevel, true);
}
});
}
AssignmentExpression(node) {
if (PatternVisitor.isPattern(node.left)) {
if (node.operator === "=") {
this.visitPattern(node.left, { processRightHandNodes: true }, (pattern, info) => {
let maybeImplicitGlobal = null;
if (!this.currentScope().isStrict) {
maybeImplicitGlobal = {
pattern,
node
};
}
this.referencingDefaultValue(pattern, info.assignments, maybeImplicitGlobal, false);
this.currentScope().__referencing(pattern, Reference.WRITE, node.right, maybeImplicitGlobal, !info.topLevel, false);
});
} else {
this.currentScope().__referencing(node.left, Reference.RW, node.right);
}
} else {
this.visit(node.left);
}
this.visit(node.right);
}
CatchClause(node) {
this.scopeManager.__nestCatchScope(node);
this.visitPattern(node.param, { processRightHandNodes: true }, (pattern, info) => {
this.currentScope().__define(pattern,
new Definition(
Variable.CatchClause,
node.param,
node,
null,
null,
null
));
this.referencingDefaultValue(pattern, info.assignments, null, true);
});
this.visit(node.body);
this.close(node);
}
Program(node) {
this.scopeManager.__nestGlobalScope(node);
if (this.scopeManager.__isNodejsScope()) {
// Force strictness of GlobalScope to false when using node.js scope.
this.currentScope().isStrict = false;
this.scopeManager.__nestFunctionScope(node, false);
}
if (this.scopeManager.__isES6() && this.scopeManager.isModule()) {
this.scopeManager.__nestModuleScope(node);
}
if (this.scopeManager.isStrictModeSupported() && this.scopeManager.isImpliedStrict()) {
this.currentScope().isStrict = true;
}
this.visitChildren(node);
this.close(node);
}
Identifier(node) {
this.currentScope().__referencing(node);
}
// eslint-disable-next-line class-methods-use-this
PrivateIdentifier() {
// Do nothing.
}
UpdateExpression(node) {
if (PatternVisitor.isPattern(node.argument)) {
this.currentScope().__referencing(node.argument, Reference.RW, null);
} else {
this.visitChildren(node);
}
}
MemberExpression(node) {
this.visit(node.object);
if (node.computed) {
this.visit(node.property);
}
}
Property(node) {
this.visitProperty(node);
}
PropertyDefinition(node) {
const { computed, key, value } = node;
if (computed) {
this.visit(key);
}
if (value) {
this.scopeManager.__nestClassFieldInitializerScope(value);
this.visit(value);
this.close(value);
}
}
StaticBlock(node) {
this.scopeManager.__nestClassStaticBlockScope(node);
this.visitChildren(node);
this.close(node);
}
MethodDefinition(node) {
this.visitProperty(node);
}
BreakStatement() {} // eslint-disable-line class-methods-use-this
ContinueStatement() {} // eslint-disable-line class-methods-use-this
LabeledStatement(node) {
this.visit(node.body);
}
ForStatement(node) {
// Create ForStatement declaration.
// NOTE: In ES6, ForStatement dynamically generates
// per iteration environment. However, escope is
// a static analyzer, we only generate one scope for ForStatement.
if (node.init && node.init.type === Syntax.VariableDeclaration && node.init.kind !== "var") {
this.scopeManager.__nestForScope(node);
}
this.visitChildren(node);
this.close(node);
}
ClassExpression(node) {
this.visitClass(node);
}
ClassDeclaration(node) {
this.visitClass(node);
}
CallExpression(node) {
// Check this is direct call to eval
if (!this.scopeManager.__ignoreEval() && node.callee.type === Syntax.Identifier && node.callee.name === "eval") {
// NOTE: This should be `variableScope`. Since direct eval call always creates Lexical environment and
// let / const should be enclosed into it. Only VariableDeclaration affects on the caller's environment.
this.currentScope().variableScope.__detectEval();
}
this.visitChildren(node);
}
BlockStatement(node) {
if (this.scopeManager.__isES6()) {
this.scopeManager.__nestBlockScope(node);
}
this.visitChildren(node);
this.close(node);
}
ThisExpression() {
this.currentScope().variableScope.__detectThis();
}
WithStatement(node) {
this.visit(node.object);
// Then nest scope for WithStatement.
this.scopeManager.__nestWithScope(node);
this.visit(node.body);
this.close(node);
}
VariableDeclaration(node) {
const variableTargetScope = (node.kind === "var") ? this.currentScope().variableScope : this.currentScope();
for (let i = 0, iz = node.declarations.length; i < iz; ++i) {
const decl = node.declarations[i];
this.visitVariableDeclaration(variableTargetScope, Variable.Variable, node, i);
if (decl.init) {
this.visit(decl.init);
}
}
}
// sec 13.11.8
SwitchStatement(node) {
this.visit(node.discriminant);
if (this.scopeManager.__isES6()) {
this.scopeManager.__nestSwitchScope(node);
}
for (let i = 0, iz = node.cases.length; i < iz; ++i) {
this.visit(node.cases[i]);
}
this.close(node);
}
FunctionDeclaration(node) {
this.visitFunction(node);
}
FunctionExpression(node) {
this.visitFunction(node);
}
ForOfStatement(node) {
this.visitForIn(node);
}
ForInStatement(node) {
this.visitForIn(node);
}
ArrowFunctionExpression(node) {
this.visitFunction(node);
}
ImportDeclaration(node) {
assert(this.scopeManager.__isES6() && this.scopeManager.isModule(), "ImportDeclaration should appear when the mode is ES6 and in the module context.");
const importer = new Importer(node, this);
importer.visit(node);
}
visitExportDeclaration(node) {
if (node.source) {
return;
}
if (node.declaration) {
this.visit(node.declaration);
return;
}
this.visitChildren(node);
}
// TODO: ExportDeclaration doesn't exist. for bc?
ExportDeclaration(node) {
this.visitExportDeclaration(node);
}
ExportAllDeclaration(node) {
this.visitExportDeclaration(node);
}
ExportDefaultDeclaration(node) {
this.visitExportDeclaration(node);
}
ExportNamedDeclaration(node) {
this.visitExportDeclaration(node);
}
ExportSpecifier(node) {
// TODO: `node.id` doesn't exist. for bc?
const local = (node.id || node.local);
this.visit(local);
}
MetaProperty() { // eslint-disable-line class-methods-use-this
// do nothing.
}
}
export default Referencer;
/* vim: set sw=4 ts=4 et tw=80 : */

View file

@ -0,0 +1,255 @@
/*
Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 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 <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* eslint-disable no-underscore-dangle */
import {
BlockScope,
CatchScope,
ClassFieldInitializerScope,
ClassStaticBlockScope,
ClassScope,
ForScope,
FunctionExpressionNameScope,
FunctionScope,
GlobalScope,
ModuleScope,
SwitchScope,
WithScope
} from "./scope.js";
import assert from "assert";
/**
* @constructor ScopeManager
*/
class ScopeManager {
constructor(options) {
this.scopes = [];
this.globalScope = null;
this.__nodeToScope = new WeakMap();
this.__currentScope = null;
this.__options = options;
this.__declaredVariables = new WeakMap();
}
__useDirective() {
return this.__options.directive;
}
__isOptimistic() {
return this.__options.optimistic;
}
__ignoreEval() {
return this.__options.ignoreEval;
}
__isNodejsScope() {
return this.__options.nodejsScope || this.__options.sourceType === "commonjs";
}
isModule() {
return this.__options.sourceType === "module";
}
isImpliedStrict() {
return this.__options.impliedStrict;
}
isStrictModeSupported() {
return this.__options.ecmaVersion >= 5;
}
// Returns appropriate scope for this node.
__get(node) {
return this.__nodeToScope.get(node);
}
/**
* Get variables that are declared by the node.
*
* "are declared by the node" means the node is same as `Variable.defs[].node` or `Variable.defs[].parent`.
* If the node declares nothing, this method returns an empty array.
* CAUTION: This API is experimental. See https://github.com/estools/escope/pull/69 for more details.
* @param {Espree.Node} node a node to get.
* @returns {Variable[]} variables that declared by the node.
*/
getDeclaredVariables(node) {
return this.__declaredVariables.get(node) || [];
}
/**
* acquire scope from node.
* @function ScopeManager#acquire
* @param {Espree.Node} node node for the acquired scope.
* @param {?boolean} [inner=false] look up the most inner scope, default value is false.
* @returns {Scope?} Scope from node
*/
acquire(node, inner) {
/**
* predicate
* @param {Scope} testScope scope to test
* @returns {boolean} predicate
*/
function predicate(testScope) {
if (testScope.type === "function" && testScope.functionExpressionScope) {
return false;
}
return true;
}
const scopes = this.__get(node);
if (!scopes || scopes.length === 0) {
return null;
}
// Heuristic selection from all scopes.
// If you would like to get all scopes, please use ScopeManager#acquireAll.
if (scopes.length === 1) {
return scopes[0];
}
if (inner) {
for (let i = scopes.length - 1; i >= 0; --i) {
const scope = scopes[i];
if (predicate(scope)) {
return scope;
}
}
} else {
for (let i = 0, iz = scopes.length; i < iz; ++i) {
const scope = scopes[i];
if (predicate(scope)) {
return scope;
}
}
}
return null;
}
/**
* acquire all scopes from node.
* @function ScopeManager#acquireAll
* @param {Espree.Node} node node for the acquired scope.
* @returns {Scopes?} Scope array
*/
acquireAll(node) {
return this.__get(node);
}
/**
* release the node.
* @function ScopeManager#release
* @param {Espree.Node} node releasing node.
* @param {?boolean} [inner=false] look up the most inner scope, default value is false.
* @returns {Scope?} upper scope for the node.
*/
release(node, inner) {
const scopes = this.__get(node);
if (scopes && scopes.length) {
const scope = scopes[0].upper;
if (!scope) {
return null;
}
return this.acquire(scope.block, inner);
}
return null;
}
attach() { } // eslint-disable-line class-methods-use-this
detach() { } // eslint-disable-line class-methods-use-this
__nestScope(scope) {
if (scope instanceof GlobalScope) {
assert(this.__currentScope === null);
this.globalScope = scope;
}
this.__currentScope = scope;
return scope;
}
__nestGlobalScope(node) {
return this.__nestScope(new GlobalScope(this, node));
}
__nestBlockScope(node) {
return this.__nestScope(new BlockScope(this, this.__currentScope, node));
}
__nestFunctionScope(node, isMethodDefinition) {
return this.__nestScope(new FunctionScope(this, this.__currentScope, node, isMethodDefinition));
}
__nestForScope(node) {
return this.__nestScope(new ForScope(this, this.__currentScope, node));
}
__nestCatchScope(node) {
return this.__nestScope(new CatchScope(this, this.__currentScope, node));
}
__nestWithScope(node) {
return this.__nestScope(new WithScope(this, this.__currentScope, node));
}
__nestClassScope(node) {
return this.__nestScope(new ClassScope(this, this.__currentScope, node));
}
__nestClassFieldInitializerScope(node) {
return this.__nestScope(new ClassFieldInitializerScope(this, this.__currentScope, node));
}
__nestClassStaticBlockScope(node) {
return this.__nestScope(new ClassStaticBlockScope(this, this.__currentScope, node));
}
__nestSwitchScope(node) {
return this.__nestScope(new SwitchScope(this, this.__currentScope, node));
}
__nestModuleScope(node) {
return this.__nestScope(new ModuleScope(this, this.__currentScope, node));
}
__nestFunctionExpressionNameScope(node) {
return this.__nestScope(new FunctionExpressionNameScope(this, this.__currentScope, node));
}
__isES6() {
return this.__options.ecmaVersion >= 6;
}
}
export default ScopeManager;
/* vim: set sw=4 ts=4 et tw=80 : */

View file

@ -0,0 +1,772 @@
/*
Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 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 <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* eslint-disable no-underscore-dangle */
/* eslint-disable no-undefined */
import estraverse from "estraverse";
import Reference from "./reference.js";
import Variable from "./variable.js";
import { Definition } from "./definition.js";
import assert from "assert";
const { Syntax } = estraverse;
/**
* Test if scope is struct
* @param {Scope} scope scope
* @param {Block} block block
* @param {boolean} isMethodDefinition is method definition
* @param {boolean} useDirective use directive
* @returns {boolean} is strict scope
*/
function isStrictScope(scope, block, isMethodDefinition, useDirective) {
let body;
// When upper scope is exists and strict, inner scope is also strict.
if (scope.upper && scope.upper.isStrict) {
return true;
}
if (isMethodDefinition) {
return true;
}
if (scope.type === "class" || scope.type === "module") {
return true;
}
if (scope.type === "block" || scope.type === "switch") {
return false;
}
if (scope.type === "function") {
if (block.type === Syntax.ArrowFunctionExpression && block.body.type !== Syntax.BlockStatement) {
return false;
}
if (block.type === Syntax.Program) {
body = block;
} else {
body = block.body;
}
if (!body) {
return false;
}
} else if (scope.type === "global") {
body = block;
} else {
return false;
}
// Search 'use strict' directive.
if (useDirective) {
for (let i = 0, iz = body.body.length; i < iz; ++i) {
const stmt = body.body[i];
if (stmt.type !== Syntax.DirectiveStatement) {
break;
}
if (stmt.raw === "\"use strict\"" || stmt.raw === "'use strict'") {
return true;
}
}
} else {
for (let i = 0, iz = body.body.length; i < iz; ++i) {
const stmt = body.body[i];
if (stmt.type !== Syntax.ExpressionStatement) {
break;
}
const expr = stmt.expression;
if (expr.type !== Syntax.Literal || typeof expr.value !== "string") {
break;
}
if (expr.raw !== null && expr.raw !== undefined) {
if (expr.raw === "\"use strict\"" || expr.raw === "'use strict'") {
return true;
}
} else {
if (expr.value === "use strict") {
return true;
}
}
}
}
return false;
}
/**
* Register scope
* @param {ScopeManager} scopeManager scope manager
* @param {Scope} scope scope
* @returns {void}
*/
function registerScope(scopeManager, scope) {
scopeManager.scopes.push(scope);
const scopes = scopeManager.__nodeToScope.get(scope.block);
if (scopes) {
scopes.push(scope);
} else {
scopeManager.__nodeToScope.set(scope.block, [scope]);
}
}
/**
* Should be statically
* @param {Object} def def
* @returns {boolean} should be statically
*/
function shouldBeStatically(def) {
return (
(def.type === Variable.ClassName) ||
(def.type === Variable.Variable && def.parent.kind !== "var")
);
}
/**
* @constructor Scope
*/
class Scope {
constructor(scopeManager, type, upperScope, block, isMethodDefinition) {
/**
* One of "global", "module", "function", "function-expression-name", "block", "switch", "catch", "with", "for",
* "class", "class-field-initializer", "class-static-block".
* @member {string} Scope#type
*/
this.type = type;
/**
* The scoped {@link Variable}s of this scope, as <code>{ Variable.name
* : Variable }</code>.
* @member {Map} Scope#set
*/
this.set = new Map();
/**
* The tainted variables of this scope, as <code>{ Variable.name :
* boolean }</code>.
* @member {Map} Scope#taints */
this.taints = new Map();
/**
* Generally, through the lexical scoping of JS you can always know
* which variable an identifier in the source code refers to. There are
* a few exceptions to this rule. With 'global' and 'with' scopes you
* can only decide at runtime which variable a reference refers to.
* Moreover, if 'eval()' is used in a scope, it might introduce new
* bindings in this or its parent scopes.
* All those scopes are considered 'dynamic'.
* @member {boolean} Scope#dynamic
*/
this.dynamic = this.type === "global" || this.type === "with";
/**
* A reference to the scope-defining syntax node.
* @member {espree.Node} Scope#block
*/
this.block = block;
/**
* The {@link Reference|references} that are not resolved with this scope.
* @member {Reference[]} Scope#through
*/
this.through = [];
/**
* The scoped {@link Variable}s of this scope. In the case of a
* 'function' scope this includes the automatic argument <em>arguments</em> as
* its first element, as well as all further formal arguments.
* @member {Variable[]} Scope#variables
*/
this.variables = [];
/**
* Any variable {@link Reference|reference} found in this scope. This
* includes occurrences of local variables as well as variables from
* parent scopes (including the global scope). For local variables
* this also includes defining occurrences (like in a 'var' statement).
* In a 'function' scope this does not include the occurrences of the
* formal parameter in the parameter list.
* @member {Reference[]} Scope#references
*/
this.references = [];
/**
* For 'global' and 'function' scopes, this is a self-reference. For
* other scope types this is the <em>variableScope</em> value of the
* parent scope.
* @member {Scope} Scope#variableScope
*/
this.variableScope =
this.type === "global" ||
this.type === "module" ||
this.type === "function" ||
this.type === "class-field-initializer" ||
this.type === "class-static-block"
? this
: upperScope.variableScope;
/**
* Whether this scope is created by a FunctionExpression.
* @member {boolean} Scope#functionExpressionScope
*/
this.functionExpressionScope = false;
/**
* Whether this is a scope that contains an 'eval()' invocation.
* @member {boolean} Scope#directCallToEvalScope
*/
this.directCallToEvalScope = false;
/**
* @member {boolean} Scope#thisFound
*/
this.thisFound = false;
this.__left = [];
/**
* Reference to the parent {@link Scope|scope}.
* @member {Scope} Scope#upper
*/
this.upper = upperScope;
/**
* Whether 'use strict' is in effect in this scope.
* @member {boolean} Scope#isStrict
*/
this.isStrict = scopeManager.isStrictModeSupported()
? isStrictScope(this, block, isMethodDefinition, scopeManager.__useDirective())
: false;
/**
* List of nested {@link Scope}s.
* @member {Scope[]} Scope#childScopes
*/
this.childScopes = [];
if (this.upper) {
this.upper.childScopes.push(this);
}
this.__declaredVariables = scopeManager.__declaredVariables;
registerScope(scopeManager, this);
}
__shouldStaticallyClose(scopeManager) {
return (!this.dynamic || scopeManager.__isOptimistic());
}
__shouldStaticallyCloseForGlobal(ref) {
// On global scope, let/const/class declarations should be resolved statically.
const name = ref.identifier.name;
if (!this.set.has(name)) {
return false;
}
const variable = this.set.get(name);
const defs = variable.defs;
return defs.length > 0 && defs.every(shouldBeStatically);
}
__staticCloseRef(ref) {
if (!this.__resolve(ref)) {
this.__delegateToUpperScope(ref);
}
}
__dynamicCloseRef(ref) {
// notify all names are through to global
let current = this;
do {
current.through.push(ref);
current = current.upper;
} while (current);
}
__globalCloseRef(ref) {
// let/const/class declarations should be resolved statically.
// others should be resolved dynamically.
if (this.__shouldStaticallyCloseForGlobal(ref)) {
this.__staticCloseRef(ref);
} else {
this.__dynamicCloseRef(ref);
}
}
__close(scopeManager) {
let closeRef;
if (this.__shouldStaticallyClose(scopeManager)) {
closeRef = this.__staticCloseRef;
} else if (this.type !== "global") {
closeRef = this.__dynamicCloseRef;
} else {
closeRef = this.__globalCloseRef;
}
// Try Resolving all references in this scope.
for (let i = 0, iz = this.__left.length; i < iz; ++i) {
const ref = this.__left[i];
closeRef.call(this, ref);
}
this.__left = null;
return this.upper;
}
// To override by function scopes.
// References in default parameters isn't resolved to variables which are in their function body.
__isValidResolution(ref, variable) { // eslint-disable-line class-methods-use-this, no-unused-vars
return true;
}
__resolve(ref) {
const name = ref.identifier.name;
if (!this.set.has(name)) {
return false;
}
const variable = this.set.get(name);
if (!this.__isValidResolution(ref, variable)) {
return false;
}
variable.references.push(ref);
variable.stack = variable.stack && ref.from.variableScope === this.variableScope;
if (ref.tainted) {
variable.tainted = true;
this.taints.set(variable.name, true);
}
ref.resolved = variable;
return true;
}
__delegateToUpperScope(ref) {
if (this.upper) {
this.upper.__left.push(ref);
}
this.through.push(ref);
}
__addDeclaredVariablesOfNode(variable, node) {
if (node === null || node === undefined) {
return;
}
let variables = this.__declaredVariables.get(node);
if (variables === null || variables === undefined) {
variables = [];
this.__declaredVariables.set(node, variables);
}
if (variables.indexOf(variable) === -1) {
variables.push(variable);
}
}
__defineGeneric(name, set, variables, node, def) {
let variable;
variable = set.get(name);
if (!variable) {
variable = new Variable(name, this);
set.set(name, variable);
variables.push(variable);
}
if (def) {
variable.defs.push(def);
this.__addDeclaredVariablesOfNode(variable, def.node);
this.__addDeclaredVariablesOfNode(variable, def.parent);
}
if (node) {
variable.identifiers.push(node);
}
}
__define(node, def) {
if (node && node.type === Syntax.Identifier) {
this.__defineGeneric(
node.name,
this.set,
this.variables,
node,
def
);
}
}
__referencing(node, assign, writeExpr, maybeImplicitGlobal, partial, init) {
// because Array element may be null
if (!node || node.type !== Syntax.Identifier) {
return;
}
// Specially handle like `this`.
if (node.name === "super") {
return;
}
const ref = new Reference(node, this, assign || Reference.READ, writeExpr, maybeImplicitGlobal, !!partial, !!init);
this.references.push(ref);
this.__left.push(ref);
}
__detectEval() {
let current = this;
this.directCallToEvalScope = true;
do {
current.dynamic = true;
current = current.upper;
} while (current);
}
__detectThis() {
this.thisFound = true;
}
__isClosed() {
return this.__left === null;
}
/**
* returns resolved {Reference}
* @function Scope#resolve
* @param {Espree.Identifier} ident identifier to be resolved.
* @returns {Reference} reference
*/
resolve(ident) {
let ref, i, iz;
assert(this.__isClosed(), "Scope should be closed.");
assert(ident.type === Syntax.Identifier, "Target should be identifier.");
for (i = 0, iz = this.references.length; i < iz; ++i) {
ref = this.references[i];
if (ref.identifier === ident) {
return ref;
}
}
return null;
}
/**
* returns this scope is static
* @function Scope#isStatic
* @returns {boolean} static
*/
isStatic() {
return !this.dynamic;
}
/**
* returns this scope has materialized arguments
* @function Scope#isArgumentsMaterialized
* @returns {boolean} arguemnts materialized
*/
isArgumentsMaterialized() { // eslint-disable-line class-methods-use-this
return true;
}
/**
* returns this scope has materialized `this` reference
* @function Scope#isThisMaterialized
* @returns {boolean} this materialized
*/
isThisMaterialized() { // eslint-disable-line class-methods-use-this
return true;
}
isUsedName(name) {
if (this.set.has(name)) {
return true;
}
for (let i = 0, iz = this.through.length; i < iz; ++i) {
if (this.through[i].identifier.name === name) {
return true;
}
}
return false;
}
}
class GlobalScope extends Scope {
constructor(scopeManager, block) {
super(scopeManager, "global", null, block, false);
this.implicit = {
set: new Map(),
variables: [],
/**
* List of {@link Reference}s that are left to be resolved (i.e. which
* need to be linked to the variable they refer to).
* @member {Reference[]} Scope#implicit#left
*/
left: []
};
}
__close(scopeManager) {
const implicit = [];
for (let i = 0, iz = this.__left.length; i < iz; ++i) {
const ref = this.__left[i];
if (ref.__maybeImplicitGlobal && !this.set.has(ref.identifier.name)) {
implicit.push(ref.__maybeImplicitGlobal);
}
}
// create an implicit global variable from assignment expression
for (let i = 0, iz = implicit.length; i < iz; ++i) {
const info = implicit[i];
this.__defineImplicit(info.pattern,
new Definition(
Variable.ImplicitGlobalVariable,
info.pattern,
info.node,
null,
null,
null
));
}
this.implicit.left = this.__left;
return super.__close(scopeManager);
}
__defineImplicit(node, def) {
if (node && node.type === Syntax.Identifier) {
this.__defineGeneric(
node.name,
this.implicit.set,
this.implicit.variables,
node,
def
);
}
}
}
class ModuleScope extends Scope {
constructor(scopeManager, upperScope, block) {
super(scopeManager, "module", upperScope, block, false);
}
}
class FunctionExpressionNameScope extends Scope {
constructor(scopeManager, upperScope, block) {
super(scopeManager, "function-expression-name", upperScope, block, false);
this.__define(block.id,
new Definition(
Variable.FunctionName,
block.id,
block,
null,
null,
null
));
this.functionExpressionScope = true;
}
}
class CatchScope extends Scope {
constructor(scopeManager, upperScope, block) {
super(scopeManager, "catch", upperScope, block, false);
}
}
class WithScope extends Scope {
constructor(scopeManager, upperScope, block) {
super(scopeManager, "with", upperScope, block, false);
}
__close(scopeManager) {
if (this.__shouldStaticallyClose(scopeManager)) {
return super.__close(scopeManager);
}
for (let i = 0, iz = this.__left.length; i < iz; ++i) {
const ref = this.__left[i];
ref.tainted = true;
this.__delegateToUpperScope(ref);
}
this.__left = null;
return this.upper;
}
}
class BlockScope extends Scope {
constructor(scopeManager, upperScope, block) {
super(scopeManager, "block", upperScope, block, false);
}
}
class SwitchScope extends Scope {
constructor(scopeManager, upperScope, block) {
super(scopeManager, "switch", upperScope, block, false);
}
}
class FunctionScope extends Scope {
constructor(scopeManager, upperScope, block, isMethodDefinition) {
super(scopeManager, "function", upperScope, block, isMethodDefinition);
// section 9.2.13, FunctionDeclarationInstantiation.
// NOTE Arrow functions never have an arguments objects.
if (this.block.type !== Syntax.ArrowFunctionExpression) {
this.__defineArguments();
}
}
isArgumentsMaterialized() {
// TODO(Constellation)
// We can more aggressive on this condition like this.
//
// function t() {
// // arguments of t is always hidden.
// function arguments() {
// }
// }
if (this.block.type === Syntax.ArrowFunctionExpression) {
return false;
}
if (!this.isStatic()) {
return true;
}
const variable = this.set.get("arguments");
assert(variable, "Always have arguments variable.");
return variable.tainted || variable.references.length !== 0;
}
isThisMaterialized() {
if (!this.isStatic()) {
return true;
}
return this.thisFound;
}
__defineArguments() {
this.__defineGeneric(
"arguments",
this.set,
this.variables,
null,
null
);
this.taints.set("arguments", true);
}
// References in default parameters isn't resolved to variables which are in their function body.
// const x = 1
// function f(a = x) { // This `x` is resolved to the `x` in the outer scope.
// const x = 2
// console.log(a)
// }
__isValidResolution(ref, variable) {
// If `options.nodejsScope` is true, `this.block` becomes a Program node.
if (this.block.type === "Program") {
return true;
}
const bodyStart = this.block.body.range[0];
// It's invalid resolution in the following case:
return !(
variable.scope === this &&
ref.identifier.range[0] < bodyStart && // the reference is in the parameter part.
variable.defs.every(d => d.name.range[0] >= bodyStart) // the variable is in the body.
);
}
}
class ForScope extends Scope {
constructor(scopeManager, upperScope, block) {
super(scopeManager, "for", upperScope, block, false);
}
}
class ClassScope extends Scope {
constructor(scopeManager, upperScope, block) {
super(scopeManager, "class", upperScope, block, false);
}
}
class ClassFieldInitializerScope extends Scope {
constructor(scopeManager, upperScope, block) {
super(scopeManager, "class-field-initializer", upperScope, block, true);
}
}
class ClassStaticBlockScope extends Scope {
constructor(scopeManager, upperScope, block) {
super(scopeManager, "class-static-block", upperScope, block, true);
}
}
export {
Scope,
GlobalScope,
ModuleScope,
FunctionExpressionNameScope,
CatchScope,
WithScope,
BlockScope,
SwitchScope,
FunctionScope,
ForScope,
ClassScope,
ClassFieldInitializerScope,
ClassStaticBlockScope
};
/* vim: set sw=4 ts=4 et tw=80 : */

View file

@ -0,0 +1,87 @@
/*
Copyright (C) 2015 Yusuke Suzuki <utatane.tea@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 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 <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* A Variable represents a locally scoped identifier. These include arguments to
* functions.
* @constructor Variable
*/
class Variable {
constructor(name, scope) {
/**
* The variable name, as given in the source code.
* @member {string} Variable#name
*/
this.name = name;
/**
* List of defining occurrences of this variable (like in 'var ...'
* statements or as parameter), as AST nodes.
* @member {espree.Identifier[]} Variable#identifiers
*/
this.identifiers = [];
/**
* List of {@link Reference|references} of this variable (excluding parameter entries)
* in its defining scope and all nested scopes. For defining
* occurrences only see {@link Variable#defs}.
* @member {Reference[]} Variable#references
*/
this.references = [];
/**
* List of defining occurrences of this variable (like in 'var ...'
* statements or as parameter), as custom objects.
* @member {Definition[]} Variable#defs
*/
this.defs = [];
this.tainted = false;
/**
* Whether this is a stack variable.
* @member {boolean} Variable#stack
*/
this.stack = true;
/**
* Reference to the enclosing Scope.
* @member {Scope} Variable#scope
*/
this.scope = scope;
}
}
Variable.CatchClause = "CatchClause";
Variable.Parameter = "Parameter";
Variable.FunctionName = "FunctionName";
Variable.ClassName = "ClassName";
Variable.Variable = "Variable";
Variable.ImportBinding = "ImportBinding";
Variable.ImplicitGlobalVariable = "ImplicitGlobalVariable";
export default Variable;
/* vim: set sw=4 ts=4 et tw=80 : */

View file

@ -0,0 +1,3 @@
const version = "7.1.1";
export default version;

View file

@ -0,0 +1,62 @@
{
"name": "eslint-scope",
"description": "ECMAScript scope analyzer for ESLint",
"homepage": "http://github.com/eslint/eslint-scope",
"main": "./dist/eslint-scope.cjs",
"type": "module",
"exports": {
".": {
"import": "./lib/index.js",
"require": "./dist/eslint-scope.cjs"
},
"./package.json": "./package.json"
},
"version": "7.1.1",
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"repository": "eslint/eslint-scope",
"bugs": {
"url": "https://github.com/eslint/eslint-scope/issues"
},
"license": "BSD-2-Clause",
"scripts": {
"build": "rollup -c",
"lint": "npm run build && node Makefile.js lint",
"update-version": "node tools/update-version.js",
"test": "npm run build && node Makefile.js test",
"prepublishOnly": "npm run update-version && npm run build",
"generate-release": "eslint-generate-release",
"generate-alpharelease": "eslint-generate-prerelease alpha",
"generate-betarelease": "eslint-generate-prerelease beta",
"generate-rcrelease": "eslint-generate-prerelease rc",
"publish-release": "eslint-publish-release"
},
"files": [
"LICENSE",
"README.md",
"lib",
"dist/eslint-scope.cjs"
],
"dependencies": {
"esrecurse": "^4.3.0",
"estraverse": "^5.2.0"
},
"devDependencies": {
"@typescript-eslint/parser": "^4.28.1",
"c8": "^7.7.3",
"chai": "^4.3.4",
"eslint": "^7.29.0",
"eslint-config-eslint": "^7.0.0",
"eslint-plugin-jsdoc": "^35.4.1",
"eslint-plugin-node": "^11.1.0",
"eslint-release": "^3.2.0",
"eslint-visitor-keys": "^3.3.0",
"espree": "^9.3.1",
"mocha": "^9.0.1",
"npm-license": "^0.3.3",
"rollup": "^2.52.7",
"shelljs": "^0.8.4",
"typescript": "^4.3.5"
}
}

View file

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -0,0 +1,107 @@
# eslint-visitor-keys
[![npm version](https://img.shields.io/npm/v/eslint-visitor-keys.svg)](https://www.npmjs.com/package/eslint-visitor-keys)
[![Downloads/month](https://img.shields.io/npm/dm/eslint-visitor-keys.svg)](http://www.npmtrends.com/eslint-visitor-keys)
[![Build Status](https://travis-ci.org/eslint/eslint-visitor-keys.svg?branch=master)](https://travis-ci.org/eslint/eslint-visitor-keys)
[![Dependency Status](https://david-dm.org/eslint/eslint-visitor-keys.svg)](https://david-dm.org/eslint/eslint-visitor-keys)
Constants and utilities about visitor keys to traverse AST.
## 💿 Installation
Use [npm] to install.
```bash
$ npm install eslint-visitor-keys
```
### Requirements
- [Node.js] `^12.22.0`, `^14.17.0`, or `>=16.0.0`
## 📖 Usage
To use in an ESM file:
```js
import * as evk from "eslint-visitor-keys"
```
To use in a CommonJS file:
```js
const evk = require("eslint-visitor-keys")
```
### evk.KEYS
> type: `{ [type: string]: string[] | undefined }`
Visitor keys. This keys are frozen.
This is an object. Keys are the type of [ESTree] nodes. Their values are an array of property names which have child nodes.
For example:
```
console.log(evk.KEYS.AssignmentExpression) // → ["left", "right"]
```
### evk.getKeys(node)
> type: `(node: object) => string[]`
Get the visitor keys of a given AST node.
This is similar to `Object.keys(node)` of ES Standard, but some keys are excluded: `parent`, `leadingComments`, `trailingComments`, and names which start with `_`.
This will be used to traverse unknown nodes.
For example:
```js
const node = {
type: "AssignmentExpression",
left: { type: "Identifier", name: "foo" },
right: { type: "Literal", value: 0 }
}
console.log(evk.getKeys(node)) // → ["type", "left", "right"]
```
### evk.unionWith(additionalKeys)
> type: `(additionalKeys: object) => { [type: string]: string[] | undefined }`
Make the union set with `evk.KEYS` and the given keys.
- The order of keys is, `additionalKeys` is at first, then `evk.KEYS` is concatenated after that.
- It removes duplicated keys as keeping the first one.
For example:
```js
console.log(evk.unionWith({
MethodDefinition: ["decorators"]
})) // → { ..., MethodDefinition: ["decorators", "key", "value"], ... }
```
## 📰 Change log
See [GitHub releases](https://github.com/eslint/eslint-visitor-keys/releases).
## 🍻 Contributing
Welcome. See [ESLint contribution guidelines](https://eslint.org/docs/developer-guide/contributing/).
### Development commands
- `npm test` runs tests and measures code coverage.
- `npm run lint` checks source codes with ESLint.
- `npm run coverage` opens the code coverage report of the previous test with your default browser.
- `npm run release` publishes this package to [npm] registory.
[npm]: https://www.npmjs.com/
[Node.js]: https://nodejs.org/
[ESTree]: https://github.com/estree/estree

View file

@ -0,0 +1,382 @@
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
/**
* @typedef {import('./index.js').VisitorKeys} VisitorKeys
*/
/**
* @type {VisitorKeys}
*/
const KEYS = {
AssignmentExpression: [
"left",
"right"
],
AssignmentPattern: [
"left",
"right"
],
ArrayExpression: [
"elements"
],
ArrayPattern: [
"elements"
],
ArrowFunctionExpression: [
"params",
"body"
],
AwaitExpression: [
"argument"
],
BlockStatement: [
"body"
],
BinaryExpression: [
"left",
"right"
],
BreakStatement: [
"label"
],
CallExpression: [
"callee",
"arguments"
],
CatchClause: [
"param",
"body"
],
ChainExpression: [
"expression"
],
ClassBody: [
"body"
],
ClassDeclaration: [
"id",
"superClass",
"body"
],
ClassExpression: [
"id",
"superClass",
"body"
],
ConditionalExpression: [
"test",
"consequent",
"alternate"
],
ContinueStatement: [
"label"
],
DebuggerStatement: [],
DoWhileStatement: [
"body",
"test"
],
EmptyStatement: [],
ExportAllDeclaration: [
"exported",
"source"
],
ExportDefaultDeclaration: [
"declaration"
],
ExportNamedDeclaration: [
"declaration",
"specifiers",
"source"
],
ExportSpecifier: [
"exported",
"local"
],
ExpressionStatement: [
"expression"
],
ExperimentalRestProperty: [
"argument"
],
ExperimentalSpreadProperty: [
"argument"
],
ForStatement: [
"init",
"test",
"update",
"body"
],
ForInStatement: [
"left",
"right",
"body"
],
ForOfStatement: [
"left",
"right",
"body"
],
FunctionDeclaration: [
"id",
"params",
"body"
],
FunctionExpression: [
"id",
"params",
"body"
],
Identifier: [],
IfStatement: [
"test",
"consequent",
"alternate"
],
ImportDeclaration: [
"specifiers",
"source"
],
ImportDefaultSpecifier: [
"local"
],
ImportExpression: [
"source"
],
ImportNamespaceSpecifier: [
"local"
],
ImportSpecifier: [
"imported",
"local"
],
JSXAttribute: [
"name",
"value"
],
JSXClosingElement: [
"name"
],
JSXElement: [
"openingElement",
"children",
"closingElement"
],
JSXEmptyExpression: [],
JSXExpressionContainer: [
"expression"
],
JSXIdentifier: [],
JSXMemberExpression: [
"object",
"property"
],
JSXNamespacedName: [
"namespace",
"name"
],
JSXOpeningElement: [
"name",
"attributes"
],
JSXSpreadAttribute: [
"argument"
],
JSXText: [],
JSXFragment: [
"openingFragment",
"children",
"closingFragment"
],
JSXClosingFragment: [],
JSXOpeningFragment: [],
Literal: [],
LabeledStatement: [
"label",
"body"
],
LogicalExpression: [
"left",
"right"
],
MemberExpression: [
"object",
"property"
],
MetaProperty: [
"meta",
"property"
],
MethodDefinition: [
"key",
"value"
],
NewExpression: [
"callee",
"arguments"
],
ObjectExpression: [
"properties"
],
ObjectPattern: [
"properties"
],
PrivateIdentifier: [],
Program: [
"body"
],
Property: [
"key",
"value"
],
PropertyDefinition: [
"key",
"value"
],
RestElement: [
"argument"
],
ReturnStatement: [
"argument"
],
SequenceExpression: [
"expressions"
],
SpreadElement: [
"argument"
],
StaticBlock: [
"body"
],
Super: [],
SwitchStatement: [
"discriminant",
"cases"
],
SwitchCase: [
"test",
"consequent"
],
TaggedTemplateExpression: [
"tag",
"quasi"
],
TemplateElement: [],
TemplateLiteral: [
"quasis",
"expressions"
],
ThisExpression: [],
ThrowStatement: [
"argument"
],
TryStatement: [
"block",
"handler",
"finalizer"
],
UnaryExpression: [
"argument"
],
UpdateExpression: [
"argument"
],
VariableDeclaration: [
"declarations"
],
VariableDeclarator: [
"id",
"init"
],
WhileStatement: [
"test",
"body"
],
WithStatement: [
"object",
"body"
],
YieldExpression: [
"argument"
]
};
// Types.
const NODE_TYPES = Object.keys(KEYS);
// Freeze the keys.
for (const type of NODE_TYPES) {
Object.freeze(KEYS[type]);
}
Object.freeze(KEYS);
/**
* @author Toru Nagashima <https://github.com/mysticatea>
* See LICENSE file in root directory for full license.
*/
/**
* @typedef {{ readonly [type: string]: ReadonlyArray<string> }} VisitorKeys
*/
// List to ignore keys.
const KEY_BLACKLIST = new Set([
"parent",
"leadingComments",
"trailingComments"
]);
/**
* Check whether a given key should be used or not.
* @param {string} key The key to check.
* @returns {boolean} `true` if the key should be used.
*/
function filterKey(key) {
return !KEY_BLACKLIST.has(key) && key[0] !== "_";
}
/**
* Get visitor keys of a given node.
* @param {object} node The AST node to get keys.
* @returns {readonly string[]} Visitor keys of the node.
*/
function getKeys(node) {
return Object.keys(node).filter(filterKey);
}
// Disable valid-jsdoc rule because it reports syntax error on the type of @returns.
// eslint-disable-next-line valid-jsdoc
/**
* Make the union set with `KEYS` and given keys.
* @param {VisitorKeys} additionalKeys The additional keys.
* @returns {VisitorKeys} The union set.
*/
function unionWith(additionalKeys) {
const retv = /** @type {{
[type: string]: ReadonlyArray<string>
}} */ (Object.assign({}, KEYS));
for (const type of Object.keys(additionalKeys)) {
if (Object.prototype.hasOwnProperty.call(retv, type)) {
const keys = new Set(additionalKeys[type]);
for (const key of retv[type]) {
keys.add(key);
}
retv[type] = Object.freeze(Array.from(keys));
} else {
retv[type] = Object.freeze(Array.from(additionalKeys[type]));
}
}
return Object.freeze(retv);
}
exports.KEYS = KEYS;
exports.getKeys = getKeys;
exports.unionWith = unionWith;
//# sourceMappingURL=eslint-visitor-keys.cjs.map

View file

@ -0,0 +1,18 @@
/**
* Get visitor keys of a given node.
* @param {object} node The AST node to get keys.
* @returns {readonly string[]} Visitor keys of the node.
*/
export function getKeys(node: object): readonly string[];
/**
* Make the union set with `KEYS` and given keys.
* @param {VisitorKeys} additionalKeys The additional keys.
* @returns {VisitorKeys} The union set.
*/
export function unionWith(additionalKeys: VisitorKeys): VisitorKeys;
export { KEYS };
export type VisitorKeys = {
readonly [type: string]: readonly string[];
};
import KEYS from "./visitor-keys.js";
//# sourceMappingURL=index.d.ts.map

View file

@ -0,0 +1,10 @@
export default KEYS;
export type VisitorKeys = import('./index.js').VisitorKeys;
/**
* @typedef {import('./index.js').VisitorKeys} VisitorKeys
*/
/**
* @type {VisitorKeys}
*/
declare const KEYS: VisitorKeys;
//# sourceMappingURL=visitor-keys.d.ts.map

View file

@ -0,0 +1,65 @@
/**
* @author Toru Nagashima <https://github.com/mysticatea>
* See LICENSE file in root directory for full license.
*/
import KEYS from "./visitor-keys.js";
/**
* @typedef {{ readonly [type: string]: ReadonlyArray<string> }} VisitorKeys
*/
// List to ignore keys.
const KEY_BLACKLIST = new Set([
"parent",
"leadingComments",
"trailingComments"
]);
/**
* Check whether a given key should be used or not.
* @param {string} key The key to check.
* @returns {boolean} `true` if the key should be used.
*/
function filterKey(key) {
return !KEY_BLACKLIST.has(key) && key[0] !== "_";
}
/**
* Get visitor keys of a given node.
* @param {object} node The AST node to get keys.
* @returns {readonly string[]} Visitor keys of the node.
*/
export function getKeys(node) {
return Object.keys(node).filter(filterKey);
}
// Disable valid-jsdoc rule because it reports syntax error on the type of @returns.
// eslint-disable-next-line valid-jsdoc
/**
* Make the union set with `KEYS` and given keys.
* @param {VisitorKeys} additionalKeys The additional keys.
* @returns {VisitorKeys} The union set.
*/
export function unionWith(additionalKeys) {
const retv = /** @type {{
[type: string]: ReadonlyArray<string>
}} */ (Object.assign({}, KEYS));
for (const type of Object.keys(additionalKeys)) {
if (Object.prototype.hasOwnProperty.call(retv, type)) {
const keys = new Set(additionalKeys[type]);
for (const key of retv[type]) {
keys.add(key);
}
retv[type] = Object.freeze(Array.from(keys));
} else {
retv[type] = Object.freeze(Array.from(additionalKeys[type]));
}
}
return Object.freeze(retv);
}
export { KEYS };

View file

@ -0,0 +1,312 @@
/**
* @typedef {import('./index.js').VisitorKeys} VisitorKeys
*/
/**
* @type {VisitorKeys}
*/
const KEYS = {
AssignmentExpression: [
"left",
"right"
],
AssignmentPattern: [
"left",
"right"
],
ArrayExpression: [
"elements"
],
ArrayPattern: [
"elements"
],
ArrowFunctionExpression: [
"params",
"body"
],
AwaitExpression: [
"argument"
],
BlockStatement: [
"body"
],
BinaryExpression: [
"left",
"right"
],
BreakStatement: [
"label"
],
CallExpression: [
"callee",
"arguments"
],
CatchClause: [
"param",
"body"
],
ChainExpression: [
"expression"
],
ClassBody: [
"body"
],
ClassDeclaration: [
"id",
"superClass",
"body"
],
ClassExpression: [
"id",
"superClass",
"body"
],
ConditionalExpression: [
"test",
"consequent",
"alternate"
],
ContinueStatement: [
"label"
],
DebuggerStatement: [],
DoWhileStatement: [
"body",
"test"
],
EmptyStatement: [],
ExportAllDeclaration: [
"exported",
"source"
],
ExportDefaultDeclaration: [
"declaration"
],
ExportNamedDeclaration: [
"declaration",
"specifiers",
"source"
],
ExportSpecifier: [
"exported",
"local"
],
ExpressionStatement: [
"expression"
],
ExperimentalRestProperty: [
"argument"
],
ExperimentalSpreadProperty: [
"argument"
],
ForStatement: [
"init",
"test",
"update",
"body"
],
ForInStatement: [
"left",
"right",
"body"
],
ForOfStatement: [
"left",
"right",
"body"
],
FunctionDeclaration: [
"id",
"params",
"body"
],
FunctionExpression: [
"id",
"params",
"body"
],
Identifier: [],
IfStatement: [
"test",
"consequent",
"alternate"
],
ImportDeclaration: [
"specifiers",
"source"
],
ImportDefaultSpecifier: [
"local"
],
ImportExpression: [
"source"
],
ImportNamespaceSpecifier: [
"local"
],
ImportSpecifier: [
"imported",
"local"
],
JSXAttribute: [
"name",
"value"
],
JSXClosingElement: [
"name"
],
JSXElement: [
"openingElement",
"children",
"closingElement"
],
JSXEmptyExpression: [],
JSXExpressionContainer: [
"expression"
],
JSXIdentifier: [],
JSXMemberExpression: [
"object",
"property"
],
JSXNamespacedName: [
"namespace",
"name"
],
JSXOpeningElement: [
"name",
"attributes"
],
JSXSpreadAttribute: [
"argument"
],
JSXText: [],
JSXFragment: [
"openingFragment",
"children",
"closingFragment"
],
JSXClosingFragment: [],
JSXOpeningFragment: [],
Literal: [],
LabeledStatement: [
"label",
"body"
],
LogicalExpression: [
"left",
"right"
],
MemberExpression: [
"object",
"property"
],
MetaProperty: [
"meta",
"property"
],
MethodDefinition: [
"key",
"value"
],
NewExpression: [
"callee",
"arguments"
],
ObjectExpression: [
"properties"
],
ObjectPattern: [
"properties"
],
PrivateIdentifier: [],
Program: [
"body"
],
Property: [
"key",
"value"
],
PropertyDefinition: [
"key",
"value"
],
RestElement: [
"argument"
],
ReturnStatement: [
"argument"
],
SequenceExpression: [
"expressions"
],
SpreadElement: [
"argument"
],
StaticBlock: [
"body"
],
Super: [],
SwitchStatement: [
"discriminant",
"cases"
],
SwitchCase: [
"test",
"consequent"
],
TaggedTemplateExpression: [
"tag",
"quasi"
],
TemplateElement: [],
TemplateLiteral: [
"quasis",
"expressions"
],
ThisExpression: [],
ThrowStatement: [
"argument"
],
TryStatement: [
"block",
"handler",
"finalizer"
],
UnaryExpression: [
"argument"
],
UpdateExpression: [
"argument"
],
VariableDeclaration: [
"declarations"
],
VariableDeclarator: [
"id",
"init"
],
WhileStatement: [
"test",
"body"
],
WithStatement: [
"object",
"body"
],
YieldExpression: [
"argument"
]
};
// Types.
const NODE_TYPES = Object.keys(KEYS);
// Freeze the keys.
for (const type of NODE_TYPES) {
Object.freeze(KEYS[type]);
}
Object.freeze(KEYS);
export default KEYS;

View file

@ -0,0 +1,62 @@
{
"name": "eslint-visitor-keys",
"version": "3.3.0",
"description": "Constants and utilities about visitor keys to traverse AST.",
"type": "module",
"main": "dist/eslint-visitor-keys.cjs",
"types": "./dist/index.d.ts",
"exports": {
".": [
{
"import": "./lib/index.js",
"require": "./dist/eslint-visitor-keys.cjs"
},
"./dist/eslint-visitor-keys.cjs"
],
"./package.json": "./package.json"
},
"files": [
"dist/index.d.ts",
"dist/visitor-keys.d.ts",
"dist/eslint-visitor-keys.cjs",
"lib"
],
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"devDependencies": {
"c8": "^7.7.3",
"eslint": "^7.29.0",
"eslint-config-eslint": "^7.0.0",
"eslint-plugin-jsdoc": "^35.4.0",
"eslint-plugin-node": "^11.1.0",
"eslint-release": "^3.2.0",
"mocha": "^9.0.1",
"opener": "^1.5.2",
"rollup": "^2.52.1",
"tsd": "^0.19.1",
"typescript": "^4.5.5"
},
"scripts": {
"prepare": "npm run build",
"build": "rollup -c && npm run tsc",
"lint": "eslint .",
"tsc": "tsc",
"tsd": "tsd",
"test": "mocha tests/lib/**/*.cjs && c8 mocha tests/lib/**/*.js && npm run tsd",
"coverage": "c8 report --reporter lcov && opener coverage/lcov-report/index.html",
"generate-release": "eslint-generate-release",
"generate-alpharelease": "eslint-generate-prerelease alpha",
"generate-betarelease": "eslint-generate-prerelease beta",
"generate-rcrelease": "eslint-generate-prerelease rc",
"publish-release": "eslint-publish-release"
},
"repository": "eslint/eslint-visitor-keys",
"keywords": [],
"author": "Toru Nagashima (https://github.com/mysticatea)",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/eslint/eslint-visitor-keys/issues"
},
"homepage": "https://github.com/eslint/eslint-visitor-keys#readme"
}

16
node_modules/eslint/node_modules/estraverse/.jshintrc generated vendored Normal file
View file

@ -0,0 +1,16 @@
{
"curly": true,
"eqeqeq": true,
"immed": true,
"eqnull": true,
"latedef": true,
"noarg": true,
"noempty": true,
"quotmark": "single",
"undef": true,
"unused": true,
"strict": true,
"trailing": true,
"node": true
}

View file

@ -0,0 +1,19 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 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 <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

153
node_modules/eslint/node_modules/estraverse/README.md generated vendored Normal file
View file

@ -0,0 +1,153 @@
### Estraverse [![Build Status](https://secure.travis-ci.org/estools/estraverse.svg)](http://travis-ci.org/estools/estraverse)
Estraverse ([estraverse](http://github.com/estools/estraverse)) is
[ECMAScript](http://www.ecma-international.org/publications/standards/Ecma-262.htm)
traversal functions from [esmangle project](http://github.com/estools/esmangle).
### Documentation
You can find usage docs at [wiki page](https://github.com/estools/estraverse/wiki/Usage).
### Example Usage
The following code will output all variables declared at the root of a file.
```javascript
estraverse.traverse(ast, {
enter: function (node, parent) {
if (node.type == 'FunctionExpression' || node.type == 'FunctionDeclaration')
return estraverse.VisitorOption.Skip;
},
leave: function (node, parent) {
if (node.type == 'VariableDeclarator')
console.log(node.id.name);
}
});
```
We can use `this.skip`, `this.remove` and `this.break` functions instead of using Skip, Remove and Break.
```javascript
estraverse.traverse(ast, {
enter: function (node) {
this.break();
}
});
```
And estraverse provides `estraverse.replace` function. When returning node from `enter`/`leave`, current node is replaced with it.
```javascript
result = estraverse.replace(tree, {
enter: function (node) {
// Replace it with replaced.
if (node.type === 'Literal')
return replaced;
}
});
```
By passing `visitor.keys` mapping, we can extend estraverse traversing functionality.
```javascript
// This tree contains a user-defined `TestExpression` node.
var tree = {
type: 'TestExpression',
// This 'argument' is the property containing the other **node**.
argument: {
type: 'Literal',
value: 20
},
// This 'extended' is the property not containing the other **node**.
extended: true
};
estraverse.traverse(tree, {
enter: function (node) { },
// Extending the existing traversing rules.
keys: {
// TargetNodeName: [ 'keys', 'containing', 'the', 'other', '**node**' ]
TestExpression: ['argument']
}
});
```
By passing `visitor.fallback` option, we can control the behavior when encountering unknown nodes.
```javascript
// This tree contains a user-defined `TestExpression` node.
var tree = {
type: 'TestExpression',
// This 'argument' is the property containing the other **node**.
argument: {
type: 'Literal',
value: 20
},
// This 'extended' is the property not containing the other **node**.
extended: true
};
estraverse.traverse(tree, {
enter: function (node) { },
// Iterating the child **nodes** of unknown nodes.
fallback: 'iteration'
});
```
When `visitor.fallback` is a function, we can determine which keys to visit on each node.
```javascript
// This tree contains a user-defined `TestExpression` node.
var tree = {
type: 'TestExpression',
// This 'argument' is the property containing the other **node**.
argument: {
type: 'Literal',
value: 20
},
// This 'extended' is the property not containing the other **node**.
extended: true
};
estraverse.traverse(tree, {
enter: function (node) { },
// Skip the `argument` property of each node
fallback: function(node) {
return Object.keys(node).filter(function(key) {
return key !== 'argument';
});
}
});
```
### License
Copyright (C) 2012-2016 [Yusuke Suzuki](http://github.com/Constellation)
(twitter: [@Constellation](http://twitter.com/Constellation)) and other contributors.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 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 <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,805 @@
/*
Copyright (C) 2012-2013 Yusuke Suzuki <utatane.tea@gmail.com>
Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 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 <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*jslint vars:false, bitwise:true*/
/*jshint indent:4*/
/*global exports:true*/
(function clone(exports) {
'use strict';
var Syntax,
VisitorOption,
VisitorKeys,
BREAK,
SKIP,
REMOVE;
function deepCopy(obj) {
var ret = {}, key, val;
for (key in obj) {
if (obj.hasOwnProperty(key)) {
val = obj[key];
if (typeof val === 'object' && val !== null) {
ret[key] = deepCopy(val);
} else {
ret[key] = val;
}
}
}
return ret;
}
// based on LLVM libc++ upper_bound / lower_bound
// MIT License
function upperBound(array, func) {
var diff, len, i, current;
len = array.length;
i = 0;
while (len) {
diff = len >>> 1;
current = i + diff;
if (func(array[current])) {
len = diff;
} else {
i = current + 1;
len -= diff + 1;
}
}
return i;
}
Syntax = {
AssignmentExpression: 'AssignmentExpression',
AssignmentPattern: 'AssignmentPattern',
ArrayExpression: 'ArrayExpression',
ArrayPattern: 'ArrayPattern',
ArrowFunctionExpression: 'ArrowFunctionExpression',
AwaitExpression: 'AwaitExpression', // CAUTION: It's deferred to ES7.
BlockStatement: 'BlockStatement',
BinaryExpression: 'BinaryExpression',
BreakStatement: 'BreakStatement',
CallExpression: 'CallExpression',
CatchClause: 'CatchClause',
ChainExpression: 'ChainExpression',
ClassBody: 'ClassBody',
ClassDeclaration: 'ClassDeclaration',
ClassExpression: 'ClassExpression',
ComprehensionBlock: 'ComprehensionBlock', // CAUTION: It's deferred to ES7.
ComprehensionExpression: 'ComprehensionExpression', // CAUTION: It's deferred to ES7.
ConditionalExpression: 'ConditionalExpression',
ContinueStatement: 'ContinueStatement',
DebuggerStatement: 'DebuggerStatement',
DirectiveStatement: 'DirectiveStatement',
DoWhileStatement: 'DoWhileStatement',
EmptyStatement: 'EmptyStatement',
ExportAllDeclaration: 'ExportAllDeclaration',
ExportDefaultDeclaration: 'ExportDefaultDeclaration',
ExportNamedDeclaration: 'ExportNamedDeclaration',
ExportSpecifier: 'ExportSpecifier',
ExpressionStatement: 'ExpressionStatement',
ForStatement: 'ForStatement',
ForInStatement: 'ForInStatement',
ForOfStatement: 'ForOfStatement',
FunctionDeclaration: 'FunctionDeclaration',
FunctionExpression: 'FunctionExpression',
GeneratorExpression: 'GeneratorExpression', // CAUTION: It's deferred to ES7.
Identifier: 'Identifier',
IfStatement: 'IfStatement',
ImportExpression: 'ImportExpression',
ImportDeclaration: 'ImportDeclaration',
ImportDefaultSpecifier: 'ImportDefaultSpecifier',
ImportNamespaceSpecifier: 'ImportNamespaceSpecifier',
ImportSpecifier: 'ImportSpecifier',
Literal: 'Literal',
LabeledStatement: 'LabeledStatement',
LogicalExpression: 'LogicalExpression',
MemberExpression: 'MemberExpression',
MetaProperty: 'MetaProperty',
MethodDefinition: 'MethodDefinition',
ModuleSpecifier: 'ModuleSpecifier',
NewExpression: 'NewExpression',
ObjectExpression: 'ObjectExpression',
ObjectPattern: 'ObjectPattern',
PrivateIdentifier: 'PrivateIdentifier',
Program: 'Program',
Property: 'Property',
PropertyDefinition: 'PropertyDefinition',
RestElement: 'RestElement',
ReturnStatement: 'ReturnStatement',
SequenceExpression: 'SequenceExpression',
SpreadElement: 'SpreadElement',
Super: 'Super',
SwitchStatement: 'SwitchStatement',
SwitchCase: 'SwitchCase',
TaggedTemplateExpression: 'TaggedTemplateExpression',
TemplateElement: 'TemplateElement',
TemplateLiteral: 'TemplateLiteral',
ThisExpression: 'ThisExpression',
ThrowStatement: 'ThrowStatement',
TryStatement: 'TryStatement',
UnaryExpression: 'UnaryExpression',
UpdateExpression: 'UpdateExpression',
VariableDeclaration: 'VariableDeclaration',
VariableDeclarator: 'VariableDeclarator',
WhileStatement: 'WhileStatement',
WithStatement: 'WithStatement',
YieldExpression: 'YieldExpression'
};
VisitorKeys = {
AssignmentExpression: ['left', 'right'],
AssignmentPattern: ['left', 'right'],
ArrayExpression: ['elements'],
ArrayPattern: ['elements'],
ArrowFunctionExpression: ['params', 'body'],
AwaitExpression: ['argument'], // CAUTION: It's deferred to ES7.
BlockStatement: ['body'],
BinaryExpression: ['left', 'right'],
BreakStatement: ['label'],
CallExpression: ['callee', 'arguments'],
CatchClause: ['param', 'body'],
ChainExpression: ['expression'],
ClassBody: ['body'],
ClassDeclaration: ['id', 'superClass', 'body'],
ClassExpression: ['id', 'superClass', 'body'],
ComprehensionBlock: ['left', 'right'], // CAUTION: It's deferred to ES7.
ComprehensionExpression: ['blocks', 'filter', 'body'], // CAUTION: It's deferred to ES7.
ConditionalExpression: ['test', 'consequent', 'alternate'],
ContinueStatement: ['label'],
DebuggerStatement: [],
DirectiveStatement: [],
DoWhileStatement: ['body', 'test'],
EmptyStatement: [],
ExportAllDeclaration: ['source'],
ExportDefaultDeclaration: ['declaration'],
ExportNamedDeclaration: ['declaration', 'specifiers', 'source'],
ExportSpecifier: ['exported', 'local'],
ExpressionStatement: ['expression'],
ForStatement: ['init', 'test', 'update', 'body'],
ForInStatement: ['left', 'right', 'body'],
ForOfStatement: ['left', 'right', 'body'],
FunctionDeclaration: ['id', 'params', 'body'],
FunctionExpression: ['id', 'params', 'body'],
GeneratorExpression: ['blocks', 'filter', 'body'], // CAUTION: It's deferred to ES7.
Identifier: [],
IfStatement: ['test', 'consequent', 'alternate'],
ImportExpression: ['source'],
ImportDeclaration: ['specifiers', 'source'],
ImportDefaultSpecifier: ['local'],
ImportNamespaceSpecifier: ['local'],
ImportSpecifier: ['imported', 'local'],
Literal: [],
LabeledStatement: ['label', 'body'],
LogicalExpression: ['left', 'right'],
MemberExpression: ['object', 'property'],
MetaProperty: ['meta', 'property'],
MethodDefinition: ['key', 'value'],
ModuleSpecifier: [],
NewExpression: ['callee', 'arguments'],
ObjectExpression: ['properties'],
ObjectPattern: ['properties'],
PrivateIdentifier: [],
Program: ['body'],
Property: ['key', 'value'],
PropertyDefinition: ['key', 'value'],
RestElement: [ 'argument' ],
ReturnStatement: ['argument'],
SequenceExpression: ['expressions'],
SpreadElement: ['argument'],
Super: [],
SwitchStatement: ['discriminant', 'cases'],
SwitchCase: ['test', 'consequent'],
TaggedTemplateExpression: ['tag', 'quasi'],
TemplateElement: [],
TemplateLiteral: ['quasis', 'expressions'],
ThisExpression: [],
ThrowStatement: ['argument'],
TryStatement: ['block', 'handler', 'finalizer'],
UnaryExpression: ['argument'],
UpdateExpression: ['argument'],
VariableDeclaration: ['declarations'],
VariableDeclarator: ['id', 'init'],
WhileStatement: ['test', 'body'],
WithStatement: ['object', 'body'],
YieldExpression: ['argument']
};
// unique id
BREAK = {};
SKIP = {};
REMOVE = {};
VisitorOption = {
Break: BREAK,
Skip: SKIP,
Remove: REMOVE
};
function Reference(parent, key) {
this.parent = parent;
this.key = key;
}
Reference.prototype.replace = function replace(node) {
this.parent[this.key] = node;
};
Reference.prototype.remove = function remove() {
if (Array.isArray(this.parent)) {
this.parent.splice(this.key, 1);
return true;
} else {
this.replace(null);
return false;
}
};
function Element(node, path, wrap, ref) {
this.node = node;
this.path = path;
this.wrap = wrap;
this.ref = ref;
}
function Controller() { }
// API:
// return property path array from root to current node
Controller.prototype.path = function path() {
var i, iz, j, jz, result, element;
function addToPath(result, path) {
if (Array.isArray(path)) {
for (j = 0, jz = path.length; j < jz; ++j) {
result.push(path[j]);
}
} else {
result.push(path);
}
}
// root node
if (!this.__current.path) {
return null;
}
// first node is sentinel, second node is root element
result = [];
for (i = 2, iz = this.__leavelist.length; i < iz; ++i) {
element = this.__leavelist[i];
addToPath(result, element.path);
}
addToPath(result, this.__current.path);
return result;
};
// API:
// return type of current node
Controller.prototype.type = function () {
var node = this.current();
return node.type || this.__current.wrap;
};
// API:
// return array of parent elements
Controller.prototype.parents = function parents() {
var i, iz, result;
// first node is sentinel
result = [];
for (i = 1, iz = this.__leavelist.length; i < iz; ++i) {
result.push(this.__leavelist[i].node);
}
return result;
};
// API:
// return current node
Controller.prototype.current = function current() {
return this.__current.node;
};
Controller.prototype.__execute = function __execute(callback, element) {
var previous, result;
result = undefined;
previous = this.__current;
this.__current = element;
this.__state = null;
if (callback) {
result = callback.call(this, element.node, this.__leavelist[this.__leavelist.length - 1].node);
}
this.__current = previous;
return result;
};
// API:
// notify control skip / break
Controller.prototype.notify = function notify(flag) {
this.__state = flag;
};
// API:
// skip child nodes of current node
Controller.prototype.skip = function () {
this.notify(SKIP);
};
// API:
// break traversals
Controller.prototype['break'] = function () {
this.notify(BREAK);
};
// API:
// remove node
Controller.prototype.remove = function () {
this.notify(REMOVE);
};
Controller.prototype.__initialize = function(root, visitor) {
this.visitor = visitor;
this.root = root;
this.__worklist = [];
this.__leavelist = [];
this.__current = null;
this.__state = null;
this.__fallback = null;
if (visitor.fallback === 'iteration') {
this.__fallback = Object.keys;
} else if (typeof visitor.fallback === 'function') {
this.__fallback = visitor.fallback;
}
this.__keys = VisitorKeys;
if (visitor.keys) {
this.__keys = Object.assign(Object.create(this.__keys), visitor.keys);
}
};
function isNode(node) {
if (node == null) {
return false;
}
return typeof node === 'object' && typeof node.type === 'string';
}
function isProperty(nodeType, key) {
return (nodeType === Syntax.ObjectExpression || nodeType === Syntax.ObjectPattern) && 'properties' === key;
}
function candidateExistsInLeaveList(leavelist, candidate) {
for (var i = leavelist.length - 1; i >= 0; --i) {
if (leavelist[i].node === candidate) {
return true;
}
}
return false;
}
Controller.prototype.traverse = function traverse(root, visitor) {
var worklist,
leavelist,
element,
node,
nodeType,
ret,
key,
current,
current2,
candidates,
candidate,
sentinel;
this.__initialize(root, visitor);
sentinel = {};
// reference
worklist = this.__worklist;
leavelist = this.__leavelist;
// initialize
worklist.push(new Element(root, null, null, null));
leavelist.push(new Element(null, null, null, null));
while (worklist.length) {
element = worklist.pop();
if (element === sentinel) {
element = leavelist.pop();
ret = this.__execute(visitor.leave, element);
if (this.__state === BREAK || ret === BREAK) {
return;
}
continue;
}
if (element.node) {
ret = this.__execute(visitor.enter, element);
if (this.__state === BREAK || ret === BREAK) {
return;
}
worklist.push(sentinel);
leavelist.push(element);
if (this.__state === SKIP || ret === SKIP) {
continue;
}
node = element.node;
nodeType = node.type || element.wrap;
candidates = this.__keys[nodeType];
if (!candidates) {
if (this.__fallback) {
candidates = this.__fallback(node);
} else {
throw new Error('Unknown node type ' + nodeType + '.');
}
}
current = candidates.length;
while ((current -= 1) >= 0) {
key = candidates[current];
candidate = node[key];
if (!candidate) {
continue;
}
if (Array.isArray(candidate)) {
current2 = candidate.length;
while ((current2 -= 1) >= 0) {
if (!candidate[current2]) {
continue;
}
if (candidateExistsInLeaveList(leavelist, candidate[current2])) {
continue;
}
if (isProperty(nodeType, candidates[current])) {
element = new Element(candidate[current2], [key, current2], 'Property', null);
} else if (isNode(candidate[current2])) {
element = new Element(candidate[current2], [key, current2], null, null);
} else {
continue;
}
worklist.push(element);
}
} else if (isNode(candidate)) {
if (candidateExistsInLeaveList(leavelist, candidate)) {
continue;
}
worklist.push(new Element(candidate, key, null, null));
}
}
}
}
};
Controller.prototype.replace = function replace(root, visitor) {
var worklist,
leavelist,
node,
nodeType,
target,
element,
current,
current2,
candidates,
candidate,
sentinel,
outer,
key;
function removeElem(element) {
var i,
key,
nextElem,
parent;
if (element.ref.remove()) {
// When the reference is an element of an array.
key = element.ref.key;
parent = element.ref.parent;
// If removed from array, then decrease following items' keys.
i = worklist.length;
while (i--) {
nextElem = worklist[i];
if (nextElem.ref && nextElem.ref.parent === parent) {
if (nextElem.ref.key < key) {
break;
}
--nextElem.ref.key;
}
}
}
}
this.__initialize(root, visitor);
sentinel = {};
// reference
worklist = this.__worklist;
leavelist = this.__leavelist;
// initialize
outer = {
root: root
};
element = new Element(root, null, null, new Reference(outer, 'root'));
worklist.push(element);
leavelist.push(element);
while (worklist.length) {
element = worklist.pop();
if (element === sentinel) {
element = leavelist.pop();
target = this.__execute(visitor.leave, element);
// node may be replaced with null,
// so distinguish between undefined and null in this place
if (target !== undefined && target !== BREAK && target !== SKIP && target !== REMOVE) {
// replace
element.ref.replace(target);
}
if (this.__state === REMOVE || target === REMOVE) {
removeElem(element);
}
if (this.__state === BREAK || target === BREAK) {
return outer.root;
}
continue;
}
target = this.__execute(visitor.enter, element);
// node may be replaced with null,
// so distinguish between undefined and null in this place
if (target !== undefined && target !== BREAK && target !== SKIP && target !== REMOVE) {
// replace
element.ref.replace(target);
element.node = target;
}
if (this.__state === REMOVE || target === REMOVE) {
removeElem(element);
element.node = null;
}
if (this.__state === BREAK || target === BREAK) {
return outer.root;
}
// node may be null
node = element.node;
if (!node) {
continue;
}
worklist.push(sentinel);
leavelist.push(element);
if (this.__state === SKIP || target === SKIP) {
continue;
}
nodeType = node.type || element.wrap;
candidates = this.__keys[nodeType];
if (!candidates) {
if (this.__fallback) {
candidates = this.__fallback(node);
} else {
throw new Error('Unknown node type ' + nodeType + '.');
}
}
current = candidates.length;
while ((current -= 1) >= 0) {
key = candidates[current];
candidate = node[key];
if (!candidate) {
continue;
}
if (Array.isArray(candidate)) {
current2 = candidate.length;
while ((current2 -= 1) >= 0) {
if (!candidate[current2]) {
continue;
}
if (isProperty(nodeType, candidates[current])) {
element = new Element(candidate[current2], [key, current2], 'Property', new Reference(candidate, current2));
} else if (isNode(candidate[current2])) {
element = new Element(candidate[current2], [key, current2], null, new Reference(candidate, current2));
} else {
continue;
}
worklist.push(element);
}
} else if (isNode(candidate)) {
worklist.push(new Element(candidate, key, null, new Reference(node, key)));
}
}
}
return outer.root;
};
function traverse(root, visitor) {
var controller = new Controller();
return controller.traverse(root, visitor);
}
function replace(root, visitor) {
var controller = new Controller();
return controller.replace(root, visitor);
}
function extendCommentRange(comment, tokens) {
var target;
target = upperBound(tokens, function search(token) {
return token.range[0] > comment.range[0];
});
comment.extendedRange = [comment.range[0], comment.range[1]];
if (target !== tokens.length) {
comment.extendedRange[1] = tokens[target].range[0];
}
target -= 1;
if (target >= 0) {
comment.extendedRange[0] = tokens[target].range[1];
}
return comment;
}
function attachComments(tree, providedComments, tokens) {
// At first, we should calculate extended comment ranges.
var comments = [], comment, len, i, cursor;
if (!tree.range) {
throw new Error('attachComments needs range information');
}
// tokens array is empty, we attach comments to tree as 'leadingComments'
if (!tokens.length) {
if (providedComments.length) {
for (i = 0, len = providedComments.length; i < len; i += 1) {
comment = deepCopy(providedComments[i]);
comment.extendedRange = [0, tree.range[0]];
comments.push(comment);
}
tree.leadingComments = comments;
}
return tree;
}
for (i = 0, len = providedComments.length; i < len; i += 1) {
comments.push(extendCommentRange(deepCopy(providedComments[i]), tokens));
}
// This is based on John Freeman's implementation.
cursor = 0;
traverse(tree, {
enter: function (node) {
var comment;
while (cursor < comments.length) {
comment = comments[cursor];
if (comment.extendedRange[1] > node.range[0]) {
break;
}
if (comment.extendedRange[1] === node.range[0]) {
if (!node.leadingComments) {
node.leadingComments = [];
}
node.leadingComments.push(comment);
comments.splice(cursor, 1);
} else {
cursor += 1;
}
}
// already out of owned node
if (cursor === comments.length) {
return VisitorOption.Break;
}
if (comments[cursor].extendedRange[0] > node.range[1]) {
return VisitorOption.Skip;
}
}
});
cursor = 0;
traverse(tree, {
leave: function (node) {
var comment;
while (cursor < comments.length) {
comment = comments[cursor];
if (node.range[1] < comment.extendedRange[0]) {
break;
}
if (node.range[1] === comment.extendedRange[0]) {
if (!node.trailingComments) {
node.trailingComments = [];
}
node.trailingComments.push(comment);
comments.splice(cursor, 1);
} else {
cursor += 1;
}
}
// already out of owned node
if (cursor === comments.length) {
return VisitorOption.Break;
}
if (comments[cursor].extendedRange[0] > node.range[1]) {
return VisitorOption.Skip;
}
}
});
return tree;
}
exports.Syntax = Syntax;
exports.traverse = traverse;
exports.replace = replace;
exports.attachComments = attachComments;
exports.VisitorKeys = VisitorKeys;
exports.VisitorOption = VisitorOption;
exports.Controller = Controller;
exports.cloneEnvironment = function () { return clone({}); };
return exports;
}(exports));
/* vim: set sw=4 ts=4 et tw=80 : */

View file

@ -0,0 +1,70 @@
/*
Copyright (C) 2014 Yusuke Suzuki <utatane.tea@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 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 <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
'use strict';
var gulp = require('gulp'),
git = require('gulp-git'),
bump = require('gulp-bump'),
filter = require('gulp-filter'),
tagVersion = require('gulp-tag-version');
var TEST = [ 'test/*.js' ];
var POWERED = [ 'powered-test/*.js' ];
var SOURCE = [ 'src/**/*.js' ];
/**
* Bumping version number and tagging the repository with it.
* Please read http://semver.org/
*
* You can use the commands
*
* gulp patch # makes v0.1.0 -> v0.1.1
* gulp feature # makes v0.1.1 -> v0.2.0
* gulp release # makes v0.2.1 -> v1.0.0
*
* To bump the version numbers accordingly after you did a patch,
* introduced a feature or made a backwards-incompatible release.
*/
function inc(importance) {
// get all the files to bump version in
return gulp.src(['./package.json'])
// bump the version number in those files
.pipe(bump({type: importance}))
// save it back to filesystem
.pipe(gulp.dest('./'))
// commit the changed version number
.pipe(git.commit('Bumps package version'))
// read only one file to get the version number
.pipe(filter('package.json'))
// **tag it in the repository**
.pipe(tagVersion({
prefix: ''
}));
}
gulp.task('patch', [ ], function () { return inc('patch'); })
gulp.task('minor', [ ], function () { return inc('minor'); })
gulp.task('major', [ ], function () { return inc('major'); })

View file

@ -0,0 +1,40 @@
{
"name": "estraverse",
"description": "ECMAScript JS AST traversal functions",
"homepage": "https://github.com/estools/estraverse",
"main": "estraverse.js",
"version": "5.3.0",
"engines": {
"node": ">=4.0"
},
"maintainers": [
{
"name": "Yusuke Suzuki",
"email": "utatane.tea@gmail.com",
"web": "http://github.com/Constellation"
}
],
"repository": {
"type": "git",
"url": "http://github.com/estools/estraverse.git"
},
"devDependencies": {
"babel-preset-env": "^1.6.1",
"babel-register": "^6.3.13",
"chai": "^2.1.1",
"espree": "^1.11.0",
"gulp": "^3.8.10",
"gulp-bump": "^0.2.2",
"gulp-filter": "^2.0.0",
"gulp-git": "^1.0.1",
"gulp-tag-version": "^1.3.0",
"jshint": "^2.5.6",
"mocha": "^2.1.0"
},
"license": "BSD-2-Clause",
"scripts": {
"test": "npm run-script lint && npm run-script unit-test",
"lint": "jshint estraverse.js",
"unit-test": "mocha --compilers js:babel-register"
}
}

138
node_modules/eslint/node_modules/find-up/index.d.ts generated vendored Normal file
View file

@ -0,0 +1,138 @@
/* eslint-disable @typescript-eslint/unified-signatures */
import {Options as LocatePathOptions} from 'locate-path';
declare const stop: unique symbol;
declare namespace findUp {
interface Options extends LocatePathOptions {}
type StopSymbol = typeof stop;
type Match = string | StopSymbol | undefined;
}
declare const findUp: {
sync: {
/**
Synchronously check if a path exists.
@param path - Path to the file or directory.
@returns Whether the path exists.
@example
```
import findUp = require('find-up');
console.log(findUp.sync.exists('/Users/sindresorhus/unicorn.png'));
//=> true
```
*/
exists: (path: string) => boolean;
/**
Synchronously find a file or directory by walking up parent directories.
@param name - Name of the file or directory to find. Can be multiple.
@returns The first path found (by respecting the order of `name`s) or `undefined` if none could be found.
*/
(name: string | readonly string[], options?: findUp.Options): string | undefined;
/**
Synchronously find a file or directory by walking up parent directories.
@param matcher - Called for each directory in the search. Return a path or `findUp.stop` to stop the search.
@returns The first path found or `undefined` if none could be found.
@example
```
import path = require('path');
import findUp = require('find-up');
console.log(findUp.sync(directory => {
const hasUnicorns = findUp.sync.exists(path.join(directory, 'unicorn.png'));
return hasUnicorns && directory;
}, {type: 'directory'}));
//=> '/Users/sindresorhus'
```
*/
(matcher: (directory: string) => findUp.Match, options?: findUp.Options): string | undefined;
};
/**
Check if a path exists.
@param path - Path to a file or directory.
@returns Whether the path exists.
@example
```
import findUp = require('find-up');
(async () => {
console.log(await findUp.exists('/Users/sindresorhus/unicorn.png'));
//=> true
})();
```
*/
exists: (path: string) => Promise<boolean>;
/**
Return this in a `matcher` function to stop the search and force `findUp` to immediately return `undefined`.
*/
readonly stop: findUp.StopSymbol;
/**
Find a file or directory by walking up parent directories.
@param name - Name of the file or directory to find. Can be multiple.
@returns The first path found (by respecting the order of `name`s) or `undefined` if none could be found.
@example
```
// /
// └── Users
// └── sindresorhus
// ├── unicorn.png
// └── foo
// └── bar
// ├── baz
// └── example.js
// example.js
import findUp = require('find-up');
(async () => {
console.log(await findUp('unicorn.png'));
//=> '/Users/sindresorhus/unicorn.png'
console.log(await findUp(['rainbow.png', 'unicorn.png']));
//=> '/Users/sindresorhus/unicorn.png'
})();
```
*/
(name: string | readonly string[], options?: findUp.Options): Promise<string | undefined>;
/**
Find a file or directory by walking up parent directories.
@param matcher - Called for each directory in the search. Return a path or `findUp.stop` to stop the search.
@returns The first path found or `undefined` if none could be found.
@example
```
import path = require('path');
import findUp = require('find-up');
(async () => {
console.log(await findUp(async directory => {
const hasUnicorns = await findUp.exists(path.join(directory, 'unicorn.png'));
return hasUnicorns && directory;
}, {type: 'directory'}));
//=> '/Users/sindresorhus'
})();
```
*/
(matcher: (directory: string) => (findUp.Match | Promise<findUp.Match>), options?: findUp.Options): Promise<string | undefined>;
};
export = findUp;

89
node_modules/eslint/node_modules/find-up/index.js generated vendored Normal file
View file

@ -0,0 +1,89 @@
'use strict';
const path = require('path');
const locatePath = require('locate-path');
const pathExists = require('path-exists');
const stop = Symbol('findUp.stop');
module.exports = async (name, options = {}) => {
let directory = path.resolve(options.cwd || '');
const {root} = path.parse(directory);
const paths = [].concat(name);
const runMatcher = async locateOptions => {
if (typeof name !== 'function') {
return locatePath(paths, locateOptions);
}
const foundPath = await name(locateOptions.cwd);
if (typeof foundPath === 'string') {
return locatePath([foundPath], locateOptions);
}
return foundPath;
};
// eslint-disable-next-line no-constant-condition
while (true) {
// eslint-disable-next-line no-await-in-loop
const foundPath = await runMatcher({...options, cwd: directory});
if (foundPath === stop) {
return;
}
if (foundPath) {
return path.resolve(directory, foundPath);
}
if (directory === root) {
return;
}
directory = path.dirname(directory);
}
};
module.exports.sync = (name, options = {}) => {
let directory = path.resolve(options.cwd || '');
const {root} = path.parse(directory);
const paths = [].concat(name);
const runMatcher = locateOptions => {
if (typeof name !== 'function') {
return locatePath.sync(paths, locateOptions);
}
const foundPath = name(locateOptions.cwd);
if (typeof foundPath === 'string') {
return locatePath.sync([foundPath], locateOptions);
}
return foundPath;
};
// eslint-disable-next-line no-constant-condition
while (true) {
const foundPath = runMatcher({...options, cwd: directory});
if (foundPath === stop) {
return;
}
if (foundPath) {
return path.resolve(directory, foundPath);
}
if (directory === root) {
return;
}
directory = path.dirname(directory);
}
};
module.exports.exists = pathExists;
module.exports.sync.exists = pathExists.sync;
module.exports.stop = stop;

54
node_modules/eslint/node_modules/find-up/package.json generated vendored Normal file
View file

@ -0,0 +1,54 @@
{
"name": "find-up",
"version": "5.0.0",
"description": "Find a file or directory by walking up parent directories",
"license": "MIT",
"repository": "sindresorhus/find-up",
"funding": "https://github.com/sponsors/sindresorhus",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "https://sindresorhus.com"
},
"engines": {
"node": ">=10"
},
"scripts": {
"test": "xo && ava && tsd"
},
"files": [
"index.js",
"index.d.ts"
],
"keywords": [
"find",
"up",
"find-up",
"findup",
"look-up",
"look",
"file",
"search",
"match",
"package",
"resolve",
"parent",
"parents",
"folder",
"directory",
"walk",
"walking",
"path"
],
"dependencies": {
"locate-path": "^6.0.0",
"path-exists": "^4.0.0"
},
"devDependencies": {
"ava": "^2.1.0",
"is-path-inside": "^2.1.0",
"tempy": "^0.6.0",
"tsd": "^0.13.1",
"xo": "^0.33.0"
}
}

151
node_modules/eslint/node_modules/find-up/readme.md generated vendored Normal file
View file

@ -0,0 +1,151 @@
# find-up [![Build Status](https://travis-ci.com/sindresorhus/find-up.svg?branch=master)](https://travis-ci.com/github/sindresorhus/find-up)
> Find a file or directory by walking up parent directories
## Install
```
$ npm install find-up
```
## Usage
```
/
└── Users
└── sindresorhus
├── unicorn.png
└── foo
└── bar
├── baz
└── example.js
```
`example.js`
```js
const path = require('path');
const findUp = require('find-up');
(async () => {
console.log(await findUp('unicorn.png'));
//=> '/Users/sindresorhus/unicorn.png'
console.log(await findUp(['rainbow.png', 'unicorn.png']));
//=> '/Users/sindresorhus/unicorn.png'
console.log(await findUp(async directory => {
const hasUnicorns = await findUp.exists(path.join(directory, 'unicorn.png'));
return hasUnicorns && directory;
}, {type: 'directory'}));
//=> '/Users/sindresorhus'
})();
```
## API
### findUp(name, options?)
### findUp(matcher, options?)
Returns a `Promise` for either the path or `undefined` if it couldn't be found.
### findUp([...name], options?)
Returns a `Promise` for either the first path found (by respecting the order of the array) or `undefined` if none could be found.
### findUp.sync(name, options?)
### findUp.sync(matcher, options?)
Returns a path or `undefined` if it couldn't be found.
### findUp.sync([...name], options?)
Returns the first path found (by respecting the order of the array) or `undefined` if none could be found.
#### name
Type: `string`
Name of the file or directory to find.
#### matcher
Type: `Function`
A function that will be called with each directory until it returns a `string` with the path, which stops the search, or the root directory has been reached and nothing was found. Useful if you want to match files with certain patterns, set of permissions, or other advanced use-cases.
When using async mode, the `matcher` may optionally be an async or promise-returning function that returns the path.
#### options
Type: `object`
##### cwd
Type: `string`\
Default: `process.cwd()`
Directory to start from.
##### type
Type: `string`\
Default: `'file'`\
Values: `'file'` `'directory'`
The type of paths that can match.
##### allowSymlinks
Type: `boolean`\
Default: `true`
Allow symbolic links to match if they point to the chosen path type.
### findUp.exists(path)
Returns a `Promise<boolean>` of whether the path exists.
### findUp.sync.exists(path)
Returns a `boolean` of whether the path exists.
#### path
Type: `string`
Path to a file or directory.
### findUp.stop
A [`Symbol`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol) that can be returned by a `matcher` function to stop the search and cause `findUp` to immediately return `undefined`. Useful as a performance optimization in case the current working directory is deeply nested in the filesystem.
```js
const path = require('path');
const findUp = require('find-up');
(async () => {
await findUp(directory => {
return path.basename(directory) === 'work' ? findUp.stop : 'logo.png';
});
})();
```
## Related
- [find-up-cli](https://github.com/sindresorhus/find-up-cli) - CLI for this module
- [pkg-up](https://github.com/sindresorhus/pkg-up) - Find the closest package.json file
- [pkg-dir](https://github.com/sindresorhus/pkg-dir) - Find the root directory of an npm package
- [resolve-from](https://github.com/sindresorhus/resolve-from) - Resolve the path of a module like `require.resolve()` but from a given path
---
<div align="center">
<b>
<a href="https://tidelift.com/subscription/pkg/npm-find-up?utm_source=npm-find-up&utm_medium=referral&utm_campaign=readme">Get professional support for 'find-up' with a Tidelift subscription</a>
</b>
<br>
<sub>
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
</sub>
</div>

15
node_modules/eslint/node_modules/glob-parent/LICENSE generated vendored Normal file
View file

@ -0,0 +1,15 @@
The ISC License
Copyright (c) 2015, 2019 Elan Shanker, 2021 Blaine Bublitz <blaine.bublitz@gmail.com>, Eric Schoffstall <yo@contra.io> and other 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.

134
node_modules/eslint/node_modules/glob-parent/README.md generated vendored Normal file
View file

@ -0,0 +1,134 @@
<p align="center">
<a href="https://gulpjs.com">
<img height="257" width="114" src="https://raw.githubusercontent.com/gulpjs/artwork/master/gulp-2x.png">
</a>
</p>
# glob-parent
[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][ci-image]][ci-url] [![Coveralls Status][coveralls-image]][coveralls-url]
Extract the non-magic parent path from a glob string.
## Usage
```js
var globParent = require('glob-parent');
globParent('path/to/*.js'); // 'path/to'
globParent('/root/path/to/*.js'); // '/root/path/to'
globParent('/*.js'); // '/'
globParent('*.js'); // '.'
globParent('**/*.js'); // '.'
globParent('path/{to,from}'); // 'path'
globParent('path/!(to|from)'); // 'path'
globParent('path/?(to|from)'); // 'path'
globParent('path/+(to|from)'); // 'path'
globParent('path/*(to|from)'); // 'path'
globParent('path/@(to|from)'); // 'path'
globParent('path/**/*'); // 'path'
// if provided a non-glob path, returns the nearest dir
globParent('path/foo/bar.js'); // 'path/foo'
globParent('path/foo/'); // 'path/foo'
globParent('path/foo'); // 'path' (see issue #3 for details)
```
## API
### `globParent(maybeGlobString, [options])`
Takes a string and returns the part of the path before the glob begins. Be aware of Escaping rules and Limitations below.
#### options
```js
{
// Disables the automatic conversion of slashes for Windows
flipBackslashes: true;
}
```
## Escaping
The following characters have special significance in glob patterns and must be escaped if you want them to be treated as regular path characters:
- `?` (question mark) unless used as a path segment alone
- `*` (asterisk)
- `|` (pipe)
- `(` (opening parenthesis)
- `)` (closing parenthesis)
- `{` (opening curly brace)
- `}` (closing curly brace)
- `[` (opening bracket)
- `]` (closing bracket)
**Example**
```js
globParent('foo/[bar]/'); // 'foo'
globParent('foo/\\[bar]/'); // 'foo/[bar]'
```
## Limitations
### Braces & Brackets
This library attempts a quick and imperfect method of determining which path
parts have glob magic without fully parsing/lexing the pattern. There are some
advanced use cases that can trip it up, such as nested braces where the outer
pair is escaped and the inner one contains a path separator. If you find
yourself in the unlikely circumstance of being affected by this or need to
ensure higher-fidelity glob handling in your library, it is recommended that you
pre-process your input with [expand-braces] and/or [expand-brackets].
### Windows
Backslashes are not valid path separators for globs. If a path with backslashes
is provided anyway, for simple cases, glob-parent will replace the path
separator for you and return the non-glob parent path (now with
forward-slashes, which are still valid as Windows path separators).
This cannot be used in conjunction with escape characters.
```js
// BAD
globParent('C:\\Program Files \\(x86\\)\\*.ext'); // 'C:/Program Files /(x86/)'
// GOOD
globParent('C:/Program Files\\(x86\\)/*.ext'); // 'C:/Program Files (x86)'
```
If you are using escape characters for a pattern without path parts (i.e.
relative to `cwd`), prefix with `./` to avoid confusing glob-parent.
```js
// BAD
globParent('foo \\[bar]'); // 'foo '
globParent('foo \\[bar]*'); // 'foo '
// GOOD
globParent('./foo \\[bar]'); // 'foo [bar]'
globParent('./foo \\[bar]*'); // '.'
```
## License
ISC
<!-- prettier-ignore-start -->
[downloads-image]: https://img.shields.io/npm/dm/glob-parent.svg?style=flat-square
[npm-url]: https://www.npmjs.com/package/glob-parent
[npm-image]: https://img.shields.io/npm/v/glob-parent.svg?style=flat-square
[ci-url]: https://github.com/gulpjs/glob-parent/actions?query=workflow:dev
[ci-image]: https://img.shields.io/github/workflow/status/gulpjs/glob-parent/dev?style=flat-square
[coveralls-url]: https://coveralls.io/r/gulpjs/glob-parent
[coveralls-image]: https://img.shields.io/coveralls/gulpjs/glob-parent/master.svg?style=flat-square
<!-- prettier-ignore-end -->
<!-- prettier-ignore-start -->
[expand-braces]: https://github.com/jonschlinkert/expand-braces
[expand-brackets]: https://github.com/jonschlinkert/expand-brackets
<!-- prettier-ignore-end -->

75
node_modules/eslint/node_modules/glob-parent/index.js generated vendored Normal file
View file

@ -0,0 +1,75 @@
'use strict';
var isGlob = require('is-glob');
var pathPosixDirname = require('path').posix.dirname;
var isWin32 = require('os').platform() === 'win32';
var slash = '/';
var backslash = /\\/g;
var escaped = /\\([!*?|[\](){}])/g;
/**
* @param {string} str
* @param {Object} opts
* @param {boolean} [opts.flipBackslashes=true]
*/
module.exports = function globParent(str, opts) {
var options = Object.assign({ flipBackslashes: true }, opts);
// flip windows path separators
if (options.flipBackslashes && isWin32 && str.indexOf(slash) < 0) {
str = str.replace(backslash, slash);
}
// special case for strings ending in enclosure containing path separator
if (isEnclosure(str)) {
str += slash;
}
// preserves full path in case of trailing path separator
str += 'a';
// remove path parts that are globby
do {
str = pathPosixDirname(str);
} while (isGlobby(str));
// remove escape chars and return result
return str.replace(escaped, '$1');
};
function isEnclosure(str) {
var lastChar = str.slice(-1);
var enclosureStart;
switch (lastChar) {
case '}':
enclosureStart = '{';
break;
case ']':
enclosureStart = '[';
break;
default:
return false;
}
var foundIndex = str.indexOf(enclosureStart);
if (foundIndex < 0) {
return false;
}
return str.slice(foundIndex + 1, -1).includes(slash);
}
function isGlobby(str) {
if (/\([^()]+$/.test(str)) {
return true;
}
if (str[0] === '{' || str[0] === '[') {
return true;
}
if (/[^\\][{[]/.test(str)) {
return true;
}
return isGlob(str);
}

View file

@ -0,0 +1,54 @@
{
"name": "glob-parent",
"version": "6.0.2",
"description": "Extract the non-magic parent path from a glob string.",
"author": "Gulp Team <team@gulpjs.com> (https://gulpjs.com/)",
"contributors": [
"Elan Shanker (https://github.com/es128)",
"Blaine Bublitz <blaine.bublitz@gmail.com>"
],
"repository": "gulpjs/glob-parent",
"license": "ISC",
"engines": {
"node": ">=10.13.0"
},
"main": "index.js",
"files": [
"LICENSE",
"index.js"
],
"scripts": {
"lint": "eslint .",
"pretest": "npm run lint",
"test": "nyc mocha --async-only"
},
"dependencies": {
"is-glob": "^4.0.3"
},
"devDependencies": {
"eslint": "^7.0.0",
"eslint-config-gulp": "^5.0.0",
"expect": "^26.0.1",
"mocha": "^7.1.2",
"nyc": "^15.0.1"
},
"nyc": {
"reporter": [
"lcov",
"text-summary"
]
},
"prettier": {
"singleQuote": true
},
"keywords": [
"glob",
"parent",
"strip",
"path",
"dirname",
"directory",
"base",
"wildcard"
]
}

View file

@ -1,19 +0,0 @@
# `node-ignore` 4 ChangeLog
# 4.x
## 2018-06-22, Version 4.0.0
- **SEMVER-MAJOR**: Drop support for node < 6 by default.
- **FEATURE**: supports the missing character ranges and sets, such as `*.[a-z]` and `*.[jJ][pP][gG]`
- **FEATURE**: new option: `ignorecase` to make `ignore` case sensitive.
- **FEATURE**: supports question mark which matches a single character.
- **PATCH**: fixes typescript declaration.
## ~ 2018-08-09, Version 4.0.1 - 4.0.5
- **PATCH**: updates README.md about frequent asked quesions from github issues.
## 2018-08-12, Version 4.0.6
- **PATCH**: `Object.prototype` methods will not ruin the result any more.

View file

@ -1,21 +0,0 @@
Copyright (c) 2013 Kael Zhang <i@kael.me>, contributors
http://kael.me/
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.

View file

@ -1,307 +0,0 @@
<table><thead>
<tr>
<th>Linux</th>
<th>OS X</th>
<th>Windows</th>
<th>Coverage</th>
<th>Downloads</th>
</tr>
</thead><tbody><tr>
<td colspan="2" align="center">
<a href="https://travis-ci.org/kaelzhang/node-ignore">
<img
src="https://travis-ci.org/kaelzhang/node-ignore.svg?branch=master"
alt="Build Status" /></a>
</td>
<td align="center">
<a href="https://ci.appveyor.com/project/kaelzhang/node-ignore">
<img
src="https://ci.appveyor.com/api/projects/status/github/kaelzhang/node-ignore?branch=master&svg=true"
alt="Windows Build Status" /></a>
</td>
<td align="center">
<a href="https://codecov.io/gh/kaelzhang/node-ignore">
<img
src="https://codecov.io/gh/kaelzhang/node-ignore/branch/master/graph/badge.svg"
alt="Coverage Status" /></a>
</td>
<td align="center">
<a href="https://www.npmjs.org/package/ignore">
<img
src="http://img.shields.io/npm/dm/ignore.svg"
alt="npm module downloads per month" /></a>
</td>
</tr></tbody></table>
# ignore
`ignore` is a manager, filter and parser which implemented in pure JavaScript according to the .gitignore [spec](http://git-scm.com/docs/gitignore).
Pay attention that [`minimatch`](https://www.npmjs.org/package/minimatch) does not work in the gitignore way. To filter filenames according to .gitignore file, I recommend this module.
##### Tested on
- Linux + Node: `0.8` - `7.x`
- Windows + Node: `0.10` - `7.x`, node < `0.10` is not tested due to the lack of support of appveyor.
Actually, `ignore` does not rely on any versions of node specially.
Since `4.0.0`, ignore will no longer support `node < 6` by default, to use in node < 6, `require('ignore/legacy')`. For details, see [CHANGELOG](https://github.com/kaelzhang/node-ignore/blob/master/CHANGELOG.md).
## Table Of Main Contents
- [Usage](#usage)
- [`Pathname` Conventions](#pathname-conventions)
- [Guide for 2.x -> 3.x](#upgrade-2x---3x)
- [Guide for 3.x -> 4.x](#upgrade-3x---4x)
- See Also:
- [`glob-gitignore`](https://www.npmjs.com/package/glob-gitignore) matches files using patterns and filters them according to gitignore rules.
## Usage
```js
import ignore from 'ignore'
const ig = ignore().add(['.abc/*', '!.abc/d/'])
```
### Filter the given paths
```js
const paths = [
'.abc/a.js', // filtered out
'.abc/d/e.js' // included
]
ig.filter(paths) // ['.abc/d/e.js']
ig.ignores('.abc/a.js') // true
```
### As the filter function
```js
paths.filter(ig.createFilter()); // ['.abc/d/e.js']
```
### Win32 paths will be handled
```js
ig.filter(['.abc\\a.js', '.abc\\d\\e.js'])
// if the code above runs on windows, the result will be
// ['.abc\\d\\e.js']
```
## Why another ignore?
- `ignore` is a standalone module, and is much simpler so that it could easy work with other programs, unlike [isaacs](https://npmjs.org/~isaacs)'s [fstream-ignore](https://npmjs.org/package/fstream-ignore) which must work with the modules of the fstream family.
- `ignore` only contains utility methods to filter paths according to the specified ignore rules, so
- `ignore` never try to find out ignore rules by traversing directories or fetching from git configurations.
- `ignore` don't cares about sub-modules of git projects.
- Exactly according to [gitignore man page](http://git-scm.com/docs/gitignore), fixes some known matching issues of fstream-ignore, such as:
- '`/*.js`' should only match '`a.js`', but not '`abc/a.js`'.
- '`**/foo`' should match '`foo`' anywhere.
- Prevent re-including a file if a parent directory of that file is excluded.
- Handle trailing whitespaces:
- `'a '`(one space) should not match `'a '`(two spaces).
- `'a \ '` matches `'a '`
- All test cases are verified with the result of `git check-ignore`.
# Methods
## .add(pattern: string | Ignore): this
## .add(patterns: Array<string | Ignore>): this
- **pattern** `String | Ignore` An ignore pattern string, or the `Ignore` instance
- **patterns** `Array<String | Ignore>` Array of ignore patterns.
Adds a rule or several rules to the current manager.
Returns `this`
Notice that a line starting with `'#'`(hash) is treated as a comment. Put a backslash (`'\'`) in front of the first hash for patterns that begin with a hash, if you want to ignore a file with a hash at the beginning of the filename.
```js
ignore().add('#abc').ignores('#abc') // false
ignore().add('\#abc').ignores('#abc') // true
```
`pattern` could either be a line of ignore pattern or a string of multiple ignore patterns, which means we could just `ignore().add()` the content of a ignore file:
```js
ignore()
.add(fs.readFileSync(filenameOfGitignore).toString())
.filter(filenames)
```
`pattern` could also be an `ignore` instance, so that we could easily inherit the rules of another `Ignore` instance.
## <strike>.addIgnoreFile(path)</strike>
REMOVED in `3.x` for now.
To upgrade `ignore@2.x` up to `3.x`, use
```js
import fs from 'fs'
if (fs.existsSync(filename)) {
ignore().add(fs.readFileSync(filename).toString())
}
```
instead.
## .filter(paths: Array<Pathname>): Array<Pathname>
```ts
type Pathname = string
```
Filters the given array of pathnames, and returns the filtered array.
- **paths** `Array.<Pathname>` The array of `pathname`s to be filtered.
### `Pathname` Conventions:
#### 1. `Pathname` should be a `path.relative()`d pathname
`Pathname` should be a string that have been `path.join()`ed, or the return value of `path.relative()` to the current directory.
```js
// WRONG
ig.ignores('./abc')
// WRONG, for it will never happen.
// If the gitignore rule locates at the root directory,
// `'/abc'` should be changed to `'abc'`.
// ```
// path.relative('/', '/abc') -> 'abc'
// ```
ig.ignores('/abc')
// Right
ig.ignores('abc')
// Right
ig.ignores(path.join('./abc')) // path.join('./abc') -> 'abc'
```
In other words, each `Pathname` here should be a relative path to the directory of the gitignore rules.
Suppose the dir structure is:
```
/path/to/your/repo
|-- a
| |-- a.js
|
|-- .b
|
|-- .c
|-- .DS_store
```
Then the `paths` might be like this:
```js
[
'a/a.js'
'.b',
'.c/.DS_store'
]
```
Usually, you could use [`glob`](http://npmjs.org/package/glob) with `option.mark = true` to fetch the structure of the current directory:
```js
import glob from 'glob'
glob('**', {
// Adds a / character to directory matches.
mark: true
}, (err, files) => {
if (err) {
return console.error(err)
}
let filtered = ignore().add(patterns).filter(files)
console.log(filtered)
})
```
#### 2. filenames and dirnames
`node-ignore` does NO `fs.stat` during path matching, so for the example below:
```js
ig.add('config/')
// `ig` does NOT know if 'config' is a normal file, directory or something
ig.ignores('config') // And it returns `false`
ig.ignores('config/') // returns `true`
```
Specially for people who develop some library based on `node-ignore`, it is important to understand that.
## .ignores(pathname: Pathname): boolean
> new in 3.2.0
Returns `Boolean` whether `pathname` should be ignored.
```js
ig.ignores('.abc/a.js') // true
```
## .createFilter()
Creates a filter function which could filter an array of paths with `Array.prototype.filter`.
Returns `function(path)` the filter function.
## `options.ignorecase` since 4.0.0
Similar as the `core.ignorecase` option of [git-config](https://git-scm.com/docs/git-config), `node-ignore` will be case insensitive if `options.ignorecase` is set to `true` (default value), otherwise case sensitive.
```js
const ig = ignore({
ignorecase: false
})
ig.add('*.png')
ig.ignores('*.PNG') // false
```
****
# Upgrade Guide
## Upgrade 2.x -> 3.x
- All `options` of 2.x are unnecessary and removed, so just remove them.
- `ignore()` instance is no longer an [`EventEmitter`](nodejs.org/api/events.html), and all events are unnecessary and removed.
- `.addIgnoreFile()` is removed, see the [.addIgnoreFile](#addignorefilepath) section for details.
## Upgrade 3.x -> 4.x
Since `4.0.0`, `ignore` will no longer support node < 6, to use `ignore` in node < 6:
```js
var ignore = require('ignore/legacy')
```
****
# Collaborators
- [@whitecolor](https://github.com/whitecolor) *Alex*
- [@SamyPesse](https://github.com/SamyPesse) *Samy Pessé*
- [@azproduction](https://github.com/azproduction) *Mikhail Davydov*
- [@TrySound](https://github.com/TrySound) *Bogdan Chadkin*
- [@JanMattner](https://github.com/JanMattner) *Jan Mattner*
- [@ntwb](https://github.com/ntwb) *Stephen Edgar*
- [@kasperisager](https://github.com/kasperisager) *Kasper Isager*
- [@sandersn](https://github.com/sandersn) *Nathan Shively-Sanders*

View file

@ -1,45 +0,0 @@
interface Ignore {
/**
* Adds a rule rules to the current manager.
* @param {string | Ignore} pattern
* @returns IgnoreBase
*/
add(pattern: string | Ignore): Ignore
/**
* Adds several rules to the current manager.
* @param {string[]} patterns
* @returns IgnoreBase
*/
add(patterns: (string | Ignore)[]): Ignore
/**
* Filters the given array of pathnames, and returns the filtered array.
* NOTICE that each path here should be a relative path to the root of your repository.
* @param paths the array of paths to be filtered.
* @returns The filtered array of paths
*/
filter(paths: string[]): string[]
/**
* Creates a filter function which could filter
* an array of paths with Array.prototype.filter.
*/
createFilter(): (path: string) => boolean
/**
* Returns Boolean whether pathname should be ignored.
* @param {string} pathname a path to check
* @returns boolean
*/
ignores(pathname: string): boolean
}
interface Options {
ignorecase?: boolean
}
/**
* Creates new ignore manager.
*/
declare function ignore(options?: Options): Ignore
export default ignore

View file

@ -1,463 +0,0 @@
// A simple implementation of make-array
function make_array (subject) {
return Array.isArray(subject)
? subject
: [subject]
}
const REGEX_BLANK_LINE = /^\s+$/
const REGEX_LEADING_EXCAPED_EXCLAMATION = /^\\!/
const REGEX_LEADING_EXCAPED_HASH = /^\\#/
const SLASH = '/'
const KEY_IGNORE = typeof Symbol !== 'undefined'
? Symbol.for('node-ignore')
/* istanbul ignore next */
: 'node-ignore'
const define = (object, key, value) =>
Object.defineProperty(object, key, {value})
const REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g
// Sanitize the range of a regular expression
// The cases are complicated, see test cases for details
const sanitizeRange = range => range.replace(
REGEX_REGEXP_RANGE,
(match, from, to) => from.charCodeAt(0) <= to.charCodeAt(0)
? match
// Invalid range (out of order) which is ok for gitignore rules but
// fatal for JavaScript regular expression, so eliminate it.
: ''
)
// > If the pattern ends with a slash,
// > it is removed for the purpose of the following description,
// > but it would only find a match with a directory.
// > In other words, foo/ will match a directory foo and paths underneath it,
// > but will not match a regular file or a symbolic link foo
// > (this is consistent with the way how pathspec works in general in Git).
// '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`'
// -> ignore-rules will not deal with it, because it costs extra `fs.stat` call
// you could use option `mark: true` with `glob`
// '`foo/`' should not continue with the '`..`'
const DEFAULT_REPLACER_PREFIX = [
// > Trailing spaces are ignored unless they are quoted with backslash ("\")
[
// (a\ ) -> (a )
// (a ) -> (a)
// (a \ ) -> (a )
/\\?\s+$/,
match => match.indexOf('\\') === 0
? ' '
: ''
],
// replace (\ ) with ' '
[
/\\\s/g,
() => ' '
],
// Escape metacharacters
// which is written down by users but means special for regular expressions.
// > There are 12 characters with special meanings:
// > - the backslash \,
// > - the caret ^,
// > - the dollar sign $,
// > - the period or dot .,
// > - the vertical bar or pipe symbol |,
// > - the question mark ?,
// > - the asterisk or star *,
// > - the plus sign +,
// > - the opening parenthesis (,
// > - the closing parenthesis ),
// > - and the opening square bracket [,
// > - the opening curly brace {,
// > These special characters are often called "metacharacters".
[
/[\\^$.|*+(){]/g,
match => `\\${match}`
],
[
// > [abc] matches any character inside the brackets
// > (in this case a, b, or c);
/\[([^\]/]*)($|\])/g,
(match, p1, p2) => p2 === ']'
? `[${sanitizeRange(p1)}]`
: `\\${match}`
],
[
// > a question mark (?) matches a single character
/(?!\\)\?/g,
() => '[^/]'
],
// leading slash
[
// > A leading slash matches the beginning of the pathname.
// > For example, "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c".
// A leading slash matches the beginning of the pathname
/^\//,
() => '^'
],
// replace special metacharacter slash after the leading slash
[
/\//g,
() => '\\/'
],
[
// > A leading "**" followed by a slash means match in all directories.
// > For example, "**/foo" matches file or directory "foo" anywhere,
// > the same as pattern "foo".
// > "**/foo/bar" matches file or directory "bar" anywhere that is directly
// > under directory "foo".
// Notice that the '*'s have been replaced as '\\*'
/^\^*\\\*\\\*\\\//,
// '**/foo' <-> 'foo'
() => '^(?:.*\\/)?'
]
]
const DEFAULT_REPLACER_SUFFIX = [
// starting
[
// there will be no leading '/'
// (which has been replaced by section "leading slash")
// If starts with '**', adding a '^' to the regular expression also works
/^(?=[^^])/,
function startingReplacer () {
return !/\/(?!$)/.test(this)
// > If the pattern does not contain a slash /,
// > Git treats it as a shell glob pattern
// Actually, if there is only a trailing slash,
// git also treats it as a shell glob pattern
? '(?:^|\\/)'
// > Otherwise, Git treats the pattern as a shell glob suitable for
// > consumption by fnmatch(3)
: '^'
}
],
// two globstars
[
// Use lookahead assertions so that we could match more than one `'/**'`
/\\\/\\\*\\\*(?=\\\/|$)/g,
// Zero, one or several directories
// should not use '*', or it will be replaced by the next replacer
// Check if it is not the last `'/**'`
(match, index, str) => index + 6 < str.length
// case: /**/
// > A slash followed by two consecutive asterisks then a slash matches
// > zero or more directories.
// > For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b" and so on.
// '/**/'
? '(?:\\/[^\\/]+)*'
// case: /**
// > A trailing `"/**"` matches everything inside.
// #21: everything inside but it should not include the current folder
: '\\/.+'
],
// intermediate wildcards
[
// Never replace escaped '*'
// ignore rule '\*' will match the path '*'
// 'abc.*/' -> go
// 'abc.*' -> skip this rule
/(^|[^\\]+)\\\*(?=.+)/g,
// '*.js' matches '.js'
// '*.js' doesn't match 'abc'
(match, p1) => `${p1}[^\\/]*`
],
// trailing wildcard
[
/(\^|\\\/)?\\\*$/,
(match, p1) => {
const prefix = p1
// '\^':
// '/*' does not match ''
// '/*' does not match everything
// '\\\/':
// 'abc/*' does not match 'abc/'
? `${p1}[^/]+`
// 'a*' matches 'a'
// 'a*' matches 'aa'
: '[^/]*'
return `${prefix}(?=$|\\/$)`
}
],
[
// unescape
/\\\\\\/g,
() => '\\'
]
]
const POSITIVE_REPLACERS = [
...DEFAULT_REPLACER_PREFIX,
// 'f'
// matches
// - /f(end)
// - /f/
// - (start)f(end)
// - (start)f/
// doesn't match
// - oof
// - foo
// pseudo:
// -> (^|/)f(/|$)
// ending
[
// 'js' will not match 'js.'
// 'ab' will not match 'abc'
/(?:[^*/])$/,
// 'js*' will not match 'a.js'
// 'js/' will not match 'a.js'
// 'js' will match 'a.js' and 'a.js/'
match => `${match}(?=$|\\/)`
],
...DEFAULT_REPLACER_SUFFIX
]
const NEGATIVE_REPLACERS = [
...DEFAULT_REPLACER_PREFIX,
// #24, #38
// The MISSING rule of [gitignore docs](https://git-scm.com/docs/gitignore)
// A negative pattern without a trailing wildcard should not
// re-include the things inside that directory.
// eg:
// ['node_modules/*', '!node_modules']
// should ignore `node_modules/a.js`
[
/(?:[^*])$/,
match => `${match}(?=$|\\/$)`
],
...DEFAULT_REPLACER_SUFFIX
]
// A simple cache, because an ignore rule only has only one certain meaning
const cache = Object.create(null)
// @param {pattern}
const make_regex = (pattern, negative, ignorecase) => {
const r = cache[pattern]
if (r) {
return r
}
const replacers = negative
? NEGATIVE_REPLACERS
: POSITIVE_REPLACERS
const source = replacers.reduce(
(prev, current) => prev.replace(current[0], current[1].bind(pattern)),
pattern
)
return cache[pattern] = ignorecase
? new RegExp(source, 'i')
: new RegExp(source)
}
// > A blank line matches no files, so it can serve as a separator for readability.
const checkPattern = pattern => pattern
&& typeof pattern === 'string'
&& !REGEX_BLANK_LINE.test(pattern)
// > A line starting with # serves as a comment.
&& pattern.indexOf('#') !== 0
const createRule = (pattern, ignorecase) => {
const origin = pattern
let negative = false
// > An optional prefix "!" which negates the pattern;
if (pattern.indexOf('!') === 0) {
negative = true
pattern = pattern.substr(1)
}
pattern = pattern
// > Put a backslash ("\") in front of the first "!" for patterns that
// > begin with a literal "!", for example, `"\!important!.txt"`.
.replace(REGEX_LEADING_EXCAPED_EXCLAMATION, '!')
// > Put a backslash ("\") in front of the first hash for patterns that
// > begin with a hash.
.replace(REGEX_LEADING_EXCAPED_HASH, '#')
const regex = make_regex(pattern, negative, ignorecase)
return {
origin,
pattern,
negative,
regex
}
}
class IgnoreBase {
constructor ({
ignorecase = true
} = {}) {
this._rules = []
this._ignorecase = ignorecase
define(this, KEY_IGNORE, true)
this._initCache()
}
_initCache () {
this._cache = Object.create(null)
}
// @param {Array.<string>|string|Ignore} pattern
add (pattern) {
this._added = false
if (typeof pattern === 'string') {
pattern = pattern.split(/\r?\n/g)
}
make_array(pattern).forEach(this._addPattern, this)
// Some rules have just added to the ignore,
// making the behavior changed.
if (this._added) {
this._initCache()
}
return this
}
// legacy
addPattern (pattern) {
return this.add(pattern)
}
_addPattern (pattern) {
// #32
if (pattern && pattern[KEY_IGNORE]) {
this._rules = this._rules.concat(pattern._rules)
this._added = true
return
}
if (checkPattern(pattern)) {
const rule = createRule(pattern, this._ignorecase)
this._added = true
this._rules.push(rule)
}
}
filter (paths) {
return make_array(paths).filter(path => this._filter(path))
}
createFilter () {
return path => this._filter(path)
}
ignores (path) {
return !this._filter(path)
}
// @returns `Boolean` true if the `path` is NOT ignored
_filter (path, slices) {
if (!path) {
return false
}
if (path in this._cache) {
return this._cache[path]
}
if (!slices) {
// path/to/a.js
// ['path', 'to', 'a.js']
slices = path.split(SLASH)
}
slices.pop()
return this._cache[path] = slices.length
// > It is not possible to re-include a file if a parent directory of
// > that file is excluded.
// If the path contains a parent directory, check the parent first
? this._filter(slices.join(SLASH) + SLASH, slices)
&& this._test(path)
// Or only test the path
: this._test(path)
}
// @returns {Boolean} true if a file is NOT ignored
_test (path) {
// Explicitly define variable type by setting matched to `0`
let matched = 0
this._rules.forEach(rule => {
// if matched = true, then we only test negative rules
// if matched = false, then we test non-negative rules
if (!(matched ^ rule.negative)) {
matched = rule.negative ^ rule.regex.test(path)
}
})
return !matched
}
}
// Windows
// --------------------------------------------------------------
/* istanbul ignore if */
if (
// Detect `process` so that it can run in browsers.
typeof process !== 'undefined'
&& (
process.env && process.env.IGNORE_TEST_WIN32
|| process.platform === 'win32'
)
) {
const filter = IgnoreBase.prototype._filter
/* eslint no-control-regex: "off" */
const make_posix = str => /^\\\\\?\\/.test(str)
|| /[^\x00-\x80]+/.test(str)
? str
: str.replace(/\\/g, '/')
IgnoreBase.prototype._filter = function filterWin32 (path, slices) {
path = make_posix(path)
return filter.call(this, path, slices)
}
}
module.exports = options => new IgnoreBase(options)

View file

@ -1,466 +0,0 @@
'use strict';
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
// A simple implementation of make-array
function make_array(subject) {
return Array.isArray(subject) ? subject : [subject];
}
var REGEX_BLANK_LINE = /^\s+$/;
var REGEX_LEADING_EXCAPED_EXCLAMATION = /^\\!/;
var REGEX_LEADING_EXCAPED_HASH = /^\\#/;
var SLASH = '/';
var KEY_IGNORE = typeof Symbol !== 'undefined' ? Symbol.for('node-ignore')
/* istanbul ignore next */
: 'node-ignore';
var define = function define(object, key, value) {
return Object.defineProperty(object, key, { value });
};
var REGEX_REGEXP_RANGE = /([0-z])-([0-z])/g;
// Sanitize the range of a regular expression
// The cases are complicated, see test cases for details
var sanitizeRange = function sanitizeRange(range) {
return range.replace(REGEX_REGEXP_RANGE, function (match, from, to) {
return from.charCodeAt(0) <= to.charCodeAt(0) ? match
// Invalid range (out of order) which is ok for gitignore rules but
// fatal for JavaScript regular expression, so eliminate it.
: '';
});
};
// > If the pattern ends with a slash,
// > it is removed for the purpose of the following description,
// > but it would only find a match with a directory.
// > In other words, foo/ will match a directory foo and paths underneath it,
// > but will not match a regular file or a symbolic link foo
// > (this is consistent with the way how pathspec works in general in Git).
// '`foo/`' will not match regular file '`foo`' or symbolic link '`foo`'
// -> ignore-rules will not deal with it, because it costs extra `fs.stat` call
// you could use option `mark: true` with `glob`
// '`foo/`' should not continue with the '`..`'
var DEFAULT_REPLACER_PREFIX = [
// > Trailing spaces are ignored unless they are quoted with backslash ("\")
[
// (a\ ) -> (a )
// (a ) -> (a)
// (a \ ) -> (a )
/\\?\s+$/, function (match) {
return match.indexOf('\\') === 0 ? ' ' : '';
}],
// replace (\ ) with ' '
[/\\\s/g, function () {
return ' ';
}],
// Escape metacharacters
// which is written down by users but means special for regular expressions.
// > There are 12 characters with special meanings:
// > - the backslash \,
// > - the caret ^,
// > - the dollar sign $,
// > - the period or dot .,
// > - the vertical bar or pipe symbol |,
// > - the question mark ?,
// > - the asterisk or star *,
// > - the plus sign +,
// > - the opening parenthesis (,
// > - the closing parenthesis ),
// > - and the opening square bracket [,
// > - the opening curly brace {,
// > These special characters are often called "metacharacters".
[/[\\^$.|*+(){]/g, function (match) {
return `\\${match}`;
}], [
// > [abc] matches any character inside the brackets
// > (in this case a, b, or c);
/\[([^\]/]*)($|\])/g, function (match, p1, p2) {
return p2 === ']' ? `[${sanitizeRange(p1)}]` : `\\${match}`;
}], [
// > a question mark (?) matches a single character
/(?!\\)\?/g, function () {
return '[^/]';
}],
// leading slash
[
// > A leading slash matches the beginning of the pathname.
// > For example, "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c".
// A leading slash matches the beginning of the pathname
/^\//, function () {
return '^';
}],
// replace special metacharacter slash after the leading slash
[/\//g, function () {
return '\\/';
}], [
// > A leading "**" followed by a slash means match in all directories.
// > For example, "**/foo" matches file or directory "foo" anywhere,
// > the same as pattern "foo".
// > "**/foo/bar" matches file or directory "bar" anywhere that is directly
// > under directory "foo".
// Notice that the '*'s have been replaced as '\\*'
/^\^*\\\*\\\*\\\//,
// '**/foo' <-> 'foo'
function () {
return '^(?:.*\\/)?';
}]];
var DEFAULT_REPLACER_SUFFIX = [
// starting
[
// there will be no leading '/'
// (which has been replaced by section "leading slash")
// If starts with '**', adding a '^' to the regular expression also works
/^(?=[^^])/, function startingReplacer() {
return !/\/(?!$)/.test(this)
// > If the pattern does not contain a slash /,
// > Git treats it as a shell glob pattern
// Actually, if there is only a trailing slash,
// git also treats it as a shell glob pattern
? '(?:^|\\/)'
// > Otherwise, Git treats the pattern as a shell glob suitable for
// > consumption by fnmatch(3)
: '^';
}],
// two globstars
[
// Use lookahead assertions so that we could match more than one `'/**'`
/\\\/\\\*\\\*(?=\\\/|$)/g,
// Zero, one or several directories
// should not use '*', or it will be replaced by the next replacer
// Check if it is not the last `'/**'`
function (match, index, str) {
return index + 6 < str.length
// case: /**/
// > A slash followed by two consecutive asterisks then a slash matches
// > zero or more directories.
// > For example, "a/**/b" matches "a/b", "a/x/b", "a/x/y/b" and so on.
// '/**/'
? '(?:\\/[^\\/]+)*'
// case: /**
// > A trailing `"/**"` matches everything inside.
// #21: everything inside but it should not include the current folder
: '\\/.+';
}],
// intermediate wildcards
[
// Never replace escaped '*'
// ignore rule '\*' will match the path '*'
// 'abc.*/' -> go
// 'abc.*' -> skip this rule
/(^|[^\\]+)\\\*(?=.+)/g,
// '*.js' matches '.js'
// '*.js' doesn't match 'abc'
function (match, p1) {
return `${p1}[^\\/]*`;
}],
// trailing wildcard
[/(\^|\\\/)?\\\*$/, function (match, p1) {
var prefix = p1
// '\^':
// '/*' does not match ''
// '/*' does not match everything
// '\\\/':
// 'abc/*' does not match 'abc/'
? `${p1}[^/]+`
// 'a*' matches 'a'
// 'a*' matches 'aa'
: '[^/]*';
return `${prefix}(?=$|\\/$)`;
}], [
// unescape
/\\\\\\/g, function () {
return '\\';
}]];
var POSITIVE_REPLACERS = [].concat(DEFAULT_REPLACER_PREFIX, [
// 'f'
// matches
// - /f(end)
// - /f/
// - (start)f(end)
// - (start)f/
// doesn't match
// - oof
// - foo
// pseudo:
// -> (^|/)f(/|$)
// ending
[
// 'js' will not match 'js.'
// 'ab' will not match 'abc'
/(?:[^*/])$/,
// 'js*' will not match 'a.js'
// 'js/' will not match 'a.js'
// 'js' will match 'a.js' and 'a.js/'
function (match) {
return `${match}(?=$|\\/)`;
}]], DEFAULT_REPLACER_SUFFIX);
var NEGATIVE_REPLACERS = [].concat(DEFAULT_REPLACER_PREFIX, [
// #24, #38
// The MISSING rule of [gitignore docs](https://git-scm.com/docs/gitignore)
// A negative pattern without a trailing wildcard should not
// re-include the things inside that directory.
// eg:
// ['node_modules/*', '!node_modules']
// should ignore `node_modules/a.js`
[/(?:[^*])$/, function (match) {
return `${match}(?=$|\\/$)`;
}]], DEFAULT_REPLACER_SUFFIX);
// A simple cache, because an ignore rule only has only one certain meaning
var cache = Object.create(null);
// @param {pattern}
var make_regex = function make_regex(pattern, negative, ignorecase) {
var r = cache[pattern];
if (r) {
return r;
}
var replacers = negative ? NEGATIVE_REPLACERS : POSITIVE_REPLACERS;
var source = replacers.reduce(function (prev, current) {
return prev.replace(current[0], current[1].bind(pattern));
}, pattern);
return cache[pattern] = ignorecase ? new RegExp(source, 'i') : new RegExp(source);
};
// > A blank line matches no files, so it can serve as a separator for readability.
var checkPattern = function checkPattern(pattern) {
return pattern && typeof pattern === 'string' && !REGEX_BLANK_LINE.test(pattern)
// > A line starting with # serves as a comment.
&& pattern.indexOf('#') !== 0;
};
var createRule = function createRule(pattern, ignorecase) {
var origin = pattern;
var negative = false;
// > An optional prefix "!" which negates the pattern;
if (pattern.indexOf('!') === 0) {
negative = true;
pattern = pattern.substr(1);
}
pattern = pattern
// > Put a backslash ("\") in front of the first "!" for patterns that
// > begin with a literal "!", for example, `"\!important!.txt"`.
.replace(REGEX_LEADING_EXCAPED_EXCLAMATION, '!')
// > Put a backslash ("\") in front of the first hash for patterns that
// > begin with a hash.
.replace(REGEX_LEADING_EXCAPED_HASH, '#');
var regex = make_regex(pattern, negative, ignorecase);
return {
origin,
pattern,
negative,
regex
};
};
var IgnoreBase = function () {
function IgnoreBase() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
_ref$ignorecase = _ref.ignorecase,
ignorecase = _ref$ignorecase === undefined ? true : _ref$ignorecase;
_classCallCheck(this, IgnoreBase);
this._rules = [];
this._ignorecase = ignorecase;
define(this, KEY_IGNORE, true);
this._initCache();
}
_createClass(IgnoreBase, [{
key: '_initCache',
value: function _initCache() {
this._cache = Object.create(null);
}
// @param {Array.<string>|string|Ignore} pattern
}, {
key: 'add',
value: function add(pattern) {
this._added = false;
if (typeof pattern === 'string') {
pattern = pattern.split(/\r?\n/g);
}
make_array(pattern).forEach(this._addPattern, this);
// Some rules have just added to the ignore,
// making the behavior changed.
if (this._added) {
this._initCache();
}
return this;
}
// legacy
}, {
key: 'addPattern',
value: function addPattern(pattern) {
return this.add(pattern);
}
}, {
key: '_addPattern',
value: function _addPattern(pattern) {
// #32
if (pattern && pattern[KEY_IGNORE]) {
this._rules = this._rules.concat(pattern._rules);
this._added = true;
return;
}
if (checkPattern(pattern)) {
var rule = createRule(pattern, this._ignorecase);
this._added = true;
this._rules.push(rule);
}
}
}, {
key: 'filter',
value: function filter(paths) {
var _this = this;
return make_array(paths).filter(function (path) {
return _this._filter(path);
});
}
}, {
key: 'createFilter',
value: function createFilter() {
var _this2 = this;
return function (path) {
return _this2._filter(path);
};
}
}, {
key: 'ignores',
value: function ignores(path) {
return !this._filter(path);
}
// @returns `Boolean` true if the `path` is NOT ignored
}, {
key: '_filter',
value: function _filter(path, slices) {
if (!path) {
return false;
}
if (path in this._cache) {
return this._cache[path];
}
if (!slices) {
// path/to/a.js
// ['path', 'to', 'a.js']
slices = path.split(SLASH);
}
slices.pop();
return this._cache[path] = slices.length
// > It is not possible to re-include a file if a parent directory of
// > that file is excluded.
// If the path contains a parent directory, check the parent first
? this._filter(slices.join(SLASH) + SLASH, slices) && this._test(path)
// Or only test the path
: this._test(path);
}
// @returns {Boolean} true if a file is NOT ignored
}, {
key: '_test',
value: function _test(path) {
// Explicitly define variable type by setting matched to `0`
var matched = 0;
this._rules.forEach(function (rule) {
// if matched = true, then we only test negative rules
// if matched = false, then we test non-negative rules
if (!(matched ^ rule.negative)) {
matched = rule.negative ^ rule.regex.test(path);
}
});
return !matched;
}
}]);
return IgnoreBase;
}();
// Windows
// --------------------------------------------------------------
/* istanbul ignore if */
if (
// Detect `process` so that it can run in browsers.
typeof process !== 'undefined' && (process.env && process.env.IGNORE_TEST_WIN32 || process.platform === 'win32')) {
var filter = IgnoreBase.prototype._filter;
/* eslint no-control-regex: "off" */
var make_posix = function make_posix(str) {
return (/^\\\\\?\\/.test(str) || /[^\x00-\x80]+/.test(str) ? str : str.replace(/\\/g, '/')
);
};
IgnoreBase.prototype._filter = function filterWin32(path, slices) {
path = make_posix(path);
return filter.call(this, path, slices);
};
}
module.exports = function (options) {
return new IgnoreBase(options);
};

View file

@ -1,64 +0,0 @@
{
"name": "ignore",
"version": "4.0.6",
"description": "Ignore is a manager and filter for .gitignore rules.",
"files": [
"legacy.js",
"index.js",
"index.d.ts",
"LICENSE-MIT"
],
"scripts": {
"prepublish": "npm run build",
"build": "babel -o legacy.js index.js",
"test:lint": "eslint .",
"test:tsc": "tsc ./test/ts/simple.ts",
"test:git": "tap test/git-check-ignore.js",
"test:ignore": "tap test/ignore.js --coverage",
"test-no-cov": "npm run test:lint && npm run test:tsc && tap test/*.js --coverage",
"test": "npm run test-no-cov",
"posttest": "tap --coverage-report=html && codecov"
},
"repository": {
"type": "git",
"url": "git@github.com:kaelzhang/node-ignore.git"
},
"keywords": [
"ignore",
".gitignore",
"gitignore",
"npmignore",
"rules",
"manager",
"filter",
"regexp",
"regex",
"fnmatch",
"glob",
"asterisks",
"regular-expression"
],
"author": "kael",
"license": "MIT",
"bugs": {
"url": "https://github.com/kaelzhang/node-ignore/issues"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-preset-env": "^1.7.0",
"codecov": "^3.0.4",
"eslint": "^5.3.0",
"eslint-config-ostai": "^1.3.2",
"eslint-plugin-import": "^2.13.0",
"mkdirp": "^0.5.1",
"pre-suf": "^1.1.0",
"rimraf": "^2.6.2",
"spawn-sync": "^2.0.0",
"tap": "^12.0.1",
"tmp": "0.0.33",
"typescript": "^3.0.1"
},
"engines": {
"node": ">= 4"
}
}

View file

@ -1,557 +0,0 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [3.14.1] - 2020-12-07
### Security
- Fix possible code execution in (already unsafe) `.load()` (in &anchor).
## [3.14.0] - 2020-05-22
### Changed
- Support `safe/loadAll(input, options)` variant of call.
- CI: drop outdated nodejs versions.
- Dev deps bump.
### Fixed
- Quote `=` in plain scalars #519.
- Check the node type for `!<?>` tag in case user manually specifies it.
- Verify that there are no null-bytes in input.
- Fix wrong quote position when writing condensed flow, #526.
## [3.13.1] - 2019-04-05
### Security
- Fix possible code execution in (already unsafe) `.load()`, #480.
## [3.13.0] - 2019-03-20
### Security
- Security fix: `safeLoad()` can hang when arrays with nested refs
used as key. Now throws exception for nested arrays. #475.
## [3.12.2] - 2019-02-26
### Fixed
- Fix `noArrayIndent` option for root level, #468.
## [3.12.1] - 2019-01-05
### Added
- Added `noArrayIndent` option, #432.
## [3.12.0] - 2018-06-02
### Changed
- Support arrow functions without a block statement, #421.
## [3.11.0] - 2018-03-05
### Added
- Add arrow functions suport for `!!js/function`.
### Fixed
- Fix dump in bin/octal/hex formats for negative integers, #399.
## [3.10.0] - 2017-09-10
### Fixed
- Fix `condenseFlow` output (quote keys for sure, instead of spaces), #371, #370.
- Dump astrals as codepoints instead of surrogate pair, #368.
## [3.9.1] - 2017-07-08
### Fixed
- Ensure stack is present for custom errors in node 7.+, #351.
## [3.9.0] - 2017-07-08
### Added
- Add `condenseFlow` option (to create pretty URL query params), #346.
### Fixed
- Support array return from safeLoadAll/loadAll, #350.
## [3.8.4] - 2017-05-08
### Fixed
- Dumper: prevent space after dash for arrays that wrap, #343.
## [3.8.3] - 2017-04-05
### Fixed
- Should not allow numbers to begin and end with underscore, #335.
## [3.8.2] - 2017-03-02
### Fixed
- Fix `!!float 123` (integers) parse, #333.
- Don't allow leading zeros in floats (except 0, 0.xxx).
- Allow positive exponent without sign in floats.
## [3.8.1] - 2017-02-07
### Changed
- Maintenance: update browserified build.
## [3.8.0] - 2017-02-07
### Fixed
- Fix reported position for `duplicated mapping key` errors.
Now points to block start instead of block end.
(#243, thanks to @shockey).
## [3.7.0] - 2016-11-12
### Added
- Support polymorphism for tags (#300, thanks to @monken).
### Fixed
- Fix parsing of quotes followed by newlines (#304, thanks to @dplepage).
## [3.6.1] - 2016-05-11
### Fixed
- Fix output cut on a pipe, #286.
## [3.6.0] - 2016-04-16
### Fixed
- Dumper rewrite, fix multiple bugs with trailing `\n`.
Big thanks to @aepsilon!
- Loader: fix leading/trailing newlines in block scalars, @aepsilon.
## [3.5.5] - 2016-03-17
### Fixed
- Date parse fix: don't allow dates with on digit in month and day, #268.
## [3.5.4] - 2016-03-09
### Added
- `noCompatMode` for dumper, to disable quoting YAML 1.1 values.
## [3.5.3] - 2016-02-11
### Changed
- Maintenance release.
## [3.5.2] - 2016-01-11
### Changed
- Maintenance: missed comma in bower config.
## [3.5.1] - 2016-01-11
### Changed
- Removed `inherit` dependency, #239.
- Better browserify workaround for esprima load.
- Demo rewrite.
## [3.5.0] - 2016-01-10
### Fixed
- Dumper. Fold strings only, #217.
- Dumper. `norefs` option, to clone linked objects, #229.
- Loader. Throw a warning for duplicate keys, #166.
- Improved browserify support (mark `esprima` & `Buffer` excluded).
## [3.4.6] - 2015-11-26
### Changed
- Use standalone `inherit` to keep browserified files clear.
## [3.4.5] - 2015-11-23
### Added
- Added `lineWidth` option to dumper.
## [3.4.4] - 2015-11-21
### Fixed
- Fixed floats dump (missed dot for scientific format), #220.
- Allow non-printable characters inside quoted scalars, #192.
## [3.4.3] - 2015-10-10
### Changed
- Maintenance release - deps bump (esprima, argparse).
## [3.4.2] - 2015-09-09
### Fixed
- Fixed serialization of duplicated entries in sequences, #205.
Thanks to @vogelsgesang.
## [3.4.1] - 2015-09-05
### Fixed
- Fixed stacktrace handling in generated errors, for browsers (FF/IE).
## [3.4.0] - 2015-08-23
### Changed
- Don't throw on warnings anymore. Use `onWarning` option to catch.
- Throw error on unknown tags (was warning before).
- Reworked internals of error class.
### Fixed
- Fixed multiline keys dump, #197. Thanks to @tcr.
- Fixed heading line breaks in some scalars (regression).
## [3.3.1] - 2015-05-13
### Added
- Added `.sortKeys` dumper option, thanks to @rjmunro.
### Fixed
- Fixed astral characters support, #191.
## [3.3.0] - 2015-04-26
### Changed
- Significantly improved long strings formatting in dumper, thanks to @isaacs.
- Strip BOM if exists.
## [3.2.7] - 2015-02-19
### Changed
- Maintenance release.
- Updated dependencies.
- HISTORY.md -> CHANGELOG.md
## [3.2.6] - 2015-02-07
### Fixed
- Fixed encoding of UTF-16 surrogate pairs. (e.g. "\U0001F431" CAT FACE).
- Fixed demo dates dump (#113, thanks to @Hypercubed).
## [3.2.5] - 2014-12-28
### Fixed
- Fixed resolving of all built-in types on empty nodes.
- Fixed invalid warning on empty lines within quoted scalars and flow collections.
- Fixed bug: Tag on an empty node didn't resolve in some cases.
## [3.2.4] - 2014-12-19
### Fixed
- Fixed resolving of !!null tag on an empty node.
## [3.2.3] - 2014-11-08
### Fixed
- Implemented dumping of objects with circular and cross references.
- Partially fixed aliasing of constructed objects. (see issue #141 for details)
## [3.2.2] - 2014-09-07
### Fixed
- Fixed infinite loop on unindented block scalars.
- Rewritten base64 encode/decode in binary type, to keep code licence clear.
## [3.2.1] - 2014-08-24
### Fixed
- Nothig new. Just fix npm publish error.
## [3.2.0] - 2014-08-24
### Added
- Added input piping support to CLI.
### Fixed
- Fixed typo, that could cause hand on initial indent (#139).
## [3.1.0] - 2014-07-07
### Changed
- 1.5x-2x speed boost.
- Removed deprecated `require('xxx.yml')` support.
- Significant code cleanup and refactoring.
- Internal API changed. If you used custom types - see updated examples.
Others are not affected.
- Even if the input string has no trailing line break character,
it will be parsed as if it has one.
- Added benchmark scripts.
- Moved bower files to /dist folder
- Bugfixes.
## [3.0.2] - 2014-02-27
### Fixed
- Fixed bug: "constructor" string parsed as `null`.
## [3.0.1] - 2013-12-22
### Fixed
- Fixed parsing of literal scalars. (issue #108)
- Prevented adding unnecessary spaces in object dumps. (issue #68)
- Fixed dumping of objects with very long (> 1024 in length) keys.
## [3.0.0] - 2013-12-16
### Changed
- Refactored code. Changed API for custom types.
- Removed output colors in CLI, dump json by default.
- Removed big dependencies from browser version (esprima, buffer). Load `esprima` manually, if `!!js/function` needed. `!!bin` now returns Array in browser
- AMD support.
- Don't quote dumped strings because of `-` & `?` (if not first char).
- __Deprecated__ loading yaml files via `require()`, as not recommended
behaviour for node.
## [2.1.3] - 2013-10-16
### Fixed
- Fix wrong loading of empty block scalars.
## [2.1.2] - 2013-10-07
### Fixed
- Fix unwanted line breaks in folded scalars.
## [2.1.1] - 2013-10-02
### Fixed
- Dumper now respects deprecated booleans syntax from YAML 1.0/1.1
- Fixed reader bug in JSON-like sequences/mappings.
## [2.1.0] - 2013-06-05
### Added
- Add standard YAML schemas: Failsafe (`FAILSAFE_SCHEMA`),
JSON (`JSON_SCHEMA`) and Core (`CORE_SCHEMA`).
- Add `skipInvalid` dumper option.
### Changed
- Rename `DEFAULT_SCHEMA` to `DEFAULT_FULL_SCHEMA`
and `SAFE_SCHEMA` to `DEFAULT_SAFE_SCHEMA`.
- Use `safeLoad` for `require` extension.
### Fixed
- Bug fix: export `NIL` constant from the public interface.
## [2.0.5] - 2013-04-26
### Security
- Close security issue in !!js/function constructor.
Big thanks to @nealpoole for security audit.
## [2.0.4] - 2013-04-08
### Changed
- Updated .npmignore to reduce package size
## [2.0.3] - 2013-02-26
### Fixed
- Fixed dumping of empty arrays ans objects. ([] and {} instead of null)
## [2.0.2] - 2013-02-15
### Fixed
- Fixed input validation: tabs are printable characters.
## [2.0.1] - 2013-02-09
### Fixed
- Fixed error, when options not passed to function cass
## [2.0.0] - 2013-02-09
### Changed
- Full rewrite. New architecture. Fast one-stage parsing.
- Changed custom types API.
- Added YAML dumper.
## [1.0.3] - 2012-11-05
### Fixed
- Fixed utf-8 files loading.
## [1.0.2] - 2012-08-02
### Fixed
- Pull out hand-written shims. Use ES5-Shims for old browsers support. See #44.
- Fix timstamps incorectly parsed in local time when no time part specified.
## [1.0.1] - 2012-07-07
### Fixed
- Fixes `TypeError: 'undefined' is not an object` under Safari. Thanks Phuong.
- Fix timestamps incorrectly parsed in local time. Thanks @caolan. Closes #46.
## [1.0.0] - 2012-07-01
### Changed
- `y`, `yes`, `n`, `no`, `on`, `off` are not converted to Booleans anymore.
Fixes #42.
- `require(filename)` now returns a single document and throws an Error if
file contains more than one document.
- CLI was merged back from js-yaml.bin
## [0.3.7] - 2012-02-28
### Fixed
- Fix export of `addConstructor()`. Closes #39.
## [0.3.6] - 2012-02-22
### Changed
- Removed AMD parts - too buggy to use. Need help to rewrite from scratch
### Fixed
- Removed YUI compressor warning (renamed `double` variable). Closes #40.
## [0.3.5] - 2012-01-10
### Fixed
- Workagound for .npmignore fuckup under windows. Thanks to airportyh.
## [0.3.4] - 2011-12-24
### Fixed
- Fixes str[] for oldIEs support.
- Adds better has change support for browserified demo.
- improves compact output of Error. Closes #33.
## [0.3.3] - 2011-12-20
### Added
- adds `compact` stringification of Errors.
### Changed
- jsyaml executable moved to separate module.
## [0.3.2] - 2011-12-16
### Added
- Added jsyaml executable.
- Added !!js/function support. Closes #12.
### Fixed
- Fixes ug with block style scalars. Closes #26.
- All sources are passing JSLint now.
- Fixes bug in Safari. Closes #28.
- Fixes bug in Opers. Closes #29.
- Improves browser support. Closes #20.
## [0.3.1] - 2011-11-18
### Added
- Added AMD support for browserified version.
- Added permalinks for online demo YAML snippets. Now we have YPaste service, lol.
- Added !!js/regexp and !!js/undefined types. Partially solves #12.
### Changed
- Wrapped browserified js-yaml into closure.
### Fixed
- Fixed the resolvement of non-specific tags. Closes #17.
- Fixed !!set mapping.
- Fixed month parse in dates. Closes #19.
## [0.3.0] - 2011-11-09
### Added
- Added browserified version. Closes #13.
- Added live demo of browserified version.
- Ported some of the PyYAML tests. See #14.
### Fixed
- Removed JS.Class dependency. Closes #3.
- Fixed timestamp bug when fraction was given.
## [0.2.2] - 2011-11-06
### Fixed
- Fixed crash on docs without ---. Closes #8.
- Fixed multiline string parse
- Fixed tests/comments for using array as key
## [0.2.1] - 2011-11-02
### Fixed
- Fixed short file read (<4k). Closes #9.
## [0.2.0] - 2011-11-02
### Changed
- First public release
[3.14.1]: https://github.com/nodeca/js-yaml/compare/3.14.0...3.14.1
[3.14.0]: https://github.com/nodeca/js-yaml/compare/3.13.1...3.14.0
[3.13.1]: https://github.com/nodeca/js-yaml/compare/3.13.0...3.13.1
[3.13.0]: https://github.com/nodeca/js-yaml/compare/3.12.2...3.13.0
[3.12.2]: https://github.com/nodeca/js-yaml/compare/3.12.1...3.12.2
[3.12.1]: https://github.com/nodeca/js-yaml/compare/3.12.0...3.12.1
[3.12.0]: https://github.com/nodeca/js-yaml/compare/3.11.0...3.12.0
[3.11.0]: https://github.com/nodeca/js-yaml/compare/3.10.0...3.11.0
[3.10.0]: https://github.com/nodeca/js-yaml/compare/3.9.1...3.10.0
[3.9.1]: https://github.com/nodeca/js-yaml/compare/3.9.0...3.9.1
[3.9.0]: https://github.com/nodeca/js-yaml/compare/3.8.4...3.9.0
[3.8.4]: https://github.com/nodeca/js-yaml/compare/3.8.3...3.8.4
[3.8.3]: https://github.com/nodeca/js-yaml/compare/3.8.2...3.8.3
[3.8.2]: https://github.com/nodeca/js-yaml/compare/3.8.1...3.8.2
[3.8.1]: https://github.com/nodeca/js-yaml/compare/3.8.0...3.8.1
[3.8.0]: https://github.com/nodeca/js-yaml/compare/3.7.0...3.8.0
[3.7.0]: https://github.com/nodeca/js-yaml/compare/3.6.1...3.7.0
[3.6.1]: https://github.com/nodeca/js-yaml/compare/3.6.0...3.6.1
[3.6.0]: https://github.com/nodeca/js-yaml/compare/3.5.5...3.6.0
[3.5.5]: https://github.com/nodeca/js-yaml/compare/3.5.4...3.5.5
[3.5.4]: https://github.com/nodeca/js-yaml/compare/3.5.3...3.5.4
[3.5.3]: https://github.com/nodeca/js-yaml/compare/3.5.2...3.5.3
[3.5.2]: https://github.com/nodeca/js-yaml/compare/3.5.1...3.5.2
[3.5.1]: https://github.com/nodeca/js-yaml/compare/3.5.0...3.5.1
[3.5.0]: https://github.com/nodeca/js-yaml/compare/3.4.6...3.5.0
[3.4.6]: https://github.com/nodeca/js-yaml/compare/3.4.5...3.4.6
[3.4.5]: https://github.com/nodeca/js-yaml/compare/3.4.4...3.4.5
[3.4.4]: https://github.com/nodeca/js-yaml/compare/3.4.3...3.4.4
[3.4.3]: https://github.com/nodeca/js-yaml/compare/3.4.2...3.4.3
[3.4.2]: https://github.com/nodeca/js-yaml/compare/3.4.1...3.4.2
[3.4.1]: https://github.com/nodeca/js-yaml/compare/3.4.0...3.4.1
[3.4.0]: https://github.com/nodeca/js-yaml/compare/3.3.1...3.4.0
[3.3.1]: https://github.com/nodeca/js-yaml/compare/3.3.0...3.3.1
[3.3.0]: https://github.com/nodeca/js-yaml/compare/3.2.7...3.3.0
[3.2.7]: https://github.com/nodeca/js-yaml/compare/3.2.6...3.2.7
[3.2.6]: https://github.com/nodeca/js-yaml/compare/3.2.5...3.2.6
[3.2.5]: https://github.com/nodeca/js-yaml/compare/3.2.4...3.2.5
[3.2.4]: https://github.com/nodeca/js-yaml/compare/3.2.3...3.2.4
[3.2.3]: https://github.com/nodeca/js-yaml/compare/3.2.2...3.2.3
[3.2.2]: https://github.com/nodeca/js-yaml/compare/3.2.1...3.2.2
[3.2.1]: https://github.com/nodeca/js-yaml/compare/3.2.0...3.2.1
[3.2.0]: https://github.com/nodeca/js-yaml/compare/3.1.0...3.2.0
[3.1.0]: https://github.com/nodeca/js-yaml/compare/3.0.2...3.1.0
[3.0.2]: https://github.com/nodeca/js-yaml/compare/3.0.1...3.0.2
[3.0.1]: https://github.com/nodeca/js-yaml/compare/3.0.0...3.0.1
[3.0.0]: https://github.com/nodeca/js-yaml/compare/2.1.3...3.0.0
[2.1.3]: https://github.com/nodeca/js-yaml/compare/2.1.2...2.1.3
[2.1.2]: https://github.com/nodeca/js-yaml/compare/2.1.1...2.1.2
[2.1.1]: https://github.com/nodeca/js-yaml/compare/2.1.0...2.1.1
[2.1.0]: https://github.com/nodeca/js-yaml/compare/2.0.5...2.1.0
[2.0.5]: https://github.com/nodeca/js-yaml/compare/2.0.4...2.0.5
[2.0.4]: https://github.com/nodeca/js-yaml/compare/2.0.3...2.0.4
[2.0.3]: https://github.com/nodeca/js-yaml/compare/2.0.2...2.0.3
[2.0.2]: https://github.com/nodeca/js-yaml/compare/2.0.1...2.0.2
[2.0.1]: https://github.com/nodeca/js-yaml/compare/2.0.0...2.0.1
[2.0.0]: https://github.com/nodeca/js-yaml/compare/1.0.3...2.0.0
[1.0.3]: https://github.com/nodeca/js-yaml/compare/1.0.2...1.0.3
[1.0.2]: https://github.com/nodeca/js-yaml/compare/1.0.1...1.0.2
[1.0.1]: https://github.com/nodeca/js-yaml/compare/1.0.0...1.0.1
[1.0.0]: https://github.com/nodeca/js-yaml/compare/0.3.7...1.0.0
[0.3.7]: https://github.com/nodeca/js-yaml/compare/0.3.6...0.3.7
[0.3.6]: https://github.com/nodeca/js-yaml/compare/0.3.5...0.3.6
[0.3.5]: https://github.com/nodeca/js-yaml/compare/0.3.4...0.3.5
[0.3.4]: https://github.com/nodeca/js-yaml/compare/0.3.3...0.3.4
[0.3.3]: https://github.com/nodeca/js-yaml/compare/0.3.2...0.3.3
[0.3.2]: https://github.com/nodeca/js-yaml/compare/0.3.1...0.3.2
[0.3.1]: https://github.com/nodeca/js-yaml/compare/0.3.0...0.3.1
[0.3.0]: https://github.com/nodeca/js-yaml/compare/0.2.2...0.3.0
[0.2.2]: https://github.com/nodeca/js-yaml/compare/0.2.1...0.2.2
[0.2.1]: https://github.com/nodeca/js-yaml/compare/0.2.0...0.2.1
[0.2.0]: https://github.com/nodeca/js-yaml/releases/tag/0.2.0

View file

@ -1,21 +0,0 @@
(The MIT License)
Copyright (C) 2011-2015 by Vitaly Puzrin
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.

View file

@ -1,299 +0,0 @@
JS-YAML - YAML 1.2 parser / writer for JavaScript
=================================================
[![Build Status](https://travis-ci.org/nodeca/js-yaml.svg?branch=master)](https://travis-ci.org/nodeca/js-yaml)
[![NPM version](https://img.shields.io/npm/v/js-yaml.svg)](https://www.npmjs.org/package/js-yaml)
__[Online Demo](http://nodeca.github.com/js-yaml/)__
This is an implementation of [YAML](http://yaml.org/), a human-friendly data
serialization language. Started as [PyYAML](http://pyyaml.org/) port, it was
completely rewritten from scratch. Now it's very fast, and supports 1.2 spec.
Installation
------------
### YAML module for node.js
```
npm install js-yaml
```
### CLI executable
If you want to inspect your YAML files from CLI, install js-yaml globally:
```
npm install -g js-yaml
```
#### Usage
```
usage: js-yaml [-h] [-v] [-c] [-t] file
Positional arguments:
file File with YAML document(s)
Optional arguments:
-h, --help Show this help message and exit.
-v, --version Show program's version number and exit.
-c, --compact Display errors in compact mode
-t, --trace Show stack trace on error
```
### Bundled YAML library for browsers
``` html
<!-- esprima required only for !!js/function -->
<script src="esprima.js"></script>
<script src="js-yaml.min.js"></script>
<script type="text/javascript">
var doc = jsyaml.load('greeting: hello\nname: world');
</script>
```
Browser support was done mostly for the online demo. If you find any errors - feel
free to send pull requests with fixes. Also note, that IE and other old browsers
needs [es5-shims](https://github.com/kriskowal/es5-shim) to operate.
Notes:
1. We have no resources to support browserified version. Don't expect it to be
well tested. Don't expect fast fixes if something goes wrong there.
2. `!!js/function` in browser bundle will not work by default. If you really need
it - load `esprima` parser first (via amd or directly).
3. `!!bin` in browser will return `Array`, because browsers do not support
node.js `Buffer` and adding Buffer shims is completely useless on practice.
API
---
Here we cover the most 'useful' methods. If you need advanced details (creating
your own tags), see [wiki](https://github.com/nodeca/js-yaml/wiki) and
[examples](https://github.com/nodeca/js-yaml/tree/master/examples) for more
info.
``` javascript
const yaml = require('js-yaml');
const fs = require('fs');
// Get document, or throw exception on error
try {
const doc = yaml.safeLoad(fs.readFileSync('/home/ixti/example.yml', 'utf8'));
console.log(doc);
} catch (e) {
console.log(e);
}
```
### safeLoad (string [ , options ])
**Recommended loading way.** Parses `string` as single YAML document. Returns either a
plain object, a string or `undefined`, or throws `YAMLException` on error. By default, does
not support regexps, functions and undefined. This method is safe for untrusted data.
options:
- `filename` _(default: null)_ - string to be used as a file path in
error/warning messages.
- `onWarning` _(default: null)_ - function to call on warning messages.
Loader will call this function with an instance of `YAMLException` for each warning.
- `schema` _(default: `DEFAULT_SAFE_SCHEMA`)_ - specifies a schema to use.
- `FAILSAFE_SCHEMA` - only strings, arrays and plain objects:
http://www.yaml.org/spec/1.2/spec.html#id2802346
- `JSON_SCHEMA` - all JSON-supported types:
http://www.yaml.org/spec/1.2/spec.html#id2803231
- `CORE_SCHEMA` - same as `JSON_SCHEMA`:
http://www.yaml.org/spec/1.2/spec.html#id2804923
- `DEFAULT_SAFE_SCHEMA` - all supported YAML types, without unsafe ones
(`!!js/undefined`, `!!js/regexp` and `!!js/function`):
http://yaml.org/type/
- `DEFAULT_FULL_SCHEMA` - all supported YAML types.
- `json` _(default: false)_ - compatibility with JSON.parse behaviour. If true, then duplicate keys in a mapping will override values rather than throwing an error.
NOTE: This function **does not** understand multi-document sources, it throws
exception on those.
NOTE: JS-YAML **does not** support schema-specific tag resolution restrictions.
So, the JSON schema is not as strictly defined in the YAML specification.
It allows numbers in any notation, use `Null` and `NULL` as `null`, etc.
The core schema also has no such restrictions. It allows binary notation for integers.
### load (string [ , options ])
**Use with care with untrusted sources**. The same as `safeLoad()` but uses
`DEFAULT_FULL_SCHEMA` by default - adds some JavaScript-specific types:
`!!js/function`, `!!js/regexp` and `!!js/undefined`. For untrusted sources, you
must additionally validate object structure to avoid injections:
``` javascript
const untrusted_code = '"toString": !<tag:yaml.org,2002:js/function> "function (){very_evil_thing();}"';
// I'm just converting that string, what could possibly go wrong?
require('js-yaml').load(untrusted_code) + ''
```
### safeLoadAll (string [, iterator] [, options ])
Same as `safeLoad()`, but understands multi-document sources. Applies
`iterator` to each document if specified, or returns array of documents.
``` javascript
const yaml = require('js-yaml');
yaml.safeLoadAll(data, function (doc) {
console.log(doc);
});
```
### loadAll (string [, iterator] [ , options ])
Same as `safeLoadAll()` but uses `DEFAULT_FULL_SCHEMA` by default.
### safeDump (object [ , options ])
Serializes `object` as a YAML document. Uses `DEFAULT_SAFE_SCHEMA`, so it will
throw an exception if you try to dump regexps or functions. However, you can
disable exceptions by setting the `skipInvalid` option to `true`.
options:
- `indent` _(default: 2)_ - indentation width to use (in spaces).
- `noArrayIndent` _(default: false)_ - when true, will not add an indentation level to array elements
- `skipInvalid` _(default: false)_ - do not throw on invalid types (like function
in the safe schema) and skip pairs and single values with such types.
- `flowLevel` (default: -1) - specifies level of nesting, when to switch from
block to flow style for collections. -1 means block style everwhere
- `styles` - "tag" => "style" map. Each tag may have own set of styles.
- `schema` _(default: `DEFAULT_SAFE_SCHEMA`)_ specifies a schema to use.
- `sortKeys` _(default: `false`)_ - if `true`, sort keys when dumping YAML. If a
function, use the function to sort the keys.
- `lineWidth` _(default: `80`)_ - set max line width.
- `noRefs` _(default: `false`)_ - if `true`, don't convert duplicate objects into references
- `noCompatMode` _(default: `false`)_ - if `true` don't try to be compatible with older
yaml versions. Currently: don't quote "yes", "no" and so on, as required for YAML 1.1
- `condenseFlow` _(default: `false`)_ - if `true` flow sequences will be condensed, omitting the space between `a, b`. Eg. `'[a,b]'`, and omitting the space between `key: value` and quoting the key. Eg. `'{"a":b}'` Can be useful when using yaml for pretty URL query params as spaces are %-encoded.
The following table show availlable styles (e.g. "canonical",
"binary"...) available for each tag (.e.g. !!null, !!int ...). Yaml
output is shown on the right side after `=>` (default setting) or `->`:
``` none
!!null
"canonical" -> "~"
"lowercase" => "null"
"uppercase" -> "NULL"
"camelcase" -> "Null"
!!int
"binary" -> "0b1", "0b101010", "0b1110001111010"
"octal" -> "01", "052", "016172"
"decimal" => "1", "42", "7290"
"hexadecimal" -> "0x1", "0x2A", "0x1C7A"
!!bool
"lowercase" => "true", "false"
"uppercase" -> "TRUE", "FALSE"
"camelcase" -> "True", "False"
!!float
"lowercase" => ".nan", '.inf'
"uppercase" -> ".NAN", '.INF'
"camelcase" -> ".NaN", '.Inf'
```
Example:
``` javascript
safeDump (object, {
'styles': {
'!!null': 'canonical' // dump null as ~
},
'sortKeys': true // sort object keys
});
```
### dump (object [ , options ])
Same as `safeDump()` but without limits (uses `DEFAULT_FULL_SCHEMA` by default).
Supported YAML types
--------------------
The list of standard YAML tags and corresponding JavaScipt types. See also
[YAML tag discussion](http://pyyaml.org/wiki/YAMLTagDiscussion) and
[YAML types repository](http://yaml.org/type/).
```
!!null '' # null
!!bool 'yes' # bool
!!int '3...' # number
!!float '3.14...' # number
!!binary '...base64...' # buffer
!!timestamp 'YYYY-...' # date
!!omap [ ... ] # array of key-value pairs
!!pairs [ ... ] # array or array pairs
!!set { ... } # array of objects with given keys and null values
!!str '...' # string
!!seq [ ... ] # array
!!map { ... } # object
```
**JavaScript-specific tags**
```
!!js/regexp /pattern/gim # RegExp
!!js/undefined '' # Undefined
!!js/function 'function () {...}' # Function
```
Caveats
-------
Note, that you use arrays or objects as key in JS-YAML. JS does not allow objects
or arrays as keys, and stringifies (by calling `toString()` method) them at the
moment of adding them.
``` yaml
---
? [ foo, bar ]
: - baz
? { foo: bar }
: - baz
- baz
```
``` javascript
{ "foo,bar": ["baz"], "[object Object]": ["baz", "baz"] }
```
Also, reading of properties on implicit block mapping keys is not supported yet.
So, the following YAML document cannot be loaded.
``` yaml
&anchor foo:
foo: bar
*anchor: duplicate key
baz: bat
*anchor: duplicate key
```
js-yaml for enterprise
----------------------
Available as part of the Tidelift Subscription
The maintainers of js-yaml and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-js-yaml?utm_source=npm-js-yaml&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)

View file

@ -1,132 +0,0 @@
#!/usr/bin/env node
'use strict';
/*eslint-disable no-console*/
// stdlib
var fs = require('fs');
// 3rd-party
var argparse = require('argparse');
// internal
var yaml = require('..');
////////////////////////////////////////////////////////////////////////////////
var cli = new argparse.ArgumentParser({
prog: 'js-yaml',
version: require('../package.json').version,
addHelp: true
});
cli.addArgument([ '-c', '--compact' ], {
help: 'Display errors in compact mode',
action: 'storeTrue'
});
// deprecated (not needed after we removed output colors)
// option suppressed, but not completely removed for compatibility
cli.addArgument([ '-j', '--to-json' ], {
help: argparse.Const.SUPPRESS,
dest: 'json',
action: 'storeTrue'
});
cli.addArgument([ '-t', '--trace' ], {
help: 'Show stack trace on error',
action: 'storeTrue'
});
cli.addArgument([ 'file' ], {
help: 'File to read, utf-8 encoded without BOM',
nargs: '?',
defaultValue: '-'
});
////////////////////////////////////////////////////////////////////////////////
var options = cli.parseArgs();
////////////////////////////////////////////////////////////////////////////////
function readFile(filename, encoding, callback) {
if (options.file === '-') {
// read from stdin
var chunks = [];
process.stdin.on('data', function (chunk) {
chunks.push(chunk);
});
process.stdin.on('end', function () {
return callback(null, Buffer.concat(chunks).toString(encoding));
});
} else {
fs.readFile(filename, encoding, callback);
}
}
readFile(options.file, 'utf8', function (error, input) {
var output, isYaml;
if (error) {
if (error.code === 'ENOENT') {
console.error('File not found: ' + options.file);
process.exit(2);
}
console.error(
options.trace && error.stack ||
error.message ||
String(error));
process.exit(1);
}
try {
output = JSON.parse(input);
isYaml = false;
} catch (err) {
if (err instanceof SyntaxError) {
try {
output = [];
yaml.loadAll(input, function (doc) { output.push(doc); }, {});
isYaml = true;
if (output.length === 0) output = null;
else if (output.length === 1) output = output[0];
} catch (e) {
if (options.trace && err.stack) console.error(e.stack);
else console.error(e.toString(options.compact));
process.exit(1);
}
} else {
console.error(
options.trace && err.stack ||
err.message ||
String(err));
process.exit(1);
}
}
if (isYaml) console.log(JSON.stringify(output, null, ' '));
else console.log(yaml.dump(output));
});

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -1,7 +0,0 @@
'use strict';
var yaml = require('./lib/js-yaml.js');
module.exports = yaml;

View file

@ -1,39 +0,0 @@
'use strict';
var loader = require('./js-yaml/loader');
var dumper = require('./js-yaml/dumper');
function deprecated(name) {
return function () {
throw new Error('Function ' + name + ' is deprecated and cannot be used.');
};
}
module.exports.Type = require('./js-yaml/type');
module.exports.Schema = require('./js-yaml/schema');
module.exports.FAILSAFE_SCHEMA = require('./js-yaml/schema/failsafe');
module.exports.JSON_SCHEMA = require('./js-yaml/schema/json');
module.exports.CORE_SCHEMA = require('./js-yaml/schema/core');
module.exports.DEFAULT_SAFE_SCHEMA = require('./js-yaml/schema/default_safe');
module.exports.DEFAULT_FULL_SCHEMA = require('./js-yaml/schema/default_full');
module.exports.load = loader.load;
module.exports.loadAll = loader.loadAll;
module.exports.safeLoad = loader.safeLoad;
module.exports.safeLoadAll = loader.safeLoadAll;
module.exports.dump = dumper.dump;
module.exports.safeDump = dumper.safeDump;
module.exports.YAMLException = require('./js-yaml/exception');
// Deprecated schema names from JS-YAML 2.0.x
module.exports.MINIMAL_SCHEMA = require('./js-yaml/schema/failsafe');
module.exports.SAFE_SCHEMA = require('./js-yaml/schema/default_safe');
module.exports.DEFAULT_SCHEMA = require('./js-yaml/schema/default_full');
// Deprecated functions from JS-YAML 1.x.x
module.exports.scan = deprecated('scan');
module.exports.parse = deprecated('parse');
module.exports.compose = deprecated('compose');
module.exports.addConstructor = deprecated('addConstructor');

View file

@ -1,59 +0,0 @@
'use strict';
function isNothing(subject) {
return (typeof subject === 'undefined') || (subject === null);
}
function isObject(subject) {
return (typeof subject === 'object') && (subject !== null);
}
function toArray(sequence) {
if (Array.isArray(sequence)) return sequence;
else if (isNothing(sequence)) return [];
return [ sequence ];
}
function extend(target, source) {
var index, length, key, sourceKeys;
if (source) {
sourceKeys = Object.keys(source);
for (index = 0, length = sourceKeys.length; index < length; index += 1) {
key = sourceKeys[index];
target[key] = source[key];
}
}
return target;
}
function repeat(string, count) {
var result = '', cycle;
for (cycle = 0; cycle < count; cycle += 1) {
result += string;
}
return result;
}
function isNegativeZero(number) {
return (number === 0) && (Number.NEGATIVE_INFINITY === 1 / number);
}
module.exports.isNothing = isNothing;
module.exports.isObject = isObject;
module.exports.toArray = toArray;
module.exports.repeat = repeat;
module.exports.isNegativeZero = isNegativeZero;
module.exports.extend = extend;

View file

@ -1,850 +0,0 @@
'use strict';
/*eslint-disable no-use-before-define*/
var common = require('./common');
var YAMLException = require('./exception');
var DEFAULT_FULL_SCHEMA = require('./schema/default_full');
var DEFAULT_SAFE_SCHEMA = require('./schema/default_safe');
var _toString = Object.prototype.toString;
var _hasOwnProperty = Object.prototype.hasOwnProperty;
var CHAR_TAB = 0x09; /* Tab */
var CHAR_LINE_FEED = 0x0A; /* LF */
var CHAR_CARRIAGE_RETURN = 0x0D; /* CR */
var CHAR_SPACE = 0x20; /* Space */
var CHAR_EXCLAMATION = 0x21; /* ! */
var CHAR_DOUBLE_QUOTE = 0x22; /* " */
var CHAR_SHARP = 0x23; /* # */
var CHAR_PERCENT = 0x25; /* % */
var CHAR_AMPERSAND = 0x26; /* & */
var CHAR_SINGLE_QUOTE = 0x27; /* ' */
var CHAR_ASTERISK = 0x2A; /* * */
var CHAR_COMMA = 0x2C; /* , */
var CHAR_MINUS = 0x2D; /* - */
var CHAR_COLON = 0x3A; /* : */
var CHAR_EQUALS = 0x3D; /* = */
var CHAR_GREATER_THAN = 0x3E; /* > */
var CHAR_QUESTION = 0x3F; /* ? */
var CHAR_COMMERCIAL_AT = 0x40; /* @ */
var CHAR_LEFT_SQUARE_BRACKET = 0x5B; /* [ */
var CHAR_RIGHT_SQUARE_BRACKET = 0x5D; /* ] */
var CHAR_GRAVE_ACCENT = 0x60; /* ` */
var CHAR_LEFT_CURLY_BRACKET = 0x7B; /* { */
var CHAR_VERTICAL_LINE = 0x7C; /* | */
var CHAR_RIGHT_CURLY_BRACKET = 0x7D; /* } */
var ESCAPE_SEQUENCES = {};
ESCAPE_SEQUENCES[0x00] = '\\0';
ESCAPE_SEQUENCES[0x07] = '\\a';
ESCAPE_SEQUENCES[0x08] = '\\b';
ESCAPE_SEQUENCES[0x09] = '\\t';
ESCAPE_SEQUENCES[0x0A] = '\\n';
ESCAPE_SEQUENCES[0x0B] = '\\v';
ESCAPE_SEQUENCES[0x0C] = '\\f';
ESCAPE_SEQUENCES[0x0D] = '\\r';
ESCAPE_SEQUENCES[0x1B] = '\\e';
ESCAPE_SEQUENCES[0x22] = '\\"';
ESCAPE_SEQUENCES[0x5C] = '\\\\';
ESCAPE_SEQUENCES[0x85] = '\\N';
ESCAPE_SEQUENCES[0xA0] = '\\_';
ESCAPE_SEQUENCES[0x2028] = '\\L';
ESCAPE_SEQUENCES[0x2029] = '\\P';
var DEPRECATED_BOOLEANS_SYNTAX = [
'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON',
'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF'
];
function compileStyleMap(schema, map) {
var result, keys, index, length, tag, style, type;
if (map === null) return {};
result = {};
keys = Object.keys(map);
for (index = 0, length = keys.length; index < length; index += 1) {
tag = keys[index];
style = String(map[tag]);
if (tag.slice(0, 2) === '!!') {
tag = 'tag:yaml.org,2002:' + tag.slice(2);
}
type = schema.compiledTypeMap['fallback'][tag];
if (type && _hasOwnProperty.call(type.styleAliases, style)) {
style = type.styleAliases[style];
}
result[tag] = style;
}
return result;
}
function encodeHex(character) {
var string, handle, length;
string = character.toString(16).toUpperCase();
if (character <= 0xFF) {
handle = 'x';
length = 2;
} else if (character <= 0xFFFF) {
handle = 'u';
length = 4;
} else if (character <= 0xFFFFFFFF) {
handle = 'U';
length = 8;
} else {
throw new YAMLException('code point within a string may not be greater than 0xFFFFFFFF');
}
return '\\' + handle + common.repeat('0', length - string.length) + string;
}
function State(options) {
this.schema = options['schema'] || DEFAULT_FULL_SCHEMA;
this.indent = Math.max(1, (options['indent'] || 2));
this.noArrayIndent = options['noArrayIndent'] || false;
this.skipInvalid = options['skipInvalid'] || false;
this.flowLevel = (common.isNothing(options['flowLevel']) ? -1 : options['flowLevel']);
this.styleMap = compileStyleMap(this.schema, options['styles'] || null);
this.sortKeys = options['sortKeys'] || false;
this.lineWidth = options['lineWidth'] || 80;
this.noRefs = options['noRefs'] || false;
this.noCompatMode = options['noCompatMode'] || false;
this.condenseFlow = options['condenseFlow'] || false;
this.implicitTypes = this.schema.compiledImplicit;
this.explicitTypes = this.schema.compiledExplicit;
this.tag = null;
this.result = '';
this.duplicates = [];
this.usedDuplicates = null;
}
// Indents every line in a string. Empty lines (\n only) are not indented.
function indentString(string, spaces) {
var ind = common.repeat(' ', spaces),
position = 0,
next = -1,
result = '',
line,
length = string.length;
while (position < length) {
next = string.indexOf('\n', position);
if (next === -1) {
line = string.slice(position);
position = length;
} else {
line = string.slice(position, next + 1);
position = next + 1;
}
if (line.length && line !== '\n') result += ind;
result += line;
}
return result;
}
function generateNextLine(state, level) {
return '\n' + common.repeat(' ', state.indent * level);
}
function testImplicitResolving(state, str) {
var index, length, type;
for (index = 0, length = state.implicitTypes.length; index < length; index += 1) {
type = state.implicitTypes[index];
if (type.resolve(str)) {
return true;
}
}
return false;
}
// [33] s-white ::= s-space | s-tab
function isWhitespace(c) {
return c === CHAR_SPACE || c === CHAR_TAB;
}
// Returns true if the character can be printed without escaping.
// From YAML 1.2: "any allowed characters known to be non-printable
// should also be escaped. [However,] This isnt mandatory"
// Derived from nb-char - \t - #x85 - #xA0 - #x2028 - #x2029.
function isPrintable(c) {
return (0x00020 <= c && c <= 0x00007E)
|| ((0x000A1 <= c && c <= 0x00D7FF) && c !== 0x2028 && c !== 0x2029)
|| ((0x0E000 <= c && c <= 0x00FFFD) && c !== 0xFEFF /* BOM */)
|| (0x10000 <= c && c <= 0x10FFFF);
}
// [34] ns-char ::= nb-char - s-white
// [27] nb-char ::= c-printable - b-char - c-byte-order-mark
// [26] b-char ::= b-line-feed | b-carriage-return
// [24] b-line-feed ::= #xA /* LF */
// [25] b-carriage-return ::= #xD /* CR */
// [3] c-byte-order-mark ::= #xFEFF
function isNsChar(c) {
return isPrintable(c) && !isWhitespace(c)
// byte-order-mark
&& c !== 0xFEFF
// b-char
&& c !== CHAR_CARRIAGE_RETURN
&& c !== CHAR_LINE_FEED;
}
// Simplified test for values allowed after the first character in plain style.
function isPlainSafe(c, prev) {
// Uses a subset of nb-char - c-flow-indicator - ":" - "#"
// where nb-char ::= c-printable - b-char - c-byte-order-mark.
return isPrintable(c) && c !== 0xFEFF
// - c-flow-indicator
&& c !== CHAR_COMMA
&& c !== CHAR_LEFT_SQUARE_BRACKET
&& c !== CHAR_RIGHT_SQUARE_BRACKET
&& c !== CHAR_LEFT_CURLY_BRACKET
&& c !== CHAR_RIGHT_CURLY_BRACKET
// - ":" - "#"
// /* An ns-char preceding */ "#"
&& c !== CHAR_COLON
&& ((c !== CHAR_SHARP) || (prev && isNsChar(prev)));
}
// Simplified test for values allowed as the first character in plain style.
function isPlainSafeFirst(c) {
// Uses a subset of ns-char - c-indicator
// where ns-char = nb-char - s-white.
return isPrintable(c) && c !== 0xFEFF
&& !isWhitespace(c) // - s-white
// - (c-indicator ::=
// “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}”
&& c !== CHAR_MINUS
&& c !== CHAR_QUESTION
&& c !== CHAR_COLON
&& c !== CHAR_COMMA
&& c !== CHAR_LEFT_SQUARE_BRACKET
&& c !== CHAR_RIGHT_SQUARE_BRACKET
&& c !== CHAR_LEFT_CURLY_BRACKET
&& c !== CHAR_RIGHT_CURLY_BRACKET
// | “#” | “&” | “*” | “!” | “|” | “=” | “>” | “'” | “"”
&& c !== CHAR_SHARP
&& c !== CHAR_AMPERSAND
&& c !== CHAR_ASTERISK
&& c !== CHAR_EXCLAMATION
&& c !== CHAR_VERTICAL_LINE
&& c !== CHAR_EQUALS
&& c !== CHAR_GREATER_THAN
&& c !== CHAR_SINGLE_QUOTE
&& c !== CHAR_DOUBLE_QUOTE
// | “%” | “@” | “`”)
&& c !== CHAR_PERCENT
&& c !== CHAR_COMMERCIAL_AT
&& c !== CHAR_GRAVE_ACCENT;
}
// Determines whether block indentation indicator is required.
function needIndentIndicator(string) {
var leadingSpaceRe = /^\n* /;
return leadingSpaceRe.test(string);
}
var STYLE_PLAIN = 1,
STYLE_SINGLE = 2,
STYLE_LITERAL = 3,
STYLE_FOLDED = 4,
STYLE_DOUBLE = 5;
// Determines which scalar styles are possible and returns the preferred style.
// lineWidth = -1 => no limit.
// Pre-conditions: str.length > 0.
// Post-conditions:
// STYLE_PLAIN or STYLE_SINGLE => no \n are in the string.
// STYLE_LITERAL => no lines are suitable for folding (or lineWidth is -1).
// STYLE_FOLDED => a line > lineWidth and can be folded (and lineWidth != -1).
function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, testAmbiguousType) {
var i;
var char, prev_char;
var hasLineBreak = false;
var hasFoldableLine = false; // only checked if shouldTrackWidth
var shouldTrackWidth = lineWidth !== -1;
var previousLineBreak = -1; // count the first line correctly
var plain = isPlainSafeFirst(string.charCodeAt(0))
&& !isWhitespace(string.charCodeAt(string.length - 1));
if (singleLineOnly) {
// Case: no block styles.
// Check for disallowed characters to rule out plain and single.
for (i = 0; i < string.length; i++) {
char = string.charCodeAt(i);
if (!isPrintable(char)) {
return STYLE_DOUBLE;
}
prev_char = i > 0 ? string.charCodeAt(i - 1) : null;
plain = plain && isPlainSafe(char, prev_char);
}
} else {
// Case: block styles permitted.
for (i = 0; i < string.length; i++) {
char = string.charCodeAt(i);
if (char === CHAR_LINE_FEED) {
hasLineBreak = true;
// Check if any line can be folded.
if (shouldTrackWidth) {
hasFoldableLine = hasFoldableLine ||
// Foldable line = too long, and not more-indented.
(i - previousLineBreak - 1 > lineWidth &&
string[previousLineBreak + 1] !== ' ');
previousLineBreak = i;
}
} else if (!isPrintable(char)) {
return STYLE_DOUBLE;
}
prev_char = i > 0 ? string.charCodeAt(i - 1) : null;
plain = plain && isPlainSafe(char, prev_char);
}
// in case the end is missing a \n
hasFoldableLine = hasFoldableLine || (shouldTrackWidth &&
(i - previousLineBreak - 1 > lineWidth &&
string[previousLineBreak + 1] !== ' '));
}
// Although every style can represent \n without escaping, prefer block styles
// for multiline, since they're more readable and they don't add empty lines.
// Also prefer folding a super-long line.
if (!hasLineBreak && !hasFoldableLine) {
// Strings interpretable as another type have to be quoted;
// e.g. the string 'true' vs. the boolean true.
return plain && !testAmbiguousType(string)
? STYLE_PLAIN : STYLE_SINGLE;
}
// Edge case: block indentation indicator can only have one digit.
if (indentPerLevel > 9 && needIndentIndicator(string)) {
return STYLE_DOUBLE;
}
// At this point we know block styles are valid.
// Prefer literal style unless we want to fold.
return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL;
}
// Note: line breaking/folding is implemented for only the folded style.
// NB. We drop the last trailing newline (if any) of a returned block scalar
// since the dumper adds its own newline. This always works:
// • No ending newline => unaffected; already using strip "-" chomping.
// • Ending newline => removed then restored.
// Importantly, this keeps the "+" chomp indicator from gaining an extra line.
function writeScalar(state, string, level, iskey) {
state.dump = (function () {
if (string.length === 0) {
return "''";
}
if (!state.noCompatMode &&
DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1) {
return "'" + string + "'";
}
var indent = state.indent * Math.max(1, level); // no 0-indent scalars
// As indentation gets deeper, let the width decrease monotonically
// to the lower bound min(state.lineWidth, 40).
// Note that this implies
// state.lineWidth ≤ 40 + state.indent: width is fixed at the lower bound.
// state.lineWidth > 40 + state.indent: width decreases until the lower bound.
// This behaves better than a constant minimum width which disallows narrower options,
// or an indent threshold which causes the width to suddenly increase.
var lineWidth = state.lineWidth === -1
? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent);
// Without knowing if keys are implicit/explicit, assume implicit for safety.
var singleLineOnly = iskey
// No block styles in flow mode.
|| (state.flowLevel > -1 && level >= state.flowLevel);
function testAmbiguity(string) {
return testImplicitResolving(state, string);
}
switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth, testAmbiguity)) {
case STYLE_PLAIN:
return string;
case STYLE_SINGLE:
return "'" + string.replace(/'/g, "''") + "'";
case STYLE_LITERAL:
return '|' + blockHeader(string, state.indent)
+ dropEndingNewline(indentString(string, indent));
case STYLE_FOLDED:
return '>' + blockHeader(string, state.indent)
+ dropEndingNewline(indentString(foldString(string, lineWidth), indent));
case STYLE_DOUBLE:
return '"' + escapeString(string, lineWidth) + '"';
default:
throw new YAMLException('impossible error: invalid scalar style');
}
}());
}
// Pre-conditions: string is valid for a block scalar, 1 <= indentPerLevel <= 9.
function blockHeader(string, indentPerLevel) {
var indentIndicator = needIndentIndicator(string) ? String(indentPerLevel) : '';
// note the special case: the string '\n' counts as a "trailing" empty line.
var clip = string[string.length - 1] === '\n';
var keep = clip && (string[string.length - 2] === '\n' || string === '\n');
var chomp = keep ? '+' : (clip ? '' : '-');
return indentIndicator + chomp + '\n';
}
// (See the note for writeScalar.)
function dropEndingNewline(string) {
return string[string.length - 1] === '\n' ? string.slice(0, -1) : string;
}
// Note: a long line without a suitable break point will exceed the width limit.
// Pre-conditions: every char in str isPrintable, str.length > 0, width > 0.
function foldString(string, width) {
// In folded style, $k$ consecutive newlines output as $k+1$ newlines—
// unless they're before or after a more-indented line, or at the very
// beginning or end, in which case $k$ maps to $k$.
// Therefore, parse each chunk as newline(s) followed by a content line.
var lineRe = /(\n+)([^\n]*)/g;
// first line (possibly an empty line)
var result = (function () {
var nextLF = string.indexOf('\n');
nextLF = nextLF !== -1 ? nextLF : string.length;
lineRe.lastIndex = nextLF;
return foldLine(string.slice(0, nextLF), width);
}());
// If we haven't reached the first content line yet, don't add an extra \n.
var prevMoreIndented = string[0] === '\n' || string[0] === ' ';
var moreIndented;
// rest of the lines
var match;
while ((match = lineRe.exec(string))) {
var prefix = match[1], line = match[2];
moreIndented = (line[0] === ' ');
result += prefix
+ (!prevMoreIndented && !moreIndented && line !== ''
? '\n' : '')
+ foldLine(line, width);
prevMoreIndented = moreIndented;
}
return result;
}
// Greedy line breaking.
// Picks the longest line under the limit each time,
// otherwise settles for the shortest line over the limit.
// NB. More-indented lines *cannot* be folded, as that would add an extra \n.
function foldLine(line, width) {
if (line === '' || line[0] === ' ') return line;
// Since a more-indented line adds a \n, breaks can't be followed by a space.
var breakRe = / [^ ]/g; // note: the match index will always be <= length-2.
var match;
// start is an inclusive index. end, curr, and next are exclusive.
var start = 0, end, curr = 0, next = 0;
var result = '';
// Invariants: 0 <= start <= length-1.
// 0 <= curr <= next <= max(0, length-2). curr - start <= width.
// Inside the loop:
// A match implies length >= 2, so curr and next are <= length-2.
while ((match = breakRe.exec(line))) {
next = match.index;
// maintain invariant: curr - start <= width
if (next - start > width) {
end = (curr > start) ? curr : next; // derive end <= length-2
result += '\n' + line.slice(start, end);
// skip the space that was output as \n
start = end + 1; // derive start <= length-1
}
curr = next;
}
// By the invariants, start <= length-1, so there is something left over.
// It is either the whole string or a part starting from non-whitespace.
result += '\n';
// Insert a break if the remainder is too long and there is a break available.
if (line.length - start > width && curr > start) {
result += line.slice(start, curr) + '\n' + line.slice(curr + 1);
} else {
result += line.slice(start);
}
return result.slice(1); // drop extra \n joiner
}
// Escapes a double-quoted string.
function escapeString(string) {
var result = '';
var char, nextChar;
var escapeSeq;
for (var i = 0; i < string.length; i++) {
char = string.charCodeAt(i);
// Check for surrogate pairs (reference Unicode 3.0 section "3.7 Surrogates").
if (char >= 0xD800 && char <= 0xDBFF/* high surrogate */) {
nextChar = string.charCodeAt(i + 1);
if (nextChar >= 0xDC00 && nextChar <= 0xDFFF/* low surrogate */) {
// Combine the surrogate pair and store it escaped.
result += encodeHex((char - 0xD800) * 0x400 + nextChar - 0xDC00 + 0x10000);
// Advance index one extra since we already used that char here.
i++; continue;
}
}
escapeSeq = ESCAPE_SEQUENCES[char];
result += !escapeSeq && isPrintable(char)
? string[i]
: escapeSeq || encodeHex(char);
}
return result;
}
function writeFlowSequence(state, level, object) {
var _result = '',
_tag = state.tag,
index,
length;
for (index = 0, length = object.length; index < length; index += 1) {
// Write only valid elements.
if (writeNode(state, level, object[index], false, false)) {
if (index !== 0) _result += ',' + (!state.condenseFlow ? ' ' : '');
_result += state.dump;
}
}
state.tag = _tag;
state.dump = '[' + _result + ']';
}
function writeBlockSequence(state, level, object, compact) {
var _result = '',
_tag = state.tag,
index,
length;
for (index = 0, length = object.length; index < length; index += 1) {
// Write only valid elements.
if (writeNode(state, level + 1, object[index], true, true)) {
if (!compact || index !== 0) {
_result += generateNextLine(state, level);
}
if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
_result += '-';
} else {
_result += '- ';
}
_result += state.dump;
}
}
state.tag = _tag;
state.dump = _result || '[]'; // Empty sequence if no valid values.
}
function writeFlowMapping(state, level, object) {
var _result = '',
_tag = state.tag,
objectKeyList = Object.keys(object),
index,
length,
objectKey,
objectValue,
pairBuffer;
for (index = 0, length = objectKeyList.length; index < length; index += 1) {
pairBuffer = '';
if (index !== 0) pairBuffer += ', ';
if (state.condenseFlow) pairBuffer += '"';
objectKey = objectKeyList[index];
objectValue = object[objectKey];
if (!writeNode(state, level, objectKey, false, false)) {
continue; // Skip this pair because of invalid key;
}
if (state.dump.length > 1024) pairBuffer += '? ';
pairBuffer += state.dump + (state.condenseFlow ? '"' : '') + ':' + (state.condenseFlow ? '' : ' ');
if (!writeNode(state, level, objectValue, false, false)) {
continue; // Skip this pair because of invalid value.
}
pairBuffer += state.dump;
// Both key and value are valid.
_result += pairBuffer;
}
state.tag = _tag;
state.dump = '{' + _result + '}';
}
function writeBlockMapping(state, level, object, compact) {
var _result = '',
_tag = state.tag,
objectKeyList = Object.keys(object),
index,
length,
objectKey,
objectValue,
explicitPair,
pairBuffer;
// Allow sorting keys so that the output file is deterministic
if (state.sortKeys === true) {
// Default sorting
objectKeyList.sort();
} else if (typeof state.sortKeys === 'function') {
// Custom sort function
objectKeyList.sort(state.sortKeys);
} else if (state.sortKeys) {
// Something is wrong
throw new YAMLException('sortKeys must be a boolean or a function');
}
for (index = 0, length = objectKeyList.length; index < length; index += 1) {
pairBuffer = '';
if (!compact || index !== 0) {
pairBuffer += generateNextLine(state, level);
}
objectKey = objectKeyList[index];
objectValue = object[objectKey];
if (!writeNode(state, level + 1, objectKey, true, true, true)) {
continue; // Skip this pair because of invalid key.
}
explicitPair = (state.tag !== null && state.tag !== '?') ||
(state.dump && state.dump.length > 1024);
if (explicitPair) {
if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
pairBuffer += '?';
} else {
pairBuffer += '? ';
}
}
pairBuffer += state.dump;
if (explicitPair) {
pairBuffer += generateNextLine(state, level);
}
if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {
continue; // Skip this pair because of invalid value.
}
if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
pairBuffer += ':';
} else {
pairBuffer += ': ';
}
pairBuffer += state.dump;
// Both key and value are valid.
_result += pairBuffer;
}
state.tag = _tag;
state.dump = _result || '{}'; // Empty mapping if no valid pairs.
}
function detectType(state, object, explicit) {
var _result, typeList, index, length, type, style;
typeList = explicit ? state.explicitTypes : state.implicitTypes;
for (index = 0, length = typeList.length; index < length; index += 1) {
type = typeList[index];
if ((type.instanceOf || type.predicate) &&
(!type.instanceOf || ((typeof object === 'object') && (object instanceof type.instanceOf))) &&
(!type.predicate || type.predicate(object))) {
state.tag = explicit ? type.tag : '?';
if (type.represent) {
style = state.styleMap[type.tag] || type.defaultStyle;
if (_toString.call(type.represent) === '[object Function]') {
_result = type.represent(object, style);
} else if (_hasOwnProperty.call(type.represent, style)) {
_result = type.represent[style](object, style);
} else {
throw new YAMLException('!<' + type.tag + '> tag resolver accepts not "' + style + '" style');
}
state.dump = _result;
}
return true;
}
}
return false;
}
// Serializes `object` and writes it to global `result`.
// Returns true on success, or false on invalid object.
//
function writeNode(state, level, object, block, compact, iskey) {
state.tag = null;
state.dump = object;
if (!detectType(state, object, false)) {
detectType(state, object, true);
}
var type = _toString.call(state.dump);
if (block) {
block = (state.flowLevel < 0 || state.flowLevel > level);
}
var objectOrArray = type === '[object Object]' || type === '[object Array]',
duplicateIndex,
duplicate;
if (objectOrArray) {
duplicateIndex = state.duplicates.indexOf(object);
duplicate = duplicateIndex !== -1;
}
if ((state.tag !== null && state.tag !== '?') || duplicate || (state.indent !== 2 && level > 0)) {
compact = false;
}
if (duplicate && state.usedDuplicates[duplicateIndex]) {
state.dump = '*ref_' + duplicateIndex;
} else {
if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {
state.usedDuplicates[duplicateIndex] = true;
}
if (type === '[object Object]') {
if (block && (Object.keys(state.dump).length !== 0)) {
writeBlockMapping(state, level, state.dump, compact);
if (duplicate) {
state.dump = '&ref_' + duplicateIndex + state.dump;
}
} else {
writeFlowMapping(state, level, state.dump);
if (duplicate) {
state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
}
}
} else if (type === '[object Array]') {
var arrayLevel = (state.noArrayIndent && (level > 0)) ? level - 1 : level;
if (block && (state.dump.length !== 0)) {
writeBlockSequence(state, arrayLevel, state.dump, compact);
if (duplicate) {
state.dump = '&ref_' + duplicateIndex + state.dump;
}
} else {
writeFlowSequence(state, arrayLevel, state.dump);
if (duplicate) {
state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;
}
}
} else if (type === '[object String]') {
if (state.tag !== '?') {
writeScalar(state, state.dump, level, iskey);
}
} else {
if (state.skipInvalid) return false;
throw new YAMLException('unacceptable kind of an object to dump ' + type);
}
if (state.tag !== null && state.tag !== '?') {
state.dump = '!<' + state.tag + '> ' + state.dump;
}
}
return true;
}
function getDuplicateReferences(object, state) {
var objects = [],
duplicatesIndexes = [],
index,
length;
inspectNode(object, objects, duplicatesIndexes);
for (index = 0, length = duplicatesIndexes.length; index < length; index += 1) {
state.duplicates.push(objects[duplicatesIndexes[index]]);
}
state.usedDuplicates = new Array(length);
}
function inspectNode(object, objects, duplicatesIndexes) {
var objectKeyList,
index,
length;
if (object !== null && typeof object === 'object') {
index = objects.indexOf(object);
if (index !== -1) {
if (duplicatesIndexes.indexOf(index) === -1) {
duplicatesIndexes.push(index);
}
} else {
objects.push(object);
if (Array.isArray(object)) {
for (index = 0, length = object.length; index < length; index += 1) {
inspectNode(object[index], objects, duplicatesIndexes);
}
} else {
objectKeyList = Object.keys(object);
for (index = 0, length = objectKeyList.length; index < length; index += 1) {
inspectNode(object[objectKeyList[index]], objects, duplicatesIndexes);
}
}
}
}
}
function dump(input, options) {
options = options || {};
var state = new State(options);
if (!state.noRefs) getDuplicateReferences(input, state);
if (writeNode(state, 0, input, true, true)) return state.dump + '\n';
return '';
}
function safeDump(input, options) {
return dump(input, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options));
}
module.exports.dump = dump;
module.exports.safeDump = safeDump;

View file

@ -1,43 +0,0 @@
// YAML error class. http://stackoverflow.com/questions/8458984
//
'use strict';
function YAMLException(reason, mark) {
// Super constructor
Error.call(this);
this.name = 'YAMLException';
this.reason = reason;
this.mark = mark;
this.message = (this.reason || '(unknown reason)') + (this.mark ? ' ' + this.mark.toString() : '');
// Include stack trace in error object
if (Error.captureStackTrace) {
// Chrome and NodeJS
Error.captureStackTrace(this, this.constructor);
} else {
// FF, IE 10+ and Safari 6+. Fallback for others
this.stack = (new Error()).stack || '';
}
}
// Inherit from Error
YAMLException.prototype = Object.create(Error.prototype);
YAMLException.prototype.constructor = YAMLException;
YAMLException.prototype.toString = function toString(compact) {
var result = this.name + ': ';
result += this.reason || '(unknown reason)';
if (!compact && this.mark) {
result += ' ' + this.mark.toString();
}
return result;
};
module.exports = YAMLException;

File diff suppressed because it is too large Load diff

View file

@ -1,76 +0,0 @@
'use strict';
var common = require('./common');
function Mark(name, buffer, position, line, column) {
this.name = name;
this.buffer = buffer;
this.position = position;
this.line = line;
this.column = column;
}
Mark.prototype.getSnippet = function getSnippet(indent, maxLength) {
var head, start, tail, end, snippet;
if (!this.buffer) return null;
indent = indent || 4;
maxLength = maxLength || 75;
head = '';
start = this.position;
while (start > 0 && '\x00\r\n\x85\u2028\u2029'.indexOf(this.buffer.charAt(start - 1)) === -1) {
start -= 1;
if (this.position - start > (maxLength / 2 - 1)) {
head = ' ... ';
start += 5;
break;
}
}
tail = '';
end = this.position;
while (end < this.buffer.length && '\x00\r\n\x85\u2028\u2029'.indexOf(this.buffer.charAt(end)) === -1) {
end += 1;
if (end - this.position > (maxLength / 2 - 1)) {
tail = ' ... ';
end -= 5;
break;
}
}
snippet = this.buffer.slice(start, end);
return common.repeat(' ', indent) + head + snippet + tail + '\n' +
common.repeat(' ', indent + this.position - start + head.length) + '^';
};
Mark.prototype.toString = function toString(compact) {
var snippet, where = '';
if (this.name) {
where += 'in "' + this.name + '" ';
}
where += 'at line ' + (this.line + 1) + ', column ' + (this.column + 1);
if (!compact) {
snippet = this.getSnippet();
if (snippet) {
where += ':\n' + snippet;
}
}
return where;
};
module.exports = Mark;

View file

@ -1,108 +0,0 @@
'use strict';
/*eslint-disable max-len*/
var common = require('./common');
var YAMLException = require('./exception');
var Type = require('./type');
function compileList(schema, name, result) {
var exclude = [];
schema.include.forEach(function (includedSchema) {
result = compileList(includedSchema, name, result);
});
schema[name].forEach(function (currentType) {
result.forEach(function (previousType, previousIndex) {
if (previousType.tag === currentType.tag && previousType.kind === currentType.kind) {
exclude.push(previousIndex);
}
});
result.push(currentType);
});
return result.filter(function (type, index) {
return exclude.indexOf(index) === -1;
});
}
function compileMap(/* lists... */) {
var result = {
scalar: {},
sequence: {},
mapping: {},
fallback: {}
}, index, length;
function collectType(type) {
result[type.kind][type.tag] = result['fallback'][type.tag] = type;
}
for (index = 0, length = arguments.length; index < length; index += 1) {
arguments[index].forEach(collectType);
}
return result;
}
function Schema(definition) {
this.include = definition.include || [];
this.implicit = definition.implicit || [];
this.explicit = definition.explicit || [];
this.implicit.forEach(function (type) {
if (type.loadKind && type.loadKind !== 'scalar') {
throw new YAMLException('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.');
}
});
this.compiledImplicit = compileList(this, 'implicit', []);
this.compiledExplicit = compileList(this, 'explicit', []);
this.compiledTypeMap = compileMap(this.compiledImplicit, this.compiledExplicit);
}
Schema.DEFAULT = null;
Schema.create = function createSchema() {
var schemas, types;
switch (arguments.length) {
case 1:
schemas = Schema.DEFAULT;
types = arguments[0];
break;
case 2:
schemas = arguments[0];
types = arguments[1];
break;
default:
throw new YAMLException('Wrong number of arguments for Schema.create function');
}
schemas = common.toArray(schemas);
types = common.toArray(types);
if (!schemas.every(function (schema) { return schema instanceof Schema; })) {
throw new YAMLException('Specified list of super schemas (or a single Schema object) contains a non-Schema object.');
}
if (!types.every(function (type) { return type instanceof Type; })) {
throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.');
}
return new Schema({
include: schemas,
explicit: types
});
};
module.exports = Schema;

View file

@ -1,18 +0,0 @@
// Standard YAML's Core schema.
// http://www.yaml.org/spec/1.2/spec.html#id2804923
//
// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.
// So, Core schema has no distinctions from JSON schema is JS-YAML.
'use strict';
var Schema = require('../schema');
module.exports = new Schema({
include: [
require('./json')
]
});

View file

@ -1,25 +0,0 @@
// JS-YAML's default schema for `load` function.
// It is not described in the YAML specification.
//
// This schema is based on JS-YAML's default safe schema and includes
// JavaScript-specific types: !!js/undefined, !!js/regexp and !!js/function.
//
// Also this schema is used as default base schema at `Schema.create` function.
'use strict';
var Schema = require('../schema');
module.exports = Schema.DEFAULT = new Schema({
include: [
require('./default_safe')
],
explicit: [
require('../type/js/undefined'),
require('../type/js/regexp'),
require('../type/js/function')
]
});

View file

@ -1,28 +0,0 @@
// JS-YAML's default schema for `safeLoad` function.
// It is not described in the YAML specification.
//
// This schema is based on standard YAML's Core schema and includes most of
// extra types described at YAML tag repository. (http://yaml.org/type/)
'use strict';
var Schema = require('../schema');
module.exports = new Schema({
include: [
require('./core')
],
implicit: [
require('../type/timestamp'),
require('../type/merge')
],
explicit: [
require('../type/binary'),
require('../type/omap'),
require('../type/pairs'),
require('../type/set')
]
});

View file

@ -1,17 +0,0 @@
// Standard YAML's Failsafe schema.
// http://www.yaml.org/spec/1.2/spec.html#id2802346
'use strict';
var Schema = require('../schema');
module.exports = new Schema({
explicit: [
require('../type/str'),
require('../type/seq'),
require('../type/map')
]
});

View file

@ -1,25 +0,0 @@
// Standard YAML's JSON schema.
// http://www.yaml.org/spec/1.2/spec.html#id2803231
//
// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.
// So, this schema is not such strict as defined in the YAML specification.
// It allows numbers in binary notaion, use `Null` and `NULL` as `null`, etc.
'use strict';
var Schema = require('../schema');
module.exports = new Schema({
include: [
require('./failsafe')
],
implicit: [
require('../type/null'),
require('../type/bool'),
require('../type/int'),
require('../type/float')
]
});

Some files were not shown because too many files have changed in this diff Show more