You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
219 lines
7.1 KiB
219 lines
7.1 KiB
"use strict"; |
|
// this is just a very light wrapper around 2 arrays with an offset index |
|
Object.defineProperty(exports, "__esModule", { value: true }); |
|
exports.Pattern = void 0; |
|
const minimatch_1 = require("minimatch"); |
|
const isPatternList = (pl) => pl.length >= 1; |
|
const isGlobList = (gl) => gl.length >= 1; |
|
/** |
|
* An immutable-ish view on an array of glob parts and their parsed |
|
* results |
|
*/ |
|
class Pattern { |
|
#patternList; |
|
#globList; |
|
#index; |
|
length; |
|
#platform; |
|
#rest; |
|
#globString; |
|
#isDrive; |
|
#isUNC; |
|
#isAbsolute; |
|
#followGlobstar = true; |
|
constructor(patternList, globList, index, platform) { |
|
if (!isPatternList(patternList)) { |
|
throw new TypeError('empty pattern list'); |
|
} |
|
if (!isGlobList(globList)) { |
|
throw new TypeError('empty glob list'); |
|
} |
|
if (globList.length !== patternList.length) { |
|
throw new TypeError('mismatched pattern list and glob list lengths'); |
|
} |
|
this.length = patternList.length; |
|
if (index < 0 || index >= this.length) { |
|
throw new TypeError('index out of range'); |
|
} |
|
this.#patternList = patternList; |
|
this.#globList = globList; |
|
this.#index = index; |
|
this.#platform = platform; |
|
// normalize root entries of absolute patterns on initial creation. |
|
if (this.#index === 0) { |
|
// c: => ['c:/'] |
|
// C:/ => ['C:/'] |
|
// C:/x => ['C:/', 'x'] |
|
// //host/share => ['//host/share/'] |
|
// //host/share/ => ['//host/share/'] |
|
// //host/share/x => ['//host/share/', 'x'] |
|
// /etc => ['/', 'etc'] |
|
// / => ['/'] |
|
if (this.isUNC()) { |
|
// '' / '' / 'host' / 'share' |
|
const [p0, p1, p2, p3, ...prest] = this.#patternList; |
|
const [g0, g1, g2, g3, ...grest] = this.#globList; |
|
if (prest[0] === '') { |
|
// ends in / |
|
prest.shift(); |
|
grest.shift(); |
|
} |
|
const p = [p0, p1, p2, p3, ''].join('/'); |
|
const g = [g0, g1, g2, g3, ''].join('/'); |
|
this.#patternList = [p, ...prest]; |
|
this.#globList = [g, ...grest]; |
|
this.length = this.#patternList.length; |
|
} |
|
else if (this.isDrive() || this.isAbsolute()) { |
|
const [p1, ...prest] = this.#patternList; |
|
const [g1, ...grest] = this.#globList; |
|
if (prest[0] === '') { |
|
// ends in / |
|
prest.shift(); |
|
grest.shift(); |
|
} |
|
const p = p1 + '/'; |
|
const g = g1 + '/'; |
|
this.#patternList = [p, ...prest]; |
|
this.#globList = [g, ...grest]; |
|
this.length = this.#patternList.length; |
|
} |
|
} |
|
} |
|
/** |
|
* The first entry in the parsed list of patterns |
|
*/ |
|
pattern() { |
|
return this.#patternList[this.#index]; |
|
} |
|
/** |
|
* true of if pattern() returns a string |
|
*/ |
|
isString() { |
|
return typeof this.#patternList[this.#index] === 'string'; |
|
} |
|
/** |
|
* true of if pattern() returns GLOBSTAR |
|
*/ |
|
isGlobstar() { |
|
return this.#patternList[this.#index] === minimatch_1.GLOBSTAR; |
|
} |
|
/** |
|
* true if pattern() returns a regexp |
|
*/ |
|
isRegExp() { |
|
return this.#patternList[this.#index] instanceof RegExp; |
|
} |
|
/** |
|
* The /-joined set of glob parts that make up this pattern |
|
*/ |
|
globString() { |
|
return (this.#globString = |
|
this.#globString || |
|
(this.#index === 0 ? |
|
this.isAbsolute() ? |
|
this.#globList[0] + this.#globList.slice(1).join('/') |
|
: this.#globList.join('/') |
|
: this.#globList.slice(this.#index).join('/'))); |
|
} |
|
/** |
|
* true if there are more pattern parts after this one |
|
*/ |
|
hasMore() { |
|
return this.length > this.#index + 1; |
|
} |
|
/** |
|
* The rest of the pattern after this part, or null if this is the end |
|
*/ |
|
rest() { |
|
if (this.#rest !== undefined) |
|
return this.#rest; |
|
if (!this.hasMore()) |
|
return (this.#rest = null); |
|
this.#rest = new Pattern(this.#patternList, this.#globList, this.#index + 1, this.#platform); |
|
this.#rest.#isAbsolute = this.#isAbsolute; |
|
this.#rest.#isUNC = this.#isUNC; |
|
this.#rest.#isDrive = this.#isDrive; |
|
return this.#rest; |
|
} |
|
/** |
|
* true if the pattern represents a //unc/path/ on windows |
|
*/ |
|
isUNC() { |
|
const pl = this.#patternList; |
|
return this.#isUNC !== undefined ? |
|
this.#isUNC |
|
: (this.#isUNC = |
|
this.#platform === 'win32' && |
|
this.#index === 0 && |
|
pl[0] === '' && |
|
pl[1] === '' && |
|
typeof pl[2] === 'string' && |
|
!!pl[2] && |
|
typeof pl[3] === 'string' && |
|
!!pl[3]); |
|
} |
|
// pattern like C:/... |
|
// split = ['C:', ...] |
|
// XXX: would be nice to handle patterns like `c:*` to test the cwd |
|
// in c: for *, but I don't know of a way to even figure out what that |
|
// cwd is without actually chdir'ing into it? |
|
/** |
|
* True if the pattern starts with a drive letter on Windows |
|
*/ |
|
isDrive() { |
|
const pl = this.#patternList; |
|
return this.#isDrive !== undefined ? |
|
this.#isDrive |
|
: (this.#isDrive = |
|
this.#platform === 'win32' && |
|
this.#index === 0 && |
|
this.length > 1 && |
|
typeof pl[0] === 'string' && |
|
/^[a-z]:$/i.test(pl[0])); |
|
} |
|
// pattern = '/' or '/...' or '/x/...' |
|
// split = ['', ''] or ['', ...] or ['', 'x', ...] |
|
// Drive and UNC both considered absolute on windows |
|
/** |
|
* True if the pattern is rooted on an absolute path |
|
*/ |
|
isAbsolute() { |
|
const pl = this.#patternList; |
|
return this.#isAbsolute !== undefined ? |
|
this.#isAbsolute |
|
: (this.#isAbsolute = |
|
(pl[0] === '' && pl.length > 1) || |
|
this.isDrive() || |
|
this.isUNC()); |
|
} |
|
/** |
|
* consume the root of the pattern, and return it |
|
*/ |
|
root() { |
|
const p = this.#patternList[0]; |
|
return (typeof p === 'string' && this.isAbsolute() && this.#index === 0) ? |
|
p |
|
: ''; |
|
} |
|
/** |
|
* Check to see if the current globstar pattern is allowed to follow |
|
* a symbolic link. |
|
*/ |
|
checkFollowGlobstar() { |
|
return !(this.#index === 0 || |
|
!this.isGlobstar() || |
|
!this.#followGlobstar); |
|
} |
|
/** |
|
* Mark that the current globstar pattern is following a symbolic link |
|
*/ |
|
markFollowGlobstar() { |
|
if (this.#index === 0 || !this.isGlobstar() || !this.#followGlobstar) |
|
return false; |
|
this.#followGlobstar = false; |
|
return true; |
|
} |
|
} |
|
exports.Pattern = Pattern; |
|
//# sourceMappingURL=pattern.js.map
|