1"use strict"; 2// this is just a very light wrapper around 2 arrays with an offset index 3Object.defineProperty(exports, "__esModule", { value: true }); 4exports.Pattern = void 0; 5const minimatch_1 = require("minimatch"); 6const isPatternList = (pl) => pl.length >= 1; 7const isGlobList = (gl) => gl.length >= 1; 8/** 9 * An immutable-ish view on an array of glob parts and their parsed 10 * results 11 */ 12class Pattern { 13 #patternList; 14 #globList; 15 #index; 16 length; 17 #platform; 18 #rest; 19 #globString; 20 #isDrive; 21 #isUNC; 22 #isAbsolute; 23 #followGlobstar = true; 24 constructor(patternList, globList, index, platform) { 25 if (!isPatternList(patternList)) { 26 throw new TypeError('empty pattern list'); 27 } 28 if (!isGlobList(globList)) { 29 throw new TypeError('empty glob list'); 30 } 31 if (globList.length !== patternList.length) { 32 throw new TypeError('mismatched pattern list and glob list lengths'); 33 } 34 this.length = patternList.length; 35 if (index < 0 || index >= this.length) { 36 throw new TypeError('index out of range'); 37 } 38 this.#patternList = patternList; 39 this.#globList = globList; 40 this.#index = index; 41 this.#platform = platform; 42 // normalize root entries of absolute patterns on initial creation. 43 if (this.#index === 0) { 44 // c: => ['c:/'] 45 // C:/ => ['C:/'] 46 // C:/x => ['C:/', 'x'] 47 // //host/share => ['//host/share/'] 48 // //host/share/ => ['//host/share/'] 49 // //host/share/x => ['//host/share/', 'x'] 50 // /etc => ['/', 'etc'] 51 // / => ['/'] 52 if (this.isUNC()) { 53 // '' / '' / 'host' / 'share' 54 const [p0, p1, p2, p3, ...prest] = this.#patternList; 55 const [g0, g1, g2, g3, ...grest] = this.#globList; 56 if (prest[0] === '') { 57 // ends in / 58 prest.shift(); 59 grest.shift(); 60 } 61 const p = [p0, p1, p2, p3, ''].join('/'); 62 const g = [g0, g1, g2, g3, ''].join('/'); 63 this.#patternList = [p, ...prest]; 64 this.#globList = [g, ...grest]; 65 this.length = this.#patternList.length; 66 } 67 else if (this.isDrive() || this.isAbsolute()) { 68 const [p1, ...prest] = this.#patternList; 69 const [g1, ...grest] = this.#globList; 70 if (prest[0] === '') { 71 // ends in / 72 prest.shift(); 73 grest.shift(); 74 } 75 const p = p1 + '/'; 76 const g = g1 + '/'; 77 this.#patternList = [p, ...prest]; 78 this.#globList = [g, ...grest]; 79 this.length = this.#patternList.length; 80 } 81 } 82 } 83 /** 84 * The first entry in the parsed list of patterns 85 */ 86 pattern() { 87 return this.#patternList[this.#index]; 88 } 89 /** 90 * true of if pattern() returns a string 91 */ 92 isString() { 93 return typeof this.#patternList[this.#index] === 'string'; 94 } 95 /** 96 * true of if pattern() returns GLOBSTAR 97 */ 98 isGlobstar() { 99 return this.#patternList[this.#index] === minimatch_1.GLOBSTAR; 100 } 101 /** 102 * true if pattern() returns a regexp 103 */ 104 isRegExp() { 105 return this.#patternList[this.#index] instanceof RegExp; 106 } 107 /** 108 * The /-joined set of glob parts that make up this pattern 109 */ 110 globString() { 111 return (this.#globString = 112 this.#globString || 113 (this.#index === 0 114 ? this.isAbsolute() 115 ? this.#globList[0] + this.#globList.slice(1).join('/') 116 : this.#globList.join('/') 117 : this.#globList.slice(this.#index).join('/'))); 118 } 119 /** 120 * true if there are more pattern parts after this one 121 */ 122 hasMore() { 123 return this.length > this.#index + 1; 124 } 125 /** 126 * The rest of the pattern after this part, or null if this is the end 127 */ 128 rest() { 129 if (this.#rest !== undefined) 130 return this.#rest; 131 if (!this.hasMore()) 132 return (this.#rest = null); 133 this.#rest = new Pattern(this.#patternList, this.#globList, this.#index + 1, this.#platform); 134 this.#rest.#isAbsolute = this.#isAbsolute; 135 this.#rest.#isUNC = this.#isUNC; 136 this.#rest.#isDrive = this.#isDrive; 137 return this.#rest; 138 } 139 /** 140 * true if the pattern represents a //unc/path/ on windows 141 */ 142 isUNC() { 143 const pl = this.#patternList; 144 return this.#isUNC !== undefined 145 ? this.#isUNC 146 : (this.#isUNC = 147 this.#platform === 'win32' && 148 this.#index === 0 && 149 pl[0] === '' && 150 pl[1] === '' && 151 typeof pl[2] === 'string' && 152 !!pl[2] && 153 typeof pl[3] === 'string' && 154 !!pl[3]); 155 } 156 // pattern like C:/... 157 // split = ['C:', ...] 158 // XXX: would be nice to handle patterns like `c:*` to test the cwd 159 // in c: for *, but I don't know of a way to even figure out what that 160 // cwd is without actually chdir'ing into it? 161 /** 162 * True if the pattern starts with a drive letter on Windows 163 */ 164 isDrive() { 165 const pl = this.#patternList; 166 return this.#isDrive !== undefined 167 ? this.#isDrive 168 : (this.#isDrive = 169 this.#platform === 'win32' && 170 this.#index === 0 && 171 this.length > 1 && 172 typeof pl[0] === 'string' && 173 /^[a-z]:$/i.test(pl[0])); 174 } 175 // pattern = '/' or '/...' or '/x/...' 176 // split = ['', ''] or ['', ...] or ['', 'x', ...] 177 // Drive and UNC both considered absolute on windows 178 /** 179 * True if the pattern is rooted on an absolute path 180 */ 181 isAbsolute() { 182 const pl = this.#patternList; 183 return this.#isAbsolute !== undefined 184 ? this.#isAbsolute 185 : (this.#isAbsolute = 186 (pl[0] === '' && pl.length > 1) || 187 this.isDrive() || 188 this.isUNC()); 189 } 190 /** 191 * consume the root of the pattern, and return it 192 */ 193 root() { 194 const p = this.#patternList[0]; 195 return typeof p === 'string' && this.isAbsolute() && this.#index === 0 196 ? p 197 : ''; 198 } 199 /** 200 * Check to see if the current globstar pattern is allowed to follow 201 * a symbolic link. 202 */ 203 checkFollowGlobstar() { 204 return !(this.#index === 0 || 205 !this.isGlobstar() || 206 !this.#followGlobstar); 207 } 208 /** 209 * Mark that the current globstar pattern is following a symbolic link 210 */ 211 markFollowGlobstar() { 212 if (this.#index === 0 || !this.isGlobstar() || !this.#followGlobstar) 213 return false; 214 this.#followGlobstar = false; 215 return true; 216 } 217} 218exports.Pattern = Pattern; 219//# sourceMappingURL=pattern.js.map