UNPKG

7.3 kBJavaScriptView Raw
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
\No newline at end of file