From 63183084f74110b03379950aae8be855051f2141 Mon Sep 17 00:00:00 2001 From: isaacs Date: Sat, 11 Feb 2023 13:09:36 -0800 Subject: [PATCH 1/2] optimize ???? patterns --- src/index.ts | 41 ++++++++++++++++++- tap-snapshots/test/basic.js.test.cjs | 60 ++++++++++++++++++++++++++++ test/patterns.js | 21 +++++++++- 3 files changed, 119 insertions(+), 3 deletions(-) diff --git a/src/index.ts b/src/index.ts index 14d32bdd..fd4d9e0e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -34,7 +34,7 @@ export const minimatch = ( export default minimatch // Optimized checking for the most common glob patterns. -const starDotExtRE = /^\*+(\.[^!?\*\[\(]*)$/ +const starDotExtRE = /^\*+([^+@!?\*\[\(]*)$/ const starDotExtTest = (ext: string) => (f: string) => !f.startsWith('.') && f.endsWith(ext) const starDotExtTestDot = (ext: string) => (f: string) => f.endsWith(ext) @@ -55,6 +55,35 @@ const dotStarTest = (f: string) => f !== '.' && f !== '..' && f.startsWith('.') const starRE = /^\*+$/ const starTest = (f: string) => f.length !== 0 && !f.startsWith('.') const starTestDot = (f: string) => f.length !== 0 && f !== '.' && f !== '..' +const qmarksRE = /^\?+([^+@!?\*\[\(]*)?$/ +const qmarksTestNocase = ([$0, ext = '']: RegExpMatchArray) => { + const noext = qmarksTestNoExt([$0]) + if (!ext) return noext + ext = ext.toLowerCase() + return (f: string) => noext(f) && f.toLowerCase().endsWith(ext) +} +const qmarksTestNocaseDot = ([$0, ext = '']: RegExpMatchArray) => { + const noext = qmarksTestNoExtDot([$0]) + if (!ext) return noext + ext = ext.toLowerCase() + return (f: string) => noext(f) && f.toLowerCase().endsWith(ext) +} +const qmarksTestDot = ([$0, ext = '']: RegExpMatchArray) => { + const noext = qmarksTestNoExtDot([$0]) + return !ext ? noext : (f: string) => noext(f) && f.endsWith(ext) +} +const qmarksTest = ([$0, ext = '']: RegExpMatchArray) => { + const noext = qmarksTestNoExt([$0]) + return !ext ? noext : (f: string) => noext(f) && f.endsWith(ext) +} +const qmarksTestNoExt = ([$0]: RegExpMatchArray) => { + const len = $0.length + return (f: string) => f.length === len && !f.startsWith('.') +} +const qmarksTestNoExtDot = ([$0]: RegExpMatchArray) => { + const len = $0.length + return (f: string) => f.length === len && f !== '.' && f !== '..' +} /* c8 ignore start */ const platform = @@ -667,6 +696,16 @@ export class Minimatch { ? starDotExtTestDot : starDotExtTest )(m[1]) + } else if ((m = pattern.match(qmarksRE))) { + fastTest = ( + options.nocase + ? options.dot + ? qmarksTestNocaseDot + : qmarksTestNocase + : options.dot + ? qmarksTestDot + : qmarksTest + )(m) } else if ((m = pattern.match(starDotStarRE))) { fastTest = options.dot ? starDotStarTestDot : starDotStarTest } else if ((m = pattern.match(dotStarRE))) { diff --git a/tap-snapshots/test/basic.js.test.cjs b/tap-snapshots/test/basic.js.test.cjs index 60dc088c..5adda089 100644 --- a/tap-snapshots/test/basic.js.test.cjs +++ b/tap-snapshots/test/basic.js.test.cjs @@ -149,6 +149,10 @@ exports[`test/basic.js TAP basic tests > makeRe *c*?** 1`] = ` /^(?:(?!\\.)(?=.)[^/]*?c[^/]*?[^/][^/]*?[^/]*?)$/ ` +exports[`test/basic.js TAP basic tests > makeRe *js 1`] = ` +/^(?:(?!\\.)(?=.)[^/]*?js)$/ +` + exports[`test/basic.js TAP basic tests > makeRe +(a)!(b)+(c) 1`] = ` /^(?:(?=.)(?:(?!\\.)a)+(?:(?!(?:b)(?:c)+)[^/]*?)(?:c)+)$/ ` @@ -213,6 +217,10 @@ exports[`test/basic.js TAP basic tests > makeRe /^root:/{s/^[^:]*:[^:]*:([^:]*). /^(?:\\/\\^root:\\/\\{s\\/(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$\\/1\\/)$/ ` +exports[`test/basic.js TAP basic tests > makeRe ? 1`] = ` +/^(?:(?!\\.)(?=.)[^/])$/ +` + exports[`test/basic.js TAP basic tests > makeRe ?************c****?**** 1`] = ` /^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?)$/ ` @@ -237,6 +245,38 @@ exports[`test/basic.js TAP basic tests > makeRe ?***?****c 1`] = ` /^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/ ` +exports[`test/basic.js TAP basic tests > makeRe ?.js 1`] = ` +/^(?:(?!\\.)(?=.)[^/]\\.js)$/ +` + +exports[`test/basic.js TAP basic tests > makeRe ?.js 2`] = ` +/^(?:(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]\\.js)$/ +` + +exports[`test/basic.js TAP basic tests > makeRe ?.js 3`] = ` +/^(?:(?!\\.)(?=.)[^/]\\.js)$/i +` + +exports[`test/basic.js TAP basic tests > makeRe ?.js 4`] = ` +/^(?:(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]\\.js)$/i +` + +exports[`test/basic.js TAP basic tests > makeRe ?? 1`] = ` +/^(?:(?!\\.)(?=.)[^/][^/])$/ +` + +exports[`test/basic.js TAP basic tests > makeRe ?? 2`] = ` +/^(?:(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/][^/])$/ +` + +exports[`test/basic.js TAP basic tests > makeRe ?? 3`] = ` +/^(?:(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/][^/])$/i +` + +exports[`test/basic.js TAP basic tests > makeRe ?? 4`] = ` +/^(?:(?!\\.)(?=.)[^/][^/])$/i +` + exports[`test/basic.js TAP basic tests > makeRe ??**********?****? 1`] = ` /^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/])$/ ` @@ -245,6 +285,26 @@ exports[`test/basic.js TAP basic tests > makeRe ??**********?****c 1`] = ` /^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/ ` +exports[`test/basic.js TAP basic tests > makeRe ??? 1`] = ` +/^(?:(?!\\.)(?=.)[^/][^/][^/])$/ +` + +exports[`test/basic.js TAP basic tests > makeRe ??? 2`] = ` +/^(?:(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/][^/][^/])$/ +` + +exports[`test/basic.js TAP basic tests > makeRe ?js 1`] = ` +/^(?:(?!\\.)(?=.)[^/]js)$/ +` + +exports[`test/basic.js TAP basic tests > makeRe ?js 2`] = ` +/^(?:(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]js)$/ +` + +exports[`test/basic.js TAP basic tests > makeRe ?js 3`] = ` +/^(?:(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]js)$/i +` + exports[`test/basic.js TAP basic tests > makeRe @(*|.*) 1`] = ` /^(?:(?=.)(?:(?!\\.)[^/]*?|\\.[^/]*?))$/ ` diff --git a/test/patterns.js b/test/patterns.js index 309fb704..3594eb28 100644 --- a/test/patterns.js +++ b/test/patterns.js @@ -364,13 +364,30 @@ module.exports = [ 'a', 'a.js', 'js', + 'JS', 'a.JS', '.a.JS', '.JS', '.', '..', ]), + ['?', ['a']], + ['??', ['js', 'JS']], + ['??', ['js', 'JS', '.a'], { dot: true }], + ['??', ['js', 'JS', '.a'], { dot: true, nocase: true }], + ['??', ['js', 'JS'], { nocase: true }], + ['???', []], + ['???', ['.js', '.JS'], { dot: true }], + ['?.js', ['a.js']], + ['?js', []], + ['?.js', ['a.js'], { dot: true }], + ['?js', ['.js'], { dot: true }], + ['?.js', ['a.js', 'a.JS'], { nocase: true }], + ['?js', ['.js', '.JS'], {dot: true, nocase: true}], + ['?.js', ['a.js', 'a.JS'], { dot: true, nocase: true }], + ['*.js', ['a.js']], + ['*js', ['a.js', 'js']], ['*.js', ['a.js', '.a.js', '.js'], { dot: true }], ['*.js', ['a.js', 'a.JS'], { nocase: true }], [ @@ -385,10 +402,10 @@ module.exports = [ { dot: true }, ], ['.*', ['.a', '.a.js', '.js', '.a.JS', '.JS']], - ['*', ['a', 'a.js', 'js', 'a.JS']], + ['*', ['a', 'a.js', 'js', 'a.JS', 'JS']], [ '*', - ['.a', '.a.js', '.js', 'a', 'a.js', 'js', 'a.JS', '.a.JS', '.JS'], + ['.a', '.a.js', '.js', 'a', 'a.js', 'js', 'a.JS', '.a.JS', '.JS', 'JS'], { dot: true }, ], ] From ee4861b752dc5f7f4a7e5c21b90c3f66354838c6 Mon Sep 17 00:00:00 2001 From: isaacs Date: Sat, 11 Feb 2023 13:09:47 -0800 Subject: [PATCH 2/2] 6.1.8 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 81b960ab..11da38dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "minimatch", - "version": "6.1.7", + "version": "6.1.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "minimatch", - "version": "6.1.7", + "version": "6.1.8", "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" diff --git a/package.json b/package.json index 0fd30606..041e3ca4 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Isaac Z. Schlueter (http://blog.izs.me)", "name": "minimatch", "description": "a glob matcher in javascript", - "version": "6.1.7", + "version": "6.1.8", "repository": { "type": "git", "url": "git://github.com/isaacs/minimatch.git"