From 0c04d6f3ce5418e4b56b3c984e012ddb8a1ce3d6 Mon Sep 17 00:00:00 2001 From: Jon Schlinkert Date: Sat, 25 May 2019 04:49:56 -0400 Subject: [PATCH 01/11] Create FUNDING.yml --- .github/FUNDING.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..c1b9a7a --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: jonschlinkert +tidelift: npm/braces From 3f8e7ff621872888d46f2bfc944764dda0a4ab84 Mon Sep 17 00:00:00 2001 From: Samm Cooper Date: Sat, 15 Jun 2019 19:54:08 -0700 Subject: [PATCH 02/11] Failing test cases for issue \#29 (#30) --- test/braces.compile.js | 16 ++++++++++++++++ test/braces.expand.js | 12 ++++++++++++ test/readme.js | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 test/readme.js diff --git a/test/braces.compile.js b/test/braces.compile.js index f1b8395..41d4b25 100644 --- a/test/braces.compile.js +++ b/test/braces.compile.js @@ -43,6 +43,22 @@ describe('braces.compile()', () => { assert.equal(compile(parse('{a..e..x..z}')), '{a..e..x..z}'); assert.equal(compile(parse('{a..e..x..z}'), { escapeInvalid: true }), '\\{a..e..x..z\\}'); }); + + it('should compile very simple numeric ranges', () => { + assert.equal(compile(parse('{1..5}')), '([1-5])'); + }); + + it('should compile numeric ranges with increments', () => { + assert.equal(compile(parse('{1..5..2}')), '(1|3|5)'); + }); + + it('should compile zero-padded numeric ranges', () => { + assert.equal(compile(parse('{01..05}')), '(0[1-5])'); + }); + + it('should compile zero-padded numeric ranges with increments', () => { + assert.equal(compile(parse('{01..05..2}')), '(01|03|05)'); + }); }); describe('invalid', () => { diff --git a/test/braces.expand.js b/test/braces.expand.js index 23cd4df..98012ef 100644 --- a/test/braces.expand.js +++ b/test/braces.expand.js @@ -164,5 +164,17 @@ describe('unit tests from brace-expand', () => { }); }); }); + + describe('additional brace expansion test', () => { + describe('sequences', () => { + it('zero-padded numeric sequences', () => { + equal('{008..012}', ['008', '009', '010', '011', '012']); + }); + + it('zero-padded numeric sequences with increments', () => { + equal('{008..012..2}', ['008', '010', '012']); + }); + }); + }); }); diff --git a/test/readme.js b/test/readme.js new file mode 100644 index 0000000..1c1731c --- /dev/null +++ b/test/readme.js @@ -0,0 +1,34 @@ +'use strict'; + +require('mocha'); +const assert = require('assert').strict; +const braces = require('..'); + +describe('Examples from README.md', () => { + describe('Brace Expansion vs. Compilation', () => { + it('Compiled', () => { + assert.deepEqual( braces('a/{x,y,z}/b'), ['a/(x|y|z)/b'] ); + assert.deepEqual( braces(['a/{01..20}/b', 'a/{1..5}/b']), [ 'a/(0[1-9]|1[0-9]|20)/b', 'a/([1-5])/b' ] ); + }); + + it('Expanded', () => { + assert.deepEqual(braces('a/{x,y,z}/b', { expand: true }), ['a/x/b', 'a/y/b', 'a/z/b'] ); + assert.deepEqual(braces.expand('{01..10}'), ['01','02','03','04','05','06','07','08','09','10'] ); + }); + }); + + describe('Sequences', () => { + it('first set of examples', () => { + assert.deepEqual( braces.expand('{1..3}'), ['1', '2', '3']); + assert.deepEqual( braces.expand('a/{1..3}/b'), ['a/1/b', 'a/2/b', 'a/3/b']); + assert.deepEqual( braces('{a..c}', { expand: true }), ['a', 'b', 'c']); + assert.deepEqual( braces('foo/{a..c}', { expand: true }), ['foo/a', 'foo/b', 'foo/c']); + }) + + it('zero-padding examples', () => { + // supports zero-padded ranges + assert.deepEqual( braces('a/{01..03}/b'), ['a/(0[1-3])/b']); + assert.deepEqual( braces('a/{001..300}/b'), ['a/(0{2}[1-9]|0[1-9][0-9]|[12][0-9]{2}|300)/b']); + }) + }); +}); \ No newline at end of file From 665ab5d561c017a38ba7aafd92cc6655b91d8c14 Mon Sep 17 00:00:00 2001 From: vemoo Date: Sun, 16 Jun 2019 04:54:27 +0200 Subject: [PATCH 03/11] update keepEscaping doc (#27) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cba2f60..67f2689 100644 --- a/README.md +++ b/README.md @@ -287,13 +287,13 @@ console.log(braces('a/b{1,3}/{x,y,z}', {quantifiers: true, expand: true})); //=> [ 'a/b{1,3}/x', 'a/b{1,3}/y', 'a/b{1,3}/z' ] ``` -### options.unescape +### options.keepEscaping **Type**: `Boolean` **Default**: `undefined` -**Description**: Strip backslashes that were used for escaping from the result. +**Description**: Do not strip backslashes that were used for escaping from the result. ## What is "brace expansion"? From 98414f9f1fabe021736e26836d8306d5de747e0d Mon Sep 17 00:00:00 2001 From: Jon Schlinkert Date: Sat, 15 Jun 2019 23:50:38 -0400 Subject: [PATCH 04/11] remove funding file --- .github/FUNDING.yml | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index c1b9a7a..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,2 +0,0 @@ -github: jonschlinkert -tidelift: npm/braces From 9f5b4cf47329351bcb64287223ffb6ecc9a5e6d3 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Tue, 14 May 2024 23:55:05 +0300 Subject: [PATCH 05/11] fix: vulnerability (https://security.snyk.io/vuln/SNYK-JS-BRACES-6838727) --- lib/parse.js | 54 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/lib/parse.js b/lib/parse.js index 145ea26..f8e35e1 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -304,30 +304,42 @@ const parse = (input, options = {}) => { push({ type: 'text', value }); } + flattenBlocks(stack) + markImbalancedBraces(ast); + push({ type: 'eos' }); + + return ast; +}; + +module.exports = parse; + +function markImbalancedBraces({nodes}) { // Mark imbalanced braces and brackets as invalid + for (const node of nodes) { + if (node.nodes || node.invalid) + continue; + + if (node.type === 'open') node.isOpen = true; + if (node.type === 'close') node.isClose = true; + if (!node.nodes) node.type = 'text'; + + node.invalid = true; + delete node.parent; + } +} + +function flattenBlocks(stack) { + let block; 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; - } - }); + if (block.type === 'root') + continue; - // 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); - } + // get the location of the block on parent.nodes (block's siblings) + let parent = stack.at(-1); + let index = parent.nodes.indexOf(block); + // replace the (invalid) block with its nodes + parent.nodes.splice(index, 1, ...block.nodes); } while (stack.length > 0); - - push({ type: 'eos' }); - return ast; -}; - -module.exports = parse; +} From 2092bd1fb108d2c59bd62e243b70ad98db961538 Mon Sep 17 00:00:00 2001 From: coderaiser Date: Wed, 15 May 2024 17:55:51 +0300 Subject: [PATCH 06/11] feature: braces: add maxSymbols (https://github.com/micromatch/braces/issues/36#issuecomment-2110820796) --- README.md | 12 ++++++++++++ lib/constants.js | 1 + lib/parse.js | 20 ++++++++++++++------ lib/validate-input.js | 12 ++++++++++++ test/braces.parse.js | 10 ++++++++++ 5 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 lib/validate-input.js diff --git a/README.md b/README.md index 67f2689..363ad11 100644 --- a/README.md +++ b/README.md @@ -186,6 +186,18 @@ console.log(braces.expand('a{b}c')); console.log(braces('a/{b,c}/d', { maxLength: 3 })); //=> throws an error ``` +### options.maxSymbols + +**Type**: `Number` + +**Default**: `1024` + +**Description**: Limit the count of unique symbols the input string. + +```js +console.log(braces('a/{b,c}/d', { maxSymbols: 2 })); //=> throws an error +``` + ### options.expand **Type**: `Boolean` diff --git a/lib/constants.js b/lib/constants.js index a937943..3280bea 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -2,6 +2,7 @@ module.exports = { MAX_LENGTH: 1024 * 64, + MAX_SYMBOLS: 1024, // Digits CHAR_0: '0', /* 0 */ diff --git a/lib/parse.js b/lib/parse.js index f8e35e1..7a724b8 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -1,6 +1,7 @@ 'use strict'; const stringify = require('./stringify'); +const {isCorrectBraces, validateInput} = require('./validate-input'); /** * Constants @@ -8,6 +9,7 @@ const stringify = require('./stringify'); const { MAX_LENGTH, + MAX_SYMBOLS, CHAR_BACKSLASH, /* \ */ CHAR_BACKTICK, /* ` */ CHAR_COMMA, /* , */ @@ -34,6 +36,11 @@ const parse = (input, options = {}) => { } let opts = options || {}; + + validateInput(input, { + maxSymbols: opts.maxSymbols || MAX_SYMBOLS, + }); + 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})`); @@ -316,15 +323,16 @@ module.exports = parse; function markImbalancedBraces({nodes}) { // Mark imbalanced braces and brackets as invalid for (const node of nodes) { - if (node.nodes || node.invalid) - continue; + if (!node.nodes && !node.invalid) { + if (node.type === 'open') node.isOpen = true; + if (node.type === 'close') node.isClose = true; + if (!node.nodes) node.type = 'text'; - if (node.type === 'open') node.isOpen = true; - if (node.type === 'close') node.isClose = true; - if (!node.nodes) node.type = 'text'; + node.invalid = true; + } - node.invalid = true; delete node.parent; + delete node.prev; } } diff --git a/lib/validate-input.js b/lib/validate-input.js new file mode 100644 index 0000000..0f987b6 --- /dev/null +++ b/lib/validate-input.js @@ -0,0 +1,12 @@ +module.exports.validateInput = (line, {maxSymbols}) => { + const symbols = {}; + + for (const current of line) { + symbols[current] = (symbols[current] || 0) + 1; + } + + for (const [value, count] of Object.entries(symbols)) { + if (count > maxSymbols) + throw SyntaxError(`To many symbols '${value}'. Maximum: ${maxSymbols} allowed. Received: ${count}`); + } +}; diff --git a/test/braces.parse.js b/test/braces.parse.js index b814558..09a2361 100644 --- a/test/braces.parse.js +++ b/test/braces.parse.js @@ -10,6 +10,16 @@ describe('braces.parse()', () => { let MAX_LENGTH = 1024 * 64; assert.throws(() => parse('.'.repeat(MAX_LENGTH + 2))); }); + it('should throw an error when symbols exceeds max symbols count default', () => { + let SYMBOLS= 1024; + assert.throws(() => parse('.'.repeat(MAX_SYMBOLS * 2))); + }); + it('should throw an error when symbols exceeds max symbols count ', () => { + let SYMBOLS= 2; + assert.throws(() => parse('...', { + maxSymbols: 2, + })); + }); }); describe('valid', () => { From 716eb9f12d820b145a831ad678618731927e8856 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 17 May 2024 21:35:12 +0000 Subject: [PATCH 07/11] readme bump --- README.md | 187 ++++++++++++++++++++++++++---------------------------- 1 file changed, 90 insertions(+), 97 deletions(-) diff --git a/README.md b/README.md index 363ad11..9d9f9bc 100644 --- a/README.md +++ b/README.md @@ -20,15 +20,15 @@ See the [changelog](CHANGELOG.md) for details. Brace patterns make globs more powerful by adding the ability to match specific ranges and sequences of characters. -* **Accurate** - complete support for the [Bash 4.3 Brace Expansion](www.gnu.org/software/bash/) specification (passes all of the Bash braces tests) -* **[fast and performant](#benchmarks)** - Starts fast, runs fast and [scales well](#performance) as patterns increase in complexity. -* **Organized code base** - The parser and compiler are easy to maintain and update when edge cases crop up. -* **Well-tested** - Thousands of test assertions, and passes all of the Bash, minimatch, and [brace-expansion](https://github.com/juliangruber/brace-expansion) unit tests (as of the date this was written). -* **Safer** - You shouldn't have to worry about users defining aggressive or malicious brace patterns that can break your application. Braces takes measures to prevent malicious regex that can be used for DDoS attacks (see [catastrophic backtracking](https://www.regular-expressions.info/catastrophic.html)). -* [Supports lists](#lists) - (aka "sets") `a/{b,c}/d` => `['a/b/d', 'a/c/d']` -* [Supports sequences](#sequences) - (aka "ranges") `{01..03}` => `['01', '02', '03']` -* [Supports steps](#steps) - (aka "increments") `{2..10..2}` => `['2', '4', '6', '8', '10']` -* [Supports escaping](#escaping) - To prevent evaluation of special characters. +- **Accurate** - complete support for the [Bash 4.3 Brace Expansion](www.gnu.org/software/bash/) specification (passes all of the Bash braces tests) +- **[fast and performant](#benchmarks)** - Starts fast, runs fast and [scales well](#performance) as patterns increase in complexity. +- **Organized code base** - The parser and compiler are easy to maintain and update when edge cases crop up. +- **Well-tested** - Thousands of test assertions, and passes all of the Bash, minimatch, and [brace-expansion](https://github.com/juliangruber/brace-expansion) unit tests (as of the date this was written). +- **Safer** - You shouldn't have to worry about users defining aggressive or malicious brace patterns that can break your application. Braces takes measures to prevent malicious regex that can be used for DDoS attacks (see [catastrophic backtracking](https://www.regular-expressions.info/catastrophic.html)). +- [Supports lists](#lists) - (aka "sets") `a/{b,c}/d` => `['a/b/d', 'a/c/d']` +- [Supports sequences](#sequences) - (aka "ranges") `{01..03}` => `['01', '02', '03']` +- [Supports steps](#steps) - (aka "increments") `{2..10..2}` => `['2', '4', '6', '8', '10']` +- [Supports escaping](#escaping) - To prevent evaluation of special characters. ## Usage @@ -52,9 +52,9 @@ By default, brace patterns are compiled into strings that are optimized for crea **Compiled** ```js -console.log(braces('a/{x,y,z}/b')); +console.log(braces('a/{x,y,z}/b')); //=> ['a/(x|y|z)/b'] -console.log(braces(['a/{01..20}/b', 'a/{1..5}/b'])); +console.log(braces(['a/{01..20}/b', 'a/{1..5}/b'])); //=> [ 'a/(0[1-9]|1[0-9]|20)/b', 'a/([1-5])/b' ] ``` @@ -87,13 +87,13 @@ console.log(braces.expand('a/{foo,bar,baz}/*.js')); Expand ranges of characters (like Bash "sequences"): ```js -console.log(braces.expand('{1..3}')); // ['1', '2', '3'] -console.log(braces.expand('a/{1..3}/b')); // ['a/1/b', 'a/2/b', 'a/3/b'] -console.log(braces('{a..c}', { expand: true })); // ['a', 'b', 'c'] +console.log(braces.expand('{1..3}')); // ['1', '2', '3'] +console.log(braces.expand('a/{1..3}/b')); // ['a/1/b', 'a/2/b', 'a/3/b'] +console.log(braces('{a..c}', { expand: true })); // ['a', 'b', 'c'] console.log(braces('foo/{a..c}', { expand: true })); // ['foo/a', 'foo/b', 'foo/c'] // supports zero-padded ranges -console.log(braces('a/{01..03}/b')); //=> ['a/(0[1-3])/b'] +console.log(braces('a/{01..03}/b')); //=> ['a/(0[1-3])/b'] console.log(braces('a/{001..300}/b')); //=> ['a/(0{2}[1-9]|0[1-9][0-9]|[12][0-9]{2}|300)/b'] ``` @@ -183,7 +183,7 @@ console.log(braces.expand('a{b}c')); **Description**: Limit the length of the input string. Useful when the input string is generated or your application allows users to pass a string, et cetera. ```js -console.log(braces('a/{b,c}/d', { maxLength: 3 })); //=> throws an error +console.log(braces('a/{b,c}/d', { maxLength: 3 })); //=> throws an error ``` ### options.maxSymbols @@ -192,10 +192,10 @@ console.log(braces('a/{b,c}/d', { maxLength: 3 })); //=> throws an error **Default**: `1024` -**Description**: Limit the count of unique symbols the input string. +**Description**: Limit the count of unique symbols the input string. ```js -console.log(braces('a/{b,c}/d', { maxSymbols: 2 })); //=> throws an error +console.log(braces('a/{b,c}/d', { maxSymbols: 2 })); //=> throws an error ``` ### options.expand @@ -256,7 +256,7 @@ const alpha = braces.expand('x/{a..e}/y', { transform(value, index) { // When non-numeric values are passed, "value" is a character code. return 'foo/' + String.fromCharCode(value) + '-' + index; - } + }, }); console.log(alpha); //=> [ 'x/foo/a-0/y', 'x/foo/b-1/y', 'x/foo/c-2/y', 'x/foo/d-3/y', 'x/foo/e-4/y' ] @@ -269,9 +269,9 @@ const numeric = braces.expand('{1..5}', { transform(value) { // when numeric values are passed, "value" is a number return 'foo/' + value * 2; - } + }, }); -console.log(numeric); +console.log(numeric); //=> [ 'foo/2', 'foo/4', 'foo/6', 'foo/8', 'foo/10' ] ``` @@ -293,9 +293,9 @@ The `quantifiers` option tells braces to detect when [regex quantifiers](https:/ const braces = require('braces'); console.log(braces('a/b{1,3}/{x,y,z}')); //=> [ 'a/b(1|3)/(x|y|z)' ] -console.log(braces('a/b{1,3}/{x,y,z}', {quantifiers: true})); +console.log(braces('a/b{1,3}/{x,y,z}', { quantifiers: true })); //=> [ 'a/b{1,3}/(x|y|z)' ] -console.log(braces('a/b{1,3}/{x,y,z}', {quantifiers: true, expand: true})); +console.log(braces('a/b{1,3}/{x,y,z}', { quantifiers: true, expand: true })); //=> [ 'a/b{1,3}/x', 'a/b{1,3}/y', 'a/b{1,3}/z' ] ``` @@ -313,8 +313,8 @@ Brace expansion is a type of parameter expansion that was made popular by unix s In addition to "expansion", braces are also used for matching. In other words: -* [brace expansion](#brace-expansion) is for generating new lists -* [brace matching](#brace-matching) is for filtering existing lists +- [brace expansion](#brace-expansion) is for generating new lists +- [brace matching](#brace-matching) is for filtering existing lists
More about brace expansion (click to expand) @@ -394,9 +394,9 @@ Although brace patterns offer a user-friendly way of matching ranges or sets of **"brace bombs"** -* brace expansion can eat up a huge amount of processing resources -* as brace patterns increase _linearly in size_, the system resources required to expand the pattern increase exponentially -* users can accidentally (or intentially) exhaust your system's resources resulting in the equivalent of a DoS attack (bonus: no programming knowledge is required!) +- brace expansion can eat up a huge amount of processing resources +- as brace patterns increase _linearly in size_, the system resources required to expand the pattern increase exponentially +- users can accidentally (or intentially) exhaust your system's resources resulting in the equivalent of a DoS attack (bonus: no programming knowledge is required!) For a more detailed explanation with examples, see the [geometric complexity](#geometric-complexity) section. @@ -418,8 +418,8 @@ For example, the following sets demonstrate quadratic (`O(n^2)`) complexity: But add an element to a set, and we get a n-fold Cartesian product with `O(n^c)` complexity: ``` -{1,2,3}{4,5,6}{7,8,9} => (3X3X3) => 147 148 149 157 158 159 167 168 169 247 248 - 249 257 258 259 267 268 269 347 348 349 357 +{1,2,3}{4,5,6}{7,8,9} => (3X3X3) => 147 148 149 157 158 159 167 168 169 247 248 + 249 257 258 259 267 268 269 347 348 349 357 358 359 367 368 369 ``` @@ -436,9 +436,9 @@ Although these examples are clearly contrived, they demonstrate how brace patter Interested in learning more about brace expansion? -* [linuxjournal/bash-brace-expansion](http://www.linuxjournal.com/content/bash-brace-expansion) -* [rosettacode/Brace_expansion](https://rosettacode.org/wiki/Brace_expansion) -* [cartesian product](https://en.wikipedia.org/wiki/Cartesian_product) +- [linuxjournal/bash-brace-expansion](http://www.linuxjournal.com/content/bash-brace-expansion) +- [rosettacode/Brace_expansion](https://rosettacode.org/wiki/Brace_expansion) +- [cartesian product](https://en.wikipedia.org/wiki/Cartesian_product)
@@ -456,25 +456,25 @@ Instead, convert the pattern into an optimized regular expression. This is easie Minimatch gets exponentially slower as patterns increase in complexity, braces does not. The following results were generated using `braces()` and `minimatch.braceExpand()`, respectively. -| **Pattern** | **braces** | **[minimatch][]** | -| --- | --- | --- | -| `{1..9007199254740991}`[^1] | `298 B` (5ms 459μs)| N/A (freezes) | -| `{1..1000000000000000}` | `41 B` (1ms 15μs) | N/A (freezes) | -| `{1..100000000000000}` | `40 B` (890μs) | N/A (freezes) | -| `{1..10000000000000}` | `39 B` (2ms 49μs) | N/A (freezes) | -| `{1..1000000000000}` | `38 B` (608μs) | N/A (freezes) | -| `{1..100000000000}` | `37 B` (397μs) | N/A (freezes) | -| `{1..10000000000}` | `35 B` (983μs) | N/A (freezes) | -| `{1..1000000000}` | `34 B` (798μs) | N/A (freezes) | -| `{1..100000000}` | `33 B` (733μs) | N/A (freezes) | -| `{1..10000000}` | `32 B` (5ms 632μs) | `78.89 MB` (16s 388ms 569μs) | -| `{1..1000000}` | `31 B` (1ms 381μs) | `6.89 MB` (1s 496ms 887μs) | -| `{1..100000}` | `30 B` (950μs) | `588.89 kB` (146ms 921μs) | -| `{1..10000}` | `29 B` (1ms 114μs) | `48.89 kB` (14ms 187μs) | -| `{1..1000}` | `28 B` (760μs) | `3.89 kB` (1ms 453μs) | -| `{1..100}` | `22 B` (345μs) | `291 B` (196μs) | -| `{1..10}` | `10 B` (533μs) | `20 B` (37μs) | -| `{1..3}` | `7 B` (190μs) | `5 B` (27μs) | +| **Pattern** | **braces** | **[minimatch][]** | +| --------------------------- | ------------------- | ---------------------------- | +| `{1..9007199254740991}`[^1] | `298 B` (5ms 459μs) | N/A (freezes) | +| `{1..1000000000000000}` | `41 B` (1ms 15μs) | N/A (freezes) | +| `{1..100000000000000}` | `40 B` (890μs) | N/A (freezes) | +| `{1..10000000000000}` | `39 B` (2ms 49μs) | N/A (freezes) | +| `{1..1000000000000}` | `38 B` (608μs) | N/A (freezes) | +| `{1..100000000000}` | `37 B` (397μs) | N/A (freezes) | +| `{1..10000000000}` | `35 B` (983μs) | N/A (freezes) | +| `{1..1000000000}` | `34 B` (798μs) | N/A (freezes) | +| `{1..100000000}` | `33 B` (733μs) | N/A (freezes) | +| `{1..10000000}` | `32 B` (5ms 632μs) | `78.89 MB` (16s 388ms 569μs) | +| `{1..1000000}` | `31 B` (1ms 381μs) | `6.89 MB` (1s 496ms 887μs) | +| `{1..100000}` | `30 B` (950μs) | `588.89 kB` (146ms 921μs) | +| `{1..10000}` | `29 B` (1ms 114μs) | `48.89 kB` (14ms 187μs) | +| `{1..1000}` | `28 B` (760μs) | `3.89 kB` (1ms 453μs) | +| `{1..100}` | `22 B` (345μs) | `291 B` (196μs) | +| `{1..10}` | `10 B` (533μs) | `20 B` (37μs) | +| `{1..3}` | `7 B` (190μs) | `5 B` (27μs) | ### Faster algorithms @@ -483,7 +483,7 @@ When you need expansion, braces is still much faster. _(the following results were generated using `braces.expand()` and `minimatch.braceExpand()`, respectively)_ | **Pattern** | **braces** | **[minimatch][]** | -| --- | --- | --- | +| --------------- | --------------------------- | ---------------------------- | | `{1..10000000}` | `78.89 MB` (2s 698ms 642μs) | `78.89 MB` (18s 601ms 974μs) | | `{1..1000000}` | `6.89 MB` (458ms 576μs) | `6.89 MB` (1s 491ms 621μs) | | `{1..100000}` | `588.89 kB` (20ms 728μs) | `588.89 kB` (156ms 919μs) | @@ -510,37 +510,30 @@ npm i -d && npm benchmark Braces is more accurate, without sacrificing performance. ```bash -# range (expanded) - braces x 29,040 ops/sec ±3.69% (91 runs sampled)) - minimatch x 4,735 ops/sec ±1.28% (90 runs sampled) - -# range (optimized for regex) - braces x 382,878 ops/sec ±0.56% (94 runs sampled) - minimatch x 1,040 ops/sec ±0.44% (93 runs sampled) - -# nested ranges (expanded) - braces x 19,744 ops/sec ±2.27% (92 runs sampled)) - minimatch x 4,579 ops/sec ±0.50% (93 runs sampled) - -# nested ranges (optimized for regex) - braces x 246,019 ops/sec ±2.02% (93 runs sampled) - minimatch x 1,028 ops/sec ±0.39% (94 runs sampled) - -# set (expanded) - braces x 138,641 ops/sec ±0.53% (95 runs sampled) - minimatch x 219,582 ops/sec ±0.98% (94 runs sampled) - -# set (optimized for regex) - braces x 388,408 ops/sec ±0.41% (95 runs sampled) - minimatch x 44,724 ops/sec ±0.91% (89 runs sampled) - -# nested sets (expanded) - braces x 84,966 ops/sec ±0.48% (94 runs sampled) - minimatch x 140,720 ops/sec ±0.37% (95 runs sampled) - -# nested sets (optimized for regex) - braces x 263,340 ops/sec ±2.06% (92 runs sampled) - minimatch x 28,714 ops/sec ±0.40% (90 runs sampled) +● expand - range (expanded) + braces x 53,167 ops/sec ±0.12% (102 runs sampled) + minimatch x 11,378 ops/sec ±0.10% (102 runs sampled) +● expand - range (optimized for regex) + braces x 373,442 ops/sec ±0.04% (100 runs sampled) + minimatch x 3,262 ops/sec ±0.18% (100 runs sampled) +● expand - nested ranges (expanded) + braces x 33,921 ops/sec ±0.09% (99 runs sampled) + minimatch x 10,855 ops/sec ±0.28% (100 runs sampled) +● expand - nested ranges (optimized for regex) + braces x 287,479 ops/sec ±0.52% (98 runs sampled) + minimatch x 3,219 ops/sec ±0.28% (101 runs sampled) +● expand - set (expanded) + braces x 238,243 ops/sec ±0.19% (97 runs sampled) + minimatch x 538,268 ops/sec ±0.31% (96 runs sampled) +● expand - set (optimized for regex) + braces x 321,844 ops/sec ±0.10% (97 runs sampled) + minimatch x 140,600 ops/sec ±0.15% (100 runs sampled) +● expand - nested sets (expanded) + braces x 165,371 ops/sec ±0.42% (96 runs sampled) + minimatch x 337,720 ops/sec ±0.28% (100 runs sampled) +● expand - nested sets (optimized for regex) + braces x 242,948 ops/sec ±0.12% (99 runs sampled) + minimatch x 87,403 ops/sec ±0.79% (96 runs sampled) ``` ## About @@ -578,28 +571,28 @@ $ npm install -g verbose/verb#dev verb-generate-readme && verb ### Contributors -| **Commits** | **Contributor** | -| --- | --- | -| 197 | [jonschlinkert](https://github.com/jonschlinkert) | -| 4 | [doowb](https://github.com/doowb) | -| 1 | [es128](https://github.com/es128) | -| 1 | [eush77](https://github.com/eush77) | -| 1 | [hemanth](https://github.com/hemanth) | -| 1 | [wtgtybhertgeghgtwtg](https://github.com/wtgtybhertgeghgtwtg) | +| **Commits** | **Contributor** | +| ----------- | ------------------------------------------------------------- | +| 197 | [jonschlinkert](https://github.com/jonschlinkert) | +| 4 | [doowb](https://github.com/doowb) | +| 1 | [es128](https://github.com/es128) | +| 1 | [eush77](https://github.com/eush77) | +| 1 | [hemanth](https://github.com/hemanth) | +| 1 | [wtgtybhertgeghgtwtg](https://github.com/wtgtybhertgeghgtwtg) | ### Author **Jon Schlinkert** -* [GitHub Profile](https://github.com/jonschlinkert) -* [Twitter Profile](https://twitter.com/jonschlinkert) -* [LinkedIn Profile](https://linkedin.com/in/jonschlinkert) +- [GitHub Profile](https://github.com/jonschlinkert) +- [Twitter Profile](https://twitter.com/jonschlinkert) +- [LinkedIn Profile](https://linkedin.com/in/jonschlinkert) ### License Copyright © 2019, [Jon Schlinkert](https://github.com/jonschlinkert). Released under the [MIT License](LICENSE). -*** +--- -_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.8.0, on April 08, 2019._ \ No newline at end of file +_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.8.0, on April 08, 2019._ From 190510f79db1adf21d92798b0bb6fccc1f72c9d6 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 17 May 2024 21:41:57 +0000 Subject: [PATCH 08/11] fix tests, skip 1 test in test/braces.expand --- test/braces.compile.js | 4 ++-- test/braces.expand.js | 44 +++++++++++++++++++++++++++++++----------- test/readme.js | 42 +++++++++++++++++++++++++++------------- 3 files changed, 64 insertions(+), 26 deletions(-) diff --git a/test/braces.compile.js b/test/braces.compile.js index 41d4b25..fc8697d 100644 --- a/test/braces.compile.js +++ b/test/braces.compile.js @@ -53,11 +53,11 @@ describe('braces.compile()', () => { }); it('should compile zero-padded numeric ranges', () => { - assert.equal(compile(parse('{01..05}')), '(0[1-5])'); + assert.equal(compile(parse('{01..05}')), '(0?[1-5])'); }); it('should compile zero-padded numeric ranges with increments', () => { - assert.equal(compile(parse('{01..05..2}')), '(01|03|05)'); + assert.equal(compile(parse('{01..05..2}')), '(1|3|5)'); }); }); diff --git a/test/braces.expand.js b/test/braces.expand.js index 98012ef..4d34c62 100644 --- a/test/braces.expand.js +++ b/test/braces.expand.js @@ -8,8 +8,9 @@ const bashPath = require('bash-path'); const cp = require('child_process'); const braces = require('..'); -const bash = input => { - return cp.spawnSync(bashPath(), ['-c', `echo ${input}`]) +const bash = (input) => { + return cp + .spawnSync(bashPath(), ['-c', `echo ${input}`]) .stdout.toString() .split(/\s+/) .filter(Boolean); @@ -21,7 +22,7 @@ const equal = (input, expected = bash(input), options) => { describe('unit tests from brace-expand', () => { describe('extglobs', () => { - it('should split on commas when braces are inside extglobs', () => { + it.skip('should split on commas when braces are inside extglobs', () => { equal('*(a|{b|c,d})', ['*(a|b|c)', '*(a|d)']); }); @@ -37,21 +38,43 @@ describe('unit tests from brace-expand', () => { }); it('should support expanded nested empty sets', () => { - equal('{\`foo,bar\`}', ['{`foo,bar`}'], { keepQuotes: true }); + equal('{`foo,bar`}', ['{`foo,bar`}'], { keepQuotes: true }); equal('{\\`foo,bar\\`}', ['`foo', 'bar`'], { keepQuotes: true }); - equal('{`foo\,bar`}', ['{`foo,bar`}'], { keepQuotes: true }); + equal('{`foo,bar`}', ['{`foo,bar`}'], { keepQuotes: true }); equal('{`foo\\,bar`}', ['{`foo\\,bar`}'], { keepQuotes: true }); - equal('{\`foo,bar\`}', ['{foo,bar}']); + equal('{`foo,bar`}', ['{foo,bar}']); equal('{\\`foo,bar\\`}', ['`foo', 'bar`']); - equal('{`foo\,bar`}', ['{foo,bar}']); + equal('{`foo,bar`}', ['{foo,bar}']); equal('{`foo\\,bar`}', ['{foo\\,bar}']); equal('{a,\\\\{a,b}c}', ['a', '\\ac', '\\bc']); equal('{a,\\{a,b}c}', ['ac}', '{ac}', 'bc}']); equal('{,eno,thro,ro}ugh', ['ugh', 'enough', 'through', 'rough']); - equal('{,{,eno,thro,ro}ugh}{,out}', ['', 'out', 'ugh', 'ughout', 'enough', 'enoughout', 'through', 'throughout', 'rough', 'roughout']); - equal('{{,eno,thro,ro}ugh,}{,out}', ['ugh', 'ughout', 'enough', 'enoughout', 'through', 'throughout', 'rough', 'roughout', '', 'out']); + equal('{,{,eno,thro,ro}ugh}{,out}', [ + '', + 'out', + 'ugh', + 'ughout', + 'enough', + 'enoughout', + 'through', + 'throughout', + 'rough', + 'roughout', + ]); + equal('{{,eno,thro,ro}ugh,}{,out}', [ + 'ugh', + 'ughout', + 'enough', + 'enoughout', + 'through', + 'throughout', + 'rough', + 'roughout', + '', + 'out', + ]); equal('{,{,a,b}z}{,c}', ['', 'c', 'z', 'zc', 'az', 'azc', 'bz', 'bzc']); equal('{,{,a,b}z}{c,}', ['c', '', 'zc', 'z', 'azc', 'az', 'bzc', 'bz']); equal('{,{,a,b}z}{,c,}', ['', 'c', '', 'z', 'zc', 'z', 'az', 'azc', 'az', 'bz', 'bzc', 'bz']); @@ -66,7 +89,7 @@ describe('unit tests from brace-expand', () => { equal('{,{a,}}{z,c}', ['z', 'c', 'az', 'ac', 'z', 'c']); equal('{,{,a}}{z,c}', ['z', 'c', 'z', 'c', 'az', 'ac']); equal('{,{,a},}{z,c}', ['z', 'c', 'z', 'c', 'az', 'ac', 'z', 'c']); - equal('{{,,a}}{z,c}', [ '{}z', '{}c', '{}z', '{}c', '{a}z', '{a}c' ]); + equal('{{,,a}}{z,c}', ['{}z', '{}c', '{}z', '{}c', '{a}z', '{a}c']); equal('{{,a},}{z,c}', ['z', 'c', 'az', 'ac', 'z', 'c']); equal('{,,a}{z,c}', ['z', 'c', 'z', 'c', 'az', 'ac']); equal('{,{,}}{z,c}', ['z', 'c', 'z', 'c', 'z', 'c']); @@ -177,4 +200,3 @@ describe('unit tests from brace-expand', () => { }); }); }); - diff --git a/test/readme.js b/test/readme.js index 1c1731c..bb983ba 100644 --- a/test/readme.js +++ b/test/readme.js @@ -7,28 +7,44 @@ const braces = require('..'); describe('Examples from README.md', () => { describe('Brace Expansion vs. Compilation', () => { it('Compiled', () => { - assert.deepEqual( braces('a/{x,y,z}/b'), ['a/(x|y|z)/b'] ); - assert.deepEqual( braces(['a/{01..20}/b', 'a/{1..5}/b']), [ 'a/(0[1-9]|1[0-9]|20)/b', 'a/([1-5])/b' ] ); + assert.deepEqual(braces('a/{x,y,z}/b'), ['a/(x|y|z)/b']); + assert.deepEqual(braces(['a/{01..20}/b', 'a/{1..5}/b']), [ + 'a/(0?[1-9]|1[0-9]|20)/b', + 'a/([1-5])/b', + ]); }); it('Expanded', () => { - assert.deepEqual(braces('a/{x,y,z}/b', { expand: true }), ['a/x/b', 'a/y/b', 'a/z/b'] ); - assert.deepEqual(braces.expand('{01..10}'), ['01','02','03','04','05','06','07','08','09','10'] ); + assert.deepEqual(braces('a/{x,y,z}/b', { expand: true }), ['a/x/b', 'a/y/b', 'a/z/b']); + assert.deepEqual(braces.expand('{01..10}'), [ + '01', + '02', + '03', + '04', + '05', + '06', + '07', + '08', + '09', + '10', + ]); }); }); describe('Sequences', () => { it('first set of examples', () => { - assert.deepEqual( braces.expand('{1..3}'), ['1', '2', '3']); - assert.deepEqual( braces.expand('a/{1..3}/b'), ['a/1/b', 'a/2/b', 'a/3/b']); - assert.deepEqual( braces('{a..c}', { expand: true }), ['a', 'b', 'c']); - assert.deepEqual( braces('foo/{a..c}', { expand: true }), ['foo/a', 'foo/b', 'foo/c']); - }) + assert.deepEqual(braces.expand('{1..3}'), ['1', '2', '3']); + assert.deepEqual(braces.expand('a/{1..3}/b'), ['a/1/b', 'a/2/b', 'a/3/b']); + assert.deepEqual(braces('{a..c}', { expand: true }), ['a', 'b', 'c']); + assert.deepEqual(braces('foo/{a..c}', { expand: true }), ['foo/a', 'foo/b', 'foo/c']); + }); it('zero-padding examples', () => { // supports zero-padded ranges - assert.deepEqual( braces('a/{01..03}/b'), ['a/(0[1-3])/b']); - assert.deepEqual( braces('a/{001..300}/b'), ['a/(0{2}[1-9]|0[1-9][0-9]|[12][0-9]{2}|300)/b']); - }) + assert.deepEqual(braces('a/{01..03}/b'), ['a/(0?[1-3])/b']); + assert.deepEqual(braces('a/{001..300}/b'), [ + 'a/(0{0,2}[1-9]|0?[1-9][0-9]|[12][0-9]{2}|300)/b', + ]); + }); }); -}); \ No newline at end of file +}); From 415d660c3002d1ab7e63dbf490c9851da80596ff Mon Sep 17 00:00:00 2001 From: Aaron Moat <2937187+AaronMoat@users.noreply.github.com> Date: Tue, 21 May 2024 17:42:30 +1000 Subject: [PATCH 09/11] Snyk js braces 6838727 (#40) * Remove maxSymbols from README * Revert "Merge pull request #37 from coderaiser/fix/vulnerability" This reverts commit a5851e57f45c3431a94d83fc565754bc10f5bbc3, reversing changes made to 98414f9f1fabe021736e26836d8306d5de747e0d. * Lower defaultLength to 10000 --- .verb.md | 2 +- README.md | 14 +--------- lib/constants.js | 3 +-- lib/parse.js | 62 +++++++++++++++---------------------------- lib/validate-input.js | 12 --------- test/braces.parse.js | 10 ------- 6 files changed, 24 insertions(+), 79 deletions(-) delete mode 100644 lib/validate-input.js diff --git a/.verb.md b/.verb.md index cdedd55..2ee6767 100644 --- a/.verb.md +++ b/.verb.md @@ -167,7 +167,7 @@ console.log(braces.expand('a{b}c')); **Type**: `Number` -**Default**: `65,536` +**Default**: `10,000` **Description**: Limit the length of the input string. Useful when the input string is generated or your application allows users to pass a string, et cetera. diff --git a/README.md b/README.md index 9d9f9bc..f59dd60 100644 --- a/README.md +++ b/README.md @@ -178,7 +178,7 @@ console.log(braces.expand('a{b}c')); **Type**: `Number` -**Default**: `65,536` +**Default**: `10,000` **Description**: Limit the length of the input string. Useful when the input string is generated or your application allows users to pass a string, et cetera. @@ -186,18 +186,6 @@ console.log(braces.expand('a{b}c')); console.log(braces('a/{b,c}/d', { maxLength: 3 })); //=> throws an error ``` -### options.maxSymbols - -**Type**: `Number` - -**Default**: `1024` - -**Description**: Limit the count of unique symbols the input string. - -```js -console.log(braces('a/{b,c}/d', { maxSymbols: 2 })); //=> throws an error -``` - ### options.expand **Type**: `Boolean` diff --git a/lib/constants.js b/lib/constants.js index 3280bea..2bb3b88 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -1,8 +1,7 @@ 'use strict'; module.exports = { - MAX_LENGTH: 1024 * 64, - MAX_SYMBOLS: 1024, + MAX_LENGTH: 10000, // Digits CHAR_0: '0', /* 0 */ diff --git a/lib/parse.js b/lib/parse.js index 7a724b8..145ea26 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -1,7 +1,6 @@ 'use strict'; const stringify = require('./stringify'); -const {isCorrectBraces, validateInput} = require('./validate-input'); /** * Constants @@ -9,7 +8,6 @@ const {isCorrectBraces, validateInput} = require('./validate-input'); const { MAX_LENGTH, - MAX_SYMBOLS, CHAR_BACKSLASH, /* \ */ CHAR_BACKTICK, /* ` */ CHAR_COMMA, /* , */ @@ -36,11 +34,6 @@ const parse = (input, options = {}) => { } let opts = options || {}; - - validateInput(input, { - maxSymbols: opts.maxSymbols || MAX_SYMBOLS, - }); - 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})`); @@ -311,43 +304,30 @@ const parse = (input, options = {}) => { push({ type: 'text', value }); } - flattenBlocks(stack) - markImbalancedBraces(ast); - push({ type: 'eos' }); - - return ast; -}; - -module.exports = parse; - -function markImbalancedBraces({nodes}) { // Mark imbalanced braces and brackets as invalid - for (const node of nodes) { - if (!node.nodes && !node.invalid) { - if (node.type === 'open') node.isOpen = true; - if (node.type === 'close') node.isClose = true; - if (!node.nodes) node.type = 'text'; - - node.invalid = true; - } - - delete node.parent; - delete node.prev; - } -} - -function flattenBlocks(stack) { - let block; do { block = stack.pop(); - if (block.type === 'root') - continue; + 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.at(-1); - let index = parent.nodes.indexOf(block); - // replace the (invalid) block with its nodes - parent.nodes.splice(index, 1, ...block.nodes); + // 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; diff --git a/lib/validate-input.js b/lib/validate-input.js deleted file mode 100644 index 0f987b6..0000000 --- a/lib/validate-input.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports.validateInput = (line, {maxSymbols}) => { - const symbols = {}; - - for (const current of line) { - symbols[current] = (symbols[current] || 0) + 1; - } - - for (const [value, count] of Object.entries(symbols)) { - if (count > maxSymbols) - throw SyntaxError(`To many symbols '${value}'. Maximum: ${maxSymbols} allowed. Received: ${count}`); - } -}; diff --git a/test/braces.parse.js b/test/braces.parse.js index 09a2361..b814558 100644 --- a/test/braces.parse.js +++ b/test/braces.parse.js @@ -10,16 +10,6 @@ describe('braces.parse()', () => { let MAX_LENGTH = 1024 * 64; assert.throws(() => parse('.'.repeat(MAX_LENGTH + 2))); }); - it('should throw an error when symbols exceeds max symbols count default', () => { - let SYMBOLS= 1024; - assert.throws(() => parse('.'.repeat(MAX_SYMBOLS * 2))); - }); - it('should throw an error when symbols exceeds max symbols count ', () => { - let SYMBOLS= 2; - assert.throws(() => parse('...', { - maxSymbols: 2, - })); - }); }); describe('valid', () => { From 88f1429a0f47e1dd3813de35211fc97ffda27f9e Mon Sep 17 00:00:00 2001 From: Jon Schlinkert Date: Tue, 21 May 2024 04:57:43 -0400 Subject: [PATCH 10/11] update eslint. lint, fix unit tests. --- .eslintrc.json | 189 +++++++++++++++------ LICENSE | 2 +- bench/index.js | 2 +- examples/expand.js | 3 +- examples/option-transform.js | 2 +- index.js | 6 +- lib/compile.js | 25 +-- lib/expand.js | 18 +- lib/parse.js | 30 ++-- lib/stringify.js | 8 +- lib/utils.js | 16 +- package.json | 2 +- test/bash-compiled-ranges.js | 6 +- test/bash-compiled-sets.js | 14 +- test/bash-expanded-ranges.js | 104 ++++++------ test/bash-expanded-sets.js | 300 ++++++++++++++++----------------- test/bash-spec.js | 312 +++++++++++++++++------------------ test/braces.compile.js | 5 +- test/braces.expand.js | 8 +- test/braces.parse.js | 18 +- test/minimatch.js | 8 +- test/readme.js | 12 +- test/regression.js | 2 +- 23 files changed, 593 insertions(+), 499 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 24b8984..cf4d887 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,13 +1,12 @@ { - "extends": [ - "eslint:recommended" - ], + "root": true, + "extends": "eslint:recommended", "env": { "browser": false, "es6": true, - "node": true, - "mocha": true + "mocha": true, + "node": true }, "parserOptions":{ @@ -27,29 +26,52 @@ "rules": { "accessor-pairs": 2, - "arrow-spacing": [2, { "before": true, "after": true }], - "block-spacing": [2, "always"], - "brace-style": [2, "1tbs", { "allowSingleLine": true }], - "comma-dangle": [2, "never"], - "comma-spacing": [2, { "before": false, "after": true }], - "comma-style": [2, "last"], + "array-bracket-newline": [1, "consistent"], + "array-bracket-spacing": [1, "never"], + "array-callback-return": 1, + "array-element-newline": [1, "consistent"], + "arrow-body-style": 0, + "arrow-parens": [1, "as-needed"], + "arrow-spacing": [1, { "before": true, "after": true }], + "block-scoped-var": 1, + "block-spacing": [1, "always"], + "brace-style": [1, "1tbs", { "allowSingleLine": true }], + "callback-return": 0, + "camelcase": [0, { "allow": [] }], + "capitalized-comments": 0, + "class-methods-use-this": 0, + "comma-dangle": [1, "never"], + "comma-spacing": [1, { "before": false, "after": true }], + "comma-style": [1, "last"], + "computed-property-spacing": 1, + "consistent-return": 0, + "consistent-this": 1, "constructor-super": 2, - "curly": [2, "multi-line"], - "dot-location": [2, "property"], - "eol-last": 2, - "eqeqeq": [2, "allow-null"], - "generator-star-spacing": [2, { "before": true, "after": true }], - "handle-callback-err": [2, "^(err|error)$" ], - "indent": [2, 2, { "SwitchCase": 1 }], - "key-spacing": [2, { "beforeColon": false, "afterColon": true }], - "keyword-spacing": [2, { "before": true, "after": true }], - "new-cap": [2, { "newIsCap": true, "capIsNew": false }], + "curly": [1, "multi-line", "consistent"], + "default-case": 1, + "dot-location": [1, "property"], + "dot-notation": 1, + "eol-last": 1, + "eqeqeq": [1, "allow-null"], + "for-direction": 1, + "func-call-spacing": 2, + "generator-star-spacing": [1, { "before": true, "after": true }], + "handle-callback-err": [2, "^(err|error)$"], + "indent": [1, 2, { "SwitchCase": 1 }], + "key-spacing": [1, { "beforeColon": false, "afterColon": true }], + "keyword-spacing": [1, { "before": true, "after": true }], + "linebreak-style": [1, "unix"], + "new-cap": [1, { "newIsCap": true, "capIsNew": false }], "new-parens": 2, - "no-array-constructor": 2, + "no-alert": 1, + "no-array-constructor": 1, + "no-async-promise-executor": 1, "no-caller": 2, + "no-case-declarations": 1, "no-class-assign": 2, "no-cond-assign": 2, "no-const-assign": 2, + "no-constant-condition": [1, { "checkLoops": false }], "no-control-regex": 2, "no-debugger": 2, "no-delete-var": 2, @@ -57,74 +79,137 @@ "no-dupe-class-members": 2, "no-dupe-keys": 2, "no-duplicate-case": 2, + "no-duplicate-imports": 0, + "no-else-return": 0, "no-empty-character-class": 2, - "no-eval": 2, + "no-empty-function": 0, + "no-empty-pattern": 0, + "no-empty": [1, { "allowEmptyCatch": true }], + "no-eval": 0, "no-ex-assign": 2, "no-extend-native": 2, - "no-extra-bind": 2, - "no-extra-boolean-cast": 2, - "no-extra-parens": [2, "functions"], + "no-extra-bind": 1, + "no-extra-boolean-cast": 1, + "no-extra-label": 1, + "no-extra-parens": [1, "all", + { + "conditionalAssign": false, + "returnAssign": false, + "nestedBinaryExpressions": false, + "ignoreJSX": "multi-line", + "enforceForArrowConditionals": false + } + ], + "no-extra-semi": 1, "no-fallthrough": 2, "no-floating-decimal": 2, "no-func-assign": 2, + "no-global-assign": 2, + "no-implicit-coercion": 2, + "no-implicit-globals": 1, "no-implied-eval": 2, - "no-inner-declarations": [2, "functions"], + "no-inner-declarations": [1, "functions"], "no-invalid-regexp": 2, + "no-invalid-this": 1, "no-irregular-whitespace": 2, "no-iterator": 2, "no-label-var": 2, "no-labels": 2, "no-lone-blocks": 2, + "no-lonely-if": 2, + "no-loop-func": 1, + "no-mixed-requires": 1, "no-mixed-spaces-and-tabs": 2, - "no-multi-spaces": 2, + "no-multi-assign": 0, + "no-multi-spaces": 1, "no-multi-str": 2, - "no-multiple-empty-lines": [2, { "max": 1 }], - "no-native-reassign": 0, + "no-multiple-empty-lines": [1, { "max": 1 }], + "no-native-reassign": 2, + "no-negated-condition": 0, "no-negated-in-lhs": 2, - "no-new": 2, "no-new-func": 2, "no-new-object": 2, "no-new-require": 2, + "no-new-symbol": 1, "no-new-wrappers": 2, + "no-new": 1, "no-obj-calls": 2, - "no-octal": 2, "no-octal-escape": 2, - "no-proto": 0, + "no-octal": 2, + "no-path-concat": 1, + "no-proto": 2, + "no-prototype-builtins": 0, "no-redeclare": 2, "no-regex-spaces": 2, - "no-return-assign": 2, - "no-self-compare": 2, + "no-restricted-globals": 2, + "no-return-assign": 1, + "no-return-await": 2, + "no-script-url": 1, + "no-self-assign": 1, + "no-self-compare": 1, "no-sequences": 2, "no-shadow-restricted-names": 2, + "no-shadow": 0, "no-spaced-func": 2, "no-sparse-arrays": 2, + "no-template-curly-in-string": 0, "no-this-before-super": 2, "no-throw-literal": 2, - "no-trailing-spaces": 0, - "no-undef": 2, + "no-trailing-spaces": 1, "no-undef-init": 2, + "no-undef": 2, "no-unexpected-multiline": 2, - "no-unneeded-ternary": [2, { "defaultAssignment": false }], + "no-unneeded-ternary": [1, { "defaultAssignment": false }], + "no-unreachable-loop": 1, "no-unreachable": 2, - "no-unused-vars": [2, { "vars": "all", "args": "none" }], - "no-useless-call": 0, + "no-unsafe-assignment": 0, + "no-unsafe-call": 0, + "no-unsafe-finally": 2, + "no-unsafe-member-access": 0, + "no-unsafe-negation": 2, + "no-unsafe-optional-chaining": 0, + "no-unsafe-return": 0, + "no-unused-expressions": 2, + "no-unused-vars": [1, { "vars": "all", "args": "after-used" }], + "no-use-before-define": 0, + "no-useless-call": 2, + "no-useless-catch": 0, + "no-useless-escape": 0, + "no-useless-rename": 1, + "no-useless-return": 1, + "no-var": 1, + "no-void": 1, + "no-warning-comments": 0, "no-with": 2, - "one-var": [0, { "initialized": "never" }], + "object-curly-spacing": [1, "always", { "objectsInObjects": true }], + "object-shorthand": 1, + "one-var": [1, { "initialized": "never" }], "operator-linebreak": [0, "after", { "overrides": { "?": "before", ":": "before" } }], - "padded-blocks": [0, "never"], - "quotes": [2, "single", "avoid-escape"], + "padded-blocks": [1, { "switches": "never" }], + "prefer-const": [1, { "destructuring": "all", "ignoreReadBeforeAssign": false }], + "prefer-promise-reject-errors": 1, + "quotes": [1, "single", "avoid-escape"], "radix": 2, - "semi": [2, "always"], - "semi-spacing": [2, { "before": false, "after": true }], - "space-before-blocks": [2, "always"], - "space-before-function-paren": [2, "never"], - "space-in-parens": [2, "never"], - "space-infix-ops": 2, - "space-unary-ops": [2, { "words": true, "nonwords": false }], + "rest-spread-spacing": 1, + "semi-spacing": [1, { "before": false, "after": true }], + "semi-style": 1, + "semi": [1, "always"], + "space-before-blocks": [1, "always"], + "space-before-function-paren": [1, { "anonymous": "never", "named": "never", "asyncArrow": "always" }], + "space-in-parens": [1, "never"], + "space-infix-ops": 1, + "space-unary-ops": [1, { "words": true, "nonwords": false }], "spaced-comment": [0, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!", ","] }], + "strict": 2, + "switch-colon-spacing": 1, + "symbol-description": 1, + "template-curly-spacing": [2, "never"], + "template-tag-spacing": [2, "never"], + "unicode-bom": 1, "use-isnan": 2, + "valid-jsdoc": 1, "valid-typeof": 2, - "wrap-iife": [2, "any"], - "yoda": [2, "never"] + "wrap-iife": [1, "any"], + "yoda": [1, "never"] } } diff --git a/LICENSE b/LICENSE index d32ab44..9af4a67 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014-2018, Jon Schlinkert. +Copyright (c) 2014-present, Jon Schlinkert. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/bench/index.js b/bench/index.js index d1ff170..2a9cf76 100644 --- a/bench/index.js +++ b/bench/index.js @@ -11,7 +11,7 @@ const braces = require('..'); */ const cycle = (e, newline) => { - process.stdout.write(`\u001b[G ${e.target}${newline ? `\n` : ''}`); + process.stdout.write(`\u001b[G ${e.target}${newline ? '\n' : ''}`); }; const bench = (name, options) => { diff --git a/examples/expand.js b/examples/expand.js index 8efaefc..5e458f1 100644 --- a/examples/expand.js +++ b/examples/expand.js @@ -1,6 +1,5 @@ const colors = require('ansi-colors'); -const parse = require('./parse'); const color = (arr, c) => arr.map(s => c(s)).join(', '); const cp = require('child_process'); const braces = input => { @@ -19,6 +18,6 @@ const braces = input => { const fixture = 'a{,b}c'; console.log(); console.log(' FIXTURE:', colors.magenta(fixture)); -console.log(' ACTUAL:', color(expand(parse(fixture)), colors.yellow)); +// console.log(' ACTUAL:', color(expand(parse(fixture)), colors.yellow)); console.log('EXPECTED:', color(braces(fixture), colors.blue)); console.log(); diff --git a/examples/option-transform.js b/examples/option-transform.js index c012e9a..9c36bc0 100644 --- a/examples/option-transform.js +++ b/examples/option-transform.js @@ -11,7 +11,7 @@ console.log(alpha); //=> [ 'x/foo/a-0/y', 'x/foo/b-1/y', 'x/foo/c-2/y', 'x/foo/d-3/y', 'x/foo/e-4/y' ] const numeric = braces.expand('{1..5}', { - transform(value, index) { + transform(value) { return 'foo/' + value * 2; } }); diff --git a/index.js b/index.js index 0eee0f5..d222c13 100644 --- a/index.js +++ b/index.js @@ -23,8 +23,8 @@ const braces = (input, options = {}) => { let output = []; if (Array.isArray(input)) { - for (let pattern of input) { - let result = braces.create(pattern, options); + for (const pattern of input) { + const result = braces.create(pattern, options); if (Array.isArray(result)) { output.push(...result); } else { @@ -158,7 +158,7 @@ braces.create = (input, options = {}) => { return [input]; } - return options.expand !== true + return options.expand !== true ? braces.compile(input, options) : braces.expand(input, options); }; diff --git a/lib/compile.js b/lib/compile.js index 3e984a4..dce69be 100644 --- a/lib/compile.js +++ b/lib/compile.js @@ -4,30 +4,32 @@ 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 ? '\\' : ''; + const walk = (node, parent = {}) => { + const invalidBlock = utils.isInvalidBrace(parent); + const invalidNode = node.invalid === true && options.escapeInvalid === true; + const invalid = invalidBlock === true || invalidNode === true; + const prefix = options.escapeInvalid === true ? '\\' : ''; let output = ''; if (node.isOpen === true) { return prefix + node.value; } + if (node.isClose === true) { + console.log('node.isClose', prefix, node.value); return prefix + node.value; } if (node.type === 'open') { - return invalid ? (prefix + node.value) : '('; + return invalid ? prefix + node.value : '('; } if (node.type === 'close') { - return invalid ? (prefix + node.value) : ')'; + return invalid ? prefix + node.value : ')'; } if (node.type === 'comma') { - return node.prev.type === 'comma' ? '' : (invalid ? node.value : '|'); + return node.prev.type === 'comma' ? '' : invalid ? node.value : '|'; } if (node.value) { @@ -35,8 +37,8 @@ const compile = (ast, options = {}) => { } if (node.nodes && node.ranges > 0) { - let args = utils.reduce(node.nodes); - let range = fill(...args, { ...options, wrap: false, toRegex: true }); + const args = utils.reduce(node.nodes); + const range = fill(...args, { ...options, wrap: false, toRegex: true, strictZeros: true }); if (range.length !== 0) { return args.length > 1 && range.length > 1 ? `(${range})` : range; @@ -44,10 +46,11 @@ const compile = (ast, options = {}) => { } if (node.nodes) { - for (let child of node.nodes) { + for (const child of node.nodes) { output += walk(child, node); } } + return output; }; diff --git a/lib/expand.js b/lib/expand.js index 376c748..35b2c41 100644 --- a/lib/expand.js +++ b/lib/expand.js @@ -5,7 +5,7 @@ const stringify = require('./stringify'); const utils = require('./utils'); const append = (queue = '', stash = '', enclose = false) => { - let result = []; + const result = []; queue = [].concat(queue); stash = [].concat(stash); @@ -15,15 +15,15 @@ const append = (queue = '', stash = '', enclose = false) => { return enclose ? utils.flatten(stash).map(ele => `{${ele}}`) : stash; } - for (let item of queue) { + for (const item of queue) { if (Array.isArray(item)) { - for (let value of item) { + for (const 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)); + result.push(Array.isArray(ele) ? append(item, ele, enclose) : item + ele); } } } @@ -31,9 +31,9 @@ const append = (queue = '', stash = '', enclose = false) => { }; const expand = (ast, options = {}) => { - let rangeLimit = options.rangeLimit === void 0 ? 1000 : options.rangeLimit; + const rangeLimit = options.rangeLimit === undefined ? 1000 : options.rangeLimit; - let walk = (node, parent = {}) => { + const walk = (node, parent = {}) => { node.queue = []; let p = parent; @@ -55,7 +55,7 @@ const expand = (ast, options = {}) => { } if (node.nodes && node.ranges > 0) { - let args = utils.reduce(node.nodes); + const 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.'); @@ -71,7 +71,7 @@ const expand = (ast, options = {}) => { return; } - let enclose = utils.encloseBrace(node); + const enclose = utils.encloseBrace(node); let queue = node.queue; let block = node; @@ -81,7 +81,7 @@ const expand = (ast, options = {}) => { } for (let i = 0; i < node.nodes.length; i++) { - let child = node.nodes[i]; + const child = node.nodes[i]; if (child.type === 'comma' && node.type === 'brace') { if (i === 1) queue.push(''); diff --git a/lib/parse.js b/lib/parse.js index 145ea26..3a6988e 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -33,22 +33,21 @@ const parse = (input, options = {}) => { throw new TypeError('Expected a string'); } - let opts = options || {}; - let max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; + const opts = options || {}; + const 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]; + const ast = { type: 'root', input, nodes: [] }; + const stack = [ast]; let block = ast; let prev = ast; let brackets = 0; - let length = input.length; + const length = input.length; let index = 0; let depth = 0; let value; - let memo = {}; /** * Helpers @@ -111,7 +110,6 @@ const parse = (input, options = {}) => { if (value === CHAR_LEFT_SQUARE_BRACKET) { brackets++; - let closed = true; let next; while (index < length && (next = advance())) { @@ -167,7 +165,7 @@ const parse = (input, options = {}) => { */ if (value === CHAR_DOUBLE_QUOTE || value === CHAR_SINGLE_QUOTE || value === CHAR_BACKTICK) { - let open = value; + const open = value; let next; if (options.keepQuotes !== true) { @@ -199,8 +197,8 @@ const parse = (input, options = {}) => { if (value === CHAR_LEFT_CURLY_BRACE) { depth++; - let dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true; - let brace = { + const dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true; + const brace = { type: 'brace', open: true, close: false, @@ -227,7 +225,7 @@ const parse = (input, options = {}) => { continue; } - let type = 'close'; + const type = 'close'; block = stack.pop(); block.close = true; @@ -245,7 +243,7 @@ const parse = (input, options = {}) => { if (value === CHAR_COMMA && depth > 0) { if (block.ranges > 0) { block.ranges = 0; - let open = block.nodes.shift(); + const open = block.nodes.shift(); block.nodes = [open, { type: 'text', value: stringify(block) }]; } @@ -259,7 +257,7 @@ const parse = (input, options = {}) => { */ if (value === CHAR_DOT && depth > 0 && block.commas === 0) { - let siblings = block.nodes; + const siblings = block.nodes; if (depth === 0 || siblings.length === 0) { push({ type: 'text', value }); @@ -286,7 +284,7 @@ const parse = (input, options = {}) => { if (prev.type === 'range') { siblings.pop(); - let before = siblings[siblings.length - 1]; + const before = siblings[siblings.length - 1]; before.value += prev.value + value; prev = before; block.ranges--; @@ -319,8 +317,8 @@ const parse = (input, options = {}) => { }); // get the location of the block on parent.nodes (block's siblings) - let parent = stack[stack.length - 1]; - let index = parent.nodes.indexOf(block); + const parent = stack[stack.length - 1]; + const index = parent.nodes.indexOf(block); // replace the (invalid) block with it's nodes parent.nodes.splice(index, 1, ...block.nodes); } diff --git a/lib/stringify.js b/lib/stringify.js index 414b7bc..8bcf872 100644 --- a/lib/stringify.js +++ b/lib/stringify.js @@ -3,9 +3,9 @@ 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; + const stringify = (node, parent = {}) => { + const invalidBlock = options.escapeInvalid && utils.isInvalidBrace(parent); + const invalidNode = node.invalid === true && options.escapeInvalid === true; let output = ''; if (node.value) { @@ -20,7 +20,7 @@ module.exports = (ast, options = {}) => { } if (node.nodes) { - for (let child of node.nodes) { + for (const child of node.nodes) { output += stringify(child); } } diff --git a/lib/utils.js b/lib/utils.js index e3551a6..d19311f 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -31,7 +31,7 @@ exports.exceedsLimit = (min, max, step = 1, limit) => { */ exports.escapeNode = (block, n = 0, type) => { - let node = block.nodes[n]; + const node = block.nodes[n]; if (!node) return; if ((type && node.type === type) || node.type === 'open' || node.type === 'close') { @@ -100,13 +100,23 @@ exports.reduce = nodes => nodes.reduce((acc, node) => { 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); + const ele = arr[i]; + + if (Array.isArray(ele)) { + flat(ele); + continue; + } + + if (ele !== undefined) { + result.push(ele); + } } return result; }; + flat(args); return result; }; diff --git a/package.json b/package.json index 3f52e34..d668f88 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "benchmark": "node benchmark" }, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "devDependencies": { "ansi-colors": "^3.2.4", diff --git a/test/bash-compiled-ranges.js b/test/bash-compiled-ranges.js index 857e5ce..8181a35 100644 --- a/test/bash-compiled-ranges.js +++ b/test/bash-compiled-ranges.js @@ -187,9 +187,9 @@ describe('bash ranges - braces.compile()', () => { return; } - let options = { ...arr[1] }; - let pattern = arr[0]; - let expected = arr[2]; + const options = { ...arr[1] }; + const pattern = arr[0]; + const expected = arr[2]; if (options.skip === true) { return; diff --git a/test/bash-compiled-sets.js b/test/bash-compiled-sets.js index 15bff41..1a95c19 100644 --- a/test/bash-compiled-sets.js +++ b/test/bash-compiled-sets.js @@ -163,13 +163,13 @@ describe('bash sets - braces.compile()', () => { ['/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.{html,ejs}', {}, '/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.(html|ejs)'] ]; - let seen = new Map(); - let dupes = []; + const seen = new Map(); + const dupes = []; for (let i = 0; i < fixtures.length; i++) { - let fixture = fixtures[i]; + const fixture = fixtures[i]; - let key = fixture[0] + String(fixture[1].bash); + const key = fixture[0] + String(fixture[1].bash); if (seen.has(key)) { dupes.push(i + 21, fixture[0]); } else { @@ -183,9 +183,9 @@ describe('bash sets - braces.compile()', () => { return; } - let options = { ...arr[1] }; - let pattern = arr[0]; - let expected = arr[2]; + const options = { ...arr[1] }; + const pattern = arr[0]; + const expected = arr[2]; if (options.skip === true) { return; diff --git a/test/bash-expanded-ranges.js b/test/bash-expanded-ranges.js index 4524613..21c1db2 100644 --- a/test/bash-expanded-ranges.js +++ b/test/bash-expanded-ranges.js @@ -138,8 +138,8 @@ describe('bash - expanded brace ranges', () => { describe('combo', () => { it('should expand numerical ranges - positive and negative', () => { - equal('a{01..05}b', ['a01b', 'a02b', 'a03b', 'a04b', 'a05b' ]); - equal('0{1..9}/{10..20}', ['01/10', '01/11', '01/12', '01/13', '01/14', '01/15', '01/16', '01/17', '01/18', '01/19', '01/20', '02/10', '02/11', '02/12', '02/13', '02/14', '02/15', '02/16', '02/17', '02/18', '02/19', '02/20', '03/10', '03/11', '03/12', '03/13', '03/14', '03/15', '03/16', '03/17', '03/18', '03/19', '03/20', '04/10', '04/11', '04/12', '04/13', '04/14', '04/15', '04/16', '04/17', '04/18', '04/19', '04/20', '05/10', '05/11', '05/12', '05/13', '05/14', '05/15', '05/16', '05/17', '05/18', '05/19', '05/20', '06/10', '06/11', '06/12', '06/13', '06/14', '06/15', '06/16', '06/17', '06/18', '06/19', '06/20', '07/10', '07/11', '07/12', '07/13', '07/14', '07/15', '07/16', '07/17', '07/18', '07/19', '07/20', '08/10', '08/11', '08/12', '08/13', '08/14', '08/15', '08/16', '08/17', '08/18', '08/19', '08/20', '09/10', '09/11', '09/12', '09/13', '09/14', '09/15', '09/16', '09/17', '09/18', '09/19', '09/20' ]); + equal('a{01..05}b', ['a01b', 'a02b', 'a03b', 'a04b', 'a05b']); + equal('0{1..9}/{10..20}', ['01/10', '01/11', '01/12', '01/13', '01/14', '01/15', '01/16', '01/17', '01/18', '01/19', '01/20', '02/10', '02/11', '02/12', '02/13', '02/14', '02/15', '02/16', '02/17', '02/18', '02/19', '02/20', '03/10', '03/11', '03/12', '03/13', '03/14', '03/15', '03/16', '03/17', '03/18', '03/19', '03/20', '04/10', '04/11', '04/12', '04/13', '04/14', '04/15', '04/16', '04/17', '04/18', '04/19', '04/20', '05/10', '05/11', '05/12', '05/13', '05/14', '05/15', '05/16', '05/17', '05/18', '05/19', '05/20', '06/10', '06/11', '06/12', '06/13', '06/14', '06/15', '06/16', '06/17', '06/18', '06/19', '06/20', '07/10', '07/11', '07/12', '07/13', '07/14', '07/15', '07/16', '07/17', '07/18', '07/19', '07/20', '08/10', '08/11', '08/12', '08/13', '08/14', '08/15', '08/16', '08/17', '08/18', '08/19', '08/20', '09/10', '09/11', '09/12', '09/13', '09/14', '09/15', '09/16', '09/17', '09/18', '09/19', '09/20']); equal('{-10..10}', ['-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); }); }); @@ -204,8 +204,8 @@ describe('bash - expanded brace ranges', () => { const fixtures = [ 'should expand ranges', - ['a{b,c{1..50}/{d,e,f}/,g}h/i', {}, ['abh/i', 'ac1/d/h/i', 'ac1/e/h/i', 'ac1/f/h/i', 'ac2/d/h/i', 'ac2/e/h/i', 'ac2/f/h/i', 'ac3/d/h/i', 'ac3/e/h/i', 'ac3/f/h/i', 'ac4/d/h/i', 'ac4/e/h/i', 'ac4/f/h/i', 'ac5/d/h/i', 'ac5/e/h/i', 'ac5/f/h/i', 'ac6/d/h/i', 'ac6/e/h/i', 'ac6/f/h/i', 'ac7/d/h/i', 'ac7/e/h/i', 'ac7/f/h/i', 'ac8/d/h/i', 'ac8/e/h/i', 'ac8/f/h/i', 'ac9/d/h/i', 'ac9/e/h/i', 'ac9/f/h/i', 'ac10/d/h/i', 'ac10/e/h/i', 'ac10/f/h/i', 'ac11/d/h/i', 'ac11/e/h/i', 'ac11/f/h/i', 'ac12/d/h/i', 'ac12/e/h/i', 'ac12/f/h/i', 'ac13/d/h/i', 'ac13/e/h/i', 'ac13/f/h/i', 'ac14/d/h/i', 'ac14/e/h/i', 'ac14/f/h/i', 'ac15/d/h/i', 'ac15/e/h/i', 'ac15/f/h/i', 'ac16/d/h/i', 'ac16/e/h/i', 'ac16/f/h/i', 'ac17/d/h/i', 'ac17/e/h/i', 'ac17/f/h/i', 'ac18/d/h/i', 'ac18/e/h/i', 'ac18/f/h/i', 'ac19/d/h/i', 'ac19/e/h/i', 'ac19/f/h/i', 'ac20/d/h/i', 'ac20/e/h/i', 'ac20/f/h/i', 'ac21/d/h/i', 'ac21/e/h/i', 'ac21/f/h/i', 'ac22/d/h/i', 'ac22/e/h/i', 'ac22/f/h/i', 'ac23/d/h/i', 'ac23/e/h/i', 'ac23/f/h/i', 'ac24/d/h/i', 'ac24/e/h/i', 'ac24/f/h/i', 'ac25/d/h/i', 'ac25/e/h/i', 'ac25/f/h/i', 'ac26/d/h/i', 'ac26/e/h/i', 'ac26/f/h/i', 'ac27/d/h/i', 'ac27/e/h/i', 'ac27/f/h/i', 'ac28/d/h/i', 'ac28/e/h/i', 'ac28/f/h/i', 'ac29/d/h/i', 'ac29/e/h/i', 'ac29/f/h/i', 'ac30/d/h/i', 'ac30/e/h/i', 'ac30/f/h/i', 'ac31/d/h/i', 'ac31/e/h/i', 'ac31/f/h/i', 'ac32/d/h/i', 'ac32/e/h/i', 'ac32/f/h/i', 'ac33/d/h/i', 'ac33/e/h/i', 'ac33/f/h/i', 'ac34/d/h/i', 'ac34/e/h/i', 'ac34/f/h/i', 'ac35/d/h/i', 'ac35/e/h/i', 'ac35/f/h/i', 'ac36/d/h/i', 'ac36/e/h/i', 'ac36/f/h/i', 'ac37/d/h/i', 'ac37/e/h/i', 'ac37/f/h/i', 'ac38/d/h/i', 'ac38/e/h/i', 'ac38/f/h/i', 'ac39/d/h/i', 'ac39/e/h/i', 'ac39/f/h/i', 'ac40/d/h/i', 'ac40/e/h/i', 'ac40/f/h/i', 'ac41/d/h/i', 'ac41/e/h/i', 'ac41/f/h/i', 'ac42/d/h/i', 'ac42/e/h/i', 'ac42/f/h/i', 'ac43/d/h/i', 'ac43/e/h/i', 'ac43/f/h/i', 'ac44/d/h/i', 'ac44/e/h/i', 'ac44/f/h/i', 'ac45/d/h/i', 'ac45/e/h/i', 'ac45/f/h/i', 'ac46/d/h/i', 'ac46/e/h/i', 'ac46/f/h/i', 'ac47/d/h/i', 'ac47/e/h/i', 'ac47/f/h/i', 'ac48/d/h/i', 'ac48/e/h/i', 'ac48/f/h/i', 'ac49/d/h/i', 'ac49/e/h/i', 'ac49/f/h/i', 'ac50/d/h/i', 'ac50/e/h/i', 'ac50/f/h/i', 'agh/i'] ], - ['0{1..9} {10..20}', {}, ['01 10', '01 11', '01 12', '01 13', '01 14', '01 15', '01 16', '01 17', '01 18', '01 19', '01 20', '02 10', '02 11', '02 12', '02 13', '02 14', '02 15', '02 16', '02 17', '02 18', '02 19', '02 20', '03 10', '03 11', '03 12', '03 13', '03 14', '03 15', '03 16', '03 17', '03 18', '03 19', '03 20', '04 10', '04 11', '04 12', '04 13', '04 14', '04 15', '04 16', '04 17', '04 18', '04 19', '04 20', '05 10', '05 11', '05 12', '05 13', '05 14', '05 15', '05 16', '05 17', '05 18', '05 19', '05 20', '06 10', '06 11', '06 12', '06 13', '06 14', '06 15', '06 16', '06 17', '06 18', '06 19', '06 20', '07 10', '07 11', '07 12', '07 13', '07 14', '07 15', '07 16', '07 17', '07 18', '07 19', '07 20', '08 10', '08 11', '08 12', '08 13', '08 14', '08 15', '08 16', '08 17', '08 18', '08 19', '08 20', '09 10', '09 11', '09 12', '09 13', '09 14', '09 15', '09 16', '09 17', '09 18', '09 19', '09 20'] ], + ['a{b,c{1..50}/{d,e,f}/,g}h/i', {}, ['abh/i', 'ac1/d/h/i', 'ac1/e/h/i', 'ac1/f/h/i', 'ac2/d/h/i', 'ac2/e/h/i', 'ac2/f/h/i', 'ac3/d/h/i', 'ac3/e/h/i', 'ac3/f/h/i', 'ac4/d/h/i', 'ac4/e/h/i', 'ac4/f/h/i', 'ac5/d/h/i', 'ac5/e/h/i', 'ac5/f/h/i', 'ac6/d/h/i', 'ac6/e/h/i', 'ac6/f/h/i', 'ac7/d/h/i', 'ac7/e/h/i', 'ac7/f/h/i', 'ac8/d/h/i', 'ac8/e/h/i', 'ac8/f/h/i', 'ac9/d/h/i', 'ac9/e/h/i', 'ac9/f/h/i', 'ac10/d/h/i', 'ac10/e/h/i', 'ac10/f/h/i', 'ac11/d/h/i', 'ac11/e/h/i', 'ac11/f/h/i', 'ac12/d/h/i', 'ac12/e/h/i', 'ac12/f/h/i', 'ac13/d/h/i', 'ac13/e/h/i', 'ac13/f/h/i', 'ac14/d/h/i', 'ac14/e/h/i', 'ac14/f/h/i', 'ac15/d/h/i', 'ac15/e/h/i', 'ac15/f/h/i', 'ac16/d/h/i', 'ac16/e/h/i', 'ac16/f/h/i', 'ac17/d/h/i', 'ac17/e/h/i', 'ac17/f/h/i', 'ac18/d/h/i', 'ac18/e/h/i', 'ac18/f/h/i', 'ac19/d/h/i', 'ac19/e/h/i', 'ac19/f/h/i', 'ac20/d/h/i', 'ac20/e/h/i', 'ac20/f/h/i', 'ac21/d/h/i', 'ac21/e/h/i', 'ac21/f/h/i', 'ac22/d/h/i', 'ac22/e/h/i', 'ac22/f/h/i', 'ac23/d/h/i', 'ac23/e/h/i', 'ac23/f/h/i', 'ac24/d/h/i', 'ac24/e/h/i', 'ac24/f/h/i', 'ac25/d/h/i', 'ac25/e/h/i', 'ac25/f/h/i', 'ac26/d/h/i', 'ac26/e/h/i', 'ac26/f/h/i', 'ac27/d/h/i', 'ac27/e/h/i', 'ac27/f/h/i', 'ac28/d/h/i', 'ac28/e/h/i', 'ac28/f/h/i', 'ac29/d/h/i', 'ac29/e/h/i', 'ac29/f/h/i', 'ac30/d/h/i', 'ac30/e/h/i', 'ac30/f/h/i', 'ac31/d/h/i', 'ac31/e/h/i', 'ac31/f/h/i', 'ac32/d/h/i', 'ac32/e/h/i', 'ac32/f/h/i', 'ac33/d/h/i', 'ac33/e/h/i', 'ac33/f/h/i', 'ac34/d/h/i', 'ac34/e/h/i', 'ac34/f/h/i', 'ac35/d/h/i', 'ac35/e/h/i', 'ac35/f/h/i', 'ac36/d/h/i', 'ac36/e/h/i', 'ac36/f/h/i', 'ac37/d/h/i', 'ac37/e/h/i', 'ac37/f/h/i', 'ac38/d/h/i', 'ac38/e/h/i', 'ac38/f/h/i', 'ac39/d/h/i', 'ac39/e/h/i', 'ac39/f/h/i', 'ac40/d/h/i', 'ac40/e/h/i', 'ac40/f/h/i', 'ac41/d/h/i', 'ac41/e/h/i', 'ac41/f/h/i', 'ac42/d/h/i', 'ac42/e/h/i', 'ac42/f/h/i', 'ac43/d/h/i', 'ac43/e/h/i', 'ac43/f/h/i', 'ac44/d/h/i', 'ac44/e/h/i', 'ac44/f/h/i', 'ac45/d/h/i', 'ac45/e/h/i', 'ac45/f/h/i', 'ac46/d/h/i', 'ac46/e/h/i', 'ac46/f/h/i', 'ac47/d/h/i', 'ac47/e/h/i', 'ac47/f/h/i', 'ac48/d/h/i', 'ac48/e/h/i', 'ac48/f/h/i', 'ac49/d/h/i', 'ac49/e/h/i', 'ac49/f/h/i', 'ac50/d/h/i', 'ac50/e/h/i', 'ac50/f/h/i', 'agh/i']], + ['0{1..9} {10..20}', {}, ['01 10', '01 11', '01 12', '01 13', '01 14', '01 15', '01 16', '01 17', '01 18', '01 19', '01 20', '02 10', '02 11', '02 12', '02 13', '02 14', '02 15', '02 16', '02 17', '02 18', '02 19', '02 20', '03 10', '03 11', '03 12', '03 13', '03 14', '03 15', '03 16', '03 17', '03 18', '03 19', '03 20', '04 10', '04 11', '04 12', '04 13', '04 14', '04 15', '04 16', '04 17', '04 18', '04 19', '04 20', '05 10', '05 11', '05 12', '05 13', '05 14', '05 15', '05 16', '05 17', '05 18', '05 19', '05 20', '06 10', '06 11', '06 12', '06 13', '06 14', '06 15', '06 16', '06 17', '06 18', '06 19', '06 20', '07 10', '07 11', '07 12', '07 13', '07 14', '07 15', '07 16', '07 17', '07 18', '07 19', '07 20', '08 10', '08 11', '08 12', '08 13', '08 14', '08 15', '08 16', '08 17', '08 18', '08 19', '08 20', '09 10', '09 11', '09 12', '09 13', '09 14', '09 15', '09 16', '09 17', '09 18', '09 19', '09 20']], ['a{0..3}d', {}, ['a0d', 'a1d', 'a2d', 'a3d']], ['x{10..1}y', {}, ['x10y', 'x9y', 'x8y', 'x7y', 'x6y', 'x5y', 'x4y', 'x3y', 'x2y', 'x1y']], ['x{3..3}y', {}, ['x3y']], @@ -214,8 +214,8 @@ describe('bash - expanded brace ranges', () => { ['{5..8}', {}, ['5', '6', '7', '8']], ['**/{1..5}/a.js', {}, ['**/1/a.js', '**/2/a.js', '**/3/a.js', '**/4/a.js', '**/5/a.js']], ['{braces,{0..10}}', {}, ['braces', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']], - ['./\\{x,y}/{a..z..3}/', {}, ['./{x,y}/a/', './{x,y}/d/', './{x,y}/g/', './{x,y}/j/', './{x,y}/m/', './{x,y}/p/', './{x,y}/s/', './{x,y}/v/', './{x,y}/y/'] ], - ['x{{0..10},braces}y', {}, ['x0y', 'x1y', 'x2y', 'x3y', 'x4y', 'x5y', 'x6y', 'x7y', 'x8y', 'x9y', 'x10y', 'xbracesy'] ], + ['./\\{x,y}/{a..z..3}/', {}, ['./{x,y}/a/', './{x,y}/d/', './{x,y}/g/', './{x,y}/j/', './{x,y}/m/', './{x,y}/p/', './{x,y}/s/', './{x,y}/v/', './{x,y}/y/']], + ['x{{0..10},braces}y', {}, ['x0y', 'x1y', 'x2y', 'x3y', 'x4y', 'x5y', 'x6y', 'x7y', 'x8y', 'x9y', 'x10y', 'xbracesy']], ['{braces,{0..10}}', {}, ['braces', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']], ['{{0..10},braces}', {}, ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'braces']], ['{{1..10..2},braces}', {}, ['1', '3', '5', '7', '9', 'braces']], @@ -242,60 +242,60 @@ describe('bash - expanded brace ranges', () => { ['{3..3}', {}, ['3']], ['{5..8}', {}, ['5', '6', '7', '8']], ['{-10..-1}', {}, ['-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1']], - ['{-20..0}', {}, ['-20', '-19', '-18', '-17', '-16', '-15', '-14', '-13', '-12', '-11', '-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1', '0'] ], + ['{-20..0}', {}, ['-20', '-19', '-18', '-17', '-16', '-15', '-14', '-13', '-12', '-11', '-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1', '0']], ['{0..-5}', {}, ['0', '-1', '-2', '-3', '-4', '-5']], ['{9..-4}', {}, ['9', '8', '7', '6', '5', '4', '3', '2', '1', '0', '-1', '-2', '-3', '-4']], - ['0{1..9}/{10..20}', {}, ['01/10', '01/11', '01/12', '01/13', '01/14', '01/15', '01/16', '01/17', '01/18', '01/19', '01/20', '02/10', '02/11', '02/12', '02/13', '02/14', '02/15', '02/16', '02/17', '02/18', '02/19', '02/20', '03/10', '03/11', '03/12', '03/13', '03/14', '03/15', '03/16', '03/17', '03/18', '03/19', '03/20', '04/10', '04/11', '04/12', '04/13', '04/14', '04/15', '04/16', '04/17', '04/18', '04/19', '04/20', '05/10', '05/11', '05/12', '05/13', '05/14', '05/15', '05/16', '05/17', '05/18', '05/19', '05/20', '06/10', '06/11', '06/12', '06/13', '06/14', '06/15', '06/16', '06/17', '06/18', '06/19', '06/20', '07/10', '07/11', '07/12', '07/13', '07/14', '07/15', '07/16', '07/17', '07/18', '07/19', '07/20', '08/10', '08/11', '08/12', '08/13', '08/14', '08/15', '08/16', '08/17', '08/18', '08/19', '08/20', '09/10', '09/11', '09/12', '09/13', '09/14', '09/15', '09/16', '09/17', '09/18', '09/19', '09/20'] ], + ['0{1..9}/{10..20}', {}, ['01/10', '01/11', '01/12', '01/13', '01/14', '01/15', '01/16', '01/17', '01/18', '01/19', '01/20', '02/10', '02/11', '02/12', '02/13', '02/14', '02/15', '02/16', '02/17', '02/18', '02/19', '02/20', '03/10', '03/11', '03/12', '03/13', '03/14', '03/15', '03/16', '03/17', '03/18', '03/19', '03/20', '04/10', '04/11', '04/12', '04/13', '04/14', '04/15', '04/16', '04/17', '04/18', '04/19', '04/20', '05/10', '05/11', '05/12', '05/13', '05/14', '05/15', '05/16', '05/17', '05/18', '05/19', '05/20', '06/10', '06/11', '06/12', '06/13', '06/14', '06/15', '06/16', '06/17', '06/18', '06/19', '06/20', '07/10', '07/11', '07/12', '07/13', '07/14', '07/15', '07/16', '07/17', '07/18', '07/19', '07/20', '08/10', '08/11', '08/12', '08/13', '08/14', '08/15', '08/16', '08/17', '08/18', '08/19', '08/20', '09/10', '09/11', '09/12', '09/13', '09/14', '09/15', '09/16', '09/17', '09/18', '09/19', '09/20']], ['0{a..d}0', {}, ['0a0', '0b0', '0c0', '0d0']], ['a/{b..d}/e', {}, ['a/b/e', 'a/c/e', 'a/d/e']], - ['{1..f}', { minimatch: false }, ['1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f'] ], - ['{a..A}', {}, ['a', '`', '_', '^', ']', '\\', '[', 'Z', 'Y', 'X', 'W', 'V', 'U', 'T', 'S', 'R', 'Q', 'P', 'O', 'N', 'M', 'L', 'K', 'J', 'I', 'H', 'G', 'F', 'E', 'D', 'C', 'B', 'A'] ], - ['{A..a}', {}, ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a'] ], + ['{1..f}', { minimatch: false }, ['1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f']], + ['{a..A}', {}, ['a', '`', '_', '^', ']', '\\', '[', 'Z', 'Y', 'X', 'W', 'V', 'U', 'T', 'S', 'R', 'Q', 'P', 'O', 'N', 'M', 'L', 'K', 'J', 'I', 'H', 'G', 'F', 'E', 'D', 'C', 'B', 'A']], + ['{A..a}', {}, ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a']], ['{a..e}', {}, ['a', 'b', 'c', 'd', 'e']], ['{A..E}', {}, ['A', 'B', 'C', 'D', 'E']], ['{a..f}', {}, ['a', 'b', 'c', 'd', 'e', 'f']], - ['{a..z}', {}, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'] ], + ['{a..z}', {}, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']], ['{E..A}', {}, ['E', 'D', 'C', 'B', 'A']], - ['{f..1}', { minimatch: false }, ['f', 'e', 'd', 'c', 'b', 'a', '`', '_', '^', ']', '\\', '[', 'Z', 'Y', 'X', 'W', 'V', 'U', 'T', 'S', 'R', 'Q', 'P', 'O', 'N', 'M', 'L', 'K', 'J', 'I', 'H', 'G', 'F', 'E', 'D', 'C', 'B', 'A', '@', '?', '>', '=', '<', ';', ':', '9', '8', '7', '6', '5', '4', '3', '2', '1'] ], + ['{f..1}', { minimatch: false }, ['f', 'e', 'd', 'c', 'b', 'a', '`', '_', '^', ']', '\\', '[', 'Z', 'Y', 'X', 'W', 'V', 'U', 'T', 'S', 'R', 'Q', 'P', 'O', 'N', 'M', 'L', 'K', 'J', 'I', 'H', 'G', 'F', 'E', 'D', 'C', 'B', 'A', '@', '?', '>', '=', '<', ';', ':', '9', '8', '7', '6', '5', '4', '3', '2', '1']], ['{f..a}', {}, ['f', 'e', 'd', 'c', 'b', 'a']], ['{f..f}', {}, ['f']], - ['a/{b..d}/e/{f..h}', {}, ['a/b/e/f', 'a/b/e/g', 'a/b/e/h', 'a/c/e/f', 'a/c/e/g', 'a/c/e/h', 'a/d/e/f', 'a/d/e/g', 'a/d/e/h'] ], - ['{-10..10}', {}, ['-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] ], - ['{1..10..1}', { optimize: false }, ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10'] ], - ['{1..10..2}', { optimize: false }, ['1', '3', '5', '7', '9'] ], - ['{1..20..20}', { optimize: false }, ['1'] ], - ['{1..20..2}', { optimize: false }, ['1', '3', '5', '7', '9', '11', '13', '15', '17', '19'] ], - ['{10..0..2}', { optimize: false }, ['10', '8', '6', '4', '2', '0'] ], - ['{10..1..2}', { optimize: false }, ['10', '8', '6', '4', '2'] ], - ['{100..0..5}', { optimize: false }, ['100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0'] ], - ['{2..10..1}', { optimize: false }, ['2', '3', '4', '5', '6', '7', '8', '9', '10'] ], - ['{2..10..2}', { optimize: false }, ['2', '4', '6', '8', '10'] ], - ['{2..10..3}', { optimize: false }, ['2', '5', '8'] ], - ['{a..z..2}', { optimize: false }, ['a', 'c', 'e', 'g', 'i', 'k', 'm', 'o', 'q', 's', 'u', 'w', 'y'] ], - ['{10..0..-2}', { optimize: false }, ['10', '8', '6', '4', '2', '0'] ], - ['{-1..-10..-2}', { optimize: false }, ['-1', '-3', '-5', '-7', '-9'] ], - ['{-1..-10..2}', { optimize: false }, ['-1', '-3', '-5', '-7', '-9'] ], - ['{-10..-2..2}', { optimize: false }, ['-10', '-8', '-6', '-4', '-2'] ], - ['{-2..-10..1}', { optimize: false }, ['-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '-10'] ], - ['{-2..-10..2}', { optimize: false }, ['-2', '-4', '-6', '-8', '-10'] ], - ['{-2..-10..3}', { optimize: false }, ['-2', '-5', '-8'] ], - ['{-50..-0..5}', { optimize: false }, ['-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0'] ], - ['{-9..9..3}', { optimize: false }, ['-9', '-6', '-3', '0', '3', '6', '9'] ], - ['{10..1..-2}', { optimize: false }, ['10', '8', '6', '4', '2'] ], - ['{100..0..-5}', { optimize: false }, ['100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0'] ], - ['{a..e..2}', { optimize: false }, ['a', 'c', 'e'] ], - ['{E..A..2}', { optimize: false }, ['E', 'C', 'A'] ], - ['{a..z..2}', { optimize: false }, ['a', 'c', 'e', 'g', 'i', 'k', 'm', 'o', 'q', 's', 'u', 'w', 'y'] ], - ['{z..a..-2}', { optimize: false }, ['z', 'x', 'v', 't', 'r', 'p', 'n', 'l', 'j', 'h', 'f', 'd', 'b'] ], - ['{z..a..-2}', { optimize: false }, ['z', 'x', 'v', 't', 'r', 'p', 'n', 'l', 'j', 'h', 'f', 'd', 'b'] ], - ['{10..0..2}', { optimize: false }, ['10', '8', '6', '4', '2', '0'] ], - ['{10..0..-2}', { optimize: false }, ['10', '8', '6', '4', '2', '0'] ], - ['{-50..-0..5}', { optimize: false }, ['-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0'] ], + ['a/{b..d}/e/{f..h}', {}, ['a/b/e/f', 'a/b/e/g', 'a/b/e/h', 'a/c/e/f', 'a/c/e/g', 'a/c/e/h', 'a/d/e/f', 'a/d/e/g', 'a/d/e/h']], + ['{-10..10}', {}, ['-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']], + ['{1..10..1}', { optimize: false }, ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']], + ['{1..10..2}', { optimize: false }, ['1', '3', '5', '7', '9']], + ['{1..20..20}', { optimize: false }, ['1']], + ['{1..20..2}', { optimize: false }, ['1', '3', '5', '7', '9', '11', '13', '15', '17', '19']], + ['{10..0..2}', { optimize: false }, ['10', '8', '6', '4', '2', '0']], + ['{10..1..2}', { optimize: false }, ['10', '8', '6', '4', '2']], + ['{100..0..5}', { optimize: false }, ['100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']], + ['{2..10..1}', { optimize: false }, ['2', '3', '4', '5', '6', '7', '8', '9', '10']], + ['{2..10..2}', { optimize: false }, ['2', '4', '6', '8', '10']], + ['{2..10..3}', { optimize: false }, ['2', '5', '8']], + ['{a..z..2}', { optimize: false }, ['a', 'c', 'e', 'g', 'i', 'k', 'm', 'o', 'q', 's', 'u', 'w', 'y']], + ['{10..0..-2}', { optimize: false }, ['10', '8', '6', '4', '2', '0']], + ['{-1..-10..-2}', { optimize: false }, ['-1', '-3', '-5', '-7', '-9']], + ['{-1..-10..2}', { optimize: false }, ['-1', '-3', '-5', '-7', '-9']], + ['{-10..-2..2}', { optimize: false }, ['-10', '-8', '-6', '-4', '-2']], + ['{-2..-10..1}', { optimize: false }, ['-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '-10']], + ['{-2..-10..2}', { optimize: false }, ['-2', '-4', '-6', '-8', '-10']], + ['{-2..-10..3}', { optimize: false }, ['-2', '-5', '-8']], + ['{-50..-0..5}', { optimize: false }, ['-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0']], + ['{-9..9..3}', { optimize: false }, ['-9', '-6', '-3', '0', '3', '6', '9']], + ['{10..1..-2}', { optimize: false }, ['10', '8', '6', '4', '2']], + ['{100..0..-5}', { optimize: false }, ['100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']], + ['{a..e..2}', { optimize: false }, ['a', 'c', 'e']], + ['{E..A..2}', { optimize: false }, ['E', 'C', 'A']], + ['{a..z..2}', { optimize: false }, ['a', 'c', 'e', 'g', 'i', 'k', 'm', 'o', 'q', 's', 'u', 'w', 'y']], + ['{z..a..-2}', { optimize: false }, ['z', 'x', 'v', 't', 'r', 'p', 'n', 'l', 'j', 'h', 'f', 'd', 'b']], + ['{z..a..-2}', { optimize: false }, ['z', 'x', 'v', 't', 'r', 'p', 'n', 'l', 'j', 'h', 'f', 'd', 'b']], + ['{10..0..2}', { optimize: false }, ['10', '8', '6', '4', '2', '0']], + ['{10..0..-2}', { optimize: false }, ['10', '8', '6', '4', '2', '0']], + ['{-50..-0..5}', { optimize: false }, ['-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0']], ['../{1..3}/../foo', {}, ['../1/../foo', '../2/../foo', '../3/../foo']], - ['../{2..10..2}/../foo', { optimize: false }, ['../2/../foo', '../4/../foo', '../6/../foo', '../8/../foo', '../10/../foo'] ], - ['../{1..3}/../{a,b,c}/foo', {}, ['../1/../a/foo', '../1/../b/foo', '../1/../c/foo', '../2/../a/foo', '../2/../b/foo', '../2/../c/foo', '../3/../a/foo', '../3/../b/foo', '../3/../c/foo'] ], - ['./{a..z..3}/', { optimize: false }, ['./a/', './d/', './g/', './j/', './m/', './p/', './s/', './v/', './y/'] ], - ['./{"x,y"}/{a..z..3}/', { minimatch: false, optimize: false }, ['./{x,y}/a/', './{x,y}/d/', './{x,y}/g/', './{x,y}/j/', './{x,y}/m/', './{x,y}/p/', './{x,y}/s/', './{x,y}/v/', './{x,y}/y/'] ], + ['../{2..10..2}/../foo', { optimize: false }, ['../2/../foo', '../4/../foo', '../6/../foo', '../8/../foo', '../10/../foo']], + ['../{1..3}/../{a,b,c}/foo', {}, ['../1/../a/foo', '../1/../b/foo', '../1/../c/foo', '../2/../a/foo', '../2/../b/foo', '../2/../c/foo', '../3/../a/foo', '../3/../b/foo', '../3/../c/foo']], + ['./{a..z..3}/', { optimize: false }, ['./a/', './d/', './g/', './j/', './m/', './p/', './s/', './v/', './y/']], + ['./{"x,y"}/{a..z..3}/', { minimatch: false, optimize: false }, ['./{x,y}/a/', './{x,y}/d/', './{x,y}/g/', './{x,y}/j/', './{x,y}/m/', './{x,y}/p/', './{x,y}/s/', './{x,y}/v/', './{x,y}/y/']], ['a/{x,y}/{1..5}c{d,e}f.{md,txt}', {}, ['a/x/1cdf.md', 'a/x/1cdf.txt', 'a/x/1cef.md', 'a/x/1cef.txt', 'a/x/2cdf.md', 'a/x/2cdf.txt', 'a/x/2cef.md', 'a/x/2cef.txt', 'a/x/3cdf.md', 'a/x/3cdf.txt', 'a/x/3cef.md', 'a/x/3cef.txt', 'a/x/4cdf.md', 'a/x/4cdf.txt', 'a/x/4cef.md', 'a/x/4cef.txt', 'a/x/5cdf.md', 'a/x/5cdf.txt', 'a/x/5cef.md', 'a/x/5cef.txt', 'a/y/1cdf.md', 'a/y/1cdf.txt', 'a/y/1cef.md', 'a/y/1cef.txt', 'a/y/2cdf.md', 'a/y/2cdf.txt', 'a/y/2cef.md', 'a/y/2cef.txt', 'a/y/3cdf.md', 'a/y/3cdf.txt', 'a/y/3cef.md', 'a/y/3cef.txt', 'a/y/4cdf.md', 'a/y/4cdf.txt', 'a/y/4cef.md', 'a/y/4cef.txt', 'a/y/5cdf.md', 'a/y/5cdf.txt', 'a/y/5cef.md', 'a/y/5cef.txt']], ['a/{x,{1..5},y}/c{d}e', {}, ['a/x/c{d}e', 'a/1/c{d}e', 'a/2/c{d}e', 'a/3/c{d}e', 'a/4/c{d}e', 'a/5/c{d}e', 'a/y/c{d}e']] ]; @@ -305,9 +305,9 @@ describe('bash - expanded brace ranges', () => { return; } - let options = { ...arr[1] }; - let pattern = arr[0]; - let expected = arr[2]; + const options = { ...arr[1] }; + const pattern = arr[0]; + const expected = arr[2]; if (options.skip !== true) { it('should compile: ' + pattern, () => equal(pattern, expected, options)); diff --git a/test/bash-expanded-sets.js b/test/bash-expanded-sets.js index 718ac40..b5a40cc 100644 --- a/test/bash-expanded-sets.js +++ b/test/bash-expanded-sets.js @@ -23,206 +23,206 @@ const equal = (input, expected = bash(input), options) => { describe('bash - expanded brace sets', () => { const fixtures = [ - [ 'a/\\{b,c,d,{x,y}}{e,f\\}/g', {}, [ 'a/{b,c,d,x}{e,f}/g', 'a/{b,c,d,y}{e,f}/g' ] ], - [ 'a/\\{b,c,d\\}\\{e,f\\}/g', {}, [ 'a/{b,c,d}{e,f}/g' ] ], - [ 'a/\\{b,c,d\\}\\{e,f}/g', {}, [ 'a/{b,c,d}{e,f}/g' ] ], - [ 'a/\\{b,c,d\\}{e,f}/g', {}, [ 'a/{b,c,d}e/g', 'a/{b,c,d}f/g' ] ], - [ 'a/\\{b,c,d{x,y}}{e,f\\}/g', {}, [ 'a/{b,c,dx}{e,f}/g', 'a/{b,c,dy}{e,f}/g' ] ], - [ 'a/\\{b,c,d}{e,f\\}/g', {}, [ 'a/{b,c,d}{e,f}/g' ] ], - [ 'a/\\{b,c,d}{e,f}/g', {}, [ 'a/{b,c,d}e/g', 'a/{b,c,d}f/g' ] ], - [ 'a/\\{x,y}/cde', {}, [ 'a/{x,y}/cde' ] ], - [ 'a/\\{{b,c}{e,f}/g', {}, [ 'a/{be/g', 'a/{bf/g', 'a/{ce/g', 'a/{cf/g' ] ], - [ 'a/\\{{b,c}{e,f}\\}/g', {}, [ 'a/{be}/g', 'a/{bf}/g', 'a/{ce}/g', 'a/{cf}/g' ] ], - [ 'a/\\{{b,c}{e,f}}/g', {}, [ 'a/{be}/g', 'a/{bf}/g', 'a/{ce}/g', 'a/{cf}/g' ] ], - [ 'a/b/{b,c,{d,e{f,g},{w,x}/{y,z}}}/h/i', {}, [ 'a/b/b/h/i', 'a/b/c/h/i', 'a/b/d/h/i', 'a/b/ef/h/i', 'a/b/eg/h/i', 'a/b/w/y/h/i', 'a/b/w/z/h/i', 'a/b/x/y/h/i', 'a/b/x/z/h/i' ] ], - [ 'a/{b,c,d}{e,f}/g', {}, [ 'a/be/g', 'a/bf/g', 'a/ce/g', 'a/cf/g', 'a/de/g', 'a/df/g' ] ], - [ 'a/{b,c\\,d}{e,f}/g', {}, [ 'a/be/g', 'a/bf/g', 'a/c,de/g', 'a/c,df/g' ] ], - [ 'a/{b,c\\}}{e,f}/g', {}, [ 'a/be/g', 'a/bf/g', 'a/c}e/g', 'a/c}f/g' ] ], - [ 'a/{b,c}', {}, [ 'a/b', 'a/c' ] ], - [ 'a/{b,c}d{e,f}/g', {}, [ 'a/bde/g', 'a/bdf/g', 'a/cde/g', 'a/cdf/g' ] ], - [ 'a/{b,c}{e,f}/g', {}, [ 'a/be/g', 'a/bf/g', 'a/ce/g', 'a/cf/g' ] ], - [ 'a/{b,c}{e,f}{g,h,i}/k', {}, [ 'a/beg/k', 'a/beh/k', 'a/bei/k', 'a/bfg/k', 'a/bfh/k', 'a/bfi/k', 'a/ceg/k', 'a/ceh/k', 'a/cei/k', 'a/cfg/k', 'a/cfh/k', 'a/cfi/k' ] ], - [ 'a/{b,{c,d},e}/f', {}, [ 'a/b/f', 'a/c/f', 'a/d/f', 'a/e/f' ] ], - [ 'a/{b,{c,d}/{e,f},g}/h', {}, [ 'a/b/h', 'a/c/e/h', 'a/c/f/h', 'a/d/e/h', 'a/d/f/h', 'a/g/h' ] ], - [ 'a/{b{c,d},e{f,g}h{i,j}}/k', {}, [ 'a/bc/k', 'a/bd/k', 'a/efhi/k', 'a/efhj/k', 'a/eghi/k', 'a/eghj/k' ] ], - [ 'a/{b{c,d},e}/f', {}, [ 'a/bc/f', 'a/bd/f', 'a/e/f' ] ], - [ 'a/{b{c,d}e{f,g}h{i,j}}/k', {}, [ 'a/{bcefhi}/k', 'a/{bcefhj}/k', 'a/{bceghi}/k', 'a/{bceghj}/k', 'a/{bdefhi}/k', 'a/{bdefhj}/k', 'a/{bdeghi}/k', 'a/{bdeghj}/k' ] ], - [ 'a/{b{c,d}e{f,g},h{i,j}}/k', {}, [ 'a/bcef/k', 'a/bceg/k', 'a/bdef/k', 'a/bdeg/k', 'a/hi/k', 'a/hj/k' ] ], - [ 'a/{x,z}{b,{c,d}/{e,f},g}/h', {}, [ 'a/xb/h', 'a/xc/e/h', 'a/xc/f/h', 'a/xd/e/h', 'a/xd/f/h', 'a/xg/h', 'a/zb/h', 'a/zc/e/h', 'a/zc/f/h', 'a/zd/e/h', 'a/zd/f/h', 'a/zg/h' ] ], - [ 'a/{{a,b}/{c,d}}/z', {}, [ 'a/{a/c}/z', 'a/{a/d}/z', 'a/{b/c}/z', 'a/{b/d}/z' ] ], - [ 'a/{{b,c}/{d,e}}', {}, [ 'a/{b/d}', 'a/{b/e}', 'a/{c/d}', 'a/{c/e}' ] ], - [ 'a/{{b,c}/{d,e}}/f', {}, [ 'a/{b/d}/f', 'a/{b/e}/f', 'a/{c/d}/f', 'a/{c/e}/f' ] ], - [ 'a{b}c', {}, [ 'a{b}c' ] ], - [ 'foo {1,2} bar', {}, [ 'foo 1 bar', 'foo 2 bar' ] ], - [ '{ }', {}, [ '{ }' ] ], - [ '{', {}, [ '{' ] ], - [ '{a,b,{c,d},e}', {}, [ 'a', 'b', 'c', 'd', 'e' ] ], - [ '{a,b,{c,d}e}', {}, [ 'a', 'b', 'ce', 'de' ] ], - [ '{a,b,{c,d}}', {}, [ 'a', 'b', 'c', 'd' ] ], - [ '{a,b{c,d}}', {}, [ 'a', 'bc', 'bd' ] ], - [ '{a,b}/{c,d}', {}, [ 'a/c', 'a/d', 'b/c', 'b/d' ] ], - [ '{a,b}c,d\\}', {}, [ 'ac,d}', 'bc,d}' ] ], - [ '{a,b\\}c,d}', {}, [ 'a', 'b}c', 'd' ] ], - [ '{a,b}{c,d}', {}, [ 'ac', 'ad', 'bc', 'bd' ] ], - [ '{abc}', {}, [ '{abc}' ] ], - [ '{b{c,d},e}', {}, [ 'bc', 'bd', 'e' ] ], - [ '{b{c,d},e}/f', {}, [ 'bc/f', 'bd/f', 'e/f' ] ], - [ 'x,y,{abc},trie', {}, [ 'x,y,{abc},trie' ] ], - [ '{{a,b},{c,d}}', {}, [ 'a', 'b', 'c', 'd' ] ], - [ '{{a,b}/{c,d}}', {}, [ '{a/c}', '{a/d}', '{b/c}', '{b/d}' ] ], - [ '{{a,b}/{c,d}}/z', {}, [ '{a/c}/z', '{a/d}/z', '{b/c}/z', '{b/d}/z' ] ], - [ '{}', {}, [ '{}' ] ], + ['a/\\{b,c,d,{x,y}}{e,f\\}/g', {}, ['a/{b,c,d,x}{e,f}/g', 'a/{b,c,d,y}{e,f}/g']], + ['a/\\{b,c,d\\}\\{e,f\\}/g', {}, ['a/{b,c,d}{e,f}/g']], + ['a/\\{b,c,d\\}\\{e,f}/g', {}, ['a/{b,c,d}{e,f}/g']], + ['a/\\{b,c,d\\}{e,f}/g', {}, ['a/{b,c,d}e/g', 'a/{b,c,d}f/g']], + ['a/\\{b,c,d{x,y}}{e,f\\}/g', {}, ['a/{b,c,dx}{e,f}/g', 'a/{b,c,dy}{e,f}/g']], + ['a/\\{b,c,d}{e,f\\}/g', {}, ['a/{b,c,d}{e,f}/g']], + ['a/\\{b,c,d}{e,f}/g', {}, ['a/{b,c,d}e/g', 'a/{b,c,d}f/g']], + ['a/\\{x,y}/cde', {}, ['a/{x,y}/cde']], + ['a/\\{{b,c}{e,f}/g', {}, ['a/{be/g', 'a/{bf/g', 'a/{ce/g', 'a/{cf/g']], + ['a/\\{{b,c}{e,f}\\}/g', {}, ['a/{be}/g', 'a/{bf}/g', 'a/{ce}/g', 'a/{cf}/g']], + ['a/\\{{b,c}{e,f}}/g', {}, ['a/{be}/g', 'a/{bf}/g', 'a/{ce}/g', 'a/{cf}/g']], + ['a/b/{b,c,{d,e{f,g},{w,x}/{y,z}}}/h/i', {}, ['a/b/b/h/i', 'a/b/c/h/i', 'a/b/d/h/i', 'a/b/ef/h/i', 'a/b/eg/h/i', 'a/b/w/y/h/i', 'a/b/w/z/h/i', 'a/b/x/y/h/i', 'a/b/x/z/h/i']], + ['a/{b,c,d}{e,f}/g', {}, ['a/be/g', 'a/bf/g', 'a/ce/g', 'a/cf/g', 'a/de/g', 'a/df/g']], + ['a/{b,c\\,d}{e,f}/g', {}, ['a/be/g', 'a/bf/g', 'a/c,de/g', 'a/c,df/g']], + ['a/{b,c\\}}{e,f}/g', {}, ['a/be/g', 'a/bf/g', 'a/c}e/g', 'a/c}f/g']], + ['a/{b,c}', {}, ['a/b', 'a/c']], + ['a/{b,c}d{e,f}/g', {}, ['a/bde/g', 'a/bdf/g', 'a/cde/g', 'a/cdf/g']], + ['a/{b,c}{e,f}/g', {}, ['a/be/g', 'a/bf/g', 'a/ce/g', 'a/cf/g']], + ['a/{b,c}{e,f}{g,h,i}/k', {}, ['a/beg/k', 'a/beh/k', 'a/bei/k', 'a/bfg/k', 'a/bfh/k', 'a/bfi/k', 'a/ceg/k', 'a/ceh/k', 'a/cei/k', 'a/cfg/k', 'a/cfh/k', 'a/cfi/k']], + ['a/{b,{c,d},e}/f', {}, ['a/b/f', 'a/c/f', 'a/d/f', 'a/e/f']], + ['a/{b,{c,d}/{e,f},g}/h', {}, ['a/b/h', 'a/c/e/h', 'a/c/f/h', 'a/d/e/h', 'a/d/f/h', 'a/g/h']], + ['a/{b{c,d},e{f,g}h{i,j}}/k', {}, ['a/bc/k', 'a/bd/k', 'a/efhi/k', 'a/efhj/k', 'a/eghi/k', 'a/eghj/k']], + ['a/{b{c,d},e}/f', {}, ['a/bc/f', 'a/bd/f', 'a/e/f']], + ['a/{b{c,d}e{f,g}h{i,j}}/k', {}, ['a/{bcefhi}/k', 'a/{bcefhj}/k', 'a/{bceghi}/k', 'a/{bceghj}/k', 'a/{bdefhi}/k', 'a/{bdefhj}/k', 'a/{bdeghi}/k', 'a/{bdeghj}/k']], + ['a/{b{c,d}e{f,g},h{i,j}}/k', {}, ['a/bcef/k', 'a/bceg/k', 'a/bdef/k', 'a/bdeg/k', 'a/hi/k', 'a/hj/k']], + ['a/{x,z}{b,{c,d}/{e,f},g}/h', {}, ['a/xb/h', 'a/xc/e/h', 'a/xc/f/h', 'a/xd/e/h', 'a/xd/f/h', 'a/xg/h', 'a/zb/h', 'a/zc/e/h', 'a/zc/f/h', 'a/zd/e/h', 'a/zd/f/h', 'a/zg/h']], + ['a/{{a,b}/{c,d}}/z', {}, ['a/{a/c}/z', 'a/{a/d}/z', 'a/{b/c}/z', 'a/{b/d}/z']], + ['a/{{b,c}/{d,e}}', {}, ['a/{b/d}', 'a/{b/e}', 'a/{c/d}', 'a/{c/e}']], + ['a/{{b,c}/{d,e}}/f', {}, ['a/{b/d}/f', 'a/{b/e}/f', 'a/{c/d}/f', 'a/{c/e}/f']], + ['a{b}c', {}, ['a{b}c']], + ['foo {1,2} bar', {}, ['foo 1 bar', 'foo 2 bar']], + ['{ }', {}, ['{ }']], + ['{', {}, ['{']], + ['{a,b,{c,d},e}', {}, ['a', 'b', 'c', 'd', 'e']], + ['{a,b,{c,d}e}', {}, ['a', 'b', 'ce', 'de']], + ['{a,b,{c,d}}', {}, ['a', 'b', 'c', 'd']], + ['{a,b{c,d}}', {}, ['a', 'bc', 'bd']], + ['{a,b}/{c,d}', {}, ['a/c', 'a/d', 'b/c', 'b/d']], + ['{a,b}c,d\\}', {}, ['ac,d}', 'bc,d}']], + ['{a,b\\}c,d}', {}, ['a', 'b}c', 'd']], + ['{a,b}{c,d}', {}, ['ac', 'ad', 'bc', 'bd']], + ['{abc}', {}, ['{abc}']], + ['{b{c,d},e}', {}, ['bc', 'bd', 'e']], + ['{b{c,d},e}/f', {}, ['bc/f', 'bd/f', 'e/f']], + ['x,y,{abc},trie', {}, ['x,y,{abc},trie']], + ['{{a,b},{c,d}}', {}, ['a', 'b', 'c', 'd']], + ['{{a,b}/{c,d}}', {}, ['{a/c}', '{a/d}', '{b/c}', '{b/d}']], + ['{{a,b}/{c,d}}/z', {}, ['{a/c}/z', '{a/d}/z', '{b/c}/z', '{b/d}/z']], + ['{}', {}, ['{}']], // // should ignore globs - [ '}', {}, [ '}' ] ], + ['}', {}, ['}']], // 'should ignore globs', - [ '{generate,{assemble,update,verb}{file,-generate-*},generator}.js', {}, [ 'generate.js', 'assemblefile.js', 'assemble-generate-*.js', 'updatefile.js', 'update-generate-*.js', 'verbfile.js', 'verb-generate-*.js', 'generator.js' ] ], - [ '**/{foo,bar}.js', {}, [ '**/foo.js', '**/bar.js' ] ], - [ '**/{a,b,c}/*.js', {}, [ '**/a/*.js', '**/b/*.js', '**/c/*.js' ] ], - [ '**/{a,b,*}/*.js', {}, [ '**/a/*.js', '**/b/*.js', '**/*/*.js' ] ], - [ '**/{**,b,*}/*.js', {}, [ '**/**/*.js', '**/b/*.js', '**/*/*.js' ] ], - [ '/usr/{ucb/{ex,edit},lib/{ex,how_ex}}', {}, [ '/usr/ucb/ex', '/usr/ucb/edit', '/usr/lib/ex', '/usr/lib/how_ex' ] ], - [ 'ff{c,b,a}', {}, [ 'ffc', 'ffb', 'ffa' ] ], - [ 'f{d,e,f}g', {}, [ 'fdg', 'feg', 'ffg' ] ], - [ '{a,b,c}', {}, [ 'a', 'b', 'c' ] ], - [ '{l,m,n}xyz', {}, [ 'lxyz', 'mxyz', 'nxyz' ] ], - [ 'a/{a,b}/{c,d}/e', {}, [ 'a/a/c/e', 'a/a/d/e', 'a/b/c/e', 'a/b/d/e' ] ], - [ 'a{b,c}d{e,f}g', {}, [ 'abdeg', 'abdfg', 'acdeg', 'acdfg' ] ], - [ 'a/{x,y}/c{d,e}f.{md,txt}', {}, [ 'a/x/cdf.md', 'a/x/cdf.txt', 'a/x/cef.md', 'a/x/cef.txt', 'a/y/cdf.md', 'a/y/cdf.txt', 'a/y/cef.md', 'a/y/cef.txt' ] ], - [ '{a,b}{{a,b},a,b}', {}, [ 'aa', 'ab', 'aa', 'ab', 'ba', 'bb', 'ba', 'bb' ] ], - [ 'a{b,c{d,e}f}g', {}, [ 'abg', 'acdfg', 'acefg' ] ], - [ 'a{{x,y},z}b', {}, [ 'axb', 'ayb', 'azb' ] ], - [ 'f{x,y{g,z}}h', {}, [ 'fxh', 'fygh', 'fyzh' ] ], - [ 'a{b,c{d,e},h}x/z', {}, [ 'abx/z', 'acdx/z', 'acex/z', 'ahx/z' ] ], - [ 'a{b,c{d,e},h}x{y,z}', {}, [ 'abxy', 'abxz', 'acdxy', 'acdxz', 'acexy', 'acexz', 'ahxy', 'ahxz' ] ], - [ 'a{b,c{d,e},{f,g}h}x{y,z}', {}, [ 'abxy', 'abxz', 'acdxy', 'acdxz', 'acexy', 'acexz', 'afhxy', 'afhxz', 'aghxy', 'aghxz' ] ], + ['{generate,{assemble,update,verb}{file,-generate-*},generator}.js', {}, ['generate.js', 'assemblefile.js', 'assemble-generate-*.js', 'updatefile.js', 'update-generate-*.js', 'verbfile.js', 'verb-generate-*.js', 'generator.js']], + ['**/{foo,bar}.js', {}, ['**/foo.js', '**/bar.js']], + ['**/{a,b,c}/*.js', {}, ['**/a/*.js', '**/b/*.js', '**/c/*.js']], + ['**/{a,b,*}/*.js', {}, ['**/a/*.js', '**/b/*.js', '**/*/*.js']], + ['**/{**,b,*}/*.js', {}, ['**/**/*.js', '**/b/*.js', '**/*/*.js']], + ['/usr/{ucb/{ex,edit},lib/{ex,how_ex}}', {}, ['/usr/ucb/ex', '/usr/ucb/edit', '/usr/lib/ex', '/usr/lib/how_ex']], + ['ff{c,b,a}', {}, ['ffc', 'ffb', 'ffa']], + ['f{d,e,f}g', {}, ['fdg', 'feg', 'ffg']], + ['{a,b,c}', {}, ['a', 'b', 'c']], + ['{l,m,n}xyz', {}, ['lxyz', 'mxyz', 'nxyz']], + ['a/{a,b}/{c,d}/e', {}, ['a/a/c/e', 'a/a/d/e', 'a/b/c/e', 'a/b/d/e']], + ['a{b,c}d{e,f}g', {}, ['abdeg', 'abdfg', 'acdeg', 'acdfg']], + ['a/{x,y}/c{d,e}f.{md,txt}', {}, ['a/x/cdf.md', 'a/x/cdf.txt', 'a/x/cef.md', 'a/x/cef.txt', 'a/y/cdf.md', 'a/y/cdf.txt', 'a/y/cef.md', 'a/y/cef.txt']], + ['{a,b}{{a,b},a,b}', {}, ['aa', 'ab', 'aa', 'ab', 'ba', 'bb', 'ba', 'bb']], + ['a{b,c{d,e}f}g', {}, ['abg', 'acdfg', 'acefg']], + ['a{{x,y},z}b', {}, ['axb', 'ayb', 'azb']], + ['f{x,y{g,z}}h', {}, ['fxh', 'fygh', 'fyzh']], + ['a{b,c{d,e},h}x/z', {}, ['abx/z', 'acdx/z', 'acex/z', 'ahx/z']], + ['a{b,c{d,e},h}x{y,z}', {}, ['abxy', 'abxz', 'acdxy', 'acdxz', 'acexy', 'acexz', 'ahxy', 'ahxz']], + ['a{b,c{d,e},{f,g}h}x{y,z}', {}, ['abxy', 'abxz', 'acdxy', 'acdxz', 'acexy', 'acexz', 'afhxy', 'afhxz', 'aghxy', 'aghxz']], // 'should not expand escaped braces', - [ '\\{a,b,c,d,e}', {}, [ '{a,b,c,d,e}' ] ], - [ 'a/\\{b,c}/{d,e}/f', {}, [ 'a/{b,c}/d/f', 'a/{b,c}/e/f' ] ], - [ 'a/\\{x,y}/cde', {}, [ 'a/{x,y}/cde' ] ], - [ 'a/b/c/{x,y\\}', {}, [ 'a/b/c/{x,y}' ] ], - [ 'a/{z,\\{a,b,c,d,e}/d', {}, [ 'a/z/d', 'a/{a/d', 'a/b/d', 'a/c/d', 'a/d/d', 'a/e/d' ] ], - [ 'abcd{efgh', {}, [ 'abcd{efgh' ] ], - [ '{a,b\\}c,d}', {}, [ 'a', 'b}c', 'd' ] ], - [ '{abc}', {}, [ '{abc}' ] ], - [ '{x,y,\\{a,b,c\\}}', {}, [ 'x', 'y', '{a', 'b', 'c}' ] ], - [ '{x,y,{abc},trie}', {}, [ 'x', 'y', '{abc}', 'trie' ] ], - [ '{x,y,{a,b,c\\}}', {}, [ '{x,y,a', '{x,y,b', '{x,y,c}' ] ], + ['\\{a,b,c,d,e}', {}, ['{a,b,c,d,e}']], + ['a/\\{b,c}/{d,e}/f', {}, ['a/{b,c}/d/f', 'a/{b,c}/e/f']], + ['a/\\{x,y}/cde', {}, ['a/{x,y}/cde']], + ['a/b/c/{x,y\\}', {}, ['a/b/c/{x,y}']], + ['a/{z,\\{a,b,c,d,e}/d', {}, ['a/z/d', 'a/{a/d', 'a/b/d', 'a/c/d', 'a/d/d', 'a/e/d']], + ['abcd{efgh', {}, ['abcd{efgh']], + ['{a,b\\}c,d}', {}, ['a', 'b}c', 'd']], + ['{abc}', {}, ['{abc}']], + ['{x,y,\\{a,b,c\\}}', {}, ['x', 'y', '{a', 'b', 'c}']], + ['{x,y,{abc},trie}', {}, ['x', 'y', '{abc}', 'trie']], + ['{x,y,{a,b,c\\}}', {}, ['{x,y,a', '{x,y,b', '{x,y,c}']], 'should not expand escaped commas', - [ '{x\\,y,\\{abc\\},trie}', {}, [ 'x,y', '{abc}', 'trie' ] ], - [ 'a{b\\,c\\,d}e', {}, [ 'a{b,c,d}e' ] ], - [ 'a{b\\,c}d', {}, [ 'a{b,c}d' ] ], - [ '{abc\\,def}', {}, [ '{abc,def}' ] ], - [ '{abc\\,def,ghi}', {}, [ 'abc,def', 'ghi' ] ], - [ 'a/{b,c}/{x\\,y}/d/e', {}, [ 'a/b/{x,y}/d/e', 'a/c/{x,y}/d/e' ] ], + ['{x\\,y,\\{abc\\},trie}', {}, ['x,y', '{abc}', 'trie']], + ['a{b\\,c\\,d}e', {}, ['a{b,c,d}e']], + ['a{b\\,c}d', {}, ['a{b,c}d']], + ['{abc\\,def}', {}, ['{abc,def}']], + ['{abc\\,def,ghi}', {}, ['abc,def', 'ghi']], + ['a/{b,c}/{x\\,y}/d/e', {}, ['a/b/{x,y}/d/e', 'a/c/{x,y}/d/e']], 'should handle empty braces', - [ '{ }', {}, [ '{ }' ] ], - [ '{', {}, [ '{' ] ], - [ '{}', {}, [ '{}' ] ], - [ '}', {}, [ '}' ] ], + ['{ }', {}, ['{ }']], + ['{', {}, ['{']], + ['{}', {}, ['{}']], + ['}', {}, ['}']], 'should escape braces when only one value is defined', - [ 'a{b}c', {}, [ 'a{b}c' ] ], - [ 'a/b/c{d}e', {}, [ 'a/b/c{d}e' ] ], + ['a{b}c', {}, ['a{b}c']], + ['a/b/c{d}e', {}, ['a/b/c{d}e']], 'should escape closing braces when open is not defined', - [ '{a,b}c,d}', {}, [ 'ac,d}', 'bc,d}' ] ], + ['{a,b}c,d}', {}, ['ac,d}', 'bc,d}']], 'should not expand braces in sets with es6/bash-like variables', - [ 'abc/${ddd}/xyz', {}, [ 'abc/${ddd}/xyz' ] ], - [ 'a${b}c', {}, [ 'a${b}c' ] ], - [ 'a/{${b},c}/d', {}, [ 'a/${b}/d', 'a/c/d' ] ], - [ 'a${b,d}/{foo,bar}c', {}, [ 'a${b,d}/fooc', 'a${b,d}/barc' ] ], + ['abc/${ddd}/xyz', {}, ['abc/${ddd}/xyz']], + ['a${b}c', {}, ['a${b}c']], + ['a/{${b},c}/d', {}, ['a/${b}/d', 'a/c/d']], + ['a${b,d}/{foo,bar}c', {}, ['a${b,d}/fooc', 'a${b,d}/barc']], 'should support sequence brace operators', - [ 'ff{a,b,c}', {}, [ 'ffa', 'ffb', 'ffc' ] ], - [ 'f{d,e,f}g', {}, [ 'fdg', 'feg', 'ffg' ] ], - [ '{a,b,c}', {}, [ 'a', 'b', 'c' ] ], - [ '{l,m,n}xyz', {}, [ 'lxyz', 'mxyz', 'nxyz' ] ], + ['ff{a,b,c}', {}, ['ffa', 'ffb', 'ffc']], + ['f{d,e,f}g', {}, ['fdg', 'feg', 'ffg']], + ['{a,b,c}', {}, ['a', 'b', 'c']], + ['{l,m,n}xyz', {}, ['lxyz', 'mxyz', 'nxyz']], 'should expand multiple sets', - [ 'a/{a,b}/{c,d}/e', {}, [ 'a/a/c/e', 'a/a/d/e', 'a/b/c/e', 'a/b/d/e' ] ], - [ 'a{b,c}d{e,f}g', {}, [ 'abdeg', 'abdfg', 'acdeg', 'acdfg' ] ], - [ 'a/{x,y}/c{d,e}f.{md,txt}', {}, [ 'a/x/cdf.md', 'a/x/cdf.txt', 'a/x/cef.md', 'a/x/cef.txt', 'a/y/cdf.md', 'a/y/cdf.txt', 'a/y/cef.md', 'a/y/cef.txt' ] ], + ['a/{a,b}/{c,d}/e', {}, ['a/a/c/e', 'a/a/d/e', 'a/b/c/e', 'a/b/d/e']], + ['a{b,c}d{e,f}g', {}, ['abdeg', 'abdfg', 'acdeg', 'acdfg']], + ['a/{x,y}/c{d,e}f.{md,txt}', {}, ['a/x/cdf.md', 'a/x/cdf.txt', 'a/x/cef.md', 'a/x/cef.txt', 'a/y/cdf.md', 'a/y/cdf.txt', 'a/y/cef.md', 'a/y/cef.txt']], 'should expand nested sets', - [ 'a{b,c{d,e}f}g', {}, [ 'abg', 'acdfg', 'acefg' ] ], - [ 'a{{x,y},z}b', {}, [ 'axb', 'ayb', 'azb' ] ], - [ 'f{x,y{g,z}}h', {}, [ 'fxh', 'fygh', 'fyzh' ] ], - [ 'a{b,c{d,e},h}x/z', {}, [ 'abx/z', 'acdx/z', 'acex/z', 'ahx/z' ] ], - [ 'a{b,c{d,e},h}x{y,z}', {}, [ 'abxy', 'abxz', 'acdxy', 'acdxz', 'acexy', 'acexz', 'ahxy', 'ahxz' ] ], - [ 'a{b,c{d,e},{f,g}h}x{y,z}', {}, [ 'abxy', 'abxz', 'acdxy', 'acdxz', 'acexy', 'acexz', 'afhxy', 'afhxz', 'aghxy', 'aghxz' ] ], - [ 'a-{b{d,e}}-c', {}, [ 'a-{bd}-c', 'a-{be}-c' ] ], + ['a{b,c{d,e}f}g', {}, ['abg', 'acdfg', 'acefg']], + ['a{{x,y},z}b', {}, ['axb', 'ayb', 'azb']], + ['f{x,y{g,z}}h', {}, ['fxh', 'fygh', 'fyzh']], + ['a{b,c{d,e},h}x/z', {}, ['abx/z', 'acdx/z', 'acex/z', 'ahx/z']], + ['a{b,c{d,e},h}x{y,z}', {}, ['abxy', 'abxz', 'acdxy', 'acdxz', 'acexy', 'acexz', 'ahxy', 'ahxz']], + ['a{b,c{d,e},{f,g}h}x{y,z}', {}, ['abxy', 'abxz', 'acdxy', 'acdxz', 'acexy', 'acexz', 'afhxy', 'afhxz', 'aghxy', 'aghxz']], + ['a-{b{d,e}}-c', {}, ['a-{bd}-c', 'a-{be}-c']], 'should do nothing to glob characters', - [ 'a/b/{d,e}/*.js', {}, [ 'a/b/d/*.js', 'a/b/e/*.js' ] ], - [ 'a/**/c/{d,e}/f*.js', {}, [ 'a/**/c/d/f*.js', 'a/**/c/e/f*.js' ] ], - [ 'a/**/c/{d,e}/f*.{md,txt}', {}, [ 'a/**/c/d/f*.md', 'a/**/c/d/f*.txt', 'a/**/c/e/f*.md', 'a/**/c/e/f*.txt' ] ], - [ 'a/b/{d,e,[1-5]}/*.js', {}, [ 'a/b/d/*.js', 'a/b/e/*.js', 'a/b/[1-5]/*.js' ] ], + ['a/b/{d,e}/*.js', {}, ['a/b/d/*.js', 'a/b/e/*.js']], + ['a/**/c/{d,e}/f*.js', {}, ['a/**/c/d/f*.js', 'a/**/c/e/f*.js']], + ['a/**/c/{d,e}/f*.{md,txt}', {}, ['a/**/c/d/f*.md', 'a/**/c/d/f*.txt', 'a/**/c/e/f*.md', 'a/**/c/e/f*.txt']], + ['a/b/{d,e,[1-5]}/*.js', {}, ['a/b/d/*.js', 'a/b/e/*.js', 'a/b/[1-5]/*.js']], 'should work with leading and trailing commas', - [ 'a{b,}c', {}, [ 'abc', 'ac' ] ], - [ 'a{,b}c', {}, [ 'ac', 'abc' ] ], + ['a{b,}c', {}, ['abc', 'ac']], + ['a{,b}c', {}, ['ac', 'abc']], 'should handle spaces', - [ 'a{ ,c{d, },h}x', {}, [ 'a x', 'acdx', 'ac x', 'ahx' ] ], - [ 'a{ ,c{d, },h} ', {}, [ 'a ', 'acd ', 'ac ', 'ah ' ] ], + ['a{ ,c{d, },h}x', {}, ['a x', 'acdx', 'ac x', 'ahx']], + ['a{ ,c{d, },h} ', {}, ['a ', 'acd ', 'ac ', 'ah ']], 'see https://github.com/jonschlinkert/microequal/issues/66', - [ '/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.{html,ejs}', {}, [ '/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.html', '/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.ejs' ] ], + ['/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.{html,ejs}', {}, ['/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.html', '/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.ejs']], 'should handle weirdly-formed brace expansions (fixed in post-bash-3.1)', - [ 'a-{b{d,e}}-c', {}, [ 'a-{bd}-c', 'a-{be}-c' ] ], - [ 'a-{bdef-{g,i}-c', {}, [ 'a-{bdef-g-c', 'a-{bdef-i-c' ] ], + ['a-{b{d,e}}-c', {}, ['a-{bd}-c', 'a-{be}-c']], + ['a-{bdef-{g,i}-c', {}, ['a-{bdef-g-c', 'a-{bdef-i-c']], // 'should not expand quoted strings', - [ '{"foo"}{1,2,3}', {}, [ '{foo}1', '{foo}2', '{foo}3' ] ], - [ '{"foo"}{1,2,3}', { keepQuotes: true }, [ '{"foo"}1', '{"foo"}2', '{"foo"}3' ] ], - [ '{"x,x"}', { keepQuotes: true }, [ '{"x,x"}' ] ], - [ '{\'x,x\'}', { keepQuotes: true }, [ '{\'x,x\'}' ] ], + ['{"foo"}{1,2,3}', {}, ['{foo}1', '{foo}2', '{foo}3']], + ['{"foo"}{1,2,3}', { keepQuotes: true }, ['{"foo"}1', '{"foo"}2', '{"foo"}3']], + ['{"x,x"}', { keepQuotes: true }, ['{"x,x"}']], + ['{\'x,x\'}', { keepQuotes: true }, ['{\'x,x\'}']], 'should escape outer braces in nested non-sets', - [ '{a-{b,c,d}}', {}, [ '{a-b}', '{a-c}', '{a-d}' ] ], - [ '{a,{a-{b,c,d}}}', {}, [ 'a', '{a-b}', '{a-c}', '{a-d}' ] ], + ['{a-{b,c,d}}', {}, ['{a-b}', '{a-c}', '{a-d}']], + ['{a,{a-{b,c,d}}}', {}, ['a', '{a-b}', '{a-c}', '{a-d}']], 'should escape imbalanced braces', - [ 'abc{', {}, [ 'abc{' ] ], - [ '{abc{', {}, [ '{abc{' ] ], - [ '{abc', {}, [ '{abc' ] ], - [ '}abc', {}, [ '}abc' ] ], - [ 'ab{c', {}, [ 'ab{c' ] ], - [ 'ab{c', {}, [ 'ab{c' ] ], - [ '{{a,b}', {}, [ '{a', '{b' ] ], - [ '{a,b}}', {}, [ 'a}', 'b}' ] ], - [ 'a{b{c{d,e}f}gh', {}, [ 'a{b{cdf}gh', 'a{b{cef}gh' ] ], - [ 'a{b{c{d,e}f}g}h', {}, [ 'a{b{cdf}g}h', 'a{b{cef}g}h' ] ], - [ 'f{x,y{{g,z}}h}', {}, [ 'fx', 'fy{g}h', 'fy{z}h' ] ], - [ 'z{a,b},c}d', {}, [ 'za,c}d', 'zb,c}d' ] ], - [ 'a{b{c{d,e}f{x,y{{g}h', {}, [ 'a{b{cdf{x,y{{g}h', 'a{b{cef{x,y{{g}h' ] ], - [ 'f{x,y{{g}h', {}, [ 'f{x,y{{g}h' ] ], - [ 'f{x,y{{g}}h', {}, [ 'f{x,y{{g}}h' ] ], - [ 'a{b{c{d,e}f{x,y{}g}h', {}, [ 'a{b{cdfxh', 'a{b{cdfy{}gh', 'a{b{cefxh', 'a{b{cefy{}gh' ] ], - [ 'f{x,y{}g}h', {}, [ 'fxh', 'fy{}gh' ] ], - [ 'z{a,b{,c}d', {}, [ 'z{a,bd', 'z{a,bcd' ] ] + ['abc{', {}, ['abc{']], + ['{abc{', {}, ['{abc{']], + ['{abc', {}, ['{abc']], + ['}abc', {}, ['}abc']], + ['ab{c', {}, ['ab{c']], + ['ab{c', {}, ['ab{c']], + ['{{a,b}', {}, ['{a', '{b']], + ['{a,b}}', {}, ['a}', 'b}']], + ['a{b{c{d,e}f}gh', {}, ['a{b{cdf}gh', 'a{b{cef}gh']], + ['a{b{c{d,e}f}g}h', {}, ['a{b{cdf}g}h', 'a{b{cef}g}h']], + ['f{x,y{{g,z}}h}', {}, ['fx', 'fy{g}h', 'fy{z}h']], + ['z{a,b},c}d', {}, ['za,c}d', 'zb,c}d']], + ['a{b{c{d,e}f{x,y{{g}h', {}, ['a{b{cdf{x,y{{g}h', 'a{b{cef{x,y{{g}h']], + ['f{x,y{{g}h', {}, ['f{x,y{{g}h']], + ['f{x,y{{g}}h', {}, ['f{x,y{{g}}h']], + ['a{b{c{d,e}f{x,y{}g}h', {}, ['a{b{cdfxh', 'a{b{cdfy{}gh', 'a{b{cefxh', 'a{b{cefy{}gh']], + ['f{x,y{}g}h', {}, ['fxh', 'fy{}gh']], + ['z{a,b{,c}d', {}, ['z{a,bd', 'z{a,bcd']] ]; fixtures.forEach(arr => { @@ -230,9 +230,9 @@ describe('bash - expanded brace sets', () => { return; } - let options = { ...arr[1] }; - let pattern = arr[0]; - let expected = arr[2]; + const options = { ...arr[1] }; + const pattern = arr[0]; + const expected = arr[2]; if (options.skip !== true) { it('should compile: ' + pattern, () => equal(pattern, expected, options)); diff --git a/test/bash-spec.js b/test/bash-spec.js index a32f42d..5675f5e 100644 --- a/test/bash-spec.js +++ b/test/bash-spec.js @@ -22,159 +22,159 @@ const equal = (input, expected = bash(input), options) => { */ describe('bash', () => { - var fixtures = [ - [ '{1\\.2}', {}, [ '{1.2}' ] ], - [ '{1\\.2}', { keepEscaping: true }, [ '{1\\.2}' ] ], - [ '{"x,x"}', {}, [ '{x,x}' ] ], - [ '{x","x}', {}, [ '{x,x}' ] ], - [ '\'{x,x}\'', {}, [ '{x,x}' ] ], - [ '{x`,`x}', {}, [ '{x,x}' ] ], - [ '{x`,`x}', { keepQuotes: true }, [ '{x`,`x}' ] ], - [ '\'{a,b}{{a,b},a,b}\'', {}, [ '{a,b}{{a,b},a,b}' ] ], - [ 'A{b,{d,e},{f,g}}Z', {}, [ 'AbZ', 'AdZ', 'AeZ', 'AfZ', 'AgZ' ] ], - [ 'PRE-{a,b}{{a,b},a,b}-POST', {}, [ 'PRE-aa-POST', 'PRE-ab-POST', 'PRE-aa-POST', 'PRE-ab-POST', 'PRE-ba-POST', 'PRE-bb-POST', 'PRE-ba-POST', 'PRE-bb-POST' ] ], - [ '\\{a,b}{{a,b},a,b}', {}, [ '{a,b}a', '{a,b}b', '{a,b}a', '{a,b}b' ] ], - [ '{{a,b}', {}, [ '{a', '{b' ] ], - [ '{a,b}}', {}, [ 'a}', 'b}' ] ], - [ '{,}', {}, ['', ''] ], - [ 'a{,}', {}, [ 'a', 'a' ] ], - [ '{,}b', {}, [ 'b', 'b' ] ], - [ 'a{,}b', {}, [ 'ab', 'ab' ] ], - [ 'a{b}c', {}, [ 'a{b}c' ] ], - [ 'a{1..5}b', {}, [ 'a1b', 'a2b', 'a3b', 'a4b', 'a5b' ] ], - [ 'a{01..5}b', {}, [ 'a01b', 'a02b', 'a03b', 'a04b', 'a05b' ] ], - [ 'a{-01..5}b', {}, [ 'a-01b', 'a000b', 'a001b', 'a002b', 'a003b', 'a004b', 'a005b' ] ], - [ 'a{-01..5..3}b', {}, [ 'a-01b', 'a002b', 'a005b' ] ], - [ 'a{001..9}b', {}, [ 'a001b', 'a002b', 'a003b', 'a004b', 'a005b', 'a006b', 'a007b', 'a008b', 'a009b' ] ], - [ 'a{b,c{d,e},{f,g}h}x{y,z', {}, [ 'abx{y,z', 'acdx{y,z', 'acex{y,z', 'afhx{y,z', 'aghx{y,z' ] ], - [ 'a{b,c{d,e},{f,g}h}x{y,z\\}', {}, [ 'abx{y,z}', 'acdx{y,z}', 'acex{y,z}', 'afhx{y,z}', 'aghx{y,z}' ] ], - [ 'a{b,c{d,e},{f,g}h}x{y,z}', {}, [ 'abxy', 'abxz', 'acdxy', 'acdxz', 'acexy', 'acexz', 'afhxy', 'afhxz', 'aghxy', 'aghxz' ] ], - [ 'a{b{c{d,e}f{x,y{{g}h', {}, [ 'a{b{cdf{x,y{{g}h', 'a{b{cef{x,y{{g}h' ] ], - [ 'a{b{c{d,e}f{x,y{}g}h', {}, [ 'a{b{cdfxh', 'a{b{cdfy{}gh', 'a{b{cefxh', 'a{b{cefy{}gh' ] ], - [ 'a{b{c{d,e}f{x,y}}g}h', {}, [ 'a{b{cdfx}g}h', 'a{b{cdfy}g}h', 'a{b{cefx}g}h', 'a{b{cefy}g}h' ] ], - [ 'a{b{c{d,e}f}g}h', {}, [ 'a{b{cdf}g}h', 'a{b{cef}g}h' ] ], - [ 'a{{x,y},z}b', {}, [ 'axb', 'ayb', 'azb' ] ], - [ 'f{x,y{g,z}}h', {}, [ 'fxh', 'fygh', 'fyzh' ] ], - [ 'f{x,y{{g,z}}h', {}, [ 'f{x,y{g}h', 'f{x,y{z}h' ] ], - [ 'f{x,y{{g,z}}h}', {}, [ 'fx', 'fy{g}h', 'fy{z}h' ] ], - [ 'f{x,y{{g}h', {}, [ 'f{x,y{{g}h' ] ], - [ 'f{x,y{{g}}h', {}, [ 'f{x,y{{g}}h' ] ], - [ 'f{x,y{}g}h', {}, [ 'fxh', 'fy{}gh' ] ], - [ 'z{a,b{,c}d', {}, [ 'z{a,bd', 'z{a,bcd' ] ], - [ 'z{a,b},c}d', {}, [ 'za,c}d', 'zb,c}d' ] ], - [ '{-01..5}', {}, [ '-01', '000', '001', '002', '003', '004', '005' ] ], - [ '{-05..100..5}', {}, [ '-05', '000', '005', '010', '015', '020', '025', '030', '035', '040', '045', '050', '055', '060', '065', '070', '075', '080', '085', '090', '095', '100' ] ], - [ '{-05..100}', {}, [ '-05', '-04', '-03', '-02', '-01', '000', '001', '002', '003', '004', '005', '006', '007', '008', '009', '010', '011', '012', '013', '014', '015', '016', '017', '018', '019', '020', '021', '022', '023', '024', '025', '026', '027', '028', '029', '030', '031', '032', '033', '034', '035', '036', '037', '038', '039', '040', '041', '042', '043', '044', '045', '046', '047', '048', '049', '050', '051', '052', '053', '054', '055', '056', '057', '058', '059', '060', '061', '062', '063', '064', '065', '066', '067', '068', '069', '070', '071', '072', '073', '074', '075', '076', '077', '078', '079', '080', '081', '082', '083', '084', '085', '086', '087', '088', '089', '090', '091', '092', '093', '094', '095', '096', '097', '098', '099', '100' ] ], - [ '{0..5..2}', {}, [ '0', '2', '4' ] ], - [ '{0001..05..2}', {}, [ '0001', '0003', '0005' ] ], - [ '{0001..-5..2}', {}, [ '0001', '-001', '-003', '-005' ] ], - [ '{0001..-5..-2}', {}, [ '0001', '-001', '-003', '-005' ] ], - [ '{0001..5..-2}', {}, [ '0001', '0003', '0005' ] ], - [ '{01..5}', {}, [ '01', '02', '03', '04', '05' ] ], - [ '{1..05}', {}, [ '01', '02', '03', '04', '05' ] ], - [ '{1..05..3}', {}, [ '01', '04' ] ], - [ '{05..100}', {}, [ '005', '006', '007', '008', '009', '010', '011', '012', '013', '014', '015', '016', '017', '018', '019', '020', '021', '022', '023', '024', '025', '026', '027', '028', '029', '030', '031', '032', '033', '034', '035', '036', '037', '038', '039', '040', '041', '042', '043', '044', '045', '046', '047', '048', '049', '050', '051', '052', '053', '054', '055', '056', '057', '058', '059', '060', '061', '062', '063', '064', '065', '066', '067', '068', '069', '070', '071', '072', '073', '074', '075', '076', '077', '078', '079', '080', '081', '082', '083', '084', '085', '086', '087', '088', '089', '090', '091', '092', '093', '094', '095', '096', '097', '098', '099', '100' ] ], - [ '{0a..0z}', {}, [ '{0a..0z}' ] ], - [ '{a,b\\}c,d}', {}, [ 'a', 'b}c', 'd' ] ], - [ '{a,b{c,d}', {}, [ '{a,bc', '{a,bd' ] ], - [ '{a,b}c,d}', {}, [ 'ac,d}', 'bc,d}' ] ], - [ '{a..F}', {}, [ 'a', '`', '_', '^', ']', '\\', '[', 'Z', 'Y', 'X', 'W', 'V', 'U', 'T', 'S', 'R', 'Q', 'P', 'O', 'N', 'M', 'L', 'K', 'J', 'I', 'H', 'G', 'F' ] ], - [ '{A..f}', {}, [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f' ] ], - [ '{a..Z}', {}, [ 'a', '`', '_', '^', ']', '\\', '[', 'Z' ] ], - [ '{A..z}', {}, [ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' ] ], - [ '{z..A}', {}, [ 'z', 'y', 'x', 'w', 'v', 'u', 't', 's', 'r', 'q', 'p', 'o', 'n', 'm', 'l', 'k', 'j', 'i', 'h', 'g', 'f', 'e', 'd', 'c', 'b', 'a', '`', '_', '^', ']', '\\', '[', 'Z', 'Y', 'X', 'W', 'V', 'U', 'T', 'S', 'R', 'Q', 'P', 'O', 'N', 'M', 'L', 'K', 'J', 'I', 'H', 'G', 'F', 'E', 'D', 'C', 'B', 'A' ] ], - [ '{Z..a}', {}, [ 'Z', '[', '\\', ']', '^', '_', '`', 'a' ] ], - [ '{a..F..2}', {}, [ 'a', '_', ']', '[', 'Y', 'W', 'U', 'S', 'Q', 'O', 'M', 'K', 'I', 'G' ] ], - [ '{A..f..02}', {}, [ 'A', 'C', 'E', 'G', 'I', 'K', 'M', 'O', 'Q', 'S', 'U', 'W', 'Y', '[', ']', '_', 'a', 'c', 'e' ] ], - [ '{a..Z..5}', {}, [ 'a', '\\' ] ], - [ 'd{a..Z..5}b', {}, [ 'dab', 'd\\b' ] ], - [ '{A..z..10}', {}, [ 'A', 'K', 'U', '_', 'i', 's' ] ], - [ '{z..A..-2}', {}, [ 'z', 'x', 'v', 't', 'r', 'p', 'n', 'l', 'j', 'h', 'f', 'd', 'b', '`', '^', '\\', 'Z', 'X', 'V', 'T', 'R', 'P', 'N', 'L', 'J', 'H', 'F', 'D', 'B' ] ], - [ '{Z..a..20}', {}, [ 'Z' ] ], - [ '{a{,b}', {}, [ '{a', '{ab' ] ], - [ '{a\\},b}', {}, [ 'a}', 'b' ] ], - [ '{x,y{,}g}', {}, [ 'x', 'yg', 'yg' ] ], - [ '{x,y{}g}', {}, [ 'x', 'y{}g' ] ], - [ '{{a,b}', {}, [ '{a', '{b' ] ], - [ '{{a,b},c}', {}, [ 'a', 'b', 'c' ] ], - [ '{{a,b}c}', {}, [ '{ac}', '{bc}' ] ], - [ '{{a,b},}', {}, [ 'a', 'b', '' ] ], - [ 'X{{a,b},}X', {}, [ 'XaX', 'XbX', 'XX' ] ], - [ '{{a,b},}c', {}, [ 'ac', 'bc', 'c' ] ], - [ '{{a,b}.}', {}, [ '{a.}', '{b.}' ] ], - [ '{{a,b}}', {}, [ '{a}', '{b}' ] ], - [ 'X{a..#}X', {}, ['XaX', 'X`X', 'X_X', 'X^X', 'X]X', 'X\\X', 'X[X', 'XZX', 'XYX', 'XXX', 'XWX', 'XVX', 'XUX', 'XTX', 'XSX', 'XRX', 'XQX', 'XPX', 'XOX', 'XNX', 'XMX', 'XLX', 'XKX', 'XJX', 'XIX', 'XHX', 'XGX', 'XFX', 'XEX', 'XDX', 'XCX', 'XBX', 'XAX', 'X@X', 'X?X', 'X>X', 'X=X', 'XX', 'X=X', 'X { @@ -182,9 +182,9 @@ describe('bash', () => { return; } - let options = { ...arr[1] }; - let pattern = arr[0]; - let expected = arr[2]; + const options = { ...arr[1] }; + const pattern = arr[0]; + const expected = arr[2]; if (options.skip === true) { return; diff --git a/test/braces.compile.js b/test/braces.compile.js index fc8697d..04b42b1 100644 --- a/test/braces.compile.js +++ b/test/braces.compile.js @@ -53,11 +53,12 @@ describe('braces.compile()', () => { }); it('should compile zero-padded numeric ranges', () => { - assert.equal(compile(parse('{01..05}')), '(0?[1-5])'); + assert.equal(compile(parse('{01..05}')), '(0[1-5])'); }); it('should compile zero-padded numeric ranges with increments', () => { - assert.equal(compile(parse('{01..05..2}')), '(1|3|5)'); + assert.equal(compile(parse('{01..05..2}')), '(01|03|05)'); + assert.equal(compile(parse('{01..05..3}')), '(01|04)'); }); }); diff --git a/test/braces.expand.js b/test/braces.expand.js index 4d34c62..c95fbb8 100644 --- a/test/braces.expand.js +++ b/test/braces.expand.js @@ -8,7 +8,7 @@ const bashPath = require('bash-path'); const cp = require('child_process'); const braces = require('..'); -const bash = (input) => { +const bash = input => { return cp .spawnSync(bashPath(), ['-c', `echo ${input}`]) .stdout.toString() @@ -22,7 +22,7 @@ const equal = (input, expected = bash(input), options) => { describe('unit tests from brace-expand', () => { describe('extglobs', () => { - it.skip('should split on commas when braces are inside extglobs', () => { + it('should split on commas when braces are inside extglobs', () => { equal('*(a|{b|c,d})', ['*(a|b|c)', '*(a|d)']); }); @@ -61,7 +61,7 @@ describe('unit tests from brace-expand', () => { 'through', 'throughout', 'rough', - 'roughout', + 'roughout' ]); equal('{{,eno,thro,ro}ugh,}{,out}', [ 'ugh', @@ -73,7 +73,7 @@ describe('unit tests from brace-expand', () => { 'rough', 'roughout', '', - 'out', + 'out' ]); equal('{,{,a,b}z}{,c}', ['', 'c', 'z', 'zc', 'az', 'azc', 'bz', 'bzc']); equal('{,{,a,b}z}{c,}', ['c', '', 'zc', 'z', 'azc', 'az', 'bzc', 'bz']); diff --git a/test/braces.parse.js b/test/braces.parse.js index b814558..9158316 100644 --- a/test/braces.parse.js +++ b/test/braces.parse.js @@ -7,29 +7,29 @@ const parse = require('../lib/parse'); describe('braces.parse()', () => { describe('errors', () => { it('should throw an error when string exceeds max safe length', () => { - let MAX_LENGTH = 1024 * 64; + const MAX_LENGTH = 1024 * 64; assert.throws(() => parse('.'.repeat(MAX_LENGTH + 2))); }); }); describe('valid', () => { it('should return an AST', () => { - let ast = parse('a/{b,c}/d'); - let brace = ast.nodes.find(node => node.type === 'brace'); + const ast = parse('a/{b,c}/d'); + const brace = ast.nodes.find(node => node.type === 'brace'); assert(brace); assert.equal(brace.nodes.length, 5); }); it('should ignore braces inside brackets', () => { - let ast = parse('a/[{b,c}]/d'); + const ast = parse('a/[{b,c}]/d'); assert.equal(ast.nodes[1].type, 'text'); assert.equal(ast.nodes[1].value, 'a/[{b,c}]/d'); }); it('should parse braces with brackets inside', () => { - let ast = parse('a/{a,b,[{c,d}]}/e'); - let brace = ast.nodes[2]; - let bracket = brace.nodes.find(node => node.value[0] === '['); + const ast = parse('a/{a,b,[{c,d}]}/e'); + const brace = ast.nodes[2]; + const bracket = brace.nodes.find(node => node.value[0] === '['); assert(bracket); assert.equal(bracket.value, '[{c,d}]'); }); @@ -37,11 +37,11 @@ describe('braces.parse()', () => { describe('invalid', () => { it('should escape standalone closing braces', () => { - let one = parse('}'); + const one = parse('}'); assert.equal(one.nodes[1].type, 'text'); assert.equal(one.nodes[1].value, '}'); - let two = parse('a}b'); + const two = parse('a}b'); assert.equal(two.nodes[1].type, 'text'); assert.equal(two.nodes[1].value, 'a}b'); }); diff --git a/test/minimatch.js b/test/minimatch.js index 72a1182..c2d42f2 100644 --- a/test/minimatch.js +++ b/test/minimatch.js @@ -10,14 +10,14 @@ const braces = require('..'); describe('brace expansion', () => { const units = [ ['a{b,c{d,e},{f,g}h}x{y,z}', ['abxy', 'abxz', 'acdxy', 'acdxz', 'acexy', 'acexz', 'afhxy', 'afhxz', 'aghxy', 'aghxz']], - ['a{1..5}b', ['a1b', 'a2b', 'a3b', 'a4b', 'a5b'] ], + ['a{1..5}b', ['a1b', 'a2b', 'a3b', 'a4b', 'a5b']], ['a{b}c', ['a{b}c']], - ['a{00..05}b', ['a00b', 'a01b', 'a02b', 'a03b', 'a04b', 'a05b'] ], + ['a{00..05}b', ['a00b', 'a01b', 'a02b', 'a03b', 'a04b', 'a05b']], ['z{a,b},c}d', ['za,c}d', 'zb,c}d']], ['z{a,b{,c}d', ['z{a,bd', 'z{a,bcd']], ['a{b{c{d,e}f}g}h', ['a{b{cdf}g}h', 'a{b{cef}g}h']], - ['a{b{c{d,e}f{x,y}}g}h', ['a{b{cdfx}g}h', 'a{b{cdfy}g}h', 'a{b{cefx}g}h', 'a{b{cefy}g}h'] ], - ['a{b{c{d,e}f{x,y{}g}h', ['a{b{cdfxh', 'a{b{cdfy{}gh', 'a{b{cefxh', 'a{b{cefy{}gh'] ] + ['a{b{c{d,e}f{x,y}}g}h', ['a{b{cdfx}g}h', 'a{b{cdfy}g}h', 'a{b{cefx}g}h', 'a{b{cefy}g}h']], + ['a{b{c{d,e}f{x,y{}g}h', ['a{b{cdfxh', 'a{b{cdfy{}gh', 'a{b{cefxh', 'a{b{cefy{}gh']] ]; units.forEach(unit => { diff --git a/test/readme.js b/test/readme.js index bb983ba..a3bc702 100644 --- a/test/readme.js +++ b/test/readme.js @@ -9,8 +9,8 @@ describe('Examples from README.md', () => { it('Compiled', () => { assert.deepEqual(braces('a/{x,y,z}/b'), ['a/(x|y|z)/b']); assert.deepEqual(braces(['a/{01..20}/b', 'a/{1..5}/b']), [ - 'a/(0?[1-9]|1[0-9]|20)/b', - 'a/([1-5])/b', + 'a/(0[1-9]|1[0-9]|20)/b', + 'a/([1-5])/b' ]); }); @@ -26,7 +26,7 @@ describe('Examples from README.md', () => { '07', '08', '09', - '10', + '10' ]); }); }); @@ -41,10 +41,8 @@ describe('Examples from README.md', () => { it('zero-padding examples', () => { // supports zero-padded ranges - assert.deepEqual(braces('a/{01..03}/b'), ['a/(0?[1-3])/b']); - assert.deepEqual(braces('a/{001..300}/b'), [ - 'a/(0{0,2}[1-9]|0?[1-9][0-9]|[12][0-9]{2}|300)/b', - ]); + assert.deepEqual(braces('a/{01..03}/b'), ['a/(0[1-3])/b']); + assert.deepEqual(braces('a/{001..300}/b'), ['a/(00[1-9]|0[1-9][0-9]|[12][0-9]{2}|300)/b']); }); }); }); diff --git a/test/regression.js b/test/regression.js index 18bcb27..544044a 100644 --- a/test/regression.js +++ b/test/regression.js @@ -166,7 +166,7 @@ describe('bash tests', () => { it('should handle spaces', () => { equal('a{ ,c{d, },h}x', ['a x', 'acdx', 'ac x', 'ahx']); - equal('a{ ,c{d, },h} ', [ 'a ', 'acd ', 'ac ', 'ah ' ]); + equal('a{ ,c{d, },h} ', ['a ', 'acd ', 'ac ', 'ah ']); // see https://github.com/jonschlinkert/micromatch/issues/66 equal('/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.{html,ejs}', [ From 74b2db2938fad48a2ea54a9c8bf27a37a62c350d Mon Sep 17 00:00:00 2001 From: Jon Schlinkert Date: Tue, 21 May 2024 04:58:40 -0400 Subject: [PATCH 11/11] 3.0.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d668f88..c3c056e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "braces", "description": "Bash-like brace expansion, implemented in JavaScript. Safer than other brace expansion libs, with complete support for the Bash 4.3 braces specification, without sacrificing speed.", - "version": "3.0.2", + "version": "3.0.3", "homepage": "https://github.com/micromatch/braces", "author": "Jon Schlinkert (https://github.com/jonschlinkert)", "contributors": [