minimatch 5.1.4 → 6.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.
package/minimatch.js DELETED
@@ -1,913 +0,0 @@
1
- const minimatch = module.exports = (p, pattern, options = {}) => {
2
- assertValidPattern(pattern)
3
-
4
- // shortcut: comments match nothing.
5
- if (!options.nocomment && pattern.charAt(0) === '#') {
6
- return false
7
- }
8
-
9
- return new Minimatch(pattern, options).match(p)
10
- }
11
-
12
- module.exports = minimatch
13
-
14
- const path = require('./lib/path.js')
15
- minimatch.sep = path.sep
16
-
17
- const GLOBSTAR = Symbol('globstar **')
18
- minimatch.GLOBSTAR = GLOBSTAR
19
- const expand = require('brace-expansion')
20
-
21
- const plTypes = {
22
- '!': { open: '(?:(?!(?:', close: '))[^/]*?)'},
23
- '?': { open: '(?:', close: ')?' },
24
- '+': { open: '(?:', close: ')+' },
25
- '*': { open: '(?:', close: ')*' },
26
- '@': { open: '(?:', close: ')' }
27
- }
28
-
29
- // any single thing other than /
30
- // don't need to escape / when using new RegExp()
31
- const qmark = '[^/]'
32
-
33
- // * => any number of characters
34
- const star = qmark + '*?'
35
-
36
- // ** when dots are allowed. Anything goes, except .. and .
37
- // not (^ or / followed by one or two dots followed by $ or /),
38
- // followed by anything, any number of times.
39
- const twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?'
40
-
41
- // not a ^ or / followed by a dot,
42
- // followed by anything, any number of times.
43
- const twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'
44
-
45
- // "abc" -> { a:true, b:true, c:true }
46
- const charSet = s => s.split('').reduce((set, c) => {
47
- set[c] = true
48
- return set
49
- }, {})
50
-
51
- // characters that need to be escaped in RegExp.
52
- const reSpecials = charSet('().*{}+?[]^$\\!')
53
-
54
- // characters that indicate we have to add the pattern start
55
- const addPatternStartSet = charSet('[.(')
56
-
57
- // normalizes slashes.
58
- const slashSplit = /\/+/
59
-
60
- minimatch.filter = (pattern, options = {}) =>
61
- (p, i, list) => minimatch(p, pattern, options)
62
-
63
- const ext = (a, b = {}) => {
64
- const t = {}
65
- Object.keys(a).forEach(k => t[k] = a[k])
66
- Object.keys(b).forEach(k => t[k] = b[k])
67
- return t
68
- }
69
-
70
- minimatch.defaults = def => {
71
- if (!def || typeof def !== 'object' || !Object.keys(def).length) {
72
- return minimatch
73
- }
74
-
75
- const orig = minimatch
76
-
77
- const m = (p, pattern, options) => orig(p, pattern, ext(def, options))
78
- m.Minimatch = class Minimatch extends orig.Minimatch {
79
- constructor (pattern, options) {
80
- super(pattern, ext(def, options))
81
- }
82
- }
83
- m.Minimatch.defaults = options => orig.defaults(ext(def, options)).Minimatch
84
- m.filter = (pattern, options) => orig.filter(pattern, ext(def, options))
85
- m.defaults = options => orig.defaults(ext(def, options))
86
- m.makeRe = (pattern, options) => orig.makeRe(pattern, ext(def, options))
87
- m.braceExpand = (pattern, options) => orig.braceExpand(pattern, ext(def, options))
88
- m.match = (list, pattern, options) => orig.match(list, pattern, ext(def, options))
89
-
90
- return m
91
- }
92
-
93
-
94
-
95
-
96
-
97
- // Brace expansion:
98
- // a{b,c}d -> abd acd
99
- // a{b,}c -> abc ac
100
- // a{0..3}d -> a0d a1d a2d a3d
101
- // a{b,c{d,e}f}g -> abg acdfg acefg
102
- // a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
103
- //
104
- // Invalid sets are not expanded.
105
- // a{2..}b -> a{2..}b
106
- // a{b}c -> a{b}c
107
- minimatch.braceExpand = (pattern, options) => braceExpand(pattern, options)
108
-
109
- const braceExpand = (pattern, options = {}) => {
110
- assertValidPattern(pattern)
111
-
112
- // Thanks to Yeting Li <https://github.com/yetingli> for
113
- // improving this regexp to avoid a ReDOS vulnerability.
114
- if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
115
- // shortcut. no need to expand.
116
- return [pattern]
117
- }
118
-
119
- return expand(pattern)
120
- }
121
-
122
- const MAX_PATTERN_LENGTH = 1024 * 64
123
- const assertValidPattern = pattern => {
124
- if (typeof pattern !== 'string') {
125
- throw new TypeError('invalid pattern')
126
- }
127
-
128
- if (pattern.length > MAX_PATTERN_LENGTH) {
129
- throw new TypeError('pattern is too long')
130
- }
131
- }
132
-
133
- // parse a component of the expanded set.
134
- // At this point, no pattern may contain "/" in it
135
- // so we're going to return a 2d array, where each entry is the full
136
- // pattern, split on '/', and then turned into a regular expression.
137
- // A regexp is made at the end which joins each array with an
138
- // escaped /, and another full one which joins each regexp with |.
139
- //
140
- // Following the lead of Bash 4.1, note that "**" only has special meaning
141
- // when it is the *only* thing in a path portion. Otherwise, any series
142
- // of * is equivalent to a single *. Globstar behavior is enabled by
143
- // default, and can be disabled by setting options.noglobstar.
144
- const SUBPARSE = Symbol('subparse')
145
-
146
- minimatch.makeRe = (pattern, options) =>
147
- new Minimatch(pattern, options || {}).makeRe()
148
-
149
- minimatch.match = (list, pattern, options = {}) => {
150
- const mm = new Minimatch(pattern, options)
151
- list = list.filter(f => mm.match(f))
152
- if (mm.options.nonull && !list.length) {
153
- list.push(pattern)
154
- }
155
- return list
156
- }
157
-
158
- // replace stuff like \* with *
159
- const globUnescape = s => s.replace(/\\(.)/g, '$1')
160
- const charUnescape = s => s.replace(/\\([^-\]])/g, '$1')
161
- const regExpEscape = s => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
162
- const braExpEscape = s => s.replace(/[[\]\\]/g, '\\$&')
163
-
164
- class Minimatch {
165
- constructor (pattern, options) {
166
- assertValidPattern(pattern)
167
-
168
- if (!options) options = {}
169
-
170
- this.options = options
171
- this.set = []
172
- this.pattern = pattern
173
- this.windowsPathsNoEscape = !!options.windowsPathsNoEscape ||
174
- options.allowWindowsEscape === false
175
- if (this.windowsPathsNoEscape) {
176
- this.pattern = this.pattern.replace(/\\/g, '/')
177
- }
178
- this.regexp = null
179
- this.negate = false
180
- this.comment = false
181
- this.empty = false
182
- this.partial = !!options.partial
183
-
184
- // make the set of regexps etc.
185
- this.make()
186
- }
187
-
188
- debug () {}
189
-
190
- make () {
191
- const pattern = this.pattern
192
- const options = this.options
193
-
194
- // empty patterns and comments match nothing.
195
- if (!options.nocomment && pattern.charAt(0) === '#') {
196
- this.comment = true
197
- return
198
- }
199
- if (!pattern) {
200
- this.empty = true
201
- return
202
- }
203
-
204
- // step 1: figure out negation, etc.
205
- this.parseNegate()
206
-
207
- // step 2: expand braces
208
- let set = this.globSet = this.braceExpand()
209
-
210
- if (options.debug) this.debug = (...args) => console.error(...args)
211
-
212
- this.debug(this.pattern, set)
213
-
214
- // step 3: now we have a set, so turn each one into a series of path-portion
215
- // matching patterns.
216
- // These will be regexps, except in the case of "**", which is
217
- // set to the GLOBSTAR object for globstar behavior,
218
- // and will not contain any / characters
219
- set = this.globParts = set.map(s => s.split(slashSplit))
220
-
221
- this.debug(this.pattern, set)
222
-
223
- // glob --> regexps
224
- set = set.map((s, si, set) => s.map(this.parse, this))
225
-
226
- this.debug(this.pattern, set)
227
-
228
- // filter out everything that didn't compile properly.
229
- set = set.filter(s => s.indexOf(false) === -1)
230
-
231
- this.debug(this.pattern, set)
232
-
233
- this.set = set
234
- }
235
-
236
- parseNegate () {
237
- if (this.options.nonegate) return
238
-
239
- const pattern = this.pattern
240
- let negate = false
241
- let negateOffset = 0
242
-
243
- for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {
244
- negate = !negate
245
- negateOffset++
246
- }
247
-
248
- if (negateOffset) this.pattern = pattern.slice(negateOffset)
249
- this.negate = negate
250
- }
251
-
252
- // set partial to true to test if, for example,
253
- // "/a/b" matches the start of "/*/b/*/d"
254
- // Partial means, if you run out of file before you run
255
- // out of pattern, then that's fine, as long as all
256
- // the parts match.
257
- matchOne (file, pattern, partial) {
258
- var options = this.options
259
-
260
- this.debug('matchOne',
261
- { 'this': this, file: file, pattern: pattern })
262
-
263
- this.debug('matchOne', file.length, pattern.length)
264
-
265
- for (var fi = 0,
266
- pi = 0,
267
- fl = file.length,
268
- pl = pattern.length
269
- ; (fi < fl) && (pi < pl)
270
- ; fi++, pi++) {
271
- this.debug('matchOne loop')
272
- var p = pattern[pi]
273
- var f = file[fi]
274
-
275
- this.debug(pattern, p, f)
276
-
277
- // should be impossible.
278
- // some invalid regexp stuff in the set.
279
- /* istanbul ignore if */
280
- if (p === false) return false
281
-
282
- if (p === GLOBSTAR) {
283
- this.debug('GLOBSTAR', [pattern, p, f])
284
-
285
- // "**"
286
- // a/**/b/**/c would match the following:
287
- // a/b/x/y/z/c
288
- // a/x/y/z/b/c
289
- // a/b/x/b/x/c
290
- // a/b/c
291
- // To do this, take the rest of the pattern after
292
- // the **, and see if it would match the file remainder.
293
- // If so, return success.
294
- // If not, the ** "swallows" a segment, and try again.
295
- // This is recursively awful.
296
- //
297
- // a/**/b/**/c matching a/b/x/y/z/c
298
- // - a matches a
299
- // - doublestar
300
- // - matchOne(b/x/y/z/c, b/**/c)
301
- // - b matches b
302
- // - doublestar
303
- // - matchOne(x/y/z/c, c) -> no
304
- // - matchOne(y/z/c, c) -> no
305
- // - matchOne(z/c, c) -> no
306
- // - matchOne(c, c) yes, hit
307
- var fr = fi
308
- var pr = pi + 1
309
- if (pr === pl) {
310
- this.debug('** at the end')
311
- // a ** at the end will just swallow the rest.
312
- // We have found a match.
313
- // however, it will not swallow /.x, unless
314
- // options.dot is set.
315
- // . and .. are *never* matched by **, for explosively
316
- // exponential reasons.
317
- for (; fi < fl; fi++) {
318
- if (file[fi] === '.' || file[fi] === '..' ||
319
- (!options.dot && file[fi].charAt(0) === '.')) return false
320
- }
321
- return true
322
- }
323
-
324
- // ok, let's see if we can swallow whatever we can.
325
- while (fr < fl) {
326
- var swallowee = file[fr]
327
-
328
- this.debug('\nglobstar while', file, fr, pattern, pr, swallowee)
329
-
330
- // XXX remove this slice. Just pass the start index.
331
- if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
332
- this.debug('globstar found match!', fr, fl, swallowee)
333
- // found a match.
334
- return true
335
- } else {
336
- // can't swallow "." or ".." ever.
337
- // can only swallow ".foo" when explicitly asked.
338
- if (swallowee === '.' || swallowee === '..' ||
339
- (!options.dot && swallowee.charAt(0) === '.')) {
340
- this.debug('dot detected!', file, fr, pattern, pr)
341
- break
342
- }
343
-
344
- // ** swallows a segment, and continue.
345
- this.debug('globstar swallow a segment, and continue')
346
- fr++
347
- }
348
- }
349
-
350
- // no match was found.
351
- // However, in partial mode, we can't say this is necessarily over.
352
- // If there's more *pattern* left, then
353
- /* istanbul ignore if */
354
- if (partial) {
355
- // ran out of file
356
- this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
357
- if (fr === fl) return true
358
- }
359
- return false
360
- }
361
-
362
- // something other than **
363
- // non-magic patterns just have to match exactly
364
- // patterns with magic have been turned into regexps.
365
- var hit
366
- if (typeof p === 'string') {
367
- hit = f === p
368
- this.debug('string match', p, f, hit)
369
- } else {
370
- hit = f.match(p)
371
- this.debug('pattern match', p, f, hit)
372
- }
373
-
374
- if (!hit) return false
375
- }
376
-
377
- // Note: ending in / means that we'll get a final ""
378
- // at the end of the pattern. This can only match a
379
- // corresponding "" at the end of the file.
380
- // If the file ends in /, then it can only match a
381
- // a pattern that ends in /, unless the pattern just
382
- // doesn't have any more for it. But, a/b/ should *not*
383
- // match "a/b/*", even though "" matches against the
384
- // [^/]*? pattern, except in partial mode, where it might
385
- // simply not be reached yet.
386
- // However, a/b/ should still satisfy a/*
387
-
388
- // now either we fell off the end of the pattern, or we're done.
389
- if (fi === fl && pi === pl) {
390
- // ran out of pattern and filename at the same time.
391
- // an exact hit!
392
- return true
393
- } else if (fi === fl) {
394
- // ran out of file, but still had pattern left.
395
- // this is ok if we're doing the match as part of
396
- // a glob fs traversal.
397
- return partial
398
- } else /* istanbul ignore else */ if (pi === pl) {
399
- // ran out of pattern, still have file left.
400
- // this is only acceptable if we're on the very last
401
- // empty segment of a file with a trailing slash.
402
- // a/* should match a/b/
403
- return (fi === fl - 1) && (file[fi] === '')
404
- }
405
-
406
- // should be unreachable.
407
- /* istanbul ignore next */
408
- throw new Error('wtf?')
409
- }
410
-
411
- braceExpand () {
412
- return braceExpand(this.pattern, this.options)
413
- }
414
-
415
- parse (pattern, isSub) {
416
- assertValidPattern(pattern)
417
-
418
- const options = this.options
419
-
420
- // shortcuts
421
- if (pattern === '**') {
422
- if (!options.noglobstar)
423
- return GLOBSTAR
424
- else
425
- pattern = '*'
426
- }
427
- if (pattern === '') return ''
428
-
429
- let re = ''
430
- let hasMagic = false
431
- let escaping = false
432
- // ? => one single character
433
- const patternListStack = []
434
- const negativeLists = []
435
- let stateChar
436
- let inClass = false
437
- let reClassStart = -1
438
- let classStart = -1
439
- let cs
440
- let pl
441
- let sp
442
- // . and .. never match anything that doesn't start with .,
443
- // even when options.dot is set.
444
- const patternStart = pattern.charAt(0) === '.' ? '' // anything
445
- // not (start or / followed by . or .. followed by / or end)
446
- : options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))'
447
- : '(?!\\.)'
448
-
449
- const clearStateChar = () => {
450
- if (stateChar) {
451
- // we had some state-tracking character
452
- // that wasn't consumed by this pass.
453
- switch (stateChar) {
454
- case '*':
455
- re += star
456
- hasMagic = true
457
- break
458
- case '?':
459
- re += qmark
460
- hasMagic = true
461
- break
462
- default:
463
- re += '\\' + stateChar
464
- break
465
- }
466
- this.debug('clearStateChar %j %j', stateChar, re)
467
- stateChar = false
468
- }
469
- }
470
-
471
- for (let i = 0, c; (i < pattern.length) && (c = pattern.charAt(i)); i++) {
472
- this.debug('%s\t%s %s %j', pattern, i, re, c)
473
-
474
- // skip over any that are escaped.
475
- if (escaping) {
476
- /* istanbul ignore next - completely not allowed, even escaped. */
477
- if (c === '/') {
478
- return false
479
- }
480
-
481
- if (reSpecials[c]) {
482
- re += '\\'
483
- }
484
- re += c
485
- escaping = false
486
- continue
487
- }
488
-
489
- switch (c) {
490
- /* istanbul ignore next */
491
- case '/': {
492
- // Should already be path-split by now.
493
- return false
494
- }
495
-
496
- case '\\':
497
- if (inClass && pattern.charAt(i + 1) === '-') {
498
- re += c
499
- continue
500
- }
501
-
502
- clearStateChar()
503
- escaping = true
504
- continue
505
-
506
- // the various stateChar values
507
- // for the "extglob" stuff.
508
- case '?':
509
- case '*':
510
- case '+':
511
- case '@':
512
- case '!':
513
- this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c)
514
-
515
- // all of those are literals inside a class, except that
516
- // the glob [!a] means [^a] in regexp
517
- if (inClass) {
518
- this.debug(' in class')
519
- if (c === '!' && i === classStart + 1) c = '^'
520
- re += c
521
- continue
522
- }
523
-
524
- // if we already have a stateChar, then it means
525
- // that there was something like ** or +? in there.
526
- // Handle the stateChar, then proceed with this one.
527
- this.debug('call clearStateChar %j', stateChar)
528
- clearStateChar()
529
- stateChar = c
530
- // if extglob is disabled, then +(asdf|foo) isn't a thing.
531
- // just clear the statechar *now*, rather than even diving into
532
- // the patternList stuff.
533
- if (options.noext) clearStateChar()
534
- continue
535
-
536
- case '(':
537
- if (inClass) {
538
- re += '('
539
- continue
540
- }
541
-
542
- if (!stateChar) {
543
- re += '\\('
544
- continue
545
- }
546
-
547
- patternListStack.push({
548
- type: stateChar,
549
- start: i - 1,
550
- reStart: re.length,
551
- open: plTypes[stateChar].open,
552
- close: plTypes[stateChar].close
553
- })
554
- // negation is (?:(?!js)[^/]*)
555
- re += stateChar === '!' ? '(?:(?!(?:' : '(?:'
556
- this.debug('plType %j %j', stateChar, re)
557
- stateChar = false
558
- continue
559
-
560
- case ')':
561
- if (inClass || !patternListStack.length) {
562
- re += '\\)'
563
- continue
564
- }
565
-
566
- clearStateChar()
567
- hasMagic = true
568
- pl = patternListStack.pop()
569
- // negation is (?:(?!js)[^/]*)
570
- // The others are (?:<pattern>)<type>
571
- re += pl.close
572
- if (pl.type === '!') {
573
- negativeLists.push(pl)
574
- }
575
- pl.reEnd = re.length
576
- continue
577
-
578
- case '|':
579
- if (inClass || !patternListStack.length) {
580
- re += '\\|'
581
- continue
582
- }
583
-
584
- clearStateChar()
585
- re += '|'
586
- continue
587
-
588
- // these are mostly the same in regexp and glob
589
- case '[':
590
- // swallow any state-tracking char before the [
591
- clearStateChar()
592
-
593
- if (inClass) {
594
- re += '\\' + c
595
- continue
596
- }
597
-
598
- inClass = true
599
- classStart = i
600
- reClassStart = re.length
601
- re += c
602
- continue
603
-
604
- case ']':
605
- // a right bracket shall lose its special
606
- // meaning and represent itself in
607
- // a bracket expression if it occurs
608
- // first in the list. -- POSIX.2 2.8.3.2
609
- if (i === classStart + 1 || !inClass) {
610
- re += '\\' + c
611
- continue
612
- }
613
-
614
- // split where the last [ was, make sure we don't have
615
- // an invalid re. if so, re-walk the contents of the
616
- // would-be class to re-translate any characters that
617
- // were passed through as-is
618
- // TODO: It would probably be faster to determine this
619
- // without a try/catch and a new RegExp, but it's tricky
620
- // to do safely. For now, this is safe and works.
621
- cs = pattern.substring(classStart + 1, i)
622
- try {
623
- RegExp('[' + braExpEscape(charUnescape(cs)) + ']')
624
- // looks good, finish up the class.
625
- re += c
626
- } catch (er) {
627
- // out of order ranges in JS are errors, but in glob syntax,
628
- // they're just a range that matches nothing.
629
- re = re.substring(0, reClassStart) + '(?:$.)' // match nothing ever
630
- }
631
- hasMagic = true
632
- inClass = false
633
- continue
634
-
635
- default:
636
- // swallow any state char that wasn't consumed
637
- clearStateChar()
638
-
639
- if (reSpecials[c] && !(c === '^' && inClass)) {
640
- re += '\\'
641
- }
642
-
643
- re += c
644
- break
645
-
646
- } // switch
647
- } // for
648
-
649
- // handle the case where we left a class open.
650
- // "[abc" is valid, equivalent to "\[abc"
651
- if (inClass) {
652
- // split where the last [ was, and escape it
653
- // this is a huge pita. We now have to re-walk
654
- // the contents of the would-be class to re-translate
655
- // any characters that were passed through as-is
656
- cs = pattern.slice(classStart + 1)
657
- sp = this.parse(cs, SUBPARSE)
658
- re = re.substring(0, reClassStart) + '\\[' + sp[0]
659
- hasMagic = hasMagic || sp[1]
660
- }
661
-
662
- // handle the case where we had a +( thing at the *end*
663
- // of the pattern.
664
- // each pattern list stack adds 3 chars, and we need to go through
665
- // and escape any | chars that were passed through as-is for the regexp.
666
- // Go through and escape them, taking care not to double-escape any
667
- // | chars that were already escaped.
668
- for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
669
- let tail
670
- tail = re.slice(pl.reStart + pl.open.length)
671
- this.debug('setting tail', re, pl)
672
- // maybe some even number of \, then maybe 1 \, followed by a |
673
- tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, (_, $1, $2) => {
674
- /* istanbul ignore else - should already be done */
675
- if (!$2) {
676
- // the | isn't already escaped, so escape it.
677
- $2 = '\\'
678
- }
679
-
680
- // need to escape all those slashes *again*, without escaping the
681
- // one that we need for escaping the | character. As it works out,
682
- // escaping an even number of slashes can be done by simply repeating
683
- // it exactly after itself. That's why this trick works.
684
- //
685
- // I am sorry that you have to see this.
686
- return $1 + $1 + $2 + '|'
687
- })
688
-
689
- this.debug('tail=%j\n %s', tail, tail, pl, re)
690
- const t = pl.type === '*' ? star
691
- : pl.type === '?' ? qmark
692
- : '\\' + pl.type
693
-
694
- hasMagic = true
695
- re = re.slice(0, pl.reStart) + t + '\\(' + tail
696
- }
697
-
698
- // handle trailing things that only matter at the very end.
699
- clearStateChar()
700
- if (escaping) {
701
- // trailing \\
702
- re += '\\\\'
703
- }
704
-
705
- // only need to apply the nodot start if the re starts with
706
- // something that could conceivably capture a dot
707
- const addPatternStart = addPatternStartSet[re.charAt(0)]
708
-
709
- // Hack to work around lack of negative lookbehind in JS
710
- // A pattern like: *.!(x).!(y|z) needs to ensure that a name
711
- // like 'a.xyz.yz' doesn't match. So, the first negative
712
- // lookahead, has to look ALL the way ahead, to the end of
713
- // the pattern.
714
- for (let n = negativeLists.length - 1; n > -1; n--) {
715
- const nl = negativeLists[n]
716
-
717
- const nlBefore = re.slice(0, nl.reStart)
718
- const nlFirst = re.slice(nl.reStart, nl.reEnd - 8)
719
- let nlAfter = re.slice(nl.reEnd)
720
- const nlLast = re.slice(nl.reEnd - 8, nl.reEnd) + nlAfter
721
-
722
- // Handle nested stuff like *(*.js|!(*.json)), where open parens
723
- // mean that we should *not* include the ) in the bit that is considered
724
- // "after" the negated section.
725
- const openParensBefore = nlBefore.split('(').length - 1
726
- let cleanAfter = nlAfter
727
- for (let i = 0; i < openParensBefore; i++) {
728
- cleanAfter = cleanAfter.replace(/\)[+*?]?/, '')
729
- }
730
- nlAfter = cleanAfter
731
-
732
- const dollar = nlAfter === '' && isSub !== SUBPARSE ? '(?:$|\\/)' : ''
733
-
734
- re = nlBefore + nlFirst + nlAfter + dollar + nlLast
735
- }
736
-
737
- // if the re is not "" at this point, then we need to make sure
738
- // it doesn't match against an empty path part.
739
- // Otherwise a/* will match a/, which it should not.
740
- if (re !== '' && hasMagic) {
741
- re = '(?=.)' + re
742
- }
743
-
744
- if (addPatternStart) {
745
- re = patternStart + re
746
- }
747
-
748
- // parsing just a piece of a larger pattern.
749
- if (isSub === SUBPARSE) {
750
- return [re, hasMagic]
751
- }
752
-
753
- // if it's nocase, and the lcase/uppercase don't match, it's magic
754
- if (options.nocase && !hasMagic) {
755
- hasMagic = pattern.toUpperCase() !== pattern.toLowerCase()
756
- }
757
-
758
- // skip the regexp for non-magical patterns
759
- // unescape anything in it, though, so that it'll be
760
- // an exact match against a file etc.
761
- if (!hasMagic) {
762
- return globUnescape(pattern)
763
- }
764
-
765
- const flags = options.nocase ? 'i' : ''
766
- try {
767
- return Object.assign(new RegExp('^' + re + '$', flags), {
768
- _glob: pattern,
769
- _src: re,
770
- })
771
- } catch (er) /* istanbul ignore next - should be impossible */ {
772
- // If it was an invalid regular expression, then it can't match
773
- // anything. This trick looks for a character after the end of
774
- // the string, which is of course impossible, except in multi-line
775
- // mode, but it's not a /m regex.
776
- return new RegExp('$.')
777
- }
778
- }
779
-
780
- makeRe () {
781
- if (this.regexp || this.regexp === false) return this.regexp
782
-
783
- // at this point, this.set is a 2d array of partial
784
- // pattern strings, or "**".
785
- //
786
- // It's better to use .match(). This function shouldn't
787
- // be used, really, but it's pretty convenient sometimes,
788
- // when you just want to work with a regex.
789
- const set = this.set
790
-
791
- if (!set.length) {
792
- this.regexp = false
793
- return this.regexp
794
- }
795
- const options = this.options
796
-
797
- const twoStar = options.noglobstar ? star
798
- : options.dot ? twoStarDot
799
- : twoStarNoDot
800
- const flags = options.nocase ? 'i' : ''
801
-
802
- // coalesce globstars and regexpify non-globstar patterns
803
- // if it's the only item, then we just do one twoStar
804
- // if it's the first, and there are more, prepend (\/|twoStar\/)? to next
805
- // if it's the last, append (\/twoStar|) to previous
806
- // if it's in the middle, append (\/|\/twoStar\/) to previous
807
- // then filter out GLOBSTAR symbols
808
- let re = set.map(pattern => {
809
- pattern = pattern.map(p =>
810
- typeof p === 'string' ? regExpEscape(p)
811
- : p === GLOBSTAR ? GLOBSTAR
812
- : p._src
813
- ).reduce((set, p) => {
814
- if (!(set[set.length - 1] === GLOBSTAR && p === GLOBSTAR)) {
815
- set.push(p)
816
- }
817
- return set
818
- }, [])
819
- pattern.forEach((p, i) => {
820
- if (p !== GLOBSTAR || pattern[i-1] === GLOBSTAR) {
821
- return
822
- }
823
- if (i === 0) {
824
- if (pattern.length > 1) {
825
- pattern[i+1] = '(?:\\\/|' + twoStar + '\\\/)?' + pattern[i+1]
826
- } else {
827
- pattern[i] = twoStar
828
- }
829
- } else if (i === pattern.length - 1) {
830
- pattern[i-1] += '(?:\\\/|' + twoStar + ')?'
831
- } else {
832
- pattern[i-1] += '(?:\\\/|\\\/' + twoStar + '\\\/)' + pattern[i+1]
833
- pattern[i+1] = GLOBSTAR
834
- }
835
- })
836
- return pattern.filter(p => p !== GLOBSTAR).join('/')
837
- }).join('|')
838
-
839
- // must match entire pattern
840
- // ending in a * or ** will make it less strict.
841
- re = '^(?:' + re + ')$'
842
-
843
- // can match anything, as long as it's not this.
844
- if (this.negate) re = '^(?!' + re + ').*$'
845
-
846
- try {
847
- this.regexp = new RegExp(re, flags)
848
- } catch (ex) /* istanbul ignore next - should be impossible */ {
849
- this.regexp = false
850
- }
851
- return this.regexp
852
- }
853
-
854
- match (f, partial = this.partial) {
855
- this.debug('match', f, this.pattern)
856
- // short-circuit in the case of busted things.
857
- // comments, etc.
858
- if (this.comment) return false
859
- if (this.empty) return f === ''
860
-
861
- if (f === '/' && partial) return true
862
-
863
- const options = this.options
864
-
865
- // windows: need to use /, not \
866
- if (path.sep !== '/') {
867
- f = f.split(path.sep).join('/')
868
- }
869
-
870
- // treat the test path as a set of pathparts.
871
- f = f.split(slashSplit)
872
- this.debug(this.pattern, 'split', f)
873
-
874
- // just ONE of the pattern sets in this.set needs to match
875
- // in order for it to be valid. If negating, then just one
876
- // match means that we have failed.
877
- // Either way, return on the first hit.
878
-
879
- const set = this.set
880
- this.debug(this.pattern, 'set', set)
881
-
882
- // Find the basename of the path by looking for the last non-empty segment
883
- let filename
884
- for (let i = f.length - 1; i >= 0; i--) {
885
- filename = f[i]
886
- if (filename) break
887
- }
888
-
889
- for (let i = 0; i < set.length; i++) {
890
- const pattern = set[i]
891
- let file = f
892
- if (options.matchBase && pattern.length === 1) {
893
- file = [filename]
894
- }
895
- const hit = this.matchOne(file, pattern, partial)
896
- if (hit) {
897
- if (options.flipNegate) return true
898
- return !this.negate
899
- }
900
- }
901
-
902
- // didn't get any hits. this is success if it's a negative
903
- // pattern, failure otherwise.
904
- if (options.flipNegate) return false
905
- return this.negate
906
- }
907
-
908
- static defaults (def) {
909
- return minimatch.defaults(def).Minimatch
910
- }
911
- }
912
-
913
- minimatch.Minimatch = Minimatch