minimatch 7.4.3 → 7.4.4

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.
package/dist/cjs/parse.js DELETED
@@ -1,650 +0,0 @@
1
- "use strict";
2
- // parse a single path portion
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.AST = void 0;
5
- const brace_expressions_1 = require("./brace-expressions");
6
- const types = new Set(['!', '?', '+', '*', '@']);
7
- const isExtglobType = (c) => types.has(c);
8
- // characters that indicate a start of pattern needs the "no dots" bit
9
- const addPatternStart = new Set(['[', '.']);
10
- const justDots = new Set(['..', '.']);
11
- const reSpecials = new Set('().*{}+?[]^$\\!');
12
- const regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
13
- // any single thing other than /
14
- // don't need to escape / when using new RegExp()
15
- const qmark = '[^/]';
16
- // * => any number of characters
17
- const star = qmark + '*?';
18
- class AST {
19
- type;
20
- #root;
21
- #parts = [];
22
- #parent;
23
- #parentIndex;
24
- #negs;
25
- #filledNegs = false;
26
- #options;
27
- constructor(type, parent, options = {}) {
28
- this.type = type;
29
- this.#parent = parent;
30
- this.#root = this.#parent ? this.#parent.#root : this;
31
- this.#options = this.#root === this ? options : this.#root.#options;
32
- this.#negs = this.#root === this ? [] : this.#root.#negs;
33
- if (type === '!' && !this.#root.#filledNegs)
34
- this.#negs.push(this);
35
- this.#parentIndex = this.#parent ? this.#parent.#parts.length : 0;
36
- }
37
- fillNegs() {
38
- if (this !== this.#root) {
39
- this.#root.fillNegs();
40
- return this;
41
- }
42
- if (this.#filledNegs)
43
- return this;
44
- this.#filledNegs = true;
45
- let n;
46
- while ((n = this.#negs.pop())) {
47
- if (n.type !== '!')
48
- continue;
49
- // walk up the tree, appending everthing that comes AFTER parentIndex
50
- let p = n;
51
- let pp = p.#parent;
52
- while (pp) {
53
- for (let i = p.#parentIndex + 1; !pp.type && i < pp.#parts.length; i++) {
54
- for (const part of n.#parts) {
55
- /* c8 ignore start */
56
- if (typeof part === 'string') {
57
- throw new Error('string part in extglob AST??');
58
- }
59
- /* c8 ignore stop */
60
- part.copyIn(pp.#parts[i]);
61
- }
62
- }
63
- p = pp;
64
- pp = p.#parent;
65
- }
66
- }
67
- return this;
68
- }
69
- push(...parts) {
70
- for (const p of parts) {
71
- if (p === '')
72
- continue;
73
- /* c8 ignore start */
74
- if (typeof p !== 'string' && !(p instanceof AST && p.#parent === this)) {
75
- throw new Error('invalid part: ' + p);
76
- }
77
- /* c8 ignore stop */
78
- this.#parts.push(p);
79
- }
80
- }
81
- toJSON() {
82
- const ret = this.type === null ? this.#parts.slice() : [this.type, ...this.#parts];
83
- if (this.isStart() && !this.type)
84
- ret.unshift([]);
85
- if (this.isEnd() &&
86
- (this === this.#root ||
87
- (this.#root.#filledNegs && this.#parent?.type === '!'))) {
88
- ret.push({});
89
- }
90
- return ret;
91
- }
92
- isStart() {
93
- if (this.#root === this)
94
- return true;
95
- // if (this.type) return !!this.#parent?.isStart()
96
- if (!this.#parent?.isStart())
97
- return false;
98
- return this.#parentIndex === 0;
99
- }
100
- isEnd() {
101
- if (this.#root === this)
102
- return true;
103
- if (this.#parent?.type === '!')
104
- return true;
105
- if (!this.#parent?.isEnd())
106
- return false;
107
- if (!this.type)
108
- return this.#parent?.isEnd();
109
- return (this.#parentIndex === (this.#parent ? this.#parent.#parts.length : 0) - 1);
110
- }
111
- copyIn(part) {
112
- if (typeof part === 'string')
113
- this.push(part);
114
- else
115
- this.push(part.clone(this));
116
- }
117
- clone(parent) {
118
- const c = new AST(this.type, parent);
119
- for (const p of this.#parts) {
120
- c.copyIn(p);
121
- }
122
- return c;
123
- }
124
- static #parseAST(str, ast, pos, opt) {
125
- let escaping = false;
126
- if (ast.type === null) {
127
- // outside of a extglob, append until we find a start
128
- let i = pos;
129
- let acc = '';
130
- while (i < str.length) {
131
- const c = str.charAt(i++);
132
- // still accumulate escapes at this point, but we do ignore
133
- // starts that are escaped
134
- if (escaping || c === '\\') {
135
- escaping = !escaping;
136
- acc += c;
137
- continue;
138
- }
139
- if (!opt.noext && isExtglobType(c) && str.charAt(i) === '(') {
140
- ast.push(acc);
141
- acc = '';
142
- const ext = new AST(c, ast);
143
- i = AST.#parseAST(str, ext, i, opt);
144
- ast.push(ext);
145
- continue;
146
- }
147
- acc += c;
148
- }
149
- ast.push(acc);
150
- return i;
151
- }
152
- // some kind of extglob, pos is at the (
153
- // find the next | or )
154
- let i = pos + 1;
155
- let part = new AST(null, ast);
156
- const parts = [];
157
- let acc = '';
158
- while (i < str.length) {
159
- const c = str.charAt(i++);
160
- // still accumulate escapes at this point, but we do ignore
161
- // starts that are escaped
162
- if (escaping || c === '\\') {
163
- escaping = !escaping;
164
- acc += c;
165
- continue;
166
- }
167
- if (isExtglobType(c) && str.charAt(i) === '(') {
168
- part.push(acc);
169
- acc = '';
170
- const ext = new AST(c, part);
171
- part.push(ext);
172
- i = AST.#parseAST(str, ext, i, opt);
173
- continue;
174
- }
175
- if (c === '|') {
176
- part.push(acc);
177
- acc = '';
178
- parts.push(part);
179
- part = new AST(null, ast);
180
- continue;
181
- }
182
- if (c === ')') {
183
- part.push(acc);
184
- acc = '';
185
- ast.push(...parts, part);
186
- return i;
187
- }
188
- acc += c;
189
- }
190
- // if we got here, it was a malformed extglob! not an extglob, but
191
- // maybe something else in there.
192
- ast.type = null;
193
- ast.#parts = [str.substring(pos)];
194
- return i;
195
- }
196
- static fromGlob(pattern, options = {}) {
197
- const ast = new AST(null, undefined, options);
198
- AST.#parseAST(pattern, ast, 0, options);
199
- console.log('parsed', pattern, JSON.stringify(ast));
200
- return ast;
201
- }
202
- toRegExpSource() {
203
- if (this.#root === this)
204
- this.fillNegs();
205
- if (!this.type) {
206
- const src = this.#parts
207
- .map(p => {
208
- if (typeof p === 'string')
209
- return AST.#parseGlob(p, this.#options);
210
- else
211
- return p.toRegExpSource();
212
- })
213
- .join('');
214
- let start = '';
215
- if (this.isStart() && typeof this.#parts[0] === 'string') {
216
- // '.' and '..' cannot match unless the pattern is that exactly
217
- const dotTravAllowed = this.#parts.length === 1 && justDots.has(this.#parts[0]);
218
- if (dotTravAllowed) {
219
- start = '(?:^|\\/)';
220
- }
221
- else {
222
- const dotsAllowed = this.#options.dot ||
223
- // no need to prevent dots if it can't match a dot, or if a sub-pattern
224
- // will be preventing it anyway.
225
- !addPatternStart.has(src.charAt(0));
226
- start = dotsAllowed ? '(?!(?:^|\\/)\\.{1,2}(?:$|\\/))' : '(?!\\.)';
227
- }
228
- }
229
- let end = '';
230
- if (this.isEnd() &&
231
- (this === this.#root ||
232
- (this.#root.#filledNegs && this.#parent?.type === '!'))) {
233
- end = '(?:$|\\/)';
234
- }
235
- return start + src + end;
236
- }
237
- // some kind of extglob
238
- const start = this.type === '!' ? '(?:(?!(?:' : '(?:';
239
- const body = this.#parts
240
- .map(p => {
241
- /* c8 ignore start */
242
- if (typeof p === 'string') {
243
- throw new Error('string type in extglob ast??');
244
- }
245
- /* c8 ignore stop */
246
- return p.toRegExpSource();
247
- })
248
- .join('|');
249
- const close = this.type === '!'
250
- ? '))[^/]*?)'
251
- : this.type === '@'
252
- ? ')'
253
- : `)${this.type}`;
254
- return start + body + close;
255
- }
256
- static #parseGlob(glob, options) {
257
- let escaping = false;
258
- let re = '';
259
- let uflag = false;
260
- let hasMagic = false;
261
- for (let i = 0; i < glob.length; i++) {
262
- const c = glob.charAt(i);
263
- if (escaping) {
264
- escaping = false;
265
- re += (reSpecials.has(c) ? '\\' : '') + c;
266
- continue;
267
- }
268
- if (c === '\\') {
269
- if (i === glob.length - 1) {
270
- re += '\\\\';
271
- }
272
- else {
273
- escaping = true;
274
- }
275
- continue;
276
- }
277
- if (c === '[') {
278
- const [src, needUflag, consumed, magic] = (0, brace_expressions_1.parseClass)(glob, i);
279
- if (consumed) {
280
- re += src;
281
- uflag = uflag || needUflag;
282
- i += consumed - 1;
283
- hasMagic = hasMagic || magic;
284
- continue;
285
- }
286
- }
287
- if (c === '*') {
288
- re += star;
289
- hasMagic = true;
290
- continue;
291
- }
292
- if (c === '?') {
293
- re += qmark;
294
- hasMagic = true;
295
- continue;
296
- }
297
- re += regExpEscape(c);
298
- }
299
- return re;
300
- }
301
- }
302
- exports.AST = AST;
303
- const pattern = 'a@(i|w!(x|y)z+(l|m)|j)';
304
- const ast = AST.fromGlob(pattern).fillNegs();
305
- console.log('negged', pattern, JSON.stringify(ast));
306
- console.log('to re src', pattern, ast.toRegExpSource());
307
- // // the type (exttype or null for strings), and array of children tokens
308
- //
309
- // // append everything after a negative extglob to each of the parts
310
- // // of the negative extglob node. So, eg, [a, [!, x, y], z]
311
- //
312
- // //
313
- // //
314
- // //
315
- // //
316
- //
317
- // const globUnescape = (s: string) => s.replace(/\\(.)/g, '$1')
318
- // const regExpEscape = (s: string) =>
319
- // s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
320
- //
321
- // // "abc" -> { a:true, b:true, c:true }
322
- // const charSet = (s: string) =>
323
- // s.split('').reduce((set: { [k: string]: boolean }, c) => {
324
- // set[c] = true
325
- // return set
326
- // }, {})
327
- //
328
- // // characters that need to be escaped in RegExp.
329
- // const reSpecials = charSet('().*{}+?[]^$\\!')
330
- //
331
- // // characters that indicate we have to add the pattern start
332
- // const addPatternStartSet = charSet('[.(')
333
- //
334
- // // any single thing other than /
335
- // // don't need to escape / when using new RegExp()
336
- // const qmark = '[^/]'
337
- //
338
- // // * => any number of characters
339
- // const star = qmark + '*?'
340
- //
341
- // // TODO: take an offset and length, so we can sub-parse the extglobs
342
- // const parse = (
343
- // options: MinimatchOptions,
344
- // pattern: string,
345
- // debug: (...a: any[]) => void
346
- // ): false | string => {
347
- // assertValidPattern(pattern)
348
- //
349
- // if (pattern === '') return ''
350
- //
351
- // let re = ''
352
- // let hasMagic = false
353
- // let escaping = false
354
- // // ? => one single character
355
- // let uflag = false
356
- //
357
- // // . and .. never match anything that doesn't start with .,
358
- // // even when options.dot is set. However, if the pattern
359
- // // starts with ., then traversal patterns can match.
360
- // let dotTravAllowed = pattern.charAt(0) === '.'
361
- // let dotFileAllowed = options.dot || dotTravAllowed
362
- // const patternStart = () =>
363
- // dotTravAllowed
364
- // ? ''
365
- // : dotFileAllowed
366
- // ? '(?!(?:^|\\/)\\.{1,2}(?:$|\\/))'
367
- // : '(?!\\.)'
368
- // const subPatternStart = (p: string) =>
369
- // p.charAt(0) === '.'
370
- // ? ''
371
- // : options.dot
372
- // ? '(?!(?:^|\\/)\\.{1,2}(?:$|\\/))'
373
- // : '(?!\\.)'
374
- //
375
- // const clearStateChar = () => {
376
- // if (stateChar) {
377
- // // we had some state-tracking character
378
- // // that wasn't consumed by this pass.
379
- // switch (stateChar) {
380
- // case '*':
381
- // re += star
382
- // hasMagic = true
383
- // break
384
- // case '?':
385
- // re += qmark
386
- // hasMagic = true
387
- // break
388
- // default:
389
- // re += '\\' + stateChar
390
- // break
391
- // }
392
- // debug('clearStateChar %j %j', stateChar, re)
393
- // stateChar = false
394
- // }
395
- // }
396
- //
397
- // for (
398
- // let i = 0, c: string;
399
- // i < pattern.length && (c = pattern.charAt(i));
400
- // i++
401
- // ) {
402
- // debug('%s\t%s %s %j', pattern, i, re, c)
403
- //
404
- // // skip over any that are escaped.
405
- // if (escaping) {
406
- // // completely not allowed, even escaped.
407
- // // should be impossible.
408
- // /* c8 ignore start */
409
- // if (c === '/') {
410
- // return false
411
- // }
412
- // /* c8 ignore stop */
413
- //
414
- // if (reSpecials[c]) {
415
- // re += '\\'
416
- // }
417
- // re += c
418
- // escaping = false
419
- // continue
420
- // }
421
- //
422
- // switch (c) {
423
- // // Should already be path-split by now.
424
- // /* c8 ignore start */
425
- // case '/': {
426
- // return false
427
- // }
428
- // /* c8 ignore stop */
429
- //
430
- // case '\\':
431
- // clearStateChar()
432
- // escaping = true
433
- // continue
434
- //
435
- // // the various stateChar values
436
- // // for the "extglob" stuff.
437
- // case '?':
438
- // case '*':
439
- // case '+':
440
- // case '@':
441
- // case '!':
442
- // debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c)
443
- //
444
- // // if we already have a stateChar, then it means
445
- // // that there was something like ** or +? in there.
446
- // // Handle the stateChar, then proceed with this one.
447
- // debug('call clearStateChar %j', stateChar)
448
- // clearStateChar()
449
- // stateChar = c
450
- // // if extglob is disabled, then +(asdf|foo) isn't a thing.
451
- // // just clear the statechar *now*, rather than even diving into
452
- // // the patternList stuff.
453
- // if (options.noext) clearStateChar()
454
- // continue
455
- //
456
- // case '(': {
457
- // if (!stateChar) {
458
- // re += '\\('
459
- // continue
460
- // }
461
- //
462
- // const plEntry: PatternListEntry = {
463
- // type: stateChar,
464
- // start: i - 1,
465
- // reStart: re.length,
466
- // open: plTypes[stateChar].open,
467
- // close: plTypes[stateChar].close,
468
- // }
469
- // debug(pattern, '\t', plEntry)
470
- // patternListStack.push(plEntry)
471
- // // negation is (?:(?!(?:js)(?:<rest>))[^/]*)
472
- // re += plEntry.open
473
- // // next entry starts with a dot maybe?
474
- // if (plEntry.start === 0 && plEntry.type !== '!') {
475
- // dotTravAllowed = true
476
- // re += subPatternStart(pattern.slice(i + 1))
477
- // }
478
- // debug('plType %j %j', stateChar, re)
479
- // stateChar = false
480
- // continue
481
- // }
482
- //
483
- // case ')': {
484
- // const plEntry = patternListStack[patternListStack.length - 1]
485
- // if (!plEntry) {
486
- // re += '\\)'
487
- // continue
488
- // }
489
- // patternListStack.pop()
490
- //
491
- // // closing an extglob
492
- // clearStateChar()
493
- // hasMagic = true
494
- // pl = plEntry
495
- // // negation is (?:(?!js)[^/]*)
496
- // // The others are (?:<pattern>)<type>
497
- // re += pl.close
498
- // if (pl.type === '!') {
499
- // negativeLists.push(Object.assign(pl, { reEnd: re.length }))
500
- // }
501
- // continue
502
- // }
503
- //
504
- // case '|': {
505
- // const plEntry = patternListStack[patternListStack.length - 1]
506
- // if (!plEntry) {
507
- // re += '\\|'
508
- // continue
509
- // }
510
- //
511
- // clearStateChar()
512
- // re += '|'
513
- // // next subpattern can start with a dot?
514
- // if (plEntry.start === 0 && plEntry.type !== '!') {
515
- // dotTravAllowed = true
516
- // re += subPatternStart(pattern.slice(i + 1))
517
- // }
518
- // continue
519
- // }
520
- //
521
- // // these are mostly the same in regexp and glob
522
- // case '[':
523
- // // swallow any state-tracking char before the [
524
- // clearStateChar()
525
- // const [src, needUflag, consumed, magic] = parseClass(pattern, i)
526
- // if (consumed) {
527
- // re += src
528
- // uflag = uflag || needUflag
529
- // i += consumed - 1
530
- // hasMagic = hasMagic || magic
531
- // } else {
532
- // re += '\\['
533
- // }
534
- // continue
535
- //
536
- // case ']':
537
- // re += '\\' + c
538
- // continue
539
- //
540
- // default:
541
- // // swallow any state char that wasn't consumed
542
- // clearStateChar()
543
- //
544
- // re += regExpEscape(c)
545
- // break
546
- // } // switch
547
- // } // for
548
- //
549
- // // handle the case where we had a +( thing at the *end*
550
- // // of the pattern.
551
- // // each pattern list stack adds 3 chars, and we need to go through
552
- // // and escape any | chars that were passed through as-is for the regexp.
553
- // // Go through and escape them, taking care not to double-escape any
554
- // // | chars that were already escaped.
555
- // for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
556
- // let tail: string
557
- // tail = re.slice(pl.reStart + pl.open.length)
558
- // debug(pattern, 'setting tail', re, pl)
559
- // // maybe some even number of \, then maybe 1 \, followed by a |
560
- // tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, (_, $1, $2) => {
561
- // if (!$2) {
562
- // // the | isn't already escaped, so escape it.
563
- // $2 = '\\'
564
- // // should already be done
565
- // /* c8 ignore start */
566
- // }
567
- // /* c8 ignore stop */
568
- //
569
- // // need to escape all those slashes *again*, without escaping the
570
- // // one that we need for escaping the | character. As it works out,
571
- // // escaping an even number of slashes can be done by simply repeating
572
- // // it exactly after itself. That's why this trick works.
573
- // //
574
- // // I am sorry that you have to see this.
575
- // return $1 + $1 + $2 + '|'
576
- // })
577
- //
578
- // debug('tail=%j\n %s', tail, tail, pl, re)
579
- // const t = pl.type === '*' ? star : pl.type === '?' ? qmark : '\\' + pl.type
580
- //
581
- // hasMagic = true
582
- // re = re.slice(0, pl.reStart) + t + '\\(' + tail
583
- // }
584
- //
585
- // // handle trailing things that only matter at the very end.
586
- // clearStateChar()
587
- // if (escaping) {
588
- // // trailing \\
589
- // re += '\\\\'
590
- // }
591
- //
592
- // // only need to apply the nodot start if the re starts with
593
- // // something that could conceivably capture a dot
594
- // const addPatternStart = addPatternStartSet[re.charAt(0)]
595
- //
596
- // // Hack to work around lack of negative lookbehind in JS
597
- // // A pattern like: *.!(x).!(y|z) needs to ensure that a name
598
- // // like 'a.xyz.yz' doesn't match. So, the first negative
599
- // // lookahead, has to look ALL the way ahead, to the end of
600
- // // the pattern.
601
- // for (let n = negativeLists.length - 1; n > -1; n--) {
602
- // const nl = negativeLists[n]
603
- //
604
- // const nlBefore = re.slice(0, nl.reStart)
605
- // const nlFirst = re.slice(nl.reStart, nl.reEnd - 8)
606
- // let nlAfter = re.slice(nl.reEnd)
607
- // const nlLast = re.slice(nl.reEnd - 8, nl.reEnd) + nlAfter
608
- //
609
- // // Handle nested stuff like *(*.js|!(*.json)), where open parens
610
- // // mean that we should *not* include the ) in the bit that is considered
611
- // // "after" the negated section.
612
- // const closeParensBefore = nlBefore.split(')').length
613
- // const openParensBefore = nlBefore.split('(').length - closeParensBefore
614
- // let cleanAfter = nlAfter
615
- // for (let i = 0; i < openParensBefore; i++) {
616
- // cleanAfter = cleanAfter.replace(/\)[+*?]?/, '')
617
- // }
618
- // nlAfter = cleanAfter
619
- //
620
- // const dollar = nlAfter === '' ? '(?:$|\\/)' : ''
621
- //
622
- // re = nlBefore + nlFirst + nlAfter + dollar + nlLast
623
- // }
624
- //
625
- // // if the re is not "" at this point, then we need to make sure
626
- // // it doesn't match against an empty path part.
627
- // // Otherwise a/* will match a/, which it should not.
628
- // if (re !== '' && hasMagic) {
629
- // re = '(?=.)' + re
630
- // }
631
- //
632
- // if (addPatternStart) {
633
- // re = patternStart() + re
634
- // }
635
- //
636
- // // if it's nocase, and the lcase/uppercase don't match, it's magic
637
- // if (options.nocase && !hasMagic && !options.nocaseMagicOnly) {
638
- // hasMagic = pattern.toUpperCase() !== pattern.toLowerCase()
639
- // }
640
- //
641
- // // skip the regexp for non-magical patterns
642
- // // unescape anything in it, though, so that it'll be
643
- // // an exact match against a file etc.
644
- // if (!hasMagic) {
645
- // return globUnescape(re)
646
- // }
647
- //
648
- // return re
649
- // }
650
- //# sourceMappingURL=parse.js.map