diff -Nru node-braces-2.0.2/appveyor.yml node-braces-3.0.2/appveyor.yml --- node-braces-2.0.2/appveyor.yml 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/appveyor.yml 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -# Test against this version of Node.js -environment: - matrix: - # node.js - - nodejs_version: "6.0" - - nodejs_version: "5.0" - - nodejs_version: "0.12" - - nodejs_version: "0.10" - -# Install scripts. (runs after repo cloning) -install: - # Get the latest stable version of Node.js or io.js - - ps: Install-Product node $env:nodejs_version - # install modules - - npm install - -# Post-install test scripts. -test_script: - # Output useful info for debugging. - - node --version - - npm --version - # run tests - - npm test - -# Don't actually build. -build: off diff -Nru node-braces-2.0.2/bench/index.js node-braces-3.0.2/bench/index.js --- node-braces-2.0.2/bench/index.js 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/bench/index.js 2019-04-16 19:50:10.000000000 +0000 @@ -0,0 +1,91 @@ +'use strict'; + +const { Suite } = require('benchmark'); +const colors = require('ansi-colors'); +const argv = require('minimist')(process.argv.slice(2)); +const minimatch = require('minimatch'); +const braces = require('..'); + +/** + * Setup + */ + +const cycle = (e, newline) => { + process.stdout.write(`\u001b[G ${e.target}${newline ? `\n` : ''}`); +}; + +const bench = (name, options) => { + const config = { name, ...options }; + const suite = new Suite(config); + const add = suite.add.bind(suite); + suite.on('error', console.error); + + if (argv.run && !new RegExp(argv.run).test(name)) { + suite.add = () => suite; + return suite; + } + + console.log(colors.green(`● ${config.name}`)); + + suite.add = (key, fn, opts) => { + if (typeof fn !== 'function') opts = fn; + + add(key, { + onCycle: e => cycle(e), + onComplete: e => cycle(e, true), + fn, + ...opts + }); + return suite; + }; + + return suite; +}; + +const skip = () => {}; +skip.add = () => skip; +skip.run = () => skip; +bench.skip = name => { + console.log(colors.cyan('● ' + colors.unstyle(name) + ' (skipped)')); + return skip; +}; + +bench('expand - range (expanded)') + .add(' braces', () => braces.expand('foo/{1..250}/bar')) + .add('minimatch', () => minimatch.braceExpand('foo/{1..250}/bar')) + .run(); + +bench('expand - range (optimized for regex)') + .add(' braces', () => braces.compile('foo/{1..250}/bar')) + .add('minimatch', () => minimatch.makeRe('foo/{1..250}/bar')) + .run(); + +bench('expand - nested ranges (expanded)') + .add(' braces', () => braces.expand('foo/{a,b,{1..250}}/bar')) + .add('minimatch', () => minimatch.braceExpand('foo/{a,b,{1..250}}/bar')) + .run(); + +bench('expand - nested ranges (optimized for regex)') + .add(' braces', () => braces.compile('foo/{a,b,{1..250}}/bar')) + .add('minimatch', () => minimatch.makeRe('foo/{a,b,{1..250}}/bar')) + .run(); + +bench('expand - set (expanded)') + .add(' braces', () => braces.expand('foo/{a,b,c}/bar')) + .add('minimatch', () => minimatch.braceExpand('foo/{a,b,c}/bar')) + .run(); + +bench('expand - set (optimized for regex)') + .add(' braces', () => braces.compile('foo/{a,b,c,d,e}/bar')) + .add('minimatch', () => minimatch.makeRe('foo/{a,b,c,d,e}/bar')) + .run(); + +bench('expand - nested sets (expanded)') + .add(' braces', () => braces.expand('foo/{a,b,{x,y,z}}/bar')) + .add('minimatch', () => minimatch.braceExpand('foo/{a,b,{x,y,z}}/bar')) + .run(); + +bench('expand - nested sets (optimized for regex)') + .add(' braces', () => braces.compile('foo/{a,b,c,d,e,{x,y,z}}/bar')) + .add('minimatch', () => minimatch.makeRe('foo/{a,b,c,d,e,{x,y,z}}/bar')) + .run(); diff -Nru node-braces-2.0.2/bench/package.json node-braces-3.0.2/bench/package.json --- node-braces-2.0.2/bench/package.json 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/bench/package.json 2019-04-16 19:50:10.000000000 +0000 @@ -0,0 +1,21 @@ +{ + "name": "picomatch-benchmarks", + "version": "0.0.0", + "private": true, + "main": "index.js", + "dependencies": { + "ansi-colors": "^3.0.3", + "benchmark": "^2.1.4", + "minimatch": "^3.0.4", + "minimist": "^1.2.0" + }, + "lintDeps": { + "devDependencies": { + "files": { + "patterns": [ + "*.js" + ] + } + } + } +} diff -Nru node-braces-2.0.2/benchmark/code/brace-expansion.js node-braces-3.0.2/benchmark/code/brace-expansion.js --- node-braces-2.0.2/benchmark/code/brace-expansion.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/benchmark/code/brace-expansion.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -var braceExpansion = require('brace-expansion'); -module.exports = function(args) { - return braceExpansion.apply(null, Array.isArray(args) ? args : [args]); -}; diff -Nru node-braces-2.0.2/benchmark/code/braces.js node-braces-3.0.2/benchmark/code/braces.js --- node-braces-2.0.2/benchmark/code/braces.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/benchmark/code/braces.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -var braces = require('../..'); -module.exports = function(args) { - return braces.apply(null, Array.isArray(args) ? args : [args]); -}; diff -Nru node-braces-2.0.2/benchmark/code/minimatch.js node-braces-3.0.2/benchmark/code/minimatch.js --- node-braces-2.0.2/benchmark/code/minimatch.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/benchmark/code/minimatch.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -var braceExpand = require('minimatch').braceExpand; -module.exports = function(args) { - return braceExpand.apply(null, Array.isArray(args) ? args : [args]); -}; diff -Nru node-braces-2.0.2/benchmark/fixtures/combination.js node-braces-3.0.2/benchmark/fixtures/combination.js --- node-braces-2.0.2/benchmark/fixtures/combination.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/benchmark/fixtures/combination.js 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -module.exports = ['a/{b,c,d}/{e,f,g}/h/{1..100}']; diff -Nru node-braces-2.0.2/benchmark/fixtures/combination-nested.js node-braces-3.0.2/benchmark/fixtures/combination-nested.js --- node-braces-2.0.2/benchmark/fixtures/combination-nested.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/benchmark/fixtures/combination-nested.js 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -module.exports = ['a{b,c{1..100}/{foo/bar},h}x/z']; diff -Nru node-braces-2.0.2/benchmark/fixtures/escaped.js node-braces-3.0.2/benchmark/fixtures/escaped.js --- node-braces-2.0.2/benchmark/fixtures/escaped.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/benchmark/fixtures/escaped.js 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -module.exports = ['a/\\{b,c}/{x\\,y}/d/e']; diff -Nru node-braces-2.0.2/benchmark/fixtures/list-basic.js node-braces-3.0.2/benchmark/fixtures/list-basic.js --- node-braces-2.0.2/benchmark/fixtures/list-basic.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/benchmark/fixtures/list-basic.js 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -module.exports = ['a/b/c/{x,y,z}/d/e']; diff -Nru node-braces-2.0.2/benchmark/fixtures/list-multiple.js node-braces-3.0.2/benchmark/fixtures/list-multiple.js --- node-braces-2.0.2/benchmark/fixtures/list-multiple.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/benchmark/fixtures/list-multiple.js 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -module.exports = ['a/b/c/{k,l,m}/d/{w,x,y,z}/d/e']; diff -Nru node-braces-2.0.2/benchmark/fixtures/match.multiple.js node-braces-3.0.2/benchmark/fixtures/match.multiple.js --- node-braces-2.0.2/benchmark/fixtures/match.multiple.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/benchmark/fixtures/match.multiple.js 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -module.exports = ['a/{b,c,d}/{e,f,g}/h/{1..100}']; diff -Nru node-braces-2.0.2/benchmark/fixtures/match.sequence.js node-braces-3.0.2/benchmark/fixtures/match.sequence.js --- node-braces-2.0.2/benchmark/fixtures/match.sequence.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/benchmark/fixtures/match.sequence.js 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -module.exports = ['a/b/c/{1..100}/d/e']; diff -Nru node-braces-2.0.2/benchmark/fixtures/no-braces.js node-braces-3.0.2/benchmark/fixtures/no-braces.js --- node-braces-2.0.2/benchmark/fixtures/no-braces.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/benchmark/fixtures/no-braces.js 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -module.exports = ['a/b/c/d/e/**/@(x|y|z)*.js']; diff -Nru node-braces-2.0.2/benchmark/fixtures/sequence-basic.js node-braces-3.0.2/benchmark/fixtures/sequence-basic.js --- node-braces-2.0.2/benchmark/fixtures/sequence-basic.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/benchmark/fixtures/sequence-basic.js 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -module.exports = ['a/b/c/{1..100}/d/e']; diff -Nru node-braces-2.0.2/benchmark/fixtures/sequence-multiple.js node-braces-3.0.2/benchmark/fixtures/sequence-multiple.js --- node-braces-2.0.2/benchmark/fixtures/sequence-multiple.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/benchmark/fixtures/sequence-multiple.js 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -module.exports = ['a/b/c/{1..50}/d/{1..100}/d/e']; diff -Nru node-braces-2.0.2/benchmark/index.js node-braces-3.0.2/benchmark/index.js --- node-braces-2.0.2/benchmark/index.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/benchmark/index.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -'use strict'; - -var path = require('path'); -var util = require('util'); -var cyan = require('ansi-cyan'); -var argv = require('yargs-parser')(process.argv.slice(2)); -var Suite = require('benchmarked'); - -function run(type, fixtures) { - var suite = new Suite({ - cwd: __dirname, - fixtures: `fixtures/${fixtures}.js`, - code: `code/${type}.js` - }); - - if (argv.dry) { - suite.dryRun(function(code, fixture) { - console.log(cyan('%s > %s'), code.key, fixture.key); - var args = require(fixture.path); - var res = code.run(args); - console.log(util.inspect(res, null, 10)); - console.log(); - }); - } else { - suite.run(); - } -} - -run(argv.code || '*', argv._[0] || '!(match)*'); -// run('braces', 'no-*'); diff -Nru node-braces-2.0.2/benchmark/last.md node-braces-3.0.2/benchmark/last.md --- node-braces-2.0.2/benchmark/last.md 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/benchmark/last.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,65 +0,0 @@ -Benchmarking: (8 of 8) - · combination-nested - · combination - · escaped - · list-basic - · list-multiple - · no-braces - · sequence-basic - · sequence-multiple - -# benchmark/fixtures/combination-nested.js (52 bytes) - brace-expansion x 4,756 ops/sec ±1.09% (86 runs sampled) - braces x 11,202,303 ops/sec ±1.06% (88 runs sampled) - minimatch x 4,816 ops/sec ±0.99% (87 runs sampled) - - fastest is braces - -# benchmark/fixtures/combination.js (51 bytes) - brace-expansion x 625 ops/sec ±0.87% (87 runs sampled) - braces x 11,031,884 ops/sec ±0.72% (90 runs sampled) - minimatch x 637 ops/sec ±0.84% (88 runs sampled) - - fastest is braces - -# benchmark/fixtures/escaped.js (44 bytes) - brace-expansion x 163,325 ops/sec ±1.05% (87 runs sampled) - braces x 10,655,071 ops/sec ±1.22% (88 runs sampled) - minimatch x 147,495 ops/sec ±0.96% (88 runs sampled) - - fastest is braces - -# benchmark/fixtures/list-basic.js (40 bytes) - brace-expansion x 99,726 ops/sec ±1.07% (83 runs sampled) - braces x 10,596,584 ops/sec ±0.98% (88 runs sampled) - minimatch x 100,069 ops/sec ±1.17% (86 runs sampled) - - fastest is braces - -# benchmark/fixtures/list-multiple.js (52 bytes) - brace-expansion x 34,348 ops/sec ±1.08% (88 runs sampled) - braces x 9,264,131 ops/sec ±1.12% (88 runs sampled) - minimatch x 34,893 ops/sec ±0.87% (87 runs sampled) - - fastest is braces - -# benchmark/fixtures/no-braces.js (48 bytes) - brace-expansion x 275,368 ops/sec ±1.18% (89 runs sampled) - braces x 9,134,677 ops/sec ±0.95% (88 runs sampled) - minimatch x 3,755,954 ops/sec ±1.13% (89 runs sampled) - - fastest is braces - -# benchmark/fixtures/sequence-basic.js (41 bytes) - brace-expansion x 5,492 ops/sec ±1.35% (87 runs sampled) - braces x 8,485,034 ops/sec ±1.28% (89 runs sampled) - minimatch x 5,341 ops/sec ±1.17% (87 runs sampled) - - fastest is braces - -# benchmark/fixtures/sequence-multiple.js (51 bytes) - brace-expansion x 116 ops/sec ±0.77% (77 runs sampled) - braces x 9,445,118 ops/sec ±1.32% (84 runs sampled) - minimatch x 109 ops/sec ±1.16% (76 runs sampled) - - fastest is braces diff -Nru node-braces-2.0.2/CHANGELOG.md node-braces-3.0.2/CHANGELOG.md --- node-braces-2.0.2/CHANGELOG.md 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/CHANGELOG.md 2019-04-16 19:50:10.000000000 +0000 @@ -0,0 +1,184 @@ +# Release history + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +
+ Guiding Principles + +- Changelogs are for humans, not machines. +- There should be an entry for every single version. +- The same types of changes should be grouped. +- Versions and sections should be linkable. +- The latest version comes first. +- The release date of each versions is displayed. +- Mention whether you follow Semantic Versioning. + +
+ +
+ Types of changes + +Changelog entries are classified using the following labels _(from [keep-a-changelog](http://keepachangelog.com/)_): + +- `Added` for new features. +- `Changed` for changes in existing functionality. +- `Deprecated` for soon-to-be removed features. +- `Removed` for now removed features. +- `Fixed` for any bug fixes. +- `Security` in case of vulnerabilities. + +
+ +## [3.0.0] - 2018-04-08 + +v3.0 is a complete refactor, resulting in a faster, smaller codebase, with fewer deps, and a more accurate parser and compiler. + +**Breaking Changes** + +- The undocumented `.makeRe` method was removed + +**Non-breaking changes** + +- Caching was removed + +## [2.3.2] - 2018-04-08 + +- start refactoring +- cover sets +- better range handling + +## [2.3.1] - 2018-02-17 + +- Remove unnecessary escape in Regex. (#14) + +## [2.3.0] - 2017-10-19 + +- minor code reorganization +- optimize regex +- expose `maxLength` option + +## [2.2.1] - 2017-05-30 + +- don't condense when braces contain extglobs + +## [2.2.0] - 2017-05-28 + +- ensure word boundaries are preserved +- fixes edge case where extglob characters precede a brace pattern + +## [2.1.1] - 2017-04-27 + +- use snapdragon-node +- handle edge case +- optimizations, lint + +## [2.0.4] - 2017-04-11 + +- pass opts to compiler +- minor optimization in create method +- re-write parser handlers to remove negation regex + +## [2.0.3] - 2016-12-10 + +- use split-string +- clear queue at the end +- adds sequences example +- add unit tests + +## [2.0.2] - 2016-10-21 + +- fix comma handling in nested extglobs + +## [2.0.1] - 2016-10-20 + +- add comments +- more tests, ensure quotes are stripped + +## [2.0.0] - 2016-10-19 + +- don't expand braces inside character classes +- add quantifier pattern + +## [1.8.5] - 2016-05-21 + +- Refactor (#10) + +## [1.8.4] - 2016-04-20 + +- fixes https://github.com/jonschlinkert/micromatch/issues/66 + +## [1.8.0] - 2015-03-18 + +- adds exponent examples, tests +- fixes the first example in https://github.com/jonschlinkert/micromatch/issues/38 + +## [1.6.0] - 2015-01-30 + +- optimizations, `bash` mode: +- improve path escaping + +## [1.5.0] - 2015-01-28 + +- Merge pull request #5 from eush77/lib-files + +## [1.4.0] - 2015-01-24 + +- add extglob tests +- externalize exponent function +- better whitespace handling + +## [1.3.0] - 2015-01-24 + +- make regex patterns explicity + +## [1.1.0] - 2015-01-11 + +- don't create a match group with `makeRe` + +## [1.0.0] - 2014-12-23 + +- Merge commit '97b05f5544f8348736a8efaecf5c32bbe3e2ad6e' +- support empty brace syntax +- better bash coverage +- better support for regex strings + +## [0.1.4] - 2014-11-14 + +- improve recognition of bad args, recognize mismatched argument types +- support escaping +- remove pathname-expansion +- support whitespace in patterns + +## [0.1.0] + +- first commit + +[2.3.2]: https://github.com/micromatch/braces/compare/2.3.1...2.3.2 +[2.3.1]: https://github.com/micromatch/braces/compare/2.3.0...2.3.1 +[2.3.0]: https://github.com/micromatch/braces/compare/2.2.1...2.3.0 +[2.2.1]: https://github.com/micromatch/braces/compare/2.2.0...2.2.1 +[2.2.0]: https://github.com/micromatch/braces/compare/2.1.1...2.2.0 +[2.1.1]: https://github.com/micromatch/braces/compare/2.1.0...2.1.1 +[2.1.0]: https://github.com/micromatch/braces/compare/2.0.4...2.1.0 +[2.0.4]: https://github.com/micromatch/braces/compare/2.0.3...2.0.4 +[2.0.3]: https://github.com/micromatch/braces/compare/2.0.2...2.0.3 +[2.0.2]: https://github.com/micromatch/braces/compare/2.0.1...2.0.2 +[2.0.1]: https://github.com/micromatch/braces/compare/2.0.0...2.0.1 +[2.0.0]: https://github.com/micromatch/braces/compare/1.8.5...2.0.0 +[1.8.5]: https://github.com/micromatch/braces/compare/1.8.4...1.8.5 +[1.8.4]: https://github.com/micromatch/braces/compare/1.8.0...1.8.4 +[1.8.0]: https://github.com/micromatch/braces/compare/1.6.0...1.8.0 +[1.6.0]: https://github.com/micromatch/braces/compare/1.5.0...1.6.0 +[1.5.0]: https://github.com/micromatch/braces/compare/1.4.0...1.5.0 +[1.4.0]: https://github.com/micromatch/braces/compare/1.3.0...1.4.0 +[1.3.0]: https://github.com/micromatch/braces/compare/1.2.0...1.3.0 +[1.2.0]: https://github.com/micromatch/braces/compare/1.1.0...1.2.0 +[1.1.0]: https://github.com/micromatch/braces/compare/1.0.0...1.1.0 +[1.0.0]: https://github.com/micromatch/braces/compare/0.1.4...1.0.0 +[0.1.4]: https://github.com/micromatch/braces/compare/0.1.0...0.1.4 + +[Unreleased]: https://github.com/micromatch/braces/compare/0.1.0...HEAD +[keep-a-changelog]: https://github.com/olivierlacan/keep-a-changelog \ No newline at end of file diff -Nru node-braces-2.0.2/debian/changelog node-braces-3.0.2/debian/changelog --- node-braces-2.0.2/debian/changelog 2017-12-29 14:33:23.000000000 +0000 +++ node-braces-3.0.2/debian/changelog 2019-09-02 04:54:27.000000000 +0000 @@ -1,3 +1,37 @@ +node-braces (3.0.2-2) unstable; urgency=medium + + * Team upload + * Back to unstable after successful tests + * Bump debhelper compatibility level to 12 + * Declare compliance with policy 4.4.0 + * Switch install to pkg-js-tools + + -- Xavier Guimard Mon, 02 Sep 2019 06:54:27 +0200 + +node-braces (3.0.2-1) experimental; urgency=medium + + * Team upload. + + [ Paolo Greppi ] + * Update Vcs fields for migration to https://salsa.debian.org/ + * Standards-Version 4.3.0 + * debhelper compat 11 and remove build-dep on dh-buildinfo + * Install examples + * New upstream version 2.3.1 (Closes: #927716, CVE-2018-1109) + + [ Xavier Guimard ] + * Add upstream/metadata + * Remove components + * New upstream version 3.0.2 + * Add base-path module for tests only + * Update debian/copyright + * Fix install + * Remove unneeded dependencies + * Update lintian-overrides + * Switch tests to pkg-js-tools + + -- Xavier Guimard Wed, 05 Jun 2019 22:29:48 +0200 + node-braces (2.0.2-2) unstable; urgency=medium * Team upload diff -Nru node-braces-2.0.2/debian/compat node-braces-3.0.2/debian/compat --- node-braces-2.0.2/debian/compat 2017-12-29 14:19:13.000000000 +0000 +++ node-braces-3.0.2/debian/compat 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -9 diff -Nru node-braces-2.0.2/debian/control node-braces-3.0.2/debian/control --- node-braces-2.0.2/debian/control 2017-12-29 14:31:37.000000000 +0000 +++ node-braces-3.0.2/debian/control 2019-09-02 04:52:40.000000000 +0000 @@ -3,45 +3,25 @@ Priority: optional Maintainer: Debian Javascript Maintainers Uploaders: Sruthi Chandran +Testsuite: autopkgtest-pkg-nodejs Build-Depends: - debhelper (>= 9) - , dh-buildinfo + debhelper-compat (= 12) , nodejs , mocha - , node-snapdragon (>= 0.8.1) - , node-regex-not (>= 1.0.0) - , node-arr-flatten (>= 1.0.1) - , node-define-property (>= 0.2.5) - , node-isobject (>= 2.1.0) - , node-repeat-element (>= 1.1.2) - , node-fill-range (>= 3.0.3) - , node-to-regex (>= 3.0.1) - , node-extend-shallow (>= 2.0.1) - , node-debug (>= 2.1.0) - , node-array-unique (>= 0.2.1) -Standards-Version: 4.1.2 -Homepage: https://github.com/jonschlinkert/braces -Vcs-Git: https://anonscm.debian.org/git/pkg-javascript/node-braces.git -Vcs-Browser: https://anonscm.debian.org/cgit/pkg-javascript/node-braces.git + , node-fill-range (>= 7.0.1) + , pkg-js-tools (>= 0.9.8~) +Standards-Version: 4.4.0 +Homepage: https://github.com/micromatch/braces +Vcs-Git: https://salsa.debian.org/js-team/node-braces.git +Vcs-Browser: https://salsa.debian.org/js-team/node-braces Package: node-braces Architecture: all Depends: ${misc:Depends} - , nodejs - , node-snapdragon (>= 0.8.1) - , node-regex-not (>= 1.0.0) - , node-arr-flatten (>= 1.0.1) - , node-define-property (>= 0.2.5) - , node-isobject (>= 2.1.0) - , node-repeat-element (>= 1.1.2) - , node-fill-range (>= 3.0.3) - , node-to-regex (>= 3.0.1) - , node-extend-shallow (>= 2.0.1) - , node-debug (>= 2.1.0) - , node-array-unique (>= 0.2.1) + , node-fill-range (>= 7.0.1) Description: Fast, comprehensive, bash-like brace expansion implemented in JS - Complete support for the Bash 4.3 braces specification, without sacrificing + Complete support for the Bash 4.3 braces specification, without sacrificing speed. . Node.js is an event-based server-side JavaScript engine. diff -Nru node-braces-2.0.2/debian/copyright node-braces-3.0.2/debian/copyright --- node-braces-2.0.2/debian/copyright 2017-12-29 14:19:13.000000000 +0000 +++ node-braces-3.0.2/debian/copyright 2019-09-02 04:34:48.000000000 +0000 @@ -1,14 +1,20 @@ -Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: braces Upstream-Contact: https://github.com/jonschlinkert/braces/issues Source: https://github.com/jonschlinkert/braces Files: * -Copyright: 2016 Jon Schlinkert (https://github.com/jonschlinkert) +Copyright: 2014-2018, Jon Schlinkert (https://github.com/jonschlinkert) License: Expat Files: debian/* -Copyright: 2016 Sruthi Chandran +Copyright: 2016, Sruthi Chandran + 2018, Paolo Greppi + 2019, Xavier Guimard +License: Expat + +Files: debian/tests/modules/bash-path/* +Copyright: 2017, Jon Schlinkert (https://github.com/jonschlinkert) License: Expat License: Expat @@ -31,4 +37,3 @@ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff -Nru node-braces-2.0.2/debian/gbp.conf node-braces-3.0.2/debian/gbp.conf --- node-braces-2.0.2/debian/gbp.conf 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/debian/gbp.conf 2019-09-02 04:34:48.000000000 +0000 @@ -0,0 +1,2 @@ +[import-orig] +filter = .gitignore diff -Nru node-braces-2.0.2/debian/gitlab-ci.yml node-braces-3.0.2/debian/gitlab-ci.yml --- node-braces-2.0.2/debian/gitlab-ci.yml 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/debian/gitlab-ci.yml 2019-09-02 04:34:48.000000000 +0000 @@ -0,0 +1,16 @@ +include: https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml + +build: + extends: .build-unstable + +reprotest: + extends: .test-reprotest + +lintian: + extends: .test-lintian + +autopkgtest: + extends: .test-autopkgtest + +piuparts: + extends: .test-piuparts diff -Nru node-braces-2.0.2/debian/install node-braces-3.0.2/debian/install --- node-braces-2.0.2/debian/install 2017-12-29 14:19:13.000000000 +0000 +++ node-braces-3.0.2/debian/install 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -package.json usr/lib/nodejs/braces/ -index.js usr/lib/nodejs/braces/ -lib usr/lib/nodejs/braces/ diff -Nru node-braces-2.0.2/debian/node-braces.examples node-braces-3.0.2/debian/node-braces.examples --- node-braces-2.0.2/debian/node-braces.examples 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/debian/node-braces.examples 2019-09-02 04:34:48.000000000 +0000 @@ -0,0 +1 @@ +examples/* diff -Nru node-braces-2.0.2/debian/patches/series node-braces-3.0.2/debian/patches/series --- node-braces-2.0.2/debian/patches/series 2017-12-29 14:21:17.000000000 +0000 +++ node-braces-3.0.2/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -upstream-test-fixes.patch diff -Nru node-braces-2.0.2/debian/patches/upstream-test-fixes.patch node-braces-3.0.2/debian/patches/upstream-test-fixes.patch --- node-braces-2.0.2/debian/patches/upstream-test-fixes.patch 2017-12-29 14:30:28.000000000 +0000 +++ node-braces-3.0.2/debian/patches/upstream-test-fixes.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,934 +0,0 @@ -Description: backport test fixes from upstream version 2.3.0 - updating to that version requires modules that are not available at that moment. -Last-Update: 2017-12-29 -Forwarded: not-needed -Author: Jérémy Lal - ---- a/test/bash.expanded.js -+++ b/test/bash.expanded.js -@@ -4,9 +4,9 @@ - var assert = require('assert'); - var braces = require('..'); - --function match(pattern, expected, options) { -- var actual = braces.expand(pattern, options).sort(); -- assert.deepEqual(actual, expected.sort(), pattern); -+function equal(pattern, expected, options) { -+ var actual = braces.expand(pattern, options); -+ assert.deepEqual(actual.sort(), expected.sort(), pattern); - } - - /** -@@ -14,6 +14,7 @@ - */ - - describe('bash.expanded', function() { -+ - var fixtures = [ - [ 'a{b,c{1..50}/{foo,bar,baz}/,g}h/i', {}, [ 'abh/i', 'ac1/bar/h/i', 'ac1/baz/h/i', 'ac1/foo/h/i', 'ac10/bar/h/i', 'ac10/baz/h/i', 'ac10/foo/h/i', 'ac11/bar/h/i', 'ac11/baz/h/i', 'ac11/foo/h/i', 'ac12/bar/h/i', 'ac12/baz/h/i', 'ac12/foo/h/i', 'ac13/bar/h/i', 'ac13/baz/h/i', 'ac13/foo/h/i', 'ac14/bar/h/i', 'ac14/baz/h/i', 'ac14/foo/h/i', 'ac15/bar/h/i', 'ac15/baz/h/i', 'ac15/foo/h/i', 'ac16/bar/h/i', 'ac16/baz/h/i', 'ac16/foo/h/i', 'ac17/bar/h/i', 'ac17/baz/h/i', 'ac17/foo/h/i', 'ac18/bar/h/i', 'ac18/baz/h/i', 'ac18/foo/h/i', 'ac19/bar/h/i', 'ac19/baz/h/i', 'ac19/foo/h/i', 'ac2/bar/h/i', 'ac2/baz/h/i', 'ac2/foo/h/i', 'ac20/bar/h/i', 'ac20/baz/h/i', 'ac20/foo/h/i', 'ac21/bar/h/i', 'ac21/baz/h/i', 'ac21/foo/h/i', 'ac22/bar/h/i', 'ac22/baz/h/i', 'ac22/foo/h/i', 'ac23/bar/h/i', 'ac23/baz/h/i', 'ac23/foo/h/i', 'ac24/bar/h/i', 'ac24/baz/h/i', 'ac24/foo/h/i', 'ac25/bar/h/i', 'ac25/baz/h/i', 'ac25/foo/h/i', 'ac26/bar/h/i', 'ac26/baz/h/i', 'ac26/foo/h/i', 'ac27/bar/h/i', 'ac27/baz/h/i', 'ac27/foo/h/i', 'ac28/bar/h/i', 'ac28/baz/h/i', 'ac28/foo/h/i', 'ac29/bar/h/i', 'ac29/baz/h/i', 'ac29/foo/h/i', 'ac3/bar/h/i', 'ac3/baz/h/i', 'ac3/foo/h/i', 'ac30/bar/h/i', 'ac30/baz/h/i', 'ac30/foo/h/i', 'ac31/bar/h/i', 'ac31/baz/h/i', 'ac31/foo/h/i', 'ac32/bar/h/i', 'ac32/baz/h/i', 'ac32/foo/h/i', 'ac33/bar/h/i', 'ac33/baz/h/i', 'ac33/foo/h/i', 'ac34/bar/h/i', 'ac34/baz/h/i', 'ac34/foo/h/i', 'ac35/bar/h/i', 'ac35/baz/h/i', 'ac35/foo/h/i', 'ac36/bar/h/i', 'ac36/baz/h/i', 'ac36/foo/h/i', 'ac37/bar/h/i', 'ac37/baz/h/i', 'ac37/foo/h/i', 'ac38/bar/h/i', 'ac38/baz/h/i', 'ac38/foo/h/i', 'ac39/bar/h/i', 'ac39/baz/h/i', 'ac39/foo/h/i', 'ac4/bar/h/i', 'ac4/baz/h/i', 'ac4/foo/h/i', 'ac40/bar/h/i', 'ac40/baz/h/i', 'ac40/foo/h/i', 'ac41/bar/h/i', 'ac41/baz/h/i', 'ac41/foo/h/i', 'ac42/bar/h/i', 'ac42/baz/h/i', 'ac42/foo/h/i', 'ac43/bar/h/i', 'ac43/baz/h/i', 'ac43/foo/h/i', 'ac44/bar/h/i', 'ac44/baz/h/i', 'ac44/foo/h/i', 'ac45/bar/h/i', 'ac45/baz/h/i', 'ac45/foo/h/i', 'ac46/bar/h/i', 'ac46/baz/h/i', 'ac46/foo/h/i', 'ac47/bar/h/i', 'ac47/baz/h/i', 'ac47/foo/h/i', 'ac48/bar/h/i', 'ac48/baz/h/i', 'ac48/foo/h/i', 'ac49/bar/h/i', 'ac49/baz/h/i', 'ac49/foo/h/i', 'ac5/bar/h/i', 'ac5/baz/h/i', 'ac5/foo/h/i', 'ac50/bar/h/i', 'ac50/baz/h/i', 'ac50/foo/h/i', 'ac6/bar/h/i', 'ac6/baz/h/i', 'ac6/foo/h/i', 'ac7/bar/h/i', 'ac7/baz/h/i', 'ac7/foo/h/i', 'ac8/bar/h/i', 'ac8/baz/h/i', 'ac8/foo/h/i', 'ac9/bar/h/i', 'ac9/baz/h/i', 'ac9/foo/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' ] ], -@@ -217,7 +218,7 @@ - [ 'a{ ,c{d, },h}x', {}, [ 'a x', 'ac x', 'acdx', 'ahx' ] ], - [ 'a{ ,c{d, },h} ', {}, [ 'a ', 'ac ', 'acd ', 'ah ' ] ], - -- 'see https://github.com/jonschlinkert/micromatch/issues/66', -+ '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/**/[^_]*.ejs', '/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.html' ] ], - -@@ -248,6 +249,7 @@ - - [ '{"klklkl"}{1,2,3}', {}, [ '{klklkl}1', '{klklkl}2', '{klklkl}3' ] ], - [ '{"x,x"}', {}, [ '{x,x}' ] ], -+ [ '{\'x,x\'}', {}, [ '{x,x}' ] ], - - 'should escaped outer braces in nested non-sets', - -@@ -321,8 +323,7 @@ - - 'HEADS UP! If you\'re using the `--mm` flag minimatch freezes on these', 'should expand large numbers', - -- [ '{2147483645..2147483649}', { minimatch: false, optimize: true }, [ '2147483645', '2147483646', '2147483647', '2147483648', '2147483649' ] ], -- [ '{214748364..2147483649}', { minimatch: false, optimize: true }, [ '(21474836[4-9]|2147483[7-9][0-9]|214748[4-9][0-9]{2}|214749[0-9]{3}|2147[5-9][0-9]{4}|214[8-9][0-9]{5}|21[5-9][0-9]{6}|2[2-9][0-9]{7}|[3-9][0-9]{8}|1[0-9]{9}|20[0-9]{8}|21[0-3][0-9]{7}|214[0-6][0-9]{6}|2147[0-3][0-9]{5}|21474[0-7][0-9]{4}|214748[0-2][0-9]{3}|2147483[0-5][0-9]{2}|21474836[0-4][0-9])' ] ], -+ [ '{2147483645..2147483649}', { minimatch: false }, [ '2147483645', '2147483646', '2147483647', '2147483648', '2147483649' ] ], - - 'should expand ranges using steps', - -@@ -405,7 +406,7 @@ - } - - it('should compile: ' + pattern, function() { -- match(pattern, expected, options); -+ equal(pattern, expected, options); - }); - }); - }); ---- a/test/bash.optimized.js -+++ b/test/bash.optimized.js -@@ -4,7 +4,7 @@ - var assert = require('assert'); - var braces = require('..'); - --function match(pattern, expected, options) { -+function equal(pattern, expected, options) { - var actual = braces.optimize(pattern, options).sort(); - assert.deepEqual(actual, expected.sort(), pattern); - } -@@ -13,7 +13,7 @@ - * Bash 4.3 unit tests with `braces.optimize()` - */ - --describe('bash.expanded', function() { -+describe('bash.optimized', function() { - var fixtures = [ - ['a{b,c{1..100}/{foo,bar}/,h}x/z', {}, ['a(b|c([1-9]|[1-9][0-9]|100)/(foo|bar)/|h)x/z']], - ['0{1..9} {10..20}', {}, ['0([1-9]) (1[0-9]|20)']], -@@ -78,7 +78,7 @@ - ['{1..ff}', {}, ['{1..ff}']], - ['{1.20..2}', {}, ['{1.20..2}']], - ['{10..1}', {}, ['([1-9]|10)']], -- ['{214748364..2147483649}', {}, ['(21474836[4-9]|2147483[7-9][0-9]|214748[4-9][0-9]{2}|214749[0-9]{3}|2147[5-9][0-9]{4}|214[8-9][0-9]{5}|21[5-9][0-9]{6}|2[2-9][0-9]{7}|[3-9][0-9]{8}|1[0-9]{9}|20[0-9]{8}|21[0-3][0-9]{7}|214[0-6][0-9]{6}|2147[0-3][0-9]{5}|21474[0-7][0-9]{4}|214748[0-2][0-9]{3}|2147483[0-5][0-9]{2}|21474836[0-4][0-9])']], -+ ['{214748364..2147483649}', {}, ['(21474836[4-9]|2147483[7-9][0-9]|214748[4-9][0-9]{2}|214749[0-9]{3}|2147[5-9][0-9]{4}|214[89][0-9]{5}|21[5-9][0-9]{6}|2[2-9][0-9]{7}|[3-9][0-9]{8}|1[0-9]{9}|20[0-9]{8}|21[0-3][0-9]{7}|214[0-6][0-9]{6}|2147[0-3][0-9]{5}|21474[0-7][0-9]{4}|214748[0-2][0-9]{3}|2147483[0-5][0-9]{2}|21474836[0-4][0-9])']], - ['{2147483645..2147483649}', {}, ['(214748364[5-9])']], - ['{3..3}', {}, ['3']], - ['{5..8}', {}, ['([5-8])']], -@@ -165,6 +165,7 @@ - // 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{a,b}}c', {}, ['a${b{a,b}}c']], - ['a/{${b},c}/d', {}, ['a/(${b}|c)/d']], - ['a${b,d}/{foo,bar}c', {}, ['a${b,d}/(foo|bar)c']], - -@@ -231,7 +232,7 @@ - ['a{ ,c{d, },h}x', {}, ['a( |c(d| )|h)x']], - ['a{ ,c{d, },h} ', {}, ['a( |c(d| )|h) ']], - -- // see https://github.com/jonschlinkert/micromatch/issues/66 -+ // 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|ejs)']], - - /** -@@ -331,7 +332,7 @@ - // HEADS UP! If you're using the `--mm` flag minimatch freezes on these - // should expand large numbers - ['{2147483645..2147483649}', {}, ['(214748364[5-9])']], -- ['{214748364..2147483649}', {}, ['(21474836[4-9]|2147483[7-9][0-9]|214748[4-9][0-9]{2}|214749[0-9]{3}|2147[5-9][0-9]{4}|214[8-9][0-9]{5}|21[5-9][0-9]{6}|2[2-9][0-9]{7}|[3-9][0-9]{8}|1[0-9]{9}|20[0-9]{8}|21[0-3][0-9]{7}|214[0-6][0-9]{6}|2147[0-3][0-9]{5}|21474[0-7][0-9]{4}|214748[0-2][0-9]{3}|2147483[0-5][0-9]{2}|21474836[0-4][0-9])']], -+ ['{214748364..2147483649}', {}, ['(21474836[4-9]|2147483[7-9][0-9]|214748[4-9][0-9]{2}|214749[0-9]{3}|2147[5-9][0-9]{4}|214[89][0-9]{5}|21[5-9][0-9]{6}|2[2-9][0-9]{7}|[3-9][0-9]{8}|1[0-9]{9}|20[0-9]{8}|21[0-3][0-9]{7}|214[0-6][0-9]{6}|2147[0-3][0-9]{5}|21474[0-7][0-9]{4}|214748[0-2][0-9]{3}|2147483[0-5][0-9]{2}|21474836[0-4][0-9])']], - - // should expand ranges using steps - ['{1..10..1}', {bash: false}, ['([1-9]|10)']], -@@ -403,7 +404,7 @@ - } - - it('should compile: ' + pattern, function() { -- match(pattern, expected, options); -+ equal(pattern, expected, options); - }); - }); - }); ---- a/test/expanded.ranges.js -+++ b/test/expanded.ranges.js -@@ -3,7 +3,7 @@ - var assert = require('assert'); - var braces = require('..'); - --function match(pattern, expected) { -+function equal(pattern, expected) { - var actual = braces.expand(pattern).sort(); - assert.deepEqual(actual, expected.sort()); - } -@@ -11,177 +11,169 @@ - describe('expanded ranges', function() { - describe('escaping / invalid ranges', function() { - it('should not try to expand ranges with decimals', function() { -- match('{1.1..2.1}', ['{1.1..2.1}']); -- match('{1.1..~2.1}', ['{1.1..~2.1}']); -+ equal('{1.1..2.1}', ['{1.1..2.1}']); -+ equal('{1.1..~2.1}', ['{1.1..~2.1}']); - }); - - it('should escape invalid ranges:', function() { -- match('{1..0f}', ['{1..0f}']); -- match('{1..10..ff}', ['{1..10..ff}']); -- match('{1..10.f}', ['{1..10.f}']); -- match('{1..10f}', ['{1..10f}']); -- match('{1..20..2f}', ['{1..20..2f}']); -- match('{1..20..f2}', ['{1..20..f2}']); -- match('{1..2f..2}', ['{1..2f..2}']); -- match('{1..ff..2}', ['{1..ff..2}']); -- match('{1..ff}', ['{1..ff}']); -- match('{1.20..2}', ['{1.20..2}']); -+ equal('{1..0f}', ['{1..0f}']); -+ equal('{1..10..ff}', ['{1..10..ff}']); -+ equal('{1..10.f}', ['{1..10.f}']); -+ equal('{1..10f}', ['{1..10f}']); -+ equal('{1..20..2f}', ['{1..20..2f}']); -+ equal('{1..20..f2}', ['{1..20..f2}']); -+ equal('{1..2f..2}', ['{1..2f..2}']); -+ equal('{1..ff..2}', ['{1..ff..2}']); -+ equal('{1..ff}', ['{1..ff}']); -+ equal('{1.20..2}', ['{1.20..2}']); - }); - - it('weirdly-formed brace expansions -- fixed in post-bash-3.1', function() { -- match('a-{b{d,e}}-c', ['a-{bd}-c', 'a-{be}-c']); -- match('a-{bdef-{g,i}-c', ['a-{bdef-g-c', 'a-{bdef-i-c']); -+ equal('a-{b{d,e}}-c', ['a-{bd}-c', 'a-{be}-c']); -+ equal('a-{bdef-{g,i}-c', ['a-{bdef-g-c', 'a-{bdef-i-c']); - }); - - it('should not expand quoted strings.', function() { -- match('{"klklkl"}{1,2,3}', ['{klklkl}1', '{klklkl}2', '{klklkl}3']); -- match('{"x,x"}', ['{x,x}']); -+ equal('{"klklkl"}{1,2,3}', ['{klklkl}1', '{klklkl}2', '{klklkl}3']); -+ equal('{"x,x"}', ['{x,x}']); - }); - - it('should escaped outer braces in nested non-sets', function() { -- match('{a-{b,c,d}}', ['{a-b}', '{a-c}', '{a-d}']); -- match('{a,{a-{b,c,d}}}', ['a', '{a-b}', '{a-c}', '{a-d}']); -+ equal('{a-{b,c,d}}', ['{a-b}', '{a-c}', '{a-d}']); -+ equal('{a,{a-{b,c,d}}}', ['a', '{a-b}', '{a-c}', '{a-d}']); - }); - - it('should escape imbalanced braces', function() { -- match('a-{bdef-{g,i}-c', ['a-{bdef-g-c', 'a-{bdef-i-c']); -- match('abc{', ['abc{']); -- match('{abc{', ['{abc{']); -- match('{abc', ['{abc']); -- match('}abc', ['}abc']); -- match('ab{c', ['ab{c']); -- match('ab{c', ['ab{c']); -- match('{{a,b}', ['{a', '{b']); -- match('{a,b}}', ['a}', 'b}']); -- match('abcd{efgh', ['abcd{efgh']); -- match('a{b{c{d,e}f}g}h', ['a{b{cdf}g}h', 'a{b{cef}g}h']); -- match('f{x,y{{g,z}}h}', ['fx', 'fy{g}h', 'fy{z}h']); -- match('z{a,b},c}d', ['za,c}d', 'zb,c}d']); -- match('a{b{c{d,e}f{x,y{{g}h', ['a{b{cdf{x,y{{g}h', 'a{b{cef{x,y{{g}h']); -- match('f{x,y{{g}h', ['f{x,y{{g}h']); -- match('f{x,y{{g}}h', ['f{x,y{{g}}h']); -- match('a{b{c{d,e}f{x,y{}g}h', ['a{b{cdfxh', 'a{b{cdfy{}gh', 'a{b{cefxh', 'a{b{cefy{}gh']); -- match('f{x,y{}g}h', ['fxh', 'fy{}gh']); -- match('z{a,b{,c}d', ['z{a,bd', 'z{a,bcd']); -+ equal('a-{bdef-{g,i}-c', ['a-{bdef-g-c', 'a-{bdef-i-c']); -+ equal('abc{', ['abc{']); -+ equal('{abc{', ['{abc{']); -+ equal('{abc', ['{abc']); -+ equal('}abc', ['}abc']); -+ equal('ab{c', ['ab{c']); -+ equal('ab{c', ['ab{c']); -+ equal('{{a,b}', ['{a', '{b']); -+ equal('{a,b}}', ['a}', 'b}']); -+ equal('abcd{efgh', ['abcd{efgh']); -+ equal('a{b{c{d,e}f}g}h', ['a{b{cdf}g}h', 'a{b{cef}g}h']); -+ equal('f{x,y{{g,z}}h}', ['fx', 'fy{g}h', 'fy{z}h']); -+ equal('z{a,b},c}d', ['za,c}d', 'zb,c}d']); -+ equal('a{b{c{d,e}f{x,y{{g}h', ['a{b{cdf{x,y{{g}h', 'a{b{cef{x,y{{g}h']); -+ equal('f{x,y{{g}h', ['f{x,y{{g}h']); -+ equal('f{x,y{{g}}h', ['f{x,y{{g}}h']); -+ equal('a{b{c{d,e}f{x,y{}g}h', ['a{b{cdfxh', 'a{b{cdfy{}gh', 'a{b{cefxh', 'a{b{cefy{}gh']); -+ equal('f{x,y{}g}h', ['fxh', 'fy{}gh']); -+ equal('z{a,b{,c}d', ['z{a,bd', 'z{a,bcd']); - }); - }); - - describe('positive numeric ranges', function() { - it('should expand numeric ranges', function() { -- match('a{0..3}d', ['a0d', 'a1d', 'a2d', 'a3d']); -- match('x{10..1}y', ['x10y', 'x9y', 'x8y', 'x7y', 'x6y', 'x5y', 'x4y', 'x3y', 'x2y', 'x1y']); -- match('x{3..3}y', ['x3y']); -- match('{1..10}', ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); -- match('{1..3}', ['1', '2', '3']); -- match('{1..9}', ['1', '2', '3', '4', '5', '6', '7', '8', '9']); -- match('{10..1}', ['10', '9', '8', '7', '6', '5', '4', '3', '2', '1']); -- match('{10..1}y', ['10y', '9y', '8y', '7y', '6y', '5y', '4y', '3y', '2y', '1y']); -- match('{3..3}', ['3']); -- match('{5..8}', ['5', '6', '7', '8']); -+ equal('a{0..3}d', ['a0d', 'a1d', 'a2d', 'a3d']); -+ equal('x{10..1}y', ['x10y', 'x9y', 'x8y', 'x7y', 'x6y', 'x5y', 'x4y', 'x3y', 'x2y', 'x1y']); -+ equal('x{3..3}y', ['x3y']); -+ equal('{1..10}', ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); -+ equal('{1..3}', ['1', '2', '3']); -+ equal('{1..9}', ['1', '2', '3', '4', '5', '6', '7', '8', '9']); -+ equal('{10..1}', ['10', '9', '8', '7', '6', '5', '4', '3', '2', '1']); -+ equal('{10..1}y', ['10y', '9y', '8y', '7y', '6y', '5y', '4y', '3y', '2y', '1y']); -+ equal('{3..3}', ['3']); -+ equal('{5..8}', ['5', '6', '7', '8']); - }); - }); - - describe('negative ranges', function() { - it('should expand ranges with negative numbers', function() { -- match('{-10..-1}', ['-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1']); -- match('{-20..0}', ['-20', '-19', '-18', '-17', '-16', '-15', '-14', '-13', '-12', '-11', '-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1', '0']); -- match('{0..-5}', ['0', '-1', '-2', '-3', '-4', '-5']); -- match('{9..-4}', ['9', '8', '7', '6', '5', '4', '3', '2', '1', '0', '-1', '-2', '-3', '-4']); -+ equal('{-10..-1}', ['-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1']); -+ equal('{-20..0}', ['-20', '-19', '-18', '-17', '-16', '-15', '-14', '-13', '-12', '-11', '-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1', '0']); -+ equal('{0..-5}', ['0', '-1', '-2', '-3', '-4', '-5']); -+ equal('{9..-4}', ['9', '8', '7', '6', '5', '4', '3', '2', '1', '0', '-1', '-2', '-3', '-4']); - }); - }); - - describe('alphabetical ranges', function() { - it('should expand alphabetical ranges', function() { -- match('{a..F}', ['F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a']); -- match('0{a..d}0', ['0a0', '0b0', '0c0', '0d0']); -- match('a/{b..d}/e', ['a/b/e', 'a/c/e', 'a/d/e']); -- match('{1..f}', ['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']); -- match('{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']); -- match('{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']); -- match('{a..e}', ['a', 'b', 'c', 'd', 'e']); -- match('{A..E}', ['A', 'B', 'C', 'D', 'E']); -- match('{a..f}', ['a', 'b', 'c', 'd', 'e', 'f']); -- match('{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']); -- match('{E..A}', ['E', 'D', 'C', 'B', 'A']); -- match('{f..1}', ['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']); -- match('{f..a}', ['f', 'e', 'd', 'c', 'b', 'a']); -- match('{f..f}', ['f']); -+ equal('{a..F}', ['F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a']); -+ equal('0{a..d}0', ['0a0', '0b0', '0c0', '0d0']); -+ equal('a/{b..d}/e', ['a/b/e', 'a/c/e', 'a/d/e']); -+ equal('{1..f}', ['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']); -+ equal('{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']); -+ equal('{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']); -+ equal('{a..e}', ['a', 'b', 'c', 'd', 'e']); -+ equal('{A..E}', ['A', 'B', 'C', 'D', 'E']); -+ equal('{a..f}', ['a', 'b', 'c', 'd', 'e', 'f']); -+ equal('{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']); -+ equal('{E..A}', ['E', 'D', 'C', 'B', 'A']); -+ equal('{f..1}', ['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']); -+ equal('{f..a}', ['f', 'e', 'd', 'c', 'b', 'a']); -+ equal('{f..f}', ['f']); - }); - - it('should expand multiple ranges:', function() { -- match('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']); -+ equal('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']); - }); - }); - - describe('combo', function() { - it('should expand numerical ranges - positive and negative', function() { -- match('a{01..05}b', ['a01b', 'a02b', 'a03b', 'a04b', 'a05b' ]); -- match('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' ]); -- match('{-10..10}', ['-1', '-10', '-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '0', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9' ]); -- }); -- }); -- -- // HEADS UP! If you're using the `--mm` flag minimatch freezes on these -- describe('large numbers', function() { -- it('should expand large numbers', function() { -- match('{2147483645..2147483649}', ['2147483645', '2147483646', '2147483647', '2147483648', '2147483649']); -- match('{214748364..2147483649}', ['(21474836[4-9]|2147483[7-9][0-9]|214748[4-9][0-9]{2}|214749[0-9]{3}|2147[5-9][0-9]{4}|214[8-9][0-9]{5}|21[5-9][0-9]{6}|2[2-9][0-9]{7}|[3-9][0-9]{8}|1[0-9]{9}|20[0-9]{8}|21[0-3][0-9]{7}|214[0-6][0-9]{6}|2147[0-3][0-9]{5}|21474[0-7][0-9]{4}|214748[0-2][0-9]{3}|2147483[0-5][0-9]{2}|21474836[0-4][0-9])']); -+ 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}', ['-1', '-10', '-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '0', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9' ]); - }); - }); - - describe('steps > positive ranges', function() { - it('should expand ranges using steps:', function() { -- match('{1..10..1}', ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); -- match('{1..10..2}', ['1', '3', '5', '7', '9']); -- match('{1..20..20}', ['1']); -- match('{1..20..2}', ['1', '3', '5', '7', '9', '11', '13', '15', '17', '19']); -- match('{10..0..2}', ['10', '8', '6', '4', '2', '0']); -- match('{10..1..2}', ['10', '8', '6', '4', '2']); -- match('{100..0..5}', ['100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']); -- match('{2..10..1}', ['2', '3', '4', '5', '6', '7', '8', '9', '10']); -- match('{2..10..2}', ['2', '4', '6', '8', '10']); -- match('{2..10..3}', ['2', '5', '8']); -- match('{a..z..2}', ['a', 'c', 'e', 'g', 'i', 'k', 'm', 'o', 'q', 's', 'u', 'w', 'y']); -+ equal('{1..10..1}', ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); -+ equal('{1..10..2}', ['1', '3', '5', '7', '9']); -+ equal('{1..20..20}', ['1']); -+ equal('{1..20..2}', ['1', '3', '5', '7', '9', '11', '13', '15', '17', '19']); -+ equal('{10..0..2}', ['10', '8', '6', '4', '2', '0']); -+ equal('{10..1..2}', ['10', '8', '6', '4', '2']); -+ equal('{100..0..5}', ['100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']); -+ equal('{2..10..1}', ['2', '3', '4', '5', '6', '7', '8', '9', '10']); -+ equal('{2..10..2}', ['2', '4', '6', '8', '10']); -+ equal('{2..10..3}', ['2', '5', '8']); -+ equal('{a..z..2}', ['a', 'c', 'e', 'g', 'i', 'k', 'm', 'o', 'q', 's', 'u', 'w', 'y']); - }); - - it('should expand positive ranges with negative steps:', function() { -- match('{10..0..-2}', ['10', '8', '6', '4', '2', '0']); -+ equal('{10..0..-2}', ['10', '8', '6', '4', '2', '0']); - }); - }); - - describe('steps > negative ranges', function() { - it('should expand negative ranges using steps:', function() { -- match('{-1..-10..-2}', ['-1', '-3', '-5', '-7', '-9']); -- match('{-1..-10..2}', ['-1', '-3', '-5', '-7', '-9']); -- match('{-10..-2..2}', ['-10', '-8', '-6', '-4', '-2']); -- match('{-2..-10..1}', ['-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '-10']); -- match('{-2..-10..2}', ['-2', '-4', '-6', '-8', '-10']); -- match('{-2..-10..3}', ['-2', '-5', '-8']); -- match('{-50..-0..5}', ['-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0']); -- match('{10..1..-2}', ['2', '4', '6', '8', '10']); -- match('{100..0..-5}', ['100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']); -+ equal('{-1..-10..-2}', ['-1', '-3', '-5', '-7', '-9']); -+ equal('{-1..-10..2}', ['-1', '-3', '-5', '-7', '-9']); -+ equal('{-10..-2..2}', ['-10', '-8', '-6', '-4', '-2']); -+ equal('{-2..-10..1}', ['-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '-10']); -+ equal('{-2..-10..2}', ['-2', '-4', '-6', '-8', '-10']); -+ equal('{-2..-10..3}', ['-2', '-5', '-8']); -+ equal('{-50..-0..5}', ['-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0']); -+ equal('{10..1..-2}', ['2', '4', '6', '8', '10']); -+ equal('{100..0..-5}', ['100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']); - }); - }); - - describe('steps > alphabetical ranges', function() { - it('should expand alpha ranges with steps', function() { -- match('{a..e..2}', ['a', 'c', 'e']); -- match('{E..A..2}', ['E', 'C', 'A']); -- match('{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']); -- match('{a..z..2}', ['a', 'c', 'e', 'g', 'i', 'k', 'm', 'o', 'q', 's', 'u', 'w', 'y']); -- match('{z..a..-2}', ['z', 'x', 'v', 't', 'r', 'p', 'n', 'l', 'j', 'h', 'f', 'd', 'b']); -+ equal('{a..e..2}', ['a', 'c', 'e']); -+ equal('{E..A..2}', ['E', 'C', 'A']); -+ equal('{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']); -+ equal('{a..z..2}', ['a', 'c', 'e', 'g', 'i', 'k', 'm', 'o', 'q', 's', 'u', 'w', 'y']); -+ equal('{z..a..-2}', ['z', 'x', 'v', 't', 'r', 'p', 'n', 'l', 'j', 'h', 'f', 'd', 'b']); - }); - - it('should expand alpha ranges with negative steps', function() { -- match('{z..a..-2}', ['z', 'x', 'v', 't', 'r', 'p', 'n', 'l', 'j', 'h', 'f', 'd', 'b']); -+ equal('{z..a..-2}', ['z', 'x', 'v', 't', 'r', 'p', 'n', 'l', 'j', 'h', 'f', 'd', 'b']); - }); - }); - - describe('padding', function() { - it('unwanted zero-padding -- fixed post-bash-4.0', function() { -- match('{10..0..2}', ['10', '8', '6', '4', '2', '0']); -- match('{10..0..-2}', ['10', '8', '6', '4', '2', '0']); -- match('{-50..-0..5}', ['-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0']); -+ equal('{10..0..2}', ['10', '8', '6', '4', '2', '0']); -+ equal('{10..0..-2}', ['10', '8', '6', '4', '2', '0']); -+ equal('{-50..-0..5}', ['-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0']); - }); - }); - }); ---- a/test/optimized.js -+++ b/test/optimized.js -@@ -11,7 +11,7 @@ - var assert = require('assert'); - var braces = require('..'); - --function match(pattern, expected, options) { -+function equal(pattern, expected, options) { - assert.deepEqual(braces(pattern, options), expected); - } - -@@ -19,129 +19,129 @@ - describe('sets', function() { - describe('invalid sets', function() { - it('should handle invalid sets:', function() { -- match('{0..10,braces}', ['(0..10|braces)']); -- match('{1..10,braces}', ['(1..10|braces)']); -+ equal('{0..10,braces}', ['(0..10|braces)']); -+ equal('{1..10,braces}', ['(1..10|braces)']); - }); - }); - - describe('escaping', function() { - it('should not expand escaped braces', function() { -- match('\\{a,b,c,d,e}', ['{a,b,c,d,e}']); -- match('a/b/c/{x,y\\}', ['a/b/c/{x,y}']); -- match('a/\\{x,y}/cde', ['a/{x,y}/cde']); -- match('abcd{efgh', ['abcd{efgh']); -- match('{abc}', ['{abc}']); -- match('{x,y,\\{a,b,c\\}}', ['(x|y|{a|b|c})']); -- match('{x,y,{a,b,c\\}}', ['{x,y,(a|b|c})']); -- match('{x,y,{abc},trie}', ['(x|y|{abc}|trie)']); -- match('{x\\,y,\\{abc\\},trie}', ['(x,y|{abc}|trie)']); -+ equal('\\{a,b,c,d,e}', ['{a,b,c,d,e}']); -+ equal('a/b/c/{x,y\\}', ['a/b/c/{x,y}']); -+ equal('a/\\{x,y}/cde', ['a/{x,y}/cde']); -+ equal('abcd{efgh', ['abcd{efgh']); -+ equal('{abc}', ['{abc}']); -+ equal('{x,y,\\{a,b,c\\}}', ['(x|y|{a|b|c})']); -+ equal('{x,y,{a,b,c\\}}', ['{x,y,(a|b|c})']); -+ equal('{x,y,{abc},trie}', ['(x|y|{abc}|trie)']); -+ equal('{x\\,y,\\{abc\\},trie}', ['(x,y|{abc}|trie)']); - }); - - it('should handle spaces', function() { - // Bash 4.3 says the following should be equivalent to `foo|(1|2)|bar`, - // That makes sense in Bash, since ' ' is a separator, but not here. -- match('foo {1,2} bar', ['foo (1|2) bar']); -+ equal('foo {1,2} bar', ['foo (1|2) bar']); - }); - - it('should handle empty braces', function() { -- match('{ }', ['{ }']); -- match('{', ['{']); -- match('{}', ['{}']); -- match('}', ['}']); -+ equal('{ }', ['{ }']); -+ equal('{', ['{']); -+ equal('{}', ['{}']); -+ equal('}', ['}']); - }); - - it('should escape braces when only one value is defined', function() { -- match('a{b}c', ['a{b}c']); -- match('a/b/c{d}e', ['a/b/c{d}e']); -+ equal('a{b}c', ['a{b}c']); -+ equal('a/b/c{d}e', ['a/b/c{d}e']); - }); - - it('should not expand braces in sets with es6/bash-like variables', function() { -- match('abc/${ddd}/xyz', ['abc/${ddd}/xyz']); -- match('a${b}c', ['a${b}c']); -- match('a/{${b},c}/d', ['a/(${b}|c)/d']); -- match('a${b,d}/{foo,bar}c', ['a${b,d}/(foo|bar)c']); -+ equal('abc/${ddd}/xyz', ['abc/${ddd}/xyz']); -+ equal('a${b}c', ['a${b}c']); -+ equal('a/{${b},c}/d', ['a/(${b}|c)/d']); -+ equal('a${b,d}/{foo,bar}c', ['a${b,d}/(foo|bar)c']); - }); - - it('should not expand escaped commas.', function() { -- match('a{b\\,c\\,d}e', ['a{b,c,d}e']); -- match('a{b\\,c}d', ['a{b,c}d']); -- match('{abc\\,def}', ['{abc,def}']); -- match('{abc\\,def,ghi}', ['(abc,def|ghi)']); -- match('a/{b,c}/{x\\,y}/d/e', ['a/(b|c)/{x,y}/d/e']); -+ equal('a{b\\,c\\,d}e', ['a{b,c,d}e']); -+ equal('a{b\\,c}d', ['a{b,c}d']); -+ equal('{abc\\,def}', ['{abc,def}']); -+ equal('{abc\\,def,ghi}', ['(abc,def|ghi)']); -+ equal('a/{b,c}/{x\\,y}/d/e', ['a/(b|c)/{x,y}/d/e']); - }); - - it('should return sets with escaped commas', function() { -- match('a/{b,c}/{x\\,y}/d/e', ['a/(b|c)/{x,y}/d/e']); -+ equal('a/{b,c}/{x\\,y}/d/e', ['a/(b|c)/{x,y}/d/e']); - }); - - it('should not expand escaped braces.', function() { -- match('{a,b\\}c,d}', ['(a|b}c|d)']); -- match('\\{a,b,c,d,e}', ['{a,b,c,d,e}']); -- match('a/{z,\\{a,b,c,d,e}/d', ['a/(z|{a|b|c|d|e)/d']); -- match('a/\\{b,c}/{d,e}/f', ['a/{b,c}/(d|e)/f']); -- match('./\\{x,y}/{a..z..3}/', ['./{x,y}/(a|d|g|j|m|p|s|v|y)/']); -+ equal('{a,b\\}c,d}', ['(a|b}c|d)']); -+ equal('\\{a,b,c,d,e}', ['{a,b,c,d,e}']); -+ equal('a/{z,\\{a,b,c,d,e}/d', ['a/(z|{a|b|c|d|e)/d']); -+ equal('a/\\{b,c}/{d,e}/f', ['a/{b,c}/(d|e)/f']); -+ equal('./\\{x,y}/{a..z..3}/', ['./{x,y}/(a|d|g|j|m|p|s|v|y)/']); - }); - - it('should not expand escaped braces or commas.', function() { -- match('{x\\,y,\\{abc\\},trie}', ['(x,y|{abc}|trie)']); -+ equal('{x\\,y,\\{abc\\},trie}', ['(x,y|{abc}|trie)']); - }); - }); - - describe('set expansion', function() { - it('should support sequence brace operators', function() { -- match('/usr/{ucb/{ex,edit},lib/{ex,how_ex}}', ['/usr/(ucb/(ex|edit)|lib/(ex|how_ex))']); -- match('ff{c,b,a}', ['ff(c|b|a)']); -- match('f{d,e,f}g', ['f(d|e|f)g']); -- match('x{{0..10},braces}y', ['x(([0-9]|10)|braces)y']); -- match('{1..10}', ['([1-9]|10)']); -- match('{a,b,c}', ['(a|b|c)']); -- match('{braces,{0..10}}', ['(braces|([0-9]|10))']); -- match('{l,n,m}xyz', ['(l|n|m)xyz']); -- match('{{0..10},braces}', ['(([0-9]|10)|braces)']); -- match('{{1..10..2},braces}', ['((1|3|5|7|9)|braces)']); -- match('{{1..10},braces}', ['(([1-9]|10)|braces)']); -+ equal('/usr/{ucb/{ex,edit},lib/{ex,how_ex}}', ['/usr/(ucb/(ex|edit)|lib/(ex|how_ex))']); -+ equal('ff{c,b,a}', ['ff(c|b|a)']); -+ equal('f{d,e,f}g', ['f(d|e|f)g']); -+ equal('x{{0..10},braces}y', ['x(([0-9]|10)|braces)y']); -+ equal('{1..10}', ['([1-9]|10)']); -+ equal('{a,b,c}', ['(a|b|c)']); -+ equal('{braces,{0..10}}', ['(braces|([0-9]|10))']); -+ equal('{l,n,m}xyz', ['(l|n|m)xyz']); -+ equal('{{0..10},braces}', ['(([0-9]|10)|braces)']); -+ equal('{{1..10..2},braces}', ['((1|3|5|7|9)|braces)']); -+ equal('{{1..10},braces}', ['(([1-9]|10)|braces)']); - }); - - it('should expand multiple sets', function() { -- match('a/{a,b}/{c,d}/e', ['a/(a|b)/(c|d)/e']); -- match('a{b,c}d{e,f}g', ['a(b|c)d(e|f)g']); -- match('a/{x,y}/c{d,e}f.{md,txt}', ['a/(x|y)/c(d|e)f.(md|txt)']); -+ equal('a/{a,b}/{c,d}/e', ['a/(a|b)/(c|d)/e']); -+ equal('a{b,c}d{e,f}g', ['a(b|c)d(e|f)g']); -+ equal('a/{x,y}/c{d,e}f.{md,txt}', ['a/(x|y)/c(d|e)f.(md|txt)']); - }); - - it('should expand nested sets', function() { -- match('{a,b}{{a,b},a,b}', ['(a|b)((a|b)|a|b)']); -- match('a{b,c{d,e}f}g', ['a(b|c(d|e)f)g']); -- match('a{{x,y},z}b', ['a((x|y)|z)b']); -- match('f{x,y{g,z}}h', ['f(x|y(g|z))h']); -- match('a{b,c}{d,e}/hx/z', ['a(b|c)(d|e)/hx/z']); -- match('a{b,c{d,e},h}x/z', ['a(b|c(d|e)|h)x/z']); -- match('a{b,c{d,e},h}x{y,z}', ['a(b|c(d|e)|h)x(y|z)']); -- match('a{b,c{d,e},{f,g}h}x{y,z}', ['a(b|c(d|e)|(f|g)h)x(y|z)']); -- match('a-{b{d,e}}-c', ['a-{b(d|e)}-c']); -+ equal('{a,b}{{a,b},a,b}', ['(a|b)((a|b)|a|b)']); -+ equal('a{b,c{d,e}f}g', ['a(b|c(d|e)f)g']); -+ equal('a{{x,y},z}b', ['a((x|y)|z)b']); -+ equal('f{x,y{g,z}}h', ['f(x|y(g|z))h']); -+ equal('a{b,c}{d,e}/hx/z', ['a(b|c)(d|e)/hx/z']); -+ equal('a{b,c{d,e},h}x/z', ['a(b|c(d|e)|h)x/z']); -+ equal('a{b,c{d,e},h}x{y,z}', ['a(b|c(d|e)|h)x(y|z)']); -+ equal('a{b,c{d,e},{f,g}h}x{y,z}', ['a(b|c(d|e)|(f|g)h)x(y|z)']); -+ equal('a-{b{d,e}}-c', ['a-{b(d|e)}-c']); - }); - - it('should expand not modify non-brace characters', function() { -- match('a/b/{d,e}/*.js', ['a/b/(d|e)/*.js']); -- match('a/**/c/{d,e}/f*.js', ['a/**/c/(d|e)/f*.js']); -- match('a/**/c/{d,e}/f*.{md,txt}', ['a/**/c/(d|e)/f*.(md|txt)']); -+ equal('a/b/{d,e}/*.js', ['a/b/(d|e)/*.js']); -+ equal('a/**/c/{d,e}/f*.js', ['a/**/c/(d|e)/f*.js']); -+ equal('a/**/c/{d,e}/f*.{md,txt}', ['a/**/c/(d|e)/f*.(md|txt)']); - }); - }); - - describe('commas', function() { - it('should work with leading and trailing commas.', function() { -- match('a{b,}c', ['a(b|)c']); -- match('a{,b}c', ['a(|b)c']); -+ equal('a{b,}c', ['a(b|)c']); -+ equal('a{,b}c', ['a(|b)c']); - }); - }); - - describe('spaces', function() { - it('should handle spaces', function() { -- match('0{1..9} {10..20}', ['0([1-9]) (1[0-9]|20)']); -- match('a{ ,c{d, },h}x', ['a( |c(d| )|h)x']); -- match('a{ ,c{d, },h} ', ['a( |c(d| )|h) ']); -+ equal('0{1..9} {10..20}', ['0([1-9]) (1[0-9]|20)']); -+ equal('a{ ,c{d, },h}x', ['a( |c(d| )|h)x']); -+ equal('a{ ,c{d, },h} ', ['a( |c(d| )|h) ']); - -- // see https://github.com/jonschlinkert/micromatch/issues/66 -- match('/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.{html,ejs}', ['/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.(html|ejs)']); -+ // see https://github.com/jonschlinkert/microequal/issues/66 -+ equal('/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.{html,ejs}', ['/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.(html|ejs)']); - }); - }); - }); -@@ -153,198 +153,198 @@ - describe('ranges', function() { - describe('escaping / invalid ranges', function() { - it('should not try to expand ranges with decimals', function() { -- match('{1.1..2.1}', ['{1.1..2.1}']); -- match('{1.1..~2.1}', ['{1.1..~2.1}']); -+ equal('{1.1..2.1}', ['{1.1..2.1}']); -+ equal('{1.1..~2.1}', ['{1.1..~2.1}']); - }); - - it('should escape invalid ranges:', function() { -- match('{1..0f}', ['{1..0f}']); -- match('{1..10..ff}', ['{1..10..ff}']); -- match('{1..10.f}', ['{1..10.f}']); -- match('{1..10f}', ['{1..10f}']); -- match('{1..20..2f}', ['{1..20..2f}']); -- match('{1..20..f2}', ['{1..20..f2}']); -- match('{1..2f..2}', ['{1..2f..2}']); -- match('{1..ff..2}', ['{1..ff..2}']); -- match('{1..ff}', ['{1..ff}']); -- match('{1..f}', ['([1-f])']); -- match('{1.20..2}', ['{1.20..2}']); -+ equal('{1..0f}', ['{1..0f}']); -+ equal('{1..10..ff}', ['{1..10..ff}']); -+ equal('{1..10.f}', ['{1..10.f}']); -+ equal('{1..10f}', ['{1..10f}']); -+ equal('{1..20..2f}', ['{1..20..2f}']); -+ equal('{1..20..f2}', ['{1..20..f2}']); -+ equal('{1..2f..2}', ['{1..2f..2}']); -+ equal('{1..ff..2}', ['{1..ff..2}']); -+ equal('{1..ff}', ['{1..ff}']); -+ equal('{1..f}', ['([1-f])']); -+ equal('{1.20..2}', ['{1.20..2}']); - }); - - it('weirdly-formed brace expansions -- fixed in post-bash-3.1', function() { -- match('a-{b{d,e}}-c', ['a-{b(d|e)}-c']); -- match('a-{bdef-{g,i}-c', ['a-{bdef-(g|i)-c']); -+ equal('a-{b{d,e}}-c', ['a-{b(d|e)}-c']); -+ equal('a-{bdef-{g,i}-c', ['a-{bdef-(g|i)-c']); - }); - - it('should not expand quoted strings.', function() { -- match('{"klklkl"}{1,2,3}', ['{klklkl}(1|2|3)']); -- match('{"x,x"}', ['{x,x}']); -+ equal('{"klklkl"}{1,2,3}', ['{klklkl}(1|2|3)']); -+ equal('{"x,x"}', ['{x,x}']); - }); - - it('should escaped outer braces in nested non-sets', function() { -- match('{a-{b,c,d}}', ['{a-(b|c|d)}']); -- match('{a,{a-{b,c,d}}}', ['(a|{a-(b|c|d)})']); -+ equal('{a-{b,c,d}}', ['{a-(b|c|d)}']); -+ equal('{a,{a-{b,c,d}}}', ['(a|{a-(b|c|d)})']); - }); - - it('should escape imbalanced braces', function() { -- match('a-{bdef-{g,i}-c', ['a-{bdef-(g|i)-c']); -- match('abc{', ['abc{']); -- match('{abc{', ['{abc{']); -- match('{abc', ['{abc']); -- match('}abc', ['}abc']); -- match('ab{c', ['ab{c']); -- match('{{a,b}', ['{(a|b)']); -- match('{a,b}}', ['(a|b)}']); -- match('abcd{efgh', ['abcd{efgh']); -- match('a{b{c{d,e}f}g}h', ['a(b(c(d|e)f)g)h']); -- match('f{x,y{{g,z}}h}', ['f(x|y((g|z))h)']); -- match('z{a,b},c}d', ['z(a|b),c}d']); -- match('a{b{c{d,e}f{x,y{{g}h', ['a{b{c(d|e)f{x,y{{g}h']); -- match('f{x,y{{g}h', ['f{x,y{{g}h']); -- match('f{x,y{{g}}h', ['f{x,y{{g}}h']); -- match('a{b{c{d,e}f{x,y{}g}h', ['a{b{c(d|e)f(x|y{}g)h']); -- match('f{x,y{}g}h', ['f(x|y{}g)h']); -- match('z{a,b{,c}d', ['z{a,b(|c)d']); -+ equal('a-{bdef-{g,i}-c', ['a-{bdef-(g|i)-c']); -+ equal('abc{', ['abc{']); -+ equal('{abc{', ['{abc{']); -+ equal('{abc', ['{abc']); -+ equal('}abc', ['}abc']); -+ equal('ab{c', ['ab{c']); -+ equal('{{a,b}', ['{(a|b)']); -+ equal('{a,b}}', ['(a|b)}']); -+ equal('abcd{efgh', ['abcd{efgh']); -+ equal('a{b{c{d,e}f}g}h', ['a(b(c(d|e)f)g)h']); -+ equal('f{x,y{{g,z}}h}', ['f(x|y((g|z))h)']); -+ equal('z{a,b},c}d', ['z(a|b),c}d']); -+ equal('a{b{c{d,e}f{x,y{{g}h', ['a{b{c(d|e)f{x,y{{g}h']); -+ equal('f{x,y{{g}h', ['f{x,y{{g}h']); -+ equal('f{x,y{{g}}h', ['f{x,y{{g}}h']); -+ equal('a{b{c{d,e}f{x,y{}g}h', ['a{b{c(d|e)f(x|y{}g)h']); -+ equal('f{x,y{}g}h', ['f(x|y{}g)h']); -+ equal('z{a,b{,c}d', ['z{a,b(|c)d']); - }); - }); - - describe('positive numeric ranges', function() { - it('should expand numeric ranges', function() { -- match('a{0..3}d', ['a([0-3])d']); -- match('x{10..1}y', ['x([1-9]|10)y']); -- match('x{3..3}y', ['x3y']); -- match('{1..10}', ['([1-9]|10)']); -- match('{1..3}', ['([1-3])']); -- match('{1..9}', ['([1-9])']); -- match('{10..1}', ['([1-9]|10)']); -- match('{10..1}y', ['([1-9]|10)y']); -- match('{3..3}', ['3']); -- match('{5..8}', ['([5-8])']); -+ equal('a{0..3}d', ['a([0-3])d']); -+ equal('x{10..1}y', ['x([1-9]|10)y']); -+ equal('x{3..3}y', ['x3y']); -+ equal('{1..10}', ['([1-9]|10)']); -+ equal('{1..3}', ['([1-3])']); -+ equal('{1..9}', ['([1-9])']); -+ equal('{10..1}', ['([1-9]|10)']); -+ equal('{10..1}y', ['([1-9]|10)y']); -+ equal('{3..3}', ['3']); -+ equal('{5..8}', ['([5-8])']); - }); - }); - - describe('negative ranges', function() { - it('should expand ranges with negative numbers', function() { -- match('{-1..-10}', ['(-[1-9]|-10)']); -- match('{-10..-1}', ['(-[1-9]|-10)']); -- match('{-20..0}', ['(-[1-9]|-1[0-9]|-20|0)']); -- match('{0..-5}', ['(-[1-5]|0)']); -- match('{9..-4}', ['(-[1-4]|[0-9])']); -+ equal('{-1..-10}', ['(-[1-9]|-10)']); -+ equal('{-10..-1}', ['(-[1-9]|-10)']); -+ equal('{-20..0}', ['(-[1-9]|-1[0-9]|-20|0)']); -+ equal('{0..-5}', ['(-[1-5]|0)']); -+ equal('{9..-4}', ['(-[1-4]|[0-9])']); - }); - }); - - describe('alphabetical ranges', function() { - it('should expand alphabetical ranges', function() { -- match('0{1..9}/{10..20}', ['0([1-9])/(1[0-9]|20)']); -- match('0{a..d}0', ['0([a-d])0']); -- match('a/{b..d}/e', ['a/([b-d])/e']); -- match('{1..f}', ['([1-f])']); -- match('{a..A}', ['([A-a])']); -- match('{A..a}', ['([A-a])']); -- match('{a..e}', ['([a-e])']); -- match('{A..E}', ['([A-E])']); -- match('{a..f}', ['([a-f])']); -- match('{a..z}', ['([a-z])']); -- match('{E..A}', ['([A-E])']); -- match('{f..1}', ['([1-f])']); -- match('{f..a}', ['([a-f])']); -- match('{f..f}', ['f']); -+ equal('0{1..9}/{10..20}', ['0([1-9])/(1[0-9]|20)']); -+ equal('0{a..d}0', ['0([a-d])0']); -+ equal('a/{b..d}/e', ['a/([b-d])/e']); -+ equal('{1..f}', ['([1-f])']); -+ equal('{a..A}', ['([A-a])']); -+ equal('{A..a}', ['([A-a])']); -+ equal('{a..e}', ['([a-e])']); -+ equal('{A..E}', ['([A-E])']); -+ equal('{a..f}', ['([a-f])']); -+ equal('{a..z}', ['([a-z])']); -+ equal('{E..A}', ['([A-E])']); -+ equal('{f..1}', ['([1-f])']); -+ equal('{f..a}', ['([a-f])']); -+ equal('{f..f}', ['f']); - }); - - it('should expand multiple ranges:', function() { -- match('a/{b..d}/e/{f..h}', ['a/([b-d])/e/([f-h])']); -+ equal('a/{b..d}/e/{f..h}', ['a/([b-d])/e/([f-h])']); - }); - }); - - describe('combo', function() { - it('should expand numerical ranges - positive and negative', function() { -- match('{-10..10}', ['(-[1-9]|-?10|[0-9])']); -+ equal('{-10..10}', ['(-[1-9]|-?10|[0-9])']); - }); - }); - - // HEADS UP! If you're using the `--mm` flag minimatch freezes on these - describe('large numbers', function() { - it('should expand large numbers', function() { -- match('{2147483645..2147483649}', ['(214748364[5-9])']); -- match('{214748364..2147483649}', ['(21474836[4-9]|2147483[7-9][0-9]|214748[4-9][0-9]{2}|214749[0-9]{3}|2147[5-9][0-9]{4}|214[8-9][0-9]{5}|21[5-9][0-9]{6}|2[2-9][0-9]{7}|[3-9][0-9]{8}|1[0-9]{9}|20[0-9]{8}|21[0-3][0-9]{7}|214[0-6][0-9]{6}|2147[0-3][0-9]{5}|21474[0-7][0-9]{4}|214748[0-2][0-9]{3}|2147483[0-5][0-9]{2}|21474836[0-4][0-9])']); -+ equal('{2147483645..2147483649}', ['(214748364[5-9])']); -+ equal('{214748364..2147483649}', ['(21474836[4-9]|2147483[7-9][0-9]|214748[4-9][0-9]{2}|214749[0-9]{3}|2147[5-9][0-9]{4}|214[89][0-9]{5}|21[5-9][0-9]{6}|2[2-9][0-9]{7}|[3-9][0-9]{8}|1[0-9]{9}|20[0-9]{8}|21[0-3][0-9]{7}|214[0-6][0-9]{6}|2147[0-3][0-9]{5}|21474[0-7][0-9]{4}|214748[0-2][0-9]{3}|2147483[0-5][0-9]{2}|21474836[0-4][0-9])']); - }); - }); - - describe('steps > positive ranges', function() { - it('should expand ranges using steps:', function() { -- match('{1..10..1}', ['([1-9]|10)']); -- match('{1..10..2}', ['(1|3|5|7|9)']); -- match('{1..20..20}', ['1']); -- match('{1..20..20}', ['1']); -- match('{1..20..20}', ['1']); -- match('{1..20..2}', ['(1|3|5|7|9|11|13|15|17|19)']); -- match('{10..0..2}', ['(10|8|6|4|2|0)']); -- match('{10..1..2}', ['(10|8|6|4|2)']); -- match('{100..0..5}', ['(100|95|90|85|80|75|70|65|60|55|50|45|40|35|30|25|20|15|10|5|0)']); -- match('{2..10..1}', ['([2-9]|10)']); -- match('{2..10..2}', ['(2|4|6|8|10)']); -- match('{2..10..3}', ['(2|5|8)']); -- match('{a..z..2}', ['(a|c|e|g|i|k|m|o|q|s|u|w|y)']); -+ equal('{1..10..1}', ['([1-9]|10)']); -+ equal('{1..10..2}', ['(1|3|5|7|9)']); -+ equal('{1..20..20}', ['1']); -+ equal('{1..20..20}', ['1']); -+ equal('{1..20..20}', ['1']); -+ equal('{1..20..2}', ['(1|3|5|7|9|11|13|15|17|19)']); -+ equal('{10..0..2}', ['(10|8|6|4|2|0)']); -+ equal('{10..1..2}', ['(10|8|6|4|2)']); -+ equal('{100..0..5}', ['(100|95|90|85|80|75|70|65|60|55|50|45|40|35|30|25|20|15|10|5|0)']); -+ equal('{2..10..1}', ['([2-9]|10)']); -+ equal('{2..10..2}', ['(2|4|6|8|10)']); -+ equal('{2..10..3}', ['(2|5|8)']); -+ equal('{a..z..2}', ['(a|c|e|g|i|k|m|o|q|s|u|w|y)']); - }); - - it('should expand positive ranges with negative steps:', function() { -- match('{10..0..-2}', ['(10|8|6|4|2|0)']); -+ equal('{10..0..-2}', ['(10|8|6|4|2|0)']); - }); - }); - - describe('steps > negative ranges', function() { - it('should expand negative ranges using steps:', function() { -- match('{-1..-10..-2}', ['(-(1|3|5|7|9))']); -- match('{-1..-10..2}', ['(-(1|3|5|7|9))']); -- match('{-10..-2..2}', ['(-(10|8|6|4|2))']); -- match('{-2..-10..1}', ['(-[2-9]|-10)']); -- match('{-2..-10..2}', ['(-(2|4|6|8|10))']); -- match('{-2..-10..3}', ['(-(2|5|8))']); -- match('{-50..-0..5}', ['(0|-(50|45|40|35|30|25|20|15|10|5))']); -- match('{-9..9..3}', ['(0|3|6|9|-(9|6|3))']); -- match('{10..1..-2}', ['(10|8|6|4|2)']); -- match('{100..0..-5}', ['(100|95|90|85|80|75|70|65|60|55|50|45|40|35|30|25|20|15|10|5|0)']); -+ equal('{-1..-10..-2}', ['(-(1|3|5|7|9))']); -+ equal('{-1..-10..2}', ['(-(1|3|5|7|9))']); -+ equal('{-10..-2..2}', ['(-(10|8|6|4|2))']); -+ equal('{-2..-10..1}', ['(-[2-9]|-10)']); -+ equal('{-2..-10..2}', ['(-(2|4|6|8|10))']); -+ equal('{-2..-10..3}', ['(-(2|5|8))']); -+ equal('{-50..-0..5}', ['(0|-(50|45|40|35|30|25|20|15|10|5))']); -+ equal('{-9..9..3}', ['(0|3|6|9|-(9|6|3))']); -+ equal('{10..1..-2}', ['(10|8|6|4|2)']); -+ equal('{100..0..-5}', ['(100|95|90|85|80|75|70|65|60|55|50|45|40|35|30|25|20|15|10|5|0)']); - }); - }); - - describe('steps > alphabetical ranges', function() { - it('should expand alpha ranges with steps', function() { -- match('{a..e..2}', ['(a|c|e)']); -- match('{E..A..2}', ['(E|C|A)']); -- match('{a..z}', ['([a-z])']); -- match('{a..z..2}', ['(a|c|e|g|i|k|m|o|q|s|u|w|y)']); -- match('{z..a..-2}', ['(z|x|v|t|r|p|n|l|j|h|f|d|b)']); -+ equal('{a..e..2}', ['(a|c|e)']); -+ equal('{E..A..2}', ['(E|C|A)']); -+ equal('{a..z}', ['([a-z])']); -+ equal('{a..z..2}', ['(a|c|e|g|i|k|m|o|q|s|u|w|y)']); -+ equal('{z..a..-2}', ['(z|x|v|t|r|p|n|l|j|h|f|d|b)']); - }); - - it('should expand alpha ranges with negative steps', function() { -- match('{z..a..-2}', ['(z|x|v|t|r|p|n|l|j|h|f|d|b)']); -+ equal('{z..a..-2}', ['(z|x|v|t|r|p|n|l|j|h|f|d|b)']); - }); - }); - - describe('padding', function() { - it('unwanted zero-padding -- fixed post-bash-4.0', function() { -- match('{10..0..2}', ['(10|8|6|4|2|0)']); -- match('{10..0..-2}', ['(10|8|6|4|2|0)']); -- match('{-50..-0..5}', ['(0|-(50|45|40|35|30|25|20|15|10|5))']); -+ equal('{10..0..2}', ['(10|8|6|4|2|0)']); -+ equal('{10..0..-2}', ['(10|8|6|4|2|0)']); -+ equal('{-50..-0..5}', ['(0|-(50|45|40|35|30|25|20|15|10|5))']); - }); - }); - }); - - describe('integration', function() { - it('should work with dots in file paths', function() { -- match('../{1..3}/../foo', ['../([1-3])/../foo']); -- match('../{2..10..2}/../foo', ['../(2|4|6|8|10)/../foo']); -- match('../{1..3}/../{a,b,c}/foo', ['../([1-3])/../(a|b|c)/foo']); -- match('./{a..z..3}/', ['./(a|d|g|j|m|p|s|v|y)/']); -- match('./{"x,y"}/{a..z..3}/', ['./{x,y}/(a|d|g|j|m|p|s|v|y)/']); -+ equal('../{1..3}/../foo', ['../([1-3])/../foo']); -+ equal('../{2..10..2}/../foo', ['../(2|4|6|8|10)/../foo']); -+ equal('../{1..3}/../{a,b,c}/foo', ['../([1-3])/../(a|b|c)/foo']); -+ equal('./{a..z..3}/', ['./(a|d|g|j|m|p|s|v|y)/']); -+ equal('./{"x,y"}/{a..z..3}/', ['./{x,y}/(a|d|g|j|m|p|s|v|y)/']); - }); - - it('should expand a complex combination of ranges and sets:', function() { -- match('a/{x,y}/{1..5}c{d,e}f.{md,txt}', ['a/(x|y)/([1-5])c(d|e)f.(md|txt)']); -+ equal('a/{x,y}/{1..5}c{d,e}f.{md,txt}', ['a/(x|y)/([1-5])c(d|e)f.(md|txt)']); - }); - - it('should expand complex sets and ranges in `bash` mode:', function() { -- match('a/{x,{1..5},y}/c{d}e', ['a/(x|([1-5])|y)/c{d}e']); -+ equal('a/{x,{1..5},y}/c{d}e', ['a/(x|([1-5])|y)/c{d}e']); - }); - }); - }); diff -Nru node-braces-2.0.2/debian/rules node-braces-3.0.2/debian/rules --- node-braces-2.0.2/debian/rules 2017-12-29 14:19:13.000000000 +0000 +++ node-braces-3.0.2/debian/rules 2019-09-02 04:34:48.000000000 +0000 @@ -5,11 +5,4 @@ #export DH_VERBOSE=1 %: - dh $@ - -#override_dh_auto_build: - -override_dh_auto_test: - mocha -R spec - - + dh $@ --with nodejs diff -Nru node-braces-2.0.2/debian/source/lintian-overrides node-braces-3.0.2/debian/source/lintian-overrides --- node-braces-2.0.2/debian/source/lintian-overrides 2017-12-29 14:19:13.000000000 +0000 +++ node-braces-3.0.2/debian/source/lintian-overrides 2019-09-02 04:34:48.000000000 +0000 @@ -1,8 +1,13 @@ #False positives -node-braces source: source-is-missing test/bash.expanded.js line length is 2439 characters (>512) -node-braces source: source-is-missing test/bash.spec.js line length is 767 characters (>512) -node-braces source: source-is-missing test/expanded.integration.js line length is 662 characters (>512) -node-braces source: source-is-missing test/expanded.ranges.js line length is 920 characters (>512) -node-braces source: source-is-missing test/expanded.sets.js line length is 919 characters (>512) -node-braces source: source-is-missing test/multiples.js line length is 3068 characters (>512) -node-braces source: source-is-missing test/regression-1.8.5.js line length is 919 characters (>512) +source: source-is-missing test/multiples.js line length is 3068 characters (>512) +source: insane-line-length-in-source-file test/bash-expanded-ranges.js line length is 926 characters (>512) +source: source-contains-prebuilt-javascript-object test/bash-expanded-ranges.js line length is 920 characters (>512) +source: source-is-missing test/bash-expanded-ranges.js line length is 920 characters (>512) +source: insane-line-length-in-source-file test/bash-spec.js line length is 771 characters (>512) +source: source-contains-prebuilt-javascript-object test/bash-spec.js line length is 767 characters (>512) +source: source-is-missing test/bash-spec.js line length is 767 characters (>512) +source: insane-line-length-in-source-file test/multiples.js line length is 3072 characters (>512) +source: source-contains-prebuilt-javascript-object test/multiples.js line length is 3068 characters (>512) +source: insane-line-length-in-source-file test/regression.js line length is 923 characters (>512) +source: source-contains-prebuilt-javascript-object test/regression.js line length is 919 characters (>512) +source: source-is-missing test/regression.js line length is 919 characters (>512) diff -Nru node-braces-2.0.2/debian/tests/control node-braces-3.0.2/debian/tests/control --- node-braces-2.0.2/debian/tests/control 2017-12-29 14:19:13.000000000 +0000 +++ node-braces-3.0.2/debian/tests/control 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -Tests: require -Depends: node-braces - -Test-Command: mocha -R spec -Depends: @, @builddeps@ diff -Nru node-braces-2.0.2/debian/tests/modules/bash-path/index.js node-braces-3.0.2/debian/tests/modules/bash-path/index.js --- node-braces-2.0.2/debian/tests/modules/bash-path/index.js 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/debian/tests/modules/bash-path/index.js 2019-09-02 04:34:48.000000000 +0000 @@ -0,0 +1,69 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +let bashPath; + +/** + * Default paths to search + */ + +const DEFAULT_PATHS = [ + '/bin/bash', + '/sbin/bash', + '/usr/bin/bash', + '/usr/local/bin/bash', + '/usr/local/sbin/bash', + '/usr/sbin/bash', + '/usr/X11/bin/bash', + '/opt/local/bin', + '/opt/local/sbin', + 'bash' +]; + +module.exports = paths => { + if (bashPath !== void 0) return bashPath; + + const pathList = getPaths(paths || DEFAULT_PATHS); + + for (let i = 0; i < pathList.length; i++) { + let filepath = path.resolve(pathList[i], 'bash'); + + if (fs.existsSync(filepath)) { + bashPath = filepath; + break; + } + + if (process.platform === 'win32') { + if (fs.existsSync(filepath + '.cmd')) { + bashPath = filepath + '.cmd'; + break; + } + + if (fs.existsSync(filepath + '.exe')) { + bashPath = filepath + '.exe'; + break; + } + + if (fs.existsSync(filepath + '.bat')) { + bashPath = filepath + '.bat'; + break; + } + } + } + + // Set to null to avoid checking again later if path was not found + if (!bashPath) { + bashPath = null; + } + + return bashPath; +}; + +function getPaths(paths) { + const compare = val => /\/use?r\//i.test(val) ? -1 : 1; + const list = paths.concat(process.env.PATH.split(path.delimiter)); + const unique = [...new Set(list)]; + unique.sort(compare); + return unique; +} diff -Nru node-braces-2.0.2/debian/tests/modules/bash-path/LICENSE node-braces-3.0.2/debian/tests/modules/bash-path/LICENSE --- node-braces-2.0.2/debian/tests/modules/bash-path/LICENSE 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/debian/tests/modules/bash-path/LICENSE 2019-09-02 04:34:48.000000000 +0000 @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017, 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 +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff -Nru node-braces-2.0.2/debian/tests/modules/bash-path/package.json node-braces-3.0.2/debian/tests/modules/bash-path/package.json --- node-braces-2.0.2/debian/tests/modules/bash-path/package.json 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/debian/tests/modules/bash-path/package.json 2019-09-02 04:34:48.000000000 +0000 @@ -0,0 +1,75 @@ +{ + "_from": "bash-path", + "_id": "bash-path@2.0.1", + "_inBundle": false, + "_integrity": "sha512-cBJaWODBsbTsf8WylNtTptGP7Vd/JSN4Vc0ahBXUY3e/HNobG+LRPCoIYvOefOkrcYnotEbjd0J9URZPtGpjlw==", + "_location": "/bash-path", + "_phantomChildren": {}, + "_requested": { + "type": "tag", + "registry": true, + "raw": "bash-path", + "name": "bash-path", + "escapedName": "bash-path", + "rawSpec": "", + "saveSpec": null, + "fetchSpec": "latest" + }, + "_requiredBy": [ + "#USER", + "/" + ], + "_resolved": "https://registry.npmjs.org/bash-path/-/bash-path-2.0.1.tgz", + "_shasum": "f1f2fa0f071aba04918ecbf21bdc4ab699e26091", + "_spec": "bash-path", + "_where": "/tmp/tt", + "author": { + "name": "Jon Schlinkert", + "url": "https://github.com/jonschlinkert" + }, + "bugs": { + "url": "https://github.com/micromatch/bash-path/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Get the path to the bash binary on your OS.", + "devDependencies": { + "gulp-format-md": "^2.0.0", + "mocha": "^6.0.2" + }, + "engines": { + "node": ">=6" + }, + "files": [ + "index.js" + ], + "homepage": "https://github.com/micromatch/bash-path", + "keywords": [ + "bash", + "path" + ], + "license": "MIT", + "main": "index.js", + "name": "bash-path", + "repository": { + "type": "git", + "url": "git+https://github.com/micromatch/bash-path.git" + }, + "scripts": { + "test": "mocha" + }, + "verb": { + "toc": false, + "layout": "default", + "tasks": [ + "readme" + ], + "plugins": [ + "gulp-format-md" + ], + "lint": { + "reflinks": true + } + }, + "version": "2.0.1" +} diff -Nru node-braces-2.0.2/debian/tests/modules/bash-path/README.md node-braces-3.0.2/debian/tests/modules/bash-path/README.md --- node-braces-2.0.2/debian/tests/modules/bash-path/README.md 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/debian/tests/modules/bash-path/README.md 2019-09-02 04:34:48.000000000 +0000 @@ -0,0 +1,79 @@ +# bash-path [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=W8YFZ425KND68) [![NPM version](https://img.shields.io/npm/v/bash-path.svg?style=flat)](https://www.npmjs.com/package/bash-path) [![NPM monthly downloads](https://img.shields.io/npm/dm/bash-path.svg?style=flat)](https://npmjs.org/package/bash-path) [![NPM total downloads](https://img.shields.io/npm/dt/bash-path.svg?style=flat)](https://npmjs.org/package/bash-path) [![Linux Build Status](https://img.shields.io/travis/micromatch/bash-path.svg?style=flat&label=Travis)](https://travis-ci.org/micromatch/bash-path) + +> Get the path to the bash binary on your OS. + +Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support. + +## Install + +Install with [npm](https://www.npmjs.com/): + +```sh +$ npm install --save bash-path +``` + +## Usage + +The path to the `bash` binary differs by OS and user settings. + +```js +var bashPath = require('bash-path'); +console.log(bashPath); +//=> '/usr/local/bin/bash' +``` + +## Windows + +Only works on [Windows 10](https://msdn.microsoft.com/en-us/commandline/wsl/about?f=255&MSPPError=-2147217396) or later. + +## About + +
+Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). + +Please read the [contributing guide](.github/contributing.md) for advice on opening issues, pull requests, and coding standards. + +
+ +
+Running Tests + +Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: + +```sh +$ npm install && npm test +``` + +
+ +
+Building docs + +_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ + +To generate the readme, run the following command: + +```sh +$ npm install -g verbose/verb#dev verb-generate-readme && verb +``` + +
+ +### Author + +**Jon Schlinkert** + +* [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 March 31, 2019._ \ No newline at end of file diff -Nru node-braces-2.0.2/debian/tests/pkg-js/files node-braces-3.0.2/debian/tests/pkg-js/files --- node-braces-2.0.2/debian/tests/pkg-js/files 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/debian/tests/pkg-js/files 2019-09-02 04:34:48.000000000 +0000 @@ -0,0 +1,2 @@ +debian/tests/modules +test diff -Nru node-braces-2.0.2/debian/tests/pkg-js/test node-braces-3.0.2/debian/tests/pkg-js/test --- node-braces-2.0.2/debian/tests/pkg-js/test 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/debian/tests/pkg-js/test 2019-09-02 04:34:48.000000000 +0000 @@ -0,0 +1 @@ +NODE_PATH=debian/tests/modules mocha -R spec diff -Nru node-braces-2.0.2/debian/tests/require node-braces-3.0.2/debian/tests/require --- node-braces-2.0.2/debian/tests/require 2017-12-29 14:19:13.000000000 +0000 +++ node-braces-3.0.2/debian/tests/require 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -#!/bin/sh -set -e -nodejs -e "require('braces');" diff -Nru node-braces-2.0.2/debian/upstream/metadata node-braces-3.0.2/debian/upstream/metadata --- node-braces-2.0.2/debian/upstream/metadata 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/debian/upstream/metadata 2019-09-02 04:34:48.000000000 +0000 @@ -0,0 +1,7 @@ +--- +Archive: GitHub +Bug-Database: https://github.com/jonschlinkert/braces/issues +Contact: https://github.com/jonschlinkert/braces/issues +Name: braces +Repository: https://github.com/jonschlinkert/braces.git +Repository-Browse: https://github.com/jonschlinkert/braces diff -Nru node-braces-2.0.2/debian/watch node-braces-3.0.2/debian/watch --- node-braces-2.0.2/debian/watch 2017-12-29 14:19:13.000000000 +0000 +++ node-braces-3.0.2/debian/watch 2019-09-02 04:34:48.000000000 +0000 @@ -2,4 +2,4 @@ opts=\ dversionmangle=s/\+(debian|dfsg|ds|deb)(\.\d+)?$//,\ filenamemangle=s/.*\/v?([\d\.-]+)\.tar\.gz/node-braces-$1.tar.gz/ \ - https://github.com/jonschlinkert/braces/tags .*/archive/v?([\d\.]+).tar.gz + https://github.com/micromatch/braces/tags .*/archive/v?([\d\.]+).tar.gz diff -Nru node-braces-2.0.2/.editorconfig node-braces-3.0.2/.editorconfig --- node-braces-2.0.2/.editorconfig 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/.editorconfig 2019-04-16 19:50:10.000000000 +0000 @@ -1,13 +1,14 @@ +# http://editorconfig.org/ root = true [*] -indent_style = space -end_of_line = lf charset = utf-8 +end_of_line = lf indent_size = 2 -trim_trailing_whitespace = true +indent_style = space insert_final_newline = true +trim_trailing_whitespace = true [{**/{actual,fixtures,expected,templates}/**,*.md}] trim_trailing_whitespace = false -insert_final_newline = false \ No newline at end of file +insert_final_newline = false diff -Nru node-braces-2.0.2/.eslintrc.json node-braces-3.0.2/.eslintrc.json --- node-braces-2.0.2/.eslintrc.json 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/.eslintrc.json 2019-04-16 19:50:10.000000000 +0000 @@ -1,8 +1,7 @@ { - "ecmaFeatures": { - "modules": true, - "experimentalObjectRestSpread": true - }, + "extends": [ + "eslint:recommended" + ], "env": { "browser": false, @@ -11,6 +10,15 @@ "mocha": true }, + "parserOptions":{ + "ecmaVersion": 9, + "sourceType": "module", + "ecmaFeatures": { + "modules": true, + "experimentalObjectRestSpread": true + } + }, + "globals": { "document": false, "navigator": false, diff -Nru node-braces-2.0.2/examples/comparison.js node-braces-3.0.2/examples/comparison.js --- node-braces-2.0.2/examples/comparison.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/examples/comparison.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -'use strict'; - -var braceExpansion = require('brace-expansion'); -var braces = require('..'); - -console.log('braces'); -console.log(braces('http://any.org/archive{1996..1999}/vol{1..4}/part{a,b,c}.html')); -console.log(braces('http://www.numericals.com/file{1..100..10}.txt')); -console.log(braces('http://www.letters.com/file{a..z..2}.txt')); -console.log(braces('mkdir /usr/local/src/bash/{old,new,dist,bugs}')); -console.log(braces('chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}')); -console.log(); -console.log(); -console.log('braces: {expand: true}'); -console.log(braces('http://any.org/archive{1996..1999}/vol{1..4}/part{a,b,c}.html', {expand: true})); -console.log(braces('http://www.numericals.com/file{1..100..10}.txt', {expand: true})); -console.log(braces('http://www.letters.com/file{a..z..2}.txt', {expand: true})); -console.log(braces('mkdir /usr/local/src/bash/{old,new,dist,bugs}', {expand: true})); -console.log(braces('chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}', {expand: true})); -console.log(); -console.log(); -console.log('brace-expansion'); -console.log(braceExpansion('http://any.org/archive{1996..1999}/vol{1..4}/part{a,b,c}.html')); -console.log(braceExpansion('http://www.numericals.com/file{1..100..10}.txt')); -console.log(braceExpansion('http://www.letters.com/file{a..z..2}.txt')); -console.log(braceExpansion('mkdir /usr/local/src/bash/{old,new,dist,bugs}')); -console.log(braceExpansion('chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}')); - - -console.log(braces('user-{200..300}/project-{a,b,c}-{1..10}')) -//=> 'user-(20[0-9]|2[1-9][0-9]|300)/project-(a|b|c)-([1-9]|10)' -console.log(braces.makeRe('user-{200..300}')) -//=> /^(?:user-(20[0-9]|2[1-9][0-9]|300))$/ diff -Nru node-braces-2.0.2/examples/compile.js node-braces-3.0.2/examples/compile.js --- node-braces-2.0.2/examples/compile.js 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/examples/compile.js 2019-04-16 19:50:10.000000000 +0000 @@ -0,0 +1,6 @@ +'use strict'; + +const compile = require('../lib/compile'); +const parse = require('../lib/parse'); +console.log(compile(parse('{a,b,c}'))); +console.log(compile(parse('{01..09}'))); diff -Nru node-braces-2.0.2/examples/escape.js node-braces-3.0.2/examples/escape.js --- node-braces-2.0.2/examples/escape.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/examples/escape.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -'use strict'; - -var braces = require('..'); -console.log(braces.expand('{1\\.2}')); diff -Nru node-braces-2.0.2/examples/expand.js node-braces-3.0.2/examples/expand.js --- node-braces-2.0.2/examples/expand.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/examples/expand.js 2019-04-16 19:50:10.000000000 +0000 @@ -1,7 +1,24 @@ -'use strict'; -var mm = require('minimatch'); -var braces = require('..'); +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 => { + return cp.execSync(`echo ${input}`).toString().trim().split(' '); +}; -console.log(braces.expand('a/{b,c}/d')); -//=> [ 'a/b/d', 'a/c/d' ] +// const fixture = '{a,{b,c},d}'; +// const fixture = '{a,b}{c,d}{e,f}'; +// const fixture = 'a/{b,c{x,y}d,e}/f'; +// const fixture = '{{a,b}/i,j,k}'; +// const fixture = '{c,d{e,f}g,h}'; +// const fixture = '{{c,d{e,f}g,h}/i,j,k}'; +// const fixture = '{a,b}/{c,d{e,f}g,h}'; +// const fixture = '{{a,b}/{c,d{e,f}g,h}/i,j,k}'; +// const fixture = '{x,y,{a,b,c\\}}'; +const fixture = 'a{,b}c'; +console.log(); +console.log(' FIXTURE:', colors.magenta(fixture)); +console.log(' ACTUAL:', color(expand(parse(fixture)), colors.yellow)); +console.log('EXPECTED:', color(braces(fixture), colors.blue)); +console.log(); diff -Nru node-braces-2.0.2/examples/nested.js node-braces-3.0.2/examples/nested.js --- node-braces-2.0.2/examples/nested.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/examples/nested.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,12 +0,0 @@ -'use strict'; - -var minimatch = require('minimatch'); -var braces = require('..'); - -console.log('braces'); -console.log(braces.makeRe('a{b,c{1..100}/{foo/bar},h}x/z')); -console.log(); -console.log(); -console.log('brace-expansion'); -console.log(minimatch.makeRe('a{b,c{1..100}/{foo/bar},h}x/z')); - diff -Nru node-braces-2.0.2/examples/options.quantifiers.js node-braces-3.0.2/examples/options.quantifiers.js --- node-braces-2.0.2/examples/options.quantifiers.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/examples/options.quantifiers.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -'use strict'; - -var mm = require('minimatch'); -var braces = require('..'); - -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})); -//=> [ 'a/b{1,3}/(x|y|z)' ] -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' ] diff -Nru node-braces-2.0.2/examples/option-transform.js node-braces-3.0.2/examples/option-transform.js --- node-braces-2.0.2/examples/option-transform.js 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/examples/option-transform.js 2019-04-16 19:50:10.000000000 +0000 @@ -0,0 +1,18 @@ +'use strict'; + +const braces = require('..'); +const alpha = braces.expand('x/{a..e}/y', { + transform(code, index) { + // when non-numeric values are passed, "code" is a character code, + return 'foo/' + String.fromCharCode(code) + '-' + 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' ] + +const numeric = braces.expand('{1..5}', { + transform(value, index) { + return 'foo/' + value * 2; + } +}); +console.log(numeric); //=> [ 'foo/2', 'foo/4', 'foo/6', 'foo/8', 'foo/10' ] diff -Nru node-braces-2.0.2/examples/parse.js node-braces-3.0.2/examples/parse.js --- node-braces-2.0.2/examples/parse.js 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/examples/parse.js 2019-04-16 19:50:10.000000000 +0000 @@ -0,0 +1,25 @@ +'use strict'; + +// const input = 'foo/{a,bar/{b,c},d}'; +// const input = 'a/{b,c{x,y}}/d'; +// const input = '{{x,y},/{b,c{x,y}d,e}/f}'; +// const input = '{{a,b}/{b,c{x,y}d,e}/f,x,z}'; +// const input = 'a/{b,c}/d'; +// const ast = parse(input); +// console.log(ast) +// console.log(JSON.stringify(ast.queue)); +// console.log('EXPECTED:', [ 'a/b/f', 'a/cxd/f', 'a/cyd/f', 'a/e/f' ]); +// console.log(JSON.stringify(ast, null, 2)) +// console.log(expand(ast)); +// expand(ast); + +// const sets = parse('foo/{a/b,{c,d,{x..z},e},f}/bar'); +// const sets = parse('{a,{c,d}'); +// console.log(sets.nodes[2]); +// console.log(compile(sets)); + +// const range = parse(']{a..e,z}'); +// console.log(range.nodes[2]); +// console.log(braces.expand(']{a..e,z}')) +// console.log(compile(range)); +// console.log(parse('[abc]')) diff -Nru node-braces-2.0.2/examples/regex.js node-braces-3.0.2/examples/regex.js --- node-braces-2.0.2/examples/regex.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/examples/regex.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -'use strict'; - -var mm = require('minimatch'); -var braces = require('..'); - -// console.log(braces.makeRe('a/b/c/{k,l,m}/d/{w,x,y,z}/d/e', {expand: true})); -// console.log(mm.makeRe('a/b/c/{k,l,m}/d/{w,x,y,z}/d/e')); - -// console.log('braces.makeRe: "foo/{1..20000}/bar/{a..j}/baz"'); -// console.log(braces.makeRe('foo/{1..20000}/bar/{a..j}/baz')); -// console.log(); -// console.log('minimatch.makeRe: "foo/{1..20000}/bar/{a..j}/baz"'); -// console.log(mm.makeRe('foo/{1..20000}/bar/{a..j}/baz')); - -var re = braces.makeRe('a/{foo/bar}/z'); -console.log(re); -console.log(re.test('a/{foo/bar}/z')); diff -Nru node-braces-2.0.2/examples/sequences-steps.js node-braces-3.0.2/examples/sequences-steps.js --- node-braces-2.0.2/examples/sequences-steps.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/examples/sequences-steps.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -'use strict'; - -var mm = require('minimatch'); -var braces = require('..'); - -console.log(braces('{0..10..2}', {expand: true})); -//=> [ '0', '2', '4', '6', '8', '10' ] diff -Nru node-braces-2.0.2/examples.md node-braces-3.0.2/examples.md --- node-braces-2.0.2/examples.md 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/examples.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,60 +0,0 @@ -# Examples - -> Usage examples - -TBC... - -## Sequences - -Letters - -```js -'{a..c}' -//=> ['a', 'b', 'c'] -``` - -Numbers - -```js -'{1..3}' -//=> ['1', '2', '3'] -``` - -### Sequences with steps - -Letters with step: - -```js -'{a..j..2}' -//=> ['b', 'd', 'f', 'h', 'j'] -``` - -Numbers with step: - -```js -'{1..10..2}' -//=> ['2', '4', '6', '8', '10'] -``` - -## Lists - -```js -'{a,b}' -//=> ['a', 'b'] - -'a/{b,c}' -//=> ['a/b', 'a/c'] -``` - -## Nesting - -```js -'a/{b,c/{d,e}}/f' -//=> ['a/b/f', 'a/c/d/f', 'a/c/e/f'] - -'a/{b,c/{d,e}/f,g}/h' -//=> ['a/b/h', 'a/c/d/f/h', 'a/c/e/f/h', 'a/g/h'] - -'a/{b,c/{2..8..2}}/f' -//=> ['a/b/f', 'a/c/2/f', 'a/c/4/f', 'a/c/6/f', 'a/c/8/f'] -``` diff -Nru node-braces-2.0.2/.gitignore node-braces-3.0.2/.gitignore --- node-braces-2.0.2/.gitignore 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/.gitignore 2019-04-16 19:50:10.000000000 +0000 @@ -1,20 +1,30 @@ # always ignore files *.DS_Store +.idea +.vscode *.sublime-* # test related, or directories generated by tests test/actual actual coverage +.nyc* # npm node_modules npm-debug.log +# yarn +yarn.lock +yarn-error.log + # misc _gh_pages +_draft +_drafts bower_components vendor temp tmp TODO.md +package-lock.json \ No newline at end of file diff -Nru node-braces-2.0.2/gulpfile.js node-braces-3.0.2/gulpfile.js --- node-braces-2.0.2/gulpfile.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/gulpfile.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -'use strict'; - -var gulp = require('gulp'); -var mocha = require('gulp-mocha'); -var unused = require('gulp-unused'); -var istanbul = require('gulp-istanbul'); -var eslint = require('gulp-eslint'); - -gulp.task('coverage', function() { - return gulp.src(['index.js', 'lib/*.js']) - .pipe(istanbul()) - .pipe(istanbul.hookRequire()); -}); - -gulp.task('test', ['coverage'], function() { - return gulp.src('test/*.js') - .pipe(mocha({reporter: 'spec'})) - .pipe(istanbul.writeReports()); -}); - -gulp.task('eslint', function() { - return gulp.src(['*.js', 'lib/*.js', 'test/*.js']) - .pipe(eslint()) - .pipe(eslint.format()); -}); - -gulp.task('unused', function() { - return gulp.src(['index.js', 'lib/*.js']) - .pipe(unused({keys: Object.keys(require('./lib/utils.js'))})); -}); - -gulp.task('default', ['test', 'eslint']); diff -Nru node-braces-2.0.2/index.js node-braces-3.0.2/index.js --- node-braces-2.0.2/index.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/index.js 2019-04-16 19:50:10.000000000 +0000 @@ -1,40 +1,17 @@ 'use strict'; -/** - * Module dependencies - */ - -var toRegex = require('to-regex'); -var unique = require('array-unique'); -var extend = require('extend-shallow'); -var debug = require('debug')('braces'); - -/** - * Local dependencies - */ - -var compilers = require('./lib/compilers'); -var parsers = require('./lib/parsers'); -var Braces = require('./lib/braces'); -var utils = require('./lib/utils'); -var MAX_LENGTH = 1024 * 64; - -/** - * Session cache (disable with `options.cache`) - */ - -var cache = {}; +const stringify = require('./lib/stringify'); +const compile = require('./lib/compile'); +const expand = require('./lib/expand'); +const parse = require('./lib/parse'); /** - * Convert the given `braces` pattern into a regex-compatible string. By default, only one string is generated for every input string. Set `options.expand` to true to return an array of patterns (similar to Bash or minimatch. Before using `options.expand`, it's recommended that you read the [performance notes](#performance)). + * Expand the given pattern or create a regex-compatible string. * * ```js - * var braces = require('braces'); - * console.log(braces('{a,b,c}')); - * //=> ['(a|b|c)'] - * - * console.log(braces('{a,b,c}', {expand: true})); - * //=> ['a', 'b', 'c'] + * const braces = require('braces'); + * console.log(braces('{a,b,c}', { compile: true })); //=> ['(a|b|c)'] + * console.log(braces('{a,b,c}')); //=> ['a', 'b', 'c'] * ``` * @param {String} `str` * @param {Object} `options` @@ -42,259 +19,152 @@ * @api public */ -function braces(pattern, options) { - debug('initializing from <%s>', __filename); - - var key = utils.createKey(pattern, options); - options = options || {}; - - if (options.cache !== false && cache.hasOwnProperty(key)) { - return cache[key]; - } - - var results = []; - if (Array.isArray(pattern)) { - for (var i = 0; i < pattern.length; i++) { - results.push.apply(results, braces.create(pattern[i], options)); - } +const braces = (input, options = {}) => { + let output = []; - if (options && options.nodupes === true) { - results = unique(results); + if (Array.isArray(input)) { + for (let pattern of input) { + let result = braces.create(pattern, options); + if (Array.isArray(result)) { + output.push(...result); + } else { + output.push(result); + } } } else { - results = braces.create(pattern, options); + output = [].concat(braces.create(input, options)); } - return (cache[key] = results); -} + if (options && options.expand === true && options.nodupes === true) { + output = [...new Set(output)]; + } + return output; +}; /** - * Expands a brace pattern into an array. This method is called by the main [braces](#braces) function when `options.expand` is true. Before using this method it's recommended that you read the [performance notes](#performance)) and advantages of using [.optimize](#optimize) instead. + * Parse the given `str` with the given `options`. * * ```js - * var braces = require('braces'); - * console.log(braces.expand('a/{b,c}/d')); - * //=> ['a/b/d', 'a/c/d']; + * // braces.parse(pattern, [, options]); + * const ast = braces.parse('a/{b,c}/d'); + * console.log(ast); * ``` - * @param {String} `pattern` Brace pattern - * @param {Object} `options` - * @return {Array} Returns an array of expanded values. + * @param {String} pattern Brace pattern to parse + * @param {Object} options + * @return {Object} Returns an AST * @api public */ -braces.expand = function(pattern, options) { - return braces.create(pattern, extend({}, options, {expand: true})); -}; +braces.parse = (input, options = {}) => parse(input, options); /** - * Expands a brace pattern into a regex-compatible, optimized string. This method is called by the main [braces](#braces) function by default. + * Creates a braces string from an AST, or an AST node. * * ```js - * var braces = require('braces'); - * console.log(braces.expand('a/{b,c}/d')); - * //=> ['a/(b|c)/d'] + * const braces = require('braces'); + * let ast = braces.parse('foo/{a,b}/bar'); + * console.log(stringify(ast.nodes[2])); //=> '{a,b}' * ``` - * @param {String} `pattern` Brace pattern + * @param {String} `input` Brace pattern or AST. * @param {Object} `options` * @return {Array} Returns an array of expanded values. * @api public */ -braces.optimize = function(pattern, options) { - return braces.create(pattern, options); +braces.stringify = (input, options = {}) => { + if (typeof input === 'string') { + return stringify(braces.parse(input, options), options); + } + return stringify(input, options); }; /** - * Processes a brace pattern and returns either an expanded array (if `options.expand` is true), a highly optimized regex-compatible string. This method is called by the main [braces](#braces) function. + * Compiles a brace pattern into a regex-compatible, optimized string. + * This method is called by the main [braces](#braces) function by default. * * ```js - * var braces = require('braces'); - * console.log(braces.create('user-{200..300}/project-{a,b,c}-{1..10}')) - * //=> 'user-(20[0-9]|2[1-9][0-9]|300)/project-(a|b|c)-([1-9]|10)' + * const braces = require('braces'); + * console.log(braces.compile('a/{b,c}/d')); + * //=> ['a/(b|c)/d'] * ``` - * @param {String} `pattern` Brace pattern + * @param {String} `input` Brace pattern or AST. * @param {Object} `options` * @return {Array} Returns an array of expanded values. * @api public */ -braces.create = function(pattern, options) { - if (pattern instanceof RegExp) { - pattern = pattern.source; - } - - if (typeof pattern !== 'string') { - throw new TypeError('expected a string'); - } - - if (pattern.length > MAX_LENGTH) { - throw new Error('expected pattern to be less than ' + MAX_LENGTH + ' characters'); - } - - function create() { - if (pattern === '' || pattern.length <= 2) { - return [pattern]; - } - - if (/^(?:{,})+$/.test(pattern)) { - return []; - } - - var quoted = /^(['"`])(.*)(\1)$/g.exec(pattern); - if (quoted) { - return [quoted[2]]; - } - - var proto = new Braces(options); - var arr = !options || !options.expand - ? proto.optimize(pattern, options) - : proto.expand(pattern, options); - - if (options && options.nodupes === true) { - return unique(arr); - } - - return arr; +braces.compile = (input, options = {}) => { + if (typeof input === 'string') { + input = braces.parse(input, options); } - - return memoize('create', pattern, options, create); + return compile(input, options); }; /** - * Create a regular expression from the given string `pattern`. + * Expands a brace pattern into an array. This method is called by the + * main [braces](#braces) function when `options.expand` is true. Before + * using this method it's recommended that you read the [performance notes](#performance)) + * and advantages of using [.compile](#compile) instead. * * ```js - * var braces = require('braces'); - * console.log(braces.makeRe('user-{200..300}')) - * //=> /^(?:user-(20[0-9]|2[1-9][0-9]|300))$/ + * const braces = require('braces'); + * console.log(braces.expand('a/{b,c}/d')); + * //=> ['a/b/d', 'a/c/d']; * ``` - * @param {String} `pattern` The pattern to convert to regex. + * @param {String} `pattern` Brace pattern * @param {Object} `options` - * @return {RegExp} + * @return {Array} Returns an array of expanded values. * @api public */ -braces.makeRe = function(pattern, options) { - if (pattern instanceof RegExp) { - return pattern; +braces.expand = (input, options = {}) => { + if (typeof input === 'string') { + input = braces.parse(input, options); } - if (typeof pattern !== 'string') { - throw new TypeError('expected a string'); - } + let result = expand(input, options); - if (pattern.length > MAX_LENGTH) { - throw new Error('expected pattern to be less than ' + MAX_LENGTH + ' characters'); + // filter out empty strings if specified + if (options.noempty === true) { + result = result.filter(Boolean); } - function makeRe() { - var arr = braces(pattern, options); - for (var i = 0; i < arr.length; i++) { - arr[i] = arr[i].replace(/([{}])/g, '\\$1'); - } - var opts = extend({strictErrors: false}, options); - return toRegex(arr, opts); + // filter out duplicates if specified + if (options.nodupes === true) { + result = [...new Set(result)]; } - return memoize('makeRe', pattern, options, makeRe); -}; - -/** - * Parse the given `str` with the given `options`. - * - * ```js - * var braces = require('braces'); - * var ast = braces.parse('a/{b,c}/d'); - * console.log(ast); - * // { type: 'root', - * // errors: [], - * // input: 'a/{b,c}/d', - * // nodes: - * // [ { type: 'bos', val: '' }, - * // { type: 'text', val: 'a/' }, - * // { type: 'brace', - * // nodes: - * // [ { type: 'brace.open', val: '{' }, - * // { type: 'text', val: 'b,c' }, - * // { type: 'brace.close', val: '}' } ] }, - * // { type: 'text', val: '/d' }, - * // { type: 'eos', val: '' } ] } - * ``` - * @param {String} `str` - * @param {Object} `options` - * @return {Object} Returns an AST - * @api public - */ - -braces.parse = function(str, options) { - var inst = new Braces(options); - return inst.parse(str, options); + return result; }; /** - * Compile the given `ast` or string with the given `options`. + * Processes a brace pattern and returns either an expanded array + * (if `options.expand` is true), a highly optimized regex-compatible string. + * This method is called by the main [braces](#braces) function. * * ```js - * var braces = require('braces'); - * var ast = braces.parse('a/{b,c}/d'); - * console.log(braces.compile(ast)); - * // { options: { source: 'string' }, - * // state: {}, - * // compilers: - * // { eos: [Function], - * // noop: [Function], - * // bos: [Function], - * // brace: [Function], - * // 'brace.open': [Function], - * // text: [Function], - * // 'brace.close': [Function] }, - * // output: [ 'a/(b|c)/d' ], - * // ast: - * // { ... }, - * // parsingErrors: [] } + * const braces = require('braces'); + * console.log(braces.create('user-{200..300}/project-{a,b,c}-{1..10}')) + * //=> 'user-(20[0-9]|2[1-9][0-9]|300)/project-(a|b|c)-([1-9]|10)' * ``` - * @param {Object|String} `ast` + * @param {String} `pattern` Brace pattern * @param {Object} `options` - * @return {Object} Returns an object that has an `output` property with the compiled string. + * @return {Array} Returns an array of expanded values. * @api public */ -braces.compile = function(ast, options) { - var inst = new Braces(options); - return inst.compile(ast, options); -}; - -/** - * Memoize if `options.cache` is not false - */ - -function memoize(type, pattern, options, fn) { - var key = utils.createKey(type + ':' + pattern, options); - options = options || {}; - - if (options.cache !== false && cache.hasOwnProperty(key)) { - return cache[key]; +braces.create = (input, options = {}) => { + if (input === '' || input.length < 3) { + return [input]; } - var res = fn(pattern, options); - if (options.cache !== false) { - cache[key] = res; - } - return res; -} + return options.expand !== true + ? braces.compile(input, options) + : braces.expand(input, options); +}; /** - * Expose `braces` - * @type {Function} + * Expose "braces" */ module.exports = braces; - -/** - * Expose `Braces` constructor - * @type {Function} - */ - -module.exports.Braces = Braces; -module.exports.compilers = compilers; -module.exports.parsers = parsers; diff -Nru node-braces-2.0.2/lib/braces.js node-braces-3.0.2/lib/braces.js --- node-braces-2.0.2/lib/braces.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/lib/braces.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,133 +0,0 @@ -'use strict'; - -var debug = require('debug')('braces'); -var Snapdragon = require('snapdragon'); -var compilers = require('./compilers'); -var parsers = require('./parsers'); -var utils = require('./utils'); - -/** - * Customize Snapdragon parser and renderer - */ - -function Braces(options) { - debug('initializing from <%s>', __filename); - this.options = utils.extend({}, options); -} - -/** - * Initialize braces - */ - -Braces.prototype.init = function(options) { - var opts = utils.createOptions({}, this.options, options); - this.snapdragon = this.options.snapdragon || new Snapdragon(opts); - this.compiler = this.snapdragon.compiler; - this.parser = this.snapdragon.parser; - - compilers(this.snapdragon); - parsers(this.snapdragon); - - /** - * Call Snapdragon `.parse` method. When AST is returned, we check to - * see if any unclosed braces are left on the stack and, if so, we iterate - * over the stack and correct the AST so that compilers are called in the correct - * order and unbalance braces are properly escaped. - */ - - utils.define(this.snapdragon, 'parse', function(pattern, options) { - var parsed = Snapdragon.prototype.parse.apply(this, arguments); - this.parser.ast.input = pattern; - - var stack = this.parser.stack; - while (stack.length) { - addParent({type: 'brace.close', val: ''}, stack.pop()); - } - - function addParent(node, parent) { - utils.define(node, 'parent', parent); - parent.nodes.push(node); - } - - // add non-enumerable parser reference - utils.define(parsed, 'parser', this.parser); - return parsed; - }); -}; - -/** - * Lazily initialize braces - */ - -Braces.prototype.lazyInit = function(options) { - if (!this.isInitialized) { - this.isInitialized = true; - this.init(options); - } -}; - -/** - * Decorate `.parse` method - */ - -Braces.prototype.parse = function(ast, options) { - if (utils.isObject(ast) && ast.nodes) return ast; - this.lazyInit(options); - return this.snapdragon.parse(ast, options); -}; - -/** - * Decorate `.compile` method - */ - -Braces.prototype.compile = function(ast, options) { - if (typeof ast === 'string') ast = this.parse(ast, options); - this.lazyInit(options); - return this.snapdragon.compile(ast, options); -}; - -/** - * Expand - */ - -Braces.prototype.expand = function(pattern) { - var ast = this.parse(pattern, {expand: true}); - var res = this.compile(ast, {expand: true}); - return res.output; -}; - -/** - * Optimize - */ - -Braces.prototype.optimize = function(pattern) { - var ast = this.parse(pattern, {optimize: true}); - var res = this.compile(ast, {optimize: true}); - return res.output; -}; - -/** - * Visit `node` with the given `fn` - */ - -function visit(node, fn) { - return node.nodes ? mapVisit(node.nodes, fn) : fn(node); -} - -/** - * Map visit over array of `nodes`. - */ - -function mapVisit(nodes, fn) { - var len = nodes.length; - var idx = -1; - while (++idx < len) { - visit(nodes[idx], fn); - } -} - -/** - * Expose `Braces` - */ - -module.exports = Braces; diff -Nru node-braces-2.0.2/lib/compile.js node-braces-3.0.2/lib/compile.js --- node-braces-2.0.2/lib/compile.js 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/lib/compile.js 2019-04-16 19:50:10.000000000 +0000 @@ -0,0 +1,57 @@ +'use strict'; + +const fill = require('fill-range'); +const utils = require('./utils'); + +const compile = (ast, options = {}) => { + let walk = (node, parent = {}) => { + let invalidBlock = utils.isInvalidBrace(parent); + let invalidNode = node.invalid === true && options.escapeInvalid === true; + let invalid = invalidBlock === true || invalidNode === true; + let prefix = options.escapeInvalid === true ? '\\' : ''; + let output = ''; + + if (node.isOpen === true) { + return prefix + node.value; + } + if (node.isClose === true) { + return prefix + node.value; + } + + if (node.type === 'open') { + return invalid ? (prefix + node.value) : '('; + } + + if (node.type === 'close') { + return invalid ? (prefix + node.value) : ')'; + } + + if (node.type === 'comma') { + return node.prev.type === 'comma' ? '' : (invalid ? node.value : '|'); + } + + if (node.value) { + return node.value; + } + + if (node.nodes && node.ranges > 0) { + let args = utils.reduce(node.nodes); + let range = fill(...args, { ...options, wrap: false, toRegex: true }); + + if (range.length !== 0) { + return args.length > 1 && range.length > 1 ? `(${range})` : range; + } + } + + if (node.nodes) { + for (let child of node.nodes) { + output += walk(child, node); + } + } + return output; + }; + + return walk(ast); +}; + +module.exports = compile; diff -Nru node-braces-2.0.2/lib/compilers.js node-braces-3.0.2/lib/compilers.js --- node-braces-2.0.2/lib/compilers.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/lib/compilers.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,270 +0,0 @@ -'use strict'; - -var utils = require('./utils'); - -module.exports = function(braces) { - braces.compiler - - /** - * bos - */ - - .set('bos', function() { - this.ast.queue = isEscaped(this.ast) ? [this.ast.val] : []; - this.ast.count = 1; - }) - - /** - * Square brackets - */ - - .set('bracket', function(node) { - var close = node.close; - var open = !node.escaped ? '[' : '\\['; - var negated = node.negated; - var inner = node.inner; - - inner = inner.replace(/\\(?=[\\\w]|$)/g, '\\\\'); - if (inner === ']-') { - inner = '\\]\\-'; - } - - if (negated && inner.indexOf('.') === -1) { - inner += '.'; - } - if (negated && inner.indexOf('/') === -1) { - inner += '/'; - } - - var val = open + negated + inner + close; - var queue = node.parent.queue; - var last = utils.arrayify(queue.pop()); - - queue.push(utils.join(last, val)); - queue.push.apply(queue, []); - }) - - /** - * Brace - */ - - .set('brace', function(node) { - node.queue = isEscaped(node) ? [node.val] : []; - node.count = 1; - return this.mapVisit(node.nodes); - }) - - /** - * Open - */ - - .set('brace.open', function(node) { - node.parent.open = node.val; - }) - - /** - * Inner - */ - - .set('text', function(node) { - var queue = node.parent.queue; - var segs = [node.val]; - var escaped = node.escaped; - - if (node.multiplier > 1) { - node.parent.count *= node.multiplier; - } - - if (this.options.quantifiers === true && /^(\d,\d|,\d|\d,)$/.test(node.val)) { - escaped = true; - - } else if (node.val.length > 1) { - if (isType(node.parent, 'brace') && !isEscaped(node)) { - var expanded = utils.expand(node.val, this.options); - segs = expanded.segs; - - if (expanded.isOptimized) { - node.parent.isOptimized = true; - } - - // if nothing was expanded, we probably have a literal brace - if (!segs.length) { - var val = (expanded.val || node.val) - // unescape unexpanded brace sequence/set separators - .replace(/\\([,.])/g, '$1') - // strip quotes - .replace(/["']/g, ''); - - segs = [val]; - escaped = true; - } - } - - } else if (node.val === ',') { - if (this.options.expand) { - node.parent.queue.push([]); - segs = ['']; - } else { - segs = ['|']; - } - } else { - escaped = true; - } - - if (escaped && isType(node.parent, 'brace')) { - if (node.parent.nodes.length <= 4 && node.parent.count === 1) { - node.parent.escaped = true; - } else if (node.parent.length <= 3) { - node.parent.escaped = true; - } - } - - if (!hasQueue(node.parent)) { - node.parent.queue = segs; - return; - } - - var last = utils.arrayify(queue.pop()); - if (node.parent.count > 1 && this.options.expand) { - last = multiply(last, node.parent.count); - node.parent.count = 1; - } - - var temp = utils.join(utils.flatten(last), segs.shift()); - queue.push(temp); - queue.push.apply(queue, segs); - }) - - /** - * Close - */ - - .set('brace.close', function(node) { - var queue = node.parent.queue; - var prev = node.parent.parent; - var last = prev.queue.pop(); - var open = node.parent.open; - var close = node.val; - - if (open && close && isOptimized(node, this.options)) { - open = '('; - close = ')'; - } - - // if a close brace exists, and the previous segment is one character - // don't wrap the result in braces or parens - var ele = utils.last(queue); - if (node.parent.count > 1 && this.options.expand) { - ele = multiply(queue.pop(), node.parent.count); - node.parent.count = 1; - queue.push(ele); - } - - if (close && typeof ele === 'string' && ele.length === 1) { - open = ''; - close = ''; - } - - if (isLiteralBrace(node, this.options) || noInner(node)) { - queue.push(utils.join(open, queue.pop() || '')); - queue = utils.flatten(utils.join(queue, close)); - } - - var arr = utils.flatten(utils.join(last, queue)); - prev.queue.push(arr); - }) - - /** - * eos - */ - - .set('eos', function(node) { - if (this.options.optimize !== false) { - this.output = utils.last(utils.flatten(this.ast.queue)); - } else if (Array.isArray(utils.last(this.ast.queue))) { - this.output = utils.flatten(this.ast.queue.pop()); - } else { - this.output = utils.flatten(this.ast.queue); - } - - if (node.parent.count > 1 && this.options.expand) { - this.output = multiply(this.output, node.parent.count); - } - - this.output = utils.arrayify(this.output); - }); - -}; - -/** - * Multiply the segments in the current brace level - */ - -function multiply(queue, n, options) { - return utils.flatten(utils.repeat(utils.arrayify(queue), n)); -} - -/** - * Return true if `node` is escaped - */ - -function isEscaped(node) { - return node.escaped === true; -} - -/** - * Returns true if regex parens should be used for sets. If the parent `type` - * is not `brace`, then we're on a root node, which means we should never - * expand segments and open/close braces should be `{}` (since this indicates - * a brace is missing from the set) - */ - -function isOptimized(node, options) { - if (node.parent.isOptimized) return true; - return isType(node.parent, 'brace') - && !isEscaped(node.parent) - && options.expand !== true; -} - -/** - * Returns true if the value in `node` should be wrapped in a literal brace. - * @return {Boolean} - */ - -function isLiteralBrace(node, options) { - return isEscaped(node.parent) || options.optimize !== false; -} - -/** - * Returns true if the given `node` does not have an inner value. - * @return {Boolean} - */ - -function noInner(node, type) { - if (node.parent.queue.length === 1) { - return true; - } - var nodes = node.parent.nodes; - return nodes.length === 3 - && isType(nodes[0], 'brace.open') - && !isType(nodes[1], 'text') - && isType(nodes[2], 'brace.close'); -} - -/** - * Returns true if the given `node` is the given `type` - * @return {Boolean} - */ - -function isType(node, type) { - return typeof node !== 'undefined' && node.type === type; -} - -/** - * Returns true if the given `node` has a non-empty queue. - * @return {Boolean} - */ - -function hasQueue(node) { - return Array.isArray(node.queue) && node.queue.length; -} diff -Nru node-braces-2.0.2/lib/constants.js node-braces-3.0.2/lib/constants.js --- node-braces-2.0.2/lib/constants.js 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/lib/constants.js 2019-04-16 19:50:10.000000000 +0000 @@ -0,0 +1,57 @@ +'use strict'; + +module.exports = { + MAX_LENGTH: 1024 * 64, + + // Digits + CHAR_0: '0', /* 0 */ + CHAR_9: '9', /* 9 */ + + // Alphabet chars. + CHAR_UPPERCASE_A: 'A', /* A */ + CHAR_LOWERCASE_A: 'a', /* a */ + CHAR_UPPERCASE_Z: 'Z', /* Z */ + CHAR_LOWERCASE_Z: 'z', /* z */ + + CHAR_LEFT_PARENTHESES: '(', /* ( */ + CHAR_RIGHT_PARENTHESES: ')', /* ) */ + + CHAR_ASTERISK: '*', /* * */ + + // Non-alphabetic chars. + CHAR_AMPERSAND: '&', /* & */ + CHAR_AT: '@', /* @ */ + CHAR_BACKSLASH: '\\', /* \ */ + CHAR_BACKTICK: '`', /* ` */ + CHAR_CARRIAGE_RETURN: '\r', /* \r */ + CHAR_CIRCUMFLEX_ACCENT: '^', /* ^ */ + CHAR_COLON: ':', /* : */ + CHAR_COMMA: ',', /* , */ + CHAR_DOLLAR: '$', /* . */ + CHAR_DOT: '.', /* . */ + CHAR_DOUBLE_QUOTE: '"', /* " */ + CHAR_EQUAL: '=', /* = */ + CHAR_EXCLAMATION_MARK: '!', /* ! */ + CHAR_FORM_FEED: '\f', /* \f */ + CHAR_FORWARD_SLASH: '/', /* / */ + CHAR_HASH: '#', /* # */ + CHAR_HYPHEN_MINUS: '-', /* - */ + CHAR_LEFT_ANGLE_BRACKET: '<', /* < */ + CHAR_LEFT_CURLY_BRACE: '{', /* { */ + CHAR_LEFT_SQUARE_BRACKET: '[', /* [ */ + CHAR_LINE_FEED: '\n', /* \n */ + CHAR_NO_BREAK_SPACE: '\u00A0', /* \u00A0 */ + CHAR_PERCENT: '%', /* % */ + CHAR_PLUS: '+', /* + */ + CHAR_QUESTION_MARK: '?', /* ? */ + CHAR_RIGHT_ANGLE_BRACKET: '>', /* > */ + CHAR_RIGHT_CURLY_BRACE: '}', /* } */ + CHAR_RIGHT_SQUARE_BRACKET: ']', /* ] */ + CHAR_SEMICOLON: ';', /* ; */ + CHAR_SINGLE_QUOTE: '\'', /* ' */ + CHAR_SPACE: ' ', /* */ + CHAR_TAB: '\t', /* \t */ + CHAR_UNDERSCORE: '_', /* _ */ + CHAR_VERTICAL_LINE: '|', /* | */ + CHAR_ZERO_WIDTH_NOBREAK_SPACE: '\uFEFF' /* \uFEFF */ +}; diff -Nru node-braces-2.0.2/lib/expand.js node-braces-3.0.2/lib/expand.js --- node-braces-2.0.2/lib/expand.js 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/lib/expand.js 2019-04-16 19:50:10.000000000 +0000 @@ -0,0 +1,113 @@ +'use strict'; + +const fill = require('fill-range'); +const stringify = require('./stringify'); +const utils = require('./utils'); + +const append = (queue = '', stash = '', enclose = false) => { + let result = []; + + queue = [].concat(queue); + stash = [].concat(stash); + + if (!stash.length) return queue; + if (!queue.length) { + return enclose ? utils.flatten(stash).map(ele => `{${ele}}`) : stash; + } + + for (let item of queue) { + if (Array.isArray(item)) { + for (let value of item) { + result.push(append(value, stash, enclose)); + } + } else { + for (let ele of stash) { + if (enclose === true && typeof ele === 'string') ele = `{${ele}}`; + result.push(Array.isArray(ele) ? append(item, ele, enclose) : (item + ele)); + } + } + } + return utils.flatten(result); +}; + +const expand = (ast, options = {}) => { + let rangeLimit = options.rangeLimit === void 0 ? 1000 : options.rangeLimit; + + let walk = (node, parent = {}) => { + node.queue = []; + + let p = parent; + let q = parent.queue; + + while (p.type !== 'brace' && p.type !== 'root' && p.parent) { + p = p.parent; + q = p.queue; + } + + if (node.invalid || node.dollar) { + q.push(append(q.pop(), stringify(node, options))); + return; + } + + if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) { + q.push(append(q.pop(), ['{}'])); + return; + } + + if (node.nodes && node.ranges > 0) { + let args = utils.reduce(node.nodes); + + if (utils.exceedsLimit(...args, options.step, rangeLimit)) { + throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.'); + } + + let range = fill(...args, options); + if (range.length === 0) { + range = stringify(node, options); + } + + q.push(append(q.pop(), range)); + node.nodes = []; + return; + } + + let enclose = utils.encloseBrace(node); + let queue = node.queue; + let block = node; + + while (block.type !== 'brace' && block.type !== 'root' && block.parent) { + block = block.parent; + queue = block.queue; + } + + for (let i = 0; i < node.nodes.length; i++) { + let child = node.nodes[i]; + + if (child.type === 'comma' && node.type === 'brace') { + if (i === 1) queue.push(''); + queue.push(''); + continue; + } + + if (child.type === 'close') { + q.push(append(q.pop(), queue, enclose)); + continue; + } + + if (child.value && child.type !== 'open') { + queue.push(append(queue.pop(), child.value)); + continue; + } + + if (child.nodes) { + walk(child, node); + } + } + + return queue; + }; + + return utils.flatten(walk(ast)); +}; + +module.exports = expand; diff -Nru node-braces-2.0.2/lib/parse.js node-braces-3.0.2/lib/parse.js --- node-braces-2.0.2/lib/parse.js 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/lib/parse.js 2019-04-16 19:50:10.000000000 +0000 @@ -0,0 +1,333 @@ +'use strict'; + +const stringify = require('./stringify'); + +/** + * Constants + */ + +const { + MAX_LENGTH, + CHAR_BACKSLASH, /* \ */ + CHAR_BACKTICK, /* ` */ + CHAR_COMMA, /* , */ + CHAR_DOT, /* . */ + CHAR_LEFT_PARENTHESES, /* ( */ + CHAR_RIGHT_PARENTHESES, /* ) */ + CHAR_LEFT_CURLY_BRACE, /* { */ + CHAR_RIGHT_CURLY_BRACE, /* } */ + CHAR_LEFT_SQUARE_BRACKET, /* [ */ + CHAR_RIGHT_SQUARE_BRACKET, /* ] */ + CHAR_DOUBLE_QUOTE, /* " */ + CHAR_SINGLE_QUOTE, /* ' */ + CHAR_NO_BREAK_SPACE, + CHAR_ZERO_WIDTH_NOBREAK_SPACE +} = require('./constants'); + +/** + * parse + */ + +const parse = (input, options = {}) => { + if (typeof input !== 'string') { + throw new TypeError('Expected a string'); + } + + let opts = options || {}; + let max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; + if (input.length > max) { + throw new SyntaxError(`Input length (${input.length}), exceeds max characters (${max})`); + } + + let ast = { type: 'root', input, nodes: [] }; + let stack = [ast]; + let block = ast; + let prev = ast; + let brackets = 0; + let length = input.length; + let index = 0; + let depth = 0; + let value; + let memo = {}; + + /** + * Helpers + */ + + const advance = () => input[index++]; + const push = node => { + if (node.type === 'text' && prev.type === 'dot') { + prev.type = 'text'; + } + + if (prev && prev.type === 'text' && node.type === 'text') { + prev.value += node.value; + return; + } + + block.nodes.push(node); + node.parent = block; + node.prev = prev; + prev = node; + return node; + }; + + push({ type: 'bos' }); + + while (index < length) { + block = stack[stack.length - 1]; + value = advance(); + + /** + * Invalid chars + */ + + if (value === CHAR_ZERO_WIDTH_NOBREAK_SPACE || value === CHAR_NO_BREAK_SPACE) { + continue; + } + + /** + * Escaped chars + */ + + if (value === CHAR_BACKSLASH) { + push({ type: 'text', value: (options.keepEscaping ? value : '') + advance() }); + continue; + } + + /** + * Right square bracket (literal): ']' + */ + + if (value === CHAR_RIGHT_SQUARE_BRACKET) { + push({ type: 'text', value: '\\' + value }); + continue; + } + + /** + * Left square bracket: '[' + */ + + if (value === CHAR_LEFT_SQUARE_BRACKET) { + brackets++; + + let closed = true; + let next; + + while (index < length && (next = advance())) { + value += next; + + if (next === CHAR_LEFT_SQUARE_BRACKET) { + brackets++; + continue; + } + + if (next === CHAR_BACKSLASH) { + value += advance(); + continue; + } + + if (next === CHAR_RIGHT_SQUARE_BRACKET) { + brackets--; + + if (brackets === 0) { + break; + } + } + } + + push({ type: 'text', value }); + continue; + } + + /** + * Parentheses + */ + + if (value === CHAR_LEFT_PARENTHESES) { + block = push({ type: 'paren', nodes: [] }); + stack.push(block); + push({ type: 'text', value }); + continue; + } + + if (value === CHAR_RIGHT_PARENTHESES) { + if (block.type !== 'paren') { + push({ type: 'text', value }); + continue; + } + block = stack.pop(); + push({ type: 'text', value }); + block = stack[stack.length - 1]; + continue; + } + + /** + * Quotes: '|"|` + */ + + if (value === CHAR_DOUBLE_QUOTE || value === CHAR_SINGLE_QUOTE || value === CHAR_BACKTICK) { + let open = value; + let next; + + if (options.keepQuotes !== true) { + value = ''; + } + + while (index < length && (next = advance())) { + if (next === CHAR_BACKSLASH) { + value += next + advance(); + continue; + } + + if (next === open) { + if (options.keepQuotes === true) value += next; + break; + } + + value += next; + } + + push({ type: 'text', value }); + continue; + } + + /** + * Left curly brace: '{' + */ + + if (value === CHAR_LEFT_CURLY_BRACE) { + depth++; + + let dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true; + let brace = { + type: 'brace', + open: true, + close: false, + dollar, + depth, + commas: 0, + ranges: 0, + nodes: [] + }; + + block = push(brace); + stack.push(block); + push({ type: 'open', value }); + continue; + } + + /** + * Right curly brace: '}' + */ + + if (value === CHAR_RIGHT_CURLY_BRACE) { + if (block.type !== 'brace') { + push({ type: 'text', value }); + continue; + } + + let type = 'close'; + block = stack.pop(); + block.close = true; + + push({ type, value }); + depth--; + + block = stack[stack.length - 1]; + continue; + } + + /** + * Comma: ',' + */ + + if (value === CHAR_COMMA && depth > 0) { + if (block.ranges > 0) { + block.ranges = 0; + let open = block.nodes.shift(); + block.nodes = [open, { type: 'text', value: stringify(block) }]; + } + + push({ type: 'comma', value }); + block.commas++; + continue; + } + + /** + * Dot: '.' + */ + + if (value === CHAR_DOT && depth > 0 && block.commas === 0) { + let siblings = block.nodes; + + if (depth === 0 || siblings.length === 0) { + push({ type: 'text', value }); + continue; + } + + if (prev.type === 'dot') { + block.range = []; + prev.value += value; + prev.type = 'range'; + + if (block.nodes.length !== 3 && block.nodes.length !== 5) { + block.invalid = true; + block.ranges = 0; + prev.type = 'text'; + continue; + } + + block.ranges++; + block.args = []; + continue; + } + + if (prev.type === 'range') { + siblings.pop(); + + let before = siblings[siblings.length - 1]; + before.value += prev.value + value; + prev = before; + block.ranges--; + continue; + } + + push({ type: 'dot', value }); + continue; + } + + /** + * Text + */ + + push({ type: 'text', value }); + } + + // Mark imbalanced braces and brackets as invalid + do { + block = stack.pop(); + + if (block.type !== 'root') { + block.nodes.forEach(node => { + if (!node.nodes) { + if (node.type === 'open') node.isOpen = true; + if (node.type === 'close') node.isClose = true; + if (!node.nodes) node.type = 'text'; + node.invalid = true; + } + }); + + // get the location of the block on parent.nodes (block's siblings) + let parent = stack[stack.length - 1]; + let index = parent.nodes.indexOf(block); + // replace the (invalid) block with it's nodes + parent.nodes.splice(index, 1, ...block.nodes); + } + } while (stack.length > 0); + + push({ type: 'eos' }); + return ast; +}; + +module.exports = parse; diff -Nru node-braces-2.0.2/lib/parsers.js node-braces-3.0.2/lib/parsers.js --- node-braces-2.0.2/lib/parsers.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/lib/parsers.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,238 +0,0 @@ -'use strict'; - -var utils = require('./utils'); -var regexNot = require('regex-not'); -var toRegex = require('to-regex'); - -/** - * Characters to use in negation regex (we want to "not" match - * characters that are matched by other parsers) - */ - -var cached; -var regex = textRegex(); - -/** - * Braces parsers - */ - -module.exports = function(brace) { - brace.parser.sets.brace = brace.parser.sets.brace || []; - brace.parser - - /** - * Brackets: "[...]" (basic, this can be overridden by other parsers) - */ - - .capture('bracket', function() { - var pos = this.position(); - var m = this.match(/^(?:\[([!^]?)([^\]]{2,}|\]\-)(\]|[^*+?]+)|\[)/); - if (!m) return; - - var val = m[0]; - var negated = m[1] ? '^' : ''; - var inner = m[2] || ''; - var close = m[3] || ''; - - var esc = this.input.slice(0, 2); - if (inner === '' && esc === '\\]') { - inner += esc; - this.consume(2); - - var str = this.input; - var idx = -1; - var ch; - - while ((ch = str[++idx])) { - this.consume(1); - if (ch === ']') { - close = ch; - break; - } - inner += ch; - } - } - - return pos({ - type: 'bracket', - val: val, - escaped: close !== ']', - negated: negated, - inner: inner, - close: close - }); - }) - - /** - * Character parsers - */ - - .capture('escape', function() { - var pos = this.position(); - var m = this.match(/^(?:\\(.)|\$\{)/); - if (!m) return; - - var node = pos({ - type: 'text', - multiplier: 1, - val: m[0] - }); - - if (node.val === '\\\\') { - return node; - } - - var chars = {'${': '}', '`': '`', '"': '"'}; - var val = node.val; - if (chars[val]) { - var str = this.input; - var idx = -1; - var ch; - - while ((ch = str[++idx])) { - this.consume(1); - node.val += ch; - if (ch === '\\') { - ch += str[++idx]; - node.val += ch; - } - if (ch === chars[val]) { - break; - } - } - } - - if (this.options.unescape !== false) { - node.val = node.val.replace(/\\([{}])/g, '$1'); - } - - return concatNodes.call(this, pos, node); - }) - - /** - * Open - */ - - .capture('brace.open', function() { - var pos = this.position(); - var m = this.match(/^\{(?!(?:[^\\}]?|,+)\})/); - if (!m) return; - - var prev = this.prev(); - var val = m[0]; - - var open = pos({ - type: 'brace.open', - val: val - }); - - var node = pos({ - type: 'brace', - nodes: [open] - }); - - utils.define(node, 'parent', prev); - utils.define(open, 'parent', node); - this.push('brace', node); - prev.nodes.push(node); - }) - - /** - * Close - */ - - .capture('brace.close', function() { - var pos = this.position(); - var m = this.match(/^\}/); - if (!m || !m[0]) return; - - var brace = this.pop('brace'); - var node = pos({ - type: 'brace.close', - val: m[0] - }); - - if (!this.isType(brace, 'brace')) { - if (this.options.strict) { - throw new Error('missing opening "{"'); - } - node.type = 'text'; - node.multiplier = 1; - node.escaped = true; - return node; - } - - brace.nodes.push(node); - utils.define(node, 'parent', brace); - }) - - /** - * Inner - */ - - .capture('text', function() { - var pos = this.position(); - var m = this.match(regex); - if (!m) return; - - var node = pos({ - type: 'text', - multiplier: 1, - val: m[0] - }); - - return concatNodes.call(this, pos, node); - }); - -}; - -/** - * Combine text nodes, and calculate empty sets (`{,,}`) - * @param {Function} `pos` Function to calculate node position - * @param {Object} `node` AST node - * @return {Object} - */ - -function concatNodes(pos, node) { - var prev = this.prev(); - var last = utils.last(prev.nodes); - var re = /^\{(,+)\}/; - var multi; - - var a = node.val.charAt(0); - var b = node.val.slice(-1); - - if ((a === '"' && b === '"') || (a === '`' && b === '`') || (a === "'" && b === "'")) { - node.val = node.val.slice(1, node.val.length - 1); - node.escaped = true; - } - - if (re.test(node.val)) { - this.input = node.val + this.input; - node.val = ''; - } - - while ((multi = re.exec(this.input))) { - this.consume(multi[0].length); - node.multiplier *= multi[1].length + 1; - } - - if (last.type === 'text' && node.val && node.multiplier === 1 && last.multiplier === 1) { - last.val += node.val; - return; - } - - return node; -} - -/** - * Create and cache regex to use for text nodes - */ - -function textRegex(pattern) { - if (cached) return cached; - var opts = {contains: true, strictClose: false}; - var not = regexNot.create('(\\$?\\{|\\\\.|\\}|[\\[\\]])', opts); - var re = toRegex('^(?:\\{(,+|.?)\\}|' + not + ')', opts); - return (cached = re); -} diff -Nru node-braces-2.0.2/lib/stringify.js node-braces-3.0.2/lib/stringify.js --- node-braces-2.0.2/lib/stringify.js 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/lib/stringify.js 2019-04-16 19:50:10.000000000 +0000 @@ -0,0 +1,32 @@ +'use strict'; + +const utils = require('./utils'); + +module.exports = (ast, options = {}) => { + let stringify = (node, parent = {}) => { + let invalidBlock = options.escapeInvalid && utils.isInvalidBrace(parent); + let invalidNode = node.invalid === true && options.escapeInvalid === true; + let output = ''; + + if (node.value) { + if ((invalidBlock || invalidNode) && utils.isOpenOrClose(node)) { + return '\\' + node.value; + } + return node.value; + } + + if (node.value) { + return node.value; + } + + if (node.nodes) { + for (let child of node.nodes) { + output += stringify(child); + } + } + return output; + }; + + return stringify(ast); +}; + diff -Nru node-braces-2.0.2/lib/utils.js node-braces-3.0.2/lib/utils.js --- node-braces-2.0.2/lib/utils.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/lib/utils.js 2019-04-16 19:50:10.000000000 +0000 @@ -1,253 +1,112 @@ 'use strict'; -var utils = module.exports; - -/** - * Module dependencies - */ - -utils.define = require('define-property'); -utils.extend = require('extend-shallow'); -utils.flatten = require('arr-flatten'); -utils.isObject = require('isobject'); -utils.range = require('fill-range'); -utils.repeat = require('repeat-element'); -utils.unique = require('array-unique'); - -/** - * Create the key to use for memoization. The unique key is generated - * by iterating over the options and concatenating key-value pairs - * to the pattern string. - */ - -utils.createKey = function(pattern, options) { - var key = pattern; - if (typeof options === 'undefined') { - return key; +exports.isInteger = num => { + if (typeof num === 'number') { + return Number.isInteger(num); } - for (var prop in options) { - if (options.hasOwnProperty(prop)) { - key += ';' + prop + '=' + String(options[prop]); - } + if (typeof num === 'string' && num.trim() !== '') { + return Number.isInteger(Number(num)); } - return key; + return false; }; /** - * Normalize options + * Find a node of the given type */ -utils.createOptions = function(options) { - var opts = utils.extend.apply(null, arguments); - if (typeof opts.expand === 'boolean') { - opts.optimize = !opts.expand; - } - if (typeof opts.optimize === 'boolean') { - opts.expand = !opts.optimize; - } - if (opts.optimize === true) { - opts.makeRe = true; - } - return opts; -}; +exports.find = (node, type) => node.nodes.find(node => node.type === type); /** - * Join patterns in `a` to patterns in `b` + * Find a node of the given type */ -utils.join = function(a, b, options) { - options = options || {}; - a = utils.arrayify(a); - b = utils.arrayify(b); - if (!a.length) return b; - if (!b.length) return a; - - var len = a.length; - var idx = -1; - var arr = []; - - while (++idx < len) { - var str = a[idx]; - if (Array.isArray(str)) { - str = str.map(function(ele) { - return utils.join(ele, b); - }); - arr.push(str); - continue; - } - - for (var i = 0; i < b.length; i++) { - if (Array.isArray(b[i])) { - arr.push(utils.join(str, b[i])); - } else { - arr.push(str + b[i]); - } - } - } - return arr; +exports.exceedsLimit = (min, max, step = 1, limit) => { + if (limit === false) return false; + if (!exports.isInteger(min) || !exports.isInteger(max)) return false; + return ((Number(max) - Number(min)) / Number(step)) >= limit; }; /** - * Split the given string on `,` if not escaped. + * Escape the given node with '\\' before node.value */ -utils.split = function(str) { - var segs = str.split(','); - var tok = {rest: ''}; - var res = []; +exports.escapeNode = (block, n = 0, type) => { + let node = block.nodes[n]; + if (!node) return; - while (segs.length) { - var key = segs.shift(); - var next = segs[segs.length - 1]; - var quoted; - - while (key.slice(-1) === '\\' || (quoted = isQuote(key, next))) { - if (quoted) tok.quoted = true; - tok.escaped = true; - var ch = segs.shift(); - if (!ch) break; - key = key.slice(0, -1) + ',' + (quoted ? ch.slice(1) : ch); + if ((type && node.type === type) || node.type === 'open' || node.type === 'close') { + if (node.escaped !== true) { + node.value = '\\' + node.value; + node.escaped = true; } - res.push(key); } - - if (tok.quoted) { - tok.val = res[0]; - } - - tok.segs = res; - return tok; }; -function isDoubleQuote(key, next) { - return key.slice(-1) === '"' && next.charAt(0) === '"'; -} - -function isSingleQuote(key, next) { - return key.slice(-1) === "'" && next.charAt(0) === "'"; -} - -function isQuote(key, next) { - return isDoubleQuote(key, next) || isSingleQuote(key, next); -} - /** - * Expand ranges or sets in the given `pattern`. - * - * @param {String} `str` - * @param {Object} `options` - * @return {Object} + * Returns true if the given brace node should be enclosed in literal braces */ -utils.expand = function(str, options) { - var opts = utils.extend({rangeLimit: 250}, options); - var tok = utils.split(str); - var segs = tok.segs; - - if (segs.length > 1) { - if (opts.optimize === false) { - tok.val = segs[0]; - return tok; - } - - tok.segs = utils.stringify(tok.segs); - } else if (segs.length === 1) { - var arr = str.split('..'); - - if (arr.length === 1) { - tok.val = tok.segs.pop() || tok.val || str; - tok.segs = []; - return tok; - } - - if (arr.length === 2 && arr[0] === arr[1]) { - tok.escaped = true; - tok.val = arr[0]; - tok.segs = []; - return tok; - } - - if (arr.length > 1) { - if (opts.optimize !== false) { - opts.optimize = true; - delete opts.expand; - } - - if (opts.optimize !== true) { - var min = Math.min(arr[0], arr[1]); - var max = Math.max(arr[0], arr[1]); - var step = arr[2] || 1; - if (((max - min) / step) >= opts.rangeLimit) { - opts.optimize = true; - tok.isOptimized = true; - delete opts.expand; - } - } - - arr.push(opts); - tok.segs = utils.range.apply(null, arr); - - if (!tok.segs.length) { - tok.escaped = true; - tok.val = str; - return tok; - } - - if (opts.optimize === true) { - tok.segs = utils.stringify(tok.segs); - } - - if (tok.segs === '') { - tok.val = str; - } else { - tok.val = tok.segs[0]; - } - return tok; - } - } else { - tok.val = str; +exports.encloseBrace = node => { + if (node.type !== 'brace') return false; + if ((node.commas >> 0 + node.ranges >> 0) === 0) { + node.invalid = true; + return true; } - return tok; + return false; }; /** - * Cast `val` to an array. - * @param {*} `val` + * Returns true if a brace node is invalid. */ -utils.stringify = function(arr) { - return [utils.arrayify(arr).join('|')]; +exports.isInvalidBrace = block => { + if (block.type !== 'brace') return false; + if (block.invalid === true || block.dollar) return true; + if ((block.commas >> 0 + block.ranges >> 0) === 0) { + block.invalid = true; + return true; + } + if (block.open !== true || block.close !== true) { + block.invalid = true; + return true; + } + return false; }; /** - * Cast `val` to an array. - * @param {*} `val` + * Returns true if a node is an open or close node */ -utils.arrayify = function(arr) { - if (typeof arr === 'undefined') return []; - return Array.isArray(arr) ? arr : [arr]; +exports.isOpenOrClose = node => { + if (node.type === 'open' || node.type === 'close') { + return true; + } + return node.open === true || node.close === true; }; /** - * Returns true if the given `str` is a non-empty string - * @return {Boolean} + * Reduce an array of text nodes. */ -utils.isString = function(str) { - return str != null && typeof str === 'string'; -}; +exports.reduce = nodes => nodes.reduce((acc, node) => { + if (node.type === 'text') acc.push(node.value); + if (node.type === 'range') node.type = 'text'; + return acc; +}, []); /** - * Get the last element from `array` - * @param {Array} `array` - * @return {*} + * Flatten an array */ -utils.last = function(arr) { - return arr[arr.length - 1]; -}; - -utils.escapeRegex = function(str) { - return str.replace(/\\?([!$^*?()\[\]{}+?/])/g, '\\$1'); +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); + } + return result; + }; + flat(args); + return result; }; diff -Nru node-braces-2.0.2/LICENSE node-braces-3.0.2/LICENSE --- node-braces-2.0.2/LICENSE 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/LICENSE 2019-04-16 19:50:10.000000000 +0000 @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014-2016, Jon Schlinkert. +Copyright (c) 2014-2018, 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 -Nru node-braces-2.0.2/package.json node-braces-3.0.2/package.json --- node-braces-2.0.2/package.json 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/package.json 2019-04-16 19:50:10.000000000 +0000 @@ -1,19 +1,19 @@ { "name": "braces", - "description": "Fast, comprehensive, bash-like brace expansion implemented in JavaScript. Complete support for the Bash 4.3 braces specification, without sacrificing speed.", - "version": "2.0.2", - "homepage": "https://github.com/jonschlinkert/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", + "homepage": "https://github.com/micromatch/braces", "author": "Jon Schlinkert (https://github.com/jonschlinkert)", "contributors": [ - "Brian Woodward (https://github.com/doowb)", + "Brian Woodward (https://twitter.com/doowb)", "Elan Shanker (https://github.com/es128)", "Eugene Sharygin (https://github.com/eush77)", - "hemanth.hm (http://h3manth.com)", - "Jon Schlinkert (http://twitter.com/jonschlinkert)" + "hemanth.hm (http://h3manth.com)", + "Jon Schlinkert (http://twitter.com/jonschlinkert)" ], - "repository": "jonschlinkert/braces", + "repository": "micromatch/braces", "bugs": { - "url": "https://github.com/jonschlinkert/braces/issues" + "url": "https://github.com/micromatch/braces/issues" }, "license": "MIT", "files": [ @@ -22,44 +22,20 @@ ], "main": "index.js", "engines": { - "node": ">=0.10.0" + "node": ">=8" }, "scripts": { - "test": "mocha" + "test": "mocha", + "benchmark": "node benchmark" }, "dependencies": { - "arr-flatten": "^1.0.1", - "array-unique": "^0.3.2", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "fill-range": "^3.0.3", - "isobject": "^2.1.0", - "regex-not": "^1.0.0", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "fill-range": "^7.0.1" }, "devDependencies": { - "ansi-cyan": "^0.1.1", - "benchmarked": "^0.2.5", - "brace-expansion": "^1.1.6", - "cross-spawn": "^4.0.2", - "fs-exists-sync": "^0.1.0", - "gulp": "^3.9.1", - "gulp-eslint": "^3.0.1", - "gulp-format-md": "^0.1.11", - "gulp-istanbul": "^1.1.1", - "gulp-mocha": "^3.0.1", - "gulp-unused": "^0.2.0", - "is-windows": "^0.2.0", - "minimatch": "^3.0.3", - "mocha": "^3.1.2", - "noncharacters": "^1.1.0", - "pretty-bytes": "^4.0.2", - "text-table": "^0.2.0", - "time-diff": "^0.3.1", - "yargs-parser": "^4.0.2" + "ansi-colors": "^3.2.4", + "bash-path": "^2.0.1", + "gulp-format-md": "^2.0.0", + "mocha": "^6.1.1" }, "keywords": [ "alpha", @@ -96,21 +72,6 @@ }, "plugins": [ "gulp-format-md" - ], - "related": { - "list": [ - "expand-brackets", - "extglob", - "fill-range", - "micromatch", - "nanomatch" - ] - }, - "reflinks": [ - "brace-expansion", - "to-regex-range", - "verb", - "verb-generate-readme" ] } } diff -Nru node-braces-2.0.2/README.md node-braces-3.0.2/README.md --- node-braces-2.0.2/README.md 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/README.md 2019-04-16 19:50:10.000000000 +0000 @@ -1,6 +1,8 @@ -# braces [![NPM version](https://img.shields.io/npm/v/braces.svg?style=flat)](https://www.npmjs.com/package/braces) [![NPM monthly downloads](https://img.shields.io/npm/dm/braces.svg?style=flat)](https://npmjs.org/package/braces) [![NPM total downloads](https://img.shields.io/npm/dt/braces.svg?style=flat)](https://npmjs.org/package/braces) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/braces.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/braces) [![Windows Build Status](https://img.shields.io/appveyor/ci/jonschlinkert/braces.svg?style=flat&label=AppVeyor)](https://ci.appveyor.com/project/jonschlinkert/braces) +# braces [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=W8YFZ425KND68) [![NPM version](https://img.shields.io/npm/v/braces.svg?style=flat)](https://www.npmjs.com/package/braces) [![NPM monthly downloads](https://img.shields.io/npm/dm/braces.svg?style=flat)](https://npmjs.org/package/braces) [![NPM total downloads](https://img.shields.io/npm/dt/braces.svg?style=flat)](https://npmjs.org/package/braces) [![Linux Build Status](https://img.shields.io/travis/micromatch/braces.svg?style=flat&label=Travis)](https://travis-ci.org/micromatch/braces) -> Fast, comprehensive, bash-like brace expansion implemented in JavaScript. Complete support for the Bash 4.3 braces specification, without sacrificing speed. +> 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. + +Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support. ## Install @@ -10,54 +12,67 @@ $ npm install --save braces ``` +## v3.0.0 Released!! + +See the [changelog](CHANGELOG.md) for details. + +## Why use braces? + +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. + ## Usage -The main export is a function that takes a brace `pattern` to expand and an `options` object if necessary. +The main export is a function that takes one or more brace `patterns` and `options`. ```js -var braces = require('braces'); -braces(pattern[, options]); -``` +const braces = require('braces'); +// braces(patterns[, options]); -## Highlights +console.log(braces(['{01..05}', '{a..e}'])); +//=> ['(0[1-5])', '([a-e])'] -* **Safer**: Braces isn't [vulnerable to DoS attacks](#braces-is-safe), unlike [brace-expansion](https://github.com/juliangruber/brace-expansion), [minimatch](https://github.com/isaacs/minimatch) and [multimatch](https://github.com/sindresorhus/multimatch) (this not the same [DoS bug](https://medium.com/node-security/minimatch-redos-vulnerability-590da24e6d3c#.jew0b6mpc) that was found in minimatch and multimatch recently) -* **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)**: not only runs fast, but scales well as patterns increase in complexity (other libs don't - see the notes on [performance](#performance)). -* **Organized code base**: with parser and compiler that are easy to maintain and update when edge cases crop up. -* **Well-tested**: 900+ unit tests with thousands of actual patterns tested. Passes 100% of the [minimatch](https://github.com/isaacs/minimatch) and [brace-expansion](https://github.com/juliangruber/brace-expansion) unit tests as well. -* **Optimized braces**: By default returns an optimized string that can be used for creating regular expressions for matching. -* **Expanded braces**: Optionally returns an array (like bash). See a [comparison](#optimized-vs-expanded) between optimized and expanded. +console.log(braces(['{01..05}', '{a..e}'], { expand: true })); +//=> ['01', '02', '03', '04', '05', 'a', 'b', 'c', 'd', 'e'] +``` + +### Brace Expansion vs. Compilation -**Optimized** +By default, brace patterns are compiled into strings that are optimized for creating regular expressions and matching. -Patterns are optimized for regex and matching by default: +**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'])); +//=> [ 'a/(0[1-9]|1[0-9]|20)/b', 'a/([1-5])/b' ] ``` **Expanded** -To expand patterns the same way as Bash or [minimatch](https://github.com/isaacs/minimatch), use the [.expand](#expand) method: +Enable brace expansion by setting the `expand` option to true, or by using [braces.expand()](#expand) (returns an array similar to what you'd expect from Bash, or `echo {1..5}`, or [minimatch](https://github.com/isaacs/minimatch)): ```js -console.log(braces.expand('a/{x,y,z}/b')); +console.log(braces('a/{x,y,z}/b', { expand: true })); //=> ['a/x/b', 'a/y/b', 'a/z/b'] -``` -## Features - -* [lists](#lists): Supports "lists": `a/{b,c}/d` => `['a/b/d', 'a/c/d']` -* [sequences](#sequences): Supports alphabetical or numerical "sequences" (ranges): `{1..3}` => `['1', '2', '3']` -* [steps](#steps): Supports "steps" or increments: `{2..10..2}` => `['2', '4', '6', '8', '10']` -* [escaping](#escaping) -* [options](#options) +console.log(braces.expand('{01..10}')); +//=> ['01','02','03','04','05','06','07','08','09','10'] +``` ### Lists -Uses [fill-range](https://github.com/jonschlinkert/fill-range) for expanding alphabetical or numeric lists: +Expand lists (like Bash "sets"): ```js console.log(braces('a/{foo,bar,baz}/*.js')); @@ -69,21 +84,22 @@ ### Sequences -Uses [fill-range](https://github.com/jonschlinkert/fill-range) for expanding alphabetical or numeric ranges (bash "sequences"): +Expand ranges of characters (like Bash "sequences"): ```js -// padding is not retained when string is optimized -console.log(braces('a{01..03}b')); // ['a([1-3])b'] -console.log(braces('a{1..3}b')); // ['a([1-3])b'] +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'] -console.log(braces.expand('{1..3}')); // ['1', '2', '3'] -console.log(braces.expand('a{01..03}b')); // ['a01b', 'a02b', 'a03b'] -console.log(braces.expand('a{1..3}b')); // ['a1b', 'a2b', 'a3b'] -console.log(braces.expand('{a..c}')); // ['a', 'b', 'c'] -console.log(braces.expand('foo/{a..c}')); // ['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/{001..300}/b')); //=> ['a/(0{2}[1-9]|0[1-9][0-9]|[12][0-9]{2}|300)/b'] ``` -### Steps +See [fill-range](https://github.com/jonschlinkert/fill-range) for all available range-expansion options. + +### Steppped ranges Steps, or increments, may be used with ranges: @@ -101,7 +117,7 @@ Brace patterns may be nested. The results of each expanded string are not sorted, and left to right order is preserved. -**"Expanded" examples** +**"Expanded" braces** ```js console.log(braces.expand('a{b,c,/{x,y}}/e')); @@ -111,7 +127,7 @@ //=> ['a/x/c', 'a/1/c', 'a/2/c', 'a/3/c', 'a/4/c', 'a/5/c', 'a/y/c'] ``` -**"Optimized" examples** +**"Optimized" braces** ```js console.log(braces('a{b,c,/{x,y}}/e')); @@ -125,7 +141,7 @@ **Escaping braces** -Prevent braces from being expanded or evaluted by escaping either the opening or closing brace: +A brace pattern will not be expanded or evaluted if _either the opening or closing brace is escaped_: ```js console.log(braces.expand('a\\{d,c,b}e')); @@ -140,67 +156,66 @@ Commas inside braces may also be escaped: ```js +console.log(braces.expand('a{b\\,c}d')); +//=> ['a{b,c}d'] + console.log(braces.expand('a{d\\,c,b}e')); //=> ['ad,ce', 'abe'] ``` **Single items** -A brace pattern is also considered to be escaped when it contains a single item: +Following bash conventions, a brace pattern is also not expanded when it contains a single character: ```js console.log(braces.expand('a{b}c')); //=> ['a{b}c'] - -console.log(braces.expand('a{b\\,c}d')); -//=> ['a{b,c}d'] ``` ## Options -### options.expand +### options.maxLength -Type: `Boolean` +**Type**: `Number` -Default: `undefined` +**Default**: `65,536` -Generate an "expanded" brace pattern (this option is unncessary with the `.expand` method, which does the same thing). +**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', {expand: true})); -//=> [ 'a/b/d', 'a/c/d' ] +console.log(braces('a/{b,c}/d', { maxLength: 3 })); //=> throws an error ``` -### options.optimize +### options.expand -Type: `Boolean` +**Type**: `Boolean` -Default: `true` +**Default**: `undefined` -Enabled by default. +**Description**: Generate an "expanded" brace pattern (alternatively you can use the `braces.expand()` method, which does the same thing). ```js -console.log(braces('a/{b,c}/d')); -//=> [ 'a/(b|c)/d' ] +console.log(braces('a/{b,c}/d', { expand: true })); +//=> [ 'a/b/d', 'a/c/d' ] ``` ### options.nodupes -Type: `Boolean` +**Type**: `Boolean` -Default: `true` +**Default**: `undefined` -Duplicates are removed by default. To keep duplicates, pass `{nodupes: false}` on the options +**Description**: Remove duplicates from the returned array. ### options.rangeLimit -Type: `Number` +**Type**: `Number` -Default: `250` +**Default**: `1000` -When `braces.expand()` is used, or `options.expand` is true, brace patterns will automatically be [optimized](#optionsoptimize) when the difference between the range minimum and range maximum exceeds the `rangeLimit`. This is to prevent huge ranges from freezing your application. +**Description**: To prevent malicious patterns from being passed by users, an error is thrown when `braces.expand()` is used or `options.expand` is true and the generated range will exceed the `rangeLimit`. -You can set this to any number, or change `options.rangeLimit` to `Inifinity` to disable this altogether. +You can customize `options.rangeLimit` or set it to `Inifinity` to disable this altogether. **Examples** @@ -216,30 +231,45 @@ ### options.transform -Type: `Function` +**Type**: `Function` + +**Default**: `undefined` -Default: `undefined` +**Description**: Customize range expansion. -Customize range expansion. +**Example: Transforming non-numeric values** ```js -var range = braces.expand('x{a..e}y', { - transform: function(str) { - return 'foo' + str; +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' ] +``` -console.log(range); -//=> [ 'xfooay', 'xfooby', 'xfoocy', 'xfoody', 'xfooey' ] +**Example: Transforming numeric values** + +```js +const numeric = braces.expand('{1..5}', { + transform(value) { + // when numeric values are passed, "value" is a number + return 'foo/' + value * 2; + } +}); +console.log(numeric); +//=> [ 'foo/2', 'foo/4', 'foo/6', 'foo/8', 'foo/10' ] ``` ### options.quantifiers -Type: `Boolean` +**Type**: `Boolean` -Default: `undefined` +**Default**: `undefined` -In regular expressions, quanitifiers can be used to specify how many times a token can be repeated. For example, `a{1,3}` will match the letter `a` one to three times. +**Description**: In regular expressions, quanitifiers can be used to specify how many times a token can be repeated. For example, `a{1,3}` will match the letter `a` one to three times. Unfortunately, regex quantifiers happen to share the same syntax as [Bash lists](#lists) @@ -248,7 +278,7 @@ **Examples** ```js -var braces = require('braces'); +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})); @@ -257,230 +287,307 @@ //=> [ 'a/b{1,3}/x', 'a/b{1,3}/y', 'a/b{1,3}/z' ] ``` -## Benchmarks +### options.unescape -### Running benchmarks +**Type**: `Boolean` -Install dev dependencies: +**Default**: `undefined` + +**Description**: Strip backslashes that were used for escaping from the result. + +## What is "brace expansion"? + +Brace expansion is a type of parameter expansion that was made popular by unix shells for generating lists of strings, as well as regex-like matching when used alongside wildcards (globs). + +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 + +
+More about brace expansion (click to expand) + +There are two main types of brace expansion: + +1. **lists**: which are defined using comma-separated values inside curly braces: `{a,b,c}` +2. **sequences**: which are defined using a starting value and an ending value, separated by two dots: `a{1..3}b`. Optionally, a third argument may be passed to define a "step" or increment to use: `a{1..100..10}b`. These are also sometimes referred to as "ranges". + +Here are some example brace patterns to illustrate how they work: + +**Sets** -```bash -npm i -d && npm benchmark +``` +{a,b,c} => a b c +{a,b,c}{1,2} => a1 a2 b1 b2 c1 c2 ``` -### Latest results +**Sequences** -```bash -Benchmarking: (8 of 8) - · combination-nested - · combination - · escaped - · list-basic - · list-multiple - · no-braces - · sequence-basic - · sequence-multiple - -# benchmark/fixtures/combination-nested.js (52 bytes) - brace-expansion x 4,756 ops/sec ±1.09% (86 runs sampled) - braces x 11,202,303 ops/sec ±1.06% (88 runs sampled) - minimatch x 4,816 ops/sec ±0.99% (87 runs sampled) - - fastest is braces - -# benchmark/fixtures/combination.js (51 bytes) - brace-expansion x 625 ops/sec ±0.87% (87 runs sampled) - braces x 11,031,884 ops/sec ±0.72% (90 runs sampled) - minimatch x 637 ops/sec ±0.84% (88 runs sampled) - - fastest is braces - -# benchmark/fixtures/escaped.js (44 bytes) - brace-expansion x 163,325 ops/sec ±1.05% (87 runs sampled) - braces x 10,655,071 ops/sec ±1.22% (88 runs sampled) - minimatch x 147,495 ops/sec ±0.96% (88 runs sampled) - - fastest is braces - -# benchmark/fixtures/list-basic.js (40 bytes) - brace-expansion x 99,726 ops/sec ±1.07% (83 runs sampled) - braces x 10,596,584 ops/sec ±0.98% (88 runs sampled) - minimatch x 100,069 ops/sec ±1.17% (86 runs sampled) - - fastest is braces - -# benchmark/fixtures/list-multiple.js (52 bytes) - brace-expansion x 34,348 ops/sec ±1.08% (88 runs sampled) - braces x 9,264,131 ops/sec ±1.12% (88 runs sampled) - minimatch x 34,893 ops/sec ±0.87% (87 runs sampled) - - fastest is braces - -# benchmark/fixtures/no-braces.js (48 bytes) - brace-expansion x 275,368 ops/sec ±1.18% (89 runs sampled) - braces x 9,134,677 ops/sec ±0.95% (88 runs sampled) - minimatch x 3,755,954 ops/sec ±1.13% (89 runs sampled) - - fastest is braces - -# benchmark/fixtures/sequence-basic.js (41 bytes) - brace-expansion x 5,492 ops/sec ±1.35% (87 runs sampled) - braces x 8,485,034 ops/sec ±1.28% (89 runs sampled) - minimatch x 5,341 ops/sec ±1.17% (87 runs sampled) - - fastest is braces - -# benchmark/fixtures/sequence-multiple.js (51 bytes) - brace-expansion x 116 ops/sec ±0.77% (77 runs sampled) - braces x 9,445,118 ops/sec ±1.32% (84 runs sampled) - minimatch x 109 ops/sec ±1.16% (76 runs sampled) +``` +{1..9} => 1 2 3 4 5 6 7 8 9 +{4..-4} => 4 3 2 1 0 -1 -2 -3 -4 +{1..20..3} => 1 4 7 10 13 16 19 +{a..j} => a b c d e f g h i j +{j..a} => j i h g f e d c b a +{a..z..3} => a d g j m p s v y +``` + +**Combination** - fastest is braces +Sets and sequences can be mixed together or used along with any other strings. + +``` +{a,b,c}{1..3} => a1 a2 a3 b1 b2 b3 c1 c2 c3 +foo/{a,b,c}/bar => foo/a/bar foo/b/bar foo/c/bar ``` -## Performance +The fact that braces can be "expanded" from relatively simple patterns makes them ideal for quickly generating test fixtures, file paths, and similar use cases. -### What's the big deal? +## Brace matching -If you use globbing a lot, whether in your build tool chain or in your application, the speed of the glob matcher not only impacts your experience, but a slow glob matcher can slow everything else down, limitimg what you thought was possible in your application. +In addition to _expansion_, brace patterns are also useful for performing regular-expression-like matching. -### Braces is fast +For example, the pattern `foo/{1..3}/bar` would match any of following strings: -> minimatch gets exponentially slower as patterns increase in complexity, braces does not +``` +foo/1/bar +foo/2/bar +foo/3/bar +``` -Brace patterns are meant to be expanded - at least, if you're using Bash, that is. It's not at all unusual for users to want to use brace patterns for dates or similar ranges. It's also very easy to define a brace pattern that appears to be very simple but in fact is fairly complex. +But not: -For example, here is how generated regex size and processing time compare as patterns increase in complexity: +``` +baz/1/qux +baz/2/qux +baz/3/qux +``` -_(the following results were generated using `braces()` and `minimatch.braceExpand()`)_ +Braces can also be combined with [glob patterns](https://github.com/jonschlinkert/micromatch) to perform more advanced wildcard matching. For example, the pattern `*/{1..3}/*` would match any of following strings: -| **Pattern** | **minimatch** | **braces** | -| --- | --- | --- | -| `{1..9007199254740991}`[1] | N/A (freezes) | `300 B` (12ms 878μs) | -| `{1..10000000}` | `98.9 MB` (20s 193ms 13μs) | `34 B` (11ms 204μs) | -| `{1..1000000}` | `8.89 MB` (1s 838ms 718μs) | `33 B` (1ms 761μs) | -| `{1..100000}` | `789 kB` (181ms 518μs) | `32 B` (1ms 76μs) | -| `{1..10000}` | `68.9 kB` (17ms 436μs) | `31 B` (1ms 382μs) | -| `{1..1000}` | `5.89 kB` (1ms 773μs) | `30 B` (1ms 509μs) | -| `{1..100}` | `491 B` (321μs) | `24 B` (309μs) | -| `{1..10}` | `40 B` (56μs) | `12 B` (333μs) | -| `{1..3}` | `11 B` (80μs) | `9 B` (370μs) | +``` +foo/1/bar +foo/2/bar +foo/3/bar +baz/1/qux +baz/2/qux +baz/3/qux +``` -These numbers are actually pretty small as far as numeric ranges are concerned. Regardless, we shouldn't have to consider such things when creating a glob pattern. The tool should get out of your way and let you be as creative as you want. +## Brace matching pitfalls -### Braces is performant +Although brace patterns offer a user-friendly way of matching ranges or sets of strings, there are also some major disadvantages and potential risks you should be aware of. -Even when brace patterns are fully **expanded**, `braces` is still much faster. +### tldr -_(the following results were generated using `braces.expand()` and `minimatch.braceExpand()`)_ +**"brace bombs"** -| **Pattern** | **minimatch** | **braces** | -| --- | --- | --- | --- | --- | --- | -| `a/{1..10000000}` | `98.9 MB` (19s 754ms 376μs) | `98.9 MB` (5s 734ms 419μs) | -| `a/{1..1000000}` | `8.89 MB` (1s 866ms 968μs) | `8.89 MB` (561ms 594μs) | -| `a/{1..100000}` | `789 kB` (178ms 311μs) | `789 kB` (29ms 823μs) | -| `a/{1..10000}` | `68.9 kB` (17ms 692μs) | `68.9 kB` (2ms 351μs) | -| `a/{1..1000}` | `5.89 kB` (1ms 823μs) | `5.89 kB` (706μs) | -| `a/{1..100}` | `491 B` (609μs) | `491 B` (267μs) | -| `a/{1..10}` | `40 B` (61μs) | `40 B` (636μs) | -| `a/{1..3}` | `11 B` (206μs) | `11 B` (207μs) | +* 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!) -### Why is braces so fast? +For a more detailed explanation with examples, see the [geometric complexity](#geometric-complexity) section. -Braces was built from the ground up to be as performant as possible when matching, using a combination of the following: +### The solution -* **minimizes loops and iterating**: we try to pass over the pattern once to parse it before passing it to the compiler. -* **generates an optimized string**: sequences/ranges are optimized by [to-regex-range](https://github.com/jonschlinkert/to-regex-range), which is not only highly accurate, but produces patterns that are a fraction of the size of patterns generated by other brace expansion libraries, such as Bash and [minimatch](https://github.com/isaacs/minimatch) (via [brace-expansion](https://github.com/juliangruber/brace-expansion)) -* **generates results faster**: can handle even the most complex patterns that cause other implementations like [minimatch](https://github.com/isaacs/minimatch) and Bash to fail. +Jump to the [performance section](#performance) to see how Braces solves this problem in comparison to other libraries. -### Braces is safe +### Geometric complexity -Last, but perhaps most important of all, unlike [brace-expansion](https://github.com/juliangruber/brace-expansion) and [minimatch](https://github.com/isaacs/minimatch), braces will not freeze your application when a user passes a complex brace pattern. +At minimum, brace patterns with sets limited to two elements have quadradic or `O(n^2)` complexity. But the complexity of the algorithm increases exponentially as the number of sets, _and elements per set_, increases, which is `O(n^c)`. -**The trouble with ~~tribbles~~ brace patterns** +For example, the following sets demonstrate quadratic (`O(n^2)`) complexity: -There are unlimited scenarios where brace patterns cause the resulting array to grow geometrically. If you define two brace patterns for example, the result is multiplicative if not exponential. For example, given the pattern `{1..1000}`, we would end up with 1 thousand strings. But if two patterns are given, such as `{1...1000}{1...1000}`, we would end up with 1 million strings. +``` +{1,2}{3,4} => (2X2) => 13 14 23 24 +{1,2}{3,4}{5,6} => (2X2X2) => 135 136 145 146 235 236 245 246 +``` -It's easy to think, "I wouldn't do that", but that's not the point. Even though those example patterns are contrived: +But add an element to a set, and we get a n-fold Cartesian product with `O(n^c)` complexity: -1. it's not uncommon for users to define brace patterns that result in similarly huge strings (consider date ranges `1-2016`, for example, and how easy it might be for someone to also add an alphabetical range if searching records of some kind) -2. we can't control how users define their patterns (and we shouldn't have to care) -3. even if it's uncommon for user to define unwieldy patterns, there is still potential for intentionally exploiting this feature to [cause a DoS](https://en.wikipedia.org/wiki/Denial-of-service_attack) in your application (and given that this is a not-very-technically-advanced method for causing a DoS - e.g. anyone can do it, you should be concerned!) +``` +{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 +``` -**Potential for DoS attacks** +Now, imagine how this complexity grows given that each element is a n-tuple: -Most brace expansion libraries, including Bash, [minimatch](https://github.com/isaacs/minimatch), [multimatch](https://github.com/sindresorhus/multimatch) and [brace-expansion](https://github.com/juliangruber/brace-expansion) are vulnerable to DoS attacks (similar to the [ReDoS bug](https://medium.com/node-security/minimatch-redos-vulnerability-590da24e6d3c#.jew0b6mpc) minimatch had recently). +``` +{1..100}{1..100} => (100X100) => 10,000 elements (38.4 kB) +{1..100}{1..100}{1..100} => (100X100X100) => 1,000,000 elements (5.76 MB) +``` -Braces mitigates this risk in three ways: +Although these examples are clearly contrived, they demonstrate how brace patterns can quickly grow out of control. -1. Braces prevents malicious strings from being used by checking the length of the input strings, as well as generated regex -2. Braces [optimizes](#optimize) the generated result by default, so that only _one output string is generated for every input string_. -3. When [.expand](#expand) or [options.expand](#optionsexpand) are used, braces has checks in place to prevent huge ranges from being (accidentally) created. By default, when more than 250 strings will result from the given pattern, braces will [optimize](#optimize) the result instead of expanding it. You can override this limit of 250 by passing a custom number on [options.rangeLimit](#optionsrangelimit). +**More information** -_(you might also want to consider using [micromatch](https://github.com/jonschlinkert/micromatch) for glob matching, as a safer alternative to minimatch and multimatch)_ +Interested in learning more about brace expansion? -## About +* [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) -### Related projects +
-* [expand-brackets](https://www.npmjs.com/package/expand-brackets): Expand POSIX bracket expressions (character classes) in glob patterns. | [homepage](https://github.com/jonschlinkert/expand-brackets "Expand POSIX bracket expressions (character classes) in glob patterns.") -* [extglob](https://www.npmjs.com/package/extglob): Convert extended globs to regex-compatible strings. Add (almost) the expressive power of regular expressions to… [more](https://github.com/jonschlinkert/extglob) | [homepage](https://github.com/jonschlinkert/extglob "Convert extended globs to regex-compatible strings. Add (almost) the expressive power of regular expressions to glob patterns.") -* [fill-range](https://www.npmjs.com/package/fill-range): Fill in a range of numbers or letters, optionally passing an increment or `step` to… [more](https://github.com/jonschlinkert/fill-range) | [homepage](https://github.com/jonschlinkert/fill-range "Fill in a range of numbers or letters, optionally passing an increment or `step` to use, or create a regex-compatible range with `options.toRegex`") -* [micromatch](https://www.npmjs.com/package/micromatch): Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch. | [homepage](https://github.com/jonschlinkert/micromatch "Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch.") -* [nanomatch](https://www.npmjs.com/package/nanomatch): Fast, minimal glob matcher for node.js. Similar to micromatch, minimatch and multimatch, but complete Bash… [more](https://github.com/jonschlinkert/nanomatch) | [homepage](https://github.com/jonschlinkert/nanomatch "Fast, minimal glob matcher for node.js. Similar to micromatch, minimatch and multimatch, but complete Bash 4.3 wildcard support only (no support for exglobs, posix brackets or braces)") +## Performance -### Contributing +Braces is not only screaming fast, it's also more accurate the other brace expansion libraries. -Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). +### Better algorithms -### Contributors +Fortunately there is a solution to the ["brace bomb" problem](#brace-matching-pitfalls): _don't expand brace patterns into an array when they're used for matching_. + +Instead, convert the pattern into an optimized regular expression. This is easier said than done, and braces is the only library that does this currently. + +**The proof is in the numbers** + +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) | + +### Faster algorithms + +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) | +| `{1..10000}` | `48.89 kB` (2ms 202μs) | `48.89 kB` (13ms 641μs) | +| `{1..1000}` | `3.89 kB` (1ms 796μs) | `3.89 kB` (1ms 958μs) | +| `{1..100}` | `291 B` (424μs) | `291 B` (211μs) | +| `{1..10}` | `20 B` (487μs) | `20 B` (72μs) | +| `{1..3}` | `5 B` (166μs) | `5 B` (27μs) | + +If you'd like to run these comparisons yourself, see [test/support/generate.js](test/support/generate.js). + +## Benchmarks + +### Running benchmarks -| **Commits** | **Contributor**
| -| --- | --- | --- | --- | --- | --- | --- | --- | -| 138 | [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) | +Install dev dependencies: -### Building docs +```bash +npm i -d && npm benchmark +``` -_(This document was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme) (a [verb](https://github.com/verbose/verb) generator), please don't edit the readme directly. Any changes to the readme must be made in [.verb.md](.verb.md).)_ +### Latest results -To generate the readme and API documentation with [verb](https://github.com/verbose/verb): +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) +``` + +## About + +
+Contributing + +Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). + +
+ +
+Running Tests + +Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: ```sh -$ npm install -g verb verb-generate-readme && verb +$ npm install && npm test ``` -### Running tests +
-Install dev dependencies: +
+Building docs + +_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ + +To generate the readme, run the following command: ```sh -$ npm install -d && npm test +$ 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) | + ### Author **Jon Schlinkert** -* [github/jonschlinkert](https://github.com/jonschlinkert) -* [twitter/jonschlinkert](http://twitter.com/jonschlinkert) +* [GitHub Profile](https://github.com/jonschlinkert) +* [Twitter Profile](https://twitter.com/jonschlinkert) +* [LinkedIn Profile](https://linkedin.com/in/jonschlinkert) ### License -Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert). -Released under the [MIT license](https://github.com/jonschlinkert/braces/blob/master/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.2.0, on October 21, 2016._ - -
-
-
    -
  1. this is the largest safe integer allowed in JavaScript. - -
  2. -
-
\ 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._ \ No newline at end of file diff -Nru node-braces-2.0.2/test/bash-compiled-ranges.js node-braces-3.0.2/test/bash-compiled-ranges.js --- node-braces-2.0.2/test/bash-compiled-ranges.js 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/test/bash-compiled-ranges.js 2019-04-16 19:50:10.000000000 +0000 @@ -0,0 +1,203 @@ +'use strict'; + +require('mocha'); +const assert = require('assert').strict; +const bashPath = require('bash-path'); +const cp = require('child_process'); +const braces = require('..'); + +const bash = input => { + return cp.spawnSync(bashPath(), ['-c', `echo ${input}`]) + .stdout.toString() + .split(/\s+/) + .filter(Boolean); +}; + +const equal = (input, expected = bash(input), options) => { + assert.deepEqual(braces.compile(input, options), expected); +}; + +/** + * Bash 4.3 unit tests with `braces.compile()` + */ + +describe('bash ranges - braces.compile()', () => { + const fixtures = [ + ['a{b,c{1..100}/{foo,bar}/,h}x/z', {}, 'a(b|c([1-9]|[1-9][0-9]|100)/(foo|bar)/|h)x/z'], + ['0{1..9} {10..20}', {}, '0([1-9]) (1[0-9]|20)'], + + // should not try to expand ranges with decimals + ['{1.1..2.1}', {}, '{1.1..2.1}'], + ['{1.1..~2.1}', {}, '{1.1..~2.1}'], + + // should escape invalid ranges + ['{1..0f}', {}, '{1..0f}'], + ['{1..10..ff}', {}, '{1..10..ff}'], + ['{1..10.f}', {}, '{1..10.f}'], + ['{1..10f}', {}, '{1..10f}'], + ['{1..20..2f}', {}, '{1..20..2f}'], + ['{1..20..f2}', {}, '{1..20..f2}'], + ['{1..2f..2}', {}, '{1..2f..2}'], + ['{1..ff..2}', {}, '{1..ff..2}'], + ['{1..ff}', {}, '{1..ff}'], + ['{1.20..2}', {}, '{1.20..2}'], + + // should handle weirdly-formed brace expansions (fixed in post-bash-3.1) + ['a-{b{d,e}}-c', {}, 'a-{b(d|e)}-c'], + ['a-{bdef-{g,i}-c', {}, 'a-{bdef-(g|i)-c'], + + // should not expand quoted strings + ['{"klklkl"}{1,2,3}', {}, '{klklkl}(1|2|3)'], + ['{"x,x"}', {}, '{x,x}'], + + // should escaped outer braces in nested non-sets + ['{a-{b,c,d}}', {}, '{a-(b|c|d)}'], + ['{a,{a-{b,c,d}}}', {}, '(a|{a-(b|c|d)})'], + + // should escape imbalanced braces + ['abc{', {}, 'abc{'], + ['{abc{', {}, '{abc{'], + ['{abc', {}, '{abc'], + ['}abc', {}, '}abc'], + ['ab{c', {}, 'ab{c'], + ['{{a,b}', {}, '{(a|b)'], + ['{a,b}}', {}, '(a|b)}'], + ['abcd{efgh', {}, 'abcd{efgh'], + ['a{b{c{d,e}f}gh', {}, 'a{b{c(d|e)f}gh'], + ['a{b{c{d,e}f}g}h', {}, 'a{b{c(d|e)f}g}h'], + ['f{x,y{{g,z}}h}', {}, 'f(x|y{(g|z)}h)'], + ['z{a,b},c}d', {}, 'z(a|b),c}d'], + ['a{b{c{d,e}f{x,y{{g}h', {}, 'a{b{c(d|e)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'], + ['a{b{c{d,e}f{x,y{}g}h', {}, 'a{b{c(d|e)f(x|y{}g)h'], + ['f{x,y{}g}h', {}, 'f(x|y{}g)h'], + ['z{a,b{,c}d', {}, 'z{a,b(|c)d'], + + // should expand numeric ranges + ['a{0..3}d', {}, 'a([0-3])d'], + ['x{10..1}y', {}, 'x([1-9]|10)y'], + ['x{3..3}y', {}, 'x3y'], + ['{1..10}', {}, '([1-9]|10)'], + ['{1..3}', {}, '([1-3])'], + ['{1..9}', {}, '([1-9])'], + ['{10..1}', {}, '([1-9]|10)'], + ['{10..1}y', {}, '([1-9]|10)y'], + ['{3..3}', {}, '3'], + ['{5..8}', {}, '([5-8])'], + + // should expand ranges with negative numbers + ['{-10..-1}', {}, '(-[1-9]|-10)'], + ['{-20..0}', {}, '(-[1-9]|-1[0-9]|-20|0)'], + ['{0..-5}', {}, '(-[1-5]|0)'], + ['{9..-4}', {}, '(-[1-4]|[0-9])'], + + // should expand alphabetical ranges + ['0{1..9}/{10..20}', {}, '0([1-9])/(1[0-9]|20)'], + ['0{a..d}0', {}, '0([a-d])0'], + ['a/{b..d}/e', {}, 'a/([b-d])/e'], + ['{1..f}', {}, '([1-f])'], + ['{a..A}', {}, '([A-a])'], + ['{A..a}', {}, '([A-a])'], + ['{a..e}', {}, '([a-e])'], + ['{A..E}', {}, '([A-E])'], + ['{a..f}', {}, '([a-f])'], + ['{a..z}', {}, '([a-z])'], + ['{E..A}', {}, '([A-E])'], + ['{f..1}', {}, '([1-f])'], + ['{f..a}', {}, '([a-f])'], + ['{f..f}', {}, 'f'], + + // should expand multiple ranges + ['a/{b..d}/e/{f..h}', {}, 'a/([b-d])/e/([f-h])'], + + // should expand numerical ranges - positive and negative + ['{-10..10}', {}, '(-[1-9]|-?10|[0-9])'], + + // HEADS UP! If you're using the `--mm` flag minimatch freezes on these + // should expand large numbers + ['{2147483645..2147483649}', {}, '(214748364[5-9])'], + ['{214748364..2147483649}', {}, '(21474836[4-9]|2147483[7-9][0-9]|214748[4-9][0-9]{2}|214749[0-9]{3}|2147[5-9][0-9]{4}|214[89][0-9]{5}|21[5-9][0-9]{6}|2[2-9][0-9]{7}|[3-9][0-9]{8}|1[0-9]{9}|20[0-9]{8}|21[0-3][0-9]{7}|214[0-6][0-9]{6}|2147[0-3][0-9]{5}|21474[0-7][0-9]{4}|214748[0-2][0-9]{3}|2147483[0-5][0-9]{2}|21474836[0-4][0-9])'], + + // should expand ranges using steps + ['{1..10..1}', { bash: false }, '([1-9]|10)'], + ['{1..10..2}', { bash: false }, '(1|3|5|7|9)'], + ['{1..20..20}', { bash: false }, '1'], + ['{1..20..2}', { bash: false }, '(1|3|5|7|9|11|13|15|17|19)'], + ['{10..1..2}', { bash: false }, '(2|4|6|8|10)'], + ['{100..0..5}', { bash: false }, '(0|5|10|15|20|25|30|35|40|45|50|55|60|65|70|75|80|85|90|95|100)'], + ['{2..10..1}', { bash: false }, '([2-9]|10)'], + ['{2..10..2}', { bash: false }, '(2|4|6|8|10)'], + ['{2..10..3}', { bash: false }, '(2|5|8)'], + + // should expand negative ranges using steps + ['{-1..-10..-2}', { bash: false }, '(-(?:1|3|5|7|9))'], + ['{-1..-10..2}', { bash: false }, '(-(?:1|3|5|7|9))'], + ['{-10..-2..2}', { bash: false }, '(-(?:2|4|6|8|10))'], + ['{-2..-10..1}', { bash: false }, '(-[2-9]|-10)'], + ['{-2..-10..2}', { bash: false }, '(-(?:2|4|6|8|10))'], + ['{-2..-10..3}', { bash: false }, '(-(?:2|5|8))'], + ['{-9..9..3}', { bash: false }, '(0|3|6|9|-(?:3|6|9))'], + ['{10..1..-2}', { bash: false }, '(2|4|6|8|10)'], + ['{100..0..-5}', { bash: false }, '(0|5|10|15|20|25|30|35|40|45|50|55|60|65|70|75|80|85|90|95|100)'], + + // should expand alpha ranges with steps + ['{a..e..2}', { bash: false }, '(a|c|e)'], + ['{E..A..2}', { bash: false }, '(E|C|A)'], + ['{a..z..2}', { bash: false }, '(a|c|e|g|i|k|m|o|q|s|u|w|y)'], + + // should expand alpha ranges with negative steps + ['{z..a..-2}', { bash: false }, '(z|x|v|t|r|p|n|l|j|h|f|d|b)'], + + // unwanted zero-padding (fixed post-bash-4.0) + ['{10..0..2}', { bash: false }, '(0|2|4|6|8|10)'], + ['{10..0..-2}', { bash: false }, '(0|2|4|6|8|10)'], + ['{-50..-0..5}', { bash: false }, '(0|-(?:5|10|15|20|25|30|35|40|45|50))'], + + // should work with dots in file paths + ['../{1..3}/../foo', {}, '../([1-3])/../foo'], + ['../{2..10..2}/../foo', {}, '../(2|4|6|8|10)/../foo'], + ['../{1..3}/../{a,b,c}/foo', {}, '../([1-3])/../(a|b|c)/foo'], + ['./{a..z..3}/', {}, './(a|d|g|j|m|p|s|v|y)/'], + ['./{"x,y"}/{a..z..3}/', { keepQuotes: true }, './{"x,y"}/(a|d|g|j|m|p|s|v|y)/'], + + // should expand a complex combination of ranges and sets + ['a/{x,y}/{1..5}c{d,e}f.{md,txt}', {}, 'a/(x|y)/([1-5])c(d|e)f.(md|txt)'], + + // should expand complex sets and ranges in `bash` mode + ['a/{x,{1..5},y}/c{d}e', {}, 'a/(x|([1-5])|y)/c{d}e'], + + // should treat glob characters as literal + ['**/{1..5}/a.js', {}, '**/([1-5])/a.js'], + ['x{{0..10},braces}y', {}, 'x(([0-9]|10)|braces)y'], + + // should handle sets with invalid ranges + ['{0..10,braces}', {}, '(0..10|braces)'], + ['{1..10,braces}', {}, '(1..10|braces)'], + + ['./\\{x,y}/{a..z..3}/', {}, './{x,y}/(a|d|g|j|m|p|s|v|y)/'], + ['{braces,{0..10}}', {}, '(braces|([0-9]|10))'], + ['{{0..10},braces}', {}, '(([0-9]|10)|braces)'], + ['{{1..10..2},braces}', { bash: false }, '((1|3|5|7|9)|braces)'], + ['{{1..10..2},braces}', {}, '((1|3|5|7|9)|braces)'] + ]; + + fixtures.forEach(arr => { + if (typeof arr === 'string') { + return; + } + + let options = { ...arr[1] }; + let pattern = arr[0]; + let expected = arr[2]; + + if (options.skip === true) { + return; + } + + it('should compile: ' + pattern, () => { + equal(pattern, expected, options); + }); + }); +}); + diff -Nru node-braces-2.0.2/test/bash-compiled-sets.js node-braces-3.0.2/test/bash-compiled-sets.js --- node-braces-2.0.2/test/bash-compiled-sets.js 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/test/bash-compiled-sets.js 2019-04-16 19:50:10.000000000 +0000 @@ -0,0 +1,199 @@ +'use strict'; + +require('mocha'); +const assert = require('assert').strict; +const bashPath = require('bash-path'); +const cp = require('child_process'); +const braces = require('..'); + +const bash = input => { + return cp.spawnSync(bashPath(), ['-c', `echo ${input}`]) + .stdout.toString() + .split(/\s+/) + .filter(Boolean); +}; + +const equal = (input, expected = bash(input), options) => { + assert.deepEqual(braces.compile(input, options), expected); +}; + +/** + * Bash 4.3 unit tests with `braces.expand()` + */ + +describe('bash sets - braces.compile()', () => { + const fixtures = [ + ['{a,b,c,d,e}', {}, '(a|b|c|d|e)'], + ['a/\\{b,c,d,{x,y}}{e,f\\}/g', {}, 'a/{b,c,d,(x|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|f)/g'], + ['a/\\{b,c,d{x,y}}{e,f\\}/g', {}, 'a/{b,c,d(x|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}{e,f}/g', {}, 'a/{(b|c)(e|f)/g'], + ['a/\\{{b,c}{e,f}\\}/g', {}, 'a/{(b|c)(e|f)}/g'], + ['a/\\{{b,c}{e,f}}/g', {}, 'a/{(b|c)(e|f)}/g'], + ['a/b/{b,c,{d,e{f,g},{w,x}/{y,z}}}/h/i', {}, 'a/b/(b|c|(d|e(f|g)|(w|x)/(y|z)))/h/i'], + ['a/{b,c}}{e,f}/g', {}, 'a/(b|c)}(e|f)/g'], + ['a/{b,c\\,d}{e,f}/g', {}, 'a/(b|c,d)(e|f)/g'], + ['a/{b,c\\}}{e,f}/g', {}, 'a/(b|c})(e|f)/g'], + ['a/{b,c}', {}, 'a/(b|c)'], + ['a/{b,c}d{e,f}/g', {}, 'a/(b|c)d(e|f)/g'], + ['a/{b,c}{e,f}/g', {}, 'a/(b|c)(e|f)/g'], + ['a/{b,c}{e,f}{g,h,i}/k', {}, 'a/(b|c)(e|f)(g|h|i)/k'], + ['a/{b,{c,d},e}/f', {}, 'a/(b|(c|d)|e)/f'], + ['a/{b,{c,d}/{e,f},g}/h', {}, 'a/(b|(c|d)/(e|f)|g)/h'], + ['a/{b{c,d},e{f,g}h{i,j}}/k', {}, 'a/(b(c|d)|e(f|g)h(i|j))/k'], + ['a/{b{c,d},e}/f', {}, 'a/(b(c|d)|e)/f'], + ['a/{b{c,d}e{f,g}h{i,j}}/k', {}, 'a/{b(c|d)e(f|g)h(i|j)}/k'], + ['a/{b{c,d}e{f,g},h{i,j}}/k', {}, 'a/(b(c|d)e(f|g)|h(i|j))/k'], + ['a/{x,z}{b,{c,d}/{e,f},g}/h', {}, 'a/(x|z)(b|(c|d)/(e|f)|g)/h'], + ['a/{{a,b}/{c,d}}/z', {}, 'a/{(a|b)/(c|d)}/z'], + ['a/{{b,c}/{d,e}}', {}, 'a/{(b|c)/(d|e)}'], + ['a/{{b,c}/{d,e}}/f', {}, 'a/{(b|c)/(d|e)}/f'], + ['a{b{c{d,e}f{x,y{{g}h', {}, 'a{b{c(d|e)f{x,y{{g}h'], + ['{a,b,{c,d},e}', {}, '(a|b|(c|d)|e)'], + ['{a,b,{c,d}e}', {}, '(a|b|(c|d)e)'], + ['{a,b,{c,d}}', {}, '(a|b|(c|d))'], + ['{a,b{c,d}}', {}, '(a|b(c|d))'], + ['{a,b}/{c,d}', {}, '(a|b)/(c|d)'], + ['{a,b}{c,d}', {}, '(a|b)(c|d)'], + + ['{{a,b},{c,d}}', {}, '((a|b)|(c|d))'], + ['{{a,b}/{c,d}}', {}, '{(a|b)/(c|d)}'], + ['{{a,b}/{c,d}}/z', {}, '{(a|b)/(c|d)}/z'], + + // should not process glob characters + ['{generate,{assemble,update,verb}{file,-generate-*},generator}.js', {}, '(generate|(assemble|update|verb)(file|-generate-*)|generator).js'], + ['**/{foo,bar}.js', {}, '**/(foo|bar).js'], + ['**/{a,b,c}/*.js', {}, '**/(a|b|c)/*.js'], + ['**/{a,b,*}/*.js', {}, '**/(a|b|*)/*.js'], + ['**/{**,b,*}/*.js', {}, '**/(**|b|*)/*.js'], + + // should not expand escaped braces + ['\\{a,b,c,d,e}', {}, '{a,b,c,d,e}'], + ['a/b/c/{x,y\\}', {}, 'a/b/c/{x,y}'], + ['a/\\{x,y}/cde', {}, 'a/{x,y}/cde'], + ['abcd{efgh', {}, 'abcd{efgh'], + ['\\{abc\\}', {}, '{abc}'], + ['{x,y,\\{a,b,c\\}}', {}, '(x|y|{a|b|c})'], + ['{x,y,{a,b,c\\}}', {}, '{x,y,(a|b|c})'], + ['{x,y,{abc},trie}', {}, '(x|y|{abc}|trie)'], + ['x,y,{abc},trie', {}, 'x,y,{abc},trie'], + ['{b{c,d},e}', {}, '(b(c|d)|e)'], + ['{b{c,d},e}/f', {}, '(b(c|d)|e)/f'], + ['{abc}', {}, '{abc}'], + + // 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'], + + // should escape closing braces when open is not defined + ['{a,b}c,d}', {}, '(a|b)c,d}'], + ['a,b,c,d}', {}, 'a,b,c,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{a,b}}c', {}, 'a${b{a,b}}c'], + ['a/{${b},c}/d', {}, 'a/(${b}|c)/d'], + ['a${b,d}/{foo,bar}c', {}, 'a${b,d}/(foo|bar)c'], + + // should not expand escaped commas + ['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|c)/{x,y}/d/e'], + + // should not expand escaped braces + ['{a,b\\}c,d}', {}, '(a|b}c|d)'], + ['a/{z,\\{a,b,c,d,e}/d', {}, 'a/(z|{a|b|c|d|e)/d'], + ['a/\\{b,c}/{d,e}/f', {}, 'a/{b,c}/(d|e)/f'], + + // should not expand escaped braces or commas + ['{x\\,y,\\{abc\\},trie}', {}, '(x,y|{abc}|trie)'], + + // should support sequence brace operators + ['ff{c,b,a}', {}, 'ff(c|b|a)'], + ['f{d,e,f}g', {}, 'f(d|e|f)g'], + ['{a,b,c}', {}, '(a|b|c)'], + ['{l,n,m}xyz', {}, '(l|n|m)xyz'], + + // should expand multiple sets + ['a/{a,b}/{c,d}/e', {}, 'a/(a|b)/(c|d)/e'], + ['a{b,c}d{e,f}g', {}, 'a(b|c)d(e|f)g'], + ['a/{x,y}/c{d,e}f.{md,txt}', {}, 'a/(x|y)/c(d|e)f.(md|txt)'], + + // should expand nested sets + ['{a,b}{{a,b},a,b}', {}, '(a|b)((a|b)|a|b)'], + ['/usr/{ucb/{ex,edit},lib/{ex,how_ex}}', {}, '/usr/(ucb/(ex|edit)|lib/(ex|how_ex))'], + ['a{b,c{d,e}f}g', {}, 'a(b|c(d|e)f)g'], + ['a{{x,y},z}b', {}, 'a((x|y)|z)b'], + ['f{x,y{g,z}}h', {}, 'f(x|y(g|z))h'], + ['a{b,c{d,e},h}x/z', {}, 'a(b|c(d|e)|h)x/z'], + ['a{b,c{d,e},h}x{y,z}', {}, 'a(b|c(d|e)|h)x(y|z)'], + ['a{b,c{d,e},{f,g}h}x{y,z}', {}, 'a(b|c(d|e)|(f|g)h)x(y|z)'], + ['a-{b{d,e}}-c', {}, 'a-{b(d|e)}-c'], + + // should expand not modify non-brace characters + ['a/b/{d,e}/*.js', {}, 'a/b/(d|e)/*.js'], + ['a/**/c/{d,e}/f*.js', {}, 'a/**/c/(d|e)/f*.js'], + ['a/**/c/{d,e}/f*.{md,txt}', {}, 'a/**/c/(d|e)/f*.(md|txt)'], + + // should work with leading and trailing commas + ['a{b,}c', {}, 'a(b|)c'], + ['a{,b}c', {}, 'a(|b)c'], + + // should handle spaces + // Bash 4.3 says the this first one should be equivalent to `foo|(1|2)|bar + // That makes sense in Bash, since ' ' is a separator, but not here. + ['foo {1,2} bar', {}, 'foo (1|2) bar'], + ['a{ ,c{d, },h}x', {}, 'a( |c(d| )|h)x'], + ['a{ ,c{d, },h} ', {}, 'a( |c(d| )|h) '], + + // 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|ejs)'] + ]; + + let seen = new Map(); + let dupes = []; + + for (let i = 0; i < fixtures.length; i++) { + let fixture = fixtures[i]; + + let key = fixture[0] + String(fixture[1].bash); + if (seen.has(key)) { + dupes.push(i + 21, fixture[0]); + } else { + + seen.set(key, i + 21); + } + } + + fixtures.forEach(arr => { + if (typeof arr === 'string') { + return; + } + + let options = { ...arr[1] }; + let pattern = arr[0]; + let expected = arr[2]; + + if (options.skip === true) { + return; + } + + it('should compile: ' + pattern, () => { + equal(pattern, expected, options); + }); + }); +}); + diff -Nru node-braces-2.0.2/test/bash.expanded.js node-braces-3.0.2/test/bash.expanded.js --- node-braces-2.0.2/test/bash.expanded.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/test/bash.expanded.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,411 +0,0 @@ -'use strict'; - -var extend = require('extend-shallow'); -var assert = require('assert'); -var braces = require('..'); - -function match(pattern, expected, options) { - var actual = braces.expand(pattern, options).sort(); - assert.deepEqual(actual, expected.sort(), pattern); -} - -/** - * Bash 4.3 unit tests with `braces.expand()` - */ - -describe('bash.expanded', function() { - var fixtures = [ - [ 'a{b,c{1..50}/{foo,bar,baz}/,g}h/i', {}, [ 'abh/i', 'ac1/bar/h/i', 'ac1/baz/h/i', 'ac1/foo/h/i', 'ac10/bar/h/i', 'ac10/baz/h/i', 'ac10/foo/h/i', 'ac11/bar/h/i', 'ac11/baz/h/i', 'ac11/foo/h/i', 'ac12/bar/h/i', 'ac12/baz/h/i', 'ac12/foo/h/i', 'ac13/bar/h/i', 'ac13/baz/h/i', 'ac13/foo/h/i', 'ac14/bar/h/i', 'ac14/baz/h/i', 'ac14/foo/h/i', 'ac15/bar/h/i', 'ac15/baz/h/i', 'ac15/foo/h/i', 'ac16/bar/h/i', 'ac16/baz/h/i', 'ac16/foo/h/i', 'ac17/bar/h/i', 'ac17/baz/h/i', 'ac17/foo/h/i', 'ac18/bar/h/i', 'ac18/baz/h/i', 'ac18/foo/h/i', 'ac19/bar/h/i', 'ac19/baz/h/i', 'ac19/foo/h/i', 'ac2/bar/h/i', 'ac2/baz/h/i', 'ac2/foo/h/i', 'ac20/bar/h/i', 'ac20/baz/h/i', 'ac20/foo/h/i', 'ac21/bar/h/i', 'ac21/baz/h/i', 'ac21/foo/h/i', 'ac22/bar/h/i', 'ac22/baz/h/i', 'ac22/foo/h/i', 'ac23/bar/h/i', 'ac23/baz/h/i', 'ac23/foo/h/i', 'ac24/bar/h/i', 'ac24/baz/h/i', 'ac24/foo/h/i', 'ac25/bar/h/i', 'ac25/baz/h/i', 'ac25/foo/h/i', 'ac26/bar/h/i', 'ac26/baz/h/i', 'ac26/foo/h/i', 'ac27/bar/h/i', 'ac27/baz/h/i', 'ac27/foo/h/i', 'ac28/bar/h/i', 'ac28/baz/h/i', 'ac28/foo/h/i', 'ac29/bar/h/i', 'ac29/baz/h/i', 'ac29/foo/h/i', 'ac3/bar/h/i', 'ac3/baz/h/i', 'ac3/foo/h/i', 'ac30/bar/h/i', 'ac30/baz/h/i', 'ac30/foo/h/i', 'ac31/bar/h/i', 'ac31/baz/h/i', 'ac31/foo/h/i', 'ac32/bar/h/i', 'ac32/baz/h/i', 'ac32/foo/h/i', 'ac33/bar/h/i', 'ac33/baz/h/i', 'ac33/foo/h/i', 'ac34/bar/h/i', 'ac34/baz/h/i', 'ac34/foo/h/i', 'ac35/bar/h/i', 'ac35/baz/h/i', 'ac35/foo/h/i', 'ac36/bar/h/i', 'ac36/baz/h/i', 'ac36/foo/h/i', 'ac37/bar/h/i', 'ac37/baz/h/i', 'ac37/foo/h/i', 'ac38/bar/h/i', 'ac38/baz/h/i', 'ac38/foo/h/i', 'ac39/bar/h/i', 'ac39/baz/h/i', 'ac39/foo/h/i', 'ac4/bar/h/i', 'ac4/baz/h/i', 'ac4/foo/h/i', 'ac40/bar/h/i', 'ac40/baz/h/i', 'ac40/foo/h/i', 'ac41/bar/h/i', 'ac41/baz/h/i', 'ac41/foo/h/i', 'ac42/bar/h/i', 'ac42/baz/h/i', 'ac42/foo/h/i', 'ac43/bar/h/i', 'ac43/baz/h/i', 'ac43/foo/h/i', 'ac44/bar/h/i', 'ac44/baz/h/i', 'ac44/foo/h/i', 'ac45/bar/h/i', 'ac45/baz/h/i', 'ac45/foo/h/i', 'ac46/bar/h/i', 'ac46/baz/h/i', 'ac46/foo/h/i', 'ac47/bar/h/i', 'ac47/baz/h/i', 'ac47/foo/h/i', 'ac48/bar/h/i', 'ac48/baz/h/i', 'ac48/foo/h/i', 'ac49/bar/h/i', 'ac49/baz/h/i', 'ac49/foo/h/i', 'ac5/bar/h/i', 'ac5/baz/h/i', 'ac5/foo/h/i', 'ac50/bar/h/i', 'ac50/baz/h/i', 'ac50/foo/h/i', 'ac6/bar/h/i', 'ac6/baz/h/i', 'ac6/foo/h/i', 'ac7/bar/h/i', 'ac7/baz/h/i', 'ac7/foo/h/i', 'ac8/bar/h/i', 'ac8/baz/h/i', 'ac8/foo/h/i', 'ac9/bar/h/i', 'ac9/baz/h/i', 'ac9/foo/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,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,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,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/{x,{1..5},y}/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/x/c{d}e', 'a/y/c{d}e' ] ], - [ '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{0..3}d', {}, [ 'a0d', 'a1d', 'a2d', 'a3d' ] ], - [ 'a{b}c', {}, [ 'a{b}c' ] ], - [ 'foo {1,2} bar', {}, [ 'foo 1 bar', 'foo 2 bar' ] ], - [ 'x{10..1}y', {}, [ 'x10y', 'x1y', 'x2y', 'x3y', 'x4y', 'x5y', 'x6y', 'x7y', 'x8y', 'x9y' ] ], - [ 'x{3..3}y', {}, [ 'x3y' ] ], - [ '{ }', {}, [ '{ }' ] ], - [ '{', {}, [ '{' ] ], - [ '{0..10,braces}', {}, [ '0..10', 'braces' ] ], - [ '{10..1}', {}, [ '1', '10', '2', '3', '4', '5', '6', '7', '8', '9' ] ], - [ '{3..3}', {}, [ '3' ] ], - [ '{5..8}', {}, [ '5', '6', '7', '8' ] ], - [ '{9..-4}', {}, [ '-1', '-2', '-3', '-4', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ] ], - [ '{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' ] ], - [ '{{0..10},braces}', {}, [ '0', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', 'braces' ] ], - [ '{{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', {}, [ 'assemble-generate-*.js', 'assemblefile.js', 'generate.js', 'generator.js', 'update-generate-*.js', 'updatefile.js', 'verb-generate-*.js', 'verbfile.js' ] ], - [ '**/{foo,bar}.js', {}, [ '**/bar.js', '**/foo.js' ] ], - [ '**/{1..5}/a.js', {}, [ '**/1/a.js', '**/2/a.js', '**/3/a.js', '**/4/a.js', '**/5/a.js' ] ], - [ '**/{a,b,c}/*.js', {}, [ '**/a/*.js', '**/b/*.js', '**/c/*.js' ] ], - [ '**/{a,b,*}/*.js', {}, [ '**/*/*.js', '**/a/*.js', '**/b/*.js' ] ], - [ '**/{**,b,*}/*.js', {}, [ '**/**/*.js', '**/*/*.js', '**/b/*.js' ] ], - [ '/usr/{ucb/{ex,edit},lib/{ex,how_ex}}', {}, [ '/usr/lib/ex', '/usr/lib/how_ex', '/usr/ucb/edit', '/usr/ucb/ex' ] ], - [ 'ff{c,b,a}', {}, [ 'ffa', 'ffb', 'ffc' ] ], - [ 'f{d,e,f}g', {}, [ 'fdg', 'feg', 'ffg' ] ], - [ 'x{{0..10},braces}y', {}, [ 'x0y', 'x10y', 'x1y', 'x2y', 'x3y', 'x4y', 'x5y', 'x6y', 'x7y', 'x8y', 'x9y', 'xbracesy' ] ], - [ '{a,b,c}', {}, [ 'a', 'b', 'c' ] ], - [ '{braces,{0..10}}', {}, [ '0', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', 'braces' ] ], - [ '{l,n,m}xyz', {}, [ 'lxyz', 'mxyz', 'nxyz' ] ], - [ '{{0..10},braces}', {}, [ '0', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', 'braces' ] ], - [ '{{1..10..2},braces}', {}, [ '1', '3', '5', '7', '9', 'braces' ] ], - [ '{{1..10},braces}', {}, [ '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', 'braces' ] ], - [ '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', 'aa', 'ab', 'ab', 'ba', 'ba', 'bb', 'bb' ] ], - [ '/usr/{ucb/{ex,edit},lib/{ex,how_ex}}', {}, [ '/usr/lib/ex', '/usr/lib/how_ex', '/usr/ucb/edit', '/usr/ucb/ex' ] ], - [ '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 gracefully handle large ranges (`braces` handles these fine,', 'they are tested elsewhere, but they break all the other reference libs)', - - [ '{214748364..2147483649}', { skip: true } ], - [ '{2147483645..2147483649}', { skip: true } ], - - 'should handle invalid sets', - - [ '{0..10,braces}', {}, [ '0..10', 'braces' ] ], - [ '{1..10,braces}', {}, [ '1..10', 'braces' ] ], - - '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/b/d', 'a/c/d', 'a/d/d', 'a/e/d', 'a/z/d', 'a/{a/d' ] ], - [ 'abcd{efgh', {}, [ 'abcd{efgh' ] ], - [ '{a,b\\}c,d}', {}, [ 'a', 'b}c', 'd' ] ], - [ '{abc}', {}, [ '{abc}' ] ], - [ '{x,y,\\{a,b,c\\}}', {}, [ 'b', 'c}', 'x', 'y', '{a' ] ], - [ '{x,y,{a,b,c\\}}', {}, [ '{x,y,a', '{x,y,b', '{x,y,c}' ] ], - [ '{x,y,{abc},trie}', {}, [ 'trie', 'x', 'y', '{abc}' ] ], - [ './\\{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/' ] ], - - 'should not expand escaped commas', - - [ '{x\\,y,\\{abc\\},trie}', {}, [ 'trie', 'x,y', '{abc}' ] ], - [ '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' ] ], - - 'should escape closing braces when open is not defined', - - [ '{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}/barc', 'a${b,d}/fooc' ] ], - - 'should support sequence brace operators', - - [ '/usr/{ucb/{ex,edit},lib/{ex,how_ex}}', {}, [ '/usr/lib/ex', '/usr/lib/how_ex', '/usr/ucb/edit', '/usr/ucb/ex' ] ], - [ 'ff{c,b,a}', {}, [ 'ffa', 'ffb', 'ffc' ] ], - [ 'f{d,e,f}g', {}, [ 'fdg', 'feg', 'ffg' ] ], - [ 'x{{0..10},braces}y', {}, [ 'x0y', 'x10y', 'x1y', 'x2y', 'x3y', 'x4y', 'x5y', 'x6y', 'x7y', 'x8y', 'x9y', 'xbracesy' ] ], - [ '{a,b,c}', {}, [ 'a', 'b', 'c' ] ], - [ '{braces,{0..10}}', {}, [ '0', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', 'braces' ] ], - [ '{l,n,m}xyz', {}, [ 'lxyz', 'mxyz', 'nxyz' ] ], - [ '{{0..10},braces}', {}, [ '0', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', 'braces' ] ], - [ '{{1..10..2},braces}', {}, [ '1', '3', '5', '7', '9', 'braces' ] ], - [ '{{1..10},braces}', {}, [ '1', '10', '2', '3', '4', '5', '6', '7', '8', '9', 'braces' ] ], - - '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' ] ], - - 'should expand nested sets', - - [ '{a,b}{{a,b},a,b}', {}, [ 'aa', 'aa', 'ab', 'ab', 'ba', 'ba', 'bb', 'bb' ] ], - [ '/usr/{ucb/{ex,edit},lib/{ex,how_ex}}', {}, [ '/usr/lib/ex', '/usr/lib/how_ex', '/usr/ucb/edit', '/usr/ucb/ex' ] ], - [ '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 ignore 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/[1-5]/*.js', 'a/b/d/*.js', 'a/b/e/*.js' ] ], - - 'should work with leading and trailing commas', - - [ 'a{b,}c', {}, [ 'abc', 'ac' ] ], - [ 'a{,b}c', {}, [ 'abc', 'ac' ] ], - - 'should handle spaces', - - [ '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{ ,c{d, },h}x', {}, [ 'a x', 'ac x', 'acdx', 'ahx' ] ], - [ 'a{ ,c{d, },h} ', {}, [ 'a ', 'ac ', 'acd ', 'ah ' ] ], - - 'see https://github.com/jonschlinkert/micromatch/issues/66', - - [ '/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.{html,ejs}', {}, [ '/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.ejs', '/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.html' ] ], - - 'should not try to expand ranges with decimals', - - [ '{1.1..2.1}', {}, [ '{1.1..2.1}' ] ], - [ '{1.1..~2.1}', {}, [ '{1.1..~2.1}' ] ], - - 'should escape invalid ranges', - - [ '{1..0f}', {}, [ '{1..0f}' ] ], - [ '{1..10..ff}', {}, [ '{1..10..ff}' ] ], - [ '{1..10.f}', {}, [ '{1..10.f}' ] ], - [ '{1..10f}', {}, [ '{1..10f}' ] ], - [ '{1..20..2f}', {}, [ '{1..20..2f}' ] ], - [ '{1..20..f2}', {}, [ '{1..20..f2}' ] ], - [ '{1..2f..2}', {}, [ '{1..2f..2}' ] ], - [ '{1..ff..2}', {}, [ '{1..ff..2}' ] ], - [ '{1..ff}', {}, [ '{1..ff}' ] ], - [ '{1.20..2}', {}, [ '{1.20..2}' ] ], - - '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' ] ], - - 'should not expand quoted strings', - - [ '{"klklkl"}{1,2,3}', {}, [ '{klklkl}1', '{klklkl}2', '{klklkl}3' ] ], - [ '{"x,x"}', {}, [ '{x,x}' ] ], - - 'should escaped 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}' ] ], - - '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,bcd', 'z{a,bd' ] ], - - 'should expand numeric ranges', - - [ 'a{0..3}d', {}, [ 'a0d', 'a1d', 'a2d', 'a3d' ] ], - [ 'x{10..1}y', {}, [ 'x10y', 'x1y', 'x2y', 'x3y', 'x4y', 'x5y', 'x6y', 'x7y', 'x8y', 'x9y' ] ], - [ 'x{3..3}y', {}, [ 'x3y' ] ], - [ '{1..10}', {}, [ '1', '10', '2', '3', '4', '5', '6', '7', '8', '9' ] ], - [ '{1..3}', {}, [ '1', '2', '3' ] ], - [ '{1..9}', {}, [ '1', '2', '3', '4', '5', '6', '7', '8', '9' ] ], - [ '{10..1}y', {}, [ '10y', '1y', '2y', '3y', '4y', '5y', '6y', '7y', '8y', '9y' ] ], - [ '{3..3}', {}, [ '3' ] ], - [ '{5..8}', {}, [ '5', '6', '7', '8' ] ], - - 'should expand ranges with negative numbers', - - [ '{-10..-1}', {}, [ '-1', '-10', '-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9' ] ], - [ '{-20..0}', {}, [ '-1', '-10', '-11', '-12', '-13', '-14', '-15', '-16', '-17', '-18', '-19', '-2', '-20', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '0' ] ], - [ '{0..-5}', {}, [ '-1', '-2', '-3', '-4', '-5', '0' ] ], - [ '{9..-4}', {}, [ '-1', '-2', '-3', '-4', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ] ], - - 'should expand alphabetical ranges', - - [ '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' ] ], - [ '{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' ] ], - [ '{E..A}', {}, [ 'A', 'B', 'C', 'D', 'E' ] ], - [ '{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}', {}, [ 'a', 'b', 'c', 'd', 'e', 'f' ] ], - [ '{f..f}', {}, [ 'f' ] ], - - 'should expand multiple ranges', - - [ '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' ] ], - - 'should expand numerical ranges - positive and negative', - - [ '{-10..10}', {}, [ '-1', '-10', '-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '0', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9' ] ], - - 'HEADS UP! If you\'re using the `--mm` flag minimatch freezes on these', 'should expand large numbers', - - [ '{2147483645..2147483649}', { minimatch: false, optimize: true }, [ '2147483645', '2147483646', '2147483647', '2147483648', '2147483649' ] ], - [ '{214748364..2147483649}', { minimatch: false, optimize: true }, [ '(21474836[4-9]|2147483[7-9][0-9]|214748[4-9][0-9]{2}|214749[0-9]{3}|2147[5-9][0-9]{4}|214[8-9][0-9]{5}|21[5-9][0-9]{6}|2[2-9][0-9]{7}|[3-9][0-9]{8}|1[0-9]{9}|20[0-9]{8}|21[0-3][0-9]{7}|214[0-6][0-9]{6}|2147[0-3][0-9]{5}|21474[0-7][0-9]{4}|214748[0-2][0-9]{3}|2147483[0-5][0-9]{2}|21474836[0-4][0-9])' ] ], - - 'should expand ranges using steps', - - [ '{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..20}', { optimize: false }, [ '1' ] ], - [ '{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' ] ], - - 'should expand positive ranges with negative steps', - - [ '{10..0..-2}', { optimize: false }, [ '10', '8', '6', '4', '2', '0' ] ], - - 'should expand negative ranges using steps', - - [ '{-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' ] ], - - 'should expand alpha ranges with steps', - - [ '{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' ] ], - - 'should expand alpha ranges with negative steps', - - [ '{z..a..-2}', { optimize: false }, [ 'z', 'x', 'v', 't', 'r', 'p', 'n', 'l', 'j', 'h', 'f', 'd', 'b' ] ], - - 'should handle unwanted zero-padding (fixed post-bash-4.0)', - - [ '{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' ] ], - - 'should work with dots in file paths', - - [ '../{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/' ] ], - - 'should expand a complex combination of ranges and sets', - - [ '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' ] ], - - 'should expand complex sets and ranges in `bash` mode', - - [ 'a/{x,{1..5},y}/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/x/c{d}e', 'a/y/c{d}e' ] ] - ]; - - fixtures.forEach(function(arr) { - if (typeof arr === 'string') { - return; - } - - var options = extend({}, arr[1]); - var pattern = arr[0]; - var expected = arr[2]; - - if (options.skip === true) { - return; - } - - it('should compile: ' + pattern, function() { - match(pattern, expected, options); - }); - }); -}); diff -Nru node-braces-2.0.2/test/bash-expanded-ranges.js node-braces-3.0.2/test/bash-expanded-ranges.js --- node-braces-2.0.2/test/bash-expanded-ranges.js 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/test/bash-expanded-ranges.js 2019-04-16 19:50:10.000000000 +0000 @@ -0,0 +1,317 @@ +'use strict'; + +require('mocha'); +const assert = require('assert').strict; +const bashPath = require('bash-path'); +const cp = require('child_process'); +const braces = require('..'); + +const bash = input => { + return cp.spawnSync(bashPath(), ['-c', `echo ${input}`]) + .stdout.toString() + .split(/\s+/) + .filter(Boolean); +}; + +const equal = (input, expected = bash(input), options) => { + assert.deepEqual(braces.expand(input, options), expected); +}; + +/** + * Bash 4.3 unit tests with `braces.expand()` + */ + +describe('bash - expanded brace ranges', () => { + describe('large numbers', () => { + it('should expand large numbers', () => { + equal('{2147483645..2147483649}', ['2147483645', '2147483646', '2147483647', '2147483648', '2147483649']); + }); + + it('should throw an error when range exceeds rangeLimit', () => { + assert.throws(() => braces.expand('{214748364..2147483649}')); + }); + }); + + describe('escaping / invalid ranges', () => { + it('should not try to expand ranges with decimals', () => { + equal('{1.1..2.1}', ['{1.1..2.1}']); + equal('{1.1..~2.1}', ['{1.1..~2.1}']); + }); + + it('should escape invalid ranges:', () => { + equal('{1..0f}', ['{1..0f}']); + equal('{1..10..ff}', ['{1..10..ff}']); + equal('{1..10.f}', ['{1..10.f}']); + equal('{1..10f}', ['{1..10f}']); + equal('{1..20..2f}', ['{1..20..2f}']); + equal('{1..20..f2}', ['{1..20..f2}']); + equal('{1..2f..2}', ['{1..2f..2}']); + equal('{1..ff..2}', ['{1..ff..2}']); + equal('{1..ff}', ['{1..ff}']); + equal('{1.20..2}', ['{1.20..2}']); + }); + + it('weirdly-formed brace expansions -- fixed in post-bash-3.1', () => { + equal('a-{b{d,e}}-c', ['a-{bd}-c', 'a-{be}-c']); + equal('a-{bdef-{g,i}-c', ['a-{bdef-g-c', 'a-{bdef-i-c']); + }); + + it('should not expand quoted strings.', () => { + equal('{"klklkl"}{1,2,3}', ['{klklkl}1', '{klklkl}2', '{klklkl}3']); + equal('{"x,x"}', ['{x,x}']); + }); + + it('should escaped outer braces in nested non-sets', () => { + equal('{a-{b,c,d}}', ['{a-b}', '{a-c}', '{a-d}']); + equal('{a,{a-{b,c,d}}}', ['a', '{a-b}', '{a-c}', '{a-d}']); + }); + + it('should escape imbalanced braces', () => { + equal('a-{bdef-{g,i}-c', ['a-{bdef-g-c', 'a-{bdef-i-c']); + equal('abc{', ['abc{']); + equal('{abc{', ['{abc{']); + equal('{abc', ['{abc']); + equal('}abc', ['}abc']); + equal('ab{c', ['ab{c']); + equal('ab{c', ['ab{c']); + equal('{{a,b}', ['{a', '{b']); + equal('{a,b}}', ['a}', 'b}']); + equal('abcd{efgh', ['abcd{efgh']); + equal('a{b{c{d,e}f}g}h', ['a{b{cdf}g}h', 'a{b{cef}g}h']); + equal('f{x,y{{g,z}}h}', ['fx', 'fy{g}h', 'fy{z}h']); + equal('z{a,b},c}d', ['za,c}d', 'zb,c}d']); + equal('a{b{c{d,e}f{x,y{{g}h', ['a{b{cdf{x,y{{g}h', 'a{b{cef{x,y{{g}h']); + equal('f{x,y{{g}h', ['f{x,y{{g}h']); + equal('f{x,y{{g}}h', ['f{x,y{{g}}h']); + equal('a{b{c{d,e}f{x,y{}g}h', ['a{b{cdfxh', 'a{b{cdfy{}gh', 'a{b{cefxh', 'a{b{cefy{}gh']); + equal('f{x,y{}g}h', ['fxh', 'fy{}gh']); + equal('z{a,b{,c}d', ['z{a,bd', 'z{a,bcd']); + }); + }); + + describe('positive numeric ranges', () => { + it('should expand numeric ranges', () => { + equal('a{0..3}d', ['a0d', 'a1d', 'a2d', 'a3d']); + equal('x{10..1}y', ['x10y', 'x9y', 'x8y', 'x7y', 'x6y', 'x5y', 'x4y', 'x3y', 'x2y', 'x1y']); + equal('x{3..3}y', ['x3y']); + equal('{1..10}', ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); + equal('{1..3}', ['1', '2', '3']); + equal('{1..9}', ['1', '2', '3', '4', '5', '6', '7', '8', '9']); + equal('{10..1}', ['10', '9', '8', '7', '6', '5', '4', '3', '2', '1']); + equal('{10..1}y', ['10y', '9y', '8y', '7y', '6y', '5y', '4y', '3y', '2y', '1y']); + equal('{3..3}', ['3']); + equal('{5..8}', ['5', '6', '7', '8']); + }); + }); + + describe('negative ranges', () => { + it('should expand ranges with negative numbers', () => { + equal('{-10..-1}', ['-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1']); + equal('{-20..0}', ['-20', '-19', '-18', '-17', '-16', '-15', '-14', '-13', '-12', '-11', '-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1', '0']); + equal('{0..-5}', ['0', '-1', '-2', '-3', '-4', '-5']); + equal('{9..-4}', ['9', '8', '7', '6', '5', '4', '3', '2', '1', '0', '-1', '-2', '-3', '-4']); + }); + }); + + describe('alphabetical ranges', () => { + it('should expand alphabetical ranges', () => { + equal('{a..F}', ['a', '`', '_', '^', ']', '\\', '[', 'Z', 'Y', 'X', 'W', 'V', 'U', 'T', 'S', 'R', 'Q', 'P', 'O', 'N', 'M', 'L', 'K', 'J', 'I', 'H', 'G', 'F']); + equal('0{a..d}0', ['0a0', '0b0', '0c0', '0d0']); + equal('a/{b..d}/e', ['a/b/e', 'a/c/e', 'a/d/e']); + equal('{1..f}', ['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']); + equal('{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']); + equal('{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']); + equal('{a..e}', ['a', 'b', 'c', 'd', 'e']); + equal('{A..E}', ['A', 'B', 'C', 'D', 'E']); + equal('{a..f}', ['a', 'b', 'c', 'd', 'e', 'f']); + equal('{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']); + equal('{E..A}', ['E', 'D', 'C', 'B', 'A']); + equal('{f..1}', ['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']); + equal('{f..a}', ['f', 'e', 'd', 'c', 'b', 'a']); + equal('{f..f}', ['f']); + }); + + it('should expand multiple ranges:', () => { + equal('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']); + }); + }); + + 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('{-10..10}', ['-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); + }); + }); + + describe('steps > positive ranges', () => { + it('should expand ranges using steps:', () => { + equal('{1..10..1}', ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); + equal('{1..10..2}', ['1', '3', '5', '7', '9']); + equal('{1..20..20}', ['1']); + equal('{1..20..2}', ['1', '3', '5', '7', '9', '11', '13', '15', '17', '19']); + equal('{10..0..2}', ['10', '8', '6', '4', '2', '0']); + equal('{10..1..2}', ['10', '8', '6', '4', '2']); + equal('{100..0..5}', ['100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']); + equal('{2..10..1}', ['2', '3', '4', '5', '6', '7', '8', '9', '10']); + equal('{2..10..2}', ['2', '4', '6', '8', '10']); + equal('{2..10..3}', ['2', '5', '8']); + equal('{a..z..2}', ['a', 'c', 'e', 'g', 'i', 'k', 'm', 'o', 'q', 's', 'u', 'w', 'y']); + }); + + it('should expand positive ranges with negative steps:', () => { + equal('{10..0..-2}', ['10', '8', '6', '4', '2', '0']); + }); + }); + + describe('steps > negative ranges', () => { + it('should expand negative ranges using steps:', () => { + equal('{-1..-10..-2}', ['-1', '-3', '-5', '-7', '-9']); + equal('{-1..-10..2}', ['-1', '-3', '-5', '-7', '-9']); + equal('{-10..-2..2}', ['-10', '-8', '-6', '-4', '-2']); + equal('{-2..-10..1}', ['-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '-10']); + equal('{-2..-10..2}', ['-2', '-4', '-6', '-8', '-10']); + equal('{-2..-10..3}', ['-2', '-5', '-8']); + equal('{-50..-0..5}', ['-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0']); + equal('{10..1..-2}', ['10', '8', '6', '4', '2']); + equal('{100..0..-5}', ['100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']); + }); + }); + + describe('steps > alphabetical ranges', () => { + it('should expand alpha ranges with steps', () => { + equal('{a..e..2}', ['a', 'c', 'e']); + equal('{E..A..2}', ['E', 'C', 'A']); + equal('{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']); + equal('{a..z..2}', ['a', 'c', 'e', 'g', 'i', 'k', 'm', 'o', 'q', 's', 'u', 'w', 'y']); + equal('{z..a..-2}', ['z', 'x', 'v', 't', 'r', 'p', 'n', 'l', 'j', 'h', 'f', 'd', 'b']); + }); + + it('should expand alpha ranges with negative steps', () => { + equal('{z..a..-2}', ['z', 'x', 'v', 't', 'r', 'p', 'n', 'l', 'j', 'h', 'f', 'd', 'b']); + }); + }); + + describe('padding', () => { + it('unwanted zero-padding -- fixed post-bash-4.0', () => { + equal('{10..0..2}', ['10', '8', '6', '4', '2', '0']); + equal('{10..0..-2}', ['10', '8', '6', '4', '2', '0']); + equal('{-50..-0..5}', ['-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0']); + }); + }); + + describe('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{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']], + ['{0..10,braces}', {}, ['0..10', 'braces']], + ['{3..3}', {}, ['3']], + ['{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'] ], + ['{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']], + ['{{1..10},braces}', {}, ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'braces']], + ['{1.1..2.1}', {}, ['{1.1..2.1}']], + ['{1.1..~2.1}', {}, ['{1.1..~2.1}']], + ['{1..0f}', {}, ['{1..0f}']], + ['{1..10..ff}', {}, ['{1..10..ff}']], + ['{1..10.f}', {}, ['{1..10.f}']], + ['{1..10f}', {}, ['{1..10f}']], + ['{1..20..2f}', {}, ['{1..20..2f}']], + ['{1..20..f2}', {}, ['{1..20..f2}']], + ['{1..2f..2}', {}, ['{1..2f..2}']], + ['{1..ff..2}', {}, ['{1..ff..2}']], + ['{1..ff}', {}, ['{1..ff}']], + ['{1.20..2}', {}, ['{1.20..2}']], + ['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']], + ['{1..10}', {}, ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']], + ['{1..3}', {}, ['1', '2', '3']], + ['{1..9}', {}, ['1', '2', '3', '4', '5', '6', '7', '8', '9']], + ['{10..1}y', {}, ['10y', '9y', '8y', '7y', '6y', '5y', '4y', '3y', '2y', '1y']], + ['{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'] ], + ['{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{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'] ], + ['{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'] ], + ['{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..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'] ], + ['../{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/'] ], + ['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']] + ]; + + fixtures.forEach(arr => { + if (typeof arr === 'string') { + return; + } + + let options = { ...arr[1] }; + let pattern = arr[0]; + let expected = arr[2]; + + if (options.skip !== true) { + it('should compile: ' + pattern, () => equal(pattern, expected, options)); + } + }); + }); +}); diff -Nru node-braces-2.0.2/test/bash-expanded-sets.js node-braces-3.0.2/test/bash-expanded-sets.js --- node-braces-2.0.2/test/bash-expanded-sets.js 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/test/bash-expanded-sets.js 2019-04-16 19:50:10.000000000 +0000 @@ -0,0 +1,241 @@ +'use strict'; + +require('mocha'); +const assert = require('assert').strict; +const bashPath = require('bash-path'); +const cp = require('child_process'); +const braces = require('..'); + +const bash = input => { + return cp.spawnSync(bashPath(), ['-c', `echo ${input}`]) + .stdout.toString() + .split(/\s+/) + .filter(Boolean); +}; + +const equal = (input, expected = bash(input), options) => { + assert.deepEqual(braces.expand(input, options), expected); +}; + +/** + * Bash 4.3 unit tests with `braces.expand()` + */ + +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' ] ], + [ '{}', {}, [ '{}' ] ], + + // // 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' ] ], + + // '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}' ] ], + + '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' ] ], + + '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' ] ], + + 'should escape closing braces when open is not defined', + + [ '{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' ] ], + + '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' ] ], + + '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' ] ], + + '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' ] ], + + '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' ] ], + + 'should work with leading and trailing commas', + [ '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 ' ] ], + + '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' ] ], + + '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' ] ], + + // '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\'}' ] ], + + '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}' ] ], + + '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' ] ] + ]; + + fixtures.forEach(arr => { + if (typeof arr === 'string') { + return; + } + + let options = { ...arr[1] }; + let pattern = arr[0]; + let expected = arr[2]; + + if (options.skip !== true) { + it('should compile: ' + pattern, () => equal(pattern, expected, options)); + } + }); +}); diff -Nru node-braces-2.0.2/test/bash.optimized.js node-braces-3.0.2/test/bash.optimized.js --- node-braces-2.0.2/test/bash.optimized.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/test/bash.optimized.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,409 +0,0 @@ -'use strict'; - -var extend = require('extend-shallow'); -var assert = require('assert'); -var braces = require('..'); - -function match(pattern, expected, options) { - var actual = braces.optimize(pattern, options).sort(); - assert.deepEqual(actual, expected.sort(), pattern); -} - -/** - * Bash 4.3 unit tests with `braces.optimize()` - */ - -describe('bash.expanded', function() { - var fixtures = [ - ['a{b,c{1..100}/{foo,bar}/,h}x/z', {}, ['a(b|c([1-9]|[1-9][0-9]|100)/(foo|bar)/|h)x/z']], - ['0{1..9} {10..20}', {}, ['0([1-9]) (1[0-9]|20)']], - ['{a,b,c,d,e}', {}, ['(a|b|c|d|e)']], - ['\\{a,b,c,d,e}', {}, ['{a,b,c,d,e}']], - ['a${b}c', {}, ['a${b}c']], - ['a/\\{b,c,d,{x,y}}{e,f\\}/g', {}, ['a/{b,c,d,(x|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|f)/g']], - ['a/\\{b,c,d{x,y}}{e,f\\}/g', {}, ['a/{b,c,d(x|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/\\{x,y}/cde', {}, ['a/{x,y}/cde']], - ['a/\\{{b,c}{e,f}/g', {}, ['a/{(b|c)(e|f)/g']], - ['a/\\{{b,c}{e,f}\\}/g', {}, ['a/{(b|c)(e|f)}/g']], - ['a/\\{{b,c}{e,f}}/g', {}, ['a/{(b|c)(e|f)}/g']], - ['a/b/c/{x,y\\}', {}, ['a/b/c/{x,y}']], - ['a/b/c{d}e', {}, ['a/b/c{d}e']], - ['a/b/{b,c,{d,e{f,g},{w,x}/{y,z}}}/h/i', {}, ['a/b/(b|c|(d|e(f|g)|(w|x)/(y|z)))/h/i']], - ['a/{${b},c}/d', {}, ['a/(${b}|c)/d']], - ['a/{b,c}}{e,f}/g', {}, ['a/(b|c)}(e|f)/g']], - ['a/{b,c\\,d}{e,f}/g', {}, ['a/(b|c,d)(e|f)/g']], - ['a/{b,c\\}}{e,f}/g', {}, ['a/(b|c})(e|f)/g']], - ['a/{b,c}', {}, ['a/(b|c)']], - ['a/{b,c}d{e,f}/g', {}, ['a/(b|c)d(e|f)/g']], - ['a/{b,c}{e,f}/g', {}, ['a/(b|c)(e|f)/g']], - ['a/{b,c}{e,f}{g,h,i}/k', {}, ['a/(b|c)(e|f)(g|h|i)/k']], - ['a/{b,{c,d},e}/f', {}, ['a/(b|(c|d)|e)/f']], - ['a/{b,{c,d}/{e,f},g}/h', {}, ['a/(b|(c|d)/(e|f)|g)/h']], - ['a/{b{c,d},e{f,g}h{i,j}}/k', {}, ['a/(b(c|d)|e(f|g)h(i|j))/k']], - ['a/{b{c,d},e}/f', {}, ['a/(b(c|d)|e)/f']], - ['a/{b{c,d}e{f,g}h{i,j}}/k', {}, ['a/(b(c|d)e(f|g)h(i|j))/k']], - ['a/{b{c,d}e{f,g},h{i,j}}/k', {}, ['a/(b(c|d)e(f|g)|h(i|j))/k']], - ['a/{x,y}/{1..5}c{d,e}f.{md,txt}', {}, ['a/(x|y)/([1-5])c(d|e)f.(md|txt)']], - ['a/{x,z}{b,{c,d}/{e,f},g}/h', {}, ['a/(x|z)(b|(c|d)/(e|f)|g)/h']], - ['a/{x,{1..5},y}/c{d}e', {}, ['a/(x|([1-5])|y)/c{d}e']], - ['a/{{a,b}/{c,d}}/z', {}, ['a/((a|b)/(c|d))/z']], - ['a/{{b,c}/{d,e}}', {}, ['a/((b|c)/(d|e))']], - ['a/{{b,c}/{d,e}}/f', {}, ['a/((b|c)/(d|e))/f']], - ['abc/${ddd}/xyz', {}, ['abc/${ddd}/xyz']], - ['abcd{efgh', {}, ['abcd{efgh']], - ['a{ ,c{d, },h} ', {}, ['a( |c(d| )|h) ']], - ['a{ ,c{d, },h}x', {}, ['a( |c(d| )|h)x']], - ['a{0..3}d', {}, ['a([0-3])d']], - ['a{b{c{d,e}f{x,y{{g}h', {}, ['a{b{c(d|e)f{x,y{{g}h']], - ['a{b}c', {}, ['a{b}c']], - ['foo {1,2} bar', {}, ['foo (1|2) bar']], - ['x{10..1}y', {}, ['x([1-9]|10)y']], - ['x{3..3}y', {}, ['x3y']], - ['{ }', {}, ['{ }']], - ['{', {}, ['{']], - ['{0..10,braces}', {}, ['(0..10|braces)']], - ['{1..0f}', {}, ['{1..0f}']], - ['{1..10,braces}', {}, ['(1..10|braces)']], - ['{1..10..ff}', {}, ['{1..10..ff}']], - ['{1..10.f}', {}, ['{1..10.f}']], - ['{1..10f}', {}, ['{1..10f}']], - ['{1..10}', {}, ['([1-9]|10)']], - ['{1..3}', {}, ['([1-3])']], - ['{1..9}', {}, ['([1-9])']], - ['{1..ff}', {}, ['{1..ff}']], - ['{1.20..2}', {}, ['{1.20..2}']], - ['{10..1}', {}, ['([1-9]|10)']], - ['{214748364..2147483649}', {}, ['(21474836[4-9]|2147483[7-9][0-9]|214748[4-9][0-9]{2}|214749[0-9]{3}|2147[5-9][0-9]{4}|214[8-9][0-9]{5}|21[5-9][0-9]{6}|2[2-9][0-9]{7}|[3-9][0-9]{8}|1[0-9]{9}|20[0-9]{8}|21[0-3][0-9]{7}|214[0-6][0-9]{6}|2147[0-3][0-9]{5}|21474[0-7][0-9]{4}|214748[0-2][0-9]{3}|2147483[0-5][0-9]{2}|21474836[0-4][0-9])']], - ['{2147483645..2147483649}', {}, ['(214748364[5-9])']], - ['{3..3}', {}, ['3']], - ['{5..8}', {}, ['([5-8])']], - ['{9..-4}', {}, ['(-[1-4]|[0-9])']], - ['{a,b,{c,d},e}', {}, ['(a|b|(c|d)|e)']], - ['{a,b,{c,d}e}', {}, ['(a|b|(c|d)e)']], - ['{a,b,{c,d}}', {}, ['(a|b|(c|d))']], - ['{a,b{c,d}}', {}, ['(a|b(c|d))']], - ['{a,b}/{c,d}', {}, ['(a|b)/(c|d)']], - ['{a,b}{c,d}', {}, ['(a|b)(c|d)']], - - ['{{0..10},braces}', {}, ['(([0-9]|10)|braces)']], - ['{{a,b},{c,d}}', {}, ['((a|b)|(c|d))']], - ['{{a,b}/{c,d}}', {}, ['((a|b)/(c|d))']], - ['{{a,b}/{c,d}}/z', {}, ['((a|b)/(c|d))/z']], - ['{}', {}, ['{}']], - ['}', {}, ['}']], - - // should not process glob characters - ['{generate,{assemble,update,verb}{file,-generate-*},generator}.js', {}, ['(generate|(assemble|update|verb)(file|-generate-*)|generator).js']], - ['**/{foo,bar}.js', {}, ['**/(foo|bar).js']], - ['**/{1..5}/a.js', {}, ['**/([1-5])/a.js']], - ['**/{a,b,c}/*.js', {}, ['**/(a|b|c)/*.js']], - ['**/{a,b,*}/*.js', {}, ['**/(a|b|*)/*.js']], - ['**/{**,b,*}/*.js', {}, ['**/(**|b|*)/*.js']], - - ['/usr/{ucb/{ex,edit},lib/{ex,how_ex}}', {}, ['/usr/(ucb/(ex|edit)|lib/(ex|how_ex))']], - ['ff{c,b,a}', {}, ['ff(c|b|a)']], - ['f{d,e,f}g', {}, ['f(d|e|f)g']], - ['x{{0..10},braces}y', {}, ['x(([0-9]|10)|braces)y']], - ['{1..10}', {}, ['([1-9]|10)']], - ['{a,b,c}', {}, ['(a|b|c)']], - ['{braces,{0..10}}', {}, ['(braces|([0-9]|10))']], - ['{l,n,m}xyz', {}, ['(l|n|m)xyz']], - ['{{0..10},braces}', {}, ['(([0-9]|10)|braces)']], - ['{{1..10..2},braces}', {bash: false }, ['((1|3|5|7|9)|braces)']], - ['{{1..10},braces}', {}, ['(([1-9]|10)|braces)']], - - ['a/{a,b}/{c,d}/e', {}, ['a/(a|b)/(c|d)/e']], - ['a{b,c}d{e,f}g', {}, ['a(b|c)d(e|f)g']], - ['a/{x,y}/c{d,e}f.{md,txt}', {}, ['a/(x|y)/c(d|e)f.(md|txt)']], - ['{a,b}{{a,b},a,b}', {}, ['(a|b)((a|b)|a|b)']], - ['/usr/{ucb/{ex,edit},lib/{ex,how_ex}}', {}, ['/usr/(ucb/(ex|edit)|lib/(ex|how_ex))']], - ['a{b,c{d,e}f}g', {}, ['a(b|c(d|e)f)g']], - ['a{{x,y},z}b', {}, ['a((x|y)|z)b']], - ['f{x,y{g,z}}h', {}, ['f(x|y(g|z))h']], - ['a{b,c{d,e},h}x/z', {}, ['a(b|c(d|e)|h)x/z']], - ['a{b,c{d,e},h}x{y,z}', {}, ['a(b|c(d|e)|h)x(y|z)']], - ['a{b,c{d,e},{f,g}h}x{y,z}', {}, ['a(b|c(d|e)|(f|g)h)x(y|z)']], - - // should handle invalid sets - ['{0..10,braces}', {}, ['(0..10|braces)']], - ['{1..10,braces}', {}, ['(1..10|braces)']], - - // should not expand escaped braces - ['\\{a,b,c,d,e}', {}, ['{a,b,c,d,e}']], - ['a/b/c/{x,y\\}', {}, ['a/b/c/{x,y}']], - ['a/\\{x,y}/cde', {}, ['a/{x,y}/cde']], - ['abcd{efgh', {}, ['abcd{efgh']], - ['\\{abc\\}', {}, ['{abc}']], - ['{x,y,\\{a,b,c\\}}', {}, ['(x|y|{a|b|c})']], - ['{x,y,{a,b,c\\}}', {}, ['{x,y,(a|b|c})']], - ['{x\\,y,\\{abc\\},trie}', {}, ['(x,y|{abc}|trie)']], - ['{x,y,{abc},trie}', {}, ['(x|y|{abc}|trie)']], - ['x,y,{abc},trie', {}, ['x,y,{abc},trie']], - ['{b{c,d},e}', {}, ['(b(c|d)|e)']], - ['{b{c,d},e}/f', {}, ['(b(c|d)|e)/f']], - ['{abc}', {}, ['{abc}']], - - // 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']], - - // should escape closing braces when open is not defined - ['{a,b}c,d}', {}, ['(a|b)c,d}']], - ['a,b,c,d}', {}, ['a,b,c,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}|c)/d']], - ['a${b,d}/{foo,bar}c', {}, ['a${b,d}/(foo|bar)c']], - - // should not expand escaped commas - ['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|c)/{x,y}/d/e']], - - // should not expand escaped braces - ['{a,b\\}c,d}', {}, ['(a|b}c|d)']], - ['\\{a,b,c,d,e}', {}, ['{a,b,c,d,e}']], - ['a/{z,\\{a,b,c,d,e}/d', {}, ['a/(z|{a|b|c|d|e)/d']], - ['a/\\{b,c}/{d,e}/f', {}, ['a/{b,c}/(d|e)/f']], - ['./\\{x,y}/{a..z..3}/', {}, ['./{x,y}/(a|d|g|j|m|p|s|v|y)/']], - - // should not expand escaped braces or commas - ['{x\\,y,\\{abc\\},trie}', {}, ['(x,y|{abc}|trie)']], - - // should support sequence brace operators - ['/usr/{ucb/{ex,edit},lib/{ex,how_ex}}', {}, ['/usr/(ucb/(ex|edit)|lib/(ex|how_ex))']], - ['ff{c,b,a}', {}, ['ff(c|b|a)']], - ['f{d,e,f}g', {}, ['f(d|e|f)g']], - ['x{{0..10},braces}y', {}, ['x(([0-9]|10)|braces)y']], - ['{1..10}', {}, ['([1-9]|10)']], - ['{a,b,c}', {}, ['(a|b|c)']], - ['{braces,{0..10}}', {}, ['(braces|([0-9]|10))']], - ['{l,n,m}xyz', {}, ['(l|n|m)xyz']], - ['{{0..10},braces}', {}, ['(([0-9]|10)|braces)']], - ['{{1..10..2},braces}', {}, ['((1|3|5|7|9)|braces)']], - ['{{1..10},braces}', {}, ['(([1-9]|10)|braces)']], - - // should expand multiple sets - ['a/{a,b}/{c,d}/e', {}, ['a/(a|b)/(c|d)/e']], - ['a{b,c}d{e,f}g', {}, ['a(b|c)d(e|f)g']], - ['a/{x,y}/c{d,e}f.{md,txt}', {}, ['a/(x|y)/c(d|e)f.(md|txt)']], - - // should expand nested sets - ['{a,b}{{a,b},a,b}', {}, ['(a|b)((a|b)|a|b)']], - ['/usr/{ucb/{ex,edit},lib/{ex,how_ex}}', {}, ['/usr/(ucb/(ex|edit)|lib/(ex|how_ex))']], - ['a{b,c{d,e}f}g', {}, ['a(b|c(d|e)f)g']], - ['a{{x,y},z}b', {}, ['a((x|y)|z)b']], - ['f{x,y{g,z}}h', {}, ['f(x|y(g|z))h']], - ['a{b,c{d,e},h}x/z', {}, ['a(b|c(d|e)|h)x/z']], - ['a{b,c{d,e},h}x{y,z}', {}, ['a(b|c(d|e)|h)x(y|z)']], - ['a{b,c{d,e},{f,g}h}x{y,z}', {}, ['a(b|c(d|e)|(f|g)h)x(y|z)']], - ['a-{b{d,e}}-c', {}, ['a-{b(d|e)}-c']], - - // should expand not modify non-brace characters - ['a/b/{d,e}/*.js', {}, ['a/b/(d|e)/*.js']], - ['a/**/c/{d,e}/f*.js', {}, ['a/**/c/(d|e)/f*.js']], - ['a/**/c/{d,e}/f*.{md,txt}', {}, ['a/**/c/(d|e)/f*.(md|txt)']], - - // should work with leading and trailing commas - ['a{b,}c', {}, ['a(b|)c']], - ['a{,b}c', {}, ['a(|b)c']], - - // should handle spaces - // Bash 4.3 says the this first one should be equivalent to `foo|(1|2)|bar - // That makes sense in Bash, since ' ' is a separator, but not here. - ['foo {1,2} bar', {}, ['foo (1|2) bar']], - ['0{1..9} {10..20}', {}, ['0([1-9]) (1[0-9]|20)']], - ['a{ ,c{d, },h}x', {}, ['a( |c(d| )|h)x']], - ['a{ ,c{d, },h} ', {}, ['a( |c(d| )|h) ']], - - // see https://github.com/jonschlinkert/micromatch/issues/66 - ['/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.{html,ejs}', {}, ['/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.(html|ejs)']], - - /** - * Ranges - */ - - // should not try to expand ranges with decimals - ['{1.1..2.1}', {}, ['{1.1..2.1}']], - ['{1.1..~2.1}', {}, ['{1.1..~2.1}']], - - // should escape invalid ranges - ['{1..0f}', {}, ['{1..0f}']], - ['{1..10..ff}', {}, ['{1..10..ff}']], - ['{1..10.f}', {}, ['{1..10.f}']], - ['{1..10f}', {}, ['{1..10f}']], - ['{1..20..2f}', {}, ['{1..20..2f}']], - ['{1..20..f2}', {}, ['{1..20..f2}']], - ['{1..2f..2}', {}, ['{1..2f..2}']], - ['{1..ff..2}', {}, ['{1..ff..2}']], - ['{1..ff}', {}, ['{1..ff}']], - ['{1.20..2}', {}, ['{1.20..2}']], - - // should handle weirdly-formed brace expansions (fixed in post-bash-3.1) - ['a-{b{d,e}}-c', {}, ['a-{b(d|e)}-c']], - ['a-{bdef-{g,i}-c', {}, ['a-{bdef-(g|i)-c']], - - // should not expand quoted strings - ['{"klklkl"}{1,2,3}', {}, ['{klklkl}(1|2|3)']], - ['{"x,x"}', {}, ['{x,x}']], - - // should escaped outer braces in nested non-sets - ['{a-{b,c,d}}', {}, ['{a-(b|c|d)}']], - ['{a,{a-{b,c,d}}}', {}, ['(a|{a-(b|c|d)})']], - - // should escape imbalanced braces - ['a-{bdef-{g,i}-c', {}, ['a-{bdef-(g|i)-c']], - ['abc{', {}, ['abc{']], - ['{abc{', {}, ['{abc{']], - ['{abc', {}, ['{abc']], - ['}abc', {}, ['}abc']], - ['ab{c', {}, ['ab{c']], - ['ab{c', {}, ['ab{c']], - ['{{a,b}', {}, ['{(a|b)']], - ['{a,b}}', {}, ['(a|b)}']], - ['abcd{efgh', {}, ['abcd{efgh']], - ['a{b{c{d,e}f}gh', {}, ['a{b(c(d|e)f)gh']], - ['a{b{c{d,e}f}g}h', {}, ['a(b(c(d|e)f)g)h']], - ['f{x,y{{g,z}}h}', {}, ['f(x|y((g|z))h)']], - ['z{a,b},c}d', {}, ['z(a|b),c}d']], - ['a{b{c{d,e}f{x,y{{g}h', {}, ['a{b{c(d|e)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']], - ['a{b{c{d,e}f{x,y{}g}h', {}, ['a{b{c(d|e)f(x|y{}g)h']], - ['f{x,y{}g}h', {}, ['f(x|y{}g)h']], - ['z{a,b{,c}d', {}, ['z{a,b(|c)d']], - - // should expand numeric ranges - ['a{0..3}d', {}, ['a([0-3])d']], - ['x{10..1}y', {}, ['x([1-9]|10)y']], - ['x{3..3}y', {}, ['x3y']], - ['{1..10}', {}, ['([1-9]|10)']], - ['{1..3}', {}, ['([1-3])']], - ['{1..9}', {}, ['([1-9])']], - ['{10..1}', {}, ['([1-9]|10)']], - ['{10..1}y', {}, ['([1-9]|10)y']], - ['{3..3}', {}, ['3']], - ['{5..8}', {}, ['([5-8])']], - - // should expand ranges with negative numbers - ['{-10..-1}', {}, ['(-[1-9]|-10)']], - ['{-20..0}', {}, ['(-[1-9]|-1[0-9]|-20|0)']], - ['{0..-5}', {}, ['(-[1-5]|0)']], - ['{9..-4}', {}, ['(-[1-4]|[0-9])']], - - // should expand alphabetical ranges - ['0{1..9}/{10..20}', {}, ['0([1-9])/(1[0-9]|20)']], - ['0{a..d}0', {}, ['0([a-d])0']], - ['a/{b..d}/e', {}, ['a/([b-d])/e']], - ['{1..f}', {}, ['([1-f])']], - ['{a..A}', {}, ['([A-a])']], - ['{A..a}', {}, ['([A-a])']], - ['{a..e}', {}, ['([a-e])']], - ['{A..E}', {}, ['([A-E])']], - ['{a..f}', {}, ['([a-f])']], - ['{a..z}', {}, ['([a-z])']], - ['{E..A}', {}, ['([A-E])']], - ['{f..1}', {}, ['([1-f])']], - ['{f..a}', {}, ['([a-f])']], - ['{f..f}', {}, ['f']], - - // should expand multiple ranges - ['a/{b..d}/e/{f..h}', {}, ['a/([b-d])/e/([f-h])']], - - // should expand numerical ranges - positive and negative - ['{-10..10}', {}, ['(-[1-9]|-?10|[0-9])']], - - // HEADS UP! If you're using the `--mm` flag minimatch freezes on these - // should expand large numbers - ['{2147483645..2147483649}', {}, ['(214748364[5-9])']], - ['{214748364..2147483649}', {}, ['(21474836[4-9]|2147483[7-9][0-9]|214748[4-9][0-9]{2}|214749[0-9]{3}|2147[5-9][0-9]{4}|214[8-9][0-9]{5}|21[5-9][0-9]{6}|2[2-9][0-9]{7}|[3-9][0-9]{8}|1[0-9]{9}|20[0-9]{8}|21[0-3][0-9]{7}|214[0-6][0-9]{6}|2147[0-3][0-9]{5}|21474[0-7][0-9]{4}|214748[0-2][0-9]{3}|2147483[0-5][0-9]{2}|21474836[0-4][0-9])']], - - // should expand ranges using steps - ['{1..10..1}', {bash: false}, ['([1-9]|10)']], - ['{1..10..2}', {bash: false}, ['(1|3|5|7|9)']], - ['{1..20..20}', {bash: false}, ['1']], - ['{1..20..2}', {bash: false}, ['(1|3|5|7|9|11|13|15|17|19)']], - ['{10..0..2}', {bash: false}, ['(10|8|6|4|2|0)']], - ['{10..1..2}', {bash: false}, ['(10|8|6|4|2)']], - ['{100..0..5}', {bash: 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}', {bash: false}, ['([2-9]|10)']], - ['{2..10..2}', {bash: false}, ['(2|4|6|8|10)']], - ['{2..10..3}', {bash: false}, ['(2|5|8)']], - ['{a..z..2}', {bash: false}, ['(a|c|e|g|i|k|m|o|q|s|u|w|y)']], - - // should expand positive ranges with negative steps - ['{10..0..-2}', {bash: false}, ['(10|8|6|4|2|0)']], - - // should expand negative ranges using steps - ['{-1..-10..-2}', {bash: false}, ['(-(1|3|5|7|9))']], - ['{-1..-10..2}', {bash: false}, ['(-(1|3|5|7|9))']], - ['{-10..-2..2}', {bash: false}, ['(-(10|8|6|4|2))']], - ['{-2..-10..1}', {bash: false}, ['(-[2-9]|-10)']], - ['{-2..-10..2}', {bash: false}, ['(-(2|4|6|8|10))']], - ['{-2..-10..3}', {bash: false}, ['(-(2|5|8))']], - ['{-50..-0..5}', {bash: false}, ['(0|-(50|45|40|35|30|25|20|15|10|5))']], - ['{-9..9..3}', {bash: false}, ['(0|3|6|9|-(9|6|3))']], - ['{10..1..-2}', {bash: false}, ['(10|8|6|4|2)']], - ['{100..0..-5}', {bash: false}, ['(100|95|90|85|80|75|70|65|60|55|50|45|40|35|30|25|20|15|10|5|0)']], - - // should expand alpha ranges with steps - ['{a..e..2}', {bash: false}, ['(a|c|e)']], - ['{E..A..2}', {bash: false}, ['(E|C|A)']], - ['{a..z..2}', {bash: false}, ['(a|c|e|g|i|k|m|o|q|s|u|w|y)']], - ['{z..a..-2}', {bash: false}, ['(z|x|v|t|r|p|n|l|j|h|f|d|b)']], - - // should expand alpha ranges with negative steps - ['{z..a..-2}', {bash: false}, ['(z|x|v|t|r|p|n|l|j|h|f|d|b)']], - - // unwanted zero-padding (fixed post-bash-4.0) - ['{10..0..2}', {bash: false}, ['(10|8|6|4|2|0)']], - ['{10..0..-2}', {bash: false}, ['(10|8|6|4|2|0)']], - ['{-50..-0..5}', {bash: false}, ['(0|-(50|45|40|35|30|25|20|15|10|5))']], - - // should work with dots in file paths - ['../{1..3}/../foo', {}, ['../([1-3])/../foo']], - ['../{2..10..2}/../foo', {}, ['../(2|4|6|8|10)/../foo']], - ['../{1..3}/../{a,b,c}/foo', {}, ['../([1-3])/../(a|b|c)/foo']], - ['./{a..z..3}/', {}, ['./(a|d|g|j|m|p|s|v|y)/']], - ['./{"x,y"}/{a..z..3}/', {}, ['./{x,y}/(a|d|g|j|m|p|s|v|y)/']], - - // should expand a complex combination of ranges and sets - ['a/{x,y}/{1..5}c{d,e}f.{md,txt}', {}, ['a/(x|y)/([1-5])c(d|e)f.(md|txt)']], - - // should expand complex sets and ranges in `bash` mode - ['a/{x,{1..5},y}/c{d}e', {}, ['a/(x|([1-5])|y)/c{d}e']] - ]; - - fixtures.forEach(function(arr) { - if (typeof arr === 'string') { - return; - } - - var options = extend({}, arr[1]); - var pattern = arr[0]; - var expected = arr[2]; - - if (options.skip === true) { - return; - } - - it('should compile: ' + pattern, function() { - match(pattern, expected, options); - }); - }); -}); diff -Nru node-braces-2.0.2/test/bash-spec.js node-braces-3.0.2/test/bash-spec.js --- node-braces-2.0.2/test/bash-spec.js 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/test/bash-spec.js 2019-04-16 19:50:10.000000000 +0000 @@ -0,0 +1,197 @@ +'use strict'; + +require('mocha'); +const assert = require('assert').strict; +const bashPath = require('bash-path'); +const cp = require('child_process'); +const braces = require('..'); + +const bash = input => { + return cp.spawnSync(bashPath(), ['-c', `echo ${input}`]) + .stdout.toString() + .split(/\s+/) + .filter(Boolean); +}; + +const equal = (input, expected = bash(input), options) => { + assert.deepEqual(braces.expand(input, options), expected); +}; + +/** + * Bash 4.3 unit tests + */ + +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', 'X { + if (typeof arr === 'string') { + return; + } + + let options = { ...arr[1] }; + let pattern = arr[0]; + let expected = arr[2]; + + if (options.skip === true) { + return; + } + + it('should compile: ' + pattern, () => { + equal(pattern, expected, options); + }); + }); +}); diff -Nru node-braces-2.0.2/test/bash.spec.js node-braces-3.0.2/test/bash.spec.js --- node-braces-2.0.2/test/bash.spec.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/test/bash.spec.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,188 +0,0 @@ -'use strict'; - -var extend = require('extend-shallow'); -var assert = require('assert'); -var braces = require('..'); - -function match(pattern, expected, options) { - var actual = braces.expand(pattern, options).sort(); - assert.deepEqual(actual, expected.sort(), pattern); -} - -/** - * Bash 4.3 unit tests - */ - -describe('bash', function() { - var fixtures = [ - [ '{1\\.2}', {}, [ '{1.2}' ] ], - [ '{"x,x"}', {}, [ '{x,x}' ] ], - [ '{x","x}', {}, [ '{x,x}' ] ], - [ '\'{x,x}\'', {}, [ '{x,x}' ] ], - [ '{x`,`x}', {}, [ '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', {}, [ 'X{a..#}X' ] ], - [ '', {}, [ '' ] ], - [ '{-10..00}', {}, [ '-10', '-09', '-08', '-07', '-06', '-05', '-04', '-03', '-02', '-01', '000' ] ], - [ '{a,\\\\{a,b}c}', {}, [ 'a', '\\\\ac', '\\\\bc' ] ], - [ '{a,\\{a,b}c}', {}, [ 'ac}', '{ac}', 'bc}' ] ], - [ 'a,\\{b,c}', {}, [ 'a,{b,c}' ] ], - [ '{-10.\\.00}', {}, [ '{-10..00}' ] ], - [ 'ff{c,b,a}', {}, [ 'ffc', 'ffb', 'ffa' ] ], - [ 'f{d,e,f}g', {}, [ 'fdg', 'feg', 'ffg' ] ], - [ '{l,n,m}xyz', {}, [ 'lxyz', 'nxyz', 'mxyz' ] ], - [ '{abc\\,def}', {}, [ '{abc,def}' ] ], - [ '{abc}', {}, [ '{abc}' ] ], - [ '{x\\,y,\\{abc\\},trie}', {}, [ 'x,y', '{abc}', 'trie' ] ], - [ '{}', {}, [ '{}' ] ], - [ '{ }', {}, [ '{ }' ] ], - [ '}', {}, [ '}' ] ], - [ '{', {}, [ '{' ] ], - [ 'abcd{efgh', {}, [ 'abcd{efgh' ] ], - [ 'foo {1,2} bar', {}, [ 'foo 1 bar', 'foo 2 bar' ] ], - [ '"${var}"{x,y}', {}, [ '${var}x', '${var}y' ] ], - [ '{1..10}', {}, [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '10' ] ], - [ '{0..10,braces}', {}, [ '0..10', 'braces' ] ], - [ '{{0..10},braces}', {}, [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'braces' ] ], - [ 'x{{0..10},braces}y', {}, [ 'x0y', 'x1y', 'x2y', 'x3y', 'x4y', 'x5y', 'x6y', 'x7y', 'x8y', 'x9y', 'x10y', 'xbracesy' ] ], - [ '{3..3}', {}, [ '3' ] ], - [ 'x{3..3}y', {}, [ 'x3y' ] ], - [ '{10..1}', {}, [ '10', '9', '8', '7', '6', '5', '4', '3', '2', '1' ] ], - [ '{10..1}y', {}, [ '10y', '9y', '8y', '7y', '6y', '5y', '4y', '3y', '2y', '1y' ] ], - [ 'x{10..1}y', {}, [ 'x10y', 'x9y', 'x8y', 'x7y', 'x6y', 'x5y', 'x4y', 'x3y', 'x2y', 'x1y' ] ], - [ '{a..f}', {}, [ 'a', 'b', 'c', 'd', 'e', 'f' ] ], - [ '{f..a}', {}, [ 'f', 'e', 'd', 'c', 'b', 'a' ] ], - [ '{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' ] ], - [ '{f..f}', {}, [ 'f' ] ], - [ '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' ] ], - [ '{-1..-10}', {}, [ '-1', '-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '-10' ] ], - [ '{-20..0}', {}, [ '-20', '-19', '-18', '-17', '-16', '-15', '-14', '-13', '-12', '-11', '-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1', '0' ] ], - [ 'a-{b{d,e}}-c', {}, [ 'a-{bd}-c', 'a-{be}-c' ] ], - [ 'a-{bdef-{g,i}-c', {}, [ 'a-{bdef-g-c', 'a-{bdef-i-c' ] ], - [ '{"klklkl"}{1,2,3}', {}, [ '{klklkl}1', '{klklkl}2', '{klklkl}3' ] ], - [ '{"x,x"}', {}, [ '{x,x}' ] ], - [ '{klklkl}{1,2,3}', {}, [ '{klklkl}1', '{klklkl}2', '{klklkl}3' ] ], - [ '{1..10..2}', {}, [ '1', '3', '5', '7', '9' ] ], - [ '{-1..-10..2}', {}, [ '-1', '-3', '-5', '-7', '-9' ] ], - [ '{-1..-10..-2}', {}, [ '-1', '-3', '-5', '-7', '-9' ] ], - [ '{10..1..-2}', {}, [ '10', '8', '6', '4', '2' ] ], - [ '{10..1..2}', {}, [ '10', '8', '6', '4', '2' ] ], - [ '{1..20..2}', {}, [ '1', '3', '5', '7', '9', '11', '13', '15', '17', '19' ] ], - [ '{1..20..20}', {}, [ '1' ] ], - [ '{100..0..5}', {}, [ '100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0' ] ], - [ '{100..0..-5}', {}, [ '100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0' ] ], - [ '{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..2}', {}, [ 'a', 'c', 'e', 'g', 'i', 'k', 'm', 'o', 'q', 's', 'u', 'w', 'y' ] ], - [ '{z..a..-2}', {}, [ 'z', 'x', 'v', 't', 'r', 'p', 'n', 'l', 'j', 'h', 'f', 'd', 'b' ] ], - [ '{2147483645..2147483649}', {}, [ '2147483645', '2147483646', '2147483647', '2147483648', '2147483649' ] ], - [ '{10..0..2}', {}, [ '10', '8', '6', '4', '2', '0' ] ], - [ '{10..0..-2}', {}, [ '10', '8', '6', '4', '2', '0' ] ], - [ '{-50..-0..5}', {}, [ '-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0' ] ], - [ '{1..10.f}', {}, [ '{1..10.f}' ] ], - [ '{1..ff}', {}, [ '{1..ff}' ] ], - [ '{1..10..ff}', {}, [ '{1..10..ff}' ] ], - [ '{1.20..2}', {}, [ '{1.20..2}' ] ], - [ '{1..20..f2}', {}, [ '{1..20..f2}' ] ], - [ '{1..20..2f}', {}, [ '{1..20..2f}' ] ], - [ '{1..2f..2}', {}, [ '{1..2f..2}' ] ], - [ '{1..ff..2}', {}, [ '{1..ff..2}' ] ], - [ '{1..ff}', {}, [ '{1..ff}' ] ], - [ '{1..0f}', {}, [ '{1..0f}' ] ], - [ '{1..10f}', {}, [ '{1..10f}' ] ], - [ '{1..10.f}', {}, [ '{1..10.f}' ] ], - [ '{},b}.h', {}, [ '{},b}.h' ] ], - [ 'y{\\},a}x', {}, [ 'y}x', 'yax' ] ], - [ '{}a,b}c', {}, [ '{}a,b}c' ] ] - ]; - - fixtures.forEach(function(arr) { - if (typeof arr === 'string') { - return; - } - - var options = extend({}, arr[1]); - var pattern = arr[0]; - var expected = arr[2]; - - if (options.skip === true) { - return; - } - - it('should compile: ' + pattern, function() { - match(pattern, expected, options); - }); - }); -}); diff -Nru node-braces-2.0.2/test/brace-expansion.js node-braces-3.0.2/test/brace-expansion.js --- node-braces-2.0.2/test/brace-expansion.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/test/brace-expansion.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,91 +0,0 @@ -'use strict'; - -var assert = require('assert'); -var braces = require('..'); - -function match(pattern, expected, options) { - var actual = braces.expand(pattern, options).sort(); - assert.deepEqual(actual, expected.sort(), pattern); -} - -/** - * All of the unit tests from brace-expansion v1.1.6 - * https://github.com/juliangruber/brace-expansion - */ - -describe('unit tests from brace-expand', function() { - describe('sequences', function() { - it('numeric sequences', function() { - match('a{1..2}b{2..3}c', ['a1b2c', 'a1b3c', 'a2b2c', 'a2b3c']); - match('{1..2}{2..3}', ['12', '13', '22', '23']); - }); - - it('numeric sequences with step count', function() { - match('{0..8..2}', ['0', '2', '4', '6', '8']); - match('{1..8..2}', ['1', '3', '5', '7']); - }); - - it('numeric sequence with negative x / y', function() { - match('{3..-2}', ['3', '2', '1', '0', '-1', '-2']); - }); - - it('alphabetic sequences', function() { - match('1{a..b}2{b..c}3', ['1a2b3', '1a2c3', '1b2b3', '1b2c3']); - match('{a..b}{b..c}', ['ab', 'ac', 'bb', 'bc']); - }); - - it('alphabetic sequences with step count', function() { - match('{a..k..2}', ['a', 'c', 'e', 'g', 'i', 'k']); - match('{b..k..2}', ['b', 'd', 'f', 'h', 'j']); - }); - }); - - describe('dollar', function() { - it('ignores ${', function() { - match('${1..3}', ['${1..3}']); - match('${a,b}${c,d}', ['${a,b}${c,d}']); - match('x${a,b}x${c,d}x', ['x${a,b}x${c,d}x']); - }); - }); - - describe('empty option', function() { - it('should support empty sets', function() { - match('-v{,,,,}', ['-v', '-v', '-v', '-v', '-v']); - }); - }); - - describe('negative increments', function() { - it('should support negative steps', function() { - match('{3..1}', ['3', '2', '1']); - match('{10..8}', ['10', '9', '8']); - match('{10..08}', ['10', '09', '08']); - match('{c..a}', ['c', 'b', 'a']); - - match('{4..0..2}', ['4', '2', '0']); - match('{4..0..-2}', ['4', '2', '0']); - match('{e..a..2}', ['e', 'c', 'a']); - }); - }); - - describe('nested', function() { - it('should support nested sets', function() { - match('{a,b{1..3},c}', ['a', 'b1', 'b2', 'b3', 'c']); - match('{{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' ].sort()); - match('ppp{,config,oe{,conf}}', ['ppp', 'pppconfig', 'pppoe', 'pppoeconf']); - }); - }); - - describe('order', function() { - it('should expand in given order', function() { - match('a{d,c,b}e', ['ade', 'ace', 'abe']); - }); - }); - - describe('pad', function() { - it('should support padding', function() { - match('{9..11}', ['9', '10', '11']); - match('{09..11}', ['09', '10', '11']); - }); - }); -}); - diff -Nru node-braces-2.0.2/test/braces.compile.js node-braces-3.0.2/test/braces.compile.js --- node-braces-2.0.2/test/braces.compile.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/test/braces.compile.js 2019-04-16 19:50:10.000000000 +0000 @@ -1,19 +1,59 @@ 'use strict'; require('mocha'); -var assert = require('assert'); -var braces = require('..'); +const assert = require('assert').strict; +const compile = require('../lib/compile'); +const parse = require('../lib/parse'); -describe('.compile', function() { - it('should return an object', function() { - var res = braces.compile('a/{b,c}/d'); - assert(res); - assert.equal(typeof res, 'object'); +describe('braces.compile()', () => { + describe('errors', () => { + it('should throw an error when invalid args are passed', () => { + assert.throws(() => compile()); + }); }); - it('should return output as an array', function() { - var res = braces.compile('a/{b,c}/d'); - assert(Array.isArray(res.output)); - assert.deepEqual(res.output, ['a/(b|c)/d']); + describe('invalid characters', () => { + it('should escape invalid bracket characters', () => { + assert.equal(compile(parse(']{a,b,c}')), '\\](a|b|c)'); + }); + }); + + describe('sets', () => { + it('should support empty sets', () => { + assert.equal(compile(parse('{a,}')), '(a|)'); + assert.equal(compile(parse('{a,,}')), '(a|)'); + assert.equal(compile(parse('{a,,,}')), '(a|)'); + assert.equal(compile(parse('{a,,,,}')), '(a|)'); + assert.equal(compile(parse('{a,,,,,}')), '(a|)'); + }); + }); + + describe('ranges', () => { + it('should escape braces with invalid ranges', () => { + assert.equal(compile(parse('{a...b}')), '{a...b}'); + assert.equal(compile(parse('{a...b}'), { escapeInvalid: true }), '\\{a...b\\}'); + }); + + it('should expand brace patterns with both sets and ranges', () => { + assert.equal(compile(parse('{a..e,z}')), '(a..e|z)'); + assert.equal(compile(parse('{a..e,a..z}')), '(a..e|a..z)'); + }); + + it('should escape braces with too many range expressions', () => { + 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\\}'); + }); + }); + + describe('invalid', () => { + it('should escape incomplete brace patterns', () => { + assert.equal(compile(parse(']{a/b')), '\\]{a/b'); + assert.equal(compile(parse(']{a/b'), { escapeInvalid: true }), '\\]\\{a/b'); + }); + + it('should escape non-brace patterns (no sets or ranges)', () => { + assert.equal(compile(parse(']{a/b}')), '\\]{a/b}'); + assert.equal(compile(parse(']{a/b}'), { escapeInvalid: true }), '\\]\\{a/b\\}'); + }); }); }); diff -Nru node-braces-2.0.2/test/braces.expand.js node-braces-3.0.2/test/braces.expand.js --- node-braces-2.0.2/test/braces.expand.js 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/test/braces.expand.js 2019-04-16 19:50:10.000000000 +0000 @@ -0,0 +1,168 @@ +'use strict'; + +require('mocha'); +const assert = require('assert').strict; +const expand = require('../lib/expand'); +const parse = require('../lib/parse'); +const bashPath = require('bash-path'); +const cp = require('child_process'); +const braces = require('..'); + +const bash = input => { + return cp.spawnSync(bashPath(), ['-c', `echo ${input}`]) + .stdout.toString() + .split(/\s+/) + .filter(Boolean); +}; + +const equal = (input, expected = bash(input), options) => { + assert.deepEqual(braces.expand(input, options), expected); +}; + +describe('unit tests from brace-expand', () => { + describe('extglobs', () => { + it('should split on commas when braces are inside extglobs', () => { + equal('*(a|{b|c,d})', ['*(a|b|c)', '*(a|d)']); + }); + + it('should not split on commas in extglobs when inside braces', () => { + equal('{a,@(b,c)}', ['a', '@(b,c)']); + equal('{a,*(b|c,d)}', ['a', '*(b|c,d)']); + }); + }); + + describe('expand', () => { + it('should expand an AST', () => { + assert.deepEqual(expand(parse('a/{b,c}/d')), ['a/b/d', 'a/c/d']); + }); + + 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}']); + 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('{,{,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']); + equal('{,{,a,b}z}{c,d}', ['c', 'd', 'zc', 'zd', 'azc', 'azd', 'bzc', 'bzd']); + equal('{{,a,b}z,}{,c}', ['z', 'zc', 'az', 'azc', 'bz', 'bzc', '', 'c']); + equal('{,a{,b}z,}{,c}', ['', 'c', 'az', 'azc', 'abz', 'abzc', '', 'c']); + equal('{,a{,b},}{,c}', ['', 'c', 'a', 'ac', 'ab', 'abc', '', 'c']); + equal('{,a{,b}}{,c}', ['', 'c', 'a', 'ac', 'ab', 'abc']); + equal('{,b}{,d}', ['', 'd', 'b', 'bd']); + equal('{a,b}{,d}', ['a', 'ad', 'b', 'bd']); + equal('{,a}{z,c}', ['z', 'c', 'az', 'ac']); + 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', 'az', 'ac', 'z', 'c']); + equal('{,,a}{z,c}', ['z', 'c', 'z', 'c', 'az', 'ac']); + equal('{,{,}}{z,c}', ['z', 'c', 'z', 'c', 'z', 'c']); + equal('{,{a,b}}{,c}', ['', 'c', 'a', 'ac', 'b', 'bc']); + equal('{,{a,}}{,c}', ['', 'c', 'a', 'ac', '', 'c']); + equal('{,{,b}}{,c}', ['', 'c', '', 'c', 'b', 'bc']); + equal('{,{,}}{,c}', ['', 'c', '', 'c', '', 'c']); + equal('{,a}{,c}', ['', 'c', 'a', 'ac']); + equal('{,{,a}b}', ['', 'b', 'ab']); + equal('{,b}', ['', 'b']); + equal('{,b{,a}}', ['', 'b', 'ba']); + equal('{b,{,a}}', ['b', '', 'a']); + equal('{,b}{,d}', ['', 'd', 'b', 'bd']); + equal('{a,b}{,d}', ['a', 'ad', 'b', 'bd']); + }); + }); + + /** + * The following unit tests are from brace-expansion v1.1.6 + * https://github.com/juliangruber/brace-expansion + */ + + describe('brace expansion unit tests from brace-expand', () => { + describe('sequences', () => { + it('numeric sequences', () => { + equal('a{1..2}b{2..3}c', ['a1b2c', 'a1b3c', 'a2b2c', 'a2b3c']); + equal('{1..2}{2..3}', ['12', '13', '22', '23']); + }); + + it('numeric sequences with step count', () => { + equal('{0..8..2}', ['0', '2', '4', '6', '8']); + equal('{1..8..2}', ['1', '3', '5', '7']); + }); + + it('numeric sequence with negative x / y', () => { + equal('{3..-2}', ['3', '2', '1', '0', '-1', '-2']); + }); + + it('alphabetic sequences', () => { + equal('1{a..b}2{b..c}3', ['1a2b3', '1a2c3', '1b2b3', '1b2c3']); + equal('{a..b}{b..c}', ['ab', 'ac', 'bb', 'bc']); + }); + + it('alphabetic sequences with step count', () => { + equal('{a..k..2}', ['a', 'c', 'e', 'g', 'i', 'k']); + equal('{b..k..2}', ['b', 'd', 'f', 'h', 'j']); + }); + }); + + describe('dollar', () => { + it('ignores ${', () => { + equal('${1..3}', ['${1..3}']); + equal('${a,b}${c,d}', ['${a,b}${c,d}']); + equal('x${a,b}x${c,d}x', ['x${a,b}x${c,d}x']); + }); + }); + + describe('empty option', () => { + it('should support empty sets', () => { + equal('-v{,,,,}', ['-v', '-v', '-v', '-v', '-v']); + }); + }); + + describe('negative increments', () => { + it('should support negative steps', () => { + equal('{3..1}', ['3', '2', '1']); + equal('{10..8}', ['10', '9', '8']); + equal('{10..08}', ['10', '09', '08']); + equal('{c..a}', ['c', 'b', 'a']); + + equal('{4..0..2}', ['4', '2', '0']); + equal('{4..0..-2}', ['4', '2', '0']); + equal('{e..a..2}', ['e', 'c', 'a']); + }); + }); + + describe('nested', () => { + it('should support nested sets', () => { + equal('{a,b{1..3},c}', ['a', 'b1', 'b2', 'b3', 'c']); + equal('{{A..E},{a..e}}', ['A', 'B', 'C', 'D', 'E', 'a', 'b', 'c', 'd', 'e']); + equal('ppp{,config,oe{,conf}}', ['ppp', 'pppconfig', 'pppoe', 'pppoeconf']); + }); + }); + + describe('order', () => { + it('should expand in given order', () => { + equal('a{d,c,b}e', ['ade', 'ace', 'abe']); + }); + }); + + describe('pad', () => { + it('should support padding', () => { + equal('{9..11}', ['9', '10', '11']); + equal('{09..11}', ['09', '10', '11']); + }); + }); + }); +}); + diff -Nru node-braces-2.0.2/test/braces.js node-braces-3.0.2/test/braces.js --- node-braces-2.0.2/test/braces.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/test/braces.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ -'use strict'; - -require('mocha'); -var assert = require('assert'); -var braces = require('..'); - -function match(pattern, expected, options) { - assert.deepEqual(braces(pattern, options), expected); -} - -describe('braces', function() { - it('should return an array', function() { - assert(Array.isArray(braces('{a,b}'))); - }); - - it('should return an optimized string by default', function() { - match('a/{b,c}/d', ['a/(b|c)/d']); - }); - - it('should return an expanded array if defined on options', function() { - match('a/{b,c}/d', ['a/b/d', 'a/c/d'], {expand: true}); - }); - - it('should optimize an array of patterns', function() { - match(['a/{b,c}/d', 'x/{foo,bar}/z'], ['a/(b|c)/d', 'x/(foo|bar)/z']); - }); - - it('should expand an array of patterns', function() { - var actual = braces(['a/{b,c}/d', 'a/{b,c}/d']); - assert.deepEqual(actual, ['a/(b|c)/d', 'a/(b|c)/d']); - }); - - it('should not uniquify by default', function() { - var actual = braces(['a/{b,c}/d', 'a/{b,c}/d']); - assert.deepEqual(actual, ['a/(b|c)/d', 'a/(b|c)/d']); - }); - - it('should uniquify when `options.nodupes` is true', function() { - var actual = braces(['a/{b,c}/d', 'a/{b,c}/d'], {nodupes: true}); - assert.deepEqual(actual, ['a/(b|c)/d']); - }); - - it('should expand ranges', function() { - match('a{1..5}b', ['a1b', 'a2b', 'a3b', 'a4b', 'a5b'], {expand: true}); - }); - - it('should expand ranges that are nested in a set', function() { - match('a{b,c,{1..5}}e', ['abe', 'ace', 'a1e', 'a2e', 'a3e', 'a4e', 'a5e'], {expand: true}); - }); - - it('should not expand ranges when they are just characters in a set', function() { - match('a{b,c,1..5}e', ['abe', 'ace', 'a1..5e'], {expand: true}); - match('a{/../}e', ['a/e'], {expand: true}); - match('a{/../,z}e', ['a/../e', 'aze'], {expand: true}); - match('a{b,c/*/../d}e', ['abe', 'ac/*/../de'], {expand: true}); - match('a{b,b,c/../b}d', ['abd', 'abd', 'ac/../bd'], {expand: true}); - }); -}); diff -Nru node-braces-2.0.2/test/braces.parse.js node-braces-3.0.2/test/braces.parse.js --- node-braces-2.0.2/test/braces.parse.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/test/braces.parse.js 2019-04-16 19:50:10.000000000 +0000 @@ -1,18 +1,49 @@ 'use strict'; require('mocha'); -var assert = require('assert'); -var braces = require('..'); +const assert = require('assert').strict; +const parse = require('../lib/parse'); -describe('.parse', function() { - it('should return an AST object', function() { - var ast = braces.parse('a/{b,c}/d'); - assert(ast); - assert.equal(typeof ast, 'object'); +describe('braces.parse()', () => { + describe('errors', () => { + it('should throw an error when string exceeds max safe length', () => { + let MAX_LENGTH = 1024 * 64; + assert.throws(() => parse('.'.repeat(MAX_LENGTH + 2))); + }); }); - it('should have an array of nodes', function() { - var ast = braces.parse('a/{b,c}/d'); - assert(Array.isArray(ast.nodes)); + describe('valid', () => { + it('should return an AST', () => { + let ast = parse('a/{b,c}/d'); + let 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'); + 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] === '['); + assert(bracket); + assert.equal(bracket.value, '[{c,d}]'); + }); + }); + + describe('invalid', () => { + it('should escape standalone closing braces', () => { + let one = parse('}'); + assert.equal(one.nodes[1].type, 'text'); + assert.equal(one.nodes[1].value, '}'); + + let two = parse('a}b'); + assert.equal(two.nodes[1].type, 'text'); + assert.equal(two.nodes[1].value, 'a}b'); + }); }); }); diff -Nru node-braces-2.0.2/test/expanded.integration.js node-braces-3.0.2/test/expanded.integration.js --- node-braces-2.0.2/test/expanded.integration.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/test/expanded.integration.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -'use strict'; - -var assert = require('assert'); -var braces = require('..'); - -function match(pattern, expected, options) { - var actual = braces.expand(pattern, options).sort(); - assert.deepEqual(actual, expected.sort(), pattern); -} - -describe('integration', function() { - it('should work with dots in file paths', function() { - match('../{1..3}/../foo', ['../1/../foo', '../2/../foo', '../3/../foo']); - match('../{2..10..2}/../foo', ['../2/../foo', '../4/../foo', '../6/../foo', '../8/../foo', '../10/../foo']); - match('../{1..3}/../{a,b,c}/foo', ['../1/../a/foo', '../2/../a/foo', '../3/../a/foo', '../1/../b/foo', '../2/../b/foo', '../3/../b/foo', '../1/../c/foo', '../2/../c/foo', '../3/../c/foo']); - match('./{a..z..3}/', ['./a/', './d/', './g/', './j/', './m/', './p/', './s/', './v/', './y/']); - match('./{"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/']); - }); - - it('should expand a complex combination of ranges and sets:', function() { - match('a/{x,y}/{1..5}c{d,e}f.{md,txt}', ['a/x/1cdf.md', 'a/y/1cdf.md', 'a/x/2cdf.md', 'a/y/2cdf.md', 'a/x/3cdf.md', 'a/y/3cdf.md', 'a/x/4cdf.md', 'a/y/4cdf.md', 'a/x/5cdf.md', 'a/y/5cdf.md', 'a/x/1cef.md', 'a/y/1cef.md', 'a/x/2cef.md', 'a/y/2cef.md', 'a/x/3cef.md', 'a/y/3cef.md', 'a/x/4cef.md', 'a/y/4cef.md', 'a/x/5cef.md', 'a/y/5cef.md', 'a/x/1cdf.txt', 'a/y/1cdf.txt', 'a/x/2cdf.txt', 'a/y/2cdf.txt', 'a/x/3cdf.txt', 'a/y/3cdf.txt', 'a/x/4cdf.txt', 'a/y/4cdf.txt', 'a/x/5cdf.txt', 'a/y/5cdf.txt', 'a/x/1cef.txt', 'a/y/1cef.txt', 'a/x/2cef.txt', 'a/y/2cef.txt', 'a/x/3cef.txt', 'a/y/3cef.txt', 'a/x/4cef.txt', 'a/y/4cef.txt', 'a/x/5cef.txt', 'a/y/5cef.txt']); - }); - - it('should expand complex sets and ranges in `bash` mode:', function() { - match('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']); - }); -}); diff -Nru node-braces-2.0.2/test/expanded.ranges.js node-braces-3.0.2/test/expanded.ranges.js --- node-braces-2.0.2/test/expanded.ranges.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/test/expanded.ranges.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,187 +0,0 @@ -'use strict'; - -var assert = require('assert'); -var braces = require('..'); - -function match(pattern, expected) { - var actual = braces.expand(pattern).sort(); - assert.deepEqual(actual, expected.sort()); -} - -describe('expanded ranges', function() { - describe('escaping / invalid ranges', function() { - it('should not try to expand ranges with decimals', function() { - match('{1.1..2.1}', ['{1.1..2.1}']); - match('{1.1..~2.1}', ['{1.1..~2.1}']); - }); - - it('should escape invalid ranges:', function() { - match('{1..0f}', ['{1..0f}']); - match('{1..10..ff}', ['{1..10..ff}']); - match('{1..10.f}', ['{1..10.f}']); - match('{1..10f}', ['{1..10f}']); - match('{1..20..2f}', ['{1..20..2f}']); - match('{1..20..f2}', ['{1..20..f2}']); - match('{1..2f..2}', ['{1..2f..2}']); - match('{1..ff..2}', ['{1..ff..2}']); - match('{1..ff}', ['{1..ff}']); - match('{1.20..2}', ['{1.20..2}']); - }); - - it('weirdly-formed brace expansions -- fixed in post-bash-3.1', function() { - match('a-{b{d,e}}-c', ['a-{bd}-c', 'a-{be}-c']); - match('a-{bdef-{g,i}-c', ['a-{bdef-g-c', 'a-{bdef-i-c']); - }); - - it('should not expand quoted strings.', function() { - match('{"klklkl"}{1,2,3}', ['{klklkl}1', '{klklkl}2', '{klklkl}3']); - match('{"x,x"}', ['{x,x}']); - }); - - it('should escaped outer braces in nested non-sets', function() { - match('{a-{b,c,d}}', ['{a-b}', '{a-c}', '{a-d}']); - match('{a,{a-{b,c,d}}}', ['a', '{a-b}', '{a-c}', '{a-d}']); - }); - - it('should escape imbalanced braces', function() { - match('a-{bdef-{g,i}-c', ['a-{bdef-g-c', 'a-{bdef-i-c']); - match('abc{', ['abc{']); - match('{abc{', ['{abc{']); - match('{abc', ['{abc']); - match('}abc', ['}abc']); - match('ab{c', ['ab{c']); - match('ab{c', ['ab{c']); - match('{{a,b}', ['{a', '{b']); - match('{a,b}}', ['a}', 'b}']); - match('abcd{efgh', ['abcd{efgh']); - match('a{b{c{d,e}f}g}h', ['a{b{cdf}g}h', 'a{b{cef}g}h']); - match('f{x,y{{g,z}}h}', ['fx', 'fy{g}h', 'fy{z}h']); - match('z{a,b},c}d', ['za,c}d', 'zb,c}d']); - match('a{b{c{d,e}f{x,y{{g}h', ['a{b{cdf{x,y{{g}h', 'a{b{cef{x,y{{g}h']); - match('f{x,y{{g}h', ['f{x,y{{g}h']); - match('f{x,y{{g}}h', ['f{x,y{{g}}h']); - match('a{b{c{d,e}f{x,y{}g}h', ['a{b{cdfxh', 'a{b{cdfy{}gh', 'a{b{cefxh', 'a{b{cefy{}gh']); - match('f{x,y{}g}h', ['fxh', 'fy{}gh']); - match('z{a,b{,c}d', ['z{a,bd', 'z{a,bcd']); - }); - }); - - describe('positive numeric ranges', function() { - it('should expand numeric ranges', function() { - match('a{0..3}d', ['a0d', 'a1d', 'a2d', 'a3d']); - match('x{10..1}y', ['x10y', 'x9y', 'x8y', 'x7y', 'x6y', 'x5y', 'x4y', 'x3y', 'x2y', 'x1y']); - match('x{3..3}y', ['x3y']); - match('{1..10}', ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); - match('{1..3}', ['1', '2', '3']); - match('{1..9}', ['1', '2', '3', '4', '5', '6', '7', '8', '9']); - match('{10..1}', ['10', '9', '8', '7', '6', '5', '4', '3', '2', '1']); - match('{10..1}y', ['10y', '9y', '8y', '7y', '6y', '5y', '4y', '3y', '2y', '1y']); - match('{3..3}', ['3']); - match('{5..8}', ['5', '6', '7', '8']); - }); - }); - - describe('negative ranges', function() { - it('should expand ranges with negative numbers', function() { - match('{-10..-1}', ['-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1']); - match('{-20..0}', ['-20', '-19', '-18', '-17', '-16', '-15', '-14', '-13', '-12', '-11', '-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1', '0']); - match('{0..-5}', ['0', '-1', '-2', '-3', '-4', '-5']); - match('{9..-4}', ['9', '8', '7', '6', '5', '4', '3', '2', '1', '0', '-1', '-2', '-3', '-4']); - }); - }); - - describe('alphabetical ranges', function() { - it('should expand alphabetical ranges', function() { - match('{a..F}', ['F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a']); - match('0{a..d}0', ['0a0', '0b0', '0c0', '0d0']); - match('a/{b..d}/e', ['a/b/e', 'a/c/e', 'a/d/e']); - match('{1..f}', ['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']); - match('{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']); - match('{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']); - match('{a..e}', ['a', 'b', 'c', 'd', 'e']); - match('{A..E}', ['A', 'B', 'C', 'D', 'E']); - match('{a..f}', ['a', 'b', 'c', 'd', 'e', 'f']); - match('{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']); - match('{E..A}', ['E', 'D', 'C', 'B', 'A']); - match('{f..1}', ['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']); - match('{f..a}', ['f', 'e', 'd', 'c', 'b', 'a']); - match('{f..f}', ['f']); - }); - - it('should expand multiple ranges:', function() { - match('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']); - }); - }); - - describe('combo', function() { - it('should expand numerical ranges - positive and negative', function() { - match('a{01..05}b', ['a01b', 'a02b', 'a03b', 'a04b', 'a05b' ]); - match('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' ]); - match('{-10..10}', ['-1', '-10', '-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '0', '1', '10', '2', '3', '4', '5', '6', '7', '8', '9' ]); - }); - }); - - // HEADS UP! If you're using the `--mm` flag minimatch freezes on these - describe('large numbers', function() { - it('should expand large numbers', function() { - match('{2147483645..2147483649}', ['2147483645', '2147483646', '2147483647', '2147483648', '2147483649']); - match('{214748364..2147483649}', ['(21474836[4-9]|2147483[7-9][0-9]|214748[4-9][0-9]{2}|214749[0-9]{3}|2147[5-9][0-9]{4}|214[8-9][0-9]{5}|21[5-9][0-9]{6}|2[2-9][0-9]{7}|[3-9][0-9]{8}|1[0-9]{9}|20[0-9]{8}|21[0-3][0-9]{7}|214[0-6][0-9]{6}|2147[0-3][0-9]{5}|21474[0-7][0-9]{4}|214748[0-2][0-9]{3}|2147483[0-5][0-9]{2}|21474836[0-4][0-9])']); - }); - }); - - describe('steps > positive ranges', function() { - it('should expand ranges using steps:', function() { - match('{1..10..1}', ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); - match('{1..10..2}', ['1', '3', '5', '7', '9']); - match('{1..20..20}', ['1']); - match('{1..20..2}', ['1', '3', '5', '7', '9', '11', '13', '15', '17', '19']); - match('{10..0..2}', ['10', '8', '6', '4', '2', '0']); - match('{10..1..2}', ['10', '8', '6', '4', '2']); - match('{100..0..5}', ['100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']); - match('{2..10..1}', ['2', '3', '4', '5', '6', '7', '8', '9', '10']); - match('{2..10..2}', ['2', '4', '6', '8', '10']); - match('{2..10..3}', ['2', '5', '8']); - match('{a..z..2}', ['a', 'c', 'e', 'g', 'i', 'k', 'm', 'o', 'q', 's', 'u', 'w', 'y']); - }); - - it('should expand positive ranges with negative steps:', function() { - match('{10..0..-2}', ['10', '8', '6', '4', '2', '0']); - }); - }); - - describe('steps > negative ranges', function() { - it('should expand negative ranges using steps:', function() { - match('{-1..-10..-2}', ['-1', '-3', '-5', '-7', '-9']); - match('{-1..-10..2}', ['-1', '-3', '-5', '-7', '-9']); - match('{-10..-2..2}', ['-10', '-8', '-6', '-4', '-2']); - match('{-2..-10..1}', ['-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '-10']); - match('{-2..-10..2}', ['-2', '-4', '-6', '-8', '-10']); - match('{-2..-10..3}', ['-2', '-5', '-8']); - match('{-50..-0..5}', ['-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0']); - match('{10..1..-2}', ['2', '4', '6', '8', '10']); - match('{100..0..-5}', ['100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']); - }); - }); - - describe('steps > alphabetical ranges', function() { - it('should expand alpha ranges with steps', function() { - match('{a..e..2}', ['a', 'c', 'e']); - match('{E..A..2}', ['E', 'C', 'A']); - match('{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']); - match('{a..z..2}', ['a', 'c', 'e', 'g', 'i', 'k', 'm', 'o', 'q', 's', 'u', 'w', 'y']); - match('{z..a..-2}', ['z', 'x', 'v', 't', 'r', 'p', 'n', 'l', 'j', 'h', 'f', 'd', 'b']); - }); - - it('should expand alpha ranges with negative steps', function() { - match('{z..a..-2}', ['z', 'x', 'v', 't', 'r', 'p', 'n', 'l', 'j', 'h', 'f', 'd', 'b']); - }); - }); - - describe('padding', function() { - it('unwanted zero-padding -- fixed post-bash-4.0', function() { - match('{10..0..2}', ['10', '8', '6', '4', '2', '0']); - match('{10..0..-2}', ['10', '8', '6', '4', '2', '0']); - match('{-50..-0..5}', ['-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0']); - }); - }); -}); diff -Nru node-braces-2.0.2/test/expanded.sets.js node-braces-3.0.2/test/expanded.sets.js --- node-braces-2.0.2/test/expanded.sets.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/test/expanded.sets.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,204 +0,0 @@ -'use strict'; - -var assert = require('assert'); -var braces = require('..'); - -function match(pattern, expected) { - assert.deepEqual(braces.expand(pattern).sort(), expected.sort()); -} - -describe('expanded sets', function() { - describe('invalid sets', function() { - it('should handle invalid sets:', function() { - match('{0..10,braces}', ['0..10', 'braces']); - match('{1..10,braces}', ['1..10', 'braces']); - }); - }); - - describe('escaping', function() { - it('should not expand escaped braces', function() { - match('y{\\},a}x', ['y}x', 'yax']); - match('{a,\\\\{a,b}c}', ['a', '\\\\ac', '\\\\bc']); - match('\\{a,b,c,d,e}', ['{a,b,c,d,e}']); - match('a/b/c/{x,y\\}', ['a/b/c/{x,y}']); - match('a/\\{x,y}/cde', ['a/{x,y}/cde']); - match('abcd{efgh', ['abcd{efgh']); - match('{abc}', ['{abc}']); - match('{x,y,\\{a,b,c\\}}', ['x', 'y', '{a', 'b', 'c}']); - match('{x,y,{a,b,c\\}}', ['{x,y,a', '{x,y,b', '{x,y,c}']); - match('{x,y,{abc},trie}', ['x', 'y', '{abc}', 'trie']); - match('{x\\,y,\\{abc\\},trie}', ['x,y', '{abc}', 'trie']); - }); - - it('should handle empty braces', function() { - match('{ }', ['{ }']); - match('{', ['{']); - match('{}', ['{}']); - match('}', ['}']); - }); - - it('should handle empty sets', function() { - match('{ }', ['{ }']); - match('{', ['{']); - match('{}', ['{}']); - match('}', ['}']); - }); - - it('should escape braces when only one value is defined', function() { - match('a{b}c', ['a{b}c']); - match('a/b/c{d}e', ['a/b/c{d}e']); - }); - - it('should escape closing braces when open is not defined', function() { - match('{a,b}c,d}', ['ac,d}', 'bc,d}']); - }); - - it('should not expand braces in sets with es6/bash-like variables', function() { - match('abc/${ddd}/xyz', ['abc/${ddd}/xyz']); - match('a${b}c', ['a${b}c']); - match('a/{${b},c}/d', ['a/${b}/d', 'a/c/d']); - match('a${b,d}/{foo,bar}c', ['a${b,d}/fooc', 'a${b,d}/barc']); - }); - - it('should not expand escaped commas.', function() { - match('a{b\\,c\\,d}e', ['a{b,c,d}e']); - match('a{b\\,c}d', ['a{b,c}d']); - match('{abc\\,def}', ['{abc,def}']); - match('{abc\\,def,ghi}', ['abc,def', 'ghi']); - match('a/{b,c}/{x\\,y}/d/e', ['a/b/{x,y}/d/e', 'a/c/{x,y}/d/e']); - }); - - it('should return sets with escaped commas', function() { - }); - - it('should not expand escaped braces.', function() { - match('{a,b\\}c,d}', ['a', 'b}c', 'd']); - match('\\{a,b,c,d,e}', ['{a,b,c,d,e}']); - match('a/{z,\\{a,b,c,d,e}/d', ['a/{a/d', 'a/b/d', 'a/c/d', 'a/d/d', 'a/e/d', 'a/z/d']); - match('a/\\{b,c}/{d,e}/f', ['a/{b,c}/d/f', 'a/{b,c}/e/f']); - match('./\\{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/']); - }); - - it('should not expand escaped braces or commas.', function() { - match('{x\\,y,\\{abc\\},trie}', ['{abc}', 'trie', 'x,y']); - }); - }); - - describe('multipliers', function() { - it('should support multipliers', function() { - match('{{d,d},e}{,}', ['d', 'd', 'd', 'd', 'e', 'e']); - match('{d{,},e}{,}', ['d', 'd', 'd', 'd', 'e', 'e']); - match('a/{,}{c,d}/e', ['a/c/e', 'a/c/e', 'a/d/e', 'a/d/e']); - match('a/{c,d}{,}/e', ['a/c/e', 'a/c/e', 'a/d/e', 'a/d/e']); - match('a/{b,c{,}}', ['a/b', 'a/c', 'a/c']); - match('a{,,}', ['a', 'a', 'a']); - match('a{,}', ['a', 'a']); - match('a{,}/{c,d}/e', ['a/c/e', 'a/c/e', 'a/d/e', 'a/d/e']); - match('a{,}{,}', ['a', 'a', 'a', 'a']); - match('a{,}{,}{,}', ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']); - match('a{,}{,}{,}{,}', ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']); - match('{,}', []); - match('{a,b{,}{,}{,},c}d', ['ad', 'bd', 'bd', 'bd', 'bd', 'bd', 'bd', 'bd', 'bd', 'cd']); - match('{a,b{,}{,}{,}}', ['a', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b']); - match('{a{,,}b{,}}', ['{ab}', '{ab}', '{ab}', '{ab}', '{ab}', '{ab}']); - match('{d{,},e}{,}', ['d', 'd', 'd', 'd', 'e', 'e']); - match('a/{b,c}{,}/{d{,},e}{,}', ['a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/e', 'a/b/e', 'a/b/e', 'a/b/e', 'a/c/d', 'a/c/d', 'a/c/d', 'a/c/d', 'a/c/d', 'a/c/d', 'a/c/d', 'a/c/d', 'a/c/e', 'a/c/e', 'a/c/e', 'a/c/e']); - match('a/{b,c{,}}', ['a/b', 'a/c', 'a/c']); - match('a{,,}', ['a', 'a', 'a']); - match('a{,}', ['a', 'a']); - match('a{,}/{c,d}/e', ['a/c/e', 'a/c/e', 'a/d/e', 'a/d/e']); - match('a/{,}{c,d}/e', ['a/c/e', 'a/c/e', 'a/d/e', 'a/d/e']); - match('a/{c,d}{,}/e', ['a/c/e', 'a/c/e', 'a/d/e', 'a/d/e']); - match('a{,}{,}', ['a', 'a', 'a', 'a']); - match('a{,}{,}{,}', ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']); - match('a{,}{,}{,}{,}', ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']); - match('{,}', []); - match('{a,b{,}{,}{,},c}d', ['ad', 'bd', 'bd', 'bd', 'bd', 'bd', 'bd', 'bd', 'bd', 'cd']); - match('{a,b{,}{,}{,}}', ['a', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b']); - match('{a{,,}b{,}}', ['{ab}', '{ab}', '{ab}', '{ab}', '{ab}', '{ab}']); - }); - }); - - describe('set expansion', function() { - it('should support sequence brace operators', function() { - match('{a,b,c}', ['a', 'b', 'c']); - match('{1..10}', ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); - }); - - it('should support sequence braces with leading characters', function() { - match('/usr/{ucb/{ex,edit},lib/{ex,how_ex}}', ['/usr/lib/ex', '/usr/lib/how_ex', '/usr/ucb/edit', '/usr/ucb/ex']); - match('ff{c,b,a}', ['ffa', 'ffb', 'ffc']); - }); - - it('should support sequence braces with trailing characters', function() { - match('f{d,e,f}g', ['fdg', 'feg', 'ffg']); - match('{l,n,m}xyz', ['lxyz', 'mxyz', 'nxyz']); - }); - - it('should support sequence braces with trailing characters', function() { - match('{braces,{0..10}}', ['braces', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); - match('{{0..10},braces}', ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'braces']); - match('{{1..10..2},braces}', ['1', '3', '5', '7', '9', 'braces']); - match('{{1..10},braces}', ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'braces']); - }); - - it('should support nested sequence braces with trailing characters', function() { - match('x{{0..10},braces}y', ['xbracesy', 'x0y', 'x1y', 'x2y', 'x3y', 'x4y', 'x5y', 'x6y', 'x7y', 'x8y', 'x9y', 'x10y']); - }); - - it('should expand multiple sets', function() { - match('a/{a,b}/{c,d}/e', ['a/a/c/e', 'a/a/d/e', 'a/b/c/e', 'a/b/d/e']); - match('a{b,c}d{e,f}g', ['abdeg', 'abdfg', 'acdeg', 'acdfg']); - match('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']); - }); - - it('should expand nested sets', function() { - match('{{d,d},e}{}', ['d{}', 'd{}', 'e{}']); - match('{{d,d},e}a', ['da', 'da', 'ea']); - match('{{d,d},e}{a,b}', ['da', 'da', 'db', 'db', 'ea', 'eb']); - match('{d,d,{d,d},{e,e}}', ['d', 'd', 'd', 'd', 'e', 'e']); - match('{{d,d},e}{a,b}', ['da', 'da', 'db', 'db', 'ea', 'eb']); - match('{{d,d},e}', ['d', 'd', 'e']); - match('{a,b}{{a,b},a,b}', ['aa', 'aa', 'ab', 'ab', 'ba', 'ba', 'bb', 'bb']); - match('a{b,c{d,e}f}g', ['abg', 'acdfg', 'acefg']); - match('a{{x,y},z}b', ['axb', 'ayb', 'azb']); - match('f{x,y{g,z}}h', ['fxh', 'fygh', 'fyzh']); - match('a{b,c{d,e},h}x/z', ['abx/z', 'acdx/z', 'acex/z', 'ahx/z']); - match('a{b,c{d,e},h}x{y,z}', ['abxy', 'abxz', 'acdxy', 'acdxz', 'acexy', 'acexz', 'ahxy', 'ahxz']); - match('a{b,c{d,e},{f,g}h}x{y,z}', ['abxy', 'abxz', 'acdxy', 'acdxz', 'acexy', 'acexz', 'afhxy', 'afhxz', 'aghxy', 'aghxz']); - match('a-{b{d,e}}-c', ['a-{bd}-c', 'a-{be}-c']); - }); - - it('should expand with globs.', function() { - match('a/b/{d,e}/*.js', ['a/b/d/*.js', 'a/b/e/*.js']); - match('a/**/c/{d,e}/f*.js', ['a/**/c/d/f*.js', 'a/**/c/e/f*.js']); - match('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']); - match('a/b/{d,e,[1-5]}/*.js', ['a/b/d/*.js', 'a/b/e/*.js', 'a/b/[1-5]/*.js']); - }); - }); - - describe('commas', function() { - it('should work with leading and trailing commas.', function() { - match('a{b,}c', ['abc', 'ac']); - match('a{,b}c', ['abc', 'ac']); - match('{{a,b},a}c', ['ac', 'ac', 'bc']); - match('{{a,b},}c', ['ac', 'bc', 'c']); - match('a{{a,b},}c', ['aac', 'abc', 'ac']); - }); - }); - - describe('spaces', function() { - it('should handle spaces', function() { - match('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']); - match('a{ ,c{d, },h}x', ['acdx', 'ac x', 'ahx', 'a x']); - match('a{ ,c{d, },h} ', ['a ', 'ac ', 'acd ', 'ah ']); - - // see https://github.com/jonschlinkert/micromatch/issues/66 - match('/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.{html,ejs}', ['/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.ejs', '/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.html' ]); - - // Bash 4.3 says the following should be equivalent to `foo|(1|2)|bar`, - // That makes sense in Bash, since ' ' is a separator, but not here. - match('foo {1,2} bar', ['foo 1 bar', 'foo 2 bar']); - }); - }); -}); diff -Nru node-braces-2.0.2/test/minimatch.js node-braces-3.0.2/test/minimatch.js --- node-braces-2.0.2/test/minimatch.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/test/minimatch.js 2019-04-16 19:50:10.000000000 +0000 @@ -1,27 +1,27 @@ 'use strict'; -var assert = require('assert'); -var braces = require('..'); +const assert = require('assert').strict; +const braces = require('..'); /** * minimatch v3.0.3 unit tests */ -describe('brace expansion', function() { - var units = [ +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{b}c', ['a{b}c']], ['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,bcd', 'z{a,bd']], + ['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'] ] ]; - units.forEach(function(unit) { - it('should expand: ' + unit[0], function() { + units.forEach(unit => { + it('should expand: ' + unit[0], () => { assert.deepEqual(braces.expand(unit[0]), unit[1], unit[0]); }); }); diff -Nru node-braces-2.0.2/test/multiples.js node-braces-3.0.2/test/multiples.js --- node-braces-2.0.2/test/multiples.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/test/multiples.js 2019-04-16 19:50:10.000000000 +0000 @@ -1,31 +1,31 @@ 'use strict'; -var assert = require('assert'); -var braces = require('..'); +const assert = require('assert').strict; +const braces = require('..'); -function match(pattern, expected, options) { - var actual = braces.expand(pattern, options).sort(); - assert.deepEqual(actual, expected.sort(), pattern); -} +const equal = (input, expected, options) => { + assert.deepEqual(braces.expand(input, options), expected); +}; -describe('multiples', function() { - var patterns = [ +describe('multiples', () => { + const patterns = [ ['-v{,,,,}', ['-v', '-v', '-v', '-v', '-v']], ['-v{,,,,}{,}', ['-v', '-v', '-v', '-v', '-v', '-v', '-v', '-v', '-v', '-v']], ['a/b{,}', ['a/b', 'a/b']], ['a/{,}/b', ['a//b', 'a//b']], - ['a/{,}{c,d}/e', ['a/c/e', 'a/c/e', 'a/d/e', 'a/d/e']], - ['a/{a,b,{,}{,}{,},c}/b', ['a//b', 'a//b', 'a//b', 'a//b', 'a//b', 'a//b', 'a//b', 'a//b', 'a/a/b', 'a/b/b', 'a/c/b']], - ['a/{a,b,{,}{,}{,}}/b', ['a//b', 'a//b', 'a//b', 'a//b', 'a//b', 'a//b', 'a//b', 'a//b', 'a/a/b', 'a/b/b']], - ['a/{b,cz{,}}/{d{,},ef}{,}', ['a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/ef', 'a/b/ef', 'a/cz/d', 'a/cz/d', 'a/cz/d', 'a/cz/d', 'a/cz/d', 'a/cz/d', 'a/cz/d', 'a/cz/d', 'a/cz/ef', 'a/cz/ef', 'a/cz/ef', 'a/cz/ef']], - ['a/{b,cz}{,}/{d{,},ef}{,}', ['a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/ef', 'a/b/ef', 'a/b/ef', 'a/b/ef', 'a/cz/d', 'a/cz/d', 'a/cz/d', 'a/cz/d', 'a/cz/d', 'a/cz/d', 'a/cz/d', 'a/cz/d', 'a/cz/ef', 'a/cz/ef', 'a/cz/ef', 'a/cz/ef']], + ['a/{,}{c,d}/e', ['a/c/e', 'a/d/e', 'a/c/e', 'a/d/e']], + ['a/{a,b,{,}{,}{,},c}/b', ['a/a/b', 'a/b/b', 'a//b', 'a//b', 'a//b', 'a//b', 'a//b', 'a//b', 'a//b', 'a//b', 'a/c/b']], + ['a/{a,b,{,},c}/b', ['a/a/b', 'a/b/b', 'a//b', 'a//b', 'a/c/b']], + ['a/{a,b,{,}{,}{,}}/b', ['a/a/b', 'a/b/b', 'a//b', 'a//b', 'a//b', 'a//b', 'a//b', 'a//b', 'a//b', 'a//b']], + ['a/{b,cz{,}}/{d{,},ef}{,}', ['a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/ef', 'a/b/ef', 'a/cz/d', 'a/cz/d', 'a/cz/d', 'a/cz/d', 'a/cz/ef', 'a/cz/ef', 'a/cz/d', 'a/cz/d', 'a/cz/d', 'a/cz/d', 'a/cz/ef', 'a/cz/ef']], + ['a/{b,cz}{,}/{d{,},ef}{,}', ['a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/ef', 'a/b/ef', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/ef', 'a/b/ef', 'a/cz/d', 'a/cz/d', 'a/cz/d', 'a/cz/d', 'a/cz/ef', 'a/cz/ef', 'a/cz/d', 'a/cz/d', 'a/cz/d', 'a/cz/d', 'a/cz/ef', 'a/cz/ef']], ['a/{b,c{,}}', ['a/b', 'a/c', 'a/c']], ['a/{b,c{,}}/{,}', ['a/b/', 'a/b/', 'a/c/', 'a/c/', 'a/c/', 'a/c/']], ['a/{b,c}/{,}', ['a/b/', 'a/b/', 'a/c/', 'a/c/']], ['a/{b,c}{,}/d{,}', ['a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/c/d', 'a/c/d', 'a/c/d', 'a/c/d']], - ['a/{b,c}{,}/{d,e{,}}', ['a/b/d', 'a/b/d', 'a/b/e', 'a/b/e', 'a/b/e', 'a/b/e', 'a/c/d', 'a/c/d', 'a/c/e', 'a/c/e', 'a/c/e', 'a/c/e']], - ['a/{b,c}{,}/{d,e}{,}', ['a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/e', 'a/b/e', 'a/b/e', 'a/b/e', 'a/c/d', 'a/c/d', 'a/c/d', 'a/c/d', 'a/c/e', 'a/c/e', 'a/c/e', 'a/c/e']], - ['a/{b,c}{,}/{d{,},e}{,}', ['a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/e', 'a/b/e', 'a/b/e', 'a/b/e', 'a/c/d', 'a/c/d', 'a/c/d', 'a/c/d', 'a/c/d', 'a/c/d', 'a/c/d', 'a/c/d', 'a/c/e', 'a/c/e', 'a/c/e', 'a/c/e']], + ['a/{b,c}{,}/{d,e{,}}', ['a/b/d', 'a/b/e', 'a/b/e', 'a/b/d', 'a/b/e', 'a/b/e', 'a/c/d', 'a/c/e', 'a/c/e', 'a/c/d', 'a/c/e', 'a/c/e']], + ['a/{b,c}{,}/{d,e}{,}', ['a/b/d', 'a/b/d', 'a/b/e', 'a/b/e', 'a/b/d', 'a/b/d', 'a/b/e', 'a/b/e', 'a/c/d', 'a/c/d', 'a/c/e', 'a/c/e', 'a/c/d', 'a/c/d', 'a/c/e', 'a/c/e']], + ['a/{b,c}{,}/{d{,},e}{,}', ['a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/e', 'a/b/e', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/d', 'a/b/e', 'a/b/e', 'a/c/d', 'a/c/d', 'a/c/d', 'a/c/d', 'a/c/e', 'a/c/e', 'a/c/d', 'a/c/d', 'a/c/d', 'a/c/d', 'a/c/e', 'a/c/e']], ['a/{c,d}/{x,y{,}}/e', ['a/c/x/e', 'a/c/y/e', 'a/c/y/e', 'a/d/x/e', 'a/d/y/e', 'a/d/y/e']], ['a/{c,d}{,}/e', ['a/c/e', 'a/c/e', 'a/d/e', 'a/d/e']], ['a{,,,,,}', ['a', 'a', 'a', 'a', 'a', 'a']], @@ -38,23 +38,21 @@ ['a{,,}{,,}{,,}{,}/b', ['a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b', 'a/b']], ['a{,,}{,}', ['a', 'a', 'a', 'a', 'a', 'a']], ['a{,}', ['a', 'a']], - ['a{,}/{c,d}/e', ['a/c/e', 'a/c/e', 'a/d/e', 'a/d/e']], + ['a{,}/{c,d}/e', ['a/c/e', 'a/d/e', 'a/c/e', 'a/d/e']], ['a{,}b', ['ab', 'ab']], ['a{,}{,}', ['a', 'a', 'a', 'a']], ['a{,}{,}{,}', ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']], ['a{,}{,}{,}{,}', ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']], ['one/{a{,}{,}}/{b/c{,,}{,}{,,}{,}}/two', ['one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two', 'one/{a}/{b/c}/two']], - ['{,}', []], + ['{,}', ['', '']], ['{,}a/{,}', ['a/', 'a/', 'a/', 'a/']], - ['{,}{,}', []], + ['{,}{,}', ['', '', '', '']], ['{a,b{,}{,}{,},c}d', ['ad', 'bd', 'bd', 'bd', 'bd', 'bd', 'bd', 'bd', 'bd', 'cd']], ['{a,b{,}{,}{,}}', ['a', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b']], ['{a{,,}b{,}}', ['{ab}', '{ab}', '{ab}', '{ab}', '{ab}', '{ab}']] ]; - patterns.forEach(function(pattern) { - it('should expand: ' + pattern[0], function() { - match(pattern[0], pattern[1]); - }); + patterns.forEach(pattern => { + it('should expand: ' + pattern[0], () => equal(pattern[0], pattern[1])); }); }); diff -Nru node-braces-2.0.2/test/optimized.js node-braces-3.0.2/test/optimized.js --- node-braces-2.0.2/test/optimized.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/test/optimized.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,350 +0,0 @@ -/*! - * braces - * - * Copyright (c) 2014-2016, Jon Schlinkert. - * Licensed under the MIT License - */ - -'use strict'; - -require('mocha'); -var assert = require('assert'); -var braces = require('..'); - -function match(pattern, expected, options) { - assert.deepEqual(braces(pattern, options), expected); -} - -describe('optimized', function() { - describe('sets', function() { - describe('invalid sets', function() { - it('should handle invalid sets:', function() { - match('{0..10,braces}', ['(0..10|braces)']); - match('{1..10,braces}', ['(1..10|braces)']); - }); - }); - - describe('escaping', function() { - it('should not expand escaped braces', function() { - match('\\{a,b,c,d,e}', ['{a,b,c,d,e}']); - match('a/b/c/{x,y\\}', ['a/b/c/{x,y}']); - match('a/\\{x,y}/cde', ['a/{x,y}/cde']); - match('abcd{efgh', ['abcd{efgh']); - match('{abc}', ['{abc}']); - match('{x,y,\\{a,b,c\\}}', ['(x|y|{a|b|c})']); - match('{x,y,{a,b,c\\}}', ['{x,y,(a|b|c})']); - match('{x,y,{abc},trie}', ['(x|y|{abc}|trie)']); - match('{x\\,y,\\{abc\\},trie}', ['(x,y|{abc}|trie)']); - }); - - it('should handle spaces', function() { - // Bash 4.3 says the following should be equivalent to `foo|(1|2)|bar`, - // That makes sense in Bash, since ' ' is a separator, but not here. - match('foo {1,2} bar', ['foo (1|2) bar']); - }); - - it('should handle empty braces', function() { - match('{ }', ['{ }']); - match('{', ['{']); - match('{}', ['{}']); - match('}', ['}']); - }); - - it('should escape braces when only one value is defined', function() { - match('a{b}c', ['a{b}c']); - match('a/b/c{d}e', ['a/b/c{d}e']); - }); - - it('should not expand braces in sets with es6/bash-like variables', function() { - match('abc/${ddd}/xyz', ['abc/${ddd}/xyz']); - match('a${b}c', ['a${b}c']); - match('a/{${b},c}/d', ['a/(${b}|c)/d']); - match('a${b,d}/{foo,bar}c', ['a${b,d}/(foo|bar)c']); - }); - - it('should not expand escaped commas.', function() { - match('a{b\\,c\\,d}e', ['a{b,c,d}e']); - match('a{b\\,c}d', ['a{b,c}d']); - match('{abc\\,def}', ['{abc,def}']); - match('{abc\\,def,ghi}', ['(abc,def|ghi)']); - match('a/{b,c}/{x\\,y}/d/e', ['a/(b|c)/{x,y}/d/e']); - }); - - it('should return sets with escaped commas', function() { - match('a/{b,c}/{x\\,y}/d/e', ['a/(b|c)/{x,y}/d/e']); - }); - - it('should not expand escaped braces.', function() { - match('{a,b\\}c,d}', ['(a|b}c|d)']); - match('\\{a,b,c,d,e}', ['{a,b,c,d,e}']); - match('a/{z,\\{a,b,c,d,e}/d', ['a/(z|{a|b|c|d|e)/d']); - match('a/\\{b,c}/{d,e}/f', ['a/{b,c}/(d|e)/f']); - match('./\\{x,y}/{a..z..3}/', ['./{x,y}/(a|d|g|j|m|p|s|v|y)/']); - }); - - it('should not expand escaped braces or commas.', function() { - match('{x\\,y,\\{abc\\},trie}', ['(x,y|{abc}|trie)']); - }); - }); - - describe('set expansion', function() { - it('should support sequence brace operators', function() { - match('/usr/{ucb/{ex,edit},lib/{ex,how_ex}}', ['/usr/(ucb/(ex|edit)|lib/(ex|how_ex))']); - match('ff{c,b,a}', ['ff(c|b|a)']); - match('f{d,e,f}g', ['f(d|e|f)g']); - match('x{{0..10},braces}y', ['x(([0-9]|10)|braces)y']); - match('{1..10}', ['([1-9]|10)']); - match('{a,b,c}', ['(a|b|c)']); - match('{braces,{0..10}}', ['(braces|([0-9]|10))']); - match('{l,n,m}xyz', ['(l|n|m)xyz']); - match('{{0..10},braces}', ['(([0-9]|10)|braces)']); - match('{{1..10..2},braces}', ['((1|3|5|7|9)|braces)']); - match('{{1..10},braces}', ['(([1-9]|10)|braces)']); - }); - - it('should expand multiple sets', function() { - match('a/{a,b}/{c,d}/e', ['a/(a|b)/(c|d)/e']); - match('a{b,c}d{e,f}g', ['a(b|c)d(e|f)g']); - match('a/{x,y}/c{d,e}f.{md,txt}', ['a/(x|y)/c(d|e)f.(md|txt)']); - }); - - it('should expand nested sets', function() { - match('{a,b}{{a,b},a,b}', ['(a|b)((a|b)|a|b)']); - match('a{b,c{d,e}f}g', ['a(b|c(d|e)f)g']); - match('a{{x,y},z}b', ['a((x|y)|z)b']); - match('f{x,y{g,z}}h', ['f(x|y(g|z))h']); - match('a{b,c}{d,e}/hx/z', ['a(b|c)(d|e)/hx/z']); - match('a{b,c{d,e},h}x/z', ['a(b|c(d|e)|h)x/z']); - match('a{b,c{d,e},h}x{y,z}', ['a(b|c(d|e)|h)x(y|z)']); - match('a{b,c{d,e},{f,g}h}x{y,z}', ['a(b|c(d|e)|(f|g)h)x(y|z)']); - match('a-{b{d,e}}-c', ['a-{b(d|e)}-c']); - }); - - it('should expand not modify non-brace characters', function() { - match('a/b/{d,e}/*.js', ['a/b/(d|e)/*.js']); - match('a/**/c/{d,e}/f*.js', ['a/**/c/(d|e)/f*.js']); - match('a/**/c/{d,e}/f*.{md,txt}', ['a/**/c/(d|e)/f*.(md|txt)']); - }); - }); - - describe('commas', function() { - it('should work with leading and trailing commas.', function() { - match('a{b,}c', ['a(b|)c']); - match('a{,b}c', ['a(|b)c']); - }); - }); - - describe('spaces', function() { - it('should handle spaces', function() { - match('0{1..9} {10..20}', ['0([1-9]) (1[0-9]|20)']); - match('a{ ,c{d, },h}x', ['a( |c(d| )|h)x']); - match('a{ ,c{d, },h} ', ['a( |c(d| )|h) ']); - - // see https://github.com/jonschlinkert/micromatch/issues/66 - match('/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.{html,ejs}', ['/Users/tobiasreich/Sites/aaa/bbb/ccc 2016/src/**/[^_]*.(html|ejs)']); - }); - }); - }); - - /** - * Ranges - */ - - describe('ranges', function() { - describe('escaping / invalid ranges', function() { - it('should not try to expand ranges with decimals', function() { - match('{1.1..2.1}', ['{1.1..2.1}']); - match('{1.1..~2.1}', ['{1.1..~2.1}']); - }); - - it('should escape invalid ranges:', function() { - match('{1..0f}', ['{1..0f}']); - match('{1..10..ff}', ['{1..10..ff}']); - match('{1..10.f}', ['{1..10.f}']); - match('{1..10f}', ['{1..10f}']); - match('{1..20..2f}', ['{1..20..2f}']); - match('{1..20..f2}', ['{1..20..f2}']); - match('{1..2f..2}', ['{1..2f..2}']); - match('{1..ff..2}', ['{1..ff..2}']); - match('{1..ff}', ['{1..ff}']); - match('{1..f}', ['([1-f])']); - match('{1.20..2}', ['{1.20..2}']); - }); - - it('weirdly-formed brace expansions -- fixed in post-bash-3.1', function() { - match('a-{b{d,e}}-c', ['a-{b(d|e)}-c']); - match('a-{bdef-{g,i}-c', ['a-{bdef-(g|i)-c']); - }); - - it('should not expand quoted strings.', function() { - match('{"klklkl"}{1,2,3}', ['{klklkl}(1|2|3)']); - match('{"x,x"}', ['{x,x}']); - }); - - it('should escaped outer braces in nested non-sets', function() { - match('{a-{b,c,d}}', ['{a-(b|c|d)}']); - match('{a,{a-{b,c,d}}}', ['(a|{a-(b|c|d)})']); - }); - - it('should escape imbalanced braces', function() { - match('a-{bdef-{g,i}-c', ['a-{bdef-(g|i)-c']); - match('abc{', ['abc{']); - match('{abc{', ['{abc{']); - match('{abc', ['{abc']); - match('}abc', ['}abc']); - match('ab{c', ['ab{c']); - match('{{a,b}', ['{(a|b)']); - match('{a,b}}', ['(a|b)}']); - match('abcd{efgh', ['abcd{efgh']); - match('a{b{c{d,e}f}g}h', ['a(b(c(d|e)f)g)h']); - match('f{x,y{{g,z}}h}', ['f(x|y((g|z))h)']); - match('z{a,b},c}d', ['z(a|b),c}d']); - match('a{b{c{d,e}f{x,y{{g}h', ['a{b{c(d|e)f{x,y{{g}h']); - match('f{x,y{{g}h', ['f{x,y{{g}h']); - match('f{x,y{{g}}h', ['f{x,y{{g}}h']); - match('a{b{c{d,e}f{x,y{}g}h', ['a{b{c(d|e)f(x|y{}g)h']); - match('f{x,y{}g}h', ['f(x|y{}g)h']); - match('z{a,b{,c}d', ['z{a,b(|c)d']); - }); - }); - - describe('positive numeric ranges', function() { - it('should expand numeric ranges', function() { - match('a{0..3}d', ['a([0-3])d']); - match('x{10..1}y', ['x([1-9]|10)y']); - match('x{3..3}y', ['x3y']); - match('{1..10}', ['([1-9]|10)']); - match('{1..3}', ['([1-3])']); - match('{1..9}', ['([1-9])']); - match('{10..1}', ['([1-9]|10)']); - match('{10..1}y', ['([1-9]|10)y']); - match('{3..3}', ['3']); - match('{5..8}', ['([5-8])']); - }); - }); - - describe('negative ranges', function() { - it('should expand ranges with negative numbers', function() { - match('{-1..-10}', ['(-[1-9]|-10)']); - match('{-10..-1}', ['(-[1-9]|-10)']); - match('{-20..0}', ['(-[1-9]|-1[0-9]|-20|0)']); - match('{0..-5}', ['(-[1-5]|0)']); - match('{9..-4}', ['(-[1-4]|[0-9])']); - }); - }); - - describe('alphabetical ranges', function() { - it('should expand alphabetical ranges', function() { - match('0{1..9}/{10..20}', ['0([1-9])/(1[0-9]|20)']); - match('0{a..d}0', ['0([a-d])0']); - match('a/{b..d}/e', ['a/([b-d])/e']); - match('{1..f}', ['([1-f])']); - match('{a..A}', ['([A-a])']); - match('{A..a}', ['([A-a])']); - match('{a..e}', ['([a-e])']); - match('{A..E}', ['([A-E])']); - match('{a..f}', ['([a-f])']); - match('{a..z}', ['([a-z])']); - match('{E..A}', ['([A-E])']); - match('{f..1}', ['([1-f])']); - match('{f..a}', ['([a-f])']); - match('{f..f}', ['f']); - }); - - it('should expand multiple ranges:', function() { - match('a/{b..d}/e/{f..h}', ['a/([b-d])/e/([f-h])']); - }); - }); - - describe('combo', function() { - it('should expand numerical ranges - positive and negative', function() { - match('{-10..10}', ['(-[1-9]|-?10|[0-9])']); - }); - }); - - // HEADS UP! If you're using the `--mm` flag minimatch freezes on these - describe('large numbers', function() { - it('should expand large numbers', function() { - match('{2147483645..2147483649}', ['(214748364[5-9])']); - match('{214748364..2147483649}', ['(21474836[4-9]|2147483[7-9][0-9]|214748[4-9][0-9]{2}|214749[0-9]{3}|2147[5-9][0-9]{4}|214[8-9][0-9]{5}|21[5-9][0-9]{6}|2[2-9][0-9]{7}|[3-9][0-9]{8}|1[0-9]{9}|20[0-9]{8}|21[0-3][0-9]{7}|214[0-6][0-9]{6}|2147[0-3][0-9]{5}|21474[0-7][0-9]{4}|214748[0-2][0-9]{3}|2147483[0-5][0-9]{2}|21474836[0-4][0-9])']); - }); - }); - - describe('steps > positive ranges', function() { - it('should expand ranges using steps:', function() { - match('{1..10..1}', ['([1-9]|10)']); - match('{1..10..2}', ['(1|3|5|7|9)']); - match('{1..20..20}', ['1']); - match('{1..20..20}', ['1']); - match('{1..20..20}', ['1']); - match('{1..20..2}', ['(1|3|5|7|9|11|13|15|17|19)']); - match('{10..0..2}', ['(10|8|6|4|2|0)']); - match('{10..1..2}', ['(10|8|6|4|2)']); - match('{100..0..5}', ['(100|95|90|85|80|75|70|65|60|55|50|45|40|35|30|25|20|15|10|5|0)']); - match('{2..10..1}', ['([2-9]|10)']); - match('{2..10..2}', ['(2|4|6|8|10)']); - match('{2..10..3}', ['(2|5|8)']); - match('{a..z..2}', ['(a|c|e|g|i|k|m|o|q|s|u|w|y)']); - }); - - it('should expand positive ranges with negative steps:', function() { - match('{10..0..-2}', ['(10|8|6|4|2|0)']); - }); - }); - - describe('steps > negative ranges', function() { - it('should expand negative ranges using steps:', function() { - match('{-1..-10..-2}', ['(-(1|3|5|7|9))']); - match('{-1..-10..2}', ['(-(1|3|5|7|9))']); - match('{-10..-2..2}', ['(-(10|8|6|4|2))']); - match('{-2..-10..1}', ['(-[2-9]|-10)']); - match('{-2..-10..2}', ['(-(2|4|6|8|10))']); - match('{-2..-10..3}', ['(-(2|5|8))']); - match('{-50..-0..5}', ['(0|-(50|45|40|35|30|25|20|15|10|5))']); - match('{-9..9..3}', ['(0|3|6|9|-(9|6|3))']); - match('{10..1..-2}', ['(10|8|6|4|2)']); - match('{100..0..-5}', ['(100|95|90|85|80|75|70|65|60|55|50|45|40|35|30|25|20|15|10|5|0)']); - }); - }); - - describe('steps > alphabetical ranges', function() { - it('should expand alpha ranges with steps', function() { - match('{a..e..2}', ['(a|c|e)']); - match('{E..A..2}', ['(E|C|A)']); - match('{a..z}', ['([a-z])']); - match('{a..z..2}', ['(a|c|e|g|i|k|m|o|q|s|u|w|y)']); - match('{z..a..-2}', ['(z|x|v|t|r|p|n|l|j|h|f|d|b)']); - }); - - it('should expand alpha ranges with negative steps', function() { - match('{z..a..-2}', ['(z|x|v|t|r|p|n|l|j|h|f|d|b)']); - }); - }); - - describe('padding', function() { - it('unwanted zero-padding -- fixed post-bash-4.0', function() { - match('{10..0..2}', ['(10|8|6|4|2|0)']); - match('{10..0..-2}', ['(10|8|6|4|2|0)']); - match('{-50..-0..5}', ['(0|-(50|45|40|35|30|25|20|15|10|5))']); - }); - }); - }); - - describe('integration', function() { - it('should work with dots in file paths', function() { - match('../{1..3}/../foo', ['../([1-3])/../foo']); - match('../{2..10..2}/../foo', ['../(2|4|6|8|10)/../foo']); - match('../{1..3}/../{a,b,c}/foo', ['../([1-3])/../(a|b|c)/foo']); - match('./{a..z..3}/', ['./(a|d|g|j|m|p|s|v|y)/']); - match('./{"x,y"}/{a..z..3}/', ['./{x,y}/(a|d|g|j|m|p|s|v|y)/']); - }); - - it('should expand a complex combination of ranges and sets:', function() { - match('a/{x,y}/{1..5}c{d,e}f.{md,txt}', ['a/(x|y)/([1-5])c(d|e)f.(md|txt)']); - }); - - it('should expand complex sets and ranges in `bash` mode:', function() { - match('a/{x,{1..5},y}/c{d}e', ['a/(x|([1-5])|y)/c{d}e']); - }); - }); -}); diff -Nru node-braces-2.0.2/test/options.js node-braces-3.0.2/test/options.js --- node-braces-2.0.2/test/options.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/test/options.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -/*! - * braces - * - * Copyright (c) 2014-2016, Jon Schlinkert. - * Licensed under the MIT License - */ - -'use strict'; - -require('mocha'); -var assert = require('assert'); -var braces = require('..'); - -function match(pattern, expected, options) { - assert.deepEqual(braces(pattern, options).sort(), expected.sort()); -} - -describe('options', function() { - describe('options.expand', function() { - it('should expand braces when `options.expand` is true', function() { - match('a/{b,c}/d', ['a/b/d', 'a/c/d'], {expand: true}); - }); - }); - - describe('options.unescape', function() { - it('should remove backslashes from escaped brace characters', function() { - match('{a,b\\}c,d}', ['(a|b}c|d)']); - match('\\{a,b,c,d,e}', ['{a,b,c,d,e}']); - match('a/{z,\\{a,b,c,d,e}/d', ['a/(z|{a|b|c|d|e)/d']); - match('a/\\{b,c}/{d,e}/f', ['a/{b,c}/(d|e)/f']); - match('./\\{x,y}/{a..z..3}/', ['./{x,y}/(a|d|g|j|m|p|s|v|y)/']); - }); - - it('should not remove backslashes when `options.unescape` is false', function() { - match('{a,b\\}c,d}', ['(a|b\\}c|d)'], {unescape: false}); - match('\\{a,b,c,d,e}', ['\\{a,b,c,d,e}'], {unescape: false}); - match('a/{z,\\{a,b,c,d,e}/d', ['a/(z|\\{a|b|c|d|e)/d'], {unescape: false}); - match('a/\\{b,c}/{d,e}/f', ['a/\\{b,c}/(d|e)/f'], {unescape: false}); - match('./\\{x,y}/{a..z..3}/', ['./\\{x,y}/(a|d|g|j|m|p|s|v|y)/'], {unescape: false}); - }); - }); - - describe('options.nodupes', function() { - it('should not remove duplicates by default', function() { - match('a/{b,b,b}/c', ['a/b/c', 'a/b/c', 'a/b/c'], {expand: true}); - }); - - it('should remove duplicates when `options.nodupes` is true', function() { - match('a/{b,b,b}/c', ['a/b/c'], {expand: true, nodupes: true}); - }); - }); - - describe('options.optimize', function() { - it('should optimize braces when `options.optimize` is true', function() { - match('a/{b,c}/d', ['a/(b|c)/d'], {optimize: true}); - }); - }); - - describe('options.quantifiers:', function() { - it('should not expand regex quantifiers when `options.quantifiers` is true', function() { - match('a{2}c', ['a{2}c']); - match('a{2}c', ['a{2}c'], {quantifiers: true}); - match('a{2,}c', ['a{2,}c'], {quantifiers: true}); - match('a{,2}c', ['a{,2}c'], {quantifiers: true}); - match('a{2,3}c', ['a{2,3}c'], {quantifiers: true}); - }); - - it('should expand non-quantifiers when `options.quantifiers` is true', function() { - match('a{2}c/{x,y}/z', ['a{2}c/(x|y)/z'], {quantifiers: true}); - match('a{2}c/{x,y}/z', ['a{2}c/x/z', 'a{2}c/y/z'], {quantifiers: true, expand: true}); - }); - }); -}); diff -Nru node-braces-2.0.2/test/regression-1.8.5.js node-braces-3.0.2/test/regression-1.8.5.js --- node-braces-2.0.2/test/regression-1.8.5.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/test/regression-1.8.5.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,463 +0,0 @@ -'use strict'; - -var assert = require('assert'); -var braces = require('..'); - -function match(pattern, expected, options) { - options = options || {}; - var fn = braces; - if (options.optimize !== true) { - fn = braces.expand; - } - var actual = fn(pattern, options).sort(); - assert.deepEqual(actual, expected.sort(), pattern); -} - -describe('braces tests from 1.8.5', function() { - it('braces', function() { - match('ff{c,b,a}', ['ffc', 'ffb', 'ffa']); - match('f{d,e,f}g', ['fdg', 'feg', 'ffg']); - match('{l,n,m}xyz', ['lxyz', 'nxyz', 'mxyz']); - match('{abc\\,d,ef}', ['abc,d', 'ef']); - match('{abc}', ['{abc}']); - - match('\\{a,b,c,d,e}', ['{a,b,c,d,e}']); - match('{x,y,\\{a,b,c}}', ['x}', 'y}', '{a}', 'b}', 'c}']); - match('{x\\,y,\\{abc\\},trie}', ['x,y', '{abc}', 'trie']); - - match('/usr/{ucb/{ex,edit},lib/{ex,how_ex}}', ['/usr/ucb/ex', '/usr/lib/ex', '/usr/ucb/edit', '/usr/lib/how_ex']); - - match('{}', ['{}']); - match('{ }', ['{ }']); - match('}', ['}']); - match('{', ['{']); - match('abcd{efgh', ['abcd{efgh']); - - match('foo {1,2} bar', ['foo 1 bar', 'foo 2 bar']); - }); - - it('new sequence brace operators', function() { - match('{1..10}', ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); - match('{0..10,braces}', ['0..10', 'braces']); - match('{braces,{0..10}}', ['braces', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); - match('{{0..10},braces}', ['0', 'braces', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); - match('x{{0..10},braces}y', ['x0y', 'xbracesy', 'x1y', 'x2y', 'x3y', 'x4y', 'x5y', 'x6y', 'x7y', 'x8y', 'x9y', 'x10y']); - }); - - it('ranges', function() { - match('{3..3}', ['3']); - match('x{3..3}y', ['x3y']); - match('{10..1}', ['10', '9', '8', '7', '6', '5', '4', '3', '2', '1']); - match('{10..1}y', ['10y', '9y', '8y', '7y', '6y', '5y', '4y', '3y', '2y', '1y']); - match('x{10..1}y', ['x10y', 'x9y', 'x8y', 'x7y', 'x6y', 'x5y', 'x4y', 'x3y', 'x2y', 'x1y']); - match('{a..f}', ['a', 'b', 'c', 'd', 'e', 'f']); - match('{f..a}', ['f', 'e', 'd', 'c', 'b', 'a']); - - match('{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']); - match('{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']); - - match('{f..f}', ['f']); - match('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']); - }); - - it('mixes are incorrectly-formed brace expansions', function() { - // the first one is valid, but Bash fails on it - match('{1..f}', ['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']); - match('{f..1}', ['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']); - }); - - it('do negative numbers work?', function() { - match('{-1..-10}', ['-1', '-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '-10']); - match('{-20..0}', ['-20', '-19', '-18', '-17', '-16', '-15', '-14', '-13', '-12', '-11', '-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1', '0']); - }); - - it('weirdly-formed brace expansions -- fixed in post-bash-3.1', function() { - match('{-1..-10}', ['-1', '-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '-10']); - match('{-20..0}', ['-20', '-19', '-18', '-17', '-16', '-15', '-14', '-13', '-12', '-11', '-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1', '0']); - match('a-{b{d,e}}-c', ['a-{bd}-c', 'a-{be}-c']); - - match('a-{bdef-{g,i}-c', ['a-{bdef-g-c', 'a-{bdef-i-c']); - - match('{"klklkl"}{1,2,3}', ['{klklkl}1', '{klklkl}2', '{klklkl}3']); - match('{"x,x"}', ['{x,x}']); - }); - - it('numerical ranges with steps', function() { - match('{1..10..2}', ['1', '3', '5', '7', '9']); - match('{-1..-10..2}', ['-1', '-3', '-5', '-7', '-9']); - match('{-1..-10..-2}', ['-1', '-3', '-5', '-7', '-9']); - - match('{10..1..-2}', ['10', '8', '6', '4', '2']); - match('{10..1..2}', ['10', '8', '6', '4', '2']); - - match('{1..20..2}', ['1', '3', '5', '7', '9', '11', '13', '15', '17', '19']); - match('{1..20..20}', ['1']); - - match('{100..0..5}', ['100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']); - match('{100..0..-5}', ['100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']); - }); - - it('alpha ranges with steps', function() { - match('{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']); - match('{a..z..2}', ['a', 'c', 'e', 'g', 'i', 'k', 'm', 'o', 'q', 's', 'u', 'w', 'y']); - match('{z..a..-2}', ['z', 'x', 'v', 't', 'r', 'p', 'n', 'l', 'j', 'h', 'f', 'd', 'b']); - }); - - it('make sure brace expansion handles ints > 2**31 - 1 using intmax_t', function() { - match('{2147483645..2147483649}', ['2147483645', '2147483646', '2147483647', '2147483648', '2147483649']); - }); - - it('unwanted zero-padding -- fixed post-bash-4.0', function() { - match('{10..0..2}', ['10', '8', '6', '4', '2', '0']); - match('{10..0..-2}', ['10', '8', '6', '4', '2', '0']); - match('{-50..-0..5}', ['-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0']); - }); - - it('bad', function() { - match('{1..10.f}', ['{1..10.f}']); - match('{1..ff}', ['{1..ff}']); - match('{1..10..ff}', ['{1..10..ff}']); - match('{1.20..2}', ['{1.20..2}']); - match('{1..20..f2}', ['{1..20..f2}']); - match('{1..20..2f}', ['{1..20..2f}']); - match('{1..2f..2}', ['{1..2f..2}']); - match('{1..ff..2}', ['{1..ff..2}']); - match('{1..ff}', ['{1..ff}']); - match('{1..0f}', ['{1..0f}']); - match('{1..10f}', ['{1..10f}']); - match('{1..10.f}', ['{1..10.f}']); - match('{1..10.f}', ['{1..10.f}']); - }); -}); - -describe('bash tests', function() { - describe('brace expansion', function() { - it('should return an empty array when no braces are found', function() { - match('', ['']); - }); - - it('should expand emty sets', function() { - match('a{,}', ['a', 'a']); - match('{,}b', ['b', 'b']); - match('a{,}b', ['ab', 'ab']); - match('a{,}', ['a', 'a']); - match('a{,}{,}', ['a', 'a', 'a', 'a']); - match('a{,}{,}{,}', ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']); - match('{a,b{,}{,}{,}}', ['a', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b']); - match('a{,}/{c,d}/e', ['a/c/e', 'a/c/e', 'a/d/e', 'a/d/e']); - match('{a,b{,}{,}{,},c}d', ['ad', 'bd', 'bd', 'bd', 'bd', 'bd', 'bd', 'bd', 'bd', 'cd']); - }); - - it('should eliminate dupes in repeated strings', function() { - match('a{,}', ['a'], {nodupes: true}); - match('a{,}{,}', ['a'], {nodupes: true}); - match('a{,}{,}{,}', ['a'], {nodupes: true}); - match('{a,b{,}{,}{,}}', ['a', 'b'], {nodupes: true}); - match('{a,b{,}{,}{,},c}d', ['ad', 'bd', 'cd'], {nodupes: true}); - match('{a,b{,}{,}{,},c}d', ['ad', 'bd', 'cd'], {nodupes: true}); - }); - - it('should work with no braces', function() { - match('abc', ['abc']); - }); - - it('should work with no commas', function() { - match('a{b}c', ['a{b}c']); - }); - - it('should work with no commas in `bash` mode', function() { - match('a{b}c', ['a{b}c']); - }); - - it('should handle spaces', function() { - match('a{ ,c{d, },h}x', ['a x', 'acdx', 'ac x', 'ahx']); - match('a{ ,c{d, },h} ', [ 'a ', 'acd ', 'ac ', 'ah ' ]); - - // see https://github.com/jonschlinkert/micromatch/issues/66 - match('/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' - ]); - }); - - it('should handle empty braces', function() { - match('{ }', ['{ }']); - match('{}', ['{}']); - match('}', ['}']); - match('{', ['{']); - match('{,}', []); - }); - - it('should handle imbalanced braces', function() { - match('a-{bdef-{g,i}-c', ['a-{bdef-g-c', 'a-{bdef-i-c']); - match('abc{', ['abc{']); - match('{abc{', ['{abc{']); - match('{abc', ['{abc']); - match('}abc', ['}abc']); - match('ab{c', ['ab{c']); - match('ab{c', ['ab{c']); - match('{{a,b}', ['{a', '{b']); - match('{a,b}}', ['a}', 'b}']); - match('abcd{efgh', ['abcd{efgh']); - match('a{b{c{d,e}f}g}h', ['a{b{cdf}g}h', 'a{b{cef}g}h']); - match('f{x,y{{g,z}}h}', ['fx', 'fy{g}h', 'fy{z}h']); - match('z{a,b},c}d', ['za,c}d', 'zb,c}d']); - match('a{b{c{d,e}f{x,y{{g}h', ['a{b{cdf{x,y{{g}h', 'a{b{cef{x,y{{g}h']); - match('f{x,y{{g}h', ['f{x,y{{g}h']); - match('f{x,y{{g}}h', ['f{x,y{{g}}h']); - match('a{b{c{d,e}f{x,y{}g}h', ['a{b{cdfxh', 'a{b{cefxh', 'a{b{cdfy{}gh', 'a{b{cefy{}gh']); - match('f{x,y{}g}h', ['fxh', 'fy{}gh']); - match('z{a,b{,c}d', ['z{a,bd', 'z{a,bcd']); - }); - - it('should handle invalid braces in `bash mode`:', function() { - match('a{b{c{d,e}f}g}h', ['a{b{cdf}g}h', 'a{b{cef}g}h']); - match('f{x,y{{g,z}}h}', ['fx', 'fy{g}h', 'fy{z}h']); - match('z{a,b},c}d', ['za,c}d', 'zb,c}d']); - match('a{b{c{d,e}f{x,y{{g}h', ['a{b{cdf{x,y{{g}h', 'a{b{cef{x,y{{g}h']); - match('f{x,y{{g}h', ['f{x,y{{g}h']); - match('f{x,y{{g}}h', ['f{x,y{{g}}h']); - }); - - it('should return invalid braces:', function() { - match('{0..10,braces}', ['0..10', 'braces']); - }); - - it('should not expand quoted strings.', function() { - match('{"x,x"}', ['{x,x}']); - match('{"klklkl"}{1,2,3}', ['{klklkl}1', '{klklkl}2', '{klklkl}3']); - }); - - it('should work with one value', function() { - match('a{b}c', ['a{b}c']); - match('a/b/c{d}e', ['a/b/c{d}e']); - }); - - it('should work with one value in `bash` mode', function() { - match('a{b}c', ['a{b}c']); - match('a/b/c{d}e', ['a/b/c{d}e']); - }); - - it('should work with nested non-sets', function() { - match('foo {1,2} bar', ['foo 1 bar', 'foo 2 bar']); - match('{a-{b,c,d}}', ['{a-b}', '{a-c}', '{a-d}']); - match('{a,{a-{b,c,d}}}', ['a', '{a-b}', '{a-c}', '{a-d}']); - }); - - it('should work with nested non-sets in `bash` mode', function() { - match('{a-{b,c,d}}', ['{a-b}', '{a-c}', '{a-d}']); - match('{a,{a-{b,c,d}}}', ['a', '{a-b}', '{a-c}', '{a-d}']); - }); - - it('should not expand dots with leading slashes (escaped or paths).', function() { - match('a{b,c/*/../d}e', ['abe', 'ac/*/../de']); - match('a{b,b,c/../b}d', ['abd', 'abd', 'ac/../bd']); - }); - - it('should work with commas.', function() { - match('a{b,}c', ['abc', 'ac']); - match('a{,b}c', ['ac', 'abc']); - }); - - it('should expand sets', function() { - match('a/{x,y}/cde', ['a/x/cde', 'a/y/cde']); - match('a/b/c/{x,y}', ['a/b/c/x', 'a/b/c/y']); - match('ff{c,b,a}', ['ffc', 'ffb', 'ffa']); - match('f{d,e,f}g', ['fdg', 'feg', 'ffg']); - match('{l,n,m}xyz', ['lxyz', 'nxyz', 'mxyz']); - match('{x,y,{abc},trie}', ['x', 'y', '{abc}', 'trie']); - }); - - it('should expand multiple sets', function() { - match('a/{a,b}/{c,d}/e', ['a/a/c/e', 'a/b/c/e', 'a/a/d/e', 'a/b/d/e']); - match('a{b,c}d{e,f}g', ['abdeg', 'acdeg', 'abdfg', 'acdfg']); - match('a/{x,y}/c{d,e}f.{md,txt}', ['a/x/cdf.md', 'a/y/cdf.md', 'a/x/cef.md', 'a/y/cef.md', 'a/x/cdf.txt', 'a/y/cdf.txt', 'a/x/cef.txt', 'a/y/cef.txt']); - }); - - it('should expand nested sets', function() { - match('a/{b,c,{d,e}}/g', ['a/b/g', 'a/c/g', 'a/d/g', 'a/e/g']); - match('a/{a,b}/{c,d}/e', ['a/a/c/e', 'a/a/d/e', 'a/b/c/e', 'a/b/d/e']); - match('{a,b}{{a,b},a,b}', ['aa', 'aa', 'ab', 'ab', 'ba', 'ba', 'bb', 'bb']); - match('/usr/{ucb/{ex,edit},lib/{ex,how_ex}}', ['/usr/ucb/ex', '/usr/lib/ex', '/usr/ucb/edit', '/usr/lib/how_ex']); - match('a{b,c{d,e}f}g', ['abg', 'acdfg', 'acefg']); - match('a{{x,y},z}b', ['axb', 'azb', 'ayb']); - match('f{x,y{g,z}}h', ['fxh', 'fygh', 'fyzh']); - match('a{b,c{d,e},h}x/z', ['abx/z', 'acdx/z', 'ahx/z', 'acex/z']); - match('a{b,c{d,e},h}x{y,z}', ['abxy', 'acdxy', 'ahxy', 'acexy', 'abxz', 'acdxz', 'ahxz', 'acexz']); - match('a{b,c{d,e},{f,g}h}x{y,z}', ['abxy', 'acdxy', 'afhxy', 'acexy', 'aghxy', 'abxz', 'acdxz', 'afhxz', 'acexz', 'aghxz']); - match('a-{b{d,e}}-c', ['a-{bd}-c', 'a-{be}-c']); - }); - - it('should expand with globs.', function() { - match('a/b/{d,e}/*.js', ['a/b/d/*.js', 'a/b/e/*.js']); - match('a/**/c/{d,e}/f*.js', ['a/**/c/d/f*.js', 'a/**/c/e/f*.js']); - match('a/**/c/{d,e}/f*.{md,txt}', ['a/**/c/d/f*.md', 'a/**/c/e/f*.md', 'a/**/c/d/f*.txt', 'a/**/c/e/f*.txt']); - }); - - it('should expand with extglobs.', function() { - match('a/b/{d,e,[1-5]}/*.js', ['a/b/d/*.js', 'a/b/e/*.js', 'a/b/[1-5]/*.js']); - }); - }); - - describe('escaping:', function() { - it('should not expand strings with es6/bash-like variables.', function() { - match('abc/${ddd}/xyz', ['abc/${ddd}/xyz']); - match('a${b}c', ['a${b}c']); - match('a/{${b},c}/d', ['a/${b}/d', 'a/c/d']); - match('a${b,d}/{foo,bar}c', ['a${b,d}/fooc', 'a${b,d}/barc']); - }); - - it('should not expand escaped commas.', function() { - match('a{b\\,c}d', ['a{b,c}d']); - match('a{b\\,c\\,d}e', ['a{b,c,d}e']); - match('{abc\\,def}', ['{abc,def}']); - match('{abc\\,def,ghi}', ['abc,def', 'ghi']); - match('a/{b,c}/{x\\,y}/d/e', ['a/b/{x,y}/d/e', 'a/c/{x,y}/d/e']); - }); - - it('should return sets with escaped commas in `bash` mode.', function() { - match('a/{b,c}/{x\\,y}/d/e', ['a/b/{x,y}/d/e', 'a/c/{x,y}/d/e']); - }); - - it('should not expand escaped braces.', function() { - match('{a,b\\}c,d}', ['a', 'b}c', 'd']); - match('\\{a,b,c,d,e}', ['{a,b,c,d,e}']); - match('a/{b,\\{a,b,c,d,e}/d', ['a/b/d', 'a/b/d', 'a/{a/d', 'a/c/d', 'a/d/d', 'a/e/d']); - match('a/\\{b,c}/{d,e}/f', ['a/{b,c}/d/f', 'a/{b,c}/e/f']); - match('./\\{x,y}/{a..z..3}/', ['./{x,y}/(a|d|g|j|m|p|s|v|y)/'], {optimize: true}); - }); - - it('should not expand escaped braces or commas.', function() { - match('{x\\,y,\\{abc\\},trie}', ['x,y', '{abc}', 'trie']); - }); - }); - - describe('complex', function() { - it('should expand a complex combination of ranges and sets:', function() { - match('a/{x,y}/{1..5}c{d,e}f.{md,txt}', ['a/x/1cdf.md', 'a/y/1cdf.md', 'a/x/2cdf.md', 'a/y/2cdf.md', 'a/x/3cdf.md', 'a/y/3cdf.md', 'a/x/4cdf.md', 'a/y/4cdf.md', 'a/x/5cdf.md', 'a/y/5cdf.md', 'a/x/1cef.md', 'a/y/1cef.md', 'a/x/2cef.md', 'a/y/2cef.md', 'a/x/3cef.md', 'a/y/3cef.md', 'a/x/4cef.md', 'a/y/4cef.md', 'a/x/5cef.md', 'a/y/5cef.md', 'a/x/1cdf.txt', 'a/y/1cdf.txt', 'a/x/2cdf.txt', 'a/y/2cdf.txt', 'a/x/3cdf.txt', 'a/y/3cdf.txt', 'a/x/4cdf.txt', 'a/y/4cdf.txt', 'a/x/5cdf.txt', 'a/y/5cdf.txt', 'a/x/1cef.txt', 'a/y/1cef.txt', 'a/x/2cef.txt', 'a/y/2cef.txt', 'a/x/3cef.txt', 'a/y/3cef.txt', 'a/x/4cef.txt', 'a/y/4cef.txt', 'a/x/5cef.txt', 'a/y/5cef.txt']); - }); - - it('should expand complex sets and ranges in `bash` mode:', function() { - match('a/{x,{1..5},y}/c{d}e', ['a/x/c{d}e', 'a/1/c{d}e', 'a/y/c{d}e', 'a/2/c{d}e', 'a/3/c{d}e', 'a/4/c{d}e', 'a/5/c{d}e']); - }); - }); -}); - -describe('range expansion', function() { - it('should expand numerical ranges', function() { - match('a{0..3}d', ['a0d', 'a1d', 'a2d', 'a3d']); - match('x{10..1}y', ['x10y', 'x9y', 'x8y', 'x7y', 'x6y', 'x5y', 'x4y', 'x3y', 'x2y', 'x1y']); - match('x{3..3}y', ['x3y']); - match('{-1..-10}', ['-1', '-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '-10']); - match('{-20..0}', ['-20', '-19', '-18', '-17', '-16', '-15', '-14', '-13', '-12', '-11', '-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1', '0']); - match('{1..10}', ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); - match('{1..3}', ['1', '2', '3']); - match('{1..9}', ['1', '2', '3', '4', '5', '6', '7', '8', '9']); - match('{3..3}', ['3']); - match('{5..8}', ['5', '6', '7', '8']); - }); - - it('should expand alphabetical ranges', function() { - match('0{a..d}0', ['0a0', '0b0', '0c0', '0d0']); - match('a/{b..d}/e', ['a/b/e', 'a/c/e', 'a/d/e']); - match('{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']); - match('{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']); - match('{a..e}', ['a', 'b', 'c', 'd', 'e']); - match('{A..E}', ['A', 'B', 'C', 'D', 'E']); - match('{a..f}', ['a', 'b', 'c', 'd', 'e', 'f']); - match('{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']); - match('{E..A}', ['E', 'D', 'C', 'B', 'A']); - match('{f..a}', ['f', 'e', 'd', 'c', 'b', 'a']); - match('{f..f}', ['f']); - }); - - it('should use steps with alphabetical ranges', function() { - match('{a..e..2}', ['a', 'c', 'e']); - match('{E..A..2}', ['E', 'C', 'A']); - }); - - it('should not try to expand ranges with decimals', function() { - match('{1.1..2.1}', ['{1.1..2.1}']); - match('{1.1..2.1}', ['{1.1..2.1}'], {optimize: true}); - match('{1.1..~2.1}', ['{1.1..~2.1}'], {optimize: true}); - }); - - it('should expand negative ranges', function() { - match('{z..a..-2}', ['z', 'x', 'v', 't', 'r', 'p', 'n', 'l', 'j', 'h', 'f', 'd', 'b']); - match('{-10..-1}', ['-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1']); - match('{0..-5}', ['0', '-1', '-2', '-3', '-4', '-5']); - match('{9..-4}', ['9', '8', '7', '6', '5', '4', '3', '2', '1', '0', '-1', '-2', '-3', '-4']); - }); - - it('should expand multiple ranges:', function() { - match('a/{b..d}/e/{f..h}', ['a/b/e/f', 'a/c/e/f', 'a/d/e/f', 'a/b/e/g', 'a/c/e/g', 'a/d/e/g', 'a/b/e/h', 'a/c/e/h', 'a/d/e/h']); - }); - - it('should work with dots in file paths', function() { - match('../{1..3}/../foo', ['../1/../foo', '../2/../foo', '../3/../foo']); - }); - - it('should make a regex-string when `options.optimize` is defined:', function() { - match('../{1..3}/../foo', ['../([1-3])/../foo'], {optimize: true}); - match('../{2..10..2}/../foo', ['../(2|4|6|8|10)/../foo'], {optimize: true}); - match('../{1..3}/../{a,b,c}/foo', ['../([1-3])/../(a|b|c)/foo'], {optimize: true}); - match('./{a..z..3}/', ['./(a|d|g|j|m|p|s|v|y)/'], {optimize: true}); - match('./{"x,y"}/{a..z..3}/', ['./{x,y}/(a|d|g|j|m|p|s|v|y)/'], {optimize: true}); - }); - - it('should expand ranges using steps:', function() { - match('{-1..-10..-2}', ['-1', '-3', '-5', '-7', '-9']); - match('{-1..-10..2}', ['-1', '-3', '-5', '-7', '-9']); - match('{-50..-0..5}', ['-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0']); - match('{1..10..2}', ['1', '3', '5', '7', '9']); - match('{1..20..20}', ['1']); - match('{1..20..2}', ['1', '3', '5', '7', '9', '11', '13', '15', '17', '19']); - match('{10..0..-2}', ['10', '8', '6', '4', '2', '0']); - match('{10..0..2}', ['10', '8', '6', '4', '2', '0']); - match('{10..1..-2}', ['10', '8', '6', '4', '2']); - match('{10..1..2}', ['10', '8', '6', '4', '2']); - match('{10..1}', ['10', '9', '8', '7', '6', '5', '4', '3', '2', '1']); - match('{10..1}y', ['10y', '9y', '8y', '7y', '6y', '5y', '4y', '3y', '2y', '1y']); - match('{100..0..-5}', ['100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']); - match('{100..0..5}', ['100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']); - match('{a..z..2}', ['a', 'c', 'e', 'g', 'i', 'k', 'm', 'o', 'q', 's', 'u', 'w', 'y']); - match('{1..10..1}', ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); - match('{1..10..2}', ['1', '3', '5', '7', '9']); - match('{1..20..20}', ['1']); - match('{1..20..2}', ['1', '3', '5', '7', '9', '11', '13', '15', '17', '19']); - match('{10..1..-2}', ['10', '8', '6', '4', '2']); - match('{10..1..2}', ['10', '8', '6', '4', '2']); - match('{2..10..1}', ['2', '3', '4', '5', '6', '7', '8', '9', '10']); - match('{2..10..2}', ['2', '4', '6', '8', '10']); - match('{2..10..3}', ['2', '5', '8']); - }); - - it('should expand negative ranges using steps:', function() { - match('{-1..-10..-2}', ['-1', '-3', '-5', '-7', '-9']); - match('{-1..-10..2}', ['-1', '-3', '-5', '-7', '-9']); - match('{-10..-2..2}', ['-10', '-8', '-6', '-4', '-2']); - match('{-2..-10..1}', ['-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '-10']); - match('{-2..-10..2}', ['-2', '-4', '-6', '-8', '-10']); - match('{-2..-10..3}', ['-2', '-5', '-8']); - match('{-9..9..3}', ['-9', '-6', '-3', '0', '3', '6', '9']); - }); - - it('should expand mixed ranges and sets:', function() { - match('x{{0..10},braces}y', ['x0y', 'xbracesy', 'x1y', 'x2y', 'x3y', 'x4y', 'x5y', 'x6y', 'x7y', 'x8y', 'x9y', 'x10y']); - match('{{0..10},braces}', ['0', 'braces', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); - match('{2147483645..2147483649}', ['2147483645', '2147483646', '2147483647', '2147483648', '2147483649']); - }); - - it('should return invalid ranges:', function() { - match('{1.20..2}', ['{1.20..2}']); - match('{1..0f}', ['{1..0f}']); - match('{1..10..ff}', ['{1..10..ff}']); - match('{1..10.f}', ['{1..10.f}']); - match('{1..10f}', ['{1..10f}']); - match('{1..20..2f}', ['{1..20..2f}']); - match('{1..20..f2}', ['{1..20..f2}']); - match('{1..2f..2}', ['{1..2f..2}']); - match('{1..ff..2}', ['{1..ff..2}']); - match('{1..ff}', ['{1..ff}']); - }); -}); diff -Nru node-braces-2.0.2/test/regression.js node-braces-3.0.2/test/regression.js --- node-braces-2.0.2/test/regression.js 1970-01-01 00:00:00.000000000 +0000 +++ node-braces-3.0.2/test/regression.js 2019-04-16 19:50:10.000000000 +0000 @@ -0,0 +1,437 @@ +'use strict'; + +require('mocha'); +const assert = require('assert').strict; +const braces = require('..'); + +const equal = (input, expected, options) => { + assert.deepEqual(braces.expand(input, options), expected); +}; + +describe('braces tests from 1.8.5', () => { + it('braces', () => { + equal('ff{c,b,a}', ['ffc', 'ffb', 'ffa']); + equal('f{d,e,f}g', ['fdg', 'feg', 'ffg']); + equal('{l,n,m}xyz', ['lxyz', 'nxyz', 'mxyz']); + equal('{abc\\,d,ef}', ['abc,d', 'ef']); + equal('{abc}', ['{abc}']); + + equal('\\{a,b,c,d,e}', ['{a,b,c,d,e}']); + equal('{x,y,\\{a,b,c}}', ['x}', 'y}', '{a}', 'b}', 'c}']); + equal('{x\\,y,\\{abc\\},trie}', ['x,y', '{abc}', 'trie']); + + equal('/usr/{ucb/{ex,edit},lib/{ex,how_ex}}', ['/usr/ucb/ex', '/usr/ucb/edit', '/usr/lib/ex', '/usr/lib/how_ex']); + + equal('{}', ['{}']); + equal('{ }', ['{ }']); + equal('}', ['}']); + equal('{', ['{']); + equal('abcd{efgh', ['abcd{efgh']); + + equal('foo {1,2} bar', ['foo 1 bar', 'foo 2 bar']); + }); + + it('new sequence brace operators', () => { + equal('{1..10}', ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); + equal('{0..10,braces}', ['0..10', 'braces']); + equal('{braces,{0..10}}', ['braces', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); + equal('{{0..10},braces}', ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'braces']); + equal('x{{0..10},braces}y', ['x0y', 'x1y', 'x2y', 'x3y', 'x4y', 'x5y', 'x6y', 'x7y', 'x8y', 'x9y', 'x10y', 'xbracesy']); + }); + + it('ranges', () => { + equal('{3..3}', ['3']); + equal('x{3..3}y', ['x3y']); + equal('{10..1}', ['10', '9', '8', '7', '6', '5', '4', '3', '2', '1']); + equal('{10..1}y', ['10y', '9y', '8y', '7y', '6y', '5y', '4y', '3y', '2y', '1y']); + equal('x{10..1}y', ['x10y', 'x9y', 'x8y', 'x7y', 'x6y', 'x5y', 'x4y', 'x3y', 'x2y', 'x1y']); + equal('{a..f}', ['a', 'b', 'c', 'd', 'e', 'f']); + equal('{f..a}', ['f', 'e', 'd', 'c', 'b', 'a']); + + equal('{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']); + equal('{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']); + + equal('{f..f}', ['f']); + 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']); + }); + + it('mixes are incorrectly-formed brace expansions', () => { + // the first one is valid, but Bash fails on it + equal('{1..f}', ['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']); + equal('{f..1}', ['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']); + }); + + it('do negative numbers work?', () => { + equal('{-1..-10}', ['-1', '-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '-10']); + equal('{-20..0}', ['-20', '-19', '-18', '-17', '-16', '-15', '-14', '-13', '-12', '-11', '-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1', '0']); + }); + + it('weirdly-formed brace expansions -- fixed in post-bash-3.1', () => { + equal('{-1..-10}', ['-1', '-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '-10']); + equal('{-20..0}', ['-20', '-19', '-18', '-17', '-16', '-15', '-14', '-13', '-12', '-11', '-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1', '0']); + equal('a-{b{d,e}}-c', ['a-{bd}-c', 'a-{be}-c']); + + equal('a-{bdef-{g,i}-c', ['a-{bdef-g-c', 'a-{bdef-i-c']); + + equal('{"klklkl"}{1,2,3}', ['{klklkl}1', '{klklkl}2', '{klklkl}3']); + equal('{"x,x"}', ['{x,x}']); + }); + + it('numerical ranges with steps', () => { + equal('{1..10..2}', ['1', '3', '5', '7', '9']); + equal('{-1..-10..2}', ['-1', '-3', '-5', '-7', '-9']); + equal('{-1..-10..-2}', ['-1', '-3', '-5', '-7', '-9']); + + equal('{10..1..-2}', ['10', '8', '6', '4', '2']); + equal('{10..1..2}', ['10', '8', '6', '4', '2']); + + equal('{1..20..2}', ['1', '3', '5', '7', '9', '11', '13', '15', '17', '19']); + equal('{1..20..20}', ['1']); + + equal('{100..0..5}', ['100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']); + equal('{100..0..-5}', ['100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']); + }); + + it('alpha ranges with steps', () => { + equal('{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']); + equal('{a..z..2}', ['a', 'c', 'e', 'g', 'i', 'k', 'm', 'o', 'q', 's', 'u', 'w', 'y']); + equal('{z..a..-2}', ['z', 'x', 'v', 't', 'r', 'p', 'n', 'l', 'j', 'h', 'f', 'd', 'b']); + }); + + it('make sure brace expansion handles ints > 2**31 - 1 using intmax_t', () => { + equal('{2147483645..2147483649}', ['2147483645', '2147483646', '2147483647', '2147483648', '2147483649']); + }); + + it('unwanted zero-padding -- fixed post-bash-4.0', () => { + equal('{10..0..2}', ['10', '8', '6', '4', '2', '0']); + equal('{10..0..-2}', ['10', '8', '6', '4', '2', '0']); + equal('{-50..-0..5}', ['-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0']); + }); + + it('bad', () => { + equal('{1..10.f}', ['{1..10.f}']); + equal('{1..ff}', ['{1..ff}']); + equal('{1..10..ff}', ['{1..10..ff}']); + equal('{1.20..2}', ['{1.20..2}']); + equal('{1..20..f2}', ['{1..20..f2}']); + equal('{1..20..2f}', ['{1..20..2f}']); + equal('{1..2f..2}', ['{1..2f..2}']); + equal('{1..ff..2}', ['{1..ff..2}']); + equal('{1..ff}', ['{1..ff}']); + equal('{1..0f}', ['{1..0f}']); + equal('{1..10f}', ['{1..10f}']); + equal('{1..10.f}', ['{1..10.f}']); + equal('{1..10.f}', ['{1..10.f}']); + }); +}); + +describe('bash tests', () => { + describe('brace expansion', () => { + it('should return an empty array when no braces are found', () => { + equal('', []); + }); + + it('should expand emty sets', () => { + equal('a{,}', ['a', 'a']); + equal('{,}b', ['b', 'b']); + equal('a{,}b', ['ab', 'ab']); + equal('a{,}', ['a', 'a']); + equal('a{,}{,}', ['a', 'a', 'a', 'a']); + equal('a{,}{,}{,}', ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a']); + equal('{a,b{,}{,}{,}}', ['a', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b']); + equal('a{,}/{c,d}/e', ['a/c/e', 'a/d/e', 'a/c/e', 'a/d/e']); + equal('{a,b{,}{,}{,},c}d', ['ad', 'bd', 'bd', 'bd', 'bd', 'bd', 'bd', 'bd', 'bd', 'cd']); + }); + + it('should eliminate dupes in repeated strings', () => { + equal('a{,}', ['a'], { nodupes: true }); + equal('a{,}{,}', ['a'], { nodupes: true }); + equal('a{,}{,}{,}', ['a'], { nodupes: true }); + equal('{a,b{,}{,}{,}}', ['a', 'b'], { nodupes: true }); + equal('{a,b{,}{,}{,},c}d', ['ad', 'bd', 'cd'], { nodupes: true }); + equal('{a,b{,}{,}{,},c}d', ['ad', 'bd', 'cd'], { nodupes: true }); + }); + + it('should work with no braces', () => { + equal('abc', ['abc']); + }); + + it('should work with no commas', () => { + equal('a{b}c', ['a{b}c']); + }); + + it('should work with no commas in `bash` mode', () => { + equal('a{b}c', ['a{b}c']); + }); + + 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 ' ]); + + // see https://github.com/jonschlinkert/micromatch/issues/66 + equal('/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' + ]); + }); + + it('should handle empty braces', () => { + equal('{ }', ['{ }']); + equal('{}', ['{}']); + equal('}', ['}']); + equal('{', ['{']); + equal('{,}', ['', '']); + }); + + it('should handle imbalanced braces', () => { + equal('a-{bdef-{g,i}-c', ['a-{bdef-g-c', 'a-{bdef-i-c']); + equal('abc{', ['abc{']); + equal('{abc{', ['{abc{']); + equal('{abc', ['{abc']); + equal('}abc', ['}abc']); + equal('ab{c', ['ab{c']); + equal('ab{c', ['ab{c']); + equal('{{a,b}', ['{a', '{b']); + equal('{a,b}}', ['a}', 'b}']); + equal('abcd{efgh', ['abcd{efgh']); + equal('a{b{c{d,e}f}g}h', ['a{b{cdf}g}h', 'a{b{cef}g}h']); + equal('f{x,y{{g,z}}h}', ['fx', 'fy{g}h', 'fy{z}h']); + equal('z{a,b},c}d', ['za,c}d', 'zb,c}d']); + equal('a{b{c{d,e}f{x,y{{g}h', ['a{b{cdf{x,y{{g}h', 'a{b{cef{x,y{{g}h']); + equal('f{x,y{{g}h', ['f{x,y{{g}h']); + equal('f{x,y{{g}}h', ['f{x,y{{g}}h']); + equal('a{b{c{d,e}f{x,y{}g}h', ['a{b{cdfxh', 'a{b{cdfy{}gh', 'a{b{cefxh', 'a{b{cefy{}gh']); + equal('f{x,y{}g}h', ['fxh', 'fy{}gh']); + equal('z{a,b{,c}d', ['z{a,bd', 'z{a,bcd']); + }); + + it('should handle invalid braces in `bash mode`:', () => { + equal('a{b{c{d,e}f}g}h', ['a{b{cdf}g}h', 'a{b{cef}g}h']); + equal('f{x,y{{g,z}}h}', ['fx', 'fy{g}h', 'fy{z}h']); + equal('z{a,b},c}d', ['za,c}d', 'zb,c}d']); + equal('a{b{c{d,e}f{x,y{{g}h', ['a{b{cdf{x,y{{g}h', 'a{b{cef{x,y{{g}h']); + equal('f{x,y{{g}h', ['f{x,y{{g}h']); + equal('f{x,y{{g}}h', ['f{x,y{{g}}h']); + }); + + it('should return invalid braces:', () => { + equal('{0..10,braces}', ['0..10', 'braces']); + }); + + it('should not expand quoted strings.', () => { + equal('{"x,x"}', ['{x,x}']); + equal('{"klklkl"}{1,2,3}', ['{klklkl}1', '{klklkl}2', '{klklkl}3']); + }); + + it('should work with one value', () => { + equal('a{b}c', ['a{b}c']); + equal('a/b/c{d}e', ['a/b/c{d}e']); + }); + + it('should work with one value in `bash` mode', () => { + equal('a{b}c', ['a{b}c']); + equal('a/b/c{d}e', ['a/b/c{d}e']); + }); + + it('should work with nested non-sets', () => { + equal('foo {1,2} bar', ['foo 1 bar', 'foo 2 bar']); + equal('{a-{b,c,d}}', ['{a-b}', '{a-c}', '{a-d}']); + equal('{a,{a-{b,c,d}}}', ['a', '{a-b}', '{a-c}', '{a-d}']); + }); + + it('should work with nested non-sets in `bash` mode', () => { + equal('{a-{b,c,d}}', ['{a-b}', '{a-c}', '{a-d}']); + equal('{a,{a-{b,c,d}}}', ['a', '{a-b}', '{a-c}', '{a-d}']); + }); + + it('should not expand dots with leading slashes (escaped or paths).', () => { + equal('a{b,c/*/../d}e', ['abe', 'ac/*/../de']); + equal('a{b,b,c/../b}d', ['abd', 'abd', 'ac/../bd']); + }); + + it('should work with commas.', () => { + equal('a{b,}c', ['abc', 'ac']); + equal('a{,b}c', ['ac', 'abc']); + }); + + it('should expand sets', () => { + equal('a/{x,y}/cde', ['a/x/cde', 'a/y/cde']); + equal('a/b/c/{x,y}', ['a/b/c/x', 'a/b/c/y']); + equal('ff{c,b,a}', ['ffc', 'ffb', 'ffa']); + equal('f{d,e,f}g', ['fdg', 'feg', 'ffg']); + equal('{l,n,m}xyz', ['lxyz', 'nxyz', 'mxyz']); + equal('{x,y,{abc},trie}', ['x', 'y', '{abc}', 'trie']); + }); + + it('should expand multiple sets', () => { + equal('a/{a,b}/{c,d}/e', ['a/a/c/e', 'a/a/d/e', 'a/b/c/e', 'a/b/d/e']); + equal('a{b,c}d{e,f}g', ['abdeg', 'abdfg', 'acdeg', 'acdfg']); + equal('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']); + }); + + it('should expand nested sets', () => { + equal('a/{b,c,{d,e}}/g', ['a/b/g', 'a/c/g', 'a/d/g', 'a/e/g']); + equal('a/{a,b}/{c,d}/e', ['a/a/c/e', 'a/a/d/e', 'a/b/c/e', 'a/b/d/e']); + equal('{a,b}{{a,b},a,b}', ['aa', 'ab', 'aa', 'ab', 'ba', 'bb', 'ba', 'bb']); + equal('/usr/{ucb/{ex,edit},lib/{ex,how_ex}}', ['/usr/ucb/ex', '/usr/ucb/edit', '/usr/lib/ex', '/usr/lib/how_ex']); + equal('a{b,c{d,e}f}g', ['abg', 'acdfg', 'acefg']); + equal('a{{x,y},z}b', ['axb', 'ayb', 'azb']); + equal('f{x,y{g,z}}h', ['fxh', 'fygh', 'fyzh']); + equal('a{b,c{d,e},h}x/z', ['abx/z', 'acdx/z', 'acex/z', 'ahx/z']); + equal('a{b,c{d,e},h}x{y,z}', ['abxy', 'abxz', 'acdxy', 'acdxz', 'acexy', 'acexz', 'ahxy', 'ahxz']); + equal('a{b,c{d,e},{f,g}h}x{y,z}', ['abxy', 'abxz', 'acdxy', 'acdxz', 'acexy', 'acexz', 'afhxy', 'afhxz', 'aghxy', 'aghxz']); + equal('a-{b{d,e}}-c', ['a-{bd}-c', 'a-{be}-c']); + }); + + it('should expand with globs.', () => { + equal('a/b/{d,e}/*.js', ['a/b/d/*.js', 'a/b/e/*.js']); + equal('a/**/c/{d,e}/f*.js', ['a/**/c/d/f*.js', 'a/**/c/e/f*.js']); + equal('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']); + }); + + it('should expand with brackets.', () => { + equal('a/b/{d,e,[1-5]}/*.js', ['a/b/d/*.js', 'a/b/e/*.js', 'a/b/[1-5]/*.js']); + }); + }); + + describe('escaping:', () => { + it('should not expand strings with es6/bash-like variables.', () => { + equal('abc/${ddd}/xyz', ['abc/${ddd}/xyz']); + equal('a${b}c', ['a${b}c']); + equal('a/{${b},c}/d', ['a/${b}/d', 'a/c/d']); + equal('a${b,d}/{foo,bar}c', ['a${b,d}/fooc', 'a${b,d}/barc']); + }); + + it('should not expand escaped commas.', () => { + equal('a{b\\,c}d', ['a{b,c}d']); + equal('a{b\\,c\\,d}e', ['a{b,c,d}e']); + equal('{abc\\,def}', ['{abc,def}']); + equal('{abc\\,def,ghi}', ['abc,def', 'ghi']); + equal('a/{b,c}/{x\\,y}/d/e', ['a/b/{x,y}/d/e', 'a/c/{x,y}/d/e']); + }); + + it('should return sets with escaped commas in `bash` mode.', () => { + equal('a/{b,c}/{x\\,y}/d/e', ['a/b/{x,y}/d/e', 'a/c/{x,y}/d/e']); + }); + + it('should not expand escaped braces.', () => { + equal('{a,b\\}c,d}', ['a', 'b}c', 'd']); + equal('\\{a,b,c,d,e}', ['{a,b,c,d,e}']); + equal('a/{b,\\{a,b,c,d,e}/d', ['a/b/d', 'a/{a/d', 'a/b/d', 'a/c/d', 'a/d/d', 'a/e/d']); + equal('a/\\{b,c}/{d,e}/f', ['a/{b,c}/d/f', 'a/{b,c}/e/f']); + }); + + it('should not expand escaped braces or commas.', () => { + equal('{x\\,y,\\{abc\\},trie}', ['x,y', '{abc}', 'trie']); + }); + }); +}); + +describe('range expansion', () => { + it('should expand numerical ranges', () => { + equal('a{0..3}d', ['a0d', 'a1d', 'a2d', 'a3d']); + equal('x{10..1}y', ['x10y', 'x9y', 'x8y', 'x7y', 'x6y', 'x5y', 'x4y', 'x3y', 'x2y', 'x1y']); + equal('x{3..3}y', ['x3y']); + equal('{-1..-10}', ['-1', '-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '-10']); + equal('{-20..0}', ['-20', '-19', '-18', '-17', '-16', '-15', '-14', '-13', '-12', '-11', '-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1', '0']); + equal('{1..10}', ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); + equal('{1..3}', ['1', '2', '3']); + equal('{1..9}', ['1', '2', '3', '4', '5', '6', '7', '8', '9']); + equal('{3..3}', ['3']); + equal('{5..8}', ['5', '6', '7', '8']); + }); + + it('should expand alphabetical ranges', () => { + equal('0{a..d}0', ['0a0', '0b0', '0c0', '0d0']); + equal('a/{b..d}/e', ['a/b/e', 'a/c/e', 'a/d/e']); + equal('{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']); + equal('{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']); + equal('{a..e}', ['a', 'b', 'c', 'd', 'e']); + equal('{A..E}', ['A', 'B', 'C', 'D', 'E']); + equal('{a..f}', ['a', 'b', 'c', 'd', 'e', 'f']); + equal('{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']); + equal('{E..A}', ['E', 'D', 'C', 'B', 'A']); + equal('{f..a}', ['f', 'e', 'd', 'c', 'b', 'a']); + equal('{f..f}', ['f']); + }); + + it('should use steps with alphabetical ranges', () => { + equal('{a..e..2}', ['a', 'c', 'e']); + equal('{E..A..2}', ['E', 'C', 'A']); + }); + + it('should not try to expand ranges with decimals', () => { + equal('{1.1..2.1}', ['{1.1..2.1}']); + }); + + it('should expand negative ranges', () => { + equal('{z..a..-2}', ['z', 'x', 'v', 't', 'r', 'p', 'n', 'l', 'j', 'h', 'f', 'd', 'b']); + equal('{-10..-1}', ['-10', '-9', '-8', '-7', '-6', '-5', '-4', '-3', '-2', '-1']); + equal('{0..-5}', ['0', '-1', '-2', '-3', '-4', '-5']); + equal('{9..-4}', ['9', '8', '7', '6', '5', '4', '3', '2', '1', '0', '-1', '-2', '-3', '-4']); + }); + + it('should expand multiple ranges:', () => { + equal('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']); + }); + + it('should work with dots in file paths', () => { + equal('../{1..3}/../foo', ['../1/../foo', '../2/../foo', '../3/../foo']); + }); + + it('should expand ranges using steps:', () => { + equal('{-1..-10..-2}', ['-1', '-3', '-5', '-7', '-9']); + equal('{-1..-10..2}', ['-1', '-3', '-5', '-7', '-9']); + equal('{-50..-0..5}', ['-50', '-45', '-40', '-35', '-30', '-25', '-20', '-15', '-10', '-5', '0']); + equal('{1..10..2}', ['1', '3', '5', '7', '9']); + equal('{1..20..20}', ['1']); + equal('{1..20..2}', ['1', '3', '5', '7', '9', '11', '13', '15', '17', '19']); + equal('{10..0..-2}', ['10', '8', '6', '4', '2', '0']); + equal('{10..0..2}', ['10', '8', '6', '4', '2', '0']); + equal('{10..1..-2}', ['10', '8', '6', '4', '2']); + equal('{10..1..2}', ['10', '8', '6', '4', '2']); + equal('{10..1}', ['10', '9', '8', '7', '6', '5', '4', '3', '2', '1']); + equal('{10..1}y', ['10y', '9y', '8y', '7y', '6y', '5y', '4y', '3y', '2y', '1y']); + equal('{100..0..-5}', ['100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']); + equal('{100..0..5}', ['100', '95', '90', '85', '80', '75', '70', '65', '60', '55', '50', '45', '40', '35', '30', '25', '20', '15', '10', '5', '0']); + equal('{a..z..2}', ['a', 'c', 'e', 'g', 'i', 'k', 'm', 'o', 'q', 's', 'u', 'w', 'y']); + equal('{1..10..1}', ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']); + equal('{1..10..2}', ['1', '3', '5', '7', '9']); + equal('{1..20..20}', ['1']); + equal('{1..20..2}', ['1', '3', '5', '7', '9', '11', '13', '15', '17', '19']); + equal('{10..1..-2}', ['10', '8', '6', '4', '2']); + equal('{10..1..2}', ['10', '8', '6', '4', '2']); + equal('{2..10..1}', ['2', '3', '4', '5', '6', '7', '8', '9', '10']); + equal('{2..10..2}', ['2', '4', '6', '8', '10']); + equal('{2..10..3}', ['2', '5', '8']); + }); + + it('should expand negative ranges using steps:', () => { + equal('{-1..-10..-2}', ['-1', '-3', '-5', '-7', '-9']); + equal('{-1..-10..2}', ['-1', '-3', '-5', '-7', '-9']); + equal('{-10..-2..2}', ['-10', '-8', '-6', '-4', '-2']); + equal('{-2..-10..1}', ['-2', '-3', '-4', '-5', '-6', '-7', '-8', '-9', '-10']); + equal('{-2..-10..2}', ['-2', '-4', '-6', '-8', '-10']); + equal('{-2..-10..3}', ['-2', '-5', '-8']); + equal('{-9..9..3}', ['-9', '-6', '-3', '0', '3', '6', '9']); + }); + + it('should expand mixed ranges and sets:', () => { + equal('x{{0..10},braces}y', ['x0y', 'x1y', 'x2y', 'x3y', 'x4y', 'x5y', 'x6y', 'x7y', 'x8y', 'x9y', 'x10y', 'xbracesy']); + equal('{{0..10},braces}', ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'braces']); + equal('{2147483645..2147483649}', ['2147483645', '2147483646', '2147483647', '2147483648', '2147483649']); + }); + + it('should return invalid ranges:', () => { + equal('{1.20..2}', ['{1.20..2}']); + equal('{1..0f}', ['{1..0f}']); + equal('{1..10..ff}', ['{1..10..ff}']); + equal('{1..10.f}', ['{1..10.f}']); + equal('{1..10f}', ['{1..10f}']); + equal('{1..20..2f}', ['{1..20..2f}']); + equal('{1..20..f2}', ['{1..20..f2}']); + equal('{1..2f..2}', ['{1..2f..2}']); + equal('{1..ff..2}', ['{1..ff..2}']); + equal('{1..ff}', ['{1..ff}']); + }); +}); diff -Nru node-braces-2.0.2/test/support/bash.js node-braces-3.0.2/test/support/bash.js --- node-braces-2.0.2/test/support/bash.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/test/support/bash.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -'use strict'; - -var isWindows = require('is-windows'); -var spawn = require('cross-spawn'); -var utils = require('./utils'); - -/** - * Expose `bash` util - */ - -module.exports = function(pattern) { - if (isWindows()) { - throw new Error('windows not supported'); - } - - var cmd = pattern; - if (!/echo/.test(cmd)) { - cmd = 'echo ' + escape(pattern); - } - - var res = spawn.sync(utils.getBashPath(), ['-c', cmd]); - var err = res.stderr && res.stderr.toString().trim(); - if (err) { - console.error(cmd); - throw new Error(err); - } - - if (!res.stdout) { - return []; - } - return unescape(res.stdout).sort(); -}; - -/** - * Escape characters that behave differently in bash than node (like spaces, which are - * valid path characters in node.js but indicate a delimiter in Bash) - */ - -function escape(buf) { - return buf.split(/\\? /).join('_SPACE_') - .replace(/([*`\[\]])/g, '\\$1') - .replace(/(\$\{)([^{}]+)(\})/g, function(m, $1, $2, $3) { - return utils.nc[0] + $2 + utils.nc[2]; - }); -} - -/** - * Unescape previously-escaped characters - */ - -function unescape(buf) { - return buf.toString().split(/[ \n]/) - .filter(Boolean) - .map(function(str) { - return utils.unescape(str, {escape: true}) - .split('_SPACE_').join(' ') - .split(/\\(?!`)/).join(''); - }); -} diff -Nru node-braces-2.0.2/test/support/generate.js node-braces-3.0.2/test/support/generate.js --- node-braces-2.0.2/test/support/generate.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/test/support/generate.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -'use strict'; - -var braces = require('../..'); -var mm = require('minimatch'); -var size = require('pretty-bytes'); -var text = require('text-table'); -var Time = require('time-diff'); -var time = new Time(); - -var table = [ - ['**Pattern**', '**minimatch**', '**braces**'], - ['---', '---', '---'], -]; - -function generate(pattern) { - // time.start('minimatch'); - - // var mval = mm.braceExpand(pattern).join('|'); - // var m = [wrap(size(mval.length)), '(' + time.end('minimatch', 'μs') + ')'].join(' '); - - time.start('braces'); - var bval = braces.expand(pattern).join('|'); - var b = [wrap(size(bval.length)), '(' + time.end('braces', 'μs') + ')'].join(' '); - - table.push([wrap(pattern), 'm', b]); - return table; -} - -function wrap(str) { - return '`' + str + '`'; -} - -var patterns = [ - '{1..9007199254740991}', - // 'a/{1..10000000}', - // 'a/{1..1000000}', - // 'a/{1..100000}', - // 'a/{1..10000}', - // 'a/{1..1000}', - // 'a/{1..100}', - // 'a/{1..10}', - // 'a/{1..3}', - // 'a/{2000..2016}/bar/{a..j}/baz', - // 'a/{1900..2016}/bar/{a..j}/baz', - // 'a/{1000..2016}/bar/{a..j}/baz', - // 'a/{100..2016}/bar/{a..j}/baz', -]; - -var len = patterns.length; -var idx = -1; -var res = []; - -while (++idx < len) { - generate(patterns[idx]); -} - -console.log(text(table, {hsep: ' | '})); diff -Nru node-braces-2.0.2/test/support/utils.js node-braces-3.0.2/test/support/utils.js --- node-braces-2.0.2/test/support/utils.js 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/test/support/utils.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -'use strict'; - -var util = require('util'); -var bashPath = ''; - -/** - * Utils - */ - -exports.exists = require('fs-exists-sync'); -exports.extend = require('extend-shallow'); -exports.nc = require('noncharacters'); - -exports.getBashPath = function() { - if (bashPath) return bashPath; - if (exports.exists('/usr/local/bin/bash')) { - bashPath = '/usr/local/bin/bash'; - } else if (exports.exists('/bin/bash')) { - bashPath = '/bin/bash'; - } else { - bashPath = 'bash'; - } - return bashPath; -}; - -exports.escape = function(str, options) { - if (typeof str !== 'string') { - throw new TypeError('expected a string: ' + util.inspect(str)); - } - var opts = exports.extend({}, options); - if (!opts.expand && !opts.escape) return str; - str = str.replace(/(\$\{([^{}]+?)\})/g, function(m, $1, $2) { - return exports.nc[0] + $2 + exports.nc[2]; - }); - str = str.replace(/(\{)([^{,.}]+?)(\})/g, function(m, $1, $2, $3) { - return exports.nc[1] + $2 + exports.nc[2]; - }); - str = str.replace(/\\\{|\{(?!.*\})/g, exports.nc[1]); - str = str.replace(/\\\}/g, exports.nc[2]); - str = str.replace(/\\\,/g, exports.nc[3]); - if (!/\{/.test(str)) { - return str.replace(/\}/g, exports.nc[2]); - } - return str; -}; - -exports.unescape = function(str, options) { - if (typeof str !== 'string') { - throw new TypeError('expected a string: ' + util.inspect(str)); - } - var opts = exports.extend({}, options); - if (!opts.expand && !opts.escape) return str; - var pre = opts.noescape ? '' : '\\'; - str = str.split(exports.nc[0]).join(pre ? '\\$\\{' : '${'); - str = str.split(exports.nc[1]).join(pre + '{'); - str = str.split(exports.nc[2]).join(pre + '}'); - str = str.split(exports.nc[3]).join(','); - return str.replace(/\\+/g, '\\'); -}; diff -Nru node-braces-2.0.2/.travis.yml node-braces-3.0.2/.travis.yml --- node-braces-2.0.2/.travis.yml 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/.travis.yml 2019-04-16 19:50:10.000000000 +0000 @@ -1,11 +1,9 @@ -sudo: false -language: node_js os: - linux - osx + - windows +language: node_js node_js: - node - - '6' - - '5' - - '0.12' - - '0.10' + - '10' + - '8' diff -Nru node-braces-2.0.2/.verb.md node-braces-3.0.2/.verb.md --- node-braces-2.0.2/.verb.md 2016-10-21 06:46:43.000000000 +0000 +++ node-braces-3.0.2/.verb.md 2019-04-16 19:50:10.000000000 +0000 @@ -1,54 +1,66 @@ + +## v3.0.0 Released!! + +See the [changelog](CHANGELOG.md) for details. + +## Why use braces? + +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][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][] 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 -The main export is a function that takes a brace `pattern` to expand and an `options` object if necessary. +The main export is a function that takes one or more brace `patterns` and `options`. ```js -var braces = require('{%= name %}'); -braces(pattern[, options]); -``` +const braces = require('braces'); +// braces(patterns[, options]); -## Highlights +console.log(braces(['{01..05}', '{a..e}'])); +//=> ['(0[1-5])', '([a-e])'] -- **Safer**: Braces isn't [vulnerable to DoS attacks](#braces-is-safe), unlike [brace-expansion][], [minimatch][] and [multimatch][] (this not the same [DoS bug][bug] that was found in minimatch and multimatch recently) -- **Accurate**: complete support for the [Bash 4.3 Brace Expansion][bash] specification (passes all of the Bash braces tests) -- **[fast and performant](#benchmarks)**: not only runs fast, but scales well as patterns increase in complexity (other libs don't - see the notes on [performance](#performance)). -- **Organized code base**: with parser and compiler that are easy to maintain and update when edge cases crop up. -- **Well-tested**: 900+ unit tests with thousands of actual patterns tested. Passes 100% of the [minimatch][] and [brace-expansion][] unit tests as well. -- **Optimized braces**: By default returns an optimized string that can be used for creating regular expressions for matching. -- **Expanded braces**: Optionally returns an array (like bash). See a [comparison](#optimized-vs-expanded) between optimized and expanded. +console.log(braces(['{01..05}', '{a..e}'], { expand: true })); +//=> ['01', '02', '03', '04', '05', 'a', 'b', 'c', 'd', 'e'] +``` +### Brace Expansion vs. Compilation -**Optimized** +By default, brace patterns are compiled into strings that are optimized for creating regular expressions and matching. -Patterns are optimized for regex and matching by default: +**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'])); +//=> [ 'a/(0[1-9]|1[0-9]|20)/b', 'a/([1-5])/b' ] ``` **Expanded** -To expand patterns the same way as Bash or [minimatch][], use the [.expand](#expand) method: +Enable brace expansion by setting the `expand` option to true, or by using [braces.expand()](#expand) (returns an array similar to what you'd expect from Bash, or `echo {1..5}`, or [minimatch](https://github.com/isaacs/minimatch)): ```js -console.log(braces.expand('a/{x,y,z}/b')); +console.log(braces('a/{x,y,z}/b', { expand: true })); //=> ['a/x/b', 'a/y/b', 'a/z/b'] -``` - - -## Features - -- [lists](#lists): Supports "lists": `a/{b,c}/d` => `['a/b/d', 'a/c/d']` -- [sequences](#sequences): Supports alphabetical or numerical "sequences" (ranges): `{1..3}` => `['1', '2', '3']` -- [steps](#steps): Supports "steps" or increments: `{2..10..2}` => `['2', '4', '6', '8', '10']` -- [escaping](#escaping) -- [options](#options) +console.log(braces.expand('{01..10}')); +//=> ['01','02','03','04','05','06','07','08','09','10'] +``` ### Lists -Uses [fill-range](https://github.com/jonschlinkert/fill-range) for expanding alphabetical or numeric lists: +Expand lists (like Bash "sets"): ```js console.log(braces('a/{foo,bar,baz}/*.js')); @@ -60,21 +72,23 @@ ### Sequences -Uses [fill-range](https://github.com/jonschlinkert/fill-range) for expanding alphabetical or numeric ranges (bash "sequences"): +Expand ranges of characters (like Bash "sequences"): ```js -// padding is not retained when string is optimized -console.log(braces('a{01..03}b')); // ['a([1-3])b'] -console.log(braces('a{1..3}b')); // ['a([1-3])b'] +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'] -console.log(braces.expand('{1..3}')); // ['1', '2', '3'] -console.log(braces.expand('a{01..03}b')); // ['a01b', 'a02b', 'a03b'] -console.log(braces.expand('a{1..3}b')); // ['a1b', 'a2b', 'a3b'] -console.log(braces.expand('{a..c}')); // ['a', 'b', 'c'] -console.log(braces.expand('foo/{a..c}')); // ['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/{001..300}/b')); //=> ['a/(0{2}[1-9]|0[1-9][0-9]|[12][0-9]{2}|300)/b'] ``` -### Steps +See [fill-range](https://github.com/jonschlinkert/fill-range) for all available range-expansion options. + + +### Steppped ranges Steps, or increments, may be used with ranges: @@ -86,13 +100,13 @@ //=> ['(2|4|6|8|10)'] ``` -When the [.optimize](#optimize) method is used, or [options.optimize](#optionsoptimize) is set to true, sequences are passed to [to-regex-range][] for expansion. +When the [.optimize](#optimize) method is used, or [options.optimize](#optionsoptimize) is set to true, sequences are passed to [to-regex-range](https://github.com/jonschlinkert/to-regex-range) for expansion. ### Nesting -Brace patterns may be nested. The results of each expanded string are not sorted, and left to right order is preserved. +Brace patterns may be nested. The results of each expanded string are not sorted, and left to right order is preserved. -**"Expanded" examples** +**"Expanded" braces** ```js console.log(braces.expand('a{b,c,/{x,y}}/e')); @@ -102,7 +116,7 @@ //=> ['a/x/c', 'a/1/c', 'a/2/c', 'a/3/c', 'a/4/c', 'a/5/c', 'a/y/c'] ``` -**"Optimized" examples** +**"Optimized" braces** ```js console.log(braces('a{b,c,/{x,y}}/e')); @@ -116,7 +130,7 @@ **Escaping braces** -Prevent braces from being expanded or evaluted by escaping either the opening or closing brace: +A brace pattern will not be expanded or evaluted if _either the opening or closing brace is escaped_: ```js console.log(braces.expand('a\\{d,c,b}e')); @@ -131,68 +145,67 @@ Commas inside braces may also be escaped: ```js +console.log(braces.expand('a{b\\,c}d')); +//=> ['a{b,c}d'] + console.log(braces.expand('a{d\\,c,b}e')); //=> ['ad,ce', 'abe'] ``` **Single items** -A brace pattern is also considered to be escaped when it contains a single item: +Following bash conventions, a brace pattern is also not expanded when it contains a single character: ```js console.log(braces.expand('a{b}c')); //=> ['a{b}c'] - -console.log(braces.expand('a{b\\,c}d')); -//=> ['a{b,c}d'] ``` ## Options -### options.expand +### options.maxLength -Type: `Boolean` +**Type**: `Number` -Default: `undefined` +**Default**: `65,536` -Generate an "expanded" brace pattern (this option is unncessary with the `.expand` method, which does the same thing). +**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', {expand: true})); -//=> [ 'a/b/d', 'a/c/d' ] +console.log(braces('a/{b,c}/d', { maxLength: 3 })); //=> throws an error ``` -### options.optimize +### options.expand -Type: `Boolean` +**Type**: `Boolean` -Default: `true` +**Default**: `undefined` -Enabled by default. +**Description**: Generate an "expanded" brace pattern (alternatively you can use the `braces.expand()` method, which does the same thing). ```js -console.log(braces('a/{b,c}/d')); -//=> [ 'a/(b|c)/d' ] +console.log(braces('a/{b,c}/d', { expand: true })); +//=> [ 'a/b/d', 'a/c/d' ] ``` ### options.nodupes -Type: `Boolean` +**Type**: `Boolean` -Default: `true` +**Default**: `undefined` -Duplicates are removed by default. To keep duplicates, pass `{nodupes: false}` on the options +**Description**: Remove duplicates from the returned array. ### options.rangeLimit -Type: `Number` +**Type**: `Number` -Default: `250` +**Default**: `1000` -When `braces.expand()` is used, or `options.expand` is true, brace patterns will automatically be [optimized](#optionsoptimize) when the difference between the range minimum and range maximum exceeds the `rangeLimit`. This is to prevent huge ranges from freezing your application. +**Description**: To prevent malicious patterns from being passed by users, an error is thrown when `braces.expand()` is used or `options.expand` is true and the generated range will exceed the `rangeLimit`. -You can set this to any number, or change `options.rangeLimit` to `Inifinity` to disable this altogether. +You can customize `options.rangeLimit` or set it to `Inifinity` to disable this altogether. **Examples** @@ -208,39 +221,56 @@ ### options.transform -Type: `Function` +**Type**: `Function` + +**Default**: `undefined` -Default: `undefined` +**Description**: Customize range expansion. -Customize range expansion. +**Example: Transforming non-numeric values** ```js -var range = braces.expand('x{a..e}y', { - transform: function(str) { - return 'foo' + str; +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' ] +``` + +**Example: Transforming numeric values** -console.log(range); -//=> [ 'xfooay', 'xfooby', 'xfoocy', 'xfoody', 'xfooey' ] +```js +const numeric = braces.expand('{1..5}', { + transform(value) { + // when numeric values are passed, "value" is a number + return 'foo/' + value * 2; + } +}); +console.log(numeric); +//=> [ 'foo/2', 'foo/4', 'foo/6', 'foo/8', 'foo/10' ] ``` + ### options.quantifiers -Type: `Boolean` +**Type**: `Boolean` -Default: `undefined` +**Default**: `undefined` -In regular expressions, quanitifiers can be used to specify how many times a token can be repeated. For example, `a{1,3}` will match the letter `a` one to three times. +**Description**: In regular expressions, quanitifiers can be used to specify how many times a token can be repeated. For example, `a{1,3}` will match the letter `a` one to three times. Unfortunately, regex quantifiers happen to share the same syntax as [Bash lists](#lists) -The `quantifiers` option tells braces to detect when [regex quantifiers][quantifiers] are defined in the given pattern, and not to try to expand them as lists. +The `quantifiers` option tells braces to detect when [regex quantifiers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#quantifiers) are defined in the given pattern, and not to try to expand them as lists. + **Examples** ```js -var braces = require('braces'); +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})); @@ -249,109 +279,259 @@ //=> [ 'a/b{1,3}/x', 'a/b{1,3}/y', 'a/b{1,3}/z' ] ``` -## Benchmarks +### options.unescape -### Running benchmarks +**Type**: `Boolean` -Install dev dependencies: +**Default**: `undefined` -```bash -npm i -d && npm benchmark +**Description**: Strip backslashes that were used for escaping from the result. + + +## What is "brace expansion"? + +Brace expansion is a type of parameter expansion that was made popular by unix shells for generating lists of strings, as well as regex-like matching when used alongside wildcards (globs). + +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 + +
+ More about brace expansion (click to expand) + +There are two main types of brace expansion: + +1. **lists**: which are defined using comma-separated values inside curly braces: `{a,b,c}` +2. **sequences**: which are defined using a starting value and an ending value, separated by two dots: `a{1..3}b`. Optionally, a third argument may be passed to define a "step" or increment to use: `a{1..100..10}b`. These are also sometimes referred to as "ranges". + +Here are some example brace patterns to illustrate how they work: + +**Sets** + +``` +{a,b,c} => a b c +{a,b,c}{1,2} => a1 a2 b1 b2 c1 c2 ``` -### Latest results +**Sequences** -```bash -{%= docs("benchmark/last.md") %} +``` +{1..9} => 1 2 3 4 5 6 7 8 9 +{4..-4} => 4 3 2 1 0 -1 -2 -3 -4 +{1..20..3} => 1 4 7 10 13 16 19 +{a..j} => a b c d e f g h i j +{j..a} => j i h g f e d c b a +{a..z..3} => a d g j m p s v y ``` -## Performance +**Combination** + +Sets and sequences can be mixed together or used along with any other strings. -### What's the big deal? +``` +{a,b,c}{1..3} => a1 a2 a3 b1 b2 b3 c1 c2 c3 +foo/{a,b,c}/bar => foo/a/bar foo/b/bar foo/c/bar +``` -If you use globbing a lot, whether in your build tool chain or in your application, the speed of the glob matcher not only impacts your experience, but a slow glob matcher can slow everything else down, limitimg what you thought was possible in your application. +The fact that braces can be "expanded" from relatively simple patterns makes them ideal for quickly generating test fixtures, file paths, and similar use cases. -### Braces is fast +## Brace matching -> minimatch gets exponentially slower as patterns increase in complexity, braces does not +In addition to _expansion_, brace patterns are also useful for performing regular-expression-like matching. -Brace patterns are meant to be expanded - at least, if you're using Bash, that is. It's not at all unusual for users to want to use brace patterns for dates or similar ranges. It's also very easy to define a brace pattern that appears to be very simple but in fact is fairly complex. +For example, the pattern `foo/{1..3}/bar` would match any of following strings: + +``` +foo/1/bar +foo/2/bar +foo/3/bar +``` -For example, here is how generated regex size and processing time compare as patterns increase in complexity: +But not: -_(the following results were generated using `braces()` and `minimatch.braceExpand()`)_ +``` +baz/1/qux +baz/2/qux +baz/3/qux +``` -| **Pattern** | **minimatch** | **braces** | -| --- | --- | --- | -| `{1..9007199254740991}`[^1] | N/A (freezes) | `300 B` (12ms 878μs) | -| `{1..10000000}` | `98.9 MB` (20s 193ms 13μs) | `34 B` (11ms 204μs) | -| `{1..1000000}` | `8.89 MB` (1s 838ms 718μs) | `33 B` (1ms 761μs) | -| `{1..100000}` | `789 kB` (181ms 518μs) | `32 B` (1ms 76μs) | -| `{1..10000}` | `68.9 kB` (17ms 436μs) | `31 B` (1ms 382μs) | -| `{1..1000}` | `5.89 kB` (1ms 773μs) | `30 B` (1ms 509μs) | -| `{1..100}` | `491 B` (321μs) | `24 B` (309μs) | -| `{1..10}` | `40 B` (56μs) | `12 B` (333μs) | -| `{1..3}` | `11 B` (80μs) | `9 B` (370μs) | +Braces can also be combined with [glob patterns][micromatch] to perform more advanced wildcard matching. For example, the pattern `*/{1..3}/*` would match any of following strings: -These numbers are actually pretty small as far as numeric ranges are concerned. Regardless, we shouldn't have to consider such things when creating a glob pattern. The tool should get out of your way and let you be as creative as you want. +``` +foo/1/bar +foo/2/bar +foo/3/bar +baz/1/qux +baz/2/qux +baz/3/qux +``` -### Braces is performant +## Brace matching pitfalls -Even when brace patterns are fully **expanded**, `braces` is still much faster. +Although brace patterns offer a user-friendly way of matching ranges or sets of strings, there are also some major disadvantages and potential risks you should be aware of. -_(the following results were generated using `braces.expand()` and `minimatch.braceExpand()`)_ +### tldr -| **Pattern** | **minimatch** | **braces** | -| --- | --- | --- | -| `a/{1..10000000}` | `98.9 MB` (19s 754ms 376μs) | `98.9 MB` (5s 734ms 419μs) | -| `a/{1..1000000}` | `8.89 MB` (1s 866ms 968μs) | `8.89 MB` (561ms 594μs) | -| `a/{1..100000}` | `789 kB` (178ms 311μs) | `789 kB` (29ms 823μs) | -| `a/{1..10000}` | `68.9 kB` (17ms 692μs) | `68.9 kB` (2ms 351μs) | -| `a/{1..1000}` | `5.89 kB` (1ms 823μs) | `5.89 kB` (706μs) | -| `a/{1..100}` | `491 B` (609μs) | `491 B` (267μs) | -| `a/{1..10}` | `40 B` (61μs) | `40 B` (636μs) | -| `a/{1..3}` | `11 B` (206μs) | `11 B` (207μs) | +**"brace bombs"** -### Why is braces so fast? +- 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!) -Braces was built from the ground up to be as performant as possible when matching, using a combination of the following: +For a more detailed explanation with examples, see the [geometric complexity](#geometric-complexity) section. -- **minimizes loops and iterating**: we try to pass over the pattern once to parse it before passing it to the compiler. -- **generates an optimized string**: sequences/ranges are optimized by [to-regex-range][], which is not only highly accurate, but produces patterns that are a fraction of the size of patterns generated by other brace expansion libraries, such as Bash and [minimatch][] (via [brace-expansion][]) -- **generates results faster**: can handle even the most complex patterns that cause other implementations like [minimatch][] and Bash to fail. +### The solution -### Braces is safe +Jump to the [performance section](#performance) to see how Braces solves this problem in comparison to other libraries. -Last, but perhaps most important of all, unlike [brace-expansion][] and [minimatch][], braces will not freeze your application when a user passes a complex brace pattern. +### Geometric complexity -**The trouble with ~~tribbles~~ brace patterns** +At minimum, brace patterns with sets limited to two elements have quadradic or `O(n^2)` complexity. But the complexity of the algorithm increases exponentially as the number of sets, _and elements per set_, increases, which is `O(n^c)`. -There are unlimited scenarios where brace patterns cause the resulting array to grow geometrically. If you define two brace patterns for example, the result is multiplicative if not exponential. For example, given the pattern `{1..1000}`, we would end up with 1 thousand strings. But if two patterns are given, such as `{1...1000}{1...1000}`, we would end up with 1 million strings. +For example, the following sets demonstrate quadratic (`O(n^2)`) complexity: -It's easy to think, "I wouldn't do that", but that's not the point. Even though those example patterns are contrived: +``` +{1,2}{3,4} => (2X2) => 13 14 23 24 +{1,2}{3,4}{5,6} => (2X2X2) => 135 136 145 146 235 236 245 246 +``` -1. it's not uncommon for users to define brace patterns that result in similarly huge strings (consider date ranges `1-2016`, for example, and how easy it might be for someone to also add an alphabetical range if searching records of some kind) -1. we can't control how users define their patterns (and we shouldn't have to care) -1. even if it's uncommon for user to define unwieldy patterns, there is still potential for intentionally exploiting this feature to [cause a DoS][dos] in your application (and given that this is a not-very-technically-advanced method for causing a DoS - e.g. anyone can do it, you should be concerned!) +But add an element to a set, and we get a n-fold Cartesian product with `O(n^c)` complexity: -**Potential for DoS attacks** +``` +{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 +``` + +Now, imagine how this complexity grows given that each element is a n-tuple: + +``` +{1..100}{1..100} => (100X100) => 10,000 elements (38.4 kB) +{1..100}{1..100}{1..100} => (100X100X100) => 1,000,000 elements (5.76 MB) +``` + +Although these examples are clearly contrived, they demonstrate how brace patterns can quickly grow out of control. + +**More information** + +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) + +
+ + +## Performance -Most brace expansion libraries, including Bash, [minimatch][], [multimatch][] and [brace-expansion](https://github.com/juliangruber/brace-expansion) are vulnerable to DoS attacks (similar to the [ReDoS bug][bug] minimatch had recently). +Braces is not only screaming fast, it's also more accurate the other brace expansion libraries. -Braces mitigates this risk in three ways: +### Better algorithms -1. Braces prevents malicious strings from being used by checking the length of the input strings, as well as generated regex -1. Braces [optimizes](#optimize) the generated result by default, so that only _one output string is generated for every input string_. -1. When [.expand](#expand) or [options.expand](#optionsexpand) are used, braces has checks in place to prevent huge ranges from being (accidentally) created. By default, when more than 250 strings will result from the given pattern, braces will [optimize](#optimize) the result instead of expanding it. You can override this limit of 250 by passing a custom number on [options.rangeLimit](#optionsrangelimit). +Fortunately there is a solution to the ["brace bomb" problem](#brace-matching-pitfalls): _don't expand brace patterns into an array when they're used for matching_. -_(you might also want to consider using [micromatch][] for glob matching, as a safer alternative to minimatch and multimatch)_ +Instead, convert the pattern into an optimized regular expression. This is easier said than done, and braces is the only library that does this currently. + +**The proof is in the numbers** + +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) | + + +### Faster algorithms + +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) | +| `{1..10000}` | `48.89 kB` (2ms 202μs) | `48.89 kB` (13ms 641μs) | +| `{1..1000}` | `3.89 kB` (1ms 796μs) | `3.89 kB` (1ms 958μs) | +| `{1..100}` | `291 B` (424μs) | `291 B` (211μs) | +| `{1..10}` | `20 B` (487μs) | `20 B` (72μs) | +| `{1..3}` | `5 B` (166μs) | `5 B` (27μs) | + +If you'd like to run these comparisons yourself, see [test/support/generate.js](test/support/generate.js). + + +## Benchmarks + +### Running benchmarks + +Install dev dependencies: + +```bash +npm i -d && npm benchmark +``` + +### Latest results + +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) +``` -[^1]: this is the largest safe integer allowed in JavaScript. +[^1]: this is the largest safe integer allowed in JavaScript. [bash]: www.gnu.org/software/bash/ [braces]: https://github.com/jonschlinkert/braces [brace-expansion]: https://github.com/juliangruber/brace-expansion -[expand-range]: https://github.com/jonschlinkert/expand-range [fill-range]: https://github.com/jonschlinkert/fill-range [micromatch]: https://github.com/jonschlinkert/micromatch [minimatch]: https://github.com/isaacs/minimatch