"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