- if (!this.preserveMultipleSlashes) {
- for (let i = 1; i < parts.length - 1; i++) {
- const p = parts[i];
- // don't squeeze out UNC patterns
- if (i === 1 && p === '' && parts[0] === '')
- continue;
- if (p === '.' || p === '') {
- didSomething = true;
- parts.splice(i, 1);
- i--;
- }
- }
- if (parts[0] === '.' &&
- parts.length === 2 &&
- (parts[1] === '.' || parts[1] === '')) {
- didSomething = true;
- parts.pop();
- }
- }
- // //../ -> /
- let dd = 0;
- while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
- const p = parts[dd - 1];
- if (p && p !== '.' && p !== '..' && p !== '**') {
- didSomething = true;
- parts.splice(dd - 1, 2);
- dd -= 2;
- }
- }
- } while (didSomething);
- return parts.length === 0 ? [''] : parts;
- }
- // First phase: single-pattern processing
- // is 1 or more portions
- // is 1 or more portions
- // is any portion other than ., .., '', or **
- // is . or ''
- //
- // **/.. is *brutal* for filesystem walking performance, because
- // it effectively resets the recursive walk each time it occurs,
- // and ** cannot be reduced out by a .. pattern part like a regexp
- // or most strings (other than .., ., and '') can be.
- //
- // /**/..//
/ -> {/..//
/,/**//
/}
- // // -> /
- // //../ -> /
- // **/**/ -> **/
- //
- // **/*/ -> */**/ <== not valid because ** doesn't follow
- // this WOULD be allowed if ** did follow symlinks, or * didn't
- firstPhasePreProcess(globParts) {
- let didSomething = false;
- do {
- didSomething = false;
- // /**/..//
/ -> {/..//
/,/**//
/}
- for (let parts of globParts) {
- let gs = -1;
- while (-1 !== (gs = parts.indexOf('**', gs + 1))) {
- let gss = gs;
- while (parts[gss + 1] === '**') {
- // /**/**/ -> /**/
- gss++;
- }
- // eg, if gs is 2 and gss is 4, that means we have 3 **
- // parts, and can remove 2 of them.
- if (gss > gs) {
- parts.splice(gs + 1, gss - gs);
- }
- let next = parts[gs + 1];
- const p = parts[gs + 2];
- const p2 = parts[gs + 3];
- if (next !== '..')
- continue;
- if (!p ||
- p === '.' ||
- p === '..' ||
- !p2 ||
- p2 === '.' ||
- p2 === '..') {
- continue;
- }
- didSomething = true;
- // edit parts in place, and push the new one
- parts.splice(gs, 1);
- const other = parts.slice(0);
- other[gs] = '**';
- globParts.push(other);
- gs--;
- }
- // // -> /
- if (!this.preserveMultipleSlashes) {
- for (let i = 1; i < parts.length - 1; i++) {
- const p = parts[i];
- // don't squeeze out UNC patterns
- if (i === 1 && p === '' && parts[0] === '')
- continue;
- if (p === '.' || p === '') {
- didSomething = true;
- parts.splice(i, 1);
- i--;
- }
- }
- if (parts[0] === '.' &&
- parts.length === 2 &&
- (parts[1] === '.' || parts[1] === '')) {
- didSomething = true;
- parts.pop();
- }
- }
- // //../ -> /
- let dd = 0;
- while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
- const p = parts[dd - 1];
- if (p && p !== '.' && p !== '..' && p !== '**') {
- didSomething = true;
- const needDot = dd === 1 && parts[dd + 1] === '**';
- const splin = needDot ? ['.'] : [];
- parts.splice(dd - 1, 2, ...splin);
- if (parts.length === 0)
- parts.push('');
- dd -= 2;
- }
- }
- }
- } while (didSomething);
- return globParts;
- }
- // second phase: multi-pattern dedupes
- // {/*/,//} -> /*/
- // {/,/} -> /
- // {/**/,/} -> /**/
- //
- // {/**/,/**//} -> /**/
- // ^-- not valid because ** doens't follow symlinks
- secondPhasePreProcess(globParts) {
- for (let i = 0; i < globParts.length - 1; i++) {
- for (let j = i + 1; j < globParts.length; j++) {
- const matched = this.partsMatch(globParts[i], globParts[j], !this.preserveMultipleSlashes);
- if (matched) {
- globParts[i] = [];
- globParts[j] = matched;
- break;
- }
- }
- }
- return globParts.filter(gs => gs.length);
- }
- partsMatch(a, b, emptyGSMatch = false) {
- let ai = 0;
- let bi = 0;
- let result = [];
- let which = '';
- while (ai < a.length && bi < b.length) {
- if (a[ai] === b[bi]) {
- result.push(which === 'b' ? b[bi] : a[ai]);
- ai++;
- bi++;
- }
- else if (emptyGSMatch && a[ai] === '**' && b[bi] === a[ai + 1]) {
- result.push(a[ai]);
- ai++;
- }
- else if (emptyGSMatch && b[bi] === '**' && a[ai] === b[bi + 1]) {
- result.push(b[bi]);
- bi++;
- }
- else if (a[ai] === '*' &&
- b[bi] &&
- (this.options.dot || !b[bi].startsWith('.')) &&
- b[bi] !== '**') {
- if (which === 'b')
- return false;
- which = 'a';
- result.push(a[ai]);
- ai++;
- bi++;
- }
- else if (b[bi] === '*' &&
- a[ai] &&
- (this.options.dot || !a[ai].startsWith('.')) &&
- a[ai] !== '**') {
- if (which === 'a')
- return false;
- which = 'b';
- result.push(b[bi]);
- ai++;
- bi++;
- }
- else {
- return false;
- }
- }
- // if we fall out of the loop, it means they two are identical
- // as long as their lengths match
- return a.length === b.length && result;
- }
- parseNegate() {
- if (this.nonegate)
- return;
- const pattern = this.pattern;
- let negate = false;
- let negateOffset = 0;
- for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {
- negate = !negate;
- negateOffset++;
- }
- if (negateOffset)
- this.pattern = pattern.slice(negateOffset);
- this.negate = negate;
- }
- // set partial to true to test if, for example,
- // "/a/b" matches the start of "/*/b/*/d"
- // Partial means, if you run out of file before you run
- // out of pattern, then that's fine, as long as all
- // the parts match.
- matchOne(file, pattern, partial = false) {
- const options = this.options;
- // UNC paths like //?/X:/... can match X:/... and vice versa
- // Drive letters in absolute drive or unc paths are always compared
- // case-insensitively.
- if (this.isWindows) {
- const fileDrive = typeof file[0] === 'string' && /^[a-z]:$/i.test(file[0]);
- const fileUNC = !fileDrive &&
- file[0] === '' &&
- file[1] === '' &&
- file[2] === '?' &&
- /^[a-z]:$/i.test(file[3]);
- const patternDrive = typeof pattern[0] === 'string' && /^[a-z]:$/i.test(pattern[0]);
- const patternUNC = !patternDrive &&
- pattern[0] === '' &&
- pattern[1] === '' &&
- pattern[2] === '?' &&
- typeof pattern[3] === 'string' &&
- /^[a-z]:$/i.test(pattern[3]);
- const fdi = fileUNC ? 3 : fileDrive ? 0 : undefined;
- const pdi = patternUNC ? 3 : patternDrive ? 0 : undefined;
- if (typeof fdi === 'number' && typeof pdi === 'number') {
- const [fd, pd] = [file[fdi], pattern[pdi]];
- if (fd.toLowerCase() === pd.toLowerCase()) {
- pattern[pdi] = fd;
- if (pdi > fdi) {
- pattern = pattern.slice(pdi);
- }
- else if (fdi > pdi) {
- file = file.slice(fdi);
- }
- }
- }
- }
- // resolve and reduce . and .. portions in the file as well.
- // dont' need to do the second phase, because it's only one string[]
- const { optimizationLevel = 1 } = this.options;
- if (optimizationLevel >= 2) {
- file = this.levelTwoFileOptimize(file);
- }
- this.debug('matchOne', this, { file, pattern });
- this.debug('matchOne', file.length, pattern.length);
- for (var fi = 0, pi = 0, fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
- this.debug('matchOne loop');
- var p = pattern[pi];
- var f = file[fi];
- this.debug(pattern, p, f);
- // should be impossible.
- // some invalid regexp stuff in the set.
- /* c8 ignore start */
- if (p === false) {
- return false;
- }
- /* c8 ignore stop */
- if (p === exports.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.
- /* c8 ignore start */
- if (partial) {
- // ran out of file
- this.debug('\n>>> no match, partial?', file, fr, pattern, pr);
- if (fr === fl) {
- return true;
- }
- }
- /* c8 ignore stop */
- return false;
- }
- // something other than **
- // non-magic patterns just have to match exactly
- // patterns with magic have been turned into regexps.
- let hit;
- if (typeof p === 'string') {
- hit = f === p;
- this.debug('string match', p, f, hit);
- }
- else {
- hit = p.test(f);
- this.debug('pattern match', p, f, hit);
- }
- 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.
- // an exact hit!
- return true;
- }
- else if (fi === fl) {
- // ran out of file, but still had pattern left.
- // this is ok if we're doing the match as part of
- // a glob fs traversal.
- return partial;
- }
- 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/
- return fi === fl - 1 && file[fi] === '';
- /* c8 ignore start */
- }
- else {
- // should be unreachable.
- throw new Error('wtf?');
- }
- /* c8 ignore stop */
- }
- braceExpand() {
- return (0, exports.braceExpand)(this.pattern, this.options);
- }
- parse(pattern) {
- (0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
- const options = this.options;
- // shortcuts
- if (pattern === '**')
- return exports.GLOBSTAR;
- if (pattern === '')
- return '';
- // far and away, the most common glob pattern parts are
- // *, *.*, and *. Add a fast check method for those.
- let m;
- let fastTest = null;
- if ((m = pattern.match(starRE))) {
- fastTest = options.dot ? starTestDot : starTest;
- }
- else if ((m = pattern.match(starDotExtRE))) {
- fastTest = (options.nocase
- ? options.dot
- ? starDotExtTestNocaseDot
- : starDotExtTestNocase
- : options.dot
- ? starDotExtTestDot
- : starDotExtTest)(m[1]);
- }
- else if ((m = pattern.match(qmarksRE))) {
- fastTest = (options.nocase
- ? options.dot
- ? qmarksTestNocaseDot
- : qmarksTestNocase
- : options.dot
- ? qmarksTestDot
- : qmarksTest)(m);
- }
- else if ((m = pattern.match(starDotStarRE))) {
- fastTest = options.dot ? starDotStarTestDot : starDotStarTest;
- }
- else if ((m = pattern.match(dotStarRE))) {
- fastTest = dotStarTest;
- }
- const re = ast_js_1.AST.fromGlob(pattern, this.options).toMMPattern();
- if (fastTest && typeof re === 'object') {
- // Avoids overriding in frozen environments
- Reflect.defineProperty(re, 'test', { value: fastTest });
- }
- return re;
- }
- makeRe() {
- if (this.regexp || this.regexp === false)
- return this.regexp;
- // at this point, this.set is a 2d array of partial
- // pattern strings, or "**".
- //
- // It's better to use .match(). This function shouldn't
- // be used, really, but it's pretty convenient sometimes,
- // when you just want to work with a regex.
- const set = this.set;
- if (!set.length) {
- this.regexp = false;
- return this.regexp;
- }
- const options = this.options;
- const twoStar = options.noglobstar
- ? star
- : options.dot
- ? twoStarDot
- : twoStarNoDot;
- const flags = new Set(options.nocase ? ['i'] : []);
- // regexpify non-globstar patterns
- // if ** is only item, then we just do one twoStar
- // if ** is first, and there are more, prepend (\/|twoStar\/)? to next
- // if ** is last, append (\/twoStar|) to previous
- // if ** is in the middle, append (\/|\/twoStar\/) to previous
- // then filter out GLOBSTAR symbols
- let re = set
- .map(pattern => {
- const pp = pattern.map(p => {
- if (p instanceof RegExp) {
- for (const f of p.flags.split(''))
- flags.add(f);
- }
- return typeof p === 'string'
- ? regExpEscape(p)
- : p === exports.GLOBSTAR
- ? exports.GLOBSTAR
- : p._src;
- });
- pp.forEach((p, i) => {
- const next = pp[i + 1];
- const prev = pp[i - 1];
- if (p !== exports.GLOBSTAR || prev === exports.GLOBSTAR) {
- return;
- }
- if (prev === undefined) {
- if (next !== undefined && next !== exports.GLOBSTAR) {
- pp[i + 1] = '(?:\\/|' + twoStar + '\\/)?' + next;
- }
- else {
- pp[i] = twoStar;
- }
- }
- else if (next === undefined) {
- pp[i - 1] = prev + '(?:\\/|' + twoStar + ')?';
- }
- else if (next !== exports.GLOBSTAR) {
- pp[i - 1] = prev + '(?:\\/|\\/' + twoStar + '\\/)' + next;
- pp[i + 1] = exports.GLOBSTAR;
- }
- });
- return pp.filter(p => p !== exports.GLOBSTAR).join('/');
- })
- .join('|');
- // need to wrap in parens if we had more than one thing with |,
- // otherwise only the first will be anchored to ^ and the last to $
- const [open, close] = set.length > 1 ? ['(?:', ')'] : ['', ''];
- // must match entire pattern
- // ending in a * or ** will make it less strict.
- re = '^' + open + re + close + '$';
- // can match anything, as long as it's not this.
- if (this.negate)
- re = '^(?!' + re + ').+$';
- try {
- this.regexp = new RegExp(re, [...flags].join(''));
- /* c8 ignore start */
- }
- catch (ex) {
- // should be impossible
- this.regexp = false;
- }
- /* c8 ignore stop */
- return this.regexp;
- }
- slashSplit(p) {
- // if p starts with // on windows, we preserve that
- // so that UNC paths aren't broken. Otherwise, any number of
- // / characters are coalesced into one, unless
- // preserveMultipleSlashes is set to true.
- if (this.preserveMultipleSlashes) {
- return p.split('/');
- }
- else if (this.isWindows && /^\/\/[^\/]+/.test(p)) {
- // add an extra '' for the one we lose
- return ['', ...p.split(/\/+/)];
- }
- else {
- return p.split(/\/+/);
- }
- }
- match(f, partial = this.partial) {
- this.debug('match', f, this.pattern);
- // short-circuit in the case of busted things.
- // comments, etc.
- if (this.comment) {
- return false;
- }
- if (this.empty) {
- return f === '';
- }
- if (f === '/' && partial) {
- return true;
- }
- const options = this.options;
- // windows: need to use /, not \
- if (this.isWindows) {
- f = f.split('\\').join('/');
- }
- // treat the test path as a set of pathparts.
- const ff = this.slashSplit(f);
- this.debug(this.pattern, 'split', ff);
- // just ONE of the pattern sets in this.set needs to match
- // in order for it to be valid. If negating, then just one
- // match means that we have failed.
- // Either way, return on the first hit.
- const set = this.set;
- this.debug(this.pattern, 'set', set);
- // Find the basename of the path by looking for the last non-empty segment
- let filename = ff[ff.length - 1];
- if (!filename) {
- for (let i = ff.length - 2; !filename && i >= 0; i--) {
- filename = ff[i];
- }
- }
- for (let i = 0; i < set.length; i++) {
- const pattern = set[i];
- let file = ff;
- if (options.matchBase && pattern.length === 1) {
- file = [filename];
- }
- const hit = this.matchOne(file, pattern, partial);
- if (hit) {
- if (options.flipNegate) {
- return true;
- }
- return !this.negate;
- }
- }
- // didn't get any hits. this is success if it's a negative
- // pattern, failure otherwise.
- if (options.flipNegate) {
- return false;
- }
- return this.negate;
- }
- static defaults(def) {
- return exports.minimatch.defaults(def).Minimatch;
- }
-}
-exports.Minimatch = Minimatch;
-/* c8 ignore start */
-var ast_js_2 = __nccwpck_require__(37095);
-Object.defineProperty(exports, "AST", ({ enumerable: true, get: function () { return ast_js_2.AST; } }));
-var escape_js_2 = __nccwpck_require__(72776);
-Object.defineProperty(exports, "escape", ({ enumerable: true, get: function () { return escape_js_2.escape; } }));
-var unescape_js_2 = __nccwpck_require__(67519);
-Object.defineProperty(exports, "unescape", ({ enumerable: true, get: function () { return unescape_js_2.unescape; } }));
-/* c8 ignore stop */
-exports.minimatch.AST = ast_js_1.AST;
-exports.minimatch.Minimatch = Minimatch;
-exports.minimatch.escape = escape_js_1.escape;
-exports.minimatch.unescape = unescape_js_1.unescape;
-//# sourceMappingURL=index.js.map
-
-/***/ }),
-
-/***/ 67519:
-/***/ ((__unused_webpack_module, exports) => {
-
-"use strict";
-
-Object.defineProperty(exports, "__esModule", ({ value: true }));
-exports.unescape = void 0;
-/**
- * Un-escape a string that has been escaped with {@link escape}.
- *
- * If the {@link windowsPathsNoEscape} option is used, then square-brace
- * escapes are removed, but not backslash escapes. For example, it will turn
- * the string `'[*]'` into `*`, but it will not turn `'\\*'` into `'*'`,
- * becuase `\` is a path separator in `windowsPathsNoEscape` mode.
- *
- * When `windowsPathsNoEscape` is not set, then both brace escapes and
- * backslash escapes are removed.
- *
- * Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot be escaped
- * or unescaped.
- */
-const unescape = (s, { windowsPathsNoEscape = false, } = {}) => {
- return windowsPathsNoEscape
- ? s.replace(/\[([^\/\\])\]/g, '$1')
- : s.replace(/((?!\\).|^)\[([^\/\\])\]/g, '$1$2').replace(/\\([^\/])/g, '$1');
-};
-exports.unescape = unescape;
-//# sourceMappingURL=unescape.js.map
-
-/***/ }),
-
-/***/ 10903:
-/***/ ((__unused_webpack_module, exports) => {
-
-"use strict";
-
-Object.defineProperty(exports, "__esModule", ({ value: true }));
-exports.assertValidPattern = void 0;
-const MAX_PATTERN_LENGTH = 1024 * 64;
-const assertValidPattern = (pattern) => {
- if (typeof pattern !== 'string') {
- throw new TypeError('invalid pattern');
- }
- if (pattern.length > MAX_PATTERN_LENGTH) {
- throw new TypeError('pattern is too long');
- }
-};
-exports.assertValidPattern = assertValidPattern;
-//# sourceMappingURL=assert-valid-pattern.js.map
-
-/***/ }),
-
-/***/ 33839:
-/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
-
-"use strict";
-
-// parse a single path portion
-Object.defineProperty(exports, "__esModule", ({ value: true }));
-exports.AST = void 0;
-const brace_expressions_js_1 = __nccwpck_require__(5822);
-const unescape_js_1 = __nccwpck_require__(87305);
-const types = new Set(['!', '?', '+', '*', '@']);
-const isExtglobType = (c) => types.has(c);
-// Patterns that get prepended to bind to the start of either the
-// entire string, or just a single path portion, to prevent dots
-// and/or traversal patterns, when needed.
-// Exts don't need the ^ or / bit, because the root binds that already.
-const startNoTraversal = '(?!(?:^|/)\\.\\.?(?:$|/))';
-const startNoDot = '(?!\\.)';
-// characters that indicate a start of pattern needs the "no dots" bit,
-// because a dot *might* be matched. ( is not in the list, because in
-// the case of a child extglob, it will handle the prevention itself.
-const addPatternStart = new Set(['[', '.']);
-// cases where traversal is A-OK, no dot prevention needed
-const justDots = new Set(['..', '.']);
-const reSpecials = new Set('().*{}+?[]^$\\!');
-const regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
-// any single thing other than /
-const qmark = '[^/]';
-// * => any number of characters
-const star = qmark + '*?';
-// use + when we need to ensure that *something* matches, because the * is
-// the only thing in the path portion.
-const starNoEmpty = qmark + '+?';
-// remove the \ chars that we added if we end up doing a nonmagic compare
-// const deslash = (s: string) => s.replace(/\\(.)/g, '$1')
-class AST {
- type;
- #root;
- #hasMagic;
- #uflag = false;
- #parts = [];
- #parent;
- #parentIndex;
- #negs;
- #filledNegs = false;
- #options;
- #toString;
- // set to true if it's an extglob with no children
- // (which really means one child of '')
- #emptyExt = false;
- constructor(type, parent, options = {}) {
- this.type = type;
- // extglobs are inherently magical
- if (type)
- this.#hasMagic = true;
- this.#parent = parent;
- this.#root = this.#parent ? this.#parent.#root : this;
- this.#options = this.#root === this ? options : this.#root.#options;
- this.#negs = this.#root === this ? [] : this.#root.#negs;
- if (type === '!' && !this.#root.#filledNegs)
- this.#negs.push(this);
- this.#parentIndex = this.#parent ? this.#parent.#parts.length : 0;
- }
- get hasMagic() {
- /* c8 ignore start */
- if (this.#hasMagic !== undefined)
- return this.#hasMagic;
- /* c8 ignore stop */
- for (const p of this.#parts) {
- if (typeof p === 'string')
- continue;
- if (p.type || p.hasMagic)
- return (this.#hasMagic = true);
- }
- // note: will be undefined until we generate the regexp src and find out
- return this.#hasMagic;
- }
- // reconstructs the pattern
- toString() {
- if (this.#toString !== undefined)
- return this.#toString;
- if (!this.type) {
- return (this.#toString = this.#parts.map(p => String(p)).join(''));
- }
- else {
- return (this.#toString =
- this.type + '(' + this.#parts.map(p => String(p)).join('|') + ')');
- }
- }
- #fillNegs() {
- /* c8 ignore start */
- if (this !== this.#root)
- throw new Error('should only call on root');
- if (this.#filledNegs)
- return this;
- /* c8 ignore stop */
- // call toString() once to fill this out
- this.toString();
- this.#filledNegs = true;
- let n;
- while ((n = this.#negs.pop())) {
- if (n.type !== '!')
- continue;
- // walk up the tree, appending everthing that comes AFTER parentIndex
- let p = n;
- let pp = p.#parent;
- while (pp) {
- for (let i = p.#parentIndex + 1; !pp.type && i < pp.#parts.length; i++) {
- for (const part of n.#parts) {
- /* c8 ignore start */
- if (typeof part === 'string') {
- throw new Error('string part in extglob AST??');
- }
- /* c8 ignore stop */
- part.copyIn(pp.#parts[i]);
- }
- }
- p = pp;
- pp = p.#parent;
- }
- }
- return this;
- }
- push(...parts) {
- for (const p of parts) {
- if (p === '')
- continue;
- /* c8 ignore start */
- if (typeof p !== 'string' && !(p instanceof AST && p.#parent === this)) {
- throw new Error('invalid part: ' + p);
- }
- /* c8 ignore stop */
- this.#parts.push(p);
- }
- }
- toJSON() {
- const ret = this.type === null
- ? this.#parts.slice().map(p => (typeof p === 'string' ? p : p.toJSON()))
- : [this.type, ...this.#parts.map(p => p.toJSON())];
- if (this.isStart() && !this.type)
- ret.unshift([]);
- if (this.isEnd() &&
- (this === this.#root ||
- (this.#root.#filledNegs && this.#parent?.type === '!'))) {
- ret.push({});
- }
- return ret;
- }
- isStart() {
- if (this.#root === this)
- return true;
- // if (this.type) return !!this.#parent?.isStart()
- if (!this.#parent?.isStart())
- return false;
- if (this.#parentIndex === 0)
- return true;
- // if everything AHEAD of this is a negation, then it's still the "start"
- const p = this.#parent;
- for (let i = 0; i < this.#parentIndex; i++) {
- const pp = p.#parts[i];
- if (!(pp instanceof AST && pp.type === '!')) {
- return false;
- }
- }
- return true;
- }
- isEnd() {
- if (this.#root === this)
- return true;
- if (this.#parent?.type === '!')
- return true;
- if (!this.#parent?.isEnd())
- return false;
- if (!this.type)
- return this.#parent?.isEnd();
- // if not root, it'll always have a parent
- /* c8 ignore start */
- const pl = this.#parent ? this.#parent.#parts.length : 0;
- /* c8 ignore stop */
- return this.#parentIndex === pl - 1;
- }
- copyIn(part) {
- if (typeof part === 'string')
- this.push(part);
- else
- this.push(part.clone(this));
- }
- clone(parent) {
- const c = new AST(this.type, parent);
- for (const p of this.#parts) {
- c.copyIn(p);
- }
- return c;
- }
- static #parseAST(str, ast, pos, opt) {
- let escaping = false;
- let inBrace = false;
- let braceStart = -1;
- let braceNeg = false;
- if (ast.type === null) {
- // outside of a extglob, append until we find a start
- let i = pos;
- let acc = '';
- while (i < str.length) {
- const c = str.charAt(i++);
- // still accumulate escapes at this point, but we do ignore
- // starts that are escaped
- if (escaping || c === '\\') {
- escaping = !escaping;
- acc += c;
- continue;
- }
- if (inBrace) {
- if (i === braceStart + 1) {
- if (c === '^' || c === '!') {
- braceNeg = true;
- }
- }
- else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {
- inBrace = false;
- }
- acc += c;
- continue;
- }
- else if (c === '[') {
- inBrace = true;
- braceStart = i;
- braceNeg = false;
- acc += c;
- continue;
- }
- if (!opt.noext && isExtglobType(c) && str.charAt(i) === '(') {
- ast.push(acc);
- acc = '';
- const ext = new AST(c, ast);
- i = AST.#parseAST(str, ext, i, opt);
- ast.push(ext);
- continue;
- }
- acc += c;
- }
- ast.push(acc);
- return i;
- }
- // some kind of extglob, pos is at the (
- // find the next | or )
- let i = pos + 1;
- let part = new AST(null, ast);
- const parts = [];
- let acc = '';
- while (i < str.length) {
- const c = str.charAt(i++);
- // still accumulate escapes at this point, but we do ignore
- // starts that are escaped
- if (escaping || c === '\\') {
- escaping = !escaping;
- acc += c;
- continue;
- }
- if (inBrace) {
- if (i === braceStart + 1) {
- if (c === '^' || c === '!') {
- braceNeg = true;
- }
- }
- else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {
- inBrace = false;
- }
- acc += c;
- continue;
- }
- else if (c === '[') {
- inBrace = true;
- braceStart = i;
- braceNeg = false;
- acc += c;
- continue;
- }
- if (isExtglobType(c) && str.charAt(i) === '(') {
- part.push(acc);
- acc = '';
- const ext = new AST(c, part);
- part.push(ext);
- i = AST.#parseAST(str, ext, i, opt);
- continue;
- }
- if (c === '|') {
- part.push(acc);
- acc = '';
- parts.push(part);
- part = new AST(null, ast);
- continue;
- }
- if (c === ')') {
- if (acc === '' && ast.#parts.length === 0) {
- ast.#emptyExt = true;
- }
- part.push(acc);
- acc = '';
- ast.push(...parts, part);
- return i;
- }
- acc += c;
- }
- // unfinished extglob
- // if we got here, it was a malformed extglob! not an extglob, but
- // maybe something else in there.
- ast.type = null;
- ast.#hasMagic = undefined;
- ast.#parts = [str.substring(pos - 1)];
- return i;
- }
- static fromGlob(pattern, options = {}) {
- const ast = new AST(null, undefined, options);
- AST.#parseAST(pattern, ast, 0, options);
- return ast;
- }
- // returns the regular expression if there's magic, or the unescaped
- // string if not.
- toMMPattern() {
- // should only be called on root
- /* c8 ignore start */
- if (this !== this.#root)
- return this.#root.toMMPattern();
- /* c8 ignore stop */
- const glob = this.toString();
- const [re, body, hasMagic, uflag] = this.toRegExpSource();
- // if we're in nocase mode, and not nocaseMagicOnly, then we do
- // still need a regular expression if we have to case-insensitively
- // match capital/lowercase characters.
- const anyMagic = hasMagic ||
- this.#hasMagic ||
- (this.#options.nocase &&
- !this.#options.nocaseMagicOnly &&
- glob.toUpperCase() !== glob.toLowerCase());
- if (!anyMagic) {
- return body;
- }
- const flags = (this.#options.nocase ? 'i' : '') + (uflag ? 'u' : '');
- return Object.assign(new RegExp(`^${re}$`, flags), {
- _src: re,
- _glob: glob,
- });
- }
- // returns the string match, the regexp source, whether there's magic
- // in the regexp (so a regular expression is required) and whether or
- // not the uflag is needed for the regular expression (for posix classes)
- // TODO: instead of injecting the start/end at this point, just return
- // the BODY of the regexp, along with the start/end portions suitable
- // for binding the start/end in either a joined full-path makeRe context
- // (where we bind to (^|/), or a standalone matchPart context (where
- // we bind to ^, and not /). Otherwise slashes get duped!
- //
- // In part-matching mode, the start is:
- // - if not isStart: nothing
- // - if traversal possible, but not allowed: ^(?!\.\.?$)
- // - if dots allowed or not possible: ^
- // - if dots possible and not allowed: ^(?!\.)
- // end is:
- // - if not isEnd(): nothing
- // - else: $
- //
- // In full-path matching mode, we put the slash at the START of the
- // pattern, so start is:
- // - if first pattern: same as part-matching mode
- // - if not isStart(): nothing
- // - if traversal possible, but not allowed: /(?!\.\.?(?:$|/))
- // - if dots allowed or not possible: /
- // - if dots possible and not allowed: /(?!\.)
- // end is:
- // - if last pattern, same as part-matching mode
- // - else nothing
- //
- // Always put the (?:$|/) on negated tails, though, because that has to be
- // there to bind the end of the negated pattern portion, and it's easier to
- // just stick it in now rather than try to inject it later in the middle of
- // the pattern.
- //
- // We can just always return the same end, and leave it up to the caller
- // to know whether it's going to be used joined or in parts.
- // And, if the start is adjusted slightly, can do the same there:
- // - if not isStart: nothing
- // - if traversal possible, but not allowed: (?:/|^)(?!\.\.?$)
- // - if dots allowed or not possible: (?:/|^)
- // - if dots possible and not allowed: (?:/|^)(?!\.)
- //
- // But it's better to have a simpler binding without a conditional, for
- // performance, so probably better to return both start options.
- //
- // Then the caller just ignores the end if it's not the first pattern,
- // and the start always gets applied.
- //
- // But that's always going to be $ if it's the ending pattern, or nothing,
- // so the caller can just attach $ at the end of the pattern when building.
- //
- // So the todo is:
- // - better detect what kind of start is needed
- // - return both flavors of starting pattern
- // - attach $ at the end of the pattern when creating the actual RegExp
- //
- // Ah, but wait, no, that all only applies to the root when the first pattern
- // is not an extglob. If the first pattern IS an extglob, then we need all
- // that dot prevention biz to live in the extglob portions, because eg
- // +(*|.x*) can match .xy but not .yx.
- //
- // So, return the two flavors if it's #root and the first child is not an
- // AST, otherwise leave it to the child AST to handle it, and there,
- // use the (?:^|/) style of start binding.
- //
- // Even simplified further:
- // - Since the start for a join is eg /(?!\.) and the start for a part
- // is ^(?!\.), we can just prepend (?!\.) to the pattern (either root
- // or start or whatever) and prepend ^ or / at the Regexp construction.
- toRegExpSource(allowDot) {
- const dot = allowDot ?? !!this.#options.dot;
- if (this.#root === this)
- this.#fillNegs();
- if (!this.type) {
- const noEmpty = this.isStart() && this.isEnd();
- const src = this.#parts
- .map(p => {
- const [re, _, hasMagic, uflag] = typeof p === 'string'
- ? AST.#parseGlob(p, this.#hasMagic, noEmpty)
- : p.toRegExpSource(allowDot);
- this.#hasMagic = this.#hasMagic || hasMagic;
- this.#uflag = this.#uflag || uflag;
- return re;
- })
- .join('');
- let start = '';
- if (this.isStart()) {
- if (typeof this.#parts[0] === 'string') {
- // this is the string that will match the start of the pattern,
- // so we need to protect against dots and such.
- // '.' and '..' cannot match unless the pattern is that exactly,
- // even if it starts with . or dot:true is set.
- const dotTravAllowed = this.#parts.length === 1 && justDots.has(this.#parts[0]);
- if (!dotTravAllowed) {
- const aps = addPatternStart;
- // check if we have a possibility of matching . or ..,
- // and prevent that.
- const needNoTrav =
- // dots are allowed, and the pattern starts with [ or .
- (dot && aps.has(src.charAt(0))) ||
- // the pattern starts with \., and then [ or .
- (src.startsWith('\\.') && aps.has(src.charAt(2))) ||
- // the pattern starts with \.\., and then [ or .
- (src.startsWith('\\.\\.') && aps.has(src.charAt(4)));
- // no need to prevent dots if it can't match a dot, or if a
- // sub-pattern will be preventing it anyway.
- const needNoDot = !dot && !allowDot && aps.has(src.charAt(0));
- start = needNoTrav ? startNoTraversal : needNoDot ? startNoDot : '';
- }
- }
- }
- // append the "end of path portion" pattern to negation tails
- let end = '';
- if (this.isEnd() &&
- this.#root.#filledNegs &&
- this.#parent?.type === '!') {
- end = '(?:$|\\/)';
- }
- const final = start + src + end;
- return [
- final,
- (0, unescape_js_1.unescape)(src),
- (this.#hasMagic = !!this.#hasMagic),
- this.#uflag,
- ];
- }
- // We need to calculate the body *twice* if it's a repeat pattern
- // at the start, once in nodot mode, then again in dot mode, so a
- // pattern like *(?) can match 'x.y'
- const repeated = this.type === '*' || this.type === '+';
- // some kind of extglob
- const start = this.type === '!' ? '(?:(?!(?:' : '(?:';
- let body = this.#partsToRegExp(dot);
- if (this.isStart() && this.isEnd() && !body && this.type !== '!') {
- // invalid extglob, has to at least be *something* present, if it's
- // the entire path portion.
- const s = this.toString();
- this.#parts = [s];
- this.type = null;
- this.#hasMagic = undefined;
- return [s, (0, unescape_js_1.unescape)(this.toString()), false, false];
- }
- // XXX abstract out this map method
- let bodyDotAllowed = !repeated || allowDot || dot || !startNoDot
- ? ''
- : this.#partsToRegExp(true);
- if (bodyDotAllowed === body) {
- bodyDotAllowed = '';
- }
- if (bodyDotAllowed) {
- body = `(?:${body})(?:${bodyDotAllowed})*?`;
- }
- // an empty !() is exactly equivalent to a starNoEmpty
- let final = '';
- if (this.type === '!' && this.#emptyExt) {
- final = (this.isStart() && !dot ? startNoDot : '') + starNoEmpty;
- }
- else {
- const close = this.type === '!'
- ? // !() must match something,but !(x) can match ''
- '))' +
- (this.isStart() && !dot && !allowDot ? startNoDot : '') +
- star +
- ')'
- : this.type === '@'
- ? ')'
- : this.type === '?'
- ? ')?'
- : this.type === '+' && bodyDotAllowed
- ? ')'
- : this.type === '*' && bodyDotAllowed
- ? `)?`
- : `)${this.type}`;
- final = start + body + close;
- }
- return [
- final,
- (0, unescape_js_1.unescape)(body),
- (this.#hasMagic = !!this.#hasMagic),
- this.#uflag,
- ];
- }
- #partsToRegExp(dot) {
- return this.#parts
- .map(p => {
- // extglob ASTs should only contain parent ASTs
- /* c8 ignore start */
- if (typeof p === 'string') {
- throw new Error('string type in extglob ast??');
- }
- /* c8 ignore stop */
- // can ignore hasMagic, because extglobs are already always magic
- const [re, _, _hasMagic, uflag] = p.toRegExpSource(dot);
- this.#uflag = this.#uflag || uflag;
- return re;
- })
- .filter(p => !(this.isStart() && this.isEnd()) || !!p)
- .join('|');
- }
- static #parseGlob(glob, hasMagic, noEmpty = false) {
- let escaping = false;
- let re = '';
- let uflag = false;
- for (let i = 0; i < glob.length; i++) {
- const c = glob.charAt(i);
- if (escaping) {
- escaping = false;
- re += (reSpecials.has(c) ? '\\' : '') + c;
- continue;
- }
- if (c === '\\') {
- if (i === glob.length - 1) {
- re += '\\\\';
- }
- else {
- escaping = true;
- }
- continue;
- }
- if (c === '[') {
- const [src, needUflag, consumed, magic] = (0, brace_expressions_js_1.parseClass)(glob, i);
- if (consumed) {
- re += src;
- uflag = uflag || needUflag;
- i += consumed - 1;
- hasMagic = hasMagic || magic;
- continue;
- }
- }
- if (c === '*') {
- if (noEmpty && glob === '*')
- re += starNoEmpty;
- else
- re += star;
- hasMagic = true;
- continue;
- }
- if (c === '?') {
- re += qmark;
- hasMagic = true;
- continue;
- }
- re += regExpEscape(c);
- }
- return [re, (0, unescape_js_1.unescape)(glob), !!hasMagic, uflag];
- }
-}
-exports.AST = AST;
-//# sourceMappingURL=ast.js.map
-
-/***/ }),
-
-/***/ 5822:
-/***/ ((__unused_webpack_module, exports) => {
-
-"use strict";
-
-// translate the various posix character classes into unicode properties
-// this works across all unicode locales
-Object.defineProperty(exports, "__esModule", ({ value: true }));
-exports.parseClass = void 0;
-// { : [, /u flag required, negated]
-const posixClasses = {
- '[:alnum:]': ['\\p{L}\\p{Nl}\\p{Nd}', true],
- '[:alpha:]': ['\\p{L}\\p{Nl}', true],
- '[:ascii:]': ['\\x' + '00-\\x' + '7f', false],
- '[:blank:]': ['\\p{Zs}\\t', true],
- '[:cntrl:]': ['\\p{Cc}', true],
- '[:digit:]': ['\\p{Nd}', true],
- '[:graph:]': ['\\p{Z}\\p{C}', true, true],
- '[:lower:]': ['\\p{Ll}', true],
- '[:print:]': ['\\p{C}', true],
- '[:punct:]': ['\\p{P}', true],
- '[:space:]': ['\\p{Z}\\t\\r\\n\\v\\f', true],
- '[:upper:]': ['\\p{Lu}', true],
- '[:word:]': ['\\p{L}\\p{Nl}\\p{Nd}\\p{Pc}', true],
- '[:xdigit:]': ['A-Fa-f0-9', false],
-};
-// only need to escape a few things inside of brace expressions
-// escapes: [ \ ] -
-const braceEscape = (s) => s.replace(/[[\]\\-]/g, '\\$&');
-// escape all regexp magic characters
-const regexpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
-// everything has already been escaped, we just have to join
-const rangesToString = (ranges) => ranges.join('');
-// takes a glob string at a posix brace expression, and returns
-// an equivalent regular expression source, and boolean indicating
-// whether the /u flag needs to be applied, and the number of chars
-// consumed to parse the character class.
-// This also removes out of order ranges, and returns ($.) if the
-// entire class just no good.
-const parseClass = (glob, position) => {
- const pos = position;
- /* c8 ignore start */
- if (glob.charAt(pos) !== '[') {
- throw new Error('not in a brace expression');
- }
- /* c8 ignore stop */
- const ranges = [];
- const negs = [];
- let i = pos + 1;
- let sawStart = false;
- let uflag = false;
- let escaping = false;
- let negate = false;
- let endPos = pos;
- let rangeStart = '';
- WHILE: while (i < glob.length) {
- const c = glob.charAt(i);
- if ((c === '!' || c === '^') && i === pos + 1) {
- negate = true;
- i++;
- continue;
- }
- if (c === ']' && sawStart && !escaping) {
- endPos = i + 1;
- break;
- }
- sawStart = true;
- if (c === '\\') {
- if (!escaping) {
- escaping = true;
- i++;
- continue;
- }
- // escaped \ char, fall through and treat like normal char
- }
- if (c === '[' && !escaping) {
- // either a posix class, a collation equivalent, or just a [
- for (const [cls, [unip, u, neg]] of Object.entries(posixClasses)) {
- if (glob.startsWith(cls, i)) {
- // invalid, [a-[] is fine, but not [a-[:alpha]]
- if (rangeStart) {
- return ['$.', false, glob.length - pos, true];
- }
- i += cls.length;
- if (neg)
- negs.push(unip);
- else
- ranges.push(unip);
- uflag = uflag || u;
- continue WHILE;
- }
- }
- }
- // now it's just a normal character, effectively
- escaping = false;
- if (rangeStart) {
- // throw this range away if it's not valid, but others
- // can still match.
- if (c > rangeStart) {
- ranges.push(braceEscape(rangeStart) + '-' + braceEscape(c));
- }
- else if (c === rangeStart) {
- ranges.push(braceEscape(c));
- }
- rangeStart = '';
- i++;
- continue;
- }
- // now might be the start of a range.
- // can be either c-d or c-] or c] or c] at this point
- if (glob.startsWith('-]', i + 1)) {
- ranges.push(braceEscape(c + '-'));
- i += 2;
- continue;
- }
- if (glob.startsWith('-', i + 1)) {
- rangeStart = c;
- i += 2;
- continue;
- }
- // not the start of a range, just a single character
- ranges.push(braceEscape(c));
- i++;
- }
- if (endPos < i) {
- // didn't see the end of the class, not a valid class,
- // but might still be valid as a literal match.
- return ['', false, 0, false];
- }
- // if we got no ranges and no negates, then we have a range that
- // cannot possibly match anything, and that poisons the whole glob
- if (!ranges.length && !negs.length) {
- return ['$.', false, glob.length - pos, true];
- }
- // if we got one positive range, and it's a single character, then that's
- // not actually a magic pattern, it's just that one literal character.
- // we should not treat that as "magic", we should just return the literal
- // character. [_] is a perfectly valid way to escape glob magic chars.
- if (negs.length === 0 &&
- ranges.length === 1 &&
- /^\\?.$/.test(ranges[0]) &&
- !negate) {
- const r = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0];
- return [regexpEscape(r), false, endPos - pos, false];
- }
- const sranges = '[' + (negate ? '^' : '') + rangesToString(ranges) + ']';
- const snegs = '[' + (negate ? '' : '^') + rangesToString(negs) + ']';
- const comb = ranges.length && negs.length
- ? '(' + sranges + '|' + snegs + ')'
- : ranges.length
- ? sranges
- : snegs;
- return [comb, uflag, endPos - pos, true];
-};
-exports.parseClass = parseClass;
-//# sourceMappingURL=brace-expressions.js.map
-
-/***/ }),
-
-/***/ 19004:
-/***/ ((__unused_webpack_module, exports) => {
-
-"use strict";
-
-Object.defineProperty(exports, "__esModule", ({ value: true }));
-exports.escape = void 0;
-/**
- * Escape all magic characters in a glob pattern.
- *
- * If the {@link windowsPathsNoEscape | GlobOptions.windowsPathsNoEscape}
- * option is used, then characters are escaped by wrapping in `[]`, because
- * a magic character wrapped in a character class can only be satisfied by
- * that exact character. In this mode, `\` is _not_ escaped, because it is
- * not interpreted as a magic character, but instead as a path separator.
- */
-const escape = (s, { windowsPathsNoEscape = false, } = {}) => {
- // don't need to escape +@! because we escape the parens
- // that make those magic, and escaping ! as [!] isn't valid,
- // because [!]] is a valid glob class meaning not ']'.
- return windowsPathsNoEscape
- ? s.replace(/[?*()[\]]/g, '[$&]')
- : s.replace(/[?*()[\]\\]/g, '\\$&');
-};
-exports.escape = escape;
-//# sourceMappingURL=escape.js.map
-
-/***/ }),
-
-/***/ 61953:
-/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
-
-"use strict";
-
-var __importDefault = (this && this.__importDefault) || function (mod) {
- return (mod && mod.__esModule) ? mod : { "default": mod };
-};
-Object.defineProperty(exports, "__esModule", ({ value: true }));
-exports.unescape = exports.escape = exports.AST = exports.Minimatch = exports.match = exports.makeRe = exports.braceExpand = exports.defaults = exports.filter = exports.GLOBSTAR = exports.sep = exports.minimatch = void 0;
-const brace_expansion_1 = __importDefault(__nccwpck_require__(33717));
-const assert_valid_pattern_js_1 = __nccwpck_require__(10903);
-const ast_js_1 = __nccwpck_require__(33839);
-const escape_js_1 = __nccwpck_require__(19004);
-const unescape_js_1 = __nccwpck_require__(87305);
-const minimatch = (p, pattern, options = {}) => {
- (0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
- // shortcut: comments match nothing.
- if (!options.nocomment && pattern.charAt(0) === '#') {
- return false;
- }
- return new Minimatch(pattern, options).match(p);
-};
-exports.minimatch = minimatch;
-// Optimized checking for the most common glob patterns.
-const starDotExtRE = /^\*+([^+@!?\*\[\(]*)$/;
-const starDotExtTest = (ext) => (f) => !f.startsWith('.') && f.endsWith(ext);
-const starDotExtTestDot = (ext) => (f) => f.endsWith(ext);
-const starDotExtTestNocase = (ext) => {
- ext = ext.toLowerCase();
- return (f) => !f.startsWith('.') && f.toLowerCase().endsWith(ext);
-};
-const starDotExtTestNocaseDot = (ext) => {
- ext = ext.toLowerCase();
- return (f) => f.toLowerCase().endsWith(ext);
-};
-const starDotStarRE = /^\*+\.\*+$/;
-const starDotStarTest = (f) => !f.startsWith('.') && f.includes('.');
-const starDotStarTestDot = (f) => f !== '.' && f !== '..' && f.includes('.');
-const dotStarRE = /^\.\*+$/;
-const dotStarTest = (f) => f !== '.' && f !== '..' && f.startsWith('.');
-const starRE = /^\*+$/;
-const starTest = (f) => f.length !== 0 && !f.startsWith('.');
-const starTestDot = (f) => f.length !== 0 && f !== '.' && f !== '..';
-const qmarksRE = /^\?+([^+@!?\*\[\(]*)?$/;
-const qmarksTestNocase = ([$0, ext = '']) => {
- const noext = qmarksTestNoExt([$0]);
- if (!ext)
- return noext;
- ext = ext.toLowerCase();
- return (f) => noext(f) && f.toLowerCase().endsWith(ext);
-};
-const qmarksTestNocaseDot = ([$0, ext = '']) => {
- const noext = qmarksTestNoExtDot([$0]);
- if (!ext)
- return noext;
- ext = ext.toLowerCase();
- return (f) => noext(f) && f.toLowerCase().endsWith(ext);
-};
-const qmarksTestDot = ([$0, ext = '']) => {
- const noext = qmarksTestNoExtDot([$0]);
- return !ext ? noext : (f) => noext(f) && f.endsWith(ext);
-};
-const qmarksTest = ([$0, ext = '']) => {
- const noext = qmarksTestNoExt([$0]);
- return !ext ? noext : (f) => noext(f) && f.endsWith(ext);
-};
-const qmarksTestNoExt = ([$0]) => {
- const len = $0.length;
- return (f) => f.length === len && !f.startsWith('.');
-};
-const qmarksTestNoExtDot = ([$0]) => {
- const len = $0.length;
- return (f) => f.length === len && f !== '.' && f !== '..';
-};
-/* c8 ignore start */
-const defaultPlatform = (typeof process === 'object' && process
- ? (typeof process.env === 'object' &&
- process.env &&
- process.env.__MINIMATCH_TESTING_PLATFORM__) ||
- process.platform
- : 'posix');
-const path = {
- win32: { sep: '\\' },
- posix: { sep: '/' },
-};
-/* c8 ignore stop */
-exports.sep = defaultPlatform === 'win32' ? path.win32.sep : path.posix.sep;
-exports.minimatch.sep = exports.sep;
-exports.GLOBSTAR = Symbol('globstar **');
-exports.minimatch.GLOBSTAR = exports.GLOBSTAR;
-// any single thing other than /
-// don't need to escape / when using new RegExp()
-const qmark = '[^/]';
-// * => any number of characters
-const star = qmark + '*?';
-// ** when dots are allowed. Anything goes, except .. and .
-// not (^ or / followed by one or two dots followed by $ or /),
-// followed by anything, any number of times.
-const twoStarDot = '(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?';
-// not a ^ or / followed by a dot,
-// followed by anything, any number of times.
-const twoStarNoDot = '(?:(?!(?:\\/|^)\\.).)*?';
-const filter = (pattern, options = {}) => (p) => (0, exports.minimatch)(p, pattern, options);
-exports.filter = filter;
-exports.minimatch.filter = exports.filter;
-const ext = (a, b = {}) => Object.assign({}, a, b);
-const defaults = (def) => {
- if (!def || typeof def !== 'object' || !Object.keys(def).length) {
- return exports.minimatch;
- }
- const orig = exports.minimatch;
- const m = (p, pattern, options = {}) => orig(p, pattern, ext(def, options));
- return Object.assign(m, {
- Minimatch: class Minimatch extends orig.Minimatch {
- constructor(pattern, options = {}) {
- super(pattern, ext(def, options));
- }
- static defaults(options) {
- return orig.defaults(ext(def, options)).Minimatch;
- }
- },
- AST: class AST extends orig.AST {
- /* c8 ignore start */
- constructor(type, parent, options = {}) {
- super(type, parent, ext(def, options));
- }
- /* c8 ignore stop */
- static fromGlob(pattern, options = {}) {
- return orig.AST.fromGlob(pattern, ext(def, options));
- }
- },
- unescape: (s, options = {}) => orig.unescape(s, ext(def, options)),
- escape: (s, options = {}) => orig.escape(s, ext(def, options)),
- filter: (pattern, options = {}) => orig.filter(pattern, ext(def, options)),
- defaults: (options) => orig.defaults(ext(def, options)),
- makeRe: (pattern, options = {}) => orig.makeRe(pattern, ext(def, options)),
- braceExpand: (pattern, options = {}) => orig.braceExpand(pattern, ext(def, options)),
- match: (list, pattern, options = {}) => orig.match(list, pattern, ext(def, options)),
- sep: orig.sep,
- GLOBSTAR: exports.GLOBSTAR,
- });
-};
-exports.defaults = defaults;
-exports.minimatch.defaults = exports.defaults;
-// Brace expansion:
-// a{b,c}d -> abd acd
-// a{b,}c -> abc ac
-// a{0..3}d -> a0d a1d a2d a3d
-// a{b,c{d,e}f}g -> abg acdfg acefg
-// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
-//
-// Invalid sets are not expanded.
-// a{2..}b -> a{2..}b
-// a{b}c -> a{b}c
-const braceExpand = (pattern, options = {}) => {
- (0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
- // Thanks to Yeting Li for
- // improving this regexp to avoid a ReDOS vulnerability.
- if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
- // shortcut. no need to expand.
- return [pattern];
- }
- return (0, brace_expansion_1.default)(pattern);
-};
-exports.braceExpand = braceExpand;
-exports.minimatch.braceExpand = exports.braceExpand;
-// 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
-// pattern, split on '/', and then turned into a regular expression.
-// A regexp is made at the end which joins each array with an
-// escaped /, and another full one which joins each regexp with |.
-//
-// Following the lead of Bash 4.1, note that "**" only has special meaning
-// when it is the *only* thing in a path portion. Otherwise, any series
-// of * is equivalent to a single *. Globstar behavior is enabled by
-// default, and can be disabled by setting options.noglobstar.
-const makeRe = (pattern, options = {}) => new Minimatch(pattern, options).makeRe();
-exports.makeRe = makeRe;
-exports.minimatch.makeRe = exports.makeRe;
-const match = (list, pattern, options = {}) => {
- const mm = new Minimatch(pattern, options);
- list = list.filter(f => mm.match(f));
- if (mm.options.nonull && !list.length) {
- list.push(pattern);
- }
- return list;
-};
-exports.match = match;
-exports.minimatch.match = exports.match;
-// replace stuff like \* with *
-const globMagic = /[?*]|[+@!]\(.*?\)|\[|\]/;
-const regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
-class Minimatch {
- options;
- set;
- pattern;
- windowsPathsNoEscape;
- nonegate;
- negate;
- comment;
- empty;
- preserveMultipleSlashes;
- partial;
- globSet;
- globParts;
- nocase;
- isWindows;
- platform;
- windowsNoMagicRoot;
- regexp;
- constructor(pattern, options = {}) {
- (0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
- options = options || {};
- this.options = options;
- this.pattern = pattern;
- this.platform = options.platform || defaultPlatform;
- this.isWindows = this.platform === 'win32';
- this.windowsPathsNoEscape =
- !!options.windowsPathsNoEscape || options.allowWindowsEscape === false;
- if (this.windowsPathsNoEscape) {
- this.pattern = this.pattern.replace(/\\/g, '/');
- }
- this.preserveMultipleSlashes = !!options.preserveMultipleSlashes;
- this.regexp = null;
- this.negate = false;
- this.nonegate = !!options.nonegate;
- this.comment = false;
- this.empty = false;
- this.partial = !!options.partial;
- this.nocase = !!this.options.nocase;
- this.windowsNoMagicRoot =
- options.windowsNoMagicRoot !== undefined
- ? options.windowsNoMagicRoot
- : !!(this.isWindows && this.nocase);
- this.globSet = [];
- this.globParts = [];
- this.set = [];
- // make the set of regexps etc.
- this.make();
- }
- hasMagic() {
- if (this.options.magicalBraces && this.set.length > 1) {
- return true;
- }
- for (const pattern of this.set) {
- for (const part of pattern) {
- if (typeof part !== 'string')
- return true;
- }
- }
- return false;
- }
- debug(..._) { }
- make() {
- const pattern = this.pattern;
- const options = this.options;
- // empty patterns and comments match nothing.
- if (!options.nocomment && pattern.charAt(0) === '#') {
- this.comment = true;
- return;
- }
- if (!pattern) {
- this.empty = true;
- return;
- }
- // step 1: figure out negation, etc.
- this.parseNegate();
- // step 2: expand braces
- this.globSet = [...new Set(this.braceExpand())];
- if (options.debug) {
- this.debug = (...args) => console.error(...args);
- }
- this.debug(this.pattern, this.globSet);
- // step 3: now we have a set, so turn each one into a series of
- // path-portion matching patterns.
- // These will be regexps, except in the case of "**", which is
- // set to the GLOBSTAR object for globstar behavior,
- // and will not contain any / characters
- //
- // First, we preprocess to make the glob pattern sets a bit simpler
- // and deduped. There are some perf-killing patterns that can cause
- // problems with a glob walk, but we can simplify them down a bit.
- const rawGlobParts = this.globSet.map(s => this.slashSplit(s));
- this.globParts = this.preprocess(rawGlobParts);
- this.debug(this.pattern, this.globParts);
- // glob --> regexps
- let set = this.globParts.map((s, _, __) => {
- if (this.isWindows && this.windowsNoMagicRoot) {
- // check if it's a drive or unc path.
- const isUNC = s[0] === '' &&
- s[1] === '' &&
- (s[2] === '?' || !globMagic.test(s[2])) &&
- !globMagic.test(s[3]);
- const isDrive = /^[a-z]:/i.test(s[0]);
- if (isUNC) {
- return [...s.slice(0, 4), ...s.slice(4).map(ss => this.parse(ss))];
- }
- else if (isDrive) {
- return [s[0], ...s.slice(1).map(ss => this.parse(ss))];
- }
- }
- return s.map(ss => this.parse(ss));
- });
- this.debug(this.pattern, set);
- // filter out everything that didn't compile properly.
- this.set = set.filter(s => s.indexOf(false) === -1);
- // do not treat the ? in UNC paths as magic
- if (this.isWindows) {
- for (let i = 0; i < this.set.length; i++) {
- const p = this.set[i];
- if (p[0] === '' &&
- p[1] === '' &&
- this.globParts[i][2] === '?' &&
- typeof p[3] === 'string' &&
- /^[a-z]:$/i.test(p[3])) {
- p[2] = '?';
- }
- }
- }
- this.debug(this.pattern, this.set);
- }
- // various transforms to equivalent pattern sets that are
- // faster to process in a filesystem walk. The goal is to
- // eliminate what we can, and push all ** patterns as far
- // to the right as possible, even if it increases the number
- // of patterns that we have to process.
- preprocess(globParts) {
- // if we're not in globstar mode, then turn all ** into *
- if (this.options.noglobstar) {
- for (let i = 0; i < globParts.length; i++) {
- for (let j = 0; j < globParts[i].length; j++) {
- if (globParts[i][j] === '**') {
- globParts[i][j] = '*';
- }
- }
- }
- }
- const { optimizationLevel = 1 } = this.options;
- if (optimizationLevel >= 2) {
- // aggressive optimization for the purpose of fs walking
- globParts = this.firstPhasePreProcess(globParts);
- globParts = this.secondPhasePreProcess(globParts);
- }
- else if (optimizationLevel >= 1) {
- // just basic optimizations to remove some .. parts
- globParts = this.levelOneOptimize(globParts);
- }
- else {
- globParts = this.adjascentGlobstarOptimize(globParts);
- }
- return globParts;
- }
- // just get rid of adjascent ** portions
- adjascentGlobstarOptimize(globParts) {
- return globParts.map(parts => {
- let gs = -1;
- while (-1 !== (gs = parts.indexOf('**', gs + 1))) {
- let i = gs;
- while (parts[i + 1] === '**') {
- i++;
- }
- if (i !== gs) {
- parts.splice(gs, i - gs);
- }
- }
- return parts;
- });
- }
- // get rid of adjascent ** and resolve .. portions
- levelOneOptimize(globParts) {
- return globParts.map(parts => {
- parts = parts.reduce((set, part) => {
- const prev = set[set.length - 1];
- if (part === '**' && prev === '**') {
- return set;
- }
- if (part === '..') {
- if (prev && prev !== '..' && prev !== '.' && prev !== '**') {
- set.pop();
- return set;
- }
- }
- set.push(part);
- return set;
- }, []);
- return parts.length === 0 ? [''] : parts;
- });
- }
- levelTwoFileOptimize(parts) {
- if (!Array.isArray(parts)) {
- parts = this.slashSplit(parts);
- }
- let didSomething = false;
- do {
- didSomething = false;
- // // -> /
- if (!this.preserveMultipleSlashes) {
- for (let i = 1; i < parts.length - 1; i++) {
- const p = parts[i];
- // don't squeeze out UNC patterns
- if (i === 1 && p === '' && parts[0] === '')
- continue;
- if (p === '.' || p === '') {
- didSomething = true;
- parts.splice(i, 1);
- i--;
- }
- }
- if (parts[0] === '.' &&
- parts.length === 2 &&
- (parts[1] === '.' || parts[1] === '')) {
- didSomething = true;
- parts.pop();
- }
- }
- // //../ -> /
- let dd = 0;
- while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
- const p = parts[dd - 1];
- if (p && p !== '.' && p !== '..' && p !== '**') {
- didSomething = true;
- parts.splice(dd - 1, 2);
- dd -= 2;
- }
- }
- } while (didSomething);
- return parts.length === 0 ? [''] : parts;
- }
- // First phase: single-pattern processing
- // is 1 or more portions
- // is 1 or more portions
- // is any portion other than ., .., '', or **
- // is . or ''
- //
- // **/.. is *brutal* for filesystem walking performance, because
- // it effectively resets the recursive walk each time it occurs,
- // and ** cannot be reduced out by a .. pattern part like a regexp
- // or most strings (other than .., ., and '') can be.
- //
- // /**/..//
/ -> {/..//
/,/**//
/}
- // // -> /
- // //../ -> /
- // **/**/ -> **/
- //
- // **/*/