Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
index.js1127 linesDownload Raw Back to commonjs
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.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;
4const brace_expansion_1 = require("brace-expansion");
5const assert_valid_pattern_js_1 = require("./assert-valid-pattern.js");
6const ast_js_1 = require("./ast.js");
7const escape_js_1 = require("./escape.js");
8const unescape_js_1 = require("./unescape.js");
9const minimatch = (p, pattern, options = {}) => {
10    (0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
11    // shortcut: comments match nothing.
12    if (!options.nocomment && pattern.charAt(0) === '#') {
13        return false;
14    }
15    return new Minimatch(pattern, options).match(p);
16};
17exports.minimatch = minimatch;
18// Optimized checking for the most common glob patterns.
19const starDotExtRE = /^\*+([^+@!?*[(]*)$/;
20const starDotExtTest = (ext) => (f) => !f.startsWith('.') && f.endsWith(ext);
21const starDotExtTestDot = (ext) => (f) => f.endsWith(ext);
22const starDotExtTestNocase = (ext) => {
23    ext = ext.toLowerCase();
24    return (f) => !f.startsWith('.') && f.toLowerCase().endsWith(ext);
25};
26const starDotExtTestNocaseDot = (ext) => {
27    ext = ext.toLowerCase();
28    return (f) => f.toLowerCase().endsWith(ext);
29};
30const starDotStarRE = /^\*+\.\*+$/;
31const starDotStarTest = (f) => !f.startsWith('.') && f.includes('.');
32const starDotStarTestDot = (f) => f !== '.' && f !== '..' && f.includes('.');
33const dotStarRE = /^\.\*+$/;
34const dotStarTest = (f) => f !== '.' && f !== '..' && f.startsWith('.');
35const starRE = /^\*+$/;
36const starTest = (f) => f.length !== 0 && !f.startsWith('.');
37const starTestDot = (f) => f.length !== 0 && f !== '.' && f !== '..';
38const qmarksRE = /^\?+([^+@!?*[(]*)?$/;
39const qmarksTestNocase = ([$0, ext = '']) => {
40    const noext = qmarksTestNoExt([$0]);
41    if (!ext)
42        return noext;
43    ext = ext.toLowerCase();
44    return (f) => noext(f) && f.toLowerCase().endsWith(ext);
45};
46const qmarksTestNocaseDot = ([$0, ext = '']) => {
47    const noext = qmarksTestNoExtDot([$0]);
48    if (!ext)
49        return noext;
50    ext = ext.toLowerCase();
51    return (f) => noext(f) && f.toLowerCase().endsWith(ext);
52};
53const qmarksTestDot = ([$0, ext = '']) => {
54    const noext = qmarksTestNoExtDot([$0]);
55    return !ext ? noext : (f) => noext(f) && f.endsWith(ext);
56};
57const qmarksTest = ([$0, ext = '']) => {
58    const noext = qmarksTestNoExt([$0]);
59    return !ext ? noext : (f) => noext(f) && f.endsWith(ext);
60};
61const qmarksTestNoExt = ([$0]) => {
62    const len = $0.length;
63    return (f) => f.length === len && !f.startsWith('.');
64};
65const qmarksTestNoExtDot = ([$0]) => {
66    const len = $0.length;
67    return (f) => f.length === len && f !== '.' && f !== '..';
68};
69/* c8 ignore start */
70const defaultPlatform = (typeof process === 'object' && process ?
71    (typeof process.env === 'object' &&
72        process.env &&
73        process.env.__MINIMATCH_TESTING_PLATFORM__) ||
74        process.platform
75    : 'posix');
76const path = {
77    win32: { sep: '\\' },
78    posix: { sep: '/' },
79};
80/* c8 ignore stop */
81exports.sep = defaultPlatform === 'win32' ? path.win32.sep : path.posix.sep;
82exports.minimatch.sep = exports.sep;
83exports.GLOBSTAR = Symbol('globstar **');
84exports.minimatch.GLOBSTAR = exports.GLOBSTAR;
85// any single thing other than /
86// don't need to escape / when using new RegExp()
87const qmark = '[^/]';
88// * => any number of characters
89const star = qmark + '*?';
90// ** when dots are allowed.  Anything goes, except .. and .
91// not (^ or / followed by one or two dots followed by $ or /),
92// followed by anything, any number of times.
93const twoStarDot = '(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?';
94// not a ^ or / followed by a dot,
95// followed by anything, any number of times.
96const twoStarNoDot = '(?:(?!(?:\\/|^)\\.).)*?';
97const filter = (pattern, options = {}) => (p) => (0, exports.minimatch)(p, pattern, options);
98exports.filter = filter;
99exports.minimatch.filter = exports.filter;
100const ext = (a, b = {}) => Object.assign({}, a, b);
101const defaults = (def) => {
102    if (!def || typeof def !== 'object' || !Object.keys(def).length) {
103        return exports.minimatch;
104    }
105    const orig = exports.minimatch;
106    const m = (p, pattern, options = {}) => orig(p, pattern, ext(def, options));
107    return Object.assign(m, {
108        Minimatch: class Minimatch extends orig.Minimatch {
109            constructor(pattern, options = {}) {
110                super(pattern, ext(def, options));
111            }
112            static defaults(options) {
113                return orig.defaults(ext(def, options)).Minimatch;
114            }
115        },
116        AST: class AST extends orig.AST {
117            /* c8 ignore start */
118            constructor(type, parent, options = {}) {
119                super(type, parent, ext(def, options));
120            }
121            /* c8 ignore stop */
122            static fromGlob(pattern, options = {}) {
123                return orig.AST.fromGlob(pattern, ext(def, options));
124            }
125        },
126        unescape: (s, options = {}) => orig.unescape(s, ext(def, options)),
127        escape: (s, options = {}) => orig.escape(s, ext(def, options)),
128        filter: (pattern, options = {}) => orig.filter(pattern, ext(def, options)),
129        defaults: (options) => orig.defaults(ext(def, options)),
130        makeRe: (pattern, options = {}) => orig.makeRe(pattern, ext(def, options)),
131        braceExpand: (pattern, options = {}) => orig.braceExpand(pattern, ext(def, options)),
132        match: (list, pattern, options = {}) => orig.match(list, pattern, ext(def, options)),
133        sep: orig.sep,
134        GLOBSTAR: exports.GLOBSTAR,
135    });
136};
137exports.defaults = defaults;
138exports.minimatch.defaults = exports.defaults;
139// Brace expansion:
140// a{b,c}d -> abd acd
141// a{b,}c -> abc ac
142// a{0..3}d -> a0d a1d a2d a3d
143// a{b,c{d,e}f}g -> abg acdfg acefg
144// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
145//
146// Invalid sets are not expanded.
147// a{2..}b -> a{2..}b
148// a{b}c -> a{b}c
149const braceExpand = (pattern, options = {}) => {
150    (0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
151    // Thanks to Yeting Li <https://github.com/yetingli> for
152    // improving this regexp to avoid a ReDOS vulnerability.
153    if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
154        // shortcut. no need to expand.
155        return [pattern];
156    }
157    return (0, brace_expansion_1.expand)(pattern, { max: options.braceExpandMax });
158};
159exports.braceExpand = braceExpand;
160exports.minimatch.braceExpand = exports.braceExpand;
161// parse a component of the expanded set.
162// At this point, no pattern may contain "/" in it
163// so we're going to return a 2d array, where each entry is the full
164// pattern, split on '/', and then turned into a regular expression.
165// A regexp is made at the end which joins each array with an
166// escaped /, and another full one which joins each regexp with |.
167//
168// Following the lead of Bash 4.1, note that "**" only has special meaning
169// when it is the *only* thing in a path portion.  Otherwise, any series
170// of * is equivalent to a single *.  Globstar behavior is enabled by
171// default, and can be disabled by setting options.noglobstar.
172const makeRe = (pattern, options = {}) => new Minimatch(pattern, options).makeRe();
173exports.makeRe = makeRe;
174exports.minimatch.makeRe = exports.makeRe;
175const match = (list, pattern, options = {}) => {
176    const mm = new Minimatch(pattern, options);
177    list = list.filter(f => mm.match(f));
178    if (mm.options.nonull && !list.length) {
179        list.push(pattern);
180    }
181    return list;
182};
183exports.match = match;
184exports.minimatch.match = exports.match;
185// replace stuff like \* with *
186const globMagic = /[?*]|[+@!]\(.*?\)|\[|\]/;
187const regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
188class Minimatch {
189    options;
190    set;
191    pattern;
192    windowsPathsNoEscape;
193    nonegate;
194    negate;
195    comment;
196    empty;
197    preserveMultipleSlashes;
198    partial;
199    globSet;
200    globParts;
201    nocase;
202    isWindows;
203    platform;
204    windowsNoMagicRoot;
205    maxGlobstarRecursion;
206    regexp;
207    constructor(pattern, options = {}) {
208        (0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
209        options = options || {};
210        this.options = options;
211        this.maxGlobstarRecursion = options.maxGlobstarRecursion ?? 200;
212        this.pattern = pattern;
213        this.platform = options.platform || defaultPlatform;
214        this.isWindows = this.platform === 'win32';
215        // avoid the annoying deprecation flag lol
216        const awe = ('allowWindow' + 'sEscape');
217        this.windowsPathsNoEscape =
218            !!options.windowsPathsNoEscape || options[awe] === false;
219        if (this.windowsPathsNoEscape) {
220            this.pattern = this.pattern.replace(/\\/g, '/');
221        }
222        this.preserveMultipleSlashes = !!options.preserveMultipleSlashes;
223        this.regexp = null;
224        this.negate = false;
225        this.nonegate = !!options.nonegate;
226        this.comment = false;
227        this.empty = false;
228        this.partial = !!options.partial;
229        this.nocase = !!this.options.nocase;
230        this.windowsNoMagicRoot =
231            options.windowsNoMagicRoot !== undefined ?
232                options.windowsNoMagicRoot
233                : !!(this.isWindows && this.nocase);
234        this.globSet = [];
235        this.globParts = [];
236        this.set = [];
237        // make the set of regexps etc.
238        this.make();
239    }
240    hasMagic() {
241        if (this.options.magicalBraces && this.set.length > 1) {
242            return true;
243        }
244        for (const pattern of this.set) {
245            for (const part of pattern) {
246                if (typeof part !== 'string')
247                    return true;
248            }
249        }
250        return false;
251    }
252    debug(..._) { }
253    make() {
254        const pattern = this.pattern;
255        const options = this.options;
256        // empty patterns and comments match nothing.
257        if (!options.nocomment && pattern.charAt(0) === '#') {
258            this.comment = true;
259            return;
260        }
261        if (!pattern) {
262            this.empty = true;
263            return;
264        }
265        // step 1: figure out negation, etc.
266        this.parseNegate();
267        // step 2: expand braces
268        this.globSet = [...new Set(this.braceExpand())];
269        if (options.debug) {
270            //oxlint-disable-next-line no-console
271            this.debug = (...args) => console.error(...args);
272        }
273        this.debug(this.pattern, this.globSet);
274        // step 3: now we have a set, so turn each one into a series of
275        // path-portion matching patterns.
276        // These will be regexps, except in the case of "**", which is
277        // set to the GLOBSTAR object for globstar behavior,
278        // and will not contain any / characters
279        //
280        // First, we preprocess to make the glob pattern sets a bit simpler
281        // and deduped.  There are some perf-killing patterns that can cause
282        // problems with a glob walk, but we can simplify them down a bit.
283        const rawGlobParts = this.globSet.map(s => this.slashSplit(s));
284        this.globParts = this.preprocess(rawGlobParts);
285        this.debug(this.pattern, this.globParts);
286        // glob --> regexps
287        let set = this.globParts.map((s, _, __) => {
288            if (this.isWindows && this.windowsNoMagicRoot) {
289                // check if it's a drive or unc path.
290                const isUNC = s[0] === '' &&
291                    s[1] === '' &&
292                    (s[2] === '?' || !globMagic.test(s[2])) &&
293                    !globMagic.test(s[3]);
294                const isDrive = /^[a-z]:/i.test(s[0]);
295                if (isUNC) {
296                    return [
297                        ...s.slice(0, 4),
298                        ...s.slice(4).map(ss => this.parse(ss)),
299                    ];
300                }
301                else if (isDrive) {
302                    return [s[0], ...s.slice(1).map(ss => this.parse(ss))];
303                }
304            }
305            return s.map(ss => this.parse(ss));
306        });
307        this.debug(this.pattern, set);
308        // filter out everything that didn't compile properly.
309        this.set = set.filter(s => s.indexOf(false) === -1);
310        // do not treat the ? in UNC paths as magic
311        if (this.isWindows) {
312            for (let i = 0; i < this.set.length; i++) {
313                const p = this.set[i];
314                if (p[0] === '' &&
315                    p[1] === '' &&
316                    this.globParts[i][2] === '?' &&
317                    typeof p[3] === 'string' &&
318                    /^[a-z]:$/i.test(p[3])) {
319                    p[2] = '?';
320                }
321            }
322        }
323        this.debug(this.pattern, this.set);
324    }
325    // various transforms to equivalent pattern sets that are
326    // faster to process in a filesystem walk.  The goal is to
327    // eliminate what we can, and push all ** patterns as far
328    // to the right as possible, even if it increases the number
329    // of patterns that we have to process.
330    preprocess(globParts) {
331        // if we're not in globstar mode, then turn ** into *
332        if (this.options.noglobstar) {
333            for (const partset of globParts) {
334                for (let j = 0; j < partset.length; j++) {
335                    if (partset[j] === '**') {
336                        partset[j] = '*';
337                    }
338                }
339            }
340        }
341        const { optimizationLevel = 1 } = this.options;
342        if (optimizationLevel >= 2) {
343            // aggressive optimization for the purpose of fs walking
344            globParts = this.firstPhasePreProcess(globParts);
345            globParts = this.secondPhasePreProcess(globParts);
346        }
347        else if (optimizationLevel >= 1) {
348            // just basic optimizations to remove some .. parts
349            globParts = this.levelOneOptimize(globParts);
350        }
351        else {
352            // just collapse multiple ** portions into one
353            globParts = this.adjascentGlobstarOptimize(globParts);
354        }
355        return globParts;
356    }
357    // just get rid of adjascent ** portions
358    adjascentGlobstarOptimize(globParts) {
359        return globParts.map(parts => {
360            let gs = -1;
361            while (-1 !== (gs = parts.indexOf('**', gs + 1))) {
362                let i = gs;
363                while (parts[i + 1] === '**') {
364                    i++;
365                }
366                if (i !== gs) {
367                    parts.splice(gs, i - gs);
368                }
369            }
370            return parts;
371        });
372    }
373    // get rid of adjascent ** and resolve .. portions
374    levelOneOptimize(globParts) {
375        return globParts.map(parts => {
376            parts = parts.reduce((set, part) => {
377                const prev = set[set.length - 1];
378                if (part === '**' && prev === '**') {
379                    return set;
380                }
381                if (part === '..') {
382                    if (prev && prev !== '..' && prev !== '.' && prev !== '**') {
383                        set.pop();
384                        return set;
385                    }
386                }
387                set.push(part);
388                return set;
389            }, []);
390            return parts.length === 0 ? [''] : parts;
391        });
392    }
393    levelTwoFileOptimize(parts) {
394        if (!Array.isArray(parts)) {
395            parts = this.slashSplit(parts);
396        }
397        let didSomething = false;
398        do {
399            didSomething = false;
400            // <pre>/<e>/<rest> -> <pre>/<rest>
401            if (!this.preserveMultipleSlashes) {
402                for (let i = 1; i < parts.length - 1; i++) {
403                    const p = parts[i];
404                    // don't squeeze out UNC patterns
405                    if (i === 1 && p === '' && parts[0] === '')
406                        continue;
407                    if (p === '.' || p === '') {
408                        didSomething = true;
409                        parts.splice(i, 1);
410                        i--;
411                    }
412                }
413                if (parts[0] === '.' &&
414                    parts.length === 2 &&
415                    (parts[1] === '.' || parts[1] === '')) {
416                    didSomething = true;
417                    parts.pop();
418                }
419            }
420            // <pre>/<p>/../<rest> -> <pre>/<rest>
421            let dd = 0;
422            while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
423                const p = parts[dd - 1];
424                if (p &&
425                    p !== '.' &&
426                    p !== '..' &&
427                    p !== '**' &&
428                    !(this.isWindows && /^[a-z]:$/i.test(p))) {
429                    didSomething = true;
430                    parts.splice(dd - 1, 2);
431                    dd -= 2;
432                }
433            }
434        } while (didSomething);
435        return parts.length === 0 ? [''] : parts;
436    }
437    // First phase: single-pattern processing
438    // <pre> is 1 or more portions
439    // <rest> is 1 or more portions
440    // <p> is any portion other than ., .., '', or **
441    // <e> is . or ''
442    //
443    // **/.. is *brutal* for filesystem walking performance, because
444    // it effectively resets the recursive walk each time it occurs,
445    // and ** cannot be reduced out by a .. pattern part like a regexp
446    // or most strings (other than .., ., and '') can be.
447    //
448    // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}
449    // <pre>/<e>/<rest> -> <pre>/<rest>
450    // <pre>/<p>/../<rest> -> <pre>/<rest>
451    // **/**/<rest> -> **/<rest>
452    //
453    // **/*/<rest> -> */**/<rest> <== not valid because ** doesn't follow
454    // this WOULD be allowed if ** did follow symlinks, or * didn't
455    firstPhasePreProcess(globParts) {
456        let didSomething = false;
457        do {
458            didSomething = false;
459            // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}
460            for (let parts of globParts) {
461                let gs = -1;
462                while (-1 !== (gs = parts.indexOf('**', gs + 1))) {
463                    let gss = gs;
464                    while (parts[gss + 1] === '**') {
465                        // <pre>/**/**/<rest> -> <pre>/**/<rest>
466                        gss++;
467                    }
468                    // eg, if gs is 2 and gss is 4, that means we have 3 **
469                    // parts, and can remove 2 of them.
470                    if (gss > gs) {
471                        parts.splice(gs + 1, gss - gs);
472                    }
473                    let next = parts[gs + 1];
474                    const p = parts[gs + 2];
475                    const p2 = parts[gs + 3];
476                    if (next !== '..')
477                        continue;
478                    if (!p ||
479                        p === '.' ||
480                        p === '..' ||
481                        !p2 ||
482                        p2 === '.' ||
483                        p2 === '..') {
484                        continue;
485                    }
486                    didSomething = true;
487                    // edit parts in place, and push the new one
488                    parts.splice(gs, 1);
489                    const other = parts.slice(0);
490                    other[gs] = '**';
491                    globParts.push(other);
492                    gs--;
493                }
494                // <pre>/<e>/<rest> -> <pre>/<rest>
495                if (!this.preserveMultipleSlashes) {
496                    for (let i = 1; i < parts.length - 1; i++) {
497                        const p = parts[i];
498                        // don't squeeze out UNC patterns
499                        if (i === 1 && p === '' && parts[0] === '')
500                            continue;
501                        if (p === '.' || p === '') {
502                            didSomething = true;
503                            parts.splice(i, 1);
504                            i--;
505                        }
506                    }
507                    if (parts[0] === '.' &&
508                        parts.length === 2 &&
509                        (parts[1] === '.' || parts[1] === '')) {
510                        didSomething = true;
511                        parts.pop();
512                    }
513                }
514                // <pre>/<p>/../<rest> -> <pre>/<rest>
515                let dd = 0;
516                while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
517                    const p = parts[dd - 1];
518                    if (p && p !== '.' && p !== '..' && p !== '**') {
519                        didSomething = true;
520                        const needDot = dd === 1 && parts[dd + 1] === '**';
521                        const splin = needDot ? ['.'] : [];
522                        parts.splice(dd - 1, 2, ...splin);
523                        if (parts.length === 0)
524                            parts.push('');
525                        dd -= 2;
526                    }
527                }
528            }
529        } while (didSomething);
530        return globParts;
531    }
532    // second phase: multi-pattern dedupes
533    // {<pre>/*/<rest>,<pre>/<p>/<rest>} -> <pre>/*/<rest>
534    // {<pre>/<rest>,<pre>/<rest>} -> <pre>/<rest>
535    // {<pre>/**/<rest>,<pre>/<rest>} -> <pre>/**/<rest>
536    //
537    // {<pre>/**/<rest>,<pre>/**/<p>/<rest>} -> <pre>/**/<rest>
538    // ^-- not valid because ** doens't follow symlinks
539    secondPhasePreProcess(globParts) {
540        for (let i = 0; i < globParts.length - 1; i++) {
541            for (let j = i + 1; j < globParts.length; j++) {
542                const matched = this.partsMatch(globParts[i], globParts[j], !this.preserveMultipleSlashes);
543                if (matched) {
544                    globParts[i] = [];
545                    globParts[j] = matched;
546                    break;
547                }
548            }
549        }
550        return globParts.filter(gs => gs.length);
551    }
552    partsMatch(a, b, emptyGSMatch = false) {
553        let ai = 0;
554        let bi = 0;
555        let result = [];
556        let which = '';
557        while (ai < a.length && bi < b.length) {
558            if (a[ai] === b[bi]) {
559                result.push(which === 'b' ? b[bi] : a[ai]);
560                ai++;
561                bi++;
562            }
563            else if (emptyGSMatch && a[ai] === '**' && b[bi] === a[ai + 1]) {
564                result.push(a[ai]);
565                ai++;
566            }
567            else if (emptyGSMatch && b[bi] === '**' && a[ai] === b[bi + 1]) {
568                result.push(b[bi]);
569                bi++;
570            }
571            else if (a[ai] === '*' &&
572                b[bi] &&
573                (this.options.dot || !b[bi].startsWith('.')) &&
574                b[bi] !== '**') {
575                if (which === 'b')
576                    return false;
577                which = 'a';
578                result.push(a[ai]);
579                ai++;
580                bi++;
581            }
582            else if (b[bi] === '*' &&
583                a[ai] &&
584                (this.options.dot || !a[ai].startsWith('.')) &&
585                a[ai] !== '**') {
586                if (which === 'a')
587                    return false;
588                which = 'b';
589                result.push(b[bi]);
590                ai++;
591                bi++;
592            }
593            else {
594                return false;
595            }
596        }
597        // if we fall out of the loop, it means they two are identical
598        // as long as their lengths match
599        return a.length === b.length && result;
600    }
601    parseNegate() {
602        if (this.nonegate)
603            return;
604        const pattern = this.pattern;
605        let negate = false;
606        let negateOffset = 0;
607        for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {
608            negate = !negate;
609            negateOffset++;
610        }
611        if (negateOffset)
612            this.pattern = pattern.slice(negateOffset);
613        this.negate = negate;
614    }
615    // set partial to true to test if, for example,
616    // "/a/b" matches the start of "/*/b/*/d"
617    // Partial means, if you run out of file before you run
618    // out of pattern, then that's fine, as long as all
619    // the parts match.
620    matchOne(file, pattern, partial = false) {
621        let fileStartIndex = 0;
622        let patternStartIndex = 0;
623        // UNC paths like //?/X:/... can match X:/... and vice versa
624        // Drive letters in absolute drive or unc paths are always compared
625        // case-insensitively.
626        if (this.isWindows) {
627            const fileDrive = typeof file[0] === 'string' && /^[a-z]:$/i.test(file[0]);
628            const fileUNC = !fileDrive &&
629                file[0] === '' &&
630                file[1] === '' &&
631                file[2] === '?' &&
632                /^[a-z]:$/i.test(file[3]);
633            const patternDrive = typeof pattern[0] === 'string' && /^[a-z]:$/i.test(pattern[0]);
634            const patternUNC = !patternDrive &&
635                pattern[0] === '' &&
636                pattern[1] === '' &&
637                pattern[2] === '?' &&
638                typeof pattern[3] === 'string' &&
639                /^[a-z]:$/i.test(pattern[3]);
640            const fdi = fileUNC ? 3
641                : fileDrive ? 0
642                    : undefined;
643            const pdi = patternUNC ? 3
644                : patternDrive ? 0
645                    : undefined;
646            if (typeof fdi === 'number' && typeof pdi === 'number') {
647                const [fd, pd] = [
648                    file[fdi],
649                    pattern[pdi],
650                ];
651                // start matching at the drive letter index of each
652                if (fd.toLowerCase() === pd.toLowerCase()) {
653                    pattern[pdi] = fd;
654                    patternStartIndex = pdi;
655                    fileStartIndex = fdi;
656                }
657            }
658        }
659        // resolve and reduce . and .. portions in the file as well.
660        // don't need to do the second phase, because it's only one string[]
661        const { optimizationLevel = 1 } = this.options;
662        if (optimizationLevel >= 2) {
663            file = this.levelTwoFileOptimize(file);
664        }
665        if (pattern.includes(exports.GLOBSTAR)) {
666            return this.#matchGlobstar(file, pattern, partial, fileStartIndex, patternStartIndex);
667        }
668        return this.#matchOne(file, pattern, partial, fileStartIndex, patternStartIndex);
669    }
670    #matchGlobstar(file, pattern, partial, fileIndex, patternIndex) {
671        // split the pattern into head, tail, and middle of ** delimited parts
672        const firstgs = pattern.indexOf(exports.GLOBSTAR, patternIndex);
673        const lastgs = pattern.lastIndexOf(exports.GLOBSTAR);
674        // split the pattern up into globstar-delimited sections
675        // the tail has to be at the end, and the others just have
676        // to be found in order from the head.
677        const [head, body, tail] = partial ?
678            [
679                pattern.slice(patternIndex, firstgs),
680                pattern.slice(firstgs + 1),
681                [],
682            ]
683            : [
684                pattern.slice(patternIndex, firstgs),
685                pattern.slice(firstgs + 1, lastgs),
686                pattern.slice(lastgs + 1),
687            ];
688        // check the head, from the current file/pattern index.
689        if (head.length) {
690            const fileHead = file.slice(fileIndex, fileIndex + head.length);
691            if (!this.#matchOne(fileHead, head, partial, 0, 0)) {
692                return false;
693            }
694            fileIndex += head.length;
695            patternIndex += head.length;
696        }
697        // now we know the head matches!
698        // if the last portion is not empty, it MUST match the end
699        // check the tail
700        let fileTailMatch = 0;
701        if (tail.length) {
702            // if head + tail > file, then we cannot possibly match
703            if (tail.length + fileIndex > file.length)
704                return false;
705            // try to match the tail
706            let tailStart = file.length - tail.length;
707            if (this.#matchOne(file, tail, partial, tailStart, 0)) {
708                fileTailMatch = tail.length;
709            }
710            else {
711                // affordance for stuff like a/**/* matching a/b/
712                // if the last file portion is '', and there's more to the pattern
713                // then try without the '' bit.
714                if (file[file.length - 1] !== '' ||
715                    fileIndex + tail.length === file.length) {
716                    return false;
717                }
718                tailStart--;
719                if (!this.#matchOne(file, tail, partial, tailStart, 0)) {
720                    return false;
721                }
722                fileTailMatch = tail.length + 1;
723            }
724        }
725        // now we know the tail matches!
726        // the middle is zero or more portions wrapped in **, possibly
727        // containing more ** sections.
728        // so a/**/b/**/c/**/d has become **/b/**/c/**
729        // if it's empty, it means a/**/b, just verify we have no bad dots
730        // if there's no tail, so it ends on /**, then we must have *something*
731        // after the head, or it's not a matc
732        if (!body.length) {
733            let sawSome = !!fileTailMatch;
734            for (let i = fileIndex; i < file.length - fileTailMatch; i++) {
735                const f = String(file[i]);
736                sawSome = true;
737                if (f === '.' ||
738                    f === '..' ||
739                    (!this.options.dot && f.startsWith('.'))) {
740                    return false;
741                }
742            }
743            // in partial mode, we just need to get past all file parts
744            return partial || sawSome;
745        }
746        // now we know that there's one or more body sections, which can
747        // be matched anywhere from the 0 index (because the head was pruned)
748        // through to the length-fileTailMatch index.
749        // split the body up into sections, and note the minimum index it can
750        // be found at (start with the length of all previous segments)
751        // [section, before, after]
752        const bodySegments = [[[], 0]];
753        let currentBody = bodySegments[0];
754        let nonGsParts = 0;
755        const nonGsPartsSums = [0];
756        for (const b of body) {
757            if (b === exports.GLOBSTAR) {
758                nonGsPartsSums.push(nonGsParts);
759                currentBody = [[], 0];
760                bodySegments.push(currentBody);
761            }
762            else {
763                currentBody[0].push(b);
764                nonGsParts++;
765            }
766        }
767        let i = bodySegments.length - 1;
768        const fileLength = file.length - fileTailMatch;
769        for (const b of bodySegments) {
770            b[1] = fileLength - (nonGsPartsSums[i--] + b[0].length);
771        }
772        return !!this.#matchGlobStarBodySections(file, bodySegments, fileIndex, 0, partial, 0, !!fileTailMatch);
773    }
774    // return false for "nope, not matching"
775    // return null for "not matching, cannot keep trying"
776    #matchGlobStarBodySections(file,
777    // pattern section, last possible position for it
778    bodySegments, fileIndex, bodyIndex, partial, globStarDepth, sawTail) {
779        // take the first body segment, and walk from fileIndex to its "after"
780        // value at the end
781        // If it doesn't match at that position, we increment, until we hit
782        // that final possible position, and give up.
783        // If it does match, then advance and try to rest.
784        // If any of them fail we keep walking forward.
785        // this is still a bit recursively painful, but it's more constrained
786        // than previous implementations, because we never test something that
787        // can't possibly be a valid matching condition.
788        const bs = bodySegments[bodyIndex];
789        if (!bs) {
790            // just make sure that there's no bad dots
791            for (let i = fileIndex; i < file.length; i++) {
792                sawTail = true;
793                const f = file[i];
794                if (f === '.' ||
795                    f === '..' ||
796                    (!this.options.dot && f.startsWith('.'))) {
797                    return false;
798                }
799            }
800            return sawTail;
801        }
802        // have a non-globstar body section to test
803        const [body, after] = bs;
804        while (fileIndex <= after) {
805            const m = this.#matchOne(file.slice(0, fileIndex + body.length), body, partial, fileIndex, 0);
806            // if limit exceeded, no match. intentional false negative,
807            // acceptable break in correctness for security.
808            if (m && globStarDepth < this.maxGlobstarRecursion) {
809                // match! see if the rest match. if so, we're done!
810                const sub = this.#matchGlobStarBodySections(file, bodySegments, fileIndex + body.length, bodyIndex + 1, partial, globStarDepth + 1, sawTail);
811                if (sub !== false) {
812                    return sub;
813                }
814            }
815            const f = file[fileIndex];
816            if (f === '.' ||
817                f === '..' ||
818                (!this.options.dot && f.startsWith('.'))) {
819                return false;
820            }
821            fileIndex++;
822        }
823        // walked off. no point continuing
824        return partial || null;
825    }
826    #matchOne(file, pattern, partial, fileIndex, patternIndex) {
827        let fi;
828        let pi;
829        let pl;
830        let fl;
831        for (fi = fileIndex,
832            pi = patternIndex,
833            fl = file.length,
834            pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
835            this.debug('matchOne loop');
836            let p = pattern[pi];
837            let f = file[fi];
838            this.debug(pattern, p, f);
839            // should be impossible.
840            // some invalid regexp stuff in the set.
841            /* c8 ignore start */
842            if (p === false || p === exports.GLOBSTAR) {
843                return false;
844            }
845            /* c8 ignore stop */
846            // something other than **
847            // non-magic patterns just have to match exactly
848            // patterns with magic have been turned into regexps.
849            let hit;
850            if (typeof p === 'string') {
851                hit = f === p;
852                this.debug('string match', p, f, hit);
853            }
854            else {
855                hit = p.test(f);
856                this.debug('pattern match', p, f, hit);
857            }
858            if (!hit)
859                return false;
860        }
861        // Note: ending in / means that we'll get a final ""
862        // at the end of the pattern.  This can only match a
863        // corresponding "" at the end of the file.
864        // If the file ends in /, then it can only match a
865        // a pattern that ends in /, unless the pattern just
866        // doesn't have any more for it. But, a/b/ should *not*
867        // match "a/b/*", even though "" matches against the
868        // [^/]*? pattern, except in partial mode, where it might
869        // simply not be reached yet.
870        // However, a/b/ should still satisfy a/*
871        // now either we fell off the end of the pattern, or we're done.
872        if (fi === fl && pi === pl) {
873            // ran out of pattern and filename at the same time.
874            // an exact hit!
875            return true;
876        }
877        else if (fi === fl) {
878            // ran out of file, but still had pattern left.
879            // this is ok if we're doing the match as part of
880            // a glob fs traversal.
881            return partial;
882        }
883        else if (pi === pl) {
884            // ran out of pattern, still have file left.
885            // this is only acceptable if we're on the very last
886            // empty segment of a file with a trailing slash.
887            // a/* should match a/b/
888            return fi === fl - 1 && file[fi] === '';
889            /* c8 ignore start */
890        }
891        else {
892            // should be unreachable.
893            throw new Error('wtf?');
894        }
895        /* c8 ignore stop */
896    }
897    braceExpand() {
898        return (0, exports.braceExpand)(this.pattern, this.options);
899    }
900    parse(pattern) {
901        (0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
902        const options = this.options;
903        // shortcuts
904        if (pattern === '**')
905            return exports.GLOBSTAR;
906        if (pattern === '')
907            return '';
908        // far and away, the most common glob pattern parts are
909        // *, *.*, and *.<ext>  Add a fast check method for those.
910        let m;
911        let fastTest = null;
912        if ((m = pattern.match(starRE))) {
913            fastTest = options.dot ? starTestDot : starTest;
914        }
915        else if ((m = pattern.match(starDotExtRE))) {
916            fastTest = (options.nocase ?
917                options.dot ?
918                    starDotExtTestNocaseDot
919                    : starDotExtTestNocase
920                : options.dot ? starDotExtTestDot
921                    : starDotExtTest)(m[1]);
922        }
923        else if ((m = pattern.match(qmarksRE))) {
924            fastTest = (options.nocase ?
925                options.dot ?
926                    qmarksTestNocaseDot
927                    : qmarksTestNocase
928                : options.dot ? qmarksTestDot
929                    : qmarksTest)(m);
930        }
931        else if ((m = pattern.match(starDotStarRE))) {
932            fastTest = options.dot ? starDotStarTestDot : starDotStarTest;
933        }
934        else if ((m = pattern.match(dotStarRE))) {
935            fastTest = dotStarTest;
936        }
937        const re = ast_js_1.AST.fromGlob(pattern, this.options).toMMPattern();
938        if (fastTest && typeof re === 'object') {
939            // Avoids overriding in frozen environments
940            Reflect.defineProperty(re, 'test', { value: fastTest });
941        }
942        return re;
943    }
944    makeRe() {
945        if (this.regexp || this.regexp === false)
946            return this.regexp;
947        // at this point, this.set is a 2d array of partial
948        // pattern strings, or "**".
949        //
950        // It's better to use .match().  This function shouldn't
951        // be used, really, but it's pretty convenient sometimes,
952        // when you just want to work with a regex.
953        const set = this.set;
954        if (!set.length) {
955            this.regexp = false;
956            return this.regexp;
957        }
958        const options = this.options;
959        const twoStar = options.noglobstar ? star
960            : options.dot ? twoStarDot
961                : twoStarNoDot;
962        const flags = new Set(options.nocase ? ['i'] : []);
963        // regexpify non-globstar patterns
964        // if ** is only item, then we just do one twoStar
965        // if ** is first, and there are more, prepend (\/|twoStar\/)? to next
966        // if ** is last, append (\/twoStar|) to previous
967        // if ** is in the middle, append (\/|\/twoStar\/) to previous
968        // then filter out GLOBSTAR symbols
969        let re = set
970            .map(pattern => {
971            const pp = pattern.map(p => {
972                if (p instanceof RegExp) {
973                    for (const f of p.flags.split(''))
974                        flags.add(f);
975                }
976                return (typeof p === 'string' ? regExpEscape(p)
977                    : p === exports.GLOBSTAR ? exports.GLOBSTAR
978                        : p._src);
979            });
980            pp.forEach((p, i) => {
981                const next = pp[i + 1];
982                const prev = pp[i - 1];
983                if (p !== exports.GLOBSTAR || prev === exports.GLOBSTAR) {
984                    return;
985                }
986                if (prev === undefined) {
987                    if (next !== undefined && next !== exports.GLOBSTAR) {
988                        pp[i + 1] = '(?:\\/|' + twoStar + '\\/)?' + next;
989                    }
990                    else {
991                        pp[i] = twoStar;
992                    }
993                }
994                else if (next === undefined) {
995                    pp[i - 1] = prev + '(?:\\/|\\/' + twoStar + ')?';
996                }
997                else if (next !== exports.GLOBSTAR) {
998                    pp[i - 1] = prev + '(?:\\/|\\/' + twoStar + '\\/)' + next;
999                    pp[i + 1] = exports.GLOBSTAR;
1000                }
1001            });
1002            const filtered = pp.filter(p => p !== exports.GLOBSTAR);
1003            // For partial matches, we need to make the pattern match
1004            // any prefix of the full path. We do this by generating
1005            // alternative patterns that match progressively longer prefixes.
1006            if (this.partial && filtered.length >= 1) {
1007                const prefixes = [];
1008                for (let i = 1; i <= filtered.length; i++) {
1009                    prefixes.push(filtered.slice(0, i).join('/'));
1010                }
1011                return '(?:' + prefixes.join('|') + ')';
1012            }
1013            return filtered.join('/');
1014        })
1015            .join('|');
1016        // need to wrap in parens if we had more than one thing with |,
1017        // otherwise only the first will be anchored to ^ and the last to $
1018        const [open, close] = set.length > 1 ? ['(?:', ')'] : ['', ''];
1019        // must match entire pattern
1020        // ending in a * or ** will make it less strict.
1021        re = '^' + open + re + close + '$';
1022        // In partial mode, '/' should always match as it's a valid prefix for any pattern
1023        if (this.partial) {
1024            re = '^(?:\\/|' + open + re.slice(1, -1) + close + ')$';
1025        }
1026        // can match anything, as long as it's not this.
1027        if (this.negate)
1028            re = '^(?!' + re + ').+$';
1029        try {
1030            this.regexp = new RegExp(re, [...flags].join(''));
1031            /* c8 ignore start */
1032        }
1033        catch {
1034            // should be impossible
1035            this.regexp = false;
1036        }
1037        /* c8 ignore stop */
1038        return this.regexp;
1039    }
1040    slashSplit(p) {
1041        // if p starts with // on windows, we preserve that
1042        // so that UNC paths aren't broken.  Otherwise, any number of
1043        // / characters are coalesced into one, unless
1044        // preserveMultipleSlashes is set to true.
1045        if (this.preserveMultipleSlashes) {
1046            return p.split('/');
1047        }
1048        else if (this.isWindows && /^\/\/[^/]+/.test(p)) {
1049            // add an extra '' for the one we lose
1050            return ['', ...p.split(/\/+/)];
1051        }
1052        else {
1053            return p.split(/\/+/);
1054        }
1055    }
1056    match(f, partial = this.partial) {
1057        this.debug('match', f, this.pattern);
1058        // short-circuit in the case of busted things.
1059        // comments, etc.
1060        if (this.comment) {
1061            return false;
1062        }
1063        if (this.empty) {
1064            return f === '';
1065        }
1066        if (f === '/' && partial) {
1067            return true;
1068        }
1069        const options = this.options;
1070        // windows: need to use /, not \
1071        if (this.isWindows) {
1072            f = f.split('\\').join('/');
1073        }
1074        // treat the test path as a set of pathparts.
1075        const ff = this.slashSplit(f);
1076        this.debug(this.pattern, 'split', ff);
1077        // just ONE of the pattern sets in this.set needs to match
1078        // in order for it to be valid.  If negating, then just one
1079        // match means that we have failed.
1080        // Either way, return on the first hit.
1081        const set = this.set;
1082        this.debug(this.pattern, 'set', set);
1083        // Find the basename of the path by looking for the last non-empty segment
1084        let filename = ff[ff.length - 1];
1085        if (!filename) {
1086            for (let i = ff.length - 2; !filename && i >= 0; i--) {
1087                filename = ff[i];
1088            }
1089        }
1090        for (const pattern of set) {
1091            let file = ff;
1092            if (options.matchBase && pattern.length === 1) {
1093                file = [filename];
1094            }
1095            const hit = this.matchOne(file, pattern, partial);
1096            if (hit) {
1097                if (options.flipNegate) {
1098                    return true;
1099                }
1100                return !this.negate;
1101            }
1102        }
1103        // didn't get any hits.  this is success if it's a negative
1104        // pattern, failure otherwise.
1105        if (options.flipNegate) {
1106            return false;
1107        }
1108        return this.negate;
1109    }
1110    static defaults(def) {
1111        return exports.minimatch.defaults(def).Minimatch;
1112    }
1113}
1114exports.Minimatch = Minimatch;
1115/* c8 ignore start */
1116var ast_js_2 = require("./ast.js");
1117Object.defineProperty(exports, "AST", { enumerable: true, get: function () { return ast_js_2.AST; } });
1118var escape_js_2 = require("./escape.js");
1119Object.defineProperty(exports, "escape", { enumerable: true, get: function () { return escape_js_2.escape; } });
1120var unescape_js_2 = require("./unescape.js");
1121Object.defineProperty(exports, "unescape", { enumerable: true, get: function () { return unescape_js_2.unescape; } });
1122/* c8 ignore stop */
1123exports.minimatch.AST = ast_js_1.AST;
1124exports.minimatch.Minimatch = Minimatch;
1125exports.minimatch.escape = escape_js_1.escape;
1126exports.minimatch.unescape = unescape_js_1.unescape;
1127//# sourceMappingURL=index.js.map
codekingpro/portable-devtools · Team Ai