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