replace jest with ava
This commit is contained in:
parent
27cc8b23fe
commit
0347b72305
11775 changed files with 84546 additions and 1440575 deletions
104
node_modules/braces/lib/braces.js
generated
vendored
104
node_modules/braces/lib/braces.js
generated
vendored
|
|
@ -1,104 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var extend = require('extend-shallow');
|
||||
var Snapdragon = require('snapdragon');
|
||||
var compilers = require('./compilers');
|
||||
var parsers = require('./parsers');
|
||||
var utils = require('./utils');
|
||||
|
||||
/**
|
||||
* Customize Snapdragon parser and renderer
|
||||
*/
|
||||
|
||||
function Braces(options) {
|
||||
this.options = extend({}, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize braces
|
||||
*/
|
||||
|
||||
Braces.prototype.init = function(options) {
|
||||
if (this.isInitialized) return;
|
||||
this.isInitialized = true;
|
||||
var opts = utils.createOptions({}, this.options, options);
|
||||
this.snapdragon = this.options.snapdragon || new Snapdragon(opts);
|
||||
this.compiler = this.snapdragon.compiler;
|
||||
this.parser = this.snapdragon.parser;
|
||||
|
||||
compilers(this.snapdragon, opts);
|
||||
parsers(this.snapdragon, opts);
|
||||
|
||||
/**
|
||||
* Call Snapdragon `.parse` method. When AST is returned, we check to
|
||||
* see if any unclosed braces are left on the stack and, if so, we iterate
|
||||
* over the stack and correct the AST so that compilers are called in the correct
|
||||
* order and unbalance braces are properly escaped.
|
||||
*/
|
||||
|
||||
utils.define(this.snapdragon, 'parse', function(pattern, options) {
|
||||
var parsed = Snapdragon.prototype.parse.apply(this, arguments);
|
||||
this.parser.ast.input = pattern;
|
||||
|
||||
var stack = this.parser.stack;
|
||||
while (stack.length) {
|
||||
addParent({type: 'brace.close', val: ''}, stack.pop());
|
||||
}
|
||||
|
||||
function addParent(node, parent) {
|
||||
utils.define(node, 'parent', parent);
|
||||
parent.nodes.push(node);
|
||||
}
|
||||
|
||||
// add non-enumerable parser reference
|
||||
utils.define(parsed, 'parser', this.parser);
|
||||
return parsed;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Decorate `.parse` method
|
||||
*/
|
||||
|
||||
Braces.prototype.parse = function(ast, options) {
|
||||
if (ast && typeof ast === 'object' && ast.nodes) return ast;
|
||||
this.init(options);
|
||||
return this.snapdragon.parse(ast, options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Decorate `.compile` method
|
||||
*/
|
||||
|
||||
Braces.prototype.compile = function(ast, options) {
|
||||
if (typeof ast === 'string') {
|
||||
ast = this.parse(ast, options);
|
||||
} else {
|
||||
this.init(options);
|
||||
}
|
||||
return this.snapdragon.compile(ast, options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Expand
|
||||
*/
|
||||
|
||||
Braces.prototype.expand = function(pattern) {
|
||||
var ast = this.parse(pattern, {expand: true});
|
||||
return this.compile(ast, {expand: true});
|
||||
};
|
||||
|
||||
/**
|
||||
* Optimize
|
||||
*/
|
||||
|
||||
Braces.prototype.optimize = function(pattern) {
|
||||
var ast = this.parse(pattern, {optimize: true});
|
||||
return this.compile(ast, {optimize: true});
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose `Braces`
|
||||
*/
|
||||
|
||||
module.exports = Braces;
|
||||
57
node_modules/braces/lib/compile.js
generated
vendored
Normal file
57
node_modules/braces/lib/compile.js
generated
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
'use strict';
|
||||
|
||||
const fill = require('fill-range');
|
||||
const utils = require('./utils');
|
||||
|
||||
const compile = (ast, options = {}) => {
|
||||
let walk = (node, parent = {}) => {
|
||||
let invalidBlock = utils.isInvalidBrace(parent);
|
||||
let invalidNode = node.invalid === true && options.escapeInvalid === true;
|
||||
let invalid = invalidBlock === true || invalidNode === true;
|
||||
let prefix = options.escapeInvalid === true ? '\\' : '';
|
||||
let output = '';
|
||||
|
||||
if (node.isOpen === true) {
|
||||
return prefix + node.value;
|
||||
}
|
||||
if (node.isClose === true) {
|
||||
return prefix + node.value;
|
||||
}
|
||||
|
||||
if (node.type === 'open') {
|
||||
return invalid ? (prefix + node.value) : '(';
|
||||
}
|
||||
|
||||
if (node.type === 'close') {
|
||||
return invalid ? (prefix + node.value) : ')';
|
||||
}
|
||||
|
||||
if (node.type === 'comma') {
|
||||
return node.prev.type === 'comma' ? '' : (invalid ? node.value : '|');
|
||||
}
|
||||
|
||||
if (node.value) {
|
||||
return node.value;
|
||||
}
|
||||
|
||||
if (node.nodes && node.ranges > 0) {
|
||||
let args = utils.reduce(node.nodes);
|
||||
let range = fill(...args, { ...options, wrap: false, toRegex: true });
|
||||
|
||||
if (range.length !== 0) {
|
||||
return args.length > 1 && range.length > 1 ? `(${range})` : range;
|
||||
}
|
||||
}
|
||||
|
||||
if (node.nodes) {
|
||||
for (let child of node.nodes) {
|
||||
output += walk(child, node);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
};
|
||||
|
||||
return walk(ast);
|
||||
};
|
||||
|
||||
module.exports = compile;
|
||||
282
node_modules/braces/lib/compilers.js
generated
vendored
282
node_modules/braces/lib/compilers.js
generated
vendored
|
|
@ -1,282 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var utils = require('./utils');
|
||||
|
||||
module.exports = function(braces, options) {
|
||||
braces.compiler
|
||||
|
||||
/**
|
||||
* bos
|
||||
*/
|
||||
|
||||
.set('bos', function() {
|
||||
if (this.output) return;
|
||||
this.ast.queue = isEscaped(this.ast) ? [this.ast.val] : [];
|
||||
this.ast.count = 1;
|
||||
})
|
||||
|
||||
/**
|
||||
* Square brackets
|
||||
*/
|
||||
|
||||
.set('bracket', function(node) {
|
||||
var close = node.close;
|
||||
var open = !node.escaped ? '[' : '\\[';
|
||||
var negated = node.negated;
|
||||
var inner = node.inner;
|
||||
|
||||
inner = inner.replace(/\\(?=[\\\w]|$)/g, '\\\\');
|
||||
if (inner === ']-') {
|
||||
inner = '\\]\\-';
|
||||
}
|
||||
|
||||
if (negated && inner.indexOf('.') === -1) {
|
||||
inner += '.';
|
||||
}
|
||||
if (negated && inner.indexOf('/') === -1) {
|
||||
inner += '/';
|
||||
}
|
||||
|
||||
var val = open + negated + inner + close;
|
||||
var queue = node.parent.queue;
|
||||
var last = utils.arrayify(queue.pop());
|
||||
|
||||
queue.push(utils.join(last, val));
|
||||
queue.push.apply(queue, []);
|
||||
})
|
||||
|
||||
/**
|
||||
* Brace
|
||||
*/
|
||||
|
||||
.set('brace', function(node) {
|
||||
node.queue = isEscaped(node) ? [node.val] : [];
|
||||
node.count = 1;
|
||||
return this.mapVisit(node.nodes);
|
||||
})
|
||||
|
||||
/**
|
||||
* Open
|
||||
*/
|
||||
|
||||
.set('brace.open', function(node) {
|
||||
node.parent.open = node.val;
|
||||
})
|
||||
|
||||
/**
|
||||
* Inner
|
||||
*/
|
||||
|
||||
.set('text', function(node) {
|
||||
var queue = node.parent.queue;
|
||||
var escaped = node.escaped;
|
||||
var segs = [node.val];
|
||||
|
||||
if (node.optimize === false) {
|
||||
options = utils.extend({}, options, {optimize: false});
|
||||
}
|
||||
|
||||
if (node.multiplier > 1) {
|
||||
node.parent.count *= node.multiplier;
|
||||
}
|
||||
|
||||
if (options.quantifiers === true && utils.isQuantifier(node.val)) {
|
||||
escaped = true;
|
||||
|
||||
} else if (node.val.length > 1) {
|
||||
if (isType(node.parent, 'brace') && !isEscaped(node)) {
|
||||
var expanded = utils.expand(node.val, options);
|
||||
segs = expanded.segs;
|
||||
|
||||
if (expanded.isOptimized) {
|
||||
node.parent.isOptimized = true;
|
||||
}
|
||||
|
||||
// if nothing was expanded, we probably have a literal brace
|
||||
if (!segs.length) {
|
||||
var val = (expanded.val || node.val);
|
||||
if (options.unescape !== false) {
|
||||
// unescape unexpanded brace sequence/set separators
|
||||
val = val.replace(/\\([,.])/g, '$1');
|
||||
// strip quotes
|
||||
val = val.replace(/["'`]/g, '');
|
||||
}
|
||||
|
||||
segs = [val];
|
||||
escaped = true;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (node.val === ',') {
|
||||
if (options.expand) {
|
||||
node.parent.queue.push(['']);
|
||||
segs = [''];
|
||||
} else {
|
||||
segs = ['|'];
|
||||
}
|
||||
} else {
|
||||
escaped = true;
|
||||
}
|
||||
|
||||
if (escaped && isType(node.parent, 'brace')) {
|
||||
if (node.parent.nodes.length <= 4 && node.parent.count === 1) {
|
||||
node.parent.escaped = true;
|
||||
} else if (node.parent.length <= 3) {
|
||||
node.parent.escaped = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasQueue(node.parent)) {
|
||||
node.parent.queue = segs;
|
||||
return;
|
||||
}
|
||||
|
||||
var last = utils.arrayify(queue.pop());
|
||||
if (node.parent.count > 1 && options.expand) {
|
||||
last = multiply(last, node.parent.count);
|
||||
node.parent.count = 1;
|
||||
}
|
||||
|
||||
queue.push(utils.join(utils.flatten(last), segs.shift()));
|
||||
queue.push.apply(queue, segs);
|
||||
})
|
||||
|
||||
/**
|
||||
* Close
|
||||
*/
|
||||
|
||||
.set('brace.close', function(node) {
|
||||
var queue = node.parent.queue;
|
||||
var prev = node.parent.parent;
|
||||
var last = prev.queue.pop();
|
||||
var open = node.parent.open;
|
||||
var close = node.val;
|
||||
|
||||
if (open && close && isOptimized(node, options)) {
|
||||
open = '(';
|
||||
close = ')';
|
||||
}
|
||||
|
||||
// if a close brace exists, and the previous segment is one character
|
||||
// don't wrap the result in braces or parens
|
||||
var ele = utils.last(queue);
|
||||
if (node.parent.count > 1 && options.expand) {
|
||||
ele = multiply(queue.pop(), node.parent.count);
|
||||
node.parent.count = 1;
|
||||
queue.push(ele);
|
||||
}
|
||||
|
||||
if (close && typeof ele === 'string' && ele.length === 1) {
|
||||
open = '';
|
||||
close = '';
|
||||
}
|
||||
|
||||
if ((isLiteralBrace(node, options) || noInner(node)) && !node.parent.hasEmpty) {
|
||||
queue.push(utils.join(open, queue.pop() || ''));
|
||||
queue = utils.flatten(utils.join(queue, close));
|
||||
}
|
||||
|
||||
if (typeof last === 'undefined') {
|
||||
prev.queue = [queue];
|
||||
} else {
|
||||
prev.queue.push(utils.flatten(utils.join(last, queue)));
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* eos
|
||||
*/
|
||||
|
||||
.set('eos', function(node) {
|
||||
if (this.input) return;
|
||||
|
||||
if (options.optimize !== false) {
|
||||
this.output = utils.last(utils.flatten(this.ast.queue));
|
||||
} else if (Array.isArray(utils.last(this.ast.queue))) {
|
||||
this.output = utils.flatten(this.ast.queue.pop());
|
||||
} else {
|
||||
this.output = utils.flatten(this.ast.queue);
|
||||
}
|
||||
|
||||
if (node.parent.count > 1 && options.expand) {
|
||||
this.output = multiply(this.output, node.parent.count);
|
||||
}
|
||||
|
||||
this.output = utils.arrayify(this.output);
|
||||
this.ast.queue = [];
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Multiply the segments in the current brace level
|
||||
*/
|
||||
|
||||
function multiply(queue, n, options) {
|
||||
return utils.flatten(utils.repeat(utils.arrayify(queue), n));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if `node` is escaped
|
||||
*/
|
||||
|
||||
function isEscaped(node) {
|
||||
return node.escaped === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if regex parens should be used for sets. If the parent `type`
|
||||
* is not `brace`, then we're on a root node, which means we should never
|
||||
* expand segments and open/close braces should be `{}` (since this indicates
|
||||
* a brace is missing from the set)
|
||||
*/
|
||||
|
||||
function isOptimized(node, options) {
|
||||
if (node.parent.isOptimized) return true;
|
||||
return isType(node.parent, 'brace')
|
||||
&& !isEscaped(node.parent)
|
||||
&& options.expand !== true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the value in `node` should be wrapped in a literal brace.
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
function isLiteralBrace(node, options) {
|
||||
return isEscaped(node.parent) || options.optimize !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given `node` does not have an inner value.
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
function noInner(node, type) {
|
||||
if (node.parent.queue.length === 1) {
|
||||
return true;
|
||||
}
|
||||
var nodes = node.parent.nodes;
|
||||
return nodes.length === 3
|
||||
&& isType(nodes[0], 'brace.open')
|
||||
&& !isType(nodes[1], 'text')
|
||||
&& isType(nodes[2], 'brace.close');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given `node` is the given `type`
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
function isType(node, type) {
|
||||
return typeof node !== 'undefined' && node.type === type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given `node` has a non-empty queue.
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
function hasQueue(node) {
|
||||
return Array.isArray(node.queue) && node.queue.length;
|
||||
}
|
||||
57
node_modules/braces/lib/constants.js
generated
vendored
Normal file
57
node_modules/braces/lib/constants.js
generated
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
MAX_LENGTH: 1024 * 64,
|
||||
|
||||
// Digits
|
||||
CHAR_0: '0', /* 0 */
|
||||
CHAR_9: '9', /* 9 */
|
||||
|
||||
// Alphabet chars.
|
||||
CHAR_UPPERCASE_A: 'A', /* A */
|
||||
CHAR_LOWERCASE_A: 'a', /* a */
|
||||
CHAR_UPPERCASE_Z: 'Z', /* Z */
|
||||
CHAR_LOWERCASE_Z: 'z', /* z */
|
||||
|
||||
CHAR_LEFT_PARENTHESES: '(', /* ( */
|
||||
CHAR_RIGHT_PARENTHESES: ')', /* ) */
|
||||
|
||||
CHAR_ASTERISK: '*', /* * */
|
||||
|
||||
// Non-alphabetic chars.
|
||||
CHAR_AMPERSAND: '&', /* & */
|
||||
CHAR_AT: '@', /* @ */
|
||||
CHAR_BACKSLASH: '\\', /* \ */
|
||||
CHAR_BACKTICK: '`', /* ` */
|
||||
CHAR_CARRIAGE_RETURN: '\r', /* \r */
|
||||
CHAR_CIRCUMFLEX_ACCENT: '^', /* ^ */
|
||||
CHAR_COLON: ':', /* : */
|
||||
CHAR_COMMA: ',', /* , */
|
||||
CHAR_DOLLAR: '$', /* . */
|
||||
CHAR_DOT: '.', /* . */
|
||||
CHAR_DOUBLE_QUOTE: '"', /* " */
|
||||
CHAR_EQUAL: '=', /* = */
|
||||
CHAR_EXCLAMATION_MARK: '!', /* ! */
|
||||
CHAR_FORM_FEED: '\f', /* \f */
|
||||
CHAR_FORWARD_SLASH: '/', /* / */
|
||||
CHAR_HASH: '#', /* # */
|
||||
CHAR_HYPHEN_MINUS: '-', /* - */
|
||||
CHAR_LEFT_ANGLE_BRACKET: '<', /* < */
|
||||
CHAR_LEFT_CURLY_BRACE: '{', /* { */
|
||||
CHAR_LEFT_SQUARE_BRACKET: '[', /* [ */
|
||||
CHAR_LINE_FEED: '\n', /* \n */
|
||||
CHAR_NO_BREAK_SPACE: '\u00A0', /* \u00A0 */
|
||||
CHAR_PERCENT: '%', /* % */
|
||||
CHAR_PLUS: '+', /* + */
|
||||
CHAR_QUESTION_MARK: '?', /* ? */
|
||||
CHAR_RIGHT_ANGLE_BRACKET: '>', /* > */
|
||||
CHAR_RIGHT_CURLY_BRACE: '}', /* } */
|
||||
CHAR_RIGHT_SQUARE_BRACKET: ']', /* ] */
|
||||
CHAR_SEMICOLON: ';', /* ; */
|
||||
CHAR_SINGLE_QUOTE: '\'', /* ' */
|
||||
CHAR_SPACE: ' ', /* */
|
||||
CHAR_TAB: '\t', /* \t */
|
||||
CHAR_UNDERSCORE: '_', /* _ */
|
||||
CHAR_VERTICAL_LINE: '|', /* | */
|
||||
CHAR_ZERO_WIDTH_NOBREAK_SPACE: '\uFEFF' /* \uFEFF */
|
||||
};
|
||||
113
node_modules/braces/lib/expand.js
generated
vendored
Normal file
113
node_modules/braces/lib/expand.js
generated
vendored
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
'use strict';
|
||||
|
||||
const fill = require('fill-range');
|
||||
const stringify = require('./stringify');
|
||||
const utils = require('./utils');
|
||||
|
||||
const append = (queue = '', stash = '', enclose = false) => {
|
||||
let result = [];
|
||||
|
||||
queue = [].concat(queue);
|
||||
stash = [].concat(stash);
|
||||
|
||||
if (!stash.length) return queue;
|
||||
if (!queue.length) {
|
||||
return enclose ? utils.flatten(stash).map(ele => `{${ele}}`) : stash;
|
||||
}
|
||||
|
||||
for (let item of queue) {
|
||||
if (Array.isArray(item)) {
|
||||
for (let value of item) {
|
||||
result.push(append(value, stash, enclose));
|
||||
}
|
||||
} else {
|
||||
for (let ele of stash) {
|
||||
if (enclose === true && typeof ele === 'string') ele = `{${ele}}`;
|
||||
result.push(Array.isArray(ele) ? append(item, ele, enclose) : (item + ele));
|
||||
}
|
||||
}
|
||||
}
|
||||
return utils.flatten(result);
|
||||
};
|
||||
|
||||
const expand = (ast, options = {}) => {
|
||||
let rangeLimit = options.rangeLimit === void 0 ? 1000 : options.rangeLimit;
|
||||
|
||||
let walk = (node, parent = {}) => {
|
||||
node.queue = [];
|
||||
|
||||
let p = parent;
|
||||
let q = parent.queue;
|
||||
|
||||
while (p.type !== 'brace' && p.type !== 'root' && p.parent) {
|
||||
p = p.parent;
|
||||
q = p.queue;
|
||||
}
|
||||
|
||||
if (node.invalid || node.dollar) {
|
||||
q.push(append(q.pop(), stringify(node, options)));
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) {
|
||||
q.push(append(q.pop(), ['{}']));
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.nodes && node.ranges > 0) {
|
||||
let args = utils.reduce(node.nodes);
|
||||
|
||||
if (utils.exceedsLimit(...args, options.step, rangeLimit)) {
|
||||
throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.');
|
||||
}
|
||||
|
||||
let range = fill(...args, options);
|
||||
if (range.length === 0) {
|
||||
range = stringify(node, options);
|
||||
}
|
||||
|
||||
q.push(append(q.pop(), range));
|
||||
node.nodes = [];
|
||||
return;
|
||||
}
|
||||
|
||||
let enclose = utils.encloseBrace(node);
|
||||
let queue = node.queue;
|
||||
let block = node;
|
||||
|
||||
while (block.type !== 'brace' && block.type !== 'root' && block.parent) {
|
||||
block = block.parent;
|
||||
queue = block.queue;
|
||||
}
|
||||
|
||||
for (let i = 0; i < node.nodes.length; i++) {
|
||||
let child = node.nodes[i];
|
||||
|
||||
if (child.type === 'comma' && node.type === 'brace') {
|
||||
if (i === 1) queue.push('');
|
||||
queue.push('');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (child.type === 'close') {
|
||||
q.push(append(q.pop(), queue, enclose));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (child.value && child.type !== 'open') {
|
||||
queue.push(append(queue.pop(), child.value));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (child.nodes) {
|
||||
walk(child, node);
|
||||
}
|
||||
}
|
||||
|
||||
return queue;
|
||||
};
|
||||
|
||||
return utils.flatten(walk(ast));
|
||||
};
|
||||
|
||||
module.exports = expand;
|
||||
333
node_modules/braces/lib/parse.js
generated
vendored
Normal file
333
node_modules/braces/lib/parse.js
generated
vendored
Normal file
|
|
@ -0,0 +1,333 @@
|
|||
'use strict';
|
||||
|
||||
const stringify = require('./stringify');
|
||||
|
||||
/**
|
||||
* Constants
|
||||
*/
|
||||
|
||||
const {
|
||||
MAX_LENGTH,
|
||||
CHAR_BACKSLASH, /* \ */
|
||||
CHAR_BACKTICK, /* ` */
|
||||
CHAR_COMMA, /* , */
|
||||
CHAR_DOT, /* . */
|
||||
CHAR_LEFT_PARENTHESES, /* ( */
|
||||
CHAR_RIGHT_PARENTHESES, /* ) */
|
||||
CHAR_LEFT_CURLY_BRACE, /* { */
|
||||
CHAR_RIGHT_CURLY_BRACE, /* } */
|
||||
CHAR_LEFT_SQUARE_BRACKET, /* [ */
|
||||
CHAR_RIGHT_SQUARE_BRACKET, /* ] */
|
||||
CHAR_DOUBLE_QUOTE, /* " */
|
||||
CHAR_SINGLE_QUOTE, /* ' */
|
||||
CHAR_NO_BREAK_SPACE,
|
||||
CHAR_ZERO_WIDTH_NOBREAK_SPACE
|
||||
} = require('./constants');
|
||||
|
||||
/**
|
||||
* parse
|
||||
*/
|
||||
|
||||
const parse = (input, options = {}) => {
|
||||
if (typeof input !== 'string') {
|
||||
throw new TypeError('Expected a string');
|
||||
}
|
||||
|
||||
let opts = options || {};
|
||||
let max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
|
||||
if (input.length > max) {
|
||||
throw new SyntaxError(`Input length (${input.length}), exceeds max characters (${max})`);
|
||||
}
|
||||
|
||||
let ast = { type: 'root', input, nodes: [] };
|
||||
let stack = [ast];
|
||||
let block = ast;
|
||||
let prev = ast;
|
||||
let brackets = 0;
|
||||
let length = input.length;
|
||||
let index = 0;
|
||||
let depth = 0;
|
||||
let value;
|
||||
let memo = {};
|
||||
|
||||
/**
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
const advance = () => input[index++];
|
||||
const push = node => {
|
||||
if (node.type === 'text' && prev.type === 'dot') {
|
||||
prev.type = 'text';
|
||||
}
|
||||
|
||||
if (prev && prev.type === 'text' && node.type === 'text') {
|
||||
prev.value += node.value;
|
||||
return;
|
||||
}
|
||||
|
||||
block.nodes.push(node);
|
||||
node.parent = block;
|
||||
node.prev = prev;
|
||||
prev = node;
|
||||
return node;
|
||||
};
|
||||
|
||||
push({ type: 'bos' });
|
||||
|
||||
while (index < length) {
|
||||
block = stack[stack.length - 1];
|
||||
value = advance();
|
||||
|
||||
/**
|
||||
* Invalid chars
|
||||
*/
|
||||
|
||||
if (value === CHAR_ZERO_WIDTH_NOBREAK_SPACE || value === CHAR_NO_BREAK_SPACE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escaped chars
|
||||
*/
|
||||
|
||||
if (value === CHAR_BACKSLASH) {
|
||||
push({ type: 'text', value: (options.keepEscaping ? value : '') + advance() });
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Right square bracket (literal): ']'
|
||||
*/
|
||||
|
||||
if (value === CHAR_RIGHT_SQUARE_BRACKET) {
|
||||
push({ type: 'text', value: '\\' + value });
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Left square bracket: '['
|
||||
*/
|
||||
|
||||
if (value === CHAR_LEFT_SQUARE_BRACKET) {
|
||||
brackets++;
|
||||
|
||||
let closed = true;
|
||||
let next;
|
||||
|
||||
while (index < length && (next = advance())) {
|
||||
value += next;
|
||||
|
||||
if (next === CHAR_LEFT_SQUARE_BRACKET) {
|
||||
brackets++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (next === CHAR_BACKSLASH) {
|
||||
value += advance();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (next === CHAR_RIGHT_SQUARE_BRACKET) {
|
||||
brackets--;
|
||||
|
||||
if (brackets === 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
push({ type: 'text', value });
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parentheses
|
||||
*/
|
||||
|
||||
if (value === CHAR_LEFT_PARENTHESES) {
|
||||
block = push({ type: 'paren', nodes: [] });
|
||||
stack.push(block);
|
||||
push({ type: 'text', value });
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value === CHAR_RIGHT_PARENTHESES) {
|
||||
if (block.type !== 'paren') {
|
||||
push({ type: 'text', value });
|
||||
continue;
|
||||
}
|
||||
block = stack.pop();
|
||||
push({ type: 'text', value });
|
||||
block = stack[stack.length - 1];
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quotes: '|"|`
|
||||
*/
|
||||
|
||||
if (value === CHAR_DOUBLE_QUOTE || value === CHAR_SINGLE_QUOTE || value === CHAR_BACKTICK) {
|
||||
let open = value;
|
||||
let next;
|
||||
|
||||
if (options.keepQuotes !== true) {
|
||||
value = '';
|
||||
}
|
||||
|
||||
while (index < length && (next = advance())) {
|
||||
if (next === CHAR_BACKSLASH) {
|
||||
value += next + advance();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (next === open) {
|
||||
if (options.keepQuotes === true) value += next;
|
||||
break;
|
||||
}
|
||||
|
||||
value += next;
|
||||
}
|
||||
|
||||
push({ type: 'text', value });
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Left curly brace: '{'
|
||||
*/
|
||||
|
||||
if (value === CHAR_LEFT_CURLY_BRACE) {
|
||||
depth++;
|
||||
|
||||
let dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true;
|
||||
let brace = {
|
||||
type: 'brace',
|
||||
open: true,
|
||||
close: false,
|
||||
dollar,
|
||||
depth,
|
||||
commas: 0,
|
||||
ranges: 0,
|
||||
nodes: []
|
||||
};
|
||||
|
||||
block = push(brace);
|
||||
stack.push(block);
|
||||
push({ type: 'open', value });
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Right curly brace: '}'
|
||||
*/
|
||||
|
||||
if (value === CHAR_RIGHT_CURLY_BRACE) {
|
||||
if (block.type !== 'brace') {
|
||||
push({ type: 'text', value });
|
||||
continue;
|
||||
}
|
||||
|
||||
let type = 'close';
|
||||
block = stack.pop();
|
||||
block.close = true;
|
||||
|
||||
push({ type, value });
|
||||
depth--;
|
||||
|
||||
block = stack[stack.length - 1];
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Comma: ','
|
||||
*/
|
||||
|
||||
if (value === CHAR_COMMA && depth > 0) {
|
||||
if (block.ranges > 0) {
|
||||
block.ranges = 0;
|
||||
let open = block.nodes.shift();
|
||||
block.nodes = [open, { type: 'text', value: stringify(block) }];
|
||||
}
|
||||
|
||||
push({ type: 'comma', value });
|
||||
block.commas++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dot: '.'
|
||||
*/
|
||||
|
||||
if (value === CHAR_DOT && depth > 0 && block.commas === 0) {
|
||||
let siblings = block.nodes;
|
||||
|
||||
if (depth === 0 || siblings.length === 0) {
|
||||
push({ type: 'text', value });
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prev.type === 'dot') {
|
||||
block.range = [];
|
||||
prev.value += value;
|
||||
prev.type = 'range';
|
||||
|
||||
if (block.nodes.length !== 3 && block.nodes.length !== 5) {
|
||||
block.invalid = true;
|
||||
block.ranges = 0;
|
||||
prev.type = 'text';
|
||||
continue;
|
||||
}
|
||||
|
||||
block.ranges++;
|
||||
block.args = [];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prev.type === 'range') {
|
||||
siblings.pop();
|
||||
|
||||
let before = siblings[siblings.length - 1];
|
||||
before.value += prev.value + value;
|
||||
prev = before;
|
||||
block.ranges--;
|
||||
continue;
|
||||
}
|
||||
|
||||
push({ type: 'dot', value });
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Text
|
||||
*/
|
||||
|
||||
push({ type: 'text', value });
|
||||
}
|
||||
|
||||
// Mark imbalanced braces and brackets as invalid
|
||||
do {
|
||||
block = stack.pop();
|
||||
|
||||
if (block.type !== 'root') {
|
||||
block.nodes.forEach(node => {
|
||||
if (!node.nodes) {
|
||||
if (node.type === 'open') node.isOpen = true;
|
||||
if (node.type === 'close') node.isClose = true;
|
||||
if (!node.nodes) node.type = 'text';
|
||||
node.invalid = true;
|
||||
}
|
||||
});
|
||||
|
||||
// get the location of the block on parent.nodes (block's siblings)
|
||||
let parent = stack[stack.length - 1];
|
||||
let index = parent.nodes.indexOf(block);
|
||||
// replace the (invalid) block with it's nodes
|
||||
parent.nodes.splice(index, 1, ...block.nodes);
|
||||
}
|
||||
} while (stack.length > 0);
|
||||
|
||||
push({ type: 'eos' });
|
||||
return ast;
|
||||
};
|
||||
|
||||
module.exports = parse;
|
||||
360
node_modules/braces/lib/parsers.js
generated
vendored
360
node_modules/braces/lib/parsers.js
generated
vendored
|
|
@ -1,360 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var Node = require('snapdragon-node');
|
||||
var utils = require('./utils');
|
||||
|
||||
/**
|
||||
* Braces parsers
|
||||
*/
|
||||
|
||||
module.exports = function(braces, options) {
|
||||
braces.parser
|
||||
.set('bos', function() {
|
||||
if (!this.parsed) {
|
||||
this.ast = this.nodes[0] = new Node(this.ast);
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Character parsers
|
||||
*/
|
||||
|
||||
.set('escape', function() {
|
||||
var pos = this.position();
|
||||
var m = this.match(/^(?:\\(.)|\$\{)/);
|
||||
if (!m) return;
|
||||
|
||||
var prev = this.prev();
|
||||
var last = utils.last(prev.nodes);
|
||||
|
||||
var node = pos(new Node({
|
||||
type: 'text',
|
||||
multiplier: 1,
|
||||
val: m[0]
|
||||
}));
|
||||
|
||||
if (node.val === '\\\\') {
|
||||
return node;
|
||||
}
|
||||
|
||||
if (node.val === '${') {
|
||||
var str = this.input;
|
||||
var idx = -1;
|
||||
var ch;
|
||||
|
||||
while ((ch = str[++idx])) {
|
||||
this.consume(1);
|
||||
node.val += ch;
|
||||
if (ch === '\\') {
|
||||
node.val += str[++idx];
|
||||
continue;
|
||||
}
|
||||
if (ch === '}') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.options.unescape !== false) {
|
||||
node.val = node.val.replace(/\\([{}])/g, '$1');
|
||||
}
|
||||
|
||||
if (last.val === '"' && this.input.charAt(0) === '"') {
|
||||
last.val = node.val;
|
||||
this.consume(1);
|
||||
return;
|
||||
}
|
||||
|
||||
return concatNodes.call(this, pos, node, prev, options);
|
||||
})
|
||||
|
||||
/**
|
||||
* Brackets: "[...]" (basic, this is overridden by
|
||||
* other parsers in more advanced implementations)
|
||||
*/
|
||||
|
||||
.set('bracket', function() {
|
||||
var isInside = this.isInside('brace');
|
||||
var pos = this.position();
|
||||
var m = this.match(/^(?:\[([!^]?)([^\]]{2,}|\]-)(\]|[^*+?]+)|\[)/);
|
||||
if (!m) return;
|
||||
|
||||
var prev = this.prev();
|
||||
var val = m[0];
|
||||
var negated = m[1] ? '^' : '';
|
||||
var inner = m[2] || '';
|
||||
var close = m[3] || '';
|
||||
|
||||
if (isInside && prev.type === 'brace') {
|
||||
prev.text = prev.text || '';
|
||||
prev.text += val;
|
||||
}
|
||||
|
||||
var esc = this.input.slice(0, 2);
|
||||
if (inner === '' && esc === '\\]') {
|
||||
inner += esc;
|
||||
this.consume(2);
|
||||
|
||||
var str = this.input;
|
||||
var idx = -1;
|
||||
var ch;
|
||||
|
||||
while ((ch = str[++idx])) {
|
||||
this.consume(1);
|
||||
if (ch === ']') {
|
||||
close = ch;
|
||||
break;
|
||||
}
|
||||
inner += ch;
|
||||
}
|
||||
}
|
||||
|
||||
return pos(new Node({
|
||||
type: 'bracket',
|
||||
val: val,
|
||||
escaped: close !== ']',
|
||||
negated: negated,
|
||||
inner: inner,
|
||||
close: close
|
||||
}));
|
||||
})
|
||||
|
||||
/**
|
||||
* Empty braces (we capture these early to
|
||||
* speed up processing in the compiler)
|
||||
*/
|
||||
|
||||
.set('multiplier', function() {
|
||||
var isInside = this.isInside('brace');
|
||||
var pos = this.position();
|
||||
var m = this.match(/^\{((?:,|\{,+\})+)\}/);
|
||||
if (!m) return;
|
||||
|
||||
this.multiplier = true;
|
||||
var prev = this.prev();
|
||||
var val = m[0];
|
||||
|
||||
if (isInside && prev.type === 'brace') {
|
||||
prev.text = prev.text || '';
|
||||
prev.text += val;
|
||||
}
|
||||
|
||||
var node = pos(new Node({
|
||||
type: 'text',
|
||||
multiplier: 1,
|
||||
match: m,
|
||||
val: val
|
||||
}));
|
||||
|
||||
return concatNodes.call(this, pos, node, prev, options);
|
||||
})
|
||||
|
||||
/**
|
||||
* Open
|
||||
*/
|
||||
|
||||
.set('brace.open', function() {
|
||||
var pos = this.position();
|
||||
var m = this.match(/^\{(?!(?:[^\\}]?|,+)\})/);
|
||||
if (!m) return;
|
||||
|
||||
var prev = this.prev();
|
||||
var last = utils.last(prev.nodes);
|
||||
|
||||
// if the last parsed character was an extglob character
|
||||
// we need to _not optimize_ the brace pattern because
|
||||
// it might be mistaken for an extglob by a downstream parser
|
||||
if (last && last.val && isExtglobChar(last.val.slice(-1))) {
|
||||
last.optimize = false;
|
||||
}
|
||||
|
||||
var open = pos(new Node({
|
||||
type: 'brace.open',
|
||||
val: m[0]
|
||||
}));
|
||||
|
||||
var node = pos(new Node({
|
||||
type: 'brace',
|
||||
nodes: []
|
||||
}));
|
||||
|
||||
node.push(open);
|
||||
prev.push(node);
|
||||
this.push('brace', node);
|
||||
})
|
||||
|
||||
/**
|
||||
* Close
|
||||
*/
|
||||
|
||||
.set('brace.close', function() {
|
||||
var pos = this.position();
|
||||
var m = this.match(/^\}/);
|
||||
if (!m || !m[0]) return;
|
||||
|
||||
var brace = this.pop('brace');
|
||||
var node = pos(new Node({
|
||||
type: 'brace.close',
|
||||
val: m[0]
|
||||
}));
|
||||
|
||||
if (!this.isType(brace, 'brace')) {
|
||||
if (this.options.strict) {
|
||||
throw new Error('missing opening "{"');
|
||||
}
|
||||
node.type = 'text';
|
||||
node.multiplier = 0;
|
||||
node.escaped = true;
|
||||
return node;
|
||||
}
|
||||
|
||||
var prev = this.prev();
|
||||
var last = utils.last(prev.nodes);
|
||||
if (last.text) {
|
||||
var lastNode = utils.last(last.nodes);
|
||||
if (lastNode.val === ')' && /[!@*?+]\(/.test(last.text)) {
|
||||
var open = last.nodes[0];
|
||||
var text = last.nodes[1];
|
||||
if (open.type === 'brace.open' && text && text.type === 'text') {
|
||||
text.optimize = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (brace.nodes.length > 2) {
|
||||
var first = brace.nodes[1];
|
||||
if (first.type === 'text' && first.val === ',') {
|
||||
brace.nodes.splice(1, 1);
|
||||
brace.nodes.push(first);
|
||||
}
|
||||
}
|
||||
|
||||
brace.push(node);
|
||||
})
|
||||
|
||||
/**
|
||||
* Capture boundary characters
|
||||
*/
|
||||
|
||||
.set('boundary', function() {
|
||||
var pos = this.position();
|
||||
var m = this.match(/^[$^](?!\{)/);
|
||||
if (!m) return;
|
||||
return pos(new Node({
|
||||
type: 'text',
|
||||
val: m[0]
|
||||
}));
|
||||
})
|
||||
|
||||
/**
|
||||
* One or zero, non-comma characters wrapped in braces
|
||||
*/
|
||||
|
||||
.set('nobrace', function() {
|
||||
var isInside = this.isInside('brace');
|
||||
var pos = this.position();
|
||||
var m = this.match(/^\{[^,]?\}/);
|
||||
if (!m) return;
|
||||
|
||||
var prev = this.prev();
|
||||
var val = m[0];
|
||||
|
||||
if (isInside && prev.type === 'brace') {
|
||||
prev.text = prev.text || '';
|
||||
prev.text += val;
|
||||
}
|
||||
|
||||
return pos(new Node({
|
||||
type: 'text',
|
||||
multiplier: 0,
|
||||
val: val
|
||||
}));
|
||||
})
|
||||
|
||||
/**
|
||||
* Text
|
||||
*/
|
||||
|
||||
.set('text', function() {
|
||||
var isInside = this.isInside('brace');
|
||||
var pos = this.position();
|
||||
var m = this.match(/^((?!\\)[^${}[\]])+/);
|
||||
if (!m) return;
|
||||
|
||||
var prev = this.prev();
|
||||
var val = m[0];
|
||||
|
||||
if (isInside && prev.type === 'brace') {
|
||||
prev.text = prev.text || '';
|
||||
prev.text += val;
|
||||
}
|
||||
|
||||
var node = pos(new Node({
|
||||
type: 'text',
|
||||
multiplier: 1,
|
||||
val: val
|
||||
}));
|
||||
|
||||
return concatNodes.call(this, pos, node, prev, options);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the character is an extglob character.
|
||||
*/
|
||||
|
||||
function isExtglobChar(ch) {
|
||||
return ch === '!' || ch === '@' || ch === '*' || ch === '?' || ch === '+';
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine text nodes, and calculate empty sets (`{,,}`)
|
||||
* @param {Function} `pos` Function to calculate node position
|
||||
* @param {Object} `node` AST node
|
||||
* @return {Object}
|
||||
*/
|
||||
|
||||
function concatNodes(pos, node, parent, options) {
|
||||
node.orig = node.val;
|
||||
var prev = this.prev();
|
||||
var last = utils.last(prev.nodes);
|
||||
var isEscaped = false;
|
||||
|
||||
if (node.val.length > 1) {
|
||||
var a = node.val.charAt(0);
|
||||
var b = node.val.slice(-1);
|
||||
|
||||
isEscaped = (a === '"' && b === '"')
|
||||
|| (a === "'" && b === "'")
|
||||
|| (a === '`' && b === '`');
|
||||
}
|
||||
|
||||
if (isEscaped && options.unescape !== false) {
|
||||
node.val = node.val.slice(1, node.val.length - 1);
|
||||
node.escaped = true;
|
||||
}
|
||||
|
||||
if (node.match) {
|
||||
var match = node.match[1];
|
||||
if (!match || match.indexOf('}') === -1) {
|
||||
match = node.match[0];
|
||||
}
|
||||
|
||||
// replace each set with a single ","
|
||||
var val = match.replace(/\{/g, ',').replace(/\}/g, '');
|
||||
node.multiplier *= val.length;
|
||||
node.val = '';
|
||||
}
|
||||
|
||||
var simpleText = last.type === 'text'
|
||||
&& last.multiplier === 1
|
||||
&& node.multiplier === 1
|
||||
&& node.val;
|
||||
|
||||
if (simpleText) {
|
||||
last.val += node.val;
|
||||
return;
|
||||
}
|
||||
|
||||
prev.push(node);
|
||||
}
|
||||
32
node_modules/braces/lib/stringify.js
generated
vendored
Normal file
32
node_modules/braces/lib/stringify.js
generated
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
'use strict';
|
||||
|
||||
const utils = require('./utils');
|
||||
|
||||
module.exports = (ast, options = {}) => {
|
||||
let stringify = (node, parent = {}) => {
|
||||
let invalidBlock = options.escapeInvalid && utils.isInvalidBrace(parent);
|
||||
let invalidNode = node.invalid === true && options.escapeInvalid === true;
|
||||
let output = '';
|
||||
|
||||
if (node.value) {
|
||||
if ((invalidBlock || invalidNode) && utils.isOpenOrClose(node)) {
|
||||
return '\\' + node.value;
|
||||
}
|
||||
return node.value;
|
||||
}
|
||||
|
||||
if (node.value) {
|
||||
return node.value;
|
||||
}
|
||||
|
||||
if (node.nodes) {
|
||||
for (let child of node.nodes) {
|
||||
output += stringify(child);
|
||||
}
|
||||
}
|
||||
return output;
|
||||
};
|
||||
|
||||
return stringify(ast);
|
||||
};
|
||||
|
||||
371
node_modules/braces/lib/utils.js
generated
vendored
371
node_modules/braces/lib/utils.js
generated
vendored
|
|
@ -1,343 +1,112 @@
|
|||
'use strict';
|
||||
|
||||
var splitString = require('split-string');
|
||||
var utils = module.exports;
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
utils.extend = require('extend-shallow');
|
||||
utils.flatten = require('arr-flatten');
|
||||
utils.isObject = require('isobject');
|
||||
utils.fillRange = require('fill-range');
|
||||
utils.repeat = require('repeat-element');
|
||||
utils.unique = require('array-unique');
|
||||
|
||||
utils.define = function(obj, key, val) {
|
||||
Object.defineProperty(obj, key, {
|
||||
writable: true,
|
||||
configurable: true,
|
||||
enumerable: false,
|
||||
value: val
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the given string contains only empty brace sets.
|
||||
*/
|
||||
|
||||
utils.isEmptySets = function(str) {
|
||||
return /^(?:\{,\})+$/.test(str);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the given string contains only empty brace sets.
|
||||
*/
|
||||
|
||||
utils.isQuotedString = function(str) {
|
||||
var open = str.charAt(0);
|
||||
if (open === '\'' || open === '"' || open === '`') {
|
||||
return str.slice(-1) === open;
|
||||
exports.isInteger = num => {
|
||||
if (typeof num === 'number') {
|
||||
return Number.isInteger(num);
|
||||
}
|
||||
if (typeof num === 'string' && num.trim() !== '') {
|
||||
return Number.isInteger(Number(num));
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create the key to use for memoization. The unique key is generated
|
||||
* by iterating over the options and concatenating key-value pairs
|
||||
* to the pattern string.
|
||||
* Find a node of the given type
|
||||
*/
|
||||
|
||||
utils.createKey = function(pattern, options) {
|
||||
var id = pattern;
|
||||
if (typeof options === 'undefined') {
|
||||
return id;
|
||||
}
|
||||
var keys = Object.keys(options);
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i];
|
||||
id += ';' + key + '=' + String(options[key]);
|
||||
}
|
||||
return id;
|
||||
exports.find = (node, type) => node.nodes.find(node => node.type === type);
|
||||
|
||||
/**
|
||||
* Find a node of the given type
|
||||
*/
|
||||
|
||||
exports.exceedsLimit = (min, max, step = 1, limit) => {
|
||||
if (limit === false) return false;
|
||||
if (!exports.isInteger(min) || !exports.isInteger(max)) return false;
|
||||
return ((Number(max) - Number(min)) / Number(step)) >= limit;
|
||||
};
|
||||
|
||||
/**
|
||||
* Normalize options
|
||||
* Escape the given node with '\\' before node.value
|
||||
*/
|
||||
|
||||
utils.createOptions = function(options) {
|
||||
var opts = utils.extend.apply(null, arguments);
|
||||
if (typeof opts.expand === 'boolean') {
|
||||
opts.optimize = !opts.expand;
|
||||
exports.escapeNode = (block, n = 0, type) => {
|
||||
let node = block.nodes[n];
|
||||
if (!node) return;
|
||||
|
||||
if ((type && node.type === type) || node.type === 'open' || node.type === 'close') {
|
||||
if (node.escaped !== true) {
|
||||
node.value = '\\' + node.value;
|
||||
node.escaped = true;
|
||||
}
|
||||
}
|
||||
if (typeof opts.optimize === 'boolean') {
|
||||
opts.expand = !opts.optimize;
|
||||
}
|
||||
if (opts.optimize === true) {
|
||||
opts.makeRe = true;
|
||||
}
|
||||
return opts;
|
||||
};
|
||||
|
||||
/**
|
||||
* Join patterns in `a` to patterns in `b`
|
||||
* Returns true if the given brace node should be enclosed in literal braces
|
||||
*/
|
||||
|
||||
utils.join = function(a, b, options) {
|
||||
options = options || {};
|
||||
a = utils.arrayify(a);
|
||||
b = utils.arrayify(b);
|
||||
|
||||
if (!a.length) return b;
|
||||
if (!b.length) return a;
|
||||
|
||||
var len = a.length;
|
||||
var idx = -1;
|
||||
var arr = [];
|
||||
|
||||
while (++idx < len) {
|
||||
var val = a[idx];
|
||||
if (Array.isArray(val)) {
|
||||
for (var i = 0; i < val.length; i++) {
|
||||
val[i] = utils.join(val[i], b, options);
|
||||
}
|
||||
arr.push(val);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var j = 0; j < b.length; j++) {
|
||||
var bval = b[j];
|
||||
|
||||
if (Array.isArray(bval)) {
|
||||
arr.push(utils.join(val, bval, options));
|
||||
} else {
|
||||
arr.push(val + bval);
|
||||
}
|
||||
}
|
||||
exports.encloseBrace = node => {
|
||||
if (node.type !== 'brace') return false;
|
||||
if ((node.commas >> 0 + node.ranges >> 0) === 0) {
|
||||
node.invalid = true;
|
||||
return true;
|
||||
}
|
||||
return arr;
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Split the given string on `,` if not escaped.
|
||||
* Returns true if a brace node is invalid.
|
||||
*/
|
||||
|
||||
utils.split = function(str, options) {
|
||||
var opts = utils.extend({sep: ','}, options);
|
||||
if (typeof opts.keepQuotes !== 'boolean') {
|
||||
opts.keepQuotes = true;
|
||||
exports.isInvalidBrace = block => {
|
||||
if (block.type !== 'brace') return false;
|
||||
if (block.invalid === true || block.dollar) return true;
|
||||
if ((block.commas >> 0 + block.ranges >> 0) === 0) {
|
||||
block.invalid = true;
|
||||
return true;
|
||||
}
|
||||
if (opts.unescape === false) {
|
||||
opts.keepEscaping = true;
|
||||
if (block.open !== true || block.close !== true) {
|
||||
block.invalid = true;
|
||||
return true;
|
||||
}
|
||||
return splitString(str, opts, utils.escapeBrackets(opts));
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Expand ranges or sets in the given `pattern`.
|
||||
*
|
||||
* @param {String} `str`
|
||||
* @param {Object} `options`
|
||||
* @return {Object}
|
||||
* Returns true if a node is an open or close node
|
||||
*/
|
||||
|
||||
utils.expand = function(str, options) {
|
||||
var opts = utils.extend({rangeLimit: 10000}, options);
|
||||
var segs = utils.split(str, opts);
|
||||
var tok = { segs: segs };
|
||||
|
||||
if (utils.isQuotedString(str)) {
|
||||
return tok;
|
||||
exports.isOpenOrClose = node => {
|
||||
if (node.type === 'open' || node.type === 'close') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (opts.rangeLimit === true) {
|
||||
opts.rangeLimit = 10000;
|
||||
}
|
||||
|
||||
if (segs.length > 1) {
|
||||
if (opts.optimize === false) {
|
||||
tok.val = segs[0];
|
||||
return tok;
|
||||
}
|
||||
|
||||
tok.segs = utils.stringifyArray(tok.segs);
|
||||
} else if (segs.length === 1) {
|
||||
var arr = str.split('..');
|
||||
|
||||
if (arr.length === 1) {
|
||||
tok.val = tok.segs[tok.segs.length - 1] || tok.val || str;
|
||||
tok.segs = [];
|
||||
return tok;
|
||||
}
|
||||
|
||||
if (arr.length === 2 && arr[0] === arr[1]) {
|
||||
tok.escaped = true;
|
||||
tok.val = arr[0];
|
||||
tok.segs = [];
|
||||
return tok;
|
||||
}
|
||||
|
||||
if (arr.length > 1) {
|
||||
if (opts.optimize !== false) {
|
||||
opts.optimize = true;
|
||||
delete opts.expand;
|
||||
}
|
||||
|
||||
if (opts.optimize !== true) {
|
||||
var min = Math.min(arr[0], arr[1]);
|
||||
var max = Math.max(arr[0], arr[1]);
|
||||
var step = arr[2] || 1;
|
||||
|
||||
if (opts.rangeLimit !== false && ((max - min) / step >= opts.rangeLimit)) {
|
||||
throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.');
|
||||
}
|
||||
}
|
||||
|
||||
arr.push(opts);
|
||||
tok.segs = utils.fillRange.apply(null, arr);
|
||||
|
||||
if (!tok.segs.length) {
|
||||
tok.escaped = true;
|
||||
tok.val = str;
|
||||
return tok;
|
||||
}
|
||||
|
||||
if (opts.optimize === true) {
|
||||
tok.segs = utils.stringifyArray(tok.segs);
|
||||
}
|
||||
|
||||
if (tok.segs === '') {
|
||||
tok.val = str;
|
||||
} else {
|
||||
tok.val = tok.segs[0];
|
||||
}
|
||||
return tok;
|
||||
}
|
||||
} else {
|
||||
tok.val = str;
|
||||
}
|
||||
return tok;
|
||||
return node.open === true || node.close === true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Ensure commas inside brackets and parens are not split.
|
||||
* @param {Object} `tok` Token from the `split-string` module
|
||||
* @return {undefined}
|
||||
* Reduce an array of text nodes.
|
||||
*/
|
||||
|
||||
utils.escapeBrackets = function(options) {
|
||||
return function(tok) {
|
||||
if (tok.escaped && tok.val === 'b') {
|
||||
tok.val = '\\b';
|
||||
return;
|
||||
exports.reduce = nodes => nodes.reduce((acc, node) => {
|
||||
if (node.type === 'text') acc.push(node.value);
|
||||
if (node.type === 'range') node.type = 'text';
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Flatten an array
|
||||
*/
|
||||
|
||||
exports.flatten = (...args) => {
|
||||
const result = [];
|
||||
const flat = arr => {
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
let ele = arr[i];
|
||||
Array.isArray(ele) ? flat(ele, result) : ele !== void 0 && result.push(ele);
|
||||
}
|
||||
|
||||
if (tok.val !== '(' && tok.val !== '[') return;
|
||||
var opts = utils.extend({}, options);
|
||||
var brackets = [];
|
||||
var parens = [];
|
||||
var stack = [];
|
||||
var val = tok.val;
|
||||
var str = tok.str;
|
||||
var i = tok.idx - 1;
|
||||
|
||||
while (++i < str.length) {
|
||||
var ch = str[i];
|
||||
|
||||
if (ch === '\\') {
|
||||
val += (opts.keepEscaping === false ? '' : ch) + str[++i];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch === '(') {
|
||||
parens.push(ch);
|
||||
stack.push(ch);
|
||||
}
|
||||
|
||||
if (ch === '[') {
|
||||
brackets.push(ch);
|
||||
stack.push(ch);
|
||||
}
|
||||
|
||||
if (ch === ')') {
|
||||
parens.pop();
|
||||
stack.pop();
|
||||
if (!stack.length) {
|
||||
val += ch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ch === ']') {
|
||||
brackets.pop();
|
||||
stack.pop();
|
||||
if (!stack.length) {
|
||||
val += ch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
val += ch;
|
||||
}
|
||||
|
||||
tok.split = false;
|
||||
tok.val = val.slice(1);
|
||||
tok.idx = i;
|
||||
return result;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the given string looks like a regex quantifier
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
utils.isQuantifier = function(str) {
|
||||
return /^(?:[0-9]?,[0-9]|[0-9],)$/.test(str);
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast `val` to an array.
|
||||
* @param {*} `val`
|
||||
*/
|
||||
|
||||
utils.stringifyArray = function(arr) {
|
||||
return [utils.arrayify(arr).join('|')];
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast `val` to an array.
|
||||
* @param {*} `val`
|
||||
*/
|
||||
|
||||
utils.arrayify = function(arr) {
|
||||
if (typeof arr === 'undefined') {
|
||||
return [];
|
||||
}
|
||||
if (typeof arr === 'string') {
|
||||
return [arr];
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the given `str` is a non-empty string
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
utils.isString = function(str) {
|
||||
return str != null && typeof str === 'string';
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the last element from `array`
|
||||
* @param {Array} `array`
|
||||
* @return {*}
|
||||
*/
|
||||
|
||||
utils.last = function(arr, n) {
|
||||
return arr[arr.length - (n || 1)];
|
||||
};
|
||||
|
||||
utils.escapeRegex = function(str) {
|
||||
return str.replace(/\\?([!^*?()[\]{}+?/])/g, '\\$1');
|
||||
flat(args);
|
||||
return result;
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue