From 327cb6059f9340fa18cc7496be224ff9eb30f880 Mon Sep 17 00:00:00 2001 From: isaacs Date: Tue, 28 Feb 2023 22:20:04 -0800 Subject: [PATCH 1/2] Add escape(), unescape(), and Minimatch.hasMagic() Also, treat single-character brace classes as their literal character, without magic. So for example, `[f]` would be parsed as just `'f'`, and not treated as a magic pattern. --- README.md | 55 +- changelog.md | 6 + src/brace-expressions.ts | 56 +- src/escape.ts | 23 + src/index.ts | 38 +- src/unescape.ts | 25 + tap-snapshots/test/basic.js.test.cjs | 20 +- .../test/escape-has-magic.js.test.cjs | 2061 +++++++++++++++++ .../test/optimization-level-0.ts.test.cjs | 20 +- .../test/optimization-level-2.ts.test.cjs | 20 +- test/defaults.js | 33 +- test/escape-has-magic.js | 29 + test/patterns.js | 9 +- 13 files changed, 2328 insertions(+), 67 deletions(-) create mode 100644 src/escape.ts create mode 100644 src/unescape.ts create mode 100644 tap-snapshots/test/escape-has-magic.js.test.cjs create mode 100644 test/escape-has-magic.js diff --git a/README.md b/README.md index b8b51604..8a1c9e26 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ var mm = new Minimatch(pattern, options) ### Methods -- `makeRe` Generate the `regexp` member if necessary, and return it. +- `makeRe()` Generate the `regexp` member if necessary, and return it. Will return `false` if the pattern is invalid. - `match(fname)` Return true if the filename matches the pattern, or false otherwise. @@ -130,6 +130,21 @@ var mm = new Minimatch(pattern, options) filename, and match it against a single row in the `regExpSet`. This method is mainly for internal use, but is exposed so that it can be used by a glob-walker that needs to avoid excessive filesystem calls. +- `hasMagic()` Returns true if the parsed pattern contains any + magic characters. Returns false if all comparator parts are + string literals. If the `magicalBraces` option is set on the + constructor, then it will consider brace expansions which are + not otherwise magical to be magic. If not set, then a pattern + like `a{b,c}d` will return `false`, because neither `abd` nor + `acd` contain any special glob characters. + + This does **not** mean that the pattern string can be used as a + literal filename, as it may contain magic glob characters that + are escaped. For example, the pattern `\\*` or `[*]` would not + be considered to have magic, as the matching portion parses to + the literal string `'*'` and would match a path named `'*'`, + not `'\\*'` or `'[*]'`. The `minimatch.unescape()` method may + be used to remove escape characters. All other methods are internal, and will be called as necessary. @@ -150,6 +165,34 @@ supplied argument, suitable for use with `Array.filter`. Example: var javascripts = fileList.filter(minimatch.filter('*.js', { matchBase: true })) ``` +### minimatch.escape(pattern, options = {}) + +Escape all magic characters in a glob pattern, so that it will +only ever match literal strings + +If the `windowsPathsNoEscape` option is used, then characters are +escaped by wrapping in `[]`, because a magic character wrapped in +a character class can only be satisfied by that exact character. + +Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot +be escaped or unescaped. + +### minimatch.unescape(pattern, options = {}) + +Un-escape a glob string that may contain some escaped characters. + +If the `windowsPathsNoEscape` option is used, then square-brace +escapes are removed, but not backslash escapes. For example, it +will turn the string `'[*]'` into `*`, but it will not turn +`'\\*'` into `'*'`, becuase `\` is a path separator in +`windowsPathsNoEscape` mode. + +When `windowsPathsNoEscape` is not set, then both brace escapes +and backslash escapes are removed. + +Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot +be escaped or unescaped. + ### minimatch.match(list, pattern, options) Match against the list of @@ -212,6 +255,16 @@ When a match is not found by `minimatch.match`, return a list containing the pattern itself if this option is set. When not set, an empty list is returned if there are no matches. +### magicalBraces + +This only affects the results of the `Minimatch.hasMagic` method. + +If the pattern contains brace expansions, such as `a{b,c}d`, but +no other magic characters, then the `Minipass.hasMagic()` method +will return `false` by default. When this option set, it will +return `true` for brace expansion as well as other magic glob +characters. + ### matchBase If set, then patterns without slashes will be matched diff --git a/changelog.md b/changelog.md index 2b13c9f0..78b27af5 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,11 @@ # change log +## 7.4 + +- Add `escape()` method +- Add `unescape()` method +- Add `Minimatch.hasMagic()` method + ## 7.3 - Add support for posix character classes in a unicode-aware way. diff --git a/src/brace-expressions.ts b/src/brace-expressions.ts index 0476f83e..a2104d77 100644 --- a/src/brace-expressions.ts +++ b/src/brace-expressions.ts @@ -20,15 +20,21 @@ const posixClasses: { [k: string]: [e: string, u: boolean, n?: boolean] } = { } // only need to escape a few things inside of brace expressions -const regExpEscape = (s: string) => s.replace(/[[\]\\-]/g, '\\$&') - -const rangesToString = (ranges: string[]): string => { - return ( - ranges - // .map(r => r.replace(/[[\]]/g, '\\$&').replace(/^-/, '\\-')) - .join('') - ) -} +// escapes: [ \ ] - +const braceEscape = (s: string) => s.replace(/[[\]\\-]/g, '\\$&') +// escape all regexp magic characters +const regexpEscape = (s: string) => + s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') + +// everything has already been escaped, we just have to join +const rangesToString = (ranges: string[]): string => ranges.join('') + +export type ParseClassResult = [ + src: string, + uFlag: boolean, + consumed: number, + hasMagic: boolean +] // takes a glob string at a posix brace expression, and returns // an equivalent regular expression source, and boolean indicating @@ -39,7 +45,7 @@ const rangesToString = (ranges: string[]): string => { export const parseClass = ( glob: string, position: number -): [string, boolean, number] => { +): ParseClassResult => { const pos = position /* c8 ignore start */ if (glob.charAt(pos) !== '[') { @@ -84,7 +90,7 @@ export const parseClass = ( if (glob.startsWith(cls, i)) { // invalid, [a-[] is fine, but not [a-[:alpha]] if (rangeStart) { - return ['$.', false, glob.length - pos] + return ['$.', false, glob.length - pos, true] } i += cls.length if (neg) negs.push(unip) @@ -101,9 +107,9 @@ export const parseClass = ( // throw this range away if it's not valid, but others // can still match. if (c > rangeStart) { - ranges.push(regExpEscape(rangeStart) + '-' + regExpEscape(c)) + ranges.push(braceEscape(rangeStart) + '-' + braceEscape(c)) } else if (c === rangeStart) { - ranges.push(regExpEscape(c)) + ranges.push(braceEscape(c)) } rangeStart = '' i++ @@ -113,7 +119,7 @@ export const parseClass = ( // now might be the start of a range. // can be either c-d or c-] or c] or c] at this point if (glob.startsWith('-]', i + 1)) { - ranges.push(regExpEscape(c + '-')) + ranges.push(braceEscape(c + '-')) i += 2 continue } @@ -124,20 +130,34 @@ export const parseClass = ( } // not the start of a range, just a single character - ranges.push(regExpEscape(c)) + ranges.push(braceEscape(c)) i++ } if (endPos < i) { // didn't see the end of the class, not a valid class, // but might still be valid as a literal match. - return ['', false, 0] + return ['', false, 0, false] } // if we got no ranges and no negates, then we have a range that // cannot possibly match anything, and that poisons the whole glob if (!ranges.length && !negs.length) { - return ['$.', false, glob.length - pos] + return ['$.', false, glob.length - pos, true] + } + + // if we got one positive range, and it's a single character, then that's + // not actually a magic pattern, it's just that one literal character. + // we should not treat that as "magic", we should just return the literal + // character. [_] is a perfectly valid way to escape glob magic chars. + if ( + negs.length === 0 && + ranges.length === 1 && + /^\\?.$/.test(ranges[0]) && + !negate + ) { + const r = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0] + return [regexpEscape(r), false, endPos - pos, false] } const sranges = '[' + (negate ? '^' : '') + rangesToString(ranges) + ']' @@ -149,5 +169,5 @@ export const parseClass = ( ? sranges : snegs - return [comb, uflag, endPos - pos] + return [comb, uflag, endPos - pos, true] } diff --git a/src/escape.ts b/src/escape.ts new file mode 100644 index 00000000..54cae011 --- /dev/null +++ b/src/escape.ts @@ -0,0 +1,23 @@ +import { MinimatchOptions } from './index.js' +/** + * Escape all magic characters in a glob pattern. + * + * If the {@link windowsPathsNoEscape | GlobOptions.windowsPathsNoEscape} + * option is used, then characters are escaped by wrapping in `[]`, because + * a magic character wrapped in a character class can only be satisfied by + * that exact character. In this mode, `\` is _not_ escaped, because it is + * not interpreted as a magic character, but instead as a path separator. + */ +export const escape = ( + s: string, + { + windowsPathsNoEscape = false, + }: Pick = {} +) => { + // don't need to escape +@! because we escape the parens + // that make those magic, and escaping ! as [!] isn't valid, + // because [!]] is a valid glob class meaning not ']'. + return windowsPathsNoEscape + ? s.replace(/[?*()[\]]/g, '[$&]') + : s.replace(/[?*()[\]\\]/g, '\\$&') +} diff --git a/src/index.ts b/src/index.ts index 1b2cc2cd..9a898413 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,7 @@ import expand from 'brace-expansion' import { parseClass } from './brace-expressions.js' +import { escape } from './escape.js' +import { unescape } from './unescape.js' export interface MinimatchOptions { nobrace?: boolean @@ -15,6 +17,7 @@ export interface MinimatchOptions { dot?: boolean nocase?: boolean nocaseMagicOnly?: boolean + magicalBraces?: boolean matchBase?: boolean flipNegate?: boolean preserveMultipleSlashes?: boolean @@ -182,6 +185,16 @@ export const defaults = (def: MinimatchOptions): typeof minimatch => { } }, + unescape: ( + s: string, + options: Pick = {} + ) => orig.unescape(s, ext(def, options)), + + escape: ( + s: string, + options: Pick = {} + ) => orig.escape(s, ext(def, options)), + filter: (pattern: string, options: MinimatchOptions = {}) => orig.filter(pattern, ext(def, options)), @@ -353,6 +366,18 @@ export class Minimatch { this.make() } + hasMagic():boolean { + if (this.options.magicalBraces && this.set.length > 1) { + return true + } + for (const pattern of this.set) { + for (const part of pattern) { + if (typeof part !== 'string') return true + } + } + return false + } + debug(..._: any[]) {} make() { @@ -1182,12 +1207,12 @@ export class Minimatch { case '[': // swallow any state-tracking char before the [ clearStateChar() - const [src, needUflag, consumed] = parseClass(pattern, i) + const [src, needUflag, consumed, magic] = parseClass(pattern, i) if (consumed) { re += src uflag = uflag || needUflag i += consumed - 1 - hasMagic = true + hasMagic = hasMagic || magic } else { re += '\\[' } @@ -1303,7 +1328,7 @@ export class Minimatch { // unescape anything in it, though, so that it'll be // an exact match against a file etc. if (!hasMagic) { - return globUnescape(pattern) + return globUnescape(re) } const flags = (options.nocase ? 'i' : '') + (uflag ? 'u' : '') @@ -1496,5 +1521,10 @@ export class Minimatch { return minimatch.defaults(def).Minimatch } } - +/* c8 ignore start */ +export { escape } from './escape.js' +export { unescape } from './unescape.js' +/* c8 ignore stop */ minimatch.Minimatch = Minimatch +minimatch.escape = escape +minimatch.unescape = unescape diff --git a/src/unescape.ts b/src/unescape.ts new file mode 100644 index 00000000..67cb7cae --- /dev/null +++ b/src/unescape.ts @@ -0,0 +1,25 @@ +import { MinimatchOptions } from './index.js' +/** + * Un-escape a string that has been escaped with {@link escape}. + * + * If the {@link windowsPathsNoEscape} option is used, then square-brace + * escapes are removed, but not backslash escapes. For example, it will turn + * the string `'[*]'` into `*`, but it will not turn `'\\*'` into `'*'`, + * becuase `\` is a path separator in `windowsPathsNoEscape` mode. + * + * When `windowsPathsNoEscape` is not set, then both brace escapes and + * backslash escapes are removed. + * + * Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot be escaped + * or unescaped. + */ +export const unescape = ( + s: string, + { + windowsPathsNoEscape = false, + }: Pick = {} +) => { + return windowsPathsNoEscape + ? s.replace(/\[([^\/\\])\]/g, '$1') + : s.replace(/((?!\\).|^)\[([^\/])\]/g, '$1$2').replace(/\\([^\/])/g, '$1') +} diff --git a/tap-snapshots/test/basic.js.test.cjs b/tap-snapshots/test/basic.js.test.cjs index 574b206f..2f826119 100644 --- a/tap-snapshots/test/basic.js.test.cjs +++ b/tap-snapshots/test/basic.js.test.cjs @@ -334,11 +334,11 @@ exports[`test/basic.js TAP basic tests > makeRe @(.*|js) 1`] = ` ` exports[`test/basic.js TAP basic tests > makeRe @(a|a[(])b 1`] = ` -/^(?:(?=.)(?:(?!\\.)a|(?!\\.)a[(])b)$/ +/^(?:(?=.)(?:(?!\\.)a|(?!\\.)a\\()b)$/ ` exports[`test/basic.js TAP basic tests > makeRe @(a|a[)])b 1`] = ` -/^(?:(?=.)(?:(?!\\.)a|(?!\\.)a[)])b)$/ +/^(?:(?=.)(?:(?!\\.)a|(?!\\.)a\\))b)$/ ` exports[`test/basic.js TAP basic tests > makeRe @(js|.*) 1`] = ` @@ -406,7 +406,7 @@ exports[`test/basic.js TAP basic tests > makeRe [[:xdigit:]][[:xdigit:]][[:xdigi ` exports[`test/basic.js TAP basic tests > makeRe [[] 1`] = ` -/^(?:(?!\\.)(?=.)[\\[])$/ +/^(?:\\[)$/ ` exports[`test/basic.js TAP basic tests > makeRe [\\-\\]] 1`] = ` @@ -414,7 +414,7 @@ exports[`test/basic.js TAP basic tests > makeRe [\\-\\]] 1`] = ` ` exports[`test/basic.js TAP basic tests > makeRe [\\\\] 1`] = ` -/^(?:(?!\\.)(?=.)[\\\\])$/ +/^(?:\\\\)$/ ` exports[`test/basic.js TAP basic tests > makeRe [\\b-a] 1`] = ` @@ -438,7 +438,7 @@ exports[`test/basic.js TAP basic tests > makeRe []-] 1`] = ` ` exports[`test/basic.js TAP basic tests > makeRe []] 1`] = ` -/^(?:(?!\\.)(?=.)[\\]])$/ +/^(?:\\])$/ ` exports[`test/basic.js TAP basic tests > makeRe [^a-c]* 1`] = ` @@ -478,7 +478,7 @@ exports[`test/basic.js TAP basic tests > makeRe [abc-] 1`] = ` ` exports[`test/basic.js TAP basic tests > makeRe [f-fz-a]* 1`] = ` -/^(?:(?!\\.)(?=.)[f][^/]*?)$/ +/^(?:(?=.)f[^/]*?)$/ ` exports[`test/basic.js TAP basic tests > makeRe [f-gz-a]* 1`] = ` @@ -486,7 +486,7 @@ exports[`test/basic.js TAP basic tests > makeRe [f-gz-a]* 1`] = ` ` exports[`test/basic.js TAP basic tests > makeRe [fz-a]* 1`] = ` -/^(?:(?!\\.)(?=.)[f][^/]*?)$/ +/^(?:(?=.)f[^/]*?)$/ ` exports[`test/basic.js TAP basic tests > makeRe [ia]?[ck] 1`] = ` @@ -502,7 +502,7 @@ exports[`test/basic.js TAP basic tests > makeRe [z-a]* 1`] = ` ` exports[`test/basic.js TAP basic tests > makeRe [z-af]* 1`] = ` -/^(?:(?!\\.)(?=.)[f][^/]*?)$/ +/^(?:(?=.)f[^/]*?)$/ ` exports[`test/basic.js TAP basic tests > makeRe [z\\-a] 1`] = ` @@ -614,11 +614,11 @@ exports[`test/basic.js TAP basic tests > makeRe a[X-]b 1`] = ` ` exports[`test/basic.js TAP basic tests > makeRe a[\\b]c 1`] = ` -/^(?:(?=.)a[b]c)$/ +/^(?:abc)$/ ` exports[`test/basic.js TAP basic tests > makeRe a[b]c 1`] = ` -/^(?:(?=.)a[b]c)$/ +/^(?:abc)$/ ` exports[`test/basic.js TAP basic tests > makeRe a\\*?/* 1`] = ` diff --git a/tap-snapshots/test/escape-has-magic.js.test.cjs b/tap-snapshots/test/escape-has-magic.js.test.cjs new file mode 100644 index 00000000..bb82c23a --- /dev/null +++ b/tap-snapshots/test/escape-has-magic.js.test.cjs @@ -0,0 +1,2061 @@ +/* IMPORTANT + * This snapshot file is auto-generated, but designed for humans. + * It should be checked into source control and tracked carefully. + * Re-generate by setting TAP_SNAPSHOT=1 and running tests. + * Make sure to inspect the output below. Do not ignore changes! + */ +'use strict' +exports[`test/escape-has-magic.js TAP > !!a* 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)a[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > !(.a|js)@(.*) 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)(?:(?!(?:\\.a|js)(?:\\.[^/]*?))[^/]*?)(?:\\.[^/]*?)$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > !\\!a* 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)\\!a[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > !a* 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)a[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > !a* 2`] = ` +Array [ + Array [ + Array [ + /^(?=.)\\!a[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > # ignore this 1`] = ` +Array [ + Array [], + false, +] +` + +exports[`test/escape-has-magic.js TAP > #* 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)\\#[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > * 1`] = ` +Array [ + Array [ + Array [ + /^(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > * 2`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > * 3`] = ` +Array [ + Array [ + Array [ + /^(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > *(a/b) 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)[^/]*?\\((?!\\.)a$/, + "b)", + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > *(a|{b),c)} 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)(?:(?!\\.)a|(?!\\.)b)*$/, + ], + Array [ + /^(?=.)(?:(?!\\.)a|(?!\\.)c)*$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > *(a|{b,c}) 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)(?:(?!\\.)a|(?!\\.)b)*$/, + ], + Array [ + /^(?=.)(?:(?!\\.)a|(?!\\.)c)*$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > *(a|{b|c,c}) 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)(?:(?!\\.)a|(?!\\.)b|(?!\\.)c)*$/, + ], + Array [ + /^(?=.)(?:(?!\\.)a|(?!\\.)c)*$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > *(a|{b|c,c}) 2`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/]*?\\(a\\|b\\|c\\)$/, + ], + Array [ + /^(?!\\.)(?=.)[^/]*?\\(a\\|c\\)$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ** 1`] = ` +Array [ + Array [ + Array [ + Symbol(globstar **), + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ** 2`] = ` +Array [ + Array [ + Array [ + Symbol(globstar **), + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ** 3`] = ` +Array [ + Array [ + Array [ + Symbol(globstar **), + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > *******? 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > *******c 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > *****?? 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > **/**/** 1`] = ` +Array [ + Array [ + Array [ + Symbol(globstar **), + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > **/.x/** 1`] = ` +Array [ + Array [ + Array [ + Symbol(globstar **), + ".x", + Symbol(globstar **), + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > **/.x/** 2`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/]*?$/, + ".x", + /^(?!\\.)(?=.)[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > *.!(js) 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/]*?\\.(?:(?!(?:js)(?:$|\\/))[^/]*?)$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > *.* 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/]*?\\.[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > *.* 2`] = ` +Array [ + Array [ + Array [ + /^(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]*?\\.[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > *.\\* 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/]*?\\.\\*$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > *.js 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/]*?\\.js$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > *.js 2`] = ` +Array [ + Array [ + Array [ + /^(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]*?\\.js$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > *.js 3`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/]*?\\.js$/i, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > *.js 4`] = ` +Array [ + Array [ + Array [ + /^(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]*?\\.js$/i, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > */man*/bash.* 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/]*?$/, + /^(?=.)man[^/]*?$/, + /^(?=.)bash\\.[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > *\\!* 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/]*?\\![^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > *\\\\!* 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/]*?\\\\\\![^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > *c*?** 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/]*?c[^/]*?[^/][^/]*?[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > *js 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/]*?js$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > +(a)!(b)+(c) 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)(?:(?!\\.)a)+(?:(?!(?:b)(?:c)+)[^/]*?)(?:c)+$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > +(a|*\\|c\\\\|d\\\\\\|e\\\\\\\\|f\\\\\\\\\\|g 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)\\+\\((?!\\.)a\\|(?!\\.)[^/]*?\\|c\\\\\\\\\\|(?!\\.)d\\\\\\\\\\|e\\\\\\\\\\\\\\\\\\|(?!\\.)f\\\\\\\\\\\\\\\\\\|g$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > .* 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)\\.[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > .* 2`] = ` +Array [ + Array [ + Array [ + /^(?=.)\\.[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > .x/**/* 1`] = ` +Array [ + Array [ + Array [ + ".x", + Symbol(globstar **), + /^(?!\\.)(?=.)[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > .x/**/* 2`] = ` +Array [ + Array [ + Array [ + ".x", + Symbol(globstar **), + /^(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > .x/**/**/* 1`] = ` +Array [ + Array [ + Array [ + ".x", + Symbol(globstar **), + /^(?!\\.)(?=.)[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > .x/**/**/* 2`] = ` +Array [ + Array [ + Array [ + ".x", + Symbol(globstar **), + /^(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > .x/**/*/** 1`] = ` +Array [ + Array [ + Array [ + ".x", + Symbol(globstar **), + /^(?!\\.)(?=.)[^/]*?$/, + Symbol(globstar **), + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > .x/**/*/** 2`] = ` +Array [ + Array [ + Array [ + ".x", + Symbol(globstar **), + /^(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]*?$/, + Symbol(globstar **), + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > .x/*/** 1`] = ` +Array [ + Array [ + Array [ + ".x", + /^(?!\\.)(?=.)[^/]*?$/, + Symbol(globstar **), + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > .x/*/** 2`] = ` +Array [ + Array [ + Array [ + ".x", + /^(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]*?$/, + Symbol(globstar **), + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > .x/*/**/** 1`] = ` +Array [ + Array [ + Array [ + ".x", + /^(?!\\.)(?=.)[^/]*?$/, + Symbol(globstar **), + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > .x/*/**/** 2`] = ` +Array [ + Array [ + Array [ + ".x", + /^(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]*?$/, + Symbol(globstar **), + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > /^root:/{s/^[^:]*:[^:]*:([^:]*).*$// 1`] = ` +Array [ + Array [ + Array [ + "", + "^root:", + "{s", + /^(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$$/, + "\\u0001", + "", + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > /^root:/{s/^[^:]*:[^:]*:([^:]*).*$/\\1/ 1`] = ` +Array [ + Array [ + Array [ + "", + "^root:", + "{s", + /^(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$$/, + "1", + "", + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ? 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ?************c****?**** 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ?*****?? 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ?*****?c 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]c$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ?***?**** 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ?***?****? 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ?***?****c 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ?.js 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/]\\.js$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ?.js 2`] = ` +Array [ + Array [ + Array [ + /^(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]\\.js$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ?.js 3`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/]\\.js$/i, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ?.js 4`] = ` +Array [ + Array [ + Array [ + /^(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]\\.js$/i, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ?? 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/][^/]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ?? 2`] = ` +Array [ + Array [ + Array [ + /^(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/][^/]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ?? 3`] = ` +Array [ + Array [ + Array [ + /^(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/][^/]$/i, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ?? 4`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/][^/]$/i, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ??**********?****? 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ??**********?****c 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ??? 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/][^/][^/]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ??? 2`] = ` +Array [ + Array [ + Array [ + /^(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/][^/][^/]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ?js 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^/]js$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ?js 2`] = ` +Array [ + Array [ + Array [ + /^(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]js$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > ?js 3`] = ` +Array [ + Array [ + Array [ + /^(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]js$/i, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > @(*|.*) 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)(?:(?!\\.)[^/]*?|\\.[^/]*?)$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > @(*|a) 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)(?:(?!(?:^|\\/)\\.{1,2}(?:$|\\/))[^/]*?|(?!(?:^|\\/)\\.{1,2}(?:$|\\/))a)$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > @(.*) 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)(?:\\.[^/]*?)$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > @(.*) 2`] = ` +Array [ + Array [ + Array [ + /^(?=.)(?:\\.[^/]*?)$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > @(.*|*) 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)(?:\\.[^/]*?|(?!\\.)[^/]*?)$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > @(.*|js) 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)(?:\\.[^/]*?|(?!\\.)js)$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > @(a|a[(])b 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)(?:(?!\\.)a|(?!\\.)a\\()b$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > @(a|a[)])b 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)(?:(?!\\.)a|(?!\\.)a\\))b$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > @(js|.*) 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)(?:(?!\\.)js|\\.[^/]*?)$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > X* 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)X[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > X* 2`] = ` +Array [ + Array [ + Array [ + /^(?=.)X[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > XYZ 1`] = ` +Array [ + Array [ + Array [ + /^XYZ$/i, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [ 1`] = ` +Array [ + Array [ + Array [ + "[", + ], + ], + false, +] +` + +exports[`test/escape-has-magic.js TAP > [!a* 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)\\[\\!a[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [#a* 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)\\[\\#a[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [* 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)\\[[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [-abc] 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[\\-abc]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]] 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[\\p{L}\\p{Nl}\\p{Nd}][\\p{L}\\p{Nl}\\p{Nd}][\\p{L}\\p{Nl}\\p{Nd}][\\p{L}\\p{Nl}\\p{Nd}][\\p{L}\\p{Nl}\\p{Nd}]$/u, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [[:alpha:]][[:alpha:]][[:alpha:]][[:alpha:]][[:alpha:]] 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[\\p{L}\\p{Nl}][\\p{L}\\p{Nl}][\\p{L}\\p{Nl}][\\p{L}\\p{Nl}][\\p{L}\\p{Nl}]$/u, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [[:ascii:]][[:ascii:]][[:ascii:]][[:ascii:]][[:ascii:]] 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[\\x00-\\x7f][\\x00-\\x7f][\\x00-\\x7f][\\x00-\\x7f][\\x00-\\x7f]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [[:graph:][:digit:]]f* 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)([\\p{Nd}]|[^\\p{Z}\\p{C}])f[^/]*?$/u, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [[:graph:]]f* 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^\\p{Z}\\p{C}]f[^/]*?$/u, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [[:xdigit:]][[:xdigit:]]??? 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[A-Fa-f0-9][A-Fa-f0-9][^/][^/][^/]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]] 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9][A-Fa-f0-9]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [[] 1`] = ` +Array [ + Array [ + Array [ + "[", + ], + ], + false, +] +` + +exports[`test/escape-has-magic.js TAP > [\\-\\]] 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[\\-\\]]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [\\\\] 1`] = ` +Array [ + Array [ + Array [ + "\\\\", + ], + ], + false, +] +` + +exports[`test/escape-has-magic.js TAP > [\\b-a] 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)$.$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [\\z-a] 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)$.$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [] 1`] = ` +Array [ + Array [ + Array [ + "[]", + ], + ], + false, +] +` + +exports[`test/escape-has-magic.js TAP > []+*] 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[\\]+*]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > []-] 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[\\]\\-]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > []] 1`] = ` +Array [ + Array [ + Array [ + "]", + ], + ], + false, +] +` + +exports[`test/escape-has-magic.js TAP > [^a-c]* 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[^a-c][^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [a-0][a-Ā] 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)$.$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [a-[:alpha:]*] 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)$.$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [a-b-c] 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[a-b\\-c]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [a-c]b* 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[a-c]b[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [a-y]*[^c] 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[a-y][^/]*?[^c]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [a-z] 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[a-z]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [abc 1`] = ` +Array [ + Array [ + Array [ + "[abc", + ], + ], + false, +] +` + +exports[`test/escape-has-magic.js TAP > [abc-] 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[abc\\-]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [f-fz-a]* 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)f[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [f-gz-a]* 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[f-g][^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [fz-a]* 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)f[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [ia]?[ck] 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[ia][^/][ck]$/i, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [z-a] 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)$.$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [z-a]* 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)$.$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [z-af]* 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)f[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > [z\\-a] 1`] = ` +Array [ + Array [ + Array [ + /^(?!\\.)(?=.)[z\\-a]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > \\ 1`] = ` +Array [ + Array [ + Array [ + "\\\\", + ], + ], + false, +] +` + +exports[`test/escape-has-magic.js TAP > \\* 1`] = ` +Array [ + Array [ + Array [ + "*", + ], + ], + false, +] +` + +exports[`test/escape-has-magic.js TAP > \\** 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)\\*[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > \\*\\* 1`] = ` +Array [ + Array [ + Array [ + "**", + ], + ], + false, +] +` + +exports[`test/escape-has-magic.js TAP > \\.\\./*/ 1`] = ` +Array [ + Array [ + Array [ + "..", + /^(?!\\.)(?=.)[^/]*?$/, + "", + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a* 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)a[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a********???******* 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a*****?c 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]c$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a*****c*?** 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/][^/]*?[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a****c**?**??***** 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a***c 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)a[^/]*?[^/]*?[^/]*?c$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a**?**cd**?**??***k 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?k$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a**?**cd**?**??***k** 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?k[^/]*?[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a**?**cd**?**??k 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a**?**cd**?**??k*** 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k[^/]*?[^/]*?[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a*[^c] 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)a[^/]*?[^c]$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a*cd**?**??k 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)a[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a/*/b 1`] = ` +Array [ + Array [ + Array [ + "a", + /^(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]*?$/, + "b", + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a/*/b 2`] = ` +Array [ + Array [ + Array [ + "a", + /^(?!\\.)(?=.)[^/]*?$/, + "b", + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a/.*/b 1`] = ` +Array [ + Array [ + Array [ + "a", + /^(?=.)\\.[^/]*?$/, + "b", + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a/.*/b 2`] = ` +Array [ + Array [ + Array [ + "a", + /^(?=.)\\.[^/]*?$/, + "b", + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a/[2015-03-10T00:23:08.647Z\\]/z 1`] = ` +Array [ + Array [ + Array [ + "a", + "[2015-03-10T00:23:08.647Z]", + "z", + ], + ], + false, +] +` + +exports[`test/escape-has-magic.js TAP > a/[2015-03-10T00:23:08.647Z]/z 1`] = ` +Array [ + Array [ + Array [ + "a", + /^(?!\\.)(?=.)[2010T00:23:08.647Z]$/, + "z", + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a?b 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)a[^/]b$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a?c 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)a[^/]c$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a[X-]b 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)a[X\\-]b$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a[\\b]c 1`] = ` +Array [ + Array [ + Array [ + "abc", + ], + ], + false, +] +` + +exports[`test/escape-has-magic.js TAP > a[b]c 1`] = ` +Array [ + Array [ + Array [ + "abc", + ], + ], + false, +] +` + +exports[`test/escape-has-magic.js TAP > a\\*?/* 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)a\\*[^/]$/, + /^(?!\\.)(?=.)[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a\\*b/* 1`] = ` +Array [ + Array [ + Array [ + "a*b", + /^(?!\\.)(?=.)[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > a\\*c 1`] = ` +Array [ + Array [ + Array [ + "a*c", + ], + ], + false, +] +` + +exports[`test/escape-has-magic.js TAP > ab* 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)ab[^/]*?$/i, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > b*/ 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)b[^/]*?$/, + "", + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > c* 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)c[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > man/man1/bash.1 1`] = ` +Array [ + Array [ + Array [ + "man", + "man1", + "bash.1", + ], + ], + false, +] +` + +exports[`test/escape-has-magic.js TAP > must match snapshot 1`] = ` +Array [ + Array [], + false, +] +` + +exports[`test/escape-has-magic.js TAP > s/\\..*// 1`] = ` +Array [ + Array [ + Array [ + "s", + /^(?=.)\\.\\.[^/]*?$/, + "", + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > x/*/../../a/b/c 1`] = ` +Array [ + Array [ + Array [ + "a", + "b", + "c", + ], + ], + false, +] +` + +exports[`test/escape-has-magic.js TAP > x/*/../a/b/c 1`] = ` +Array [ + Array [ + Array [ + "x", + "a", + "b", + "c", + ], + ], + false, +] +` + +exports[`test/escape-has-magic.js TAP > x/z/../*/a/b/c 1`] = ` +Array [ + Array [ + Array [ + "x", + /^(?!\\.)(?=.)[^/]*?$/, + "a", + "b", + "c", + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > {/*,*} 1`] = ` +Array [ + Array [ + Array [ + "", + /^(?!\\.)(?=.)[^/]*?$/, + ], + Array [ + /^(?!\\.)(?=.)[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > {/?,*} 1`] = ` +Array [ + Array [ + Array [ + "", + /^(?!\\.)(?=.)[^/]$/, + ], + Array [ + /^(?!\\.)(?=.)[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > {a,*(b|c,d)} 1`] = ` +Array [ + Array [ + Array [ + "a", + ], + Array [ + /^(?=.)[^/]*?\\((?!\\.)b\\|(?!\\.)c$/, + ], + Array [ + "d)", + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > {a,*(b|{c,d})} 1`] = ` +Array [ + Array [ + Array [ + "a", + ], + Array [ + /^(?=.)(?:(?!\\.)b|(?!\\.)c)*$/, + ], + Array [ + /^(?=.)(?:(?!\\.)b|(?!\\.)d)*$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > {c*,./c*} 1`] = ` +Array [ + Array [ + Array [ + /^(?=.)c[^/]*?$/, + ], + Array [ + ".", + /^(?=.)c[^/]*?$/, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > Å 1`] = ` +Array [ + Array [ + Array [ + /^Å$/i, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > Å 2`] = ` +Array [ + Array [ + Array [ + "Å", + ], + ], + false, +] +` + +exports[`test/escape-has-magic.js TAP > Å 3`] = ` +Array [ + Array [ + Array [ + "Å", + ], + ], + false, +] +` + +exports[`test/escape-has-magic.js TAP > Å 4`] = ` +Array [ + Array [ + Array [ + /^Å$/i, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > å 1`] = ` +Array [ + Array [ + Array [ + "å", + ], + ], + false, +] +` + +exports[`test/escape-has-magic.js TAP > å 2`] = ` +Array [ + Array [ + Array [ + /^å$/i, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > å 3`] = ` +Array [ + Array [ + Array [ + /^å$/i, + ], + ], + true, +] +` + +exports[`test/escape-has-magic.js TAP > å 4`] = ` +Array [ + Array [ + Array [ + "å", + ], + ], + false, +] +` diff --git a/tap-snapshots/test/optimization-level-0.ts.test.cjs b/tap-snapshots/test/optimization-level-0.ts.test.cjs index 94c10cda..a56217a1 100644 --- a/tap-snapshots/test/optimization-level-0.ts.test.cjs +++ b/tap-snapshots/test/optimization-level-0.ts.test.cjs @@ -1549,11 +1549,11 @@ exports[`test/optimization-level-0.ts TAP basic tests > makeRe @(.*|js) 1`] = ` ` exports[`test/optimization-level-0.ts TAP basic tests > makeRe @(a|a[(])b 1`] = ` -/^(?:(?=.)(?:(?!\\.)a|(?!\\.)a[(])b)$/ +/^(?:(?=.)(?:(?!\\.)a|(?!\\.)a\\()b)$/ ` exports[`test/optimization-level-0.ts TAP basic tests > makeRe @(a|a[)])b 1`] = ` -/^(?:(?=.)(?:(?!\\.)a|(?!\\.)a[)])b)$/ +/^(?:(?=.)(?:(?!\\.)a|(?!\\.)a\\))b)$/ ` exports[`test/optimization-level-0.ts TAP basic tests > makeRe @(js|.*) 1`] = ` @@ -1621,7 +1621,7 @@ exports[`test/optimization-level-0.ts TAP basic tests > makeRe [[:xdigit:]][[:xd ` exports[`test/optimization-level-0.ts TAP basic tests > makeRe [[] 1`] = ` -/^(?:(?!\\.)(?=.)[\\[])$/ +/^(?:\\[)$/ ` exports[`test/optimization-level-0.ts TAP basic tests > makeRe [\\-\\]] 1`] = ` @@ -1629,7 +1629,7 @@ exports[`test/optimization-level-0.ts TAP basic tests > makeRe [\\-\\]] 1`] = ` ` exports[`test/optimization-level-0.ts TAP basic tests > makeRe [\\\\] 1`] = ` -/^(?:(?!\\.)(?=.)[\\\\])$/ +/^(?:\\\\)$/ ` exports[`test/optimization-level-0.ts TAP basic tests > makeRe [\\b-a] 1`] = ` @@ -1653,7 +1653,7 @@ exports[`test/optimization-level-0.ts TAP basic tests > makeRe []-] 1`] = ` ` exports[`test/optimization-level-0.ts TAP basic tests > makeRe []] 1`] = ` -/^(?:(?!\\.)(?=.)[\\]])$/ +/^(?:\\])$/ ` exports[`test/optimization-level-0.ts TAP basic tests > makeRe [^a-c]* 1`] = ` @@ -1693,7 +1693,7 @@ exports[`test/optimization-level-0.ts TAP basic tests > makeRe [abc-] 1`] = ` ` exports[`test/optimization-level-0.ts TAP basic tests > makeRe [f-fz-a]* 1`] = ` -/^(?:(?!\\.)(?=.)[f][^/]*?)$/ +/^(?:(?=.)f[^/]*?)$/ ` exports[`test/optimization-level-0.ts TAP basic tests > makeRe [f-gz-a]* 1`] = ` @@ -1701,7 +1701,7 @@ exports[`test/optimization-level-0.ts TAP basic tests > makeRe [f-gz-a]* 1`] = ` ` exports[`test/optimization-level-0.ts TAP basic tests > makeRe [fz-a]* 1`] = ` -/^(?:(?!\\.)(?=.)[f][^/]*?)$/ +/^(?:(?=.)f[^/]*?)$/ ` exports[`test/optimization-level-0.ts TAP basic tests > makeRe [ia]?[ck] 1`] = ` @@ -1717,7 +1717,7 @@ exports[`test/optimization-level-0.ts TAP basic tests > makeRe [z-a]* 1`] = ` ` exports[`test/optimization-level-0.ts TAP basic tests > makeRe [z-af]* 1`] = ` -/^(?:(?!\\.)(?=.)[f][^/]*?)$/ +/^(?:(?=.)f[^/]*?)$/ ` exports[`test/optimization-level-0.ts TAP basic tests > makeRe [z\\-a] 1`] = ` @@ -1829,11 +1829,11 @@ exports[`test/optimization-level-0.ts TAP basic tests > makeRe a[X-]b 1`] = ` ` exports[`test/optimization-level-0.ts TAP basic tests > makeRe a[\\b]c 1`] = ` -/^(?:(?=.)a[b]c)$/ +/^(?:abc)$/ ` exports[`test/optimization-level-0.ts TAP basic tests > makeRe a[b]c 1`] = ` -/^(?:(?=.)a[b]c)$/ +/^(?:abc)$/ ` exports[`test/optimization-level-0.ts TAP basic tests > makeRe a\\*?/* 1`] = ` diff --git a/tap-snapshots/test/optimization-level-2.ts.test.cjs b/tap-snapshots/test/optimization-level-2.ts.test.cjs index 15f670fb..54475d51 100644 --- a/tap-snapshots/test/optimization-level-2.ts.test.cjs +++ b/tap-snapshots/test/optimization-level-2.ts.test.cjs @@ -334,11 +334,11 @@ exports[`test/optimization-level-2.ts TAP basic tests > makeRe @(.*|js) 1`] = ` ` exports[`test/optimization-level-2.ts TAP basic tests > makeRe @(a|a[(])b 1`] = ` -/^(?:(?=.)(?:(?!\\.)a|(?!\\.)a[(])b)$/ +/^(?:(?=.)(?:(?!\\.)a|(?!\\.)a\\()b)$/ ` exports[`test/optimization-level-2.ts TAP basic tests > makeRe @(a|a[)])b 1`] = ` -/^(?:(?=.)(?:(?!\\.)a|(?!\\.)a[)])b)$/ +/^(?:(?=.)(?:(?!\\.)a|(?!\\.)a\\))b)$/ ` exports[`test/optimization-level-2.ts TAP basic tests > makeRe @(js|.*) 1`] = ` @@ -406,7 +406,7 @@ exports[`test/optimization-level-2.ts TAP basic tests > makeRe [[:xdigit:]][[:xd ` exports[`test/optimization-level-2.ts TAP basic tests > makeRe [[] 1`] = ` -/^(?:(?!\\.)(?=.)[\\[])$/ +/^(?:\\[)$/ ` exports[`test/optimization-level-2.ts TAP basic tests > makeRe [\\-\\]] 1`] = ` @@ -414,7 +414,7 @@ exports[`test/optimization-level-2.ts TAP basic tests > makeRe [\\-\\]] 1`] = ` ` exports[`test/optimization-level-2.ts TAP basic tests > makeRe [\\\\] 1`] = ` -/^(?:(?!\\.)(?=.)[\\\\])$/ +/^(?:\\\\)$/ ` exports[`test/optimization-level-2.ts TAP basic tests > makeRe [\\b-a] 1`] = ` @@ -438,7 +438,7 @@ exports[`test/optimization-level-2.ts TAP basic tests > makeRe []-] 1`] = ` ` exports[`test/optimization-level-2.ts TAP basic tests > makeRe []] 1`] = ` -/^(?:(?!\\.)(?=.)[\\]])$/ +/^(?:\\])$/ ` exports[`test/optimization-level-2.ts TAP basic tests > makeRe [^a-c]* 1`] = ` @@ -478,7 +478,7 @@ exports[`test/optimization-level-2.ts TAP basic tests > makeRe [abc-] 1`] = ` ` exports[`test/optimization-level-2.ts TAP basic tests > makeRe [f-fz-a]* 1`] = ` -/^(?:(?!\\.)(?=.)[f][^/]*?)$/ +/^(?:(?=.)f[^/]*?)$/ ` exports[`test/optimization-level-2.ts TAP basic tests > makeRe [f-gz-a]* 1`] = ` @@ -486,7 +486,7 @@ exports[`test/optimization-level-2.ts TAP basic tests > makeRe [f-gz-a]* 1`] = ` ` exports[`test/optimization-level-2.ts TAP basic tests > makeRe [fz-a]* 1`] = ` -/^(?:(?!\\.)(?=.)[f][^/]*?)$/ +/^(?:(?=.)f[^/]*?)$/ ` exports[`test/optimization-level-2.ts TAP basic tests > makeRe [ia]?[ck] 1`] = ` @@ -502,7 +502,7 @@ exports[`test/optimization-level-2.ts TAP basic tests > makeRe [z-a]* 1`] = ` ` exports[`test/optimization-level-2.ts TAP basic tests > makeRe [z-af]* 1`] = ` -/^(?:(?!\\.)(?=.)[f][^/]*?)$/ +/^(?:(?=.)f[^/]*?)$/ ` exports[`test/optimization-level-2.ts TAP basic tests > makeRe [z\\-a] 1`] = ` @@ -614,11 +614,11 @@ exports[`test/optimization-level-2.ts TAP basic tests > makeRe a[X-]b 1`] = ` ` exports[`test/optimization-level-2.ts TAP basic tests > makeRe a[\\b]c 1`] = ` -/^(?:(?=.)a[b]c)$/ +/^(?:abc)$/ ` exports[`test/optimization-level-2.ts TAP basic tests > makeRe a[b]c 1`] = ` -/^(?:(?=.)a[b]c)$/ +/^(?:abc)$/ ` exports[`test/optimization-level-2.ts TAP basic tests > makeRe a\\*?/* 1`] = ` diff --git a/test/defaults.js b/test/defaults.js index d9d8458b..f1a7319a 100644 --- a/test/defaults.js +++ b/test/defaults.js @@ -3,13 +3,13 @@ // TODO: Some of these tests do very bad things with backslashes, and will // most likely fail badly on windows. They should probably be skipped. -var tap = require('tap') -var globalBefore = Object.keys(global) -var mm = require('../').default +const t = require('tap') +const globalBefore = Object.keys(global) +const mm = require('../').default -var patterns = require('./patterns.js') +const patterns = require('./patterns.js') -tap.test('basic tests', function (t) { +t.test('basic tests', function (t) { var start = Date.now() // [ pattern, [matches], MM opts, files, TAP opts] @@ -48,7 +48,7 @@ tap.test('basic tests', function (t) { t.end() }) -tap.test('global leak test', function (t) { +t.test('global leak test', function (t) { var globalAfter = Object.keys(global).filter(function (k) { return k !== '__coverage__' }) @@ -56,7 +56,7 @@ tap.test('global leak test', function (t) { t.end() }) -tap.test('empty defaults obj returns original ctor', t => { +t.test('empty defaults obj returns original ctor', t => { for (const empty of [{}, undefined]) { const defmm = mm.defaults(empty) t.equal(defmm, mm) @@ -66,7 +66,7 @@ tap.test('empty defaults obj returns original ctor', t => { t.end() }) -tap.test('call defaults mm function', t => { +t.test('call defaults mm function', t => { const defmm = mm.defaults({ nocomment: true }) t.equal(mm('# nocomment', '# nocomment'), false) t.equal(defmm('# nocomment', '# nocomment'), true) @@ -87,6 +87,23 @@ tap.test('call defaults mm function', t => { t.end() }) +t.test('defaults applied to minimatch.escape()', t => { + const { escape, unescape } = mm + const { escape: escapew, unescape: unescapew } = mm.defaults({ + windowsPathsNoEscape: true, + }) + const { escape: escapep, unescape: unescapep } = mm.defaults({ + windowsPathsNoEscape: false, + }) + t.equal(escape('*'), '\\*') + t.equal(unescape(escape('*')), '*') + t.equal(escapew('*'), '[*]') + t.equal(unescapew(escapew('*')), '*') + t.equal(escapep('*'), '\\*') + t.equal(unescapep(escapep('*')), '*') + t.end() +}) + function alpha(a, b) { return a > b ? 1 : -1 } diff --git a/test/escape-has-magic.js b/test/escape-has-magic.js new file mode 100644 index 00000000..8e5a1e4d --- /dev/null +++ b/test/escape-has-magic.js @@ -0,0 +1,29 @@ +const t = require('tap') +const { unescape, escape, Minimatch } = require('../') +const patterns = require('./patterns.js') + +for (const p of patterns) { + if (!Array.isArray(p) || typeof p[0] !== 'string') continue + const pattern = p[0] + const opts = p[2] || {} + const escapep = escape(pattern) + const escapew = escape(pattern, { windowsPathsNoEscape: true }) + t.equal(unescape(escapep), pattern, 'posix unescape(' + pattern + ')') + t.equal(unescape(escapew, { + windowsPathsNoEscape: true, + }), pattern, 'win32 unescape(' + pattern + ')') + const mmp = new Minimatch(escapep, { ...opts, nocaseMagicOnly: true }) + const mmw = new Minimatch(escapew, { + ...opts, + platform: 'win32', + windowsPathsNoEscape: true, + nocaseMagicOnly: true, + }) + t.equal(mmp.hasMagic(), false, 'posix escape(' + pattern + ')') + t.equal(mmw.hasMagic(), false, 'win32 escape(' + pattern + ')') + const maybeMagic = new Minimatch(pattern, opts) + t.matchSnapshot([maybeMagic.set, maybeMagic.hasMagic()], pattern) +} + +t.equal(new Minimatch('{a,b}').hasMagic(), false) +t.equal(new Minimatch('{a,b}', { magicalBraces: true }).hasMagic(), true) diff --git a/test/patterns.js b/test/patterns.js index 34408e70..047a9702 100644 --- a/test/patterns.js +++ b/test/patterns.js @@ -439,12 +439,9 @@ module.exports = [ '[[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]][[:alnum:]]', ['åéîøü', 'aeiou', 'fffff', '0f7fa', '99999'], ], - [ - '[[:xdigit:]][[:xdigit:]]???', - ['aeiou', 'fffff', '0f7fa', '99999'], - ], - [ '[[:graph:]]f*', ['fffff', '0f7fa']], - [ '[[:graph:][:digit:]]f*', ['fffff', '0f7fa']], + ['[[:xdigit:]][[:xdigit:]]???', ['aeiou', 'fffff', '0f7fa', '99999']], + ['[[:graph:]]f*', ['fffff', '0f7fa']], + ['[[:graph:][:digit:]]f*', ['fffff', '0f7fa']], ] Object.defineProperty(module.exports, 'files', { From f19f6ab371448d0e819129d40b66745a7b6ba7c8 Mon Sep 17 00:00:00 2001 From: isaacs Date: Tue, 28 Feb 2023 22:59:04 -0800 Subject: [PATCH 2/2] 7.4.0 --- 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 1a766b60..50880b40 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "minimatch", - "version": "7.3.0", + "version": "7.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "minimatch", - "version": "7.3.0", + "version": "7.4.0", "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" diff --git a/package.json b/package.json index 615aa364..a5780cc2 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": "7.3.0", + "version": "7.4.0", "repository": { "type": "git", "url": "git://github.com/isaacs/minimatch.git"