Skip to content

Commit 6318308

Browse files
committed
optimize ???? patterns
1 parent 61df471 commit 6318308

File tree

3 files changed

+119
-3
lines changed

3 files changed

+119
-3
lines changed

src/index.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export const minimatch = (
3434
export default minimatch
3535

3636
// Optimized checking for the most common glob patterns.
37-
const starDotExtRE = /^\*+(\.[^!?\*\[\(]*)$/
37+
const starDotExtRE = /^\*+([^+@!?\*\[\(]*)$/
3838
const starDotExtTest = (ext: string) => (f: string) =>
3939
!f.startsWith('.') && f.endsWith(ext)
4040
const starDotExtTestDot = (ext: string) => (f: string) => f.endsWith(ext)
@@ -55,6 +55,35 @@ const dotStarTest = (f: string) => f !== '.' && f !== '..' && f.startsWith('.')
5555
const starRE = /^\*+$/
5656
const starTest = (f: string) => f.length !== 0 && !f.startsWith('.')
5757
const starTestDot = (f: string) => f.length !== 0 && f !== '.' && f !== '..'
58+
const qmarksRE = /^\?+([^+@!?\*\[\(]*)?$/
59+
const qmarksTestNocase = ([$0, ext = '']: RegExpMatchArray) => {
60+
const noext = qmarksTestNoExt([$0])
61+
if (!ext) return noext
62+
ext = ext.toLowerCase()
63+
return (f: string) => noext(f) && f.toLowerCase().endsWith(ext)
64+
}
65+
const qmarksTestNocaseDot = ([$0, ext = '']: RegExpMatchArray) => {
66+
const noext = qmarksTestNoExtDot([$0])
67+
if (!ext) return noext
68+
ext = ext.toLowerCase()
69+
return (f: string) => noext(f) && f.toLowerCase().endsWith(ext)
70+
}
71+
const qmarksTestDot = ([$0, ext = '']: RegExpMatchArray) => {
72+
const noext = qmarksTestNoExtDot([$0])
73+
return !ext ? noext : (f: string) => noext(f) && f.endsWith(ext)
74+
}
75+
const qmarksTest = ([$0, ext = '']: RegExpMatchArray) => {
76+
const noext = qmarksTestNoExt([$0])
77+
return !ext ? noext : (f: string) => noext(f) && f.endsWith(ext)
78+
}
79+
const qmarksTestNoExt = ([$0]: RegExpMatchArray) => {
80+
const len = $0.length
81+
return (f: string) => f.length === len && !f.startsWith('.')
82+
}
83+
const qmarksTestNoExtDot = ([$0]: RegExpMatchArray) => {
84+
const len = $0.length
85+
return (f: string) => f.length === len && f !== '.' && f !== '..'
86+
}
5887

5988
/* c8 ignore start */
6089
const platform =
@@ -667,6 +696,16 @@ export class Minimatch {
667696
? starDotExtTestDot
668697
: starDotExtTest
669698
)(m[1])
699+
} else if ((m = pattern.match(qmarksRE))) {
700+
fastTest = (
701+
options.nocase
702+
? options.dot
703+
? qmarksTestNocaseDot
704+
: qmarksTestNocase
705+
: options.dot
706+
? qmarksTestDot
707+
: qmarksTest
708+
)(m)
670709
} else if ((m = pattern.match(starDotStarRE))) {
671710
fastTest = options.dot ? starDotStarTestDot : starDotStarTest
672711
} else if ((m = pattern.match(dotStarRE))) {

tap-snapshots/test/basic.js.test.cjs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,10 @@ exports[`test/basic.js TAP basic tests > makeRe *c*?** 1`] = `
149149
/^(?:(?!\\.)(?=.)[^/]*?c[^/]*?[^/][^/]*?[^/]*?)$/
150150
`
151151

152+
exports[`test/basic.js TAP basic tests > makeRe *js 1`] = `
153+
/^(?:(?!\\.)(?=.)[^/]*?js)$/
154+
`
155+
152156
exports[`test/basic.js TAP basic tests > makeRe +(a)!(b)+(c) 1`] = `
153157
/^(?:(?=.)(?:(?!\\.)a)+(?:(?!(?:b)(?:c)+)[^/]*?)(?:c)+)$/
154158
`
@@ -213,6 +217,10 @@ exports[`test/basic.js TAP basic tests > makeRe /^root:/{s/^[^:]*:[^:]*:([^:]*).
213217
/^(?:\\/\\^root:\\/\\{s\\/(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$\\/1\\/)$/
214218
`
215219

220+
exports[`test/basic.js TAP basic tests > makeRe ? 1`] = `
221+
/^(?:(?!\\.)(?=.)[^/])$/
222+
`
223+
216224
exports[`test/basic.js TAP basic tests > makeRe ?************c****?**** 1`] = `
217225
/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?)$/
218226
`
@@ -237,6 +245,38 @@ exports[`test/basic.js TAP basic tests > makeRe ?***?****c 1`] = `
237245
/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/
238246
`
239247

248+
exports[`test/basic.js TAP basic tests > makeRe ?.js 1`] = `
249+
/^(?:(?!\\.)(?=.)[^/]\\.js)$/
250+
`
251+
252+
exports[`test/basic.js TAP basic tests > makeRe ?.js 2`] = `
253+
/^(?:(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]\\.js)$/
254+
`
255+
256+
exports[`test/basic.js TAP basic tests > makeRe ?.js 3`] = `
257+
/^(?:(?!\\.)(?=.)[^/]\\.js)$/i
258+
`
259+
260+
exports[`test/basic.js TAP basic tests > makeRe ?.js 4`] = `
261+
/^(?:(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]\\.js)$/i
262+
`
263+
264+
exports[`test/basic.js TAP basic tests > makeRe ?? 1`] = `
265+
/^(?:(?!\\.)(?=.)[^/][^/])$/
266+
`
267+
268+
exports[`test/basic.js TAP basic tests > makeRe ?? 2`] = `
269+
/^(?:(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/][^/])$/
270+
`
271+
272+
exports[`test/basic.js TAP basic tests > makeRe ?? 3`] = `
273+
/^(?:(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/][^/])$/i
274+
`
275+
276+
exports[`test/basic.js TAP basic tests > makeRe ?? 4`] = `
277+
/^(?:(?!\\.)(?=.)[^/][^/])$/i
278+
`
279+
240280
exports[`test/basic.js TAP basic tests > makeRe ??**********?****? 1`] = `
241281
/^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/])$/
242282
`
@@ -245,6 +285,26 @@ exports[`test/basic.js TAP basic tests > makeRe ??**********?****c 1`] = `
245285
/^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/
246286
`
247287

288+
exports[`test/basic.js TAP basic tests > makeRe ??? 1`] = `
289+
/^(?:(?!\\.)(?=.)[^/][^/][^/])$/
290+
`
291+
292+
exports[`test/basic.js TAP basic tests > makeRe ??? 2`] = `
293+
/^(?:(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/][^/][^/])$/
294+
`
295+
296+
exports[`test/basic.js TAP basic tests > makeRe ?js 1`] = `
297+
/^(?:(?!\\.)(?=.)[^/]js)$/
298+
`
299+
300+
exports[`test/basic.js TAP basic tests > makeRe ?js 2`] = `
301+
/^(?:(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]js)$/
302+
`
303+
304+
exports[`test/basic.js TAP basic tests > makeRe ?js 3`] = `
305+
/^(?:(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]js)$/i
306+
`
307+
248308
exports[`test/basic.js TAP basic tests > makeRe @(*|.*) 1`] = `
249309
/^(?:(?=.)(?:(?!\\.)[^/]*?|\\.[^/]*?))$/
250310
`

test/patterns.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,13 +364,30 @@ module.exports = [
364364
'a',
365365
'a.js',
366366
'js',
367+
'JS',
367368
'a.JS',
368369
'.a.JS',
369370
'.JS',
370371
'.',
371372
'..',
372373
]),
374+
['?', ['a']],
375+
['??', ['js', 'JS']],
376+
['??', ['js', 'JS', '.a'], { dot: true }],
377+
['??', ['js', 'JS', '.a'], { dot: true, nocase: true }],
378+
['??', ['js', 'JS'], { nocase: true }],
379+
['???', []],
380+
['???', ['.js', '.JS'], { dot: true }],
381+
['?.js', ['a.js']],
382+
['?js', []],
383+
['?.js', ['a.js'], { dot: true }],
384+
['?js', ['.js'], { dot: true }],
385+
['?.js', ['a.js', 'a.JS'], { nocase: true }],
386+
['?js', ['.js', '.JS'], {dot: true, nocase: true}],
387+
['?.js', ['a.js', 'a.JS'], { dot: true, nocase: true }],
388+
373389
['*.js', ['a.js']],
390+
['*js', ['a.js', 'js']],
374391
['*.js', ['a.js', '.a.js', '.js'], { dot: true }],
375392
['*.js', ['a.js', 'a.JS'], { nocase: true }],
376393
[
@@ -385,10 +402,10 @@ module.exports = [
385402
{ dot: true },
386403
],
387404
['.*', ['.a', '.a.js', '.js', '.a.JS', '.JS']],
388-
['*', ['a', 'a.js', 'js', 'a.JS']],
405+
['*', ['a', 'a.js', 'js', 'a.JS', 'JS']],
389406
[
390407
'*',
391-
['.a', '.a.js', '.js', 'a', 'a.js', 'js', 'a.JS', '.a.JS', '.JS'],
408+
['.a', '.a.js', '.js', 'a', 'a.js', 'js', 'a.JS', '.a.JS', '.JS', 'JS'],
392409
{ dot: true },
393410
],
394411
]

0 commit comments

Comments
 (0)