minimatch 6.2.0 → 7.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,799 @@
1
+ "use strict";
2
+ // this is a much more "mini" minimatch, optimized for use in a recursive
3
+ // glob walk.
4
+ //
5
+ // String parts of the pattern set are only parsed and used on demand,
6
+ // so that we don't have to bother parsing parts of the pattern that
7
+ // don't ever end up being used.
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.tokenize = exports.compile = exports.parsePattern = exports.Pattern = exports.braceExpand = exports.Mini = void 0;
13
+ const brace_expansion_1 = __importDefault(require("brace-expansion"));
14
+ const index_js_1 = require("./index.js");
15
+ /* c8 ignore start */
16
+ const defaultPlatform = typeof process === 'object' &&
17
+ !!process &&
18
+ typeof process.platform === 'string'
19
+ ? process.platform
20
+ : 'linux';
21
+ /* c8 ignore stop */
22
+ class Mini {
23
+ options;
24
+ globLists;
25
+ patterns;
26
+ dot;
27
+ nocase;
28
+ noext;
29
+ noglobstar;
30
+ nobrace;
31
+ windowsPathsNoEscape;
32
+ platform;
33
+ isWindows;
34
+ constructor(patterns, opts = {}) {
35
+ const { dot = false, nocase, noext = false, noglobstar = false, nobrace = false, windowsPathsNoEscape = false, platform = defaultPlatform, } = opts;
36
+ this.dot = dot;
37
+ this.noext = noext;
38
+ this.noglobstar = noglobstar;
39
+ this.nobrace = nobrace;
40
+ this.windowsPathsNoEscape = windowsPathsNoEscape;
41
+ this.platform = platform;
42
+ this.nocase =
43
+ nocase !== undefined
44
+ ? nocase
45
+ : this.platform === 'win32' || this.platform === 'darwin';
46
+ this.isWindows = this.platform === 'win32';
47
+ opts = {
48
+ dot: this.dot,
49
+ nocase: this.nocase,
50
+ noext: this.noext,
51
+ noglobstar: this.noglobstar,
52
+ nobrace: this.nobrace,
53
+ windowsPathsNoEscape: this.windowsPathsNoEscape,
54
+ platform: this.platform,
55
+ };
56
+ this.options = opts;
57
+ if (!patterns)
58
+ throw new TypeError('pattern required');
59
+ if (!Array.isArray(patterns))
60
+ patterns = [patterns];
61
+ if (opts.windowsPathsNoEscape) {
62
+ patterns = patterns.map(p => p.replace(/\\/g, '/'));
63
+ }
64
+ this.globLists = this.preprocess(patterns
65
+ .map(p => (0, exports.braceExpand)(p, this.options))
66
+ .reduce((ps, p) => ps.concat(p), [])
67
+ .map(p => this.splitGlobString(p))
68
+ .filter(gl => !!gl.length));
69
+ const parsed = new Map();
70
+ this.patterns = this.globLists.map(gl => new Pattern(gl, 0, parsed, opts));
71
+ }
72
+ splitGlobString(globString) {
73
+ const parts = globString.split('/');
74
+ // canonincalize UNC paths and drives, make the first
75
+ // pattern the whole root ending in / for absolute patterns.
76
+ if (this.isUNC(parts)) {
77
+ const [p0, p1, p2] = parts;
78
+ parts.shift();
79
+ parts.shift();
80
+ parts.shift();
81
+ parts.unshift([p0, p1, p2, ''].join('/').toUpperCase());
82
+ }
83
+ else if (this.isDrive(parts)) {
84
+ const drive = parts[0].toUpperCase() + '/';
85
+ parts.shift();
86
+ parts.unshift(drive);
87
+ }
88
+ else if (parts[0] === '') {
89
+ parts[0] = '/';
90
+ }
91
+ // now strip any empty parts
92
+ return parts.filter(p => !!p);
93
+ }
94
+ isDrive(pl) {
95
+ return (this.isWindows && typeof pl[0] === 'string' && /^[a-z]:$/i.test(pl[0]));
96
+ }
97
+ isUNC(pl) {
98
+ return (this.isWindows &&
99
+ pl[0] === '' &&
100
+ pl[1] === '' &&
101
+ typeof pl[2] === 'string' &&
102
+ !!pl[2] &&
103
+ typeof pl[3] === 'string' &&
104
+ !!pl[3]);
105
+ }
106
+ preprocess(globParts) {
107
+ // if we're not in globstar mode, then turn all ** into *
108
+ if (this.noglobstar) {
109
+ for (let i = 0; i < globParts.length; i++) {
110
+ for (let j = 0; j < globParts[i].length; j++) {
111
+ if (globParts[i][j] === '**') {
112
+ globParts[i][j] = '*';
113
+ }
114
+ }
115
+ }
116
+ }
117
+ globParts = this.firstPhasePreProcess(globParts);
118
+ globParts = this.secondPhasePreProcess(globParts);
119
+ return globParts;
120
+ }
121
+ // First phase: single-pattern processing
122
+ // <pre> is 1 or more portions
123
+ // <rest> is 1 or more portions
124
+ // <p> is any portion other than ., .., '', or **
125
+ // <e> is . or ''
126
+ //
127
+ // **/.. is *brutal* for filesystem walking performance, because
128
+ // it effectively resets the recursive walk each time it occurs,
129
+ // and ** cannot be reduced out by a .. pattern part like a regexp
130
+ // or most strings (other than .., ., and '') can be.
131
+ //
132
+ // <pre>/**/../<p>/<rest> -> {<pre>/../<p>/<rest>,<pre>/**/<p>/<rest>}
133
+ // <pre>/<e>/<rest> -> <pre>/<rest>
134
+ // <pre>/<p>/../<rest> -> <pre>/<rest>
135
+ // **/**/<rest> -> **/<rest>
136
+ //
137
+ // **/*/<rest> -> */**/<rest> <== not valid because ** doesn't follow
138
+ // this WOULD be allowed if ** did follow symlinks, or * didn't
139
+ firstPhasePreProcess(globParts) {
140
+ let didSomething = false;
141
+ do {
142
+ didSomething = false;
143
+ // <pre>/**/../<p>/<rest> -> {<pre>/../<p>/<rest>,<pre>/**/<p>/<rest>}
144
+ for (let parts of globParts) {
145
+ let gs = -1;
146
+ while (-1 !== (gs = parts.indexOf('**', gs + 1))) {
147
+ let gss = gs;
148
+ while (parts[gss + 1] === '**') {
149
+ // <pre>/**/**/<rest> -> <pre>/**/<rest>
150
+ gss++;
151
+ }
152
+ // eg, if gs is 2 and gss is 4, that means we have 3 **
153
+ // parts, and can remove 2 of them.
154
+ if (gss > gs) {
155
+ parts.splice(gs + 1, gss - gs);
156
+ }
157
+ let next = parts[gs + 1];
158
+ const p = parts[gs + 2];
159
+ if (next !== '..')
160
+ continue;
161
+ if (!p || p === '.' || p === '..')
162
+ continue;
163
+ didSomething = true;
164
+ // edit parts in place, and push the new one
165
+ parts.splice(gs, 1);
166
+ const other = parts.slice(0);
167
+ other[gs] = '**';
168
+ globParts.push(other);
169
+ gs--;
170
+ }
171
+ // <pre>/<e>/<rest> -> <pre>/<rest>
172
+ for (let i = 1; i < parts.length - 1; i++) {
173
+ const p = parts[i];
174
+ // don't squeeze out UNC patterns
175
+ if (i === 1 && p === '' && parts[0] === '')
176
+ continue;
177
+ if (p === '.' || p === '') {
178
+ didSomething = true;
179
+ parts.splice(i, 1);
180
+ i--;
181
+ }
182
+ }
183
+ if (parts[0] === '.') {
184
+ didSomething = true;
185
+ parts.shift();
186
+ }
187
+ // <pre>/<p>/../<rest> -> <pre>/<rest>
188
+ let dd = 0;
189
+ while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
190
+ const p = parts[dd - 1];
191
+ if (p && p !== '.' && p !== '..' && p !== '**') {
192
+ didSomething = true;
193
+ parts.splice(dd - 1, 2);
194
+ if (parts.length === 0)
195
+ parts.push('');
196
+ dd -= 2;
197
+ }
198
+ }
199
+ }
200
+ } while (didSomething);
201
+ return globParts;
202
+ }
203
+ // second phase: multi-pattern dedupes
204
+ // {<pre>/*/<rest>,<pre>/<p>/<rest>} -> <pre>/*/<rest>
205
+ // {<pre>/<rest>,<pre>/<rest>} -> <pre>/<rest>
206
+ // {<pre>/**/<rest>,<pre>/<rest>} -> <pre>/**/<rest>
207
+ //
208
+ // {<pre>/**/<rest>,<pre>/**/<p>/<rest>} -> <pre>/**/<rest>
209
+ // ^-- not valid because ** doens't follow symlinks
210
+ secondPhasePreProcess(globParts) {
211
+ for (let i = 0; i < globParts.length - 1; i++) {
212
+ for (let j = i + 1; j < globParts.length; j++) {
213
+ const matched = this.partsMatch(globParts[i], globParts[j]);
214
+ if (!matched)
215
+ continue;
216
+ globParts[i] = matched;
217
+ globParts[j] = [];
218
+ }
219
+ }
220
+ return globParts.filter(gs => gs.length);
221
+ }
222
+ partsMatch(a, b) {
223
+ let ai = 0;
224
+ let bi = 0;
225
+ let result = [];
226
+ let which = '';
227
+ while (ai < a.length && bi < b.length) {
228
+ if (a[ai] === b[bi]) {
229
+ result.push(which === 'b' ? b[bi] : a[ai]);
230
+ ai++;
231
+ bi++;
232
+ }
233
+ else if (a[ai] === '**' && b[bi] === a[ai + 1]) {
234
+ result.push(a[ai]);
235
+ ai++;
236
+ }
237
+ else if (b[bi] === '**' && a[ai] === b[bi + 1]) {
238
+ result.push(b[bi]);
239
+ bi++;
240
+ }
241
+ else if (a[ai] === '*' &&
242
+ b[bi] &&
243
+ !b[bi].startsWith('.') &&
244
+ b[bi] !== '**') {
245
+ if (which === 'b')
246
+ return false;
247
+ which = 'a';
248
+ result.push(a[ai]);
249
+ ai++;
250
+ bi++;
251
+ }
252
+ else if (b[bi] === '*' &&
253
+ a[ai] &&
254
+ (this.dot || !a[ai].startsWith('.')) &&
255
+ a[ai] !== '**') {
256
+ if (which === 'a')
257
+ return false;
258
+ which = 'b';
259
+ result.push(b[bi]);
260
+ ai++;
261
+ bi++;
262
+ }
263
+ else {
264
+ return false;
265
+ }
266
+ }
267
+ // if we fall out of the loop, it means they two are identical
268
+ // as long as their lengths match
269
+ return a.length === b.length && result;
270
+ }
271
+ }
272
+ exports.Mini = Mini;
273
+ const braceExpand = (pattern, options = {}) => {
274
+ assertValidPattern(pattern);
275
+ // Thanks to Yeting Li <https://github.com/yetingli> for
276
+ // improving this regexp to avoid a ReDOS vulnerability.
277
+ if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
278
+ // shortcut. no need to expand.
279
+ return [pattern];
280
+ }
281
+ return (0, brace_expansion_1.default)(pattern);
282
+ };
283
+ exports.braceExpand = braceExpand;
284
+ const MAX_PATTERN_LENGTH = 1024 * 64;
285
+ const assertValidPattern = (pattern) => {
286
+ if (typeof pattern !== 'string') {
287
+ throw new TypeError('invalid pattern');
288
+ }
289
+ if (pattern.length > MAX_PATTERN_LENGTH) {
290
+ throw new TypeError('pattern is too long');
291
+ }
292
+ };
293
+ const isGlobList = (gl) => gl.length >= 1;
294
+ class Pattern {
295
+ #options;
296
+ #globList;
297
+ length;
298
+ #index;
299
+ #parsed;
300
+ // memoizing
301
+ #pattern;
302
+ #rest;
303
+ constructor(globList, index, parsed, options) {
304
+ if (!isGlobList(globList)) {
305
+ throw new TypeError('empty glob list');
306
+ }
307
+ this.#globList = globList;
308
+ if (index >= globList.length) {
309
+ throw new TypeError('index out of range');
310
+ }
311
+ this.length = globList.length;
312
+ this.#options = options;
313
+ this.#index = index;
314
+ this.#parsed = parsed;
315
+ }
316
+ glob() {
317
+ return this.#globList[this.#index];
318
+ }
319
+ pattern() {
320
+ if (this.#pattern !== undefined) {
321
+ return this.#pattern;
322
+ }
323
+ const glob = this.glob();
324
+ if (glob.endsWith('/')) {
325
+ return (this.#pattern = glob);
326
+ }
327
+ const cached = this.#parsed.get(glob);
328
+ if (cached !== undefined) {
329
+ return (this.#pattern = cached);
330
+ }
331
+ const pattern = parse(glob, this.#options);
332
+ this.#parsed.set(glob, pattern);
333
+ return (this.#pattern = pattern);
334
+ }
335
+ isAbsolute() {
336
+ return this.#globList[0].endsWith('/');
337
+ }
338
+ root() {
339
+ return this.#index === 0 && this.isAbsolute() ? this.#globList[0] : '';
340
+ }
341
+ rest() {
342
+ if (this.#rest !== undefined)
343
+ return this.#rest;
344
+ if (this.#index >= this.length - 1)
345
+ return (this.#rest = null);
346
+ const rest = new Pattern(this.#globList, this.#index + 1, this.#parsed, this.#options);
347
+ this.#rest = rest;
348
+ return rest;
349
+ }
350
+ hasMore() {
351
+ return this.#index < this.length - 1;
352
+ }
353
+ }
354
+ exports.Pattern = Pattern;
355
+ const parsePattern = (pattern, options) => {
356
+ const ast = (0, exports.tokenize)(pattern, options);
357
+ if (ast.length === 1 && ast[0][TokenField.TYPE] === TokenType.STRING) {
358
+ return ast[0][TokenField.VALUE];
359
+ }
360
+ const re = (0, exports.compile)(ast, options, true);
361
+ try {
362
+ return new RegExp(re, options.nocase ? 'i' : '');
363
+ }
364
+ catch (er) {
365
+ return /$./;
366
+ }
367
+ };
368
+ exports.parsePattern = parsePattern;
369
+ const compile = (ast, options, isTop = false, isStart = true) => {
370
+ const negativeExts = [];
371
+ const re = [];
372
+ let stillStart = isStart;
373
+ let maybeEmpty = true;
374
+ for (let i = 0; i < ast.length; i++) {
375
+ const token = ast[i];
376
+ if (isStringToken(token)) {
377
+ if (token[TokenField.VALUE] !== '') {
378
+ maybeEmpty = false;
379
+ }
380
+ re.push(compileNonMagic(token, options));
381
+ }
382
+ else if (isClassToken(token)) {
383
+ maybeEmpty = false;
384
+ re.push(compileClass(token, options));
385
+ }
386
+ else if (isExtToken(token)) {
387
+ if (token[TokenField.VALUE] === '!') {
388
+ negativeExts.push(i);
389
+ }
390
+ re.push(compileExt(token, options, stillStart));
391
+ }
392
+ else if (isQmarkToken(token)) {
393
+ maybeEmpty = false;
394
+ re.push(compileQmark(token, options));
395
+ }
396
+ else if (isStarToken(token)) {
397
+ re.push(compileStar(token, options));
398
+ /* c8 ignore start */
399
+ }
400
+ else {
401
+ throw new TypeError('unknown token type: ' + token);
402
+ }
403
+ /* c8 ignore stop */
404
+ stillStart = false;
405
+ }
406
+ if (isTop) {
407
+ re.push('$');
408
+ }
409
+ // a negative extglob is:
410
+ // ((?!(sub|patterns)<rest of the pattern>).*?)
411
+ // so we need to do it in two passes.
412
+ for (let i = negativeExts.length - 1; i >= 0; i--) {
413
+ const n = negativeExts[i];
414
+ re[n] += compileNegativeExtClose(re, n);
415
+ }
416
+ if (isTop) {
417
+ if (!options.dot && needDotProtection(ast)) {
418
+ re.unshift('(?!^\\.)');
419
+ }
420
+ if (maybeEmpty) {
421
+ re.unshift('(?=.)');
422
+ }
423
+ re.unshift('^');
424
+ }
425
+ else if (isStart) {
426
+ if (!options.dot && needDotProtection(ast)) {
427
+ re.unshift('(?!^\\.)');
428
+ }
429
+ }
430
+ return re.join('');
431
+ };
432
+ exports.compile = compile;
433
+ const needDotProtection = (ast) => {
434
+ const first = ast[0];
435
+ return isClassToken(first) || isStarToken(first) || isQmarkToken(first);
436
+ };
437
+ const compileQmark = (_, __) => '.';
438
+ const compileStar = (_, __) => '.*?';
439
+ const compileNonMagic = (token, _) => regExpEscape(token[TokenField.VALUE]);
440
+ const compileClass = (token, _) => {
441
+ // TODO: posix classes
442
+ const cls = braceEscape(charUnescape(token[TokenField.VALUE]));
443
+ const re = `[${cls}]`;
444
+ // handle out of order classes, like `[z-a]`, which throw
445
+ // in javascript, but just match nothing in glob syntax.
446
+ try {
447
+ RegExp(re);
448
+ return re;
449
+ }
450
+ catch (_) {
451
+ return '$.';
452
+ }
453
+ };
454
+ const charUnescape = (s) => s.replace(/\\([^-\]])/g, '$1');
455
+ const braceEscape = (s) => s.replace(/[[\]\\]/g, '\\$&');
456
+ const globSpecialChars = new Set(['?', '*', '+', '@', '!', '[', '(']);
457
+ const escapeInClass = new Set(['-', ']']);
458
+ const regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
459
+ const isExtToken = (t) => t[TokenField.TYPE] === TokenType.EXT;
460
+ const isStringToken = (t) => t[TokenField.TYPE] === TokenType.STRING;
461
+ const isStarToken = (t) => t[TokenField.TYPE] === TokenType.STAR;
462
+ const isQmarkToken = (t) => t[TokenField.TYPE] === TokenType.QMARK;
463
+ const isClassToken = (t) => t[TokenField.TYPE] === TokenType.CLASS;
464
+ var TokenField;
465
+ (function (TokenField) {
466
+ TokenField[TokenField["TYPE"] = 0] = "TYPE";
467
+ TokenField[TokenField["VALUE"] = 1] = "VALUE";
468
+ TokenField[TokenField["CHILDREN"] = 2] = "CHILDREN";
469
+ })(TokenField || (TokenField = {}));
470
+ var TokenType;
471
+ (function (TokenType) {
472
+ TokenType["STRING"] = "string";
473
+ TokenType["STAR"] = "star";
474
+ TokenType["EXT"] = "ext";
475
+ TokenType["QMARK"] = "qmark";
476
+ TokenType["CLASS"] = "class";
477
+ })(TokenType || (TokenType = {}));
478
+ const extGlobTypes = new Set(['?', '*', '+', '@', '!']);
479
+ const isExtGlobType = (s) => extGlobTypes.has(s);
480
+ const extTypes = {
481
+ '!': { open: '(?:(?!(?:', close: ').*?))' },
482
+ '?': { open: '(?:', close: ')?' },
483
+ '+': { open: '(?:', close: ')+' },
484
+ '*': { open: '(?:', close: ')*' },
485
+ '@': { open: '(?:', close: ')' },
486
+ };
487
+ const compileExt = (token, options, isStart) => {
488
+ const t = token[TokenField.VALUE];
489
+ const open = extTypes[t].open;
490
+ const close = t === '!' ? '' : extTypes[t].close;
491
+ const subs = token[TokenField.CHILDREN];
492
+ const body = subs.map(ast => (0, exports.compile)(ast, options, false, isStart)).join('|');
493
+ return open + body + close;
494
+ };
495
+ const compileNegativeExtClose = (re, n) => {
496
+ // walk the AST from i onwards, collecting the regexp
497
+ // then add the end bit:
498
+ // ((?!(sub|patterns)<rest of the pattern>).*?)
499
+ // ^-- from here on
500
+ let s = ')';
501
+ for (let i = n + 1; i < re.length; i++) {
502
+ s += re[i];
503
+ }
504
+ s += ').*?)';
505
+ return s;
506
+ };
507
+ const tokenize = (pattern, options, ast = []) => {
508
+ // tokenize the string up into chunks first
509
+ // sort of like an AST of the pattern
510
+ // each node is [type, value, [...children]]
511
+ // root, or children of extglobs, are an array of nodes
512
+ // so 'i\?jk?*.@(xy[a-c]|!(foo|ba*r))baz*bo' becomes:
513
+ // [
514
+ // [STRING, 'i?jk'],
515
+ // [QMARK, '?'],
516
+ // [STAR, '*'],
517
+ // [STRING, '.'],
518
+ // [EXT, '@', [
519
+ // [[STRING, 'xy'], [CLASS, 'a-c']],
520
+ // [[EXT, '!', [
521
+ // [[STRING, 'foo']],
522
+ // [[STRING, 'ba'], [STAR, '*'], [STRING, 'r']]
523
+ // ]]],
524
+ // ]],
525
+ // [STRING, 'baz'],
526
+ // [STAR, '*'],
527
+ // [STRING, 'bo'],
528
+ // ]
529
+ //
530
+ // which turns into the regexp:
531
+ // ^i\?jk..*?\.(?:xy[a-c]|(?:(?!(?:foo|ba.*?r).*$)))baz.*?bo$
532
+ // Place the "no dot allowed" if the AST starts at position 0,
533
+ // and is a *, ?, or class at the start
534
+ let i = 0;
535
+ const length = pattern.length;
536
+ while (i < length) {
537
+ let c = pattern.charAt(i);
538
+ // take our best guess as to what it is
539
+ // the other tokenizers will append to the AST and return
540
+ // the amount of string that was consumed.
541
+ if (!options.noext && isExtGlobType(c) && pattern.charAt(i + 1) === '(') {
542
+ const consumed = tokenizeExt(pattern, options, i, ast);
543
+ if (consumed) {
544
+ i += consumed;
545
+ c = pattern.charAt(i);
546
+ continue;
547
+ }
548
+ }
549
+ if (c === '[') {
550
+ const consumed = tokenizeClass(pattern, options, i, ast);
551
+ if (consumed) {
552
+ i += consumed;
553
+ continue;
554
+ }
555
+ }
556
+ if (c === '*') {
557
+ ast.push([TokenType.STAR, '*']);
558
+ }
559
+ else if (c === '?') {
560
+ ast.push([TokenType.QMARK, '?']);
561
+ }
562
+ else {
563
+ const consumed = tokenizeNonMagic(pattern, options, i, ast);
564
+ if (consumed) {
565
+ i += consumed;
566
+ c = pattern.charAt(i);
567
+ continue;
568
+ }
569
+ }
570
+ i++;
571
+ }
572
+ return ast;
573
+ };
574
+ exports.tokenize = tokenize;
575
+ const tokenizeExt = (pattern, options, i, ast) => {
576
+ const extType = pattern.charAt(i);
577
+ if (!isExtGlobType(extType)) {
578
+ throw new Error('invalid extglob type: ' + extType);
579
+ }
580
+ const matchStack = [];
581
+ const pipes = [];
582
+ let p;
583
+ const length = pattern.length;
584
+ let end = -1;
585
+ let escaping = false;
586
+ // first split out the top-level set of strings
587
+ // if we can't do that, it's not a valid extglob
588
+ for (p = i + 2; p < length; p++) {
589
+ const c = pattern.charAt(p);
590
+ if (escaping) {
591
+ escaping = false;
592
+ continue;
593
+ }
594
+ if (c === '\\') {
595
+ escaping = true;
596
+ continue;
597
+ }
598
+ if (c === ']') {
599
+ if (matchStack[0] === '[' && pattern.charAt(p - 1) !== '[') {
600
+ matchStack.shift();
601
+ }
602
+ }
603
+ else if (c === ')') {
604
+ if (!matchStack.length) {
605
+ // finished!
606
+ end = p;
607
+ break;
608
+ }
609
+ else if (matchStack[0] === '(') {
610
+ matchStack.shift();
611
+ }
612
+ }
613
+ else if (c === '(') {
614
+ if (matchStack[0] !== '[' && isExtGlobType(pattern.charAt(p - 1))) {
615
+ matchStack.unshift(c);
616
+ }
617
+ }
618
+ else if (c === '|' && matchStack.length === 0) {
619
+ pipes.push(p);
620
+ }
621
+ }
622
+ if (!end || matchStack.length) {
623
+ return 0;
624
+ }
625
+ // i + 1, pipes, and end define the outside boundaries of the subs
626
+ const subPatterns = [];
627
+ let start = i + 2;
628
+ for (const pipe of pipes) {
629
+ subPatterns.push(pattern.substring(start, pipe));
630
+ start = pipe + 1;
631
+ }
632
+ subPatterns.push(pattern.substring(start, end));
633
+ const subTokenized = subPatterns.map(p => (0, exports.tokenize)(p, options));
634
+ ast.push([TokenType.EXT, extType, subTokenized]);
635
+ return end - i + 1;
636
+ };
637
+ const tokenizeClass = (pattern, _, i, ast) => {
638
+ // walk until we find the closing ] that is not escaped or the first char
639
+ // return 0 if it's not a valid class (basically, just if it's left open)
640
+ let p;
641
+ let escaping = false;
642
+ const length = pattern.length;
643
+ let s = '';
644
+ for (p = i + 1; p < length; p++) {
645
+ const c = pattern.charAt(p);
646
+ if (c === '\\' && !escaping) {
647
+ escaping = true;
648
+ continue;
649
+ }
650
+ if (p === i + 1 && c === ']') {
651
+ s += c;
652
+ continue;
653
+ }
654
+ if (escaping) {
655
+ escaping = false;
656
+ if (escapeInClass.has(c)) {
657
+ s += '\\';
658
+ }
659
+ s += c;
660
+ continue;
661
+ }
662
+ if (c === ']') {
663
+ ast.push([TokenType.CLASS, s]);
664
+ return p - i + 1;
665
+ }
666
+ s += c;
667
+ }
668
+ return 0;
669
+ };
670
+ const tokenizeNonMagic = (pattern, _, i, ast) => {
671
+ let escaping = false;
672
+ let p = i;
673
+ let sawFirst = false;
674
+ const length = pattern.length;
675
+ let s = '';
676
+ for (p = i; p < length; p++) {
677
+ let c = pattern.charAt(p);
678
+ if (c === '\\' && !escaping) {
679
+ escaping = true;
680
+ continue;
681
+ }
682
+ if (escaping) {
683
+ escaping = false;
684
+ s += c;
685
+ continue;
686
+ }
687
+ // this is only called when we KNOW the first char is not magic,
688
+ // so no need to stop for that at the outset.
689
+ if (!sawFirst) {
690
+ sawFirst = true;
691
+ s += c;
692
+ continue;
693
+ }
694
+ if (globSpecialChars.has(c)) {
695
+ break;
696
+ }
697
+ s += c;
698
+ }
699
+ ast.push([TokenType.STRING, s]);
700
+ return p - i;
701
+ };
702
+ const parse = (pattern, options) => {
703
+ if (pattern === '**')
704
+ return index_js_1.GLOBSTAR;
705
+ let m;
706
+ let fastTest = null;
707
+ if ((m = pattern.match(starRE))) {
708
+ fastTest = options.dot ? starTestDot : starTest;
709
+ }
710
+ else if ((m = pattern.match(starDotExtRE))) {
711
+ fastTest = (options.nocase
712
+ ? options.dot
713
+ ? starDotExtTestNocaseDot
714
+ : starDotExtTestNocase
715
+ : options.dot
716
+ ? starDotExtTestDot
717
+ : starDotExtTest)(m[1]);
718
+ }
719
+ else if ((m = pattern.match(qmarksRE))) {
720
+ fastTest = (options.nocase
721
+ ? options.dot
722
+ ? qmarksTestNocaseDot
723
+ : qmarksTestNocase
724
+ : options.dot
725
+ ? qmarksTestDot
726
+ : qmarksTest)(m);
727
+ }
728
+ else if ((m = pattern.match(starDotStarRE))) {
729
+ fastTest = options.dot ? starDotStarTestDot : starDotStarTest;
730
+ }
731
+ else if ((m = pattern.match(dotStarRE))) {
732
+ fastTest = dotStarTest;
733
+ }
734
+ if (fastTest) {
735
+ return Object.assign(/$./, {
736
+ _glob: pattern,
737
+ test: fastTest,
738
+ });
739
+ }
740
+ else {
741
+ // ok we have to actually parse it
742
+ const re = (0, exports.parsePattern)(pattern, options);
743
+ return typeof re === 'string' ? re : Object.assign(re, {
744
+ _glob: pattern,
745
+ });
746
+ }
747
+ };
748
+ // Optimized checking for the most common glob patterns.
749
+ const starDotExtRE = /^\*+([^+@!?\*\[\(]*)$/;
750
+ const starDotExtTest = (ext) => (f) => !f.startsWith('.') && f.endsWith(ext);
751
+ const starDotExtTestDot = (ext) => (f) => f.endsWith(ext);
752
+ const starDotExtTestNocase = (ext) => {
753
+ ext = ext.toLowerCase();
754
+ return (f) => !f.startsWith('.') && f.toLowerCase().endsWith(ext);
755
+ };
756
+ const starDotExtTestNocaseDot = (ext) => {
757
+ ext = ext.toLowerCase();
758
+ return (f) => f.toLowerCase().endsWith(ext);
759
+ };
760
+ const starDotStarRE = /^\*+\.\*+$/;
761
+ const starDotStarTest = (f) => !f.startsWith('.') && f.includes('.');
762
+ const starDotStarTestDot = (f) => f !== '.' && f !== '..' && f.includes('.');
763
+ const dotStarRE = /^\.\*+$/;
764
+ const dotStarTest = (f) => f !== '.' && f !== '..' && f.startsWith('.');
765
+ const starRE = /^\*+$/;
766
+ const starTest = (f) => f.length !== 0 && !f.startsWith('.');
767
+ const starTestDot = (f) => f.length !== 0 && f !== '.' && f !== '..';
768
+ const qmarksRE = /^\?+([^+@!?\*\[\(]*)?$/;
769
+ const qmarksTestNocase = ([$0, ext = '']) => {
770
+ const noext = qmarksTestNoExt([$0]);
771
+ if (!ext)
772
+ return noext;
773
+ ext = ext.toLowerCase();
774
+ return (f) => noext(f) && f.toLowerCase().endsWith(ext);
775
+ };
776
+ const qmarksTestNocaseDot = ([$0, ext = '']) => {
777
+ const noext = qmarksTestNoExtDot([$0]);
778
+ if (!ext)
779
+ return noext;
780
+ ext = ext.toLowerCase();
781
+ return (f) => noext(f) && f.toLowerCase().endsWith(ext);
782
+ };
783
+ const qmarksTestDot = ([$0, ext = '']) => {
784
+ const noext = qmarksTestNoExtDot([$0]);
785
+ return !ext ? noext : (f) => noext(f) && f.endsWith(ext);
786
+ };
787
+ const qmarksTest = ([$0, ext = '']) => {
788
+ const noext = qmarksTestNoExt([$0]);
789
+ return !ext ? noext : (f) => noext(f) && f.endsWith(ext);
790
+ };
791
+ const qmarksTestNoExt = ([$0]) => {
792
+ const len = $0.length;
793
+ return (f) => f.length === len && !f.startsWith('.');
794
+ };
795
+ const qmarksTestNoExtDot = ([$0]) => {
796
+ const len = $0.length;
797
+ return (f) => f.length === len && f !== '.' && f !== '..';
798
+ };
799
+ //# sourceMappingURL=mini.js.map