update electron to v43
All checks were successful
Android Build / publish (push) Successful in 55s
Linux Build / publish (push) Successful in 1m6s

This commit is contained in:
olcxja 2026-07-09 22:38:33 +02:00
commit fb6c8b6ee9
5385 changed files with 513060 additions and 123058 deletions

View file

@ -0,0 +1,2 @@
tidelift: "npm/balanced-match"
patreon: juliangruber

View file

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

View file

@ -0,0 +1,97 @@
# balanced-match
Match balanced string pairs, like `{` and `}` or `<b>` and `</b>`. Supports regular expressions as well!
[![build status](https://secure.travis-ci.org/juliangruber/balanced-match.svg)](http://travis-ci.org/juliangruber/balanced-match)
[![downloads](https://img.shields.io/npm/dm/balanced-match.svg)](https://www.npmjs.org/package/balanced-match)
[![testling badge](https://ci.testling.com/juliangruber/balanced-match.png)](https://ci.testling.com/juliangruber/balanced-match)
## Example
Get the first matching pair of braces:
```js
var balanced = require('balanced-match');
console.log(balanced('{', '}', 'pre{in{nested}}post'));
console.log(balanced('{', '}', 'pre{first}between{second}post'));
console.log(balanced(/\s+\{\s+/, /\s+\}\s+/, 'pre { in{nest} } post'));
```
The matches are:
```bash
$ node example.js
{ start: 3, end: 14, pre: 'pre', body: 'in{nested}', post: 'post' }
{ start: 3,
end: 9,
pre: 'pre',
body: 'first',
post: 'between{second}post' }
{ start: 3, end: 17, pre: 'pre', body: 'in{nest}', post: 'post' }
```
## API
### var m = balanced(a, b, str)
For the first non-nested matching pair of `a` and `b` in `str`, return an
object with those keys:
* **start** the index of the first match of `a`
* **end** the index of the matching `b`
* **pre** the preamble, `a` and `b` not included
* **body** the match, `a` and `b` not included
* **post** the postscript, `a` and `b` not included
If there's no match, `undefined` will be returned.
If the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `['{', 'a', '']` and `{a}}` will match `['', 'a', '}']`.
### var r = balanced.range(a, b, str)
For the first non-nested matching pair of `a` and `b` in `str`, return an
array with indexes: `[ <a index>, <b index> ]`.
If there's no match, `undefined` will be returned.
If the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `[ 1, 3 ]` and `{a}}` will match `[0, 2]`.
## Installation
With [npm](https://npmjs.org) do:
```bash
npm install balanced-match
```
## Security contact information
To report a security vulnerability, please use the
[Tidelift security contact](https://tidelift.com/security).
Tidelift will coordinate the fix and disclosure.
## License
(MIT)
Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,62 @@
'use strict';
module.exports = balanced;
function balanced(a, b, str) {
if (a instanceof RegExp) a = maybeMatch(a, str);
if (b instanceof RegExp) b = maybeMatch(b, str);
var r = range(a, b, str);
return r && {
start: r[0],
end: r[1],
pre: str.slice(0, r[0]),
body: str.slice(r[0] + a.length, r[1]),
post: str.slice(r[1] + b.length)
};
}
function maybeMatch(reg, str) {
var m = str.match(reg);
return m ? m[0] : null;
}
balanced.range = range;
function range(a, b, str) {
var begs, beg, left, right, result;
var ai = str.indexOf(a);
var bi = str.indexOf(b, ai + 1);
var i = ai;
if (ai >= 0 && bi > 0) {
if(a===b) {
return [ai, bi];
}
begs = [];
left = str.length;
while (i >= 0 && !result) {
if (i == ai) {
begs.push(i);
ai = str.indexOf(a, i + 1);
} else if (begs.length == 1) {
result = [ begs.pop(), bi ];
} else {
beg = begs.pop();
if (beg < left) {
left = beg;
right = bi;
}
bi = str.indexOf(b, i + 1);
}
i = ai < bi && ai >= 0 ? ai : bi;
}
if (begs.length) {
result = [ left, right ];
}
}
return result;
}

View file

@ -0,0 +1,48 @@
{
"name": "balanced-match",
"description": "Match balanced character pairs, like \"{\" and \"}\"",
"version": "1.0.2",
"repository": {
"type": "git",
"url": "git://github.com/juliangruber/balanced-match.git"
},
"homepage": "https://github.com/juliangruber/balanced-match",
"main": "index.js",
"scripts": {
"test": "tape test/test.js",
"bench": "matcha test/bench.js"
},
"devDependencies": {
"matcha": "^0.7.0",
"tape": "^4.6.0"
},
"keywords": [
"match",
"regexp",
"test",
"balanced",
"parse"
],
"author": {
"name": "Julian Gruber",
"email": "mail@juliangruber.com",
"url": "http://juliangruber.com"
},
"license": "MIT",
"testling": {
"files": "test/*.js",
"browsers": [
"ie/8..latest",
"firefox/20..latest",
"firefox/nightly",
"chrome/25..latest",
"chrome/canary",
"opera/12..latest",
"opera/next",
"safari/5.1..latest",
"ipad/6.0..latest",
"iphone/6.0..latest",
"android-browser/4.2..latest"
]
}
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,719 @@
{
"date": "2026-07-04T09:15:24.678Z",
"argv": [
"/usr/local/bin/node",
"/workspace/test/index.js"
],
"execArgv": [
"--import=file:///workspace/node_modules/@tapjs/typescript/dist/esm/import.mjs",
"--import=file:///workspace/node_modules/@tapjs/mock/dist/esm/import.mjs",
"--enable-source-maps",
"--import=file:///workspace/node_modules/@tapjs/processinfo/dist/esm/import.mjs"
],
"NODE_OPTIONS": "\"--import=file:///workspace/node_modules/@tapjs/processinfo/dist/esm/import.mjs\"",
"cwd": "/workspace",
"pid": 814,
"ppid": 803,
"parent": null,
"uuid": "8b906b8c-e21f-40b5-8c0d-214d8c2682c5",
"files": [
"/workspace/test/index.js",
"/workspace/node_modules/@tapjs/typescript/dist/esm/import.mjs",
"/workspace/node_modules/@isaacs/ts-node-temp-fork-for-pr-2009/import.mjs",
"/workspace/node_modules/@isaacs/ts-node-temp-fork-for-pr-2009/import-loader.mjs",
"/workspace/node_modules/@tapjs/mock/dist/esm/import.mjs",
"/workspace/node_modules/@tapjs/mock/dist/esm/mock-service.js",
"/workspace/node_modules/@tapjs/core/dist/esm/index.js",
"/workspace/node_modules/@tapjs/core/dist/esm/base.js",
"/workspace/node_modules/@tapjs/core/dist/esm/counts.js",
"/workspace/node_modules/@tapjs/core/dist/esm/extra-from-error.js",
"/workspace/node_modules/resolve-import/dist/esm/resolve-import-sync.min.js",
"/workspace/node_modules/resolve-import/dist/esm/is-relative-require.js",
"/workspace/node_modules/@tapjs/mock/dist/esm/resolve-mock-entry-point.js",
"/workspace/node_modules/@tapjs/mock/dist/esm/export-line.js",
"/workspace/node_modules/@tapjs/mock/dist/esm/service-key.js",
"/workspace/node_modules/@tapjs/mock/dist/esm/munge-mocks.js",
"/workspace/node_modules/@tapjs/stack/dist/esm/index.js",
"/workspace/node_modules/@tapjs/core/dist/esm/lists.js",
"/workspace/node_modules/@tapjs/core/dist/esm/main-script.js",
"/workspace/node_modules/@tapjs/core/dist/esm/minimal.js",
"/workspace/node_modules/@tapjs/core/dist/esm/normalize-message-extra.js",
"/workspace/node_modules/@tapjs/core/dist/esm/parse-test-args.js",
"/workspace/node_modules/@tapjs/core/dist/esm/proc.js",
"/workspace/node_modules/@tapjs/core/dist/esm/tap-file.js",
"/workspace/node_modules/@tapjs/core/dist/esm/spawn.js",
"/workspace/node_modules/@tapjs/core/dist/esm/stdin.js",
"/workspace/node_modules/@tapjs/core/dist/esm/use-sync-hooks.js",
"/workspace/node_modules/@tapjs/core/dist/esm/waiter.js",
"/workspace/node_modules/@tapjs/core/dist/esm/tap-dir.js",
"/workspace/node_modules/@tapjs/core/dist/esm/test-base.js",
"/workspace/node_modules/@tapjs/core/dist/esm/tap.js",
"/workspace/node_modules/@tapjs/core/dist/esm/worker.js",
"/workspace/node_modules/@tapjs/core/dist/esm/test-point.js",
"/workspace/node_modules/async-hook-domain/dist/mjs/index.js",
"/workspace/node_modules/minipass/dist/esm/index.js",
"/workspace/node_modules/tap-parser/dist/esm/index.js",
"/workspace/node_modules/@tapjs/core/dist/esm/diags.js",
"/workspace/node_modules/@tapjs/core/dist/esm/message-from-error.js",
"/workspace/node_modules/resolve-import/dist/esm/is-windows.js",
"/workspace/node_modules/@tapjs/stack/dist/esm/call-site-like.js",
"/workspace/node_modules/@tapjs/stack/dist/esm/require-resolve.js",
"/workspace/node_modules/@tapjs/processinfo/dist/esm/index.js",
"/workspace/node_modules/@tapjs/core/dist/esm/throw-to-parser.js",
"/workspace/node_modules/@tapjs/core/dist/esm/esc.js",
"/workspace/node_modules/@tapjs/test/dist/esm/index.js",
"/workspace/node_modules/@tapjs/core/dist/esm/implicit-end-sigil.js",
"/workspace/node_modules/is-actual-promise/dist/esm/index.js",
"/workspace/node_modules/trivial-deferred/dist/mjs/index.js",
"/workspace/node_modules/tap-yaml/dist/esm/index.js",
"/workspace/node_modules/tap-parser/dist/esm/final-results.js",
"/workspace/node_modules/tap-parser/dist/esm/plan.js",
"/workspace/node_modules/tap-parser/dist/esm/line-type.js",
"/workspace/node_modules/tap-parser/dist/esm/parse-directive.js",
"/workspace/node_modules/tap-parser/dist/esm/result.js",
"/workspace/node_modules/tap-parser/dist/esm/statics.js",
"/workspace/node_modules/@tapjs/core/dist/esm/clean-yaml-object.js",
"/workspace/node_modules/tap-parser/dist/esm/escape.js",
"/workspace/node_modules/@tapjs/stack/dist/esm/parse.js",
"/workspace/node_modules/@tapjs/processinfo/dist/esm/child_process.js",
"/workspace/node_modules/@tapjs/processinfo/dist/esm/process-info-node.js",
"/workspace/node_modules/@tapjs/processinfo/dist/esm/json-file.js",
"/workspace/node_modules/@tapjs/test/test-built/dist/esm/index.js",
"/workspace/node_modules/tap-parser/dist/esm/final-plan.js",
"/workspace/node_modules/tap-yaml/dist/esm/parse.js",
"/workspace/node_modules/tap-yaml/dist/esm/stringify.js",
"/workspace/node_modules/@tapjs/test/dist/esm/default-plugins.js",
"/workspace/node_modules/tap-parser/dist/esm/brace-patterns.js",
"/workspace/node_modules/diff/libesm/index.js",
"/workspace/node_modules/tcompare/dist/esm/index.js",
"/workspace/node_modules/@tapjs/processinfo/dist/esm/spawn-opts.js",
"/workspace/node_modules/@tapjs/after/dist/esm/index.js",
"/workspace/node_modules/@tapjs/after-each/dist/esm/index.js",
"/workspace/node_modules/@tapjs/asserts/dist/esm/index.js",
"/workspace/node_modules/@tapjs/before/dist/esm/index.js",
"/workspace/node_modules/@tapjs/before-each/dist/esm/index.js",
"/workspace/node_modules/@tapjs/chdir/dist/esm/index.js",
"/workspace/node_modules/@tapjs/filter/dist/esm/index.js",
"/workspace/node_modules/@tapjs/fixture/dist/esm/index.js",
"/workspace/node_modules/@tapjs/intercept/dist/esm/index.js",
"/workspace/node_modules/@tapjs/mock/dist/esm/index.js",
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/index.js",
"/workspace/node_modules/@tapjs/snapshot/dist/esm/index.js",
"/workspace/node_modules/@tapjs/spawn/dist/esm/index.js",
"/workspace/node_modules/@tapjs/stdin/dist/esm/index.js",
"/workspace/node_modules/@tapjs/typescript/dist/esm/index.js",
"/workspace/node_modules/@tapjs/worker/dist/esm/index.js",
"/workspace/node_modules/jackspeak/dist/esm/index.js",
"/workspace/node_modules/tap-yaml/dist/esm/types/index.js",
"/workspace/node_modules/diff/libesm/patch/parse.js",
"/workspace/node_modules/diff/libesm/patch/reverse.js",
"/workspace/node_modules/diff/libesm/patch/create.js",
"/workspace/node_modules/diff/libesm/convert/dmp.js",
"/workspace/node_modules/diff/libesm/convert/xml.js",
"/workspace/node_modules/diff/libesm/diff/base.js",
"/workspace/node_modules/diff/libesm/diff/character.js",
"/workspace/node_modules/diff/libesm/diff/word.js",
"/workspace/node_modules/diff/libesm/diff/line.js",
"/workspace/node_modules/diff/libesm/diff/sentence.js",
"/workspace/node_modules/diff/libesm/diff/css.js",
"/workspace/node_modules/diff/libesm/diff/array.js",
"/workspace/node_modules/diff/libesm/diff/json.js",
"/workspace/node_modules/diff/libesm/patch/apply.js",
"/workspace/node_modules/tcompare/dist/esm/format.js",
"/workspace/node_modules/tcompare/dist/esm/has-strict.js",
"/workspace/node_modules/tcompare/dist/esm/has.js",
"/workspace/node_modules/tcompare/dist/esm/match-strict.js",
"/workspace/node_modules/tcompare/dist/esm/match-only.js",
"/workspace/node_modules/tcompare/dist/esm/match-only-strict.js",
"/workspace/node_modules/tcompare/dist/esm/match.js",
"/workspace/node_modules/tcompare/dist/esm/strict.js",
"/workspace/node_modules/tcompare/dist/esm/styles.js",
"/workspace/node_modules/tcompare/dist/esm/same.js",
"/workspace/node_modules/function-loop/dist/mjs/index.js",
"/workspace/node_modules/@tapjs/asserts/dist/esm/normalize-throws-args.js",
"/workspace/node_modules/rimraf/dist/esm/index.js",
"/workspace/node_modules/@tapjs/fixture/dist/esm/fixture.js",
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/serialize.js",
"/workspace/node_modules/@tapjs/mock/dist/esm/mock-require.js",
"/workspace/node_modules/@tapjs/snapshot/dist/esm/clean-cwd.js",
"/workspace/node_modules/@tapjs/snapshot/dist/esm/provider.js",
"/workspace/node_modules/@isaacs/cliui/dist/esm/index.min.js",
"/workspace/node_modules/tap-yaml/dist/esm/types/date.js",
"/workspace/node_modules/tap-yaml/dist/esm/types/timestamp.js",
"/workspace/node_modules/diff/libesm/util/string.js",
"/workspace/node_modules/diff/libesm/util/distance-iterator.js",
"/workspace/node_modules/diff/libesm/patch/line-endings.js",
"/workspace/node_modules/diff/libesm/util/params.js",
"/workspace/node_modules/tcompare/dist/esm/react-element-to-jsx-string.js",
"/workspace/node_modules/rimraf/dist/esm/opt-arg.js",
"/workspace/node_modules/glob/dist/esm/index.min.js",
"/workspace/node_modules/rimraf/dist/esm/path-arg.js",
"/workspace/node_modules/rimraf/dist/esm/rimraf-manual.js",
"/workspace/node_modules/rimraf/dist/esm/rimraf-move-remove.js",
"/workspace/node_modules/rimraf/dist/esm/rimraf-native.js",
"/workspace/node_modules/rimraf/dist/esm/rimraf-posix.js",
"/workspace/node_modules/rimraf/dist/esm/rimraf-windows.js",
"/workspace/node_modules/rimraf/dist/esm/use-native.js",
"/workspace/node_modules/mkdirp/dist/mjs/index.js",
"/workspace/node_modules/walk-up-path/dist/esm/index.js",
"/workspace/node_modules/@tapjs/error-serdes/dist/esm/index.js",
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/comment.js",
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/on-add.js",
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/print-messages.js",
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/stdio.js",
"/workspace/node_modules/@tapjs/snapshot/dist/esm/require.js",
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/test-map.js",
"/workspace/node_modules/mkdirp/dist/mjs/mkdirp-manual.js",
"/workspace/node_modules/mkdirp/dist/mjs/opts-arg.js",
"/workspace/node_modules/mkdirp/dist/mjs/mkdirp-native.js",
"/workspace/node_modules/rimraf/dist/esm/default-tmp.js",
"/workspace/node_modules/mkdirp/dist/mjs/path-arg.js",
"/workspace/node_modules/mkdirp/dist/mjs/use-native.js",
"/workspace/node_modules/rimraf/dist/esm/ignore-enoent.js",
"/workspace/node_modules/rimraf/dist/esm/readdir-or-error.js",
"/workspace/node_modules/rimraf/dist/esm/fix-eperm.js",
"/workspace/node_modules/rimraf/dist/esm/error.js",
"/workspace/node_modules/rimraf/dist/esm/retry-busy.js",
"/workspace/node_modules/rimraf/dist/esm/fs.js",
"/workspace/node_modules/@tapjs/error-serdes/dist/esm/test-stream-serialize.js",
"/workspace/node_modules/@tapjs/error-serdes/dist/esm/serialize.js",
"/workspace/node_modules/@tapjs/error-serdes/dist/esm/deserialize.js",
"/workspace/node_modules/@tapjs/error-serdes/dist/esm/test-stream-deserialize.js",
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/test-nested-location.js",
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/loc-from-at.js",
"/workspace/node_modules/@tapjs/error-serdes/dist/esm/constants.js",
"/workspace/node_modules/@tapjs/error-serdes/dist/esm/messages.js",
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/test-results.js",
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/test-point-message-data.js",
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/test-message-data.js",
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/test-point-results.js",
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/loc-from-callsite.js",
"/workspace/node_modules/mkdirp/dist/mjs/find-made.js",
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/result-to-error.js",
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/pretty-diff.js",
"/workspace/node_modules/@tapjs/mock/dist/esm/loader.mjs",
"/workspace/node_modules/@tapjs/mock/dist/esm/hooks.mjs",
"/workspace/node_modules/@tapjs/mock/dist/esm/mock-service-client.js",
"/workspace/node_modules/tap/dist/esm/index.js",
"/workspace/dist/esm/index.js",
"/workspace/node_modules/tap/dist/esm/main.js",
"/workspace/node_modules/balanced-match/dist/esm/index.js"
],
"sources": {
"/workspace/node_modules/@tapjs/typescript/dist/esm/import.mjs": [
"/workspace/node_modules/@tapjs/typescript/src/import.mts"
],
"/workspace/node_modules/@tapjs/mock/dist/esm/import.mjs": [
"/workspace/node_modules/@tapjs/mock/src/import.mts"
],
"/workspace/node_modules/@tapjs/mock/dist/esm/mock-service.js": [
"/workspace/node_modules/@tapjs/mock/src/mock-service.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/core/src/index.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/base.js": [
"/workspace/node_modules/@tapjs/core/src/base.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/counts.js": [
"/workspace/node_modules/@tapjs/core/src/counts.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/extra-from-error.js": [
"/workspace/node_modules/@tapjs/core/src/extra-from-error.ts"
],
"/workspace/node_modules/resolve-import/dist/esm/resolve-import-sync.min.js": [
"/workspace/node_modules/resolve-import/src/resolve-import-sync.ts",
"/workspace/node_modules/resolve-import/src/resolve-import-async.ts",
"/workspace/node_modules/resolve-import/src/file-exists.ts",
"/workspace/node_modules/resolve-import/src/is-windows.ts",
"/workspace/node_modules/resolve-import/src/is-relative-require.ts",
"/workspace/node_modules/resolve-import/src/resolve-dependency-export.ts",
"/workspace/node_modules/resolve-import/src/find-dep-package.ts",
"/workspace/node_modules/resolve-import/node_modules/walk-up-path/src/index.ts",
"/workspace/node_modules/resolve-import/src/read-json.ts",
"/workspace/node_modules/resolve-import/src/read-pkg.ts",
"/workspace/node_modules/resolve-import/src/find-star-match.ts",
"/workspace/node_modules/resolve-import/src/resolve-conditional-value.ts",
"/workspace/node_modules/resolve-import/src/resolve-export.ts",
"/workspace/node_modules/resolve-import/src/resolve-dependency-export-sync.ts",
"/workspace/node_modules/resolve-import/src/resolve-package-import.ts",
"/workspace/node_modules/resolve-import/src/resolve-package-import-sync.ts",
"/workspace/node_modules/resolve-import/src/to-file-url.ts",
"/workspace/node_modules/resolve-import/src/to-path.ts",
"/workspace/node_modules/resolve-import/src/errors.ts"
],
"/workspace/node_modules/resolve-import/dist/esm/is-relative-require.js": [
"/workspace/node_modules/resolve-import/src/is-relative-require.ts"
],
"/workspace/node_modules/@tapjs/mock/dist/esm/resolve-mock-entry-point.js": [
"/workspace/node_modules/@tapjs/mock/src/resolve-mock-entry-point.ts"
],
"/workspace/node_modules/@tapjs/mock/dist/esm/export-line.js": [
"/workspace/node_modules/@tapjs/mock/src/export-line.ts"
],
"/workspace/node_modules/@tapjs/mock/dist/esm/service-key.js": [
"/workspace/node_modules/@tapjs/mock/src/service-key.ts"
],
"/workspace/node_modules/@tapjs/mock/dist/esm/munge-mocks.js": [
"/workspace/node_modules/@tapjs/mock/src/munge-mocks.ts"
],
"/workspace/node_modules/@tapjs/stack/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/stack/src/index.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/lists.js": [
"/workspace/node_modules/@tapjs/core/src/lists.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/main-script.js": [
"/workspace/node_modules/@tapjs/core/src/main-script.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/minimal.js": [
"/workspace/node_modules/@tapjs/core/src/minimal.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/normalize-message-extra.js": [
"/workspace/node_modules/@tapjs/core/src/normalize-message-extra.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/parse-test-args.js": [
"/workspace/node_modules/@tapjs/core/src/parse-test-args.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/proc.js": [
"/workspace/node_modules/@tapjs/core/src/proc.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/tap-file.js": [
"/workspace/node_modules/@tapjs/core/src/tap-file.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/spawn.js": [
"/workspace/node_modules/@tapjs/core/src/spawn.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/stdin.js": [
"/workspace/node_modules/@tapjs/core/src/stdin.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/use-sync-hooks.js": [
"/workspace/node_modules/@tapjs/core/src/use-sync-hooks.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/waiter.js": [
"/workspace/node_modules/@tapjs/core/src/waiter.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/tap-dir.js": [
"/workspace/node_modules/@tapjs/core/src/tap-dir.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/test-base.js": [
"/workspace/node_modules/@tapjs/core/src/test-base.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/tap.js": [
"/workspace/node_modules/@tapjs/core/src/tap.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/worker.js": [
"/workspace/node_modules/@tapjs/core/src/worker.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/test-point.js": [
"/workspace/node_modules/@tapjs/core/src/test-point.ts"
],
"/workspace/node_modules/async-hook-domain/dist/mjs/index.js": [
"/workspace/node_modules/async-hook-domain/src/index.ts"
],
"/workspace/node_modules/minipass/dist/esm/index.js": [
"/workspace/node_modules/minipass/src/index.ts"
],
"/workspace/node_modules/tap-parser/dist/esm/index.js": [
"/workspace/node_modules/tap-parser/src/index.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/diags.js": [
"/workspace/node_modules/@tapjs/core/src/diags.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/message-from-error.js": [
"/workspace/node_modules/@tapjs/core/src/message-from-error.ts"
],
"/workspace/node_modules/resolve-import/dist/esm/is-windows.js": [
"/workspace/node_modules/resolve-import/src/is-windows.ts"
],
"/workspace/node_modules/@tapjs/stack/dist/esm/call-site-like.js": [
"/workspace/node_modules/@tapjs/stack/src/call-site-like.ts"
],
"/workspace/node_modules/@tapjs/stack/dist/esm/require-resolve.js": [
"/workspace/node_modules/@tapjs/stack/src/require-resolve.ts"
],
"/workspace/node_modules/@tapjs/processinfo/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/processinfo/src/index.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/throw-to-parser.js": [
"/workspace/node_modules/@tapjs/core/src/throw-to-parser.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/esc.js": [
"/workspace/node_modules/@tapjs/core/src/esc.ts"
],
"/workspace/node_modules/@tapjs/test/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/test/src/index.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/implicit-end-sigil.js": [
"/workspace/node_modules/@tapjs/core/src/implicit-end-sigil.ts"
],
"/workspace/node_modules/is-actual-promise/dist/esm/index.js": [
"/workspace/node_modules/is-actual-promise/src/index.ts"
],
"/workspace/node_modules/trivial-deferred/dist/mjs/index.js": [
"/workspace/node_modules/trivial-deferred/src/index.ts"
],
"/workspace/node_modules/tap-yaml/dist/esm/index.js": [
"/workspace/node_modules/tap-yaml/src/index.ts"
],
"/workspace/node_modules/tap-parser/dist/esm/final-results.js": [
"/workspace/node_modules/tap-parser/src/final-results.ts"
],
"/workspace/node_modules/tap-parser/dist/esm/plan.js": [
"/workspace/node_modules/tap-parser/src/plan.ts"
],
"/workspace/node_modules/tap-parser/dist/esm/line-type.js": [
"/workspace/node_modules/tap-parser/src/line-type.ts"
],
"/workspace/node_modules/tap-parser/dist/esm/parse-directive.js": [
"/workspace/node_modules/tap-parser/src/parse-directive.ts"
],
"/workspace/node_modules/tap-parser/dist/esm/result.js": [
"/workspace/node_modules/tap-parser/src/result.ts"
],
"/workspace/node_modules/tap-parser/dist/esm/statics.js": [
"/workspace/node_modules/tap-parser/src/statics.ts"
],
"/workspace/node_modules/@tapjs/core/dist/esm/clean-yaml-object.js": [
"/workspace/node_modules/@tapjs/core/src/clean-yaml-object.ts"
],
"/workspace/node_modules/tap-parser/dist/esm/escape.js": [
"/workspace/node_modules/tap-parser/src/escape.ts"
],
"/workspace/node_modules/@tapjs/stack/dist/esm/parse.js": [
"/workspace/node_modules/@tapjs/stack/src/parse.ts"
],
"/workspace/node_modules/@tapjs/processinfo/dist/esm/child_process.js": [
"/workspace/node_modules/@tapjs/processinfo/src/child_process.ts"
],
"/workspace/node_modules/@tapjs/processinfo/dist/esm/process-info-node.js": [
"/workspace/node_modules/@tapjs/processinfo/src/process-info-node.ts"
],
"/workspace/node_modules/@tapjs/processinfo/dist/esm/json-file.js": [
"/workspace/node_modules/@tapjs/processinfo/src/json-file.ts"
],
"/workspace/node_modules/@tapjs/test/test-built/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/test/test-built/src/index.ts"
],
"/workspace/node_modules/tap-parser/dist/esm/final-plan.js": [
"/workspace/node_modules/tap-parser/src/final-plan.ts"
],
"/workspace/node_modules/tap-yaml/dist/esm/parse.js": [
"/workspace/node_modules/tap-yaml/src/parse.ts"
],
"/workspace/node_modules/tap-yaml/dist/esm/stringify.js": [
"/workspace/node_modules/tap-yaml/src/stringify.ts"
],
"/workspace/node_modules/@tapjs/test/dist/esm/default-plugins.js": [
"/workspace/node_modules/@tapjs/test/src/default-plugins.ts"
],
"/workspace/node_modules/tap-parser/dist/esm/brace-patterns.js": [
"/workspace/node_modules/tap-parser/src/brace-patterns.ts"
],
"/workspace/node_modules/tcompare/dist/esm/index.js": [
"/workspace/node_modules/tcompare/src/index.ts"
],
"/workspace/node_modules/@tapjs/processinfo/dist/esm/spawn-opts.js": [
"/workspace/node_modules/@tapjs/processinfo/src/spawn-opts.ts"
],
"/workspace/node_modules/@tapjs/after/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/after/src/index.ts"
],
"/workspace/node_modules/@tapjs/after-each/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/after-each/src/index.ts"
],
"/workspace/node_modules/@tapjs/asserts/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/asserts/src/index.ts"
],
"/workspace/node_modules/@tapjs/before/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/before/src/index.ts"
],
"/workspace/node_modules/@tapjs/before-each/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/before-each/src/index.ts"
],
"/workspace/node_modules/@tapjs/chdir/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/chdir/src/index.ts"
],
"/workspace/node_modules/@tapjs/filter/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/filter/src/index.ts"
],
"/workspace/node_modules/@tapjs/fixture/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/fixture/src/index.ts"
],
"/workspace/node_modules/@tapjs/intercept/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/intercept/src/index.ts"
],
"/workspace/node_modules/@tapjs/mock/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/mock/src/index.ts"
],
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/node-serialize/src/index.ts"
],
"/workspace/node_modules/@tapjs/snapshot/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/snapshot/src/index.ts"
],
"/workspace/node_modules/@tapjs/spawn/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/spawn/src/index.ts"
],
"/workspace/node_modules/@tapjs/stdin/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/stdin/src/index.ts"
],
"/workspace/node_modules/@tapjs/typescript/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/typescript/src/index.ts"
],
"/workspace/node_modules/@tapjs/worker/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/worker/src/index.ts"
],
"/workspace/node_modules/jackspeak/dist/esm/index.js": [
"/workspace/node_modules/jackspeak/src/index.ts"
],
"/workspace/node_modules/tap-yaml/dist/esm/types/index.js": [
"/workspace/node_modules/tap-yaml/src/types/index.ts"
],
"/workspace/node_modules/tcompare/dist/esm/format.js": [
"/workspace/node_modules/tcompare/src/format.ts"
],
"/workspace/node_modules/tcompare/dist/esm/has-strict.js": [
"/workspace/node_modules/tcompare/src/has-strict.ts"
],
"/workspace/node_modules/tcompare/dist/esm/has.js": [
"/workspace/node_modules/tcompare/src/has.ts"
],
"/workspace/node_modules/tcompare/dist/esm/match-strict.js": [
"/workspace/node_modules/tcompare/src/match-strict.ts"
],
"/workspace/node_modules/tcompare/dist/esm/match-only.js": [
"/workspace/node_modules/tcompare/src/match-only.ts"
],
"/workspace/node_modules/tcompare/dist/esm/match-only-strict.js": [
"/workspace/node_modules/tcompare/src/match-only-strict.ts"
],
"/workspace/node_modules/tcompare/dist/esm/match.js": [
"/workspace/node_modules/tcompare/src/match.ts"
],
"/workspace/node_modules/tcompare/dist/esm/strict.js": [
"/workspace/node_modules/tcompare/src/strict.ts"
],
"/workspace/node_modules/tcompare/dist/esm/styles.js": [
"/workspace/node_modules/tcompare/src/styles.ts"
],
"/workspace/node_modules/tcompare/dist/esm/same.js": [
"/workspace/node_modules/tcompare/src/same.ts"
],
"/workspace/node_modules/function-loop/dist/mjs/index.js": [
"/workspace/node_modules/function-loop/src/index.ts"
],
"/workspace/node_modules/@tapjs/asserts/dist/esm/normalize-throws-args.js": [
"/workspace/node_modules/@tapjs/asserts/src/normalize-throws-args.ts"
],
"/workspace/node_modules/rimraf/dist/esm/index.js": [
"/workspace/node_modules/rimraf/src/index.ts"
],
"/workspace/node_modules/@tapjs/fixture/dist/esm/fixture.js": [
"/workspace/node_modules/@tapjs/fixture/src/fixture.ts"
],
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/serialize.js": [
"/workspace/node_modules/@tapjs/node-serialize/src/serialize.ts"
],
"/workspace/node_modules/@tapjs/mock/dist/esm/mock-require.js": [
"/workspace/node_modules/@tapjs/mock/src/mock-require.ts"
],
"/workspace/node_modules/@tapjs/snapshot/dist/esm/clean-cwd.js": [
"/workspace/node_modules/@tapjs/snapshot/src/clean-cwd.ts"
],
"/workspace/node_modules/@tapjs/snapshot/dist/esm/provider.js": [
"/workspace/node_modules/@tapjs/snapshot/src/provider.ts"
],
"/workspace/node_modules/@isaacs/cliui/dist/esm/index.min.js": [
"/workspace/node_modules/@isaacs/cliui/src/ansi-regex/index.ts",
"/workspace/node_modules/@isaacs/cliui/src/strip-ansi/index.ts",
"/workspace/node_modules/@isaacs/cliui/src/eastasianwidth/index.ts",
"/workspace/node_modules/@isaacs/cliui/src/emoji-regex/index.ts",
"/workspace/node_modules/@isaacs/cliui/src/string-width/index.ts",
"/workspace/node_modules/@isaacs/cliui/src/ansi-styles/index.ts",
"/workspace/node_modules/@isaacs/cliui/src/wrap-ansi/index.ts",
"/workspace/node_modules/@isaacs/cliui/src/index.ts"
],
"/workspace/node_modules/tap-yaml/dist/esm/types/date.js": [
"/workspace/node_modules/tap-yaml/src/types/date.ts"
],
"/workspace/node_modules/tap-yaml/dist/esm/types/timestamp.js": [
"/workspace/node_modules/tap-yaml/src/types/timestamp.ts"
],
"/workspace/node_modules/tcompare/dist/esm/react-element-to-jsx-string.js": [
"/workspace/node_modules/tcompare/src/react-element-to-jsx-string.ts"
],
"/workspace/node_modules/rimraf/dist/esm/opt-arg.js": [
"/workspace/node_modules/rimraf/src/opt-arg.ts"
],
"/workspace/node_modules/glob/dist/esm/index.min.js": [
"/workspace/node_modules/glob/node_modules/balanced-match/src/index.ts",
"/workspace/node_modules/glob/node_modules/brace-expansion/src/index.ts",
"/workspace/node_modules/glob/node_modules/minimatch/src/assert-valid-pattern.ts",
"/workspace/node_modules/glob/node_modules/minimatch/src/brace-expressions.ts",
"/workspace/node_modules/glob/node_modules/minimatch/src/unescape.ts",
"/workspace/node_modules/glob/node_modules/minimatch/src/ast.ts",
"/workspace/node_modules/glob/node_modules/minimatch/src/escape.ts",
"/workspace/node_modules/glob/node_modules/minimatch/src/index.ts",
"/workspace/node_modules/glob/src/glob.ts",
"/workspace/node_modules/glob/node_modules/lru-cache/src/index.ts",
"/workspace/node_modules/glob/node_modules/path-scurry/src/index.ts",
"/workspace/node_modules/glob/node_modules/minipass/src/index.ts",
"/workspace/node_modules/glob/src/pattern.ts",
"/workspace/node_modules/glob/src/ignore.ts",
"/workspace/node_modules/glob/src/processor.ts",
"/workspace/node_modules/glob/src/walker.ts",
"/workspace/node_modules/glob/src/has-magic.ts",
"/workspace/node_modules/glob/src/index.ts"
],
"/workspace/node_modules/rimraf/dist/esm/path-arg.js": [
"/workspace/node_modules/rimraf/src/path-arg.ts"
],
"/workspace/node_modules/rimraf/dist/esm/rimraf-manual.js": [
"/workspace/node_modules/rimraf/src/rimraf-manual.ts"
],
"/workspace/node_modules/rimraf/dist/esm/rimraf-move-remove.js": [
"/workspace/node_modules/rimraf/src/rimraf-move-remove.ts"
],
"/workspace/node_modules/rimraf/dist/esm/rimraf-native.js": [
"/workspace/node_modules/rimraf/src/rimraf-native.ts"
],
"/workspace/node_modules/rimraf/dist/esm/rimraf-posix.js": [
"/workspace/node_modules/rimraf/src/rimraf-posix.ts"
],
"/workspace/node_modules/rimraf/dist/esm/rimraf-windows.js": [
"/workspace/node_modules/rimraf/src/rimraf-windows.ts"
],
"/workspace/node_modules/rimraf/dist/esm/use-native.js": [
"/workspace/node_modules/rimraf/src/use-native.ts"
],
"/workspace/node_modules/mkdirp/dist/mjs/index.js": [
"/workspace/node_modules/mkdirp/src/index.ts"
],
"/workspace/node_modules/walk-up-path/dist/esm/index.js": [
"/workspace/node_modules/walk-up-path/src/index.ts"
],
"/workspace/node_modules/@tapjs/error-serdes/dist/esm/index.js": [
"/workspace/node_modules/@tapjs/error-serdes/src/index.ts"
],
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/comment.js": [
"/workspace/node_modules/@tapjs/node-serialize/src/comment.ts"
],
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/on-add.js": [
"/workspace/node_modules/@tapjs/node-serialize/src/on-add.ts"
],
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/print-messages.js": [
"/workspace/node_modules/@tapjs/node-serialize/src/print-messages.ts"
],
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/stdio.js": [
"/workspace/node_modules/@tapjs/node-serialize/src/stdio.ts"
],
"/workspace/node_modules/@tapjs/snapshot/dist/esm/require.js": [
"/workspace/node_modules/@tapjs/snapshot/src/require.ts"
],
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/test-map.js": [
"/workspace/node_modules/@tapjs/node-serialize/src/test-map.ts"
],
"/workspace/node_modules/mkdirp/dist/mjs/mkdirp-manual.js": [
"/workspace/node_modules/mkdirp/src/mkdirp-manual.ts"
],
"/workspace/node_modules/mkdirp/dist/mjs/opts-arg.js": [
"/workspace/node_modules/mkdirp/src/opts-arg.ts"
],
"/workspace/node_modules/mkdirp/dist/mjs/mkdirp-native.js": [
"/workspace/node_modules/mkdirp/src/mkdirp-native.ts"
],
"/workspace/node_modules/rimraf/dist/esm/default-tmp.js": [
"/workspace/node_modules/rimraf/src/default-tmp.ts"
],
"/workspace/node_modules/mkdirp/dist/mjs/path-arg.js": [
"/workspace/node_modules/mkdirp/src/path-arg.ts"
],
"/workspace/node_modules/mkdirp/dist/mjs/use-native.js": [
"/workspace/node_modules/mkdirp/src/use-native.ts"
],
"/workspace/node_modules/rimraf/dist/esm/ignore-enoent.js": [
"/workspace/node_modules/rimraf/src/ignore-enoent.ts"
],
"/workspace/node_modules/rimraf/dist/esm/readdir-or-error.js": [
"/workspace/node_modules/rimraf/src/readdir-or-error.ts"
],
"/workspace/node_modules/rimraf/dist/esm/fix-eperm.js": [
"/workspace/node_modules/rimraf/src/fix-eperm.ts"
],
"/workspace/node_modules/rimraf/dist/esm/error.js": [
"/workspace/node_modules/rimraf/src/error.ts"
],
"/workspace/node_modules/rimraf/dist/esm/retry-busy.js": [
"/workspace/node_modules/rimraf/src/retry-busy.ts"
],
"/workspace/node_modules/rimraf/dist/esm/fs.js": [
"/workspace/node_modules/rimraf/src/fs.ts"
],
"/workspace/node_modules/@tapjs/error-serdes/dist/esm/test-stream-serialize.js": [
"/workspace/node_modules/@tapjs/error-serdes/src/test-stream-serialize.ts"
],
"/workspace/node_modules/@tapjs/error-serdes/dist/esm/serialize.js": [
"/workspace/node_modules/@tapjs/error-serdes/src/serialize.ts"
],
"/workspace/node_modules/@tapjs/error-serdes/dist/esm/deserialize.js": [
"/workspace/node_modules/@tapjs/error-serdes/src/deserialize.ts"
],
"/workspace/node_modules/@tapjs/error-serdes/dist/esm/test-stream-deserialize.js": [
"/workspace/node_modules/@tapjs/error-serdes/src/test-stream-deserialize.ts"
],
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/test-nested-location.js": [
"/workspace/node_modules/@tapjs/node-serialize/src/test-nested-location.ts"
],
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/loc-from-at.js": [
"/workspace/node_modules/@tapjs/node-serialize/src/loc-from-at.ts"
],
"/workspace/node_modules/@tapjs/error-serdes/dist/esm/constants.js": [
"/workspace/node_modules/@tapjs/error-serdes/src/constants.ts"
],
"/workspace/node_modules/@tapjs/error-serdes/dist/esm/messages.js": [
"/workspace/node_modules/@tapjs/error-serdes/src/messages.ts"
],
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/test-results.js": [
"/workspace/node_modules/@tapjs/node-serialize/src/test-results.ts"
],
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/test-point-message-data.js": [
"/workspace/node_modules/@tapjs/node-serialize/src/test-point-message-data.ts"
],
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/test-message-data.js": [
"/workspace/node_modules/@tapjs/node-serialize/src/test-message-data.ts"
],
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/test-point-results.js": [
"/workspace/node_modules/@tapjs/node-serialize/src/test-point-results.ts"
],
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/loc-from-callsite.js": [
"/workspace/node_modules/@tapjs/node-serialize/src/loc-from-callsite.ts"
],
"/workspace/node_modules/mkdirp/dist/mjs/find-made.js": [
"/workspace/node_modules/mkdirp/src/find-made.ts"
],
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/result-to-error.js": [
"/workspace/node_modules/@tapjs/node-serialize/src/result-to-error.ts"
],
"/workspace/node_modules/@tapjs/node-serialize/dist/esm/pretty-diff.js": [
"/workspace/node_modules/@tapjs/node-serialize/src/pretty-diff.ts"
],
"/workspace/node_modules/tap/dist/esm/index.js": [
"/workspace/node_modules/tap/src/index.ts"
],
"/workspace/dist/esm/index.js": [
"/workspace/src/index.ts"
],
"/workspace/node_modules/tap/dist/esm/main.js": [
"/workspace/node_modules/tap/src/main.ts"
],
"/workspace/node_modules/balanced-match/dist/esm/index.js": [
"/workspace/node_modules/balanced-match/src/index.ts"
]
},
"root": "8b906b8c-e21f-40b5-8c0d-214d8c2682c5",
"externalID": "test/index.js",
"code": 0,
"signal": null,
"runtime": 2740.9173339999998
}

View file

@ -0,0 +1,107 @@
# DoS via unbounded expansion length — out-of-memory process crash
- **CVE:** CVE-2026-14257
- **Package:** brace-expansion (npm)
- **Reporter:** @bnbdr
- **Severity (proposed):** High — `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H` (7.5)
- **Weakness:** CWE-770 (Allocation of Resources Without Limits or Throttling) / CWE-400 (Uncontrolled Resource Consumption)
- **Affected:** all versions up to and including `5.0.7` (the `1.x`, `2.x`, `3.x` and `4.x` lines share the same combine logic and are expected to be affected)
### Summary
`expand()` bounds the *number* of results it produces (the `max` option,
`100_000` by default) but not their *length*. By chaining many brace groups,
an attacker keeps the result count under `max` while making every result grow
with the number of groups. Building `max` long results — plus the intermediate
arrays combined at each brace group — exhausts memory and crashes the Node
process with an **uncatchable** out-of-memory error. `try/catch` around
`expand()` does not help: the fatal error terminates the process.
A ~7.5 KB input (`'{a,b}'.repeat(1500)`) is enough to crash a default Node
process.
### Details
For `N` chained brace groups such as `'{a,b}'.repeat(N)`:
- the result count is `2^N`, immediately capped at `max` (`100_000`), so the
`max` protection appears to hold, but
- each result is `N` characters long, so the total output size is
`max × N` characters, which grows without bound in `N`.
`expand_` combines each brace set with the fully-expanded tail:
```js
const post = m.post.length ? expand_(m.post, max, false) : ['']
...
for (let j = 0; j < N.length; j++) {
for (let k = 0; k < post.length && expansions.length < max; k++) {
const expansion = pre + N[j] + post[k] // grows one group longer per level
...
expansions.push(expansion)
}
}
```
The loop guard `expansions.length < max` limits how many strings are built, but
nothing limits how long they get. Each recursion level materializes another
array of up to `max` strings, one character longer than the level below, and —
because V8 represents `pre + N[j] + post[k]` as a cons-string (rope) that
references `post[k]` — those intermediate strings stay reachable through the
whole chain. Memory therefore scales with `max × N`.
Measured on `5.0.7` (`'{a,b}'.repeat(N)`, default `max`):
| groups (N) | input bytes | result count | peak RSS |
|---|---|---|---|
| 20 | 100 | 100,000 | ~80 MB |
| 50 | 250 | 100,000 | ~214 MB |
| 100 | 500 | 100,000 | ~409 MB |
| 300 | 1,500 | 100,000 | ~1,148 MB |
| 1500 | 7,500 | — | **OOM crash** |
### Proof of concept
```js
const { expand } = require('brace-expansion')
// ~7.5 KB input — crashes the process with a fatal, uncatchable OOM:
// FATAL ERROR: ... JavaScript heap out of memory
try {
expand('{a,b}'.repeat(1500))
} catch (e) {
// never reached — the process is already dead
}
```
### Impact
Any application that passes attacker-influenced strings to
`brace-expansion.expand()` — directly, or transitively via `minimatch` / `glob`
brace patterns — can be crashed by a small request. Because the failure is a
fatal V8 out-of-memory error rather than a thrown exception, it cannot be caught
and it takes down the whole worker/process, denying service.
### Remediation
Upgrade to a patched release. The fix bounds the total number of characters a
single `expand()` call may accumulate (`EXPANSION_MAX_LENGTH`, default
`4_000_000`, configurable via a new `maxLength` option), applied inside the
output-building loops so intermediate arrays are bounded too. Once the limit is
reached, output is truncated — consistent with how `max` already truncates —
instead of growing without bound. The limit sits well above any realistic
expansion (100,000 results hitting `max` measure ~1M characters), so legitimate
input is unaffected.
After the fix, `'{a,b}'.repeat(1500)` returns a bounded, truncated result in
~0.7 s using ~340 MB and never crashes, including under a constrained 512 MB
heap.
The fix bounds memory but the algorithm still rebuilds intermediate arrays at
each level (roughly `O(N × maxLength)` work on this input class). A streaming
rewrite that produces output in `O(total output size)` can be a non-urgent
follow-up.
If immediate upgrade isn't possible, avoid passing untrusted input to
`expand()` / glob brace patterns, or pass a small explicit `max` **and**
`maxLength`.

View file

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

View file

@ -0,0 +1,129 @@
# brace-expansion
[Brace expansion](https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html),
as known from sh/bash, in JavaScript.
[![build status](https://secure.travis-ci.org/juliangruber/brace-expansion.svg)](http://travis-ci.org/juliangruber/brace-expansion)
[![downloads](https://img.shields.io/npm/dm/brace-expansion.svg)](https://www.npmjs.org/package/brace-expansion)
[![Greenkeeper badge](https://badges.greenkeeper.io/juliangruber/brace-expansion.svg)](https://greenkeeper.io/)
[![testling badge](https://ci.testling.com/juliangruber/brace-expansion.png)](https://ci.testling.com/juliangruber/brace-expansion)
## Example
```js
var expand = require('brace-expansion');
expand('file-{a,b,c}.jpg')
// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']
expand('-v{,,}')
// => ['-v', '-v', '-v']
expand('file{0..2}.jpg')
// => ['file0.jpg', 'file1.jpg', 'file2.jpg']
expand('file-{a..c}.jpg')
// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']
expand('file{2..0}.jpg')
// => ['file2.jpg', 'file1.jpg', 'file0.jpg']
expand('file{0..4..2}.jpg')
// => ['file0.jpg', 'file2.jpg', 'file4.jpg']
expand('file-{a..e..2}.jpg')
// => ['file-a.jpg', 'file-c.jpg', 'file-e.jpg']
expand('file{00..10..5}.jpg')
// => ['file00.jpg', 'file05.jpg', 'file10.jpg']
expand('{{A..C},{a..c}}')
// => ['A', 'B', 'C', 'a', 'b', 'c']
expand('ppp{,config,oe{,conf}}')
// => ['ppp', 'pppconfig', 'pppoe', 'pppoeconf']
```
## API
```js
var expand = require('brace-expansion');
```
### var expanded = expand(str)
Return an array of all possible and valid expansions of `str`. If none are
found, `[str]` is returned.
Valid expansions are:
```js
/^(.*,)+(.+)?$/
// {a,b,...}
```
A comma separated list of options, like `{a,b}` or `{a,{b,c}}` or `{,a,}`.
```js
/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/
// {x..y[..incr]}
```
A numeric sequence from `x` to `y` inclusive, with optional increment.
If `x` or `y` start with a leading `0`, all the numbers will be padded
to have equal length. Negative numbers and backwards iteration work too.
```js
/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/
// {x..y[..incr]}
```
An alphabetic sequence from `x` to `y` inclusive, with optional increment.
`x` and `y` must be exactly one character, and if given, `incr` must be a
number.
For compatibility reasons, the string `${` is not eligible for brace expansion.
## Installation
With [npm](https://npmjs.org) do:
```bash
npm install brace-expansion
```
## Contributors
- [Julian Gruber](https://github.com/juliangruber)
- [Isaac Z. Schlueter](https://github.com/isaacs)
## Sponsors
This module is proudly supported by my [Sponsors](https://github.com/juliangruber/sponsors)!
Do you want to support modules like this to improve their quality, stability and weigh in on new features? Then please consider donating to my [Patreon](https://www.patreon.com/juliangruber). Not sure how much of my modules you're using? Try [feross/thanks](https://github.com/feross/thanks)!
## License
(MIT)
Copyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,8 @@
export declare const EXPANSION_MAX = 100000;
export declare const EXPANSION_MAX_LENGTH = 4000000;
export type BraceExpansionOptions = {
max?: number;
maxLength?: number;
};
export declare function expand(str: string, options?: BraceExpansionOptions): string[];
//# sourceMappingURL=index.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,aAAa,SAAU,CAAA;AAYpC,eAAO,MAAM,oBAAoB,UAAY,CAAA;AAwD7C,MAAM,MAAM,qBAAqB,GAAG;IAClC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,YAkBtE"}

View file

@ -0,0 +1,263 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EXPANSION_MAX_LENGTH = exports.EXPANSION_MAX = void 0;
exports.expand = expand;
const balanced_match_1 = require("balanced-match");
const escSlash = '\0SLASH' + Math.random() + '\0';
const escOpen = '\0OPEN' + Math.random() + '\0';
const escClose = '\0CLOSE' + Math.random() + '\0';
const escComma = '\0COMMA' + Math.random() + '\0';
const escPeriod = '\0PERIOD' + Math.random() + '\0';
const escSlashPattern = new RegExp(escSlash, 'g');
const escOpenPattern = new RegExp(escOpen, 'g');
const escClosePattern = new RegExp(escClose, 'g');
const escCommaPattern = new RegExp(escComma, 'g');
const escPeriodPattern = new RegExp(escPeriod, 'g');
const slashPattern = /\\\\/g;
const openPattern = /\\{/g;
const closePattern = /\\}/g;
const commaPattern = /\\,/g;
const periodPattern = /\\\./g;
exports.EXPANSION_MAX = 100_000;
// `EXPANSION_MAX` caps the *number* of expansions, but not their length. An
// input like `'{a,b}'.repeat(1500)` stays under that count - its output is
// truncated to 100k results - while making every result ~1500 characters
// long. The result set, and the intermediate arrays built while combining
// brace sets, then grow large enough to exhaust memory and crash the process
// (CVE-2026-14257). `EXPANSION_MAX_LENGTH` bounds the total number of
// characters the accumulator may hold at any point, so memory stays flat no
// matter how many brace groups are chained. The limit sits well above any
// realistic expansion (100k results hitting `EXPANSION_MAX` measure ~1M
// characters) so legitimate input is unaffected.
exports.EXPANSION_MAX_LENGTH = 4_000_000;
function numeric(str) {
return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
}
function escapeBraces(str) {
return str
.replace(slashPattern, escSlash)
.replace(openPattern, escOpen)
.replace(closePattern, escClose)
.replace(commaPattern, escComma)
.replace(periodPattern, escPeriod);
}
function unescapeBraces(str) {
return str
.replace(escSlashPattern, '\\')
.replace(escOpenPattern, '{')
.replace(escClosePattern, '}')
.replace(escCommaPattern, ',')
.replace(escPeriodPattern, '.');
}
/**
* Basically just str.split(","), but handling cases
* where we have nested braced sections, which should be
* treated as individual members, like {a,{b,c},d}
*/
function parseCommaParts(str) {
if (!str) {
return [''];
}
const parts = [];
const m = (0, balanced_match_1.balanced)('{', '}', str);
if (!m) {
return str.split(',');
}
const { pre, body, post } = m;
const p = pre.split(',');
p[p.length - 1] += '{' + body + '}';
const postParts = parseCommaParts(post);
if (post.length) {
;
p[p.length - 1] += postParts.shift();
p.push.apply(p, postParts);
}
parts.push.apply(parts, p);
return parts;
}
function expand(str, options = {}) {
if (!str) {
return [];
}
const { max = exports.EXPANSION_MAX, maxLength = exports.EXPANSION_MAX_LENGTH } = options;
// I don't know why Bash 4.3 does this, but it does.
// Anything starting with {} will have the first two bytes preserved
// but *only* at the top level, so {},a}b will not expand to anything,
// but a{},b}c will be expanded to [a}c,abc].
// One could argue that this is a bug in Bash, but since the goal of
// this module is to match Bash's rules, we escape a leading {}
if (str.slice(0, 2) === '{}') {
str = '\\{\\}' + str.slice(2);
}
return expand_(escapeBraces(str), max, maxLength, true).map(unescapeBraces);
}
function embrace(str) {
return '{' + str + '}';
}
function isPadded(el) {
return /^-?0\d/.test(el);
}
function lte(i, y) {
return i <= y;
}
function gte(i, y) {
return i >= y;
}
// Build `{ acc[a] + pre + values[v] }` for every combination, capping the
// number of results at `max` and the total number of characters at `maxLength`.
// This is the one place output grows, so bounding it here keeps the single
// accumulator - and therefore memory - flat regardless of how many brace groups
// are combined (CVE-2026-14257).
function combine(acc, pre, values, max, maxLength, dropEmpties) {
const out = [];
let length = 0;
for (let a = 0; a < acc.length; a++) {
for (let v = 0; v < values.length; v++) {
if (out.length >= max)
return out;
const expansion = acc[a] + pre + values[v];
// Bash drops empty results at the top level. Skip them before they count
// against `max`, so `max` bounds the number of *kept* results.
if (dropEmpties && !expansion)
continue;
if (length + expansion.length > maxLength)
return out;
out.push(expansion);
length += expansion.length;
}
}
return out;
}
// The expansion values of a single numeric (`1..5`) or alphabetic (`a..e..2`)
// sequence body.
function expandSequence(body, isAlphaSequence, max) {
const n = body.split(/\.\./);
const N = [];
// A sequence body always splits into two or three parts, but the compiler
// can't know that.
/* c8 ignore start */
if (n[0] === undefined || n[1] === undefined) {
return N;
}
/* c8 ignore stop */
const x = numeric(n[0]);
const y = numeric(n[1]);
const width = Math.max(n[0].length, n[1].length);
let incr = n.length === 3 && n[2] !== undefined ?
Math.max(Math.abs(numeric(n[2])), 1)
: 1;
let test = lte;
const reverse = y < x;
if (reverse) {
incr *= -1;
test = gte;
}
const pad = n.some(isPadded);
for (let i = x; test(i, y) && N.length < max; i += incr) {
let c;
if (isAlphaSequence) {
c = String.fromCharCode(i);
if (c === '\\') {
c = '';
}
}
else {
c = String(i);
if (pad) {
const need = width - c.length;
if (need > 0) {
const z = new Array(need + 1).join('0');
if (i < 0) {
c = '-' + z + c.slice(1);
}
else {
c = z + c;
}
}
}
}
N.push(c);
}
return N;
}
function expand_(str, max, maxLength, isTop) {
// Consume the string's top-level brace groups left to right, threading a
// running set of combined prefixes (`acc`). Expanding the tail iteratively -
// rather than recursing on `m.post` once per group - keeps the native stack
// depth constant, so deeply chained input (`'{a,b}'.repeat(3000)`) can no
// longer overflow the stack, and leaves a single accumulator whose size
// `maxLength` bounds directly (CVE-2026-14257).
let acc = [''];
// Bash drops empty results, but only when the *first* top-level group is a
// comma set - a sequence like `{a..\}` may legitimately yield ''. The drop
// is on the final strings, so it is applied to whichever `combine` produces
// them (the one with no brace set left in the tail).
let dropEmpties = false;
let firstGroup = true;
for (;;) {
const m = (0, balanced_match_1.balanced)('{', '}', str);
// No brace set left: the rest of the string is literal.
if (!m) {
return combine(acc, str, [''], max, maxLength, dropEmpties);
}
// no need to expand pre, since it is guaranteed to be free of brace-sets
const pre = m.pre;
if (/\$$/.test(pre)) {
acc = combine(acc, pre + '{' + m.body + '}', [''], max, maxLength, dropEmpties && !m.post.length);
firstGroup = false;
if (!m.post.length)
break;
str = m.post;
continue;
}
const isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
const isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
const isSequence = isNumericSequence || isAlphaSequence;
const isOptions = m.body.indexOf(',') >= 0;
if (!isSequence && !isOptions) {
// {a},b}
if (m.post.match(/,(?!,).*\}/)) {
str = m.pre + '{' + m.body + escClose + m.post;
isTop = true;
continue;
}
// Nothing here expands, so the whole remaining string is literal.
return combine(acc, pre + '{' + m.body + '}' + m.post, [''], max, maxLength, dropEmpties);
}
if (firstGroup) {
dropEmpties = isTop && !isSequence;
firstGroup = false;
}
let values;
if (isSequence) {
values = expandSequence(m.body, isAlphaSequence, max);
}
else {
let n = parseCommaParts(m.body);
if (n.length === 1 && n[0] !== undefined) {
// x{{a,b}}y ==> x{a}y x{b}y
n = expand_(n[0], max, maxLength, false).map(embrace);
//XXX is this necessary? Can't seem to hit it in tests.
/* c8 ignore start */
if (n.length === 1) {
acc = combine(acc, pre + n[0], [''], max, maxLength, dropEmpties && !m.post.length);
if (!m.post.length)
break;
str = m.post;
continue;
}
/* c8 ignore stop */
}
values = [];
for (let j = 0; j < n.length; j++) {
values.push.apply(values, expand_(n[j], max, maxLength, false));
}
}
acc = combine(acc, pre, values, max, maxLength, dropEmpties && !m.post.length);
if (!m.post.length)
break;
str = m.post;
}
return acc;
}
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,3 @@
{
"type": "commonjs"
}

View file

@ -0,0 +1,8 @@
export declare const EXPANSION_MAX = 100000;
export declare const EXPANSION_MAX_LENGTH = 4000000;
export type BraceExpansionOptions = {
max?: number;
maxLength?: number;
};
export declare function expand(str: string, options?: BraceExpansionOptions): string[];
//# sourceMappingURL=index.d.ts.map

View file

@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,aAAa,SAAU,CAAA;AAYpC,eAAO,MAAM,oBAAoB,UAAY,CAAA;AAwD7C,MAAM,MAAM,qBAAqB,GAAG;IAClC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,YAkBtE"}

View file

@ -0,0 +1,259 @@
import { balanced } from 'balanced-match';
const escSlash = '\0SLASH' + Math.random() + '\0';
const escOpen = '\0OPEN' + Math.random() + '\0';
const escClose = '\0CLOSE' + Math.random() + '\0';
const escComma = '\0COMMA' + Math.random() + '\0';
const escPeriod = '\0PERIOD' + Math.random() + '\0';
const escSlashPattern = new RegExp(escSlash, 'g');
const escOpenPattern = new RegExp(escOpen, 'g');
const escClosePattern = new RegExp(escClose, 'g');
const escCommaPattern = new RegExp(escComma, 'g');
const escPeriodPattern = new RegExp(escPeriod, 'g');
const slashPattern = /\\\\/g;
const openPattern = /\\{/g;
const closePattern = /\\}/g;
const commaPattern = /\\,/g;
const periodPattern = /\\\./g;
export const EXPANSION_MAX = 100_000;
// `EXPANSION_MAX` caps the *number* of expansions, but not their length. An
// input like `'{a,b}'.repeat(1500)` stays under that count - its output is
// truncated to 100k results - while making every result ~1500 characters
// long. The result set, and the intermediate arrays built while combining
// brace sets, then grow large enough to exhaust memory and crash the process
// (CVE-2026-14257). `EXPANSION_MAX_LENGTH` bounds the total number of
// characters the accumulator may hold at any point, so memory stays flat no
// matter how many brace groups are chained. The limit sits well above any
// realistic expansion (100k results hitting `EXPANSION_MAX` measure ~1M
// characters) so legitimate input is unaffected.
export const EXPANSION_MAX_LENGTH = 4_000_000;
function numeric(str) {
return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
}
function escapeBraces(str) {
return str
.replace(slashPattern, escSlash)
.replace(openPattern, escOpen)
.replace(closePattern, escClose)
.replace(commaPattern, escComma)
.replace(periodPattern, escPeriod);
}
function unescapeBraces(str) {
return str
.replace(escSlashPattern, '\\')
.replace(escOpenPattern, '{')
.replace(escClosePattern, '}')
.replace(escCommaPattern, ',')
.replace(escPeriodPattern, '.');
}
/**
* Basically just str.split(","), but handling cases
* where we have nested braced sections, which should be
* treated as individual members, like {a,{b,c},d}
*/
function parseCommaParts(str) {
if (!str) {
return [''];
}
const parts = [];
const m = balanced('{', '}', str);
if (!m) {
return str.split(',');
}
const { pre, body, post } = m;
const p = pre.split(',');
p[p.length - 1] += '{' + body + '}';
const postParts = parseCommaParts(post);
if (post.length) {
;
p[p.length - 1] += postParts.shift();
p.push.apply(p, postParts);
}
parts.push.apply(parts, p);
return parts;
}
export function expand(str, options = {}) {
if (!str) {
return [];
}
const { max = EXPANSION_MAX, maxLength = EXPANSION_MAX_LENGTH } = options;
// I don't know why Bash 4.3 does this, but it does.
// Anything starting with {} will have the first two bytes preserved
// but *only* at the top level, so {},a}b will not expand to anything,
// but a{},b}c will be expanded to [a}c,abc].
// One could argue that this is a bug in Bash, but since the goal of
// this module is to match Bash's rules, we escape a leading {}
if (str.slice(0, 2) === '{}') {
str = '\\{\\}' + str.slice(2);
}
return expand_(escapeBraces(str), max, maxLength, true).map(unescapeBraces);
}
function embrace(str) {
return '{' + str + '}';
}
function isPadded(el) {
return /^-?0\d/.test(el);
}
function lte(i, y) {
return i <= y;
}
function gte(i, y) {
return i >= y;
}
// Build `{ acc[a] + pre + values[v] }` for every combination, capping the
// number of results at `max` and the total number of characters at `maxLength`.
// This is the one place output grows, so bounding it here keeps the single
// accumulator - and therefore memory - flat regardless of how many brace groups
// are combined (CVE-2026-14257).
function combine(acc, pre, values, max, maxLength, dropEmpties) {
const out = [];
let length = 0;
for (let a = 0; a < acc.length; a++) {
for (let v = 0; v < values.length; v++) {
if (out.length >= max)
return out;
const expansion = acc[a] + pre + values[v];
// Bash drops empty results at the top level. Skip them before they count
// against `max`, so `max` bounds the number of *kept* results.
if (dropEmpties && !expansion)
continue;
if (length + expansion.length > maxLength)
return out;
out.push(expansion);
length += expansion.length;
}
}
return out;
}
// The expansion values of a single numeric (`1..5`) or alphabetic (`a..e..2`)
// sequence body.
function expandSequence(body, isAlphaSequence, max) {
const n = body.split(/\.\./);
const N = [];
// A sequence body always splits into two or three parts, but the compiler
// can't know that.
/* c8 ignore start */
if (n[0] === undefined || n[1] === undefined) {
return N;
}
/* c8 ignore stop */
const x = numeric(n[0]);
const y = numeric(n[1]);
const width = Math.max(n[0].length, n[1].length);
let incr = n.length === 3 && n[2] !== undefined ?
Math.max(Math.abs(numeric(n[2])), 1)
: 1;
let test = lte;
const reverse = y < x;
if (reverse) {
incr *= -1;
test = gte;
}
const pad = n.some(isPadded);
for (let i = x; test(i, y) && N.length < max; i += incr) {
let c;
if (isAlphaSequence) {
c = String.fromCharCode(i);
if (c === '\\') {
c = '';
}
}
else {
c = String(i);
if (pad) {
const need = width - c.length;
if (need > 0) {
const z = new Array(need + 1).join('0');
if (i < 0) {
c = '-' + z + c.slice(1);
}
else {
c = z + c;
}
}
}
}
N.push(c);
}
return N;
}
function expand_(str, max, maxLength, isTop) {
// Consume the string's top-level brace groups left to right, threading a
// running set of combined prefixes (`acc`). Expanding the tail iteratively -
// rather than recursing on `m.post` once per group - keeps the native stack
// depth constant, so deeply chained input (`'{a,b}'.repeat(3000)`) can no
// longer overflow the stack, and leaves a single accumulator whose size
// `maxLength` bounds directly (CVE-2026-14257).
let acc = [''];
// Bash drops empty results, but only when the *first* top-level group is a
// comma set - a sequence like `{a..\}` may legitimately yield ''. The drop
// is on the final strings, so it is applied to whichever `combine` produces
// them (the one with no brace set left in the tail).
let dropEmpties = false;
let firstGroup = true;
for (;;) {
const m = balanced('{', '}', str);
// No brace set left: the rest of the string is literal.
if (!m) {
return combine(acc, str, [''], max, maxLength, dropEmpties);
}
// no need to expand pre, since it is guaranteed to be free of brace-sets
const pre = m.pre;
if (/\$$/.test(pre)) {
acc = combine(acc, pre + '{' + m.body + '}', [''], max, maxLength, dropEmpties && !m.post.length);
firstGroup = false;
if (!m.post.length)
break;
str = m.post;
continue;
}
const isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
const isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
const isSequence = isNumericSequence || isAlphaSequence;
const isOptions = m.body.indexOf(',') >= 0;
if (!isSequence && !isOptions) {
// {a},b}
if (m.post.match(/,(?!,).*\}/)) {
str = m.pre + '{' + m.body + escClose + m.post;
isTop = true;
continue;
}
// Nothing here expands, so the whole remaining string is literal.
return combine(acc, pre + '{' + m.body + '}' + m.post, [''], max, maxLength, dropEmpties);
}
if (firstGroup) {
dropEmpties = isTop && !isSequence;
firstGroup = false;
}
let values;
if (isSequence) {
values = expandSequence(m.body, isAlphaSequence, max);
}
else {
let n = parseCommaParts(m.body);
if (n.length === 1 && n[0] !== undefined) {
// x{{a,b}}y ==> x{a}y x{b}y
n = expand_(n[0], max, maxLength, false).map(embrace);
//XXX is this necessary? Can't seem to hit it in tests.
/* c8 ignore start */
if (n.length === 1) {
acc = combine(acc, pre + n[0], [''], max, maxLength, dropEmpties && !m.post.length);
if (!m.post.length)
break;
str = m.post;
continue;
}
/* c8 ignore stop */
}
values = [];
for (let j = 0; j < n.length; j++) {
values.push.apply(values, expand_(n[j], max, maxLength, false));
}
}
acc = combine(acc, pre, values, max, maxLength, dropEmpties && !m.post.length);
if (!m.post.length)
break;
str = m.post;
}
return acc;
}
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,3 @@
{
"type": "module"
}

View file

@ -0,0 +1,209 @@
var concatMap = require('concat-map');
var balanced = require('balanced-match');
module.exports = expandTop;
var escSlash = '\0SLASH'+Math.random()+'\0';
var escOpen = '\0OPEN'+Math.random()+'\0';
var escClose = '\0CLOSE'+Math.random()+'\0';
var escComma = '\0COMMA'+Math.random()+'\0';
var escPeriod = '\0PERIOD'+Math.random()+'\0';
function numeric(str) {
return parseInt(str, 10) == str
? parseInt(str, 10)
: str.charCodeAt(0);
}
function escapeBraces(str) {
return str.split('\\\\').join(escSlash)
.split('\\{').join(escOpen)
.split('\\}').join(escClose)
.split('\\,').join(escComma)
.split('\\.').join(escPeriod);
}
function unescapeBraces(str) {
return str.split(escSlash).join('\\')
.split(escOpen).join('{')
.split(escClose).join('}')
.split(escComma).join(',')
.split(escPeriod).join('.');
}
// Basically just str.split(","), but handling cases
// where we have nested braced sections, which should be
// treated as individual members, like {a,{b,c},d}
function parseCommaParts(str) {
if (!str)
return [''];
var parts = [];
var m = balanced('{', '}', str);
if (!m)
return str.split(',');
var pre = m.pre;
var body = m.body;
var post = m.post;
var p = pre.split(',');
p[p.length-1] += '{' + body + '}';
var postParts = parseCommaParts(post);
if (post.length) {
p[p.length-1] += postParts.shift();
p.push.apply(p, postParts);
}
parts.push.apply(parts, p);
return parts;
}
function expandTop(str, options) {
if (!str)
return [];
options = options || {};
var max = options.max == null ? Infinity : options.max;
// I don't know why Bash 4.3 does this, but it does.
// Anything starting with {} will have the first two bytes preserved
// but *only* at the top level, so {},a}b will not expand to anything,
// but a{},b}c will be expanded to [a}c,abc].
// One could argue that this is a bug in Bash, but since the goal of
// this module is to match Bash's rules, we escape a leading {}
if (str.substr(0, 2) === '{}') {
str = '\\{\\}' + str.substr(2);
}
return expand(escapeBraces(str), max, true).map(unescapeBraces);
}
function identity(e) {
return e;
}
function embrace(str) {
return '{' + str + '}';
}
function isPadded(el) {
return /^-?0\d/.test(el);
}
function lte(i, y) {
return i <= y;
}
function gte(i, y) {
return i >= y;
}
function expand(str, max, isTop) {
var expansions = [];
// The `{a},b}` rewrite below restarts expansion on a rewritten string with
// the same `max` and `isTop = true`. Loop instead of recursing so a long run
// of non-expanding `{}` groups can't exhaust the call stack.
for (;;) {
var m = balanced('{', '}', str);
if (!m || /\$$/.test(m.pre)) return [str];
var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
var isSequence = isNumericSequence || isAlphaSequence;
var isOptions = m.body.indexOf(',') >= 0;
if (!isSequence && !isOptions) {
// {a},b}
if (m.post.match(/,(?!,).*\}/)) {
str = m.pre + '{' + m.body + escClose + m.post;
isTop = true
continue
}
return [str];
}
var n;
if (isSequence) {
n = m.body.split(/\.\./);
} else {
n = parseCommaParts(m.body);
if (n.length === 1) {
// x{{a,b}}y ==> x{a}y x{b}y
n = expand(n[0], max, false).map(embrace);
if (n.length === 1) {
var post = m.post.length
? expand(m.post, max, false)
: [''];
return post.map(function(p) {
return m.pre + n[0] + p;
});
}
}
}
// at this point, n is the parts, and we know it's not a comma set
// with a single entry.
// no need to expand pre, since it is guaranteed to be free of brace-sets
var pre = m.pre;
var post = m.post.length
? expand(m.post, max, false)
: [''];
var N;
if (isSequence) {
var x = numeric(n[0]);
var y = numeric(n[1]);
var width = Math.max(n[0].length, n[1].length)
var incr = n.length == 3
? Math.max(Math.abs(numeric(n[2])), 1)
: 1;
var test = lte;
var reverse = y < x;
if (reverse) {
incr *= -1;
test = gte;
}
var pad = n.some(isPadded);
N = [];
for (var i = x; test(i, y) && N.length < max; i += incr) {
var c;
if (isAlphaSequence) {
c = String.fromCharCode(i);
if (c === '\\')
c = '';
} else {
c = String(i);
if (pad) {
var need = width - c.length;
if (need > 0) {
var z = new Array(need + 1).join('0');
if (i < 0)
c = '-' + z + c.slice(1);
else
c = z + c;
}
}
}
N.push(c);
}
} else {
N = concatMap(n, function(el) { return expand(el, max, false) });
}
for (var j = 0; j < N.length; j++) {
for (var k = 0; k < post.length && expansions.length < max; k++) {
var expansion = pre + N[j] + post[k];
if (!isTop || isSequence || expansion)
expansions.push(expansion);
}
}
return expansions;
}
}

View file

@ -0,0 +1,50 @@
{
"name": "brace-expansion",
"description": "Brace expansion as known from sh/bash",
"version": "1.1.16",
"repository": {
"type": "git",
"url": "git://github.com/juliangruber/brace-expansion.git"
},
"homepage": "https://github.com/juliangruber/brace-expansion",
"main": "index.js",
"scripts": {
"test": "tape test/*.js",
"gentest": "bash test/generate.sh",
"bench": "matcha test/perf/bench.js"
},
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
},
"devDependencies": {
"matcha": "^0.7.0",
"tape": "^4.6.0"
},
"keywords": [],
"author": {
"name": "Julian Gruber",
"email": "mail@juliangruber.com",
"url": "http://juliangruber.com"
},
"license": "MIT",
"testling": {
"files": "test/*.js",
"browsers": [
"ie/8..latest",
"firefox/20..latest",
"firefox/nightly",
"chrome/25..latest",
"chrome/canary",
"opera/12..latest",
"opera/next",
"safari/5.1..latest",
"ipad/6.0..latest",
"iphone/6.0..latest",
"android-browser/4.2..latest"
]
},
"publishConfig": {
"tag": "1.x"
}
}

View file

@ -1,261 +0,0 @@
2.9.0 / 2015-10-13
==================
* Add option `isDefault` to set default subcommand #415 @Qix-
* Add callback to allow filtering or post-processing of help text #434 @djulien
* Fix `undefined` text in help information close #414 #416 @zhiyelee
2.8.1 / 2015-04-22
==================
* Back out `support multiline description` Close #396 #397
2.8.0 / 2015-04-07
==================
* Add `process.execArg` support, execution args like `--harmony` will be passed to sub-commands #387 @DigitalIO @zhiyelee
* Fix bug in Git-style sub-commands #372 @zhiyelee
* Allow commands to be hidden from help #383 @tonylukasavage
* When git-style sub-commands are in use, yet none are called, display help #382 @claylo
* Add ability to specify arguments syntax for top-level command #258 @rrthomas
* Support multiline descriptions #208 @zxqfox
2.7.1 / 2015-03-11
==================
* Revert #347 (fix collisions when option and first arg have same name) which causes a bug in #367.
2.7.0 / 2015-03-09
==================
* Fix git-style bug when installed globally. Close #335 #349 @zhiyelee
* Fix collisions when option and first arg have same name. Close #346 #347 @tonylukasavage
* Add support for camelCase on `opts()`. Close #353 @nkzawa
* Add node.js 0.12 and io.js to travis.yml
* Allow RegEx options. #337 @palanik
* Fixes exit code when sub-command failing. Close #260 #332 @pirelenito
* git-style `bin` files in $PATH make sense. Close #196 #327 @zhiyelee
2.6.0 / 2014-12-30
==================
* added `Command#allowUnknownOption` method. Close #138 #318 @doozr @zhiyelee
* Add application description to the help msg. Close #112 @dalssoft
2.5.1 / 2014-12-15
==================
* fixed two bugs incurred by variadic arguments. Close #291 @Quentin01 #302 @zhiyelee
2.5.0 / 2014-10-24
==================
* add support for variadic arguments. Closes #277 @whitlockjc
2.4.0 / 2014-10-17
==================
* fixed a bug on executing the coercion function of subcommands option. Closes #270
* added `Command.prototype.name` to retrieve command name. Closes #264 #266 @tonylukasavage
* added `Command.prototype.opts` to retrieve all the options as a simple object of key-value pairs. Closes #262 @tonylukasavage
* fixed a bug on subcommand name. Closes #248 @jonathandelgado
* fixed function normalize doesnt honor option terminator. Closes #216 @abbr
2.3.0 / 2014-07-16
==================
* add command alias'. Closes PR #210
* fix: Typos. Closes #99
* fix: Unused fs module. Closes #217
2.2.0 / 2014-03-29
==================
* add passing of previous option value
* fix: support subcommands on windows. Closes #142
* Now the defaultValue passed as the second argument of the coercion function.
2.1.0 / 2013-11-21
==================
* add: allow cflag style option params, unit test, fixes #174
2.0.0 / 2013-07-18
==================
* remove input methods (.prompt, .confirm, etc)
1.3.2 / 2013-07-18
==================
* add support for sub-commands to co-exist with the original command
1.3.1 / 2013-07-18
==================
* add quick .runningCommand hack so you can opt-out of other logic when running a sub command
1.3.0 / 2013-07-09
==================
* add EACCES error handling
* fix sub-command --help
1.2.0 / 2013-06-13
==================
* allow "-" hyphen as an option argument
* support for RegExp coercion
1.1.1 / 2012-11-20
==================
* add more sub-command padding
* fix .usage() when args are present. Closes #106
1.1.0 / 2012-11-16
==================
* add git-style executable subcommand support. Closes #94
1.0.5 / 2012-10-09
==================
* fix `--name` clobbering. Closes #92
* fix examples/help. Closes #89
1.0.4 / 2012-09-03
==================
* add `outputHelp()` method.
1.0.3 / 2012-08-30
==================
* remove invalid .version() defaulting
1.0.2 / 2012-08-24
==================
* add `--foo=bar` support [arv]
* fix password on node 0.8.8. Make backward compatible with 0.6 [focusaurus]
1.0.1 / 2012-08-03
==================
* fix issue #56
* fix tty.setRawMode(mode) was moved to tty.ReadStream#setRawMode() (i.e. process.stdin.setRawMode())
1.0.0 / 2012-07-05
==================
* add support for optional option descriptions
* add defaulting of `.version()` to package.json's version
0.6.1 / 2012-06-01
==================
* Added: append (yes or no) on confirmation
* Added: allow node.js v0.7.x
0.6.0 / 2012-04-10
==================
* Added `.prompt(obj, callback)` support. Closes #49
* Added default support to .choose(). Closes #41
* Fixed the choice example
0.5.1 / 2011-12-20
==================
* Fixed `password()` for recent nodes. Closes #36
0.5.0 / 2011-12-04
==================
* Added sub-command option support [itay]
0.4.3 / 2011-12-04
==================
* Fixed custom help ordering. Closes #32
0.4.2 / 2011-11-24
==================
* Added travis support
* Fixed: line-buffered input automatically trimmed. Closes #31
0.4.1 / 2011-11-18
==================
* Removed listening for "close" on --help
0.4.0 / 2011-11-15
==================
* Added support for `--`. Closes #24
0.3.3 / 2011-11-14
==================
* Fixed: wait for close event when writing help info [Jerry Hamlet]
0.3.2 / 2011-11-01
==================
* Fixed long flag definitions with values [felixge]
0.3.1 / 2011-10-31
==================
* Changed `--version` short flag to `-V` from `-v`
* Changed `.version()` so it's configurable [felixge]
0.3.0 / 2011-10-31
==================
* Added support for long flags only. Closes #18
0.2.1 / 2011-10-24
==================
* "node": ">= 0.4.x < 0.7.0". Closes #20
0.2.0 / 2011-09-26
==================
* Allow for defaults that are not just boolean. Default peassignment only occurs for --no-*, optional, and required arguments. [Jim Isaacs]
0.1.0 / 2011-08-24
==================
* Added support for custom `--help` output
0.0.5 / 2011-08-18
==================
* Changed: when the user enters nothing prompt for password again
* Fixed issue with passwords beginning with numbers [NuckChorris]
0.0.4 / 2011-08-15
==================
* Fixed `Commander#args`
0.0.3 / 2011-08-15
==================
* Added default option value support
0.0.2 / 2011-08-15
==================
* Added mask support to `Command#password(str[, mask], fn)`
* Added `Command#password(str, fn)`
0.0.1 / 2010-01-03
==================
* Initial release

View file

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

View file

@ -1,351 +0,0 @@
# Commander.js
[![Build Status](https://api.travis-ci.org/tj/commander.js.svg)](http://travis-ci.org/tj/commander.js)
[![NPM Version](http://img.shields.io/npm/v/commander.svg?style=flat)](https://www.npmjs.org/package/commander)
[![NPM Downloads](https://img.shields.io/npm/dm/commander.svg?style=flat)](https://www.npmjs.org/package/commander)
[![Join the chat at https://gitter.im/tj/commander.js](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/tj/commander.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/tj/commander).
[API documentation](http://tj.github.com/commander.js/)
## Installation
$ npm install commander
## Option parsing
Options with commander are defined with the `.option()` method, also serving as documentation for the options. The example below parses args and options from `process.argv`, leaving remaining args as the `program.args` array which were not consumed by options.
```js
#!/usr/bin/env node
/**
* Module dependencies.
*/
var program = require('commander');
program
.version('0.0.1')
.option('-p, --peppers', 'Add peppers')
.option('-P, --pineapple', 'Add pineapple')
.option('-b, --bbq-sauce', 'Add bbq sauce')
.option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble')
.parse(process.argv);
console.log('you ordered a pizza with:');
if (program.peppers) console.log(' - peppers');
if (program.pineapple) console.log(' - pineapple');
if (program.bbqSauce) console.log(' - bbq');
console.log(' - %s cheese', program.cheese);
```
Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as "--template-engine" are camel-cased, becoming `program.templateEngine` etc.
## Coercion
```js
function range(val) {
return val.split('..').map(Number);
}
function list(val) {
return val.split(',');
}
function collect(val, memo) {
memo.push(val);
return memo;
}
function increaseVerbosity(v, total) {
return total + 1;
}
program
.version('0.0.1')
.usage('[options] <file ...>')
.option('-i, --integer <n>', 'An integer argument', parseInt)
.option('-f, --float <n>', 'A float argument', parseFloat)
.option('-r, --range <a>..<b>', 'A range', range)
.option('-l, --list <items>', 'A list', list)
.option('-o, --optional [value]', 'An optional value')
.option('-c, --collect [value]', 'A repeatable value', collect, [])
.option('-v, --verbose', 'A value that can be increased', increaseVerbosity, 0)
.parse(process.argv);
console.log(' int: %j', program.integer);
console.log(' float: %j', program.float);
console.log(' optional: %j', program.optional);
program.range = program.range || [];
console.log(' range: %j..%j', program.range[0], program.range[1]);
console.log(' list: %j', program.list);
console.log(' collect: %j', program.collect);
console.log(' verbosity: %j', program.verbose);
console.log(' args: %j', program.args);
```
## Regular Expression
```js
program
.version('0.0.1')
.option('-s --size <size>', 'Pizza size', /^(large|medium|small)$/i, 'medium')
.option('-d --drink [drink]', 'Drink', /^(coke|pepsi|izze)$/i)
.parse(process.argv);
console.log(' size: %j', program.size);
console.log(' drink: %j', program.drink);
```
## Variadic arguments
The last argument of a command can be variadic, and only the last argument. To make an argument variadic you have to
append `...` to the argument name. Here is an example:
```js
#!/usr/bin/env node
/**
* Module dependencies.
*/
var program = require('commander');
program
.version('0.0.1')
.command('rmdir <dir> [otherDirs...]')
.action(function (dir, otherDirs) {
console.log('rmdir %s', dir);
if (otherDirs) {
otherDirs.forEach(function (oDir) {
console.log('rmdir %s', oDir);
});
}
});
program.parse(process.argv);
```
An `Array` is used for the value of a variadic argument. This applies to `program.args` as well as the argument passed
to your action as demonstrated above.
## Specify the argument syntax
```js
#!/usr/bin/env node
var program = require('../');
program
.version('0.0.1')
.arguments('<cmd> [env]')
.action(function (cmd, env) {
cmdValue = cmd;
envValue = env;
});
program.parse(process.argv);
if (typeof cmdValue === 'undefined') {
console.error('no command given!');
process.exit(1);
}
console.log('command:', cmdValue);
console.log('environment:', envValue || "no environment given");
```
## Git-style sub-commands
```js
// file: ./examples/pm
var program = require('..');
program
.version('0.0.1')
.command('install [name]', 'install one or more packages')
.command('search [query]', 'search with optional query')
.command('list', 'list packages installed', {isDefault: true})
.parse(process.argv);
```
When `.command()` is invoked with a description argument, no `.action(callback)` should be called to handle sub-commands, otherwise there will be an error. This tells commander that you're going to use separate executables for sub-commands, much like `git(1)` and other popular tools.
The commander will try to search the executables in the directory of the entry script (like `./examples/pm`) with the name `program-command`, like `pm-install`, `pm-search`.
Options can be passed with the call to `.command()`. Specifying `true` for `opts.noHelp` will remove the option from the generated help output. Specifying `true` for `opts.isDefault` will run the subcommand if no other subcommand is specified.
If the program is designed to be installed globally, make sure the executables have proper modes, like `755`.
### `--harmony`
You can enable `--harmony` option in two ways:
* Use `#! /usr/bin/env node --harmony` in the sub-commands scripts. Note some os version dont support this pattern.
* Use the `--harmony` option when call the command, like `node --harmony examples/pm publish`. The `--harmony` option will be preserved when spawning sub-command process.
## Automated --help
The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free:
```
$ ./examples/pizza --help
Usage: pizza [options]
An application for pizzas ordering
Options:
-h, --help output usage information
-V, --version output the version number
-p, --peppers Add peppers
-P, --pineapple Add pineapple
-b, --bbq Add bbq sauce
-c, --cheese <type> Add the specified type of cheese [marble]
-C, --no-cheese You do not want any cheese
```
## Custom help
You can display arbitrary `-h, --help` information
by listening for "--help". Commander will automatically
exit once you are done so that the remainder of your program
does not execute causing undesired behaviours, for example
in the following executable "stuff" will not output when
`--help` is used.
```js
#!/usr/bin/env node
/**
* Module dependencies.
*/
var program = require('commander');
program
.version('0.0.1')
.option('-f, --foo', 'enable some foo')
.option('-b, --bar', 'enable some bar')
.option('-B, --baz', 'enable some baz');
// must be before .parse() since
// node's emit() is immediate
program.on('--help', function(){
console.log(' Examples:');
console.log('');
console.log(' $ custom-help --help');
console.log(' $ custom-help -h');
console.log('');
});
program.parse(process.argv);
console.log('stuff');
```
Yields the following help output when `node script-name.js -h` or `node script-name.js --help` are run:
```
Usage: custom-help [options]
Options:
-h, --help output usage information
-V, --version output the version number
-f, --foo enable some foo
-b, --bar enable some bar
-B, --baz enable some baz
Examples:
$ custom-help --help
$ custom-help -h
```
## .outputHelp(cb)
Output help information without exiting.
Optional callback cb allows post-processing of help text before it is displayed.
If you want to display help by default (e.g. if no command was provided), you can use something like:
```js
var program = require('commander');
var colors = require('colors');
program
.version('0.0.1')
.command('getstream [url]', 'get stream URL')
.parse(process.argv);
if (!process.argv.slice(2).length) {
program.outputHelp(make_red);
}
function make_red(txt) {
return colors.red(txt); //display the help text in red on the console
}
```
## .help(cb)
Output help information and exit immediately.
Optional callback cb allows post-processing of help text before it is displayed.
## Examples
```js
var program = require('commander');
program
.version('0.0.1')
.option('-C, --chdir <path>', 'change the working directory')
.option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
.option('-T, --no-tests', 'ignore test hook')
program
.command('setup [env]')
.description('run setup commands for all envs')
.option("-s, --setup_mode [mode]", "Which setup mode to use")
.action(function(env, options){
var mode = options.setup_mode || "normal";
env = env || 'all';
console.log('setup for %s env(s) with %s mode', env, mode);
});
program
.command('exec <cmd>')
.alias('ex')
.description('execute the given remote cmd')
.option("-e, --exec_mode <mode>", "Which exec mode to use")
.action(function(cmd, options){
console.log('exec "%s" using %s mode', cmd, options.exec_mode);
}).on('--help', function() {
console.log(' Examples:');
console.log();
console.log(' $ deploy exec sequential');
console.log(' $ deploy exec async');
console.log();
});
program
.command('*')
.action(function(env){
console.log('deploying "%s"', env);
});
program.parse(process.argv);
```
More Demos can be found in the [examples](https://github.com/tj/commander.js/tree/master/examples) directory.
## License
MIT

File diff suppressed because it is too large Load diff

View file

@ -1,33 +0,0 @@
{
"name": "commander",
"version": "2.9.0",
"description": "the complete solution for node.js command-line programs",
"keywords": [
"command",
"option",
"parser"
],
"author": "TJ Holowaychuk <tj@vision-media.ca>",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/tj/commander.js.git"
},
"devDependencies": {
"should": ">= 0.0.1",
"sinon": ">=1.17.1"
},
"scripts": {
"test": "make test"
},
"main": "index",
"engines": {
"node": ">= 0.6.x"
},
"files": [
"index.js"
],
"dependencies": {
"graceful-readlink": ">= 1.0.0"
}
}

View file

@ -2,7 +2,7 @@
A minimal matching utility.
[![Build Status](https://secure.travis-ci.org/isaacs/minimatch.svg)](http://travis-ci.org/isaacs/minimatch)
[![Build Status](https://travis-ci.org/isaacs/minimatch.svg?branch=master)](http://travis-ci.org/isaacs/minimatch)
This is the matching library used internally by npm.
@ -10,6 +10,43 @@ This is the matching library used internally by npm.
It works by converting glob expressions into JavaScript `RegExp`
objects.
## Important Security Consideration!
> [!WARNING]
> This library uses JavaScript regular expressions. Please read
> the following warning carefully, and be thoughtful about what
> you provide to this library in production systems.
_Any_ library in JavaScript that deals with matching string
patterns using regular expressions will be subject to
[ReDoS](https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS)
if the pattern is generated using untrusted input.
Efforts have been made to mitigate risk as much as is feasible in
such a library, providing maximum recursion depths and so forth,
but these measures can only ultimately protect against accidents,
not malice. A dedicated attacker can _always_ find patterns that
cannot be defended against by a bash-compatible glob pattern
matching system that uses JavaScript regular expressions.
To be extremely clear:
> [!WARNING]
> **If you create a system where you take user input, and use
> that input as the source of a Regular Expression pattern, in
> this or any extant glob matcher in JavaScript, you will be
> pwned.**
A future version of this library _may_ use a different matching
algorithm which does not exhibit backtracking problems. If and
when that happens, it will likely be a sweeping change, and those
improvements will **not** be backported to legacy versions.
In the near term, it is not reasonable to continue to play
whack-a-mole with security advisories, and so any future ReDoS
reports will be considered "working as intended", and resolved
entirely by this warning.
## Usage
```javascript
@ -171,6 +208,27 @@ Suppress the behavior of treating a leading `!` character as negation.
Returns from negate expressions the same as if they were not negated.
(Ie, true on a hit, false on a miss.)
### partial
Compare a partial path to a pattern. As long as the parts of the path that
are present are not contradicted by the pattern, it will be treated as a
match. This is useful in applications where you're walking through a
folder structure, and don't yet have the full path, but want to ensure that
you do not walk down paths that can never be a match.
For example,
```js
minimatch('/a/b', '/a/*/c/d', { partial: true }) // true, might be /a/b/c/d
minimatch('/a/b', '/**/d', { partial: true }) // true, might be /a/b/.../d
minimatch('/x/y/z', '/a/**/z', { partial: true }) // false, because x !== a
```
### allowWindowsEscape
Windows path separator `\` is by default converted to `/`, which
prohibits the usage of `\` as a escape character. This flag skips that
behavior and allows using the escape character.
## Comparisons to other fnmatch/glob implementations

View file

@ -1,10 +1,10 @@
module.exports = minimatch
minimatch.Minimatch = Minimatch
var path = { sep: '/' }
try {
path = require('path')
} catch (er) {}
var path = (function () { try { return require('path') } catch (e) {}}()) || {
sep: '/'
}
minimatch.sep = path.sep
var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
var expand = require('brace-expansion')
@ -56,43 +56,64 @@ function filter (pattern, options) {
}
function ext (a, b) {
a = a || {}
b = b || {}
var t = {}
Object.keys(b).forEach(function (k) {
t[k] = b[k]
})
Object.keys(a).forEach(function (k) {
t[k] = a[k]
})
Object.keys(b).forEach(function (k) {
t[k] = b[k]
})
return t
}
minimatch.defaults = function (def) {
if (!def || !Object.keys(def).length) return minimatch
if (!def || typeof def !== 'object' || !Object.keys(def).length) {
return minimatch
}
var orig = minimatch
var m = function minimatch (p, pattern, options) {
return orig.minimatch(p, pattern, ext(def, options))
return orig(p, pattern, ext(def, options))
}
m.Minimatch = function Minimatch (pattern, options) {
return new orig.Minimatch(pattern, ext(def, options))
}
m.Minimatch.defaults = function defaults (options) {
return orig.defaults(ext(def, options)).Minimatch
}
m.filter = function filter (pattern, options) {
return orig.filter(pattern, ext(def, options))
}
m.defaults = function defaults (options) {
return orig.defaults(ext(def, options))
}
m.makeRe = function makeRe (pattern, options) {
return orig.makeRe(pattern, ext(def, options))
}
m.braceExpand = function braceExpand (pattern, options) {
return orig.braceExpand(pattern, ext(def, options))
}
m.match = function (list, pattern, options) {
return orig.match(list, pattern, ext(def, options))
}
return m
}
Minimatch.defaults = function (def) {
if (!def || !Object.keys(def).length) return Minimatch
return minimatch.defaults(def).Minimatch
}
function minimatch (p, pattern, options) {
if (typeof pattern !== 'string') {
throw new TypeError('glob pattern string required')
}
assertValidPattern(pattern)
if (!options) options = {}
@ -101,9 +122,6 @@ function minimatch (p, pattern, options) {
return false
}
// "" only matches ""
if (pattern.trim() === '') return p === ''
return new Minimatch(pattern, options).match(p)
}
@ -112,25 +130,27 @@ function Minimatch (pattern, options) {
return new Minimatch(pattern, options)
}
if (typeof pattern !== 'string') {
throw new TypeError('glob pattern string required')
}
assertValidPattern(pattern)
if (!options) options = {}
pattern = pattern.trim()
// windows support: need to use /, not \
if (path.sep !== '/') {
if (!options.allowWindowsEscape && path.sep !== '/') {
pattern = pattern.split(path.sep).join('/')
}
this.options = options
this.maxGlobstarRecursion = options.maxGlobstarRecursion !== undefined
? options.maxGlobstarRecursion : 200
this.set = []
this.pattern = pattern
this.regexp = null
this.negate = false
this.comment = false
this.empty = false
this.partial = !!options.partial
// make the set of regexps etc.
this.make()
@ -140,9 +160,6 @@ Minimatch.prototype.debug = function () {}
Minimatch.prototype.make = make
function make () {
// don't do it more than once.
if (this._made) return
var pattern = this.pattern
var options = this.options
@ -162,7 +179,7 @@ function make () {
// step 2: expand braces
var set = this.globSet = this.braceExpand()
if (options.debug) this.debug = console.error
if (options.debug) this.debug = function debug() { console.error.apply(console, arguments) }
this.debug(this.pattern, set)
@ -242,12 +259,11 @@ function braceExpand (pattern, options) {
pattern = typeof pattern === 'undefined'
? this.pattern : pattern
if (typeof pattern === 'undefined') {
throw new TypeError('undefined pattern')
}
assertValidPattern(pattern)
if (options.nobrace ||
!pattern.match(/\{.*\}/)) {
// Thanks to Yeting Li <https://github.com/yetingli> for
// improving this regexp to avoid a ReDOS vulnerability.
if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
// shortcut. no need to expand.
return [pattern]
}
@ -255,6 +271,17 @@ function braceExpand (pattern, options) {
return expand(pattern)
}
var MAX_PATTERN_LENGTH = 1024 * 64
var assertValidPattern = function (pattern) {
if (typeof pattern !== 'string') {
throw new TypeError('invalid pattern')
}
if (pattern.length > MAX_PATTERN_LENGTH) {
throw new TypeError('pattern is too long')
}
}
// parse a component of the expanded set.
// At this point, no pattern may contain "/" in it
// so we're going to return a 2d array, where each entry is the full
@ -269,14 +296,17 @@ function braceExpand (pattern, options) {
Minimatch.prototype.parse = parse
var SUBPARSE = {}
function parse (pattern, isSub) {
if (pattern.length > 1024 * 64) {
throw new TypeError('pattern is too long')
}
assertValidPattern(pattern)
var options = this.options
// shortcuts
if (!options.noglobstar && pattern === '**') return GLOBSTAR
if (pattern === '**') {
if (!options.noglobstar)
return GLOBSTAR
else
pattern = '*'
}
if (pattern === '') return ''
var re = ''
@ -332,10 +362,12 @@ function parse (pattern, isSub) {
}
switch (c) {
case '/':
/* istanbul ignore next */
case '/': {
// completely not allowed, even escaped.
// Should already be path-split by now.
return false
}
case '\\':
clearStateChar()
@ -360,6 +392,9 @@ function parse (pattern, isSub) {
continue
}
// coalesce consecutive non-globstar * characters
if (c === '*' && stateChar === '*') continue
// if we already have a stateChar, then it means
// that there was something like ** or +? in there.
// Handle the stateChar, then proceed with this one.
@ -454,25 +489,23 @@ function parse (pattern, isSub) {
// handle the case where we left a class open.
// "[z-a]" is valid, equivalent to "\[z-a\]"
if (inClass) {
// split where the last [ was, make sure we don't have
// an invalid re. if so, re-walk the contents of the
// would-be class to re-translate any characters that
// were passed through as-is
// TODO: It would probably be faster to determine this
// without a try/catch and a new RegExp, but it's tricky
// to do safely. For now, this is safe and works.
var cs = pattern.substring(classStart + 1, i)
try {
RegExp('[' + cs + ']')
} catch (er) {
// not a valid class!
var sp = this.parse(cs, SUBPARSE)
re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
hasMagic = hasMagic || sp[1]
inClass = false
continue
}
// split where the last [ was, make sure we don't have
// an invalid re. if so, re-walk the contents of the
// would-be class to re-translate any characters that
// were passed through as-is
// TODO: It would probably be faster to determine this
// without a try/catch and a new RegExp, but it's tricky
// to do safely. For now, this is safe and works.
var cs = pattern.substring(classStart + 1, i)
try {
RegExp('[' + cs + ']')
} catch (er) {
// not a valid class!
var sp = this.parse(cs, SUBPARSE)
re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
hasMagic = hasMagic || sp[1]
inClass = false
continue
}
// finish up the class.
@ -556,9 +589,7 @@ function parse (pattern, isSub) {
// something that could conceivably capture a dot
var addPatternStart = false
switch (re.charAt(0)) {
case '.':
case '[':
case '(': addPatternStart = true
case '[': case '.': case '(': addPatternStart = true
}
// Hack to work around lack of negative lookbehind in JS
@ -620,7 +651,7 @@ function parse (pattern, isSub) {
var flags = options.nocase ? 'i' : ''
try {
var regExp = new RegExp('^' + re + '$', flags)
} catch (er) {
} catch (er) /* istanbul ignore next - should be impossible */ {
// If it was an invalid regular expression, then it can't match
// anything. This trick looks for a character after the end of
// the string, which is of course impossible, except in multi-line
@ -678,7 +709,7 @@ function makeRe () {
try {
this.regexp = new RegExp(re, flags)
} catch (ex) {
} catch (ex) /* istanbul ignore next - should be impossible */ {
this.regexp = false
}
return this.regexp
@ -696,8 +727,8 @@ minimatch.match = function (list, pattern, options) {
return list
}
Minimatch.prototype.match = match
function match (f, partial) {
Minimatch.prototype.match = function match (f, partial) {
if (typeof partial === 'undefined') partial = this.partial
this.debug('match', f, this.pattern)
// short-circuit in the case of busted things.
// comments, etc.
@ -758,19 +789,163 @@ function match (f, partial) {
// out of pattern, then that's fine, as long as all
// the parts match.
Minimatch.prototype.matchOne = function (file, pattern, partial) {
var options = this.options
if (pattern.indexOf(GLOBSTAR) !== -1) {
return this._matchGlobstar(file, pattern, partial, 0, 0)
}
return this._matchOne(file, pattern, partial, 0, 0)
}
this.debug('matchOne',
{ 'this': this, file: file, pattern: pattern })
Minimatch.prototype._matchGlobstar = function (file, pattern, partial, fileIndex, patternIndex) {
var i
this.debug('matchOne', file.length, pattern.length)
// find first globstar from patternIndex
var firstgs = -1
for (i = patternIndex; i < pattern.length; i++) {
if (pattern[i] === GLOBSTAR) { firstgs = i; break }
}
for (var fi = 0,
pi = 0,
fl = file.length,
pl = pattern.length
; (fi < fl) && (pi < pl)
; fi++, pi++) {
// find last globstar
var lastgs = -1
for (i = pattern.length - 1; i >= 0; i--) {
if (pattern[i] === GLOBSTAR) { lastgs = i; break }
}
var head = pattern.slice(patternIndex, firstgs)
var body = partial ? pattern.slice(firstgs + 1) : pattern.slice(firstgs + 1, lastgs)
var tail = partial ? [] : pattern.slice(lastgs + 1)
// check the head
if (head.length) {
var fileHead = file.slice(fileIndex, fileIndex + head.length)
if (!this._matchOne(fileHead, head, partial, 0, 0)) {
return false
}
fileIndex += head.length
}
// check the tail
var fileTailMatch = 0
if (tail.length) {
if (tail.length + fileIndex > file.length) return false
var tailStart = file.length - tail.length
if (this._matchOne(file, tail, partial, tailStart, 0)) {
fileTailMatch = tail.length
} else {
// affordance for stuff like a/**/* matching a/b/
if (file[file.length - 1] !== '' ||
fileIndex + tail.length === file.length) {
return false
}
tailStart--
if (!this._matchOne(file, tail, partial, tailStart, 0)) {
return false
}
fileTailMatch = tail.length + 1
}
}
// if body is empty (single ** between head and tail)
if (!body.length) {
var sawSome = !!fileTailMatch
for (i = fileIndex; i < file.length - fileTailMatch; i++) {
var f = String(file[i])
sawSome = true
if (f === '.' || f === '..' ||
(!this.options.dot && f.charAt(0) === '.')) {
return false
}
}
return partial || sawSome
}
// split body into segments at each GLOBSTAR
var bodySegments = [[[], 0]]
var currentBody = bodySegments[0]
var nonGsParts = 0
var nonGsPartsSums = [0]
for (var bi = 0; bi < body.length; bi++) {
var b = body[bi]
if (b === GLOBSTAR) {
nonGsPartsSums.push(nonGsParts)
currentBody = [[], 0]
bodySegments.push(currentBody)
} else {
currentBody[0].push(b)
nonGsParts++
}
}
var idx = bodySegments.length - 1
var fileLength = file.length - fileTailMatch
for (var si = 0; si < bodySegments.length; si++) {
bodySegments[si][1] = fileLength -
(nonGsPartsSums[idx--] + bodySegments[si][0].length)
}
return !!this._matchGlobStarBodySections(
file, bodySegments, fileIndex, 0, partial, 0, !!fileTailMatch
)
}
// return false for "nope, not matching"
// return null for "not matching, cannot keep trying"
Minimatch.prototype._matchGlobStarBodySections = function (
file, bodySegments, fileIndex, bodyIndex, partial, globStarDepth, sawTail
) {
var bs = bodySegments[bodyIndex]
if (!bs) {
// just make sure there are no bad dots
for (var i = fileIndex; i < file.length; i++) {
sawTail = true
var f = file[i]
if (f === '.' || f === '..' ||
(!this.options.dot && f.charAt(0) === '.')) {
return false
}
}
return sawTail
}
var body = bs[0]
var after = bs[1]
while (fileIndex <= after) {
var m = this._matchOne(
file.slice(0, fileIndex + body.length),
body,
partial,
fileIndex,
0
)
// if limit exceeded, no match. intentional false negative,
// acceptable break in correctness for security.
if (m && globStarDepth < this.maxGlobstarRecursion) {
var sub = this._matchGlobStarBodySections(
file, bodySegments,
fileIndex + body.length, bodyIndex + 1,
partial, globStarDepth + 1, sawTail
)
if (sub !== false) {
return sub
}
}
var f = file[fileIndex]
if (f === '.' || f === '..' ||
(!this.options.dot && f.charAt(0) === '.')) {
return false
}
fileIndex++
}
return partial || null
}
Minimatch.prototype._matchOne = function (file, pattern, partial, fileIndex, patternIndex) {
var fi, pi, fl, pl
for (
fi = fileIndex, pi = patternIndex, fl = file.length, pl = pattern.length
; (fi < fl) && (pi < pl)
; fi++, pi++
) {
this.debug('matchOne loop')
var p = pattern[pi]
var f = file[fi]
@ -779,97 +954,15 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// should be impossible.
// some invalid regexp stuff in the set.
if (p === false) return false
if (p === GLOBSTAR) {
this.debug('GLOBSTAR', [pattern, p, f])
// "**"
// a/**/b/**/c would match the following:
// a/b/x/y/z/c
// a/x/y/z/b/c
// a/b/x/b/x/c
// a/b/c
// To do this, take the rest of the pattern after
// the **, and see if it would match the file remainder.
// If so, return success.
// If not, the ** "swallows" a segment, and try again.
// This is recursively awful.
//
// a/**/b/**/c matching a/b/x/y/z/c
// - a matches a
// - doublestar
// - matchOne(b/x/y/z/c, b/**/c)
// - b matches b
// - doublestar
// - matchOne(x/y/z/c, c) -> no
// - matchOne(y/z/c, c) -> no
// - matchOne(z/c, c) -> no
// - matchOne(c, c) yes, hit
var fr = fi
var pr = pi + 1
if (pr === pl) {
this.debug('** at the end')
// a ** at the end will just swallow the rest.
// We have found a match.
// however, it will not swallow /.x, unless
// options.dot is set.
// . and .. are *never* matched by **, for explosively
// exponential reasons.
for (; fi < fl; fi++) {
if (file[fi] === '.' || file[fi] === '..' ||
(!options.dot && file[fi].charAt(0) === '.')) return false
}
return true
}
// ok, let's see if we can swallow whatever we can.
while (fr < fl) {
var swallowee = file[fr]
this.debug('\nglobstar while', file, fr, pattern, pr, swallowee)
// XXX remove this slice. Just pass the start index.
if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
this.debug('globstar found match!', fr, fl, swallowee)
// found a match.
return true
} else {
// can't swallow "." or ".." ever.
// can only swallow ".foo" when explicitly asked.
if (swallowee === '.' || swallowee === '..' ||
(!options.dot && swallowee.charAt(0) === '.')) {
this.debug('dot detected!', file, fr, pattern, pr)
break
}
// ** swallows a segment, and continue.
this.debug('globstar swallow a segment, and continue')
fr++
}
}
// no match was found.
// However, in partial mode, we can't say this is necessarily over.
// If there's more *pattern* left, then
if (partial) {
// ran out of file
this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
if (fr === fl) return true
}
return false
}
/* istanbul ignore if */
if (p === false || p === GLOBSTAR) return false
// something other than **
// non-magic patterns just have to match exactly
// patterns with magic have been turned into regexps.
var hit
if (typeof p === 'string') {
if (options.nocase) {
hit = f.toLowerCase() === p.toLowerCase()
} else {
hit = f === p
}
hit = f === p
this.debug('string match', p, f, hit)
} else {
hit = f.match(p)
@ -879,17 +972,6 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
if (!hit) return false
}
// Note: ending in / means that we'll get a final ""
// at the end of the pattern. This can only match a
// corresponding "" at the end of the file.
// If the file ends in /, then it can only match a
// a pattern that ends in /, unless the pattern just
// doesn't have any more for it. But, a/b/ should *not*
// match "a/b/*", even though "" matches against the
// [^/]*? pattern, except in partial mode, where it might
// simply not be reached yet.
// However, a/b/ should still satisfy a/*
// now either we fell off the end of the pattern, or we're done.
if (fi === fl && pi === pl) {
// ran out of pattern and filename at the same time.
@ -900,16 +982,16 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) {
// this is ok if we're doing the match as part of
// a glob fs traversal.
return partial
} else if (pi === pl) {
} else /* istanbul ignore else */ if (pi === pl) {
// ran out of pattern, still have file left.
// this is only acceptable if we're on the very last
// empty segment of a file with a trailing slash.
// a/* should match a/b/
var emptyFileEnd = (fi === fl - 1) && (file[fi] === '')
return emptyFileEnd
return (fi === fl - 1) && (file[fi] === '')
}
// should be unreachable.
/* istanbul ignore next */
throw new Error('wtf?')
}

View file

@ -2,14 +2,17 @@
"author": "Isaac Z. Schlueter <i@izs.me> (http://blog.izs.me)",
"name": "minimatch",
"description": "a glob matcher in javascript",
"version": "3.0.4",
"version": "3.1.5",
"publishConfig": {
"tag": "legacy-v3"
},
"repository": {
"type": "git",
"url": "git://github.com/isaacs/minimatch.git"
},
"main": "minimatch.js",
"scripts": {
"test": "tap test/*.js --cov",
"test": "tap",
"preversion": "npm test",
"postversion": "npm publish",
"postpublish": "git push origin --all; git push origin --tags"
@ -21,7 +24,7 @@
"brace-expansion": "^1.1.7"
},
"devDependencies": {
"tap": "^10.3.2"
"tap": "^15.1.6"
},
"license": "ISC",
"files": [