Skip to content

Commit

Permalink
Use escape, unescape, hasMagic from Minimatch
Browse files Browse the repository at this point in the history
Fix: #367
  • Loading branch information
isaacs committed Mar 1, 2023
1 parent acace9a commit 8404778
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 23 deletions.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,34 @@ if you had called it on `['xay', 'xby']`. When
`magicalBraces:true` is in the options, brace expansion _is_
treated as a pattern having magic.

## `escape(pattern: string, options?: GlobOptions) => string`

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.

## `unescape(pattern: string, options?: GlobOptions) => string`

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 `'*'`, because `\` 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.

## Class `Glob`

An object that can perform glob pattern traversals.
Expand Down
20 changes: 9 additions & 11 deletions src/has-magic.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { Glob, GlobOptions } from './glob.js'
import { Minimatch } from 'minimatch'
import { GlobOptions } from './glob.js'

/**
* Return true if the patterns provided contain any magic
* glob characters, given the options provided.
* Return true if the patterns provided contain any magic glob characters,
* given the options provided.
*
* Brace expansion is not considered "magic" unless the `magicalBraces` option
* is set, as brace expansion just turns one string into an array of strings.
* So a pattern like `'x{a,b}y'` would return `false`, because `'xay'` and
* `'xby'` both do not contain any magic glob characters, and it's treated the
* same as if you had called it on `['xay', 'xby']`. When
* `magicalBraces:true` is in the options, brace expansion _is_ treated as a
* pattern having magic.
* same as if you had called it on `['xay', 'xby']`. When `magicalBraces:true`
* is in the options, brace expansion _is_ treated as a pattern having magic.
*/
export const hasMagic = (
pattern: string | string[],
Expand All @@ -19,10 +19,8 @@ export const hasMagic = (
if (!Array.isArray(pattern)) {
pattern = [pattern]
}
const length = pattern.length
const g = new Glob(pattern, options)
if (g.magicalBraces && g.patterns.length !== length) {
return true
for (const p of pattern) {
if (new Minimatch(p, options).hasMagic()) return true
}
return g.patterns.some(p => p.hasMagic())
return false
}
5 changes: 5 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { escape, unescape } from 'minimatch'
import type {
GlobOptions,
GlobOptionsWithFileTypesFalse,
Expand Down Expand Up @@ -178,6 +179,7 @@ export function globIterateSync(
}

/* c8 ignore start */
export { escape, unescape } from 'minimatch'
export { Glob } from './glob.js'
export type {
GlobOptions,
Expand All @@ -189,6 +191,7 @@ export type {
} from './glob.js'
export { hasMagic } from './has-magic.js'
export type { MatchStream } from './walker.js'

/* c8 ignore stop */
export default Object.assign(glob, {
glob,
Expand All @@ -199,4 +202,6 @@ export default Object.assign(glob, {
globIterateSync,
Glob,
hasMagic,
escape,
unescape,
})
12 changes: 0 additions & 12 deletions src/pattern.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,18 +230,6 @@ export class Pattern {
: ''
}

/**
* True if the pattern has any non-string components
*/
hasMagic(): boolean {
for (let i = 0; i < this.length; i++) {
if (typeof this.#patternList[i] !== 'string') {
return true
}
}
return false
}

/**
* Check to see if the current globstar pattern is allowed to follow
* a symbolic link.
Expand Down
18 changes: 18 additions & 0 deletions test/escape.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import t from 'tap'
import { unescape, escape, hasMagic } from '../'
import { bashResults } from './bash-results'

for (const pattern of Object.keys(bashResults)) {
t.notOk(hasMagic(escape(pattern)), `escape(${pattern})`)
const pp = escape(pattern)
const pw = escape(pattern, {
windowsPathsNoEscape: true
})
t.notOk(hasMagic(pp, { platform: 'linux' }), 'no magic after posix escape')
t.notOk(hasMagic(pw, { platform: 'win32', windowsPathsNoEscape: true }),
'no magic after windows escape')
const up = unescape(pp)
const uw = unescape(pw, { windowsPathsNoEscape: true })
t.equal(up, pattern, 'unescaped posix pattern returned')
t.equal(uw, pattern, 'unescaped windows pattern returned')
}

0 comments on commit 8404778

Please sign in to comment.