@shopware/api-gen 1.5.1 → 1.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -15
- package/dist/cli.mjs +1476 -2577
- package/dist/index.mjs +1 -1
- package/dist/shared/{api-gen.DDkIkZIo.mjs → api-gen.DwUlbL4g.mjs} +70 -35
- package/package.json +8 -6
package/dist/cli.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import yargs from 'yargs';
|
|
2
2
|
import { hideBin } from 'yargs/helpers';
|
|
3
|
-
import { a as getAugmentedNamespace, f as formatSource, g as generate, l as loadSchema, v as validateJson } from './shared/api-gen.
|
|
3
|
+
import { a as getAugmentedNamespace, f as formatSource, g as generate, l as loadSchema, v as validateJson } from './shared/api-gen.DwUlbL4g.mjs';
|
|
4
4
|
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
5
5
|
import { resolve as resolve$2 } from 'node:path';
|
|
6
6
|
import require$$0$5 from 'fs';
|
|
@@ -32,7 +32,7 @@ import __cjs_mod__ from 'module';
|
|
|
32
32
|
const __filename = __cjs_url__.fileURLToPath(import.meta.url);
|
|
33
33
|
const __dirname = __cjs_path__.dirname(__filename);
|
|
34
34
|
const require = __cjs_mod__.createRequire(import.meta.url);
|
|
35
|
-
const version$1 = "1.5.
|
|
35
|
+
const version$1 = "1.5.3";
|
|
36
36
|
const packageJson = {
|
|
37
37
|
version: version$1};
|
|
38
38
|
|
|
@@ -40,2607 +40,1495 @@ var lib = {};
|
|
|
40
40
|
|
|
41
41
|
var utils$3 = {};
|
|
42
42
|
|
|
43
|
-
var
|
|
43
|
+
var path;
|
|
44
|
+
var hasRequiredPath;
|
|
45
|
+
|
|
46
|
+
function requirePath () {
|
|
47
|
+
if (hasRequiredPath) return path;
|
|
48
|
+
hasRequiredPath = 1;
|
|
49
|
+
const isWindows = typeof process === 'object' &&
|
|
50
|
+
process &&
|
|
51
|
+
process.platform === 'win32';
|
|
52
|
+
path = isWindows ? { sep: '\\' } : { sep: '/' };
|
|
53
|
+
return path;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
var balancedMatch;
|
|
57
|
+
var hasRequiredBalancedMatch;
|
|
58
|
+
|
|
59
|
+
function requireBalancedMatch () {
|
|
60
|
+
if (hasRequiredBalancedMatch) return balancedMatch;
|
|
61
|
+
hasRequiredBalancedMatch = 1;
|
|
62
|
+
balancedMatch = balanced;
|
|
63
|
+
function balanced(a, b, str) {
|
|
64
|
+
if (a instanceof RegExp) a = maybeMatch(a, str);
|
|
65
|
+
if (b instanceof RegExp) b = maybeMatch(b, str);
|
|
66
|
+
|
|
67
|
+
var r = range(a, b, str);
|
|
68
|
+
|
|
69
|
+
return r && {
|
|
70
|
+
start: r[0],
|
|
71
|
+
end: r[1],
|
|
72
|
+
pre: str.slice(0, r[0]),
|
|
73
|
+
body: str.slice(r[0] + a.length, r[1]),
|
|
74
|
+
post: str.slice(r[1] + b.length)
|
|
75
|
+
};
|
|
76
|
+
}
|
|
44
77
|
|
|
45
|
-
|
|
78
|
+
function maybeMatch(reg, str) {
|
|
79
|
+
var m = str.match(reg);
|
|
80
|
+
return m ? m[0] : null;
|
|
81
|
+
}
|
|
46
82
|
|
|
47
|
-
|
|
83
|
+
balanced.range = range;
|
|
84
|
+
function range(a, b, str) {
|
|
85
|
+
var begs, beg, left, right, result;
|
|
86
|
+
var ai = str.indexOf(a);
|
|
87
|
+
var bi = str.indexOf(b, ai + 1);
|
|
88
|
+
var i = ai;
|
|
48
89
|
|
|
49
|
-
|
|
90
|
+
if (ai >= 0 && bi > 0) {
|
|
91
|
+
if(a===b) {
|
|
92
|
+
return [ai, bi];
|
|
93
|
+
}
|
|
94
|
+
begs = [];
|
|
95
|
+
left = str.length;
|
|
50
96
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
end: r[1],
|
|
64
|
-
pre: str.slice(0, r[0]),
|
|
65
|
-
body: str.slice(r[0] + ma.length, r[1]),
|
|
66
|
-
post: str.slice(r[1] + mb.length),
|
|
67
|
-
});
|
|
68
|
-
};
|
|
69
|
-
exports.balanced = balanced;
|
|
70
|
-
const maybeMatch = (reg, str) => {
|
|
71
|
-
const m = str.match(reg);
|
|
72
|
-
return m ? m[0] : null;
|
|
73
|
-
};
|
|
74
|
-
const range = (a, b, str) => {
|
|
75
|
-
let begs, beg, left, right = undefined, result;
|
|
76
|
-
let ai = str.indexOf(a);
|
|
77
|
-
let bi = str.indexOf(b, ai + 1);
|
|
78
|
-
let i = ai;
|
|
79
|
-
if (ai >= 0 && bi > 0) {
|
|
80
|
-
if (a === b) {
|
|
81
|
-
return [ai, bi];
|
|
82
|
-
}
|
|
83
|
-
begs = [];
|
|
84
|
-
left = str.length;
|
|
85
|
-
while (i >= 0 && !result) {
|
|
86
|
-
if (i === ai) {
|
|
87
|
-
begs.push(i);
|
|
88
|
-
ai = str.indexOf(a, i + 1);
|
|
89
|
-
}
|
|
90
|
-
else if (begs.length === 1) {
|
|
91
|
-
const r = begs.pop();
|
|
92
|
-
if (r !== undefined)
|
|
93
|
-
result = [r, bi];
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
beg = begs.pop();
|
|
97
|
-
if (beg !== undefined && beg < left) {
|
|
98
|
-
left = beg;
|
|
99
|
-
right = bi;
|
|
100
|
-
}
|
|
101
|
-
bi = str.indexOf(b, i + 1);
|
|
102
|
-
}
|
|
103
|
-
i = ai < bi && ai >= 0 ? ai : bi;
|
|
104
|
-
}
|
|
105
|
-
if (begs.length && right !== undefined) {
|
|
106
|
-
result = [left, right];
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return result;
|
|
110
|
-
};
|
|
111
|
-
exports.range = range;
|
|
112
|
-
|
|
113
|
-
} (commonjs));
|
|
114
|
-
return commonjs;
|
|
115
|
-
}
|
|
97
|
+
while (i >= 0 && !result) {
|
|
98
|
+
if (i == ai) {
|
|
99
|
+
begs.push(i);
|
|
100
|
+
ai = str.indexOf(a, i + 1);
|
|
101
|
+
} else if (begs.length == 1) {
|
|
102
|
+
result = [ begs.pop(), bi ];
|
|
103
|
+
} else {
|
|
104
|
+
beg = begs.pop();
|
|
105
|
+
if (beg < left) {
|
|
106
|
+
left = beg;
|
|
107
|
+
right = bi;
|
|
108
|
+
}
|
|
116
109
|
|
|
117
|
-
|
|
110
|
+
bi = str.indexOf(b, i + 1);
|
|
111
|
+
}
|
|
118
112
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
function isPadded(el) {
|
|
218
|
-
return /^-?0\d/.test(el);
|
|
219
|
-
}
|
|
220
|
-
function lte(i, y) {
|
|
221
|
-
return i <= y;
|
|
222
|
-
}
|
|
223
|
-
function gte(i, y) {
|
|
224
|
-
return i >= y;
|
|
225
|
-
}
|
|
226
|
-
// Build `{ acc[a] + pre + values[v] }` for every combination, capping the
|
|
227
|
-
// number of results at `max` and the total number of characters at `maxLength`.
|
|
228
|
-
// This is the one place output grows, so bounding it here keeps the single
|
|
229
|
-
// accumulator - and therefore memory - flat regardless of how many brace groups
|
|
230
|
-
// are combined (CVE-2026-14257).
|
|
231
|
-
function combine(acc, pre, values, max, maxLength, dropEmpties) {
|
|
232
|
-
const out = [];
|
|
233
|
-
let length = 0;
|
|
234
|
-
for (let a = 0; a < acc.length; a++) {
|
|
235
|
-
for (let v = 0; v < values.length; v++) {
|
|
236
|
-
if (out.length >= max)
|
|
237
|
-
return out;
|
|
238
|
-
const expansion = acc[a] + pre + values[v];
|
|
239
|
-
// Bash drops empty results at the top level. Skip them before they count
|
|
240
|
-
// against `max`, so `max` bounds the number of *kept* results.
|
|
241
|
-
if (dropEmpties && !expansion)
|
|
242
|
-
continue;
|
|
243
|
-
if (length + expansion.length > maxLength)
|
|
244
|
-
return out;
|
|
245
|
-
out.push(expansion);
|
|
246
|
-
length += expansion.length;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
return out;
|
|
250
|
-
}
|
|
251
|
-
// The expansion values of a single numeric (`1..5`) or alphabetic (`a..e..2`)
|
|
252
|
-
// sequence body.
|
|
253
|
-
function expandSequence(body, isAlphaSequence, max) {
|
|
254
|
-
const n = body.split(/\.\./);
|
|
255
|
-
const N = [];
|
|
256
|
-
// A sequence body always splits into two or three parts, but the compiler
|
|
257
|
-
// can't know that.
|
|
258
|
-
/* c8 ignore start */
|
|
259
|
-
if (n[0] === undefined || n[1] === undefined) {
|
|
260
|
-
return N;
|
|
261
|
-
}
|
|
262
|
-
/* c8 ignore stop */
|
|
263
|
-
const x = numeric(n[0]);
|
|
264
|
-
const y = numeric(n[1]);
|
|
265
|
-
const width = Math.max(n[0].length, n[1].length);
|
|
266
|
-
let incr = n.length === 3 && n[2] !== undefined ?
|
|
267
|
-
Math.max(Math.abs(numeric(n[2])), 1)
|
|
268
|
-
: 1;
|
|
269
|
-
let test = lte;
|
|
270
|
-
const reverse = y < x;
|
|
271
|
-
if (reverse) {
|
|
272
|
-
incr *= -1;
|
|
273
|
-
test = gte;
|
|
274
|
-
}
|
|
275
|
-
const pad = n.some(isPadded);
|
|
276
|
-
for (let i = x; test(i, y) && N.length < max; i += incr) {
|
|
277
|
-
let c;
|
|
278
|
-
if (isAlphaSequence) {
|
|
279
|
-
c = String.fromCharCode(i);
|
|
280
|
-
if (c === '\\') {
|
|
281
|
-
c = '';
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
else {
|
|
285
|
-
c = String(i);
|
|
286
|
-
if (pad) {
|
|
287
|
-
const need = width - c.length;
|
|
288
|
-
if (need > 0) {
|
|
289
|
-
const z = new Array(need + 1).join('0');
|
|
290
|
-
if (i < 0) {
|
|
291
|
-
c = '-' + z + c.slice(1);
|
|
292
|
-
}
|
|
293
|
-
else {
|
|
294
|
-
c = z + c;
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
N.push(c);
|
|
300
|
-
}
|
|
301
|
-
return N;
|
|
302
|
-
}
|
|
303
|
-
function expand_(str, max, maxLength, isTop) {
|
|
304
|
-
// Consume the string's top-level brace groups left to right, threading a
|
|
305
|
-
// running set of combined prefixes (`acc`). Expanding the tail iteratively -
|
|
306
|
-
// rather than recursing on `m.post` once per group - keeps the native stack
|
|
307
|
-
// depth constant, so deeply chained input (`'{a,b}'.repeat(3000)`) can no
|
|
308
|
-
// longer overflow the stack, and leaves a single accumulator whose size
|
|
309
|
-
// `maxLength` bounds directly (CVE-2026-14257).
|
|
310
|
-
let acc = [''];
|
|
311
|
-
// Bash drops empty results, but only when the *first* top-level group is a
|
|
312
|
-
// comma set - a sequence like `{a..\}` may legitimately yield ''. The drop
|
|
313
|
-
// is on the final strings, so it is applied to whichever `combine` produces
|
|
314
|
-
// them (the one with no brace set left in the tail).
|
|
315
|
-
let dropEmpties = false;
|
|
316
|
-
let firstGroup = true;
|
|
317
|
-
for (;;) {
|
|
318
|
-
const m = (0, balanced_match_1.balanced)('{', '}', str);
|
|
319
|
-
// No brace set left: the rest of the string is literal.
|
|
320
|
-
if (!m) {
|
|
321
|
-
return combine(acc, str, [''], max, maxLength, dropEmpties);
|
|
322
|
-
}
|
|
323
|
-
// no need to expand pre, since it is guaranteed to be free of brace-sets
|
|
324
|
-
const pre = m.pre;
|
|
325
|
-
if (/\$$/.test(pre)) {
|
|
326
|
-
acc = combine(acc, pre + '{' + m.body + '}', [''], max, maxLength, dropEmpties && !m.post.length);
|
|
327
|
-
firstGroup = false;
|
|
328
|
-
if (!m.post.length)
|
|
329
|
-
break;
|
|
330
|
-
str = m.post;
|
|
331
|
-
continue;
|
|
332
|
-
}
|
|
333
|
-
const isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
|
|
334
|
-
const isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
|
|
335
|
-
const isSequence = isNumericSequence || isAlphaSequence;
|
|
336
|
-
const isOptions = m.body.indexOf(',') >= 0;
|
|
337
|
-
if (!isSequence && !isOptions) {
|
|
338
|
-
// {a},b}
|
|
339
|
-
if (m.post.match(/,(?!,).*\}/)) {
|
|
340
|
-
str = m.pre + '{' + m.body + escClose + m.post;
|
|
341
|
-
isTop = true;
|
|
342
|
-
continue;
|
|
343
|
-
}
|
|
344
|
-
// Nothing here expands, so the whole remaining string is literal.
|
|
345
|
-
return combine(acc, pre + '{' + m.body + '}' + m.post, [''], max, maxLength, dropEmpties);
|
|
346
|
-
}
|
|
347
|
-
if (firstGroup) {
|
|
348
|
-
dropEmpties = isTop && !isSequence;
|
|
349
|
-
firstGroup = false;
|
|
350
|
-
}
|
|
351
|
-
let values;
|
|
352
|
-
if (isSequence) {
|
|
353
|
-
values = expandSequence(m.body, isAlphaSequence, max);
|
|
354
|
-
}
|
|
355
|
-
else {
|
|
356
|
-
let n = parseCommaParts(m.body);
|
|
357
|
-
if (n.length === 1 && n[0] !== undefined) {
|
|
358
|
-
// x{{a,b}}y ==> x{a}y x{b}y
|
|
359
|
-
n = expand_(n[0], max, maxLength, false).map(embrace);
|
|
360
|
-
//XXX is this necessary? Can't seem to hit it in tests.
|
|
361
|
-
/* c8 ignore start */
|
|
362
|
-
if (n.length === 1) {
|
|
363
|
-
acc = combine(acc, pre + n[0], [''], max, maxLength, dropEmpties && !m.post.length);
|
|
364
|
-
if (!m.post.length)
|
|
365
|
-
break;
|
|
366
|
-
str = m.post;
|
|
367
|
-
continue;
|
|
368
|
-
}
|
|
369
|
-
/* c8 ignore stop */
|
|
370
|
-
}
|
|
371
|
-
values = [];
|
|
372
|
-
for (let j = 0; j < n.length; j++) {
|
|
373
|
-
values.push.apply(values, expand_(n[j], max, maxLength, false));
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
acc = combine(acc, pre, values, max, maxLength, dropEmpties && !m.post.length);
|
|
377
|
-
if (!m.post.length)
|
|
378
|
-
break;
|
|
379
|
-
str = m.post;
|
|
380
|
-
}
|
|
381
|
-
return acc;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
} (commonjs$1));
|
|
385
|
-
return commonjs$1;
|
|
386
|
-
}
|
|
113
|
+
i = ai < bi && ai >= 0 ? ai : bi;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (begs.length) {
|
|
117
|
+
result = [ left, right ];
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
return balancedMatch;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
var braceExpansion;
|
|
127
|
+
var hasRequiredBraceExpansion;
|
|
128
|
+
|
|
129
|
+
function requireBraceExpansion () {
|
|
130
|
+
if (hasRequiredBraceExpansion) return braceExpansion;
|
|
131
|
+
hasRequiredBraceExpansion = 1;
|
|
132
|
+
var balanced = requireBalancedMatch();
|
|
133
|
+
|
|
134
|
+
braceExpansion = expandTop;
|
|
135
|
+
|
|
136
|
+
var escSlash = '\0SLASH'+Math.random()+'\0';
|
|
137
|
+
var escOpen = '\0OPEN'+Math.random()+'\0';
|
|
138
|
+
var escClose = '\0CLOSE'+Math.random()+'\0';
|
|
139
|
+
var escComma = '\0COMMA'+Math.random()+'\0';
|
|
140
|
+
var escPeriod = '\0PERIOD'+Math.random()+'\0';
|
|
141
|
+
|
|
142
|
+
var EXPANSION_MAX = 100000;
|
|
143
|
+
|
|
144
|
+
// `EXPANSION_MAX` caps the *number* of expansions, but not their length. An
|
|
145
|
+
// input like `'{a,b}'.repeat(1500)` stays under that count - its output is
|
|
146
|
+
// truncated to 100k results - while making every result ~1500 characters
|
|
147
|
+
// long. The result set, and the intermediate arrays built while combining
|
|
148
|
+
// brace sets, then grow large enough to exhaust memory and crash the process
|
|
149
|
+
// (CVE-2026-14257). `EXPANSION_MAX_LENGTH` bounds the total number of
|
|
150
|
+
// characters the accumulator may hold at any point, so memory stays flat no
|
|
151
|
+
// matter how many brace groups are chained. The limit sits well above any
|
|
152
|
+
// realistic expansion (100k results hitting `EXPANSION_MAX` measure ~1M
|
|
153
|
+
// characters) so legitimate input is unaffected.
|
|
154
|
+
var EXPANSION_MAX_LENGTH = 4000000;
|
|
155
|
+
|
|
156
|
+
// `expand` recurses once per level of brace *nesting* - both when expanding a
|
|
157
|
+
// set's comma members and when re-wrapping a set whose body is a single part.
|
|
158
|
+
// The CVE-2026-14257 fix made the *tail* iterative (recursion on `m.post`, one
|
|
159
|
+
// level per chained group), which left nesting depth unbounded: about 3,100
|
|
160
|
+
// levels of `{{{...a,b...}}}` - only ~6KB of input - exhausted the native stack
|
|
161
|
+
// and crashed the process. `EXPANSION_MAX_DEPTH` bounds how deep the parser
|
|
162
|
+
// will follow nesting. It sits far above any realistic pattern and well below
|
|
163
|
+
// the depth at which the stack runs out.
|
|
164
|
+
var EXPANSION_MAX_DEPTH = 1000;
|
|
165
|
+
|
|
166
|
+
// Bash keeps a quirk where a brace group followed by a comma set still expands
|
|
167
|
+
// (`{a},b}`). The parser implements it by rewriting the string and restarting
|
|
168
|
+
// the scan, absorbing one `}` per pass. `n` trailing braces therefore cost `n`
|
|
169
|
+
// full passes over a string that itself grows by one `escClose` sentinel each
|
|
170
|
+
// time - quadratic in `n`, with a ~26x constant from the sentinel's length.
|
|
171
|
+
// 128KB of `'{a}' + '}'.repeat(n) + ',z}'` blocked the event loop for 27
|
|
172
|
+
// seconds to produce two results. `EXPANSION_MAX_REWRITES` bounds how many
|
|
173
|
+
// times the scan may restart. Real `{a},b}` input needs a handful.
|
|
174
|
+
var EXPANSION_MAX_REWRITES = 1000;
|
|
175
|
+
|
|
176
|
+
function numeric(str) {
|
|
177
|
+
return parseInt(str, 10) == str
|
|
178
|
+
? parseInt(str, 10)
|
|
179
|
+
: str.charCodeAt(0);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function escapeBraces(str) {
|
|
183
|
+
return str.split('\\\\').join(escSlash)
|
|
184
|
+
.split('\\{').join(escOpen)
|
|
185
|
+
.split('\\}').join(escClose)
|
|
186
|
+
.split('\\,').join(escComma)
|
|
187
|
+
.split('\\.').join(escPeriod);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function unescapeBraces(str) {
|
|
191
|
+
return str.split(escSlash).join('\\')
|
|
192
|
+
.split(escOpen).join('{')
|
|
193
|
+
.split(escClose).join('}')
|
|
194
|
+
.split(escComma).join(',')
|
|
195
|
+
.split(escPeriod).join('.');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
// Like `target.push(...items)` but doesn't overflow the stack
|
|
200
|
+
function pushAll(target, items) {
|
|
201
|
+
for (var i = 0; i < items.length; i++) {
|
|
202
|
+
target.push(items[i]);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Basically just str.split(","), but handling cases
|
|
207
|
+
// where we have nested braced sections, which should be
|
|
208
|
+
// treated as individual members, like {a,{b,c},d}
|
|
209
|
+
function parseCommaParts(str) {
|
|
210
|
+
var parts = [];
|
|
387
211
|
|
|
388
|
-
|
|
212
|
+
// Walk the brace groups iteratively. Recursing on `post` once per group let a
|
|
213
|
+
// chain of them exhaust the stack - the parsing-side counterpart to
|
|
214
|
+
// the `expand` overflow fixed for CVE-2026-14257, and not something `max` or
|
|
215
|
+
// `maxLength` can bound, since it happens before expansion.
|
|
216
|
+
//
|
|
217
|
+
// The part the next chunk continues
|
|
218
|
+
var carry = '';
|
|
389
219
|
|
|
390
|
-
|
|
220
|
+
for (;;) {
|
|
221
|
+
var m = balanced('{', '}', str);
|
|
391
222
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
const MAX_PATTERN_LENGTH = 1024 * 64;
|
|
398
|
-
const assertValidPattern$1 = (pattern) => {
|
|
399
|
-
if (typeof pattern !== 'string') {
|
|
400
|
-
throw new TypeError('invalid pattern');
|
|
223
|
+
if (!m) {
|
|
224
|
+
var tail = str.split(',');
|
|
225
|
+
tail[0] = carry + tail[0];
|
|
226
|
+
pushAll(parts, tail);
|
|
227
|
+
return parts;
|
|
401
228
|
}
|
|
402
|
-
|
|
403
|
-
|
|
229
|
+
|
|
230
|
+
var pre = m.pre;
|
|
231
|
+
var body = m.body;
|
|
232
|
+
var post = m.post;
|
|
233
|
+
var p = pre.split(',');
|
|
234
|
+
|
|
235
|
+
p[0] = carry + p[0];
|
|
236
|
+
p[p.length-1] += '{' + body + '}';
|
|
237
|
+
|
|
238
|
+
if (!post.length) {
|
|
239
|
+
pushAll(parts, p);
|
|
240
|
+
return parts;
|
|
404
241
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
//
|
|
450
|
-
//
|
|
451
|
-
//
|
|
452
|
-
//
|
|
453
|
-
//
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
242
|
+
|
|
243
|
+
carry = p.pop();
|
|
244
|
+
pushAll(parts, p);
|
|
245
|
+
str = post;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function expandTop(str, options) {
|
|
250
|
+
if (!str)
|
|
251
|
+
return [];
|
|
252
|
+
|
|
253
|
+
options = options || {};
|
|
254
|
+
var max = options.max == null ? EXPANSION_MAX : options.max;
|
|
255
|
+
var maxLength = options.maxLength == null ? EXPANSION_MAX_LENGTH : options.maxLength;
|
|
256
|
+
var maxDepth = options.maxDepth == null ? EXPANSION_MAX_DEPTH : options.maxDepth;
|
|
257
|
+
var maxRewrites = options.maxRewrites == null ? EXPANSION_MAX_REWRITES : options.maxRewrites;
|
|
258
|
+
|
|
259
|
+
// I don't know why Bash 4.3 does this, but it does.
|
|
260
|
+
// Anything starting with {} will have the first two bytes preserved
|
|
261
|
+
// but *only* at the top level, so {},a}b will not expand to anything,
|
|
262
|
+
// but a{},b}c will be expanded to [a}c,abc].
|
|
263
|
+
// One could argue that this is a bug in Bash, but since the goal of
|
|
264
|
+
// this module is to match Bash's rules, we escape a leading {}
|
|
265
|
+
if (str.substr(0, 2) === '{}') {
|
|
266
|
+
str = '\\{\\}' + str.substr(2);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return expand(escapeBraces(str), max, maxLength, maxDepth, 0, maxRewrites, true).map(unescapeBraces);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function embrace(str) {
|
|
273
|
+
return '{' + str + '}';
|
|
274
|
+
}
|
|
275
|
+
function isPadded(el) {
|
|
276
|
+
return /^-?0\d/.test(el);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function lte(i, y) {
|
|
280
|
+
return i <= y;
|
|
281
|
+
}
|
|
282
|
+
function gte(i, y) {
|
|
283
|
+
return i >= y;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Build `{ acc[a] + pre + values[v] }` for every combination, capping the
|
|
287
|
+
// number of results at `max` and the total number of characters at `maxLength`.
|
|
288
|
+
// This is the one place output grows, so bounding it here keeps the single
|
|
289
|
+
// accumulator - and therefore memory - flat regardless of how many brace groups
|
|
290
|
+
// are combined (CVE-2026-14257).
|
|
291
|
+
function combine(
|
|
292
|
+
acc,
|
|
293
|
+
pre,
|
|
294
|
+
values,
|
|
295
|
+
max,
|
|
296
|
+
maxLength,
|
|
297
|
+
dropEmpties
|
|
298
|
+
) {
|
|
299
|
+
var out = [];
|
|
300
|
+
var length = 0;
|
|
301
|
+
for (var a = 0; a < acc.length; a++) {
|
|
302
|
+
for (var v = 0; v < values.length; v++) {
|
|
303
|
+
if (out.length >= max) return out
|
|
304
|
+
var expansion = acc[a] + pre + values[v];
|
|
305
|
+
// Bash drops empty results at the top level. Skip them before they count
|
|
306
|
+
// against `max`, so `max` bounds the number of *kept* results.
|
|
307
|
+
if (dropEmpties && !expansion) continue
|
|
308
|
+
if (length + expansion.length > maxLength) return out
|
|
309
|
+
out.push(expansion);
|
|
310
|
+
length += expansion.length;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return out
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// The expansion values of a single numeric (`1..5`) or alphabetic (`a..e..2`)
|
|
317
|
+
// sequence body.
|
|
318
|
+
function expandSequence(
|
|
319
|
+
body,
|
|
320
|
+
isAlphaSequence,
|
|
321
|
+
max,
|
|
322
|
+
maxLength
|
|
323
|
+
) {
|
|
324
|
+
var n = body.split(/\.\./);
|
|
325
|
+
var N = [];
|
|
326
|
+
// A sequence body always splits into two or three parts, but the compiler
|
|
327
|
+
// can't know that.
|
|
328
|
+
/* c8 ignore start */
|
|
329
|
+
if (n[0] === undefined || n[1] === undefined) {
|
|
330
|
+
return N
|
|
331
|
+
}
|
|
332
|
+
/* c8 ignore stop */
|
|
333
|
+
var x = numeric(n[0]);
|
|
334
|
+
var y = numeric(n[1]);
|
|
335
|
+
var width = Math.max(n[0].length, n[1].length);
|
|
336
|
+
var incr =
|
|
337
|
+
n.length === 3 && n[2] !== undefined ?
|
|
338
|
+
Math.max(Math.abs(numeric(n[2])), 1)
|
|
339
|
+
: 1;
|
|
340
|
+
var test = lte;
|
|
341
|
+
var reverse = y < x;
|
|
342
|
+
if (reverse) {
|
|
343
|
+
incr *= -1;
|
|
344
|
+
test = gte;
|
|
345
|
+
}
|
|
346
|
+
var pad = n.some(isPadded);
|
|
347
|
+
|
|
348
|
+
var length = 0;
|
|
349
|
+
for (var i = x; test(i, y) && N.length < max; i += incr) {
|
|
350
|
+
var c;
|
|
351
|
+
if (isAlphaSequence) {
|
|
352
|
+
c = String.fromCharCode(i);
|
|
353
|
+
if (c === '\\') {
|
|
354
|
+
c = '';
|
|
355
|
+
}
|
|
356
|
+
} else {
|
|
357
|
+
c = String(i);
|
|
358
|
+
if (pad) {
|
|
359
|
+
var need = width - c.length;
|
|
360
|
+
if (need > 0) {
|
|
361
|
+
var z = new Array(need + 1).join('0');
|
|
362
|
+
if (i < 0) {
|
|
363
|
+
c = '-' + z + c.slice(1);
|
|
364
|
+
} else {
|
|
365
|
+
c = z + c;
|
|
366
|
+
}
|
|
507
367
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
if (length + c.length > maxLength) break
|
|
371
|
+
N.push(c);
|
|
372
|
+
length += c.length;
|
|
373
|
+
}
|
|
374
|
+
return N
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function expand(
|
|
378
|
+
str,
|
|
379
|
+
max,
|
|
380
|
+
maxLength,
|
|
381
|
+
maxDepth,
|
|
382
|
+
depth,
|
|
383
|
+
maxRewrites,
|
|
384
|
+
isTop
|
|
385
|
+
) {
|
|
386
|
+
// Too deeply nested to keep following: treat the rest as literal, the same
|
|
387
|
+
// way a group that cannot expand is already handled. Truncating rather than
|
|
388
|
+
// throwing keeps expansion total, matching `max` and `maxLength`.
|
|
389
|
+
if (depth > maxDepth) {
|
|
390
|
+
return [str];
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// Consume the string's top-level brace groups left to right, threading a
|
|
394
|
+
// running set of combined prefixes (`acc`). Expanding the tail iteratively -
|
|
395
|
+
// rather than recursing on `m.post` once per group - keeps the native stack
|
|
396
|
+
// depth constant, so deeply chained input (`'{a,b}'.repeat(3000)`) can no
|
|
397
|
+
// longer overflow the stack, and leaves a single accumulator whose size
|
|
398
|
+
// `maxLength` bounds directly (CVE-2026-14257).
|
|
399
|
+
var acc = [''];
|
|
400
|
+
|
|
401
|
+
// Bash drops empty results, but only when the *first* top-level group is a
|
|
402
|
+
// comma set - a sequence like `{a..\}` may legitimately yield ''. The drop
|
|
403
|
+
// is on the final strings, so it is applied to whichever `combine` produces
|
|
404
|
+
// them (the one with no brace set left in the tail).
|
|
405
|
+
// How many times the `{a},b}` rewrite below has restarted the scan. Each pass
|
|
406
|
+
// re-reads the whole string, so leaving this unbounded is quadratic.
|
|
407
|
+
var rewrites = 0;
|
|
408
|
+
var dropEmpties = false;
|
|
409
|
+
var firstGroup = true;
|
|
410
|
+
|
|
411
|
+
for (;;) {
|
|
412
|
+
const m = balanced('{', '}', str);
|
|
413
|
+
|
|
414
|
+
// No brace set left: the rest of the string is literal.
|
|
415
|
+
if (!m) {
|
|
416
|
+
return combine(acc, str, [''], max, maxLength, dropEmpties)
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// no need to expand pre, since it is guaranteed to be free of brace-sets
|
|
420
|
+
const pre = m.pre;
|
|
421
|
+
|
|
422
|
+
if (/\$$/.test(pre)) {
|
|
423
|
+
acc = combine(
|
|
424
|
+
acc,
|
|
425
|
+
pre + '{' + m.body + '}',
|
|
426
|
+
[''],
|
|
427
|
+
max,
|
|
428
|
+
maxLength,
|
|
429
|
+
dropEmpties && !m.post.length
|
|
430
|
+
);
|
|
431
|
+
firstGroup = false;
|
|
432
|
+
if (!m.post.length) break
|
|
433
|
+
str = m.post;
|
|
434
|
+
continue
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
|
|
438
|
+
var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
|
|
439
|
+
var isSequence = isNumericSequence || isAlphaSequence;
|
|
440
|
+
var isOptions = m.body.indexOf(',') >= 0;
|
|
441
|
+
if (!isSequence && !isOptions) {
|
|
442
|
+
// {a},b}
|
|
443
|
+
if (rewrites < maxRewrites && m.post.match(/,(?!,).*\}/)) {
|
|
444
|
+
rewrites++;
|
|
445
|
+
str = m.pre + '{' + m.body + escClose + m.post;
|
|
446
|
+
isTop = true;
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
449
|
+
// Nothing here expands, so the whole remaining string is literal.
|
|
450
|
+
return combine(
|
|
451
|
+
acc,
|
|
452
|
+
pre + '{' + m.body + '}' + m.post,
|
|
453
|
+
[''],
|
|
454
|
+
max,
|
|
455
|
+
maxLength,
|
|
456
|
+
dropEmpties
|
|
457
|
+
)
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
if (firstGroup) {
|
|
461
|
+
dropEmpties = isTop && !isSequence;
|
|
462
|
+
firstGroup = false;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
var values;
|
|
466
|
+
if (isSequence) {
|
|
467
|
+
values = expandSequence(m.body, isAlphaSequence, max, maxLength);
|
|
468
|
+
} else {
|
|
469
|
+
var n = parseCommaParts(m.body);
|
|
470
|
+
if (n.length === 1 && n[0] !== undefined) {
|
|
471
|
+
// x{{a,b}}y ==> x{a}y x{b}y
|
|
472
|
+
n = expand(n[0], max, maxLength, maxDepth, depth + 1, maxRewrites, false).map(embrace);
|
|
473
|
+
//XXX is this necessary? Can't seem to hit it in tests.
|
|
474
|
+
/* c8 ignore start */
|
|
475
|
+
if (n.length === 1) {
|
|
476
|
+
acc = combine(
|
|
477
|
+
acc,
|
|
478
|
+
pre + n[0],
|
|
479
|
+
[''],
|
|
480
|
+
max,
|
|
481
|
+
maxLength,
|
|
482
|
+
dropEmpties && !m.post.length
|
|
483
|
+
);
|
|
484
|
+
if (!m.post.length) break
|
|
485
|
+
str = m.post;
|
|
486
|
+
continue
|
|
522
487
|
}
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
488
|
+
/* c8 ignore stop */
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// Values that `combine` is going to drop as empty produce no result, so
|
|
492
|
+
// they must not count against `max` - otherwise `{a,,b}` with `max: 2`
|
|
493
|
+
// would stop at `['a', '']` and yield one result instead of two. Skipping
|
|
494
|
+
// them outright keeps `values` bounded while leaving `max` a bound on
|
|
495
|
+
// *kept* results.
|
|
496
|
+
var dropsEmpties = dropEmpties && !m.post.length && !pre;
|
|
497
|
+
for (var d = 0; dropsEmpties && d < acc.length; d++) {
|
|
498
|
+
if (acc[d]) {
|
|
499
|
+
dropsEmpties = false;
|
|
529
500
|
}
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
values = [];
|
|
504
|
+
var valuesLength = 0;
|
|
505
|
+
outer: for (var j = 0; j < n.length; j++) {
|
|
506
|
+
var expanded = expand(n[j], max, maxLength, maxDepth, depth + 1, maxRewrites, false);
|
|
507
|
+
for (var k = 0; k < expanded.length; k++) {
|
|
508
|
+
var v = expanded[k];
|
|
509
|
+
if (dropsEmpties && !v) continue
|
|
510
|
+
if (values.length >= max || valuesLength + v.length > maxLength) {
|
|
511
|
+
break outer
|
|
512
|
+
}
|
|
513
|
+
values.push(v);
|
|
514
|
+
valuesLength += v.length;
|
|
534
515
|
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
if (
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
if (!ranges.length && !negs.length) {
|
|
547
|
-
return ['$.', false, glob.length - pos, true];
|
|
548
|
-
}
|
|
549
|
-
// if we got one positive range, and it's a single character, then that's
|
|
550
|
-
// not actually a magic pattern, it's just that one literal character.
|
|
551
|
-
// we should not treat that as "magic", we should just return the literal
|
|
552
|
-
// character. [_] is a perfectly valid way to escape glob magic chars.
|
|
553
|
-
if (negs.length === 0 &&
|
|
554
|
-
ranges.length === 1 &&
|
|
555
|
-
/^\\?.$/.test(ranges[0]) &&
|
|
556
|
-
!negate) {
|
|
557
|
-
const r = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0];
|
|
558
|
-
return [regexpEscape(r), false, endPos - pos, false];
|
|
559
|
-
}
|
|
560
|
-
const sranges = '[' + (negate ? '^' : '') + rangesToString(ranges) + ']';
|
|
561
|
-
const snegs = '[' + (negate ? '' : '^') + rangesToString(negs) + ']';
|
|
562
|
-
const comb = ranges.length && negs.length ? '(' + sranges + '|' + snegs + ')'
|
|
563
|
-
: ranges.length ? sranges
|
|
564
|
-
: snegs;
|
|
565
|
-
return [comb, uflag, endPos - pos, true];
|
|
566
|
-
};
|
|
567
|
-
braceExpressions.parseClass = parseClass;
|
|
568
|
-
|
|
569
|
-
return braceExpressions;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
acc = combine(acc, pre, values, max, maxLength, dropEmpties && !m.post.length);
|
|
520
|
+
if (!m.post.length) break
|
|
521
|
+
str = m.post;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
return acc
|
|
525
|
+
}
|
|
526
|
+
return braceExpansion;
|
|
570
527
|
}
|
|
571
528
|
|
|
572
|
-
var
|
|
529
|
+
var minimatch_1;
|
|
530
|
+
var hasRequiredMinimatch;
|
|
573
531
|
|
|
574
|
-
|
|
532
|
+
function requireMinimatch () {
|
|
533
|
+
if (hasRequiredMinimatch) return minimatch_1;
|
|
534
|
+
hasRequiredMinimatch = 1;
|
|
535
|
+
const minimatch = minimatch_1 = (p, pattern, options = {}) => {
|
|
536
|
+
assertValidPattern(pattern);
|
|
537
|
+
|
|
538
|
+
// shortcut: comments match nothing.
|
|
539
|
+
if (!options.nocomment && pattern.charAt(0) === '#') {
|
|
540
|
+
return false
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
return new Minimatch(pattern, options).match(p)
|
|
544
|
+
};
|
|
545
|
+
|
|
546
|
+
minimatch_1 = minimatch;
|
|
547
|
+
|
|
548
|
+
const path = requirePath();
|
|
549
|
+
minimatch.sep = path.sep;
|
|
550
|
+
|
|
551
|
+
const GLOBSTAR = Symbol('globstar **');
|
|
552
|
+
minimatch.GLOBSTAR = GLOBSTAR;
|
|
553
|
+
const expand = requireBraceExpansion();
|
|
554
|
+
|
|
555
|
+
const plTypes = {
|
|
556
|
+
'!': { open: '(?:(?!(?:', close: '))[^/]*?)'},
|
|
557
|
+
'?': { open: '(?:', close: ')?' },
|
|
558
|
+
'+': { open: '(?:', close: ')+' },
|
|
559
|
+
'*': { open: '(?:', close: ')*' },
|
|
560
|
+
'@': { open: '(?:', close: ')' }
|
|
561
|
+
};
|
|
575
562
|
|
|
576
|
-
function require_unescape () {
|
|
577
|
-
if (hasRequired_unescape) return _unescape;
|
|
578
|
-
hasRequired_unescape = 1;
|
|
579
|
-
Object.defineProperty(_unescape, "__esModule", { value: true });
|
|
580
|
-
_unescape.unescape = void 0;
|
|
581
|
-
/**
|
|
582
|
-
* Un-escape a string that has been escaped with {@link escape}.
|
|
583
|
-
*
|
|
584
|
-
* If the {@link MinimatchOptions.windowsPathsNoEscape} option is used, then
|
|
585
|
-
* square-bracket escapes are removed, but not backslash escapes.
|
|
586
|
-
*
|
|
587
|
-
* For example, it will turn the string `'[*]'` into `*`, but it will not
|
|
588
|
-
* turn `'\\*'` into `'*'`, because `\` is a path separator in
|
|
589
|
-
* `windowsPathsNoEscape` mode.
|
|
590
|
-
*
|
|
591
|
-
* When `windowsPathsNoEscape` is not set, then both square-bracket escapes and
|
|
592
|
-
* backslash escapes are removed.
|
|
593
|
-
*
|
|
594
|
-
* Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot be escaped
|
|
595
|
-
* or unescaped.
|
|
596
|
-
*
|
|
597
|
-
* When `magicalBraces` is not set, escapes of braces (`{` and `}`) will not be
|
|
598
|
-
* unescaped.
|
|
599
|
-
*/
|
|
600
|
-
const unescape = (s, { windowsPathsNoEscape = false, magicalBraces = true, } = {}) => {
|
|
601
|
-
if (magicalBraces) {
|
|
602
|
-
return windowsPathsNoEscape ?
|
|
603
|
-
s.replace(/\[([^/\\])\]/g, '$1')
|
|
604
|
-
: s
|
|
605
|
-
.replace(/((?!\\).|^)\[([^/\\])\]/g, '$1$2')
|
|
606
|
-
.replace(/\\([^/])/g, '$1');
|
|
607
|
-
}
|
|
608
|
-
return windowsPathsNoEscape ?
|
|
609
|
-
s.replace(/\[([^/\\{}])\]/g, '$1')
|
|
610
|
-
: s
|
|
611
|
-
.replace(/((?!\\).|^)\[([^/\\{}])\]/g, '$1$2')
|
|
612
|
-
.replace(/\\([^/{}])/g, '$1');
|
|
613
|
-
};
|
|
614
|
-
_unescape.unescape = unescape;
|
|
615
|
-
|
|
616
|
-
return _unescape;
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
var hasRequiredAst;
|
|
620
|
-
|
|
621
|
-
function requireAst () {
|
|
622
|
-
if (hasRequiredAst) return ast;
|
|
623
|
-
hasRequiredAst = 1;
|
|
624
|
-
// parse a single path portion
|
|
625
|
-
var _a;
|
|
626
|
-
Object.defineProperty(ast, "__esModule", { value: true });
|
|
627
|
-
ast.AST = void 0;
|
|
628
|
-
const brace_expressions_js_1 = requireBraceExpressions();
|
|
629
|
-
const unescape_js_1 = require_unescape();
|
|
630
|
-
const types = new Set(['!', '?', '+', '*', '@']);
|
|
631
|
-
const isExtglobType = (c) => types.has(c);
|
|
632
|
-
const isExtglobAST = (c) => isExtglobType(c.type);
|
|
633
|
-
// Map of which extglob types can adopt the children of a nested extglob
|
|
634
|
-
//
|
|
635
|
-
// anything but ! can adopt a matching type:
|
|
636
|
-
// +(a|+(b|c)|d) => +(a|b|c|d)
|
|
637
|
-
// *(a|*(b|c)|d) => *(a|b|c|d)
|
|
638
|
-
// @(a|@(b|c)|d) => @(a|b|c|d)
|
|
639
|
-
// ?(a|?(b|c)|d) => ?(a|b|c|d)
|
|
640
|
-
//
|
|
641
|
-
// * can adopt anything, because 0 or repetition is allowed
|
|
642
|
-
// *(a|?(b|c)|d) => *(a|b|c|d)
|
|
643
|
-
// *(a|+(b|c)|d) => *(a|b|c|d)
|
|
644
|
-
// *(a|@(b|c)|d) => *(a|b|c|d)
|
|
645
|
-
//
|
|
646
|
-
// + can adopt @, because 1 or repetition is allowed
|
|
647
|
-
// +(a|@(b|c)|d) => +(a|b|c|d)
|
|
648
|
-
//
|
|
649
|
-
// + and @ CANNOT adopt *, because 0 would be allowed
|
|
650
|
-
// +(a|*(b|c)|d) => would match "", on *(b|c)
|
|
651
|
-
// @(a|*(b|c)|d) => would match "", on *(b|c)
|
|
652
|
-
//
|
|
653
|
-
// + and @ CANNOT adopt ?, because 0 would be allowed
|
|
654
|
-
// +(a|?(b|c)|d) => would match "", on ?(b|c)
|
|
655
|
-
// @(a|?(b|c)|d) => would match "", on ?(b|c)
|
|
656
|
-
//
|
|
657
|
-
// ? can adopt @, because 0 or 1 is allowed
|
|
658
|
-
// ?(a|@(b|c)|d) => ?(a|b|c|d)
|
|
659
|
-
//
|
|
660
|
-
// ? and @ CANNOT adopt * or +, because >1 would be allowed
|
|
661
|
-
// ?(a|*(b|c)|d) => would match bbb on *(b|c)
|
|
662
|
-
// @(a|*(b|c)|d) => would match bbb on *(b|c)
|
|
663
|
-
// ?(a|+(b|c)|d) => would match bbb on +(b|c)
|
|
664
|
-
// @(a|+(b|c)|d) => would match bbb on +(b|c)
|
|
665
|
-
//
|
|
666
|
-
// ! CANNOT adopt ! (nothing else can either)
|
|
667
|
-
// !(a|!(b|c)|d) => !(a|b|c|d) would fail to match on b (not not b|c)
|
|
668
|
-
//
|
|
669
|
-
// ! can adopt @
|
|
670
|
-
// !(a|@(b|c)|d) => !(a|b|c|d)
|
|
671
|
-
//
|
|
672
|
-
// ! CANNOT adopt *
|
|
673
|
-
// !(a|*(b|c)|d) => !(a|b|c|d) would match on bbb, not allowed
|
|
674
|
-
//
|
|
675
|
-
// ! CANNOT adopt +
|
|
676
|
-
// !(a|+(b|c)|d) => !(a|b|c|d) would match on bbb, not allowed
|
|
677
|
-
//
|
|
678
|
-
// ! CANNOT adopt ?
|
|
679
|
-
// x!(a|?(b|c)|d) => x!(a|b|c|d) would fail to match "x"
|
|
680
|
-
const adoptionMap = new Map([
|
|
681
|
-
['!', ['@']],
|
|
682
|
-
['?', ['?', '@']],
|
|
683
|
-
['@', ['@']],
|
|
684
|
-
['*', ['*', '+', '?', '@']],
|
|
685
|
-
['+', ['+', '@']],
|
|
686
|
-
]);
|
|
687
|
-
// nested extglobs that can be adopted in, but with the addition of
|
|
688
|
-
// a blank '' element.
|
|
689
|
-
const adoptionWithSpaceMap = new Map([
|
|
690
|
-
['!', ['?']],
|
|
691
|
-
['@', ['?']],
|
|
692
|
-
['+', ['?', '*']],
|
|
693
|
-
]);
|
|
694
|
-
// union of the previous two maps
|
|
695
|
-
const adoptionAnyMap = new Map([
|
|
696
|
-
['!', ['?', '@']],
|
|
697
|
-
['?', ['?', '@']],
|
|
698
|
-
['@', ['?', '@']],
|
|
699
|
-
['*', ['*', '+', '?', '@']],
|
|
700
|
-
['+', ['+', '@', '?', '*']],
|
|
701
|
-
]);
|
|
702
|
-
// Extglobs that can take over their parent if they are the only child
|
|
703
|
-
// the key is parent, value maps child to resulting extglob parent type
|
|
704
|
-
// '@' is omitted because it's a special case. An `@` extglob with a single
|
|
705
|
-
// member can always be usurped by that subpattern.
|
|
706
|
-
const usurpMap = new Map([
|
|
707
|
-
['!', new Map([['!', '@']])],
|
|
708
|
-
[
|
|
709
|
-
'?',
|
|
710
|
-
new Map([
|
|
711
|
-
['*', '*'],
|
|
712
|
-
['+', '*'],
|
|
713
|
-
]),
|
|
714
|
-
],
|
|
715
|
-
[
|
|
716
|
-
'@',
|
|
717
|
-
new Map([
|
|
718
|
-
['!', '!'],
|
|
719
|
-
['?', '?'],
|
|
720
|
-
['@', '@'],
|
|
721
|
-
['*', '*'],
|
|
722
|
-
['+', '+'],
|
|
723
|
-
]),
|
|
724
|
-
],
|
|
725
|
-
[
|
|
726
|
-
'+',
|
|
727
|
-
new Map([
|
|
728
|
-
['?', '*'],
|
|
729
|
-
['*', '*'],
|
|
730
|
-
]),
|
|
731
|
-
],
|
|
732
|
-
]);
|
|
733
|
-
// Patterns that get prepended to bind to the start of either the
|
|
734
|
-
// entire string, or just a single path portion, to prevent dots
|
|
735
|
-
// and/or traversal patterns, when needed.
|
|
736
|
-
// Exts don't need the ^ or / bit, because the root binds that already.
|
|
737
|
-
const startNoTraversal = '(?!(?:^|/)\\.\\.?(?:$|/))';
|
|
738
|
-
const startNoDot = '(?!\\.)';
|
|
739
|
-
// characters that indicate a start of pattern needs the "no dots" bit,
|
|
740
|
-
// because a dot *might* be matched. ( is not in the list, because in
|
|
741
|
-
// the case of a child extglob, it will handle the prevention itself.
|
|
742
|
-
const addPatternStart = new Set(['[', '.']);
|
|
743
|
-
// cases where traversal is A-OK, no dot prevention needed
|
|
744
|
-
const justDots = new Set(['..', '.']);
|
|
745
|
-
const reSpecials = new Set('().*{}+?[]^$\\!');
|
|
746
|
-
const regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
|
747
563
|
// any single thing other than /
|
|
564
|
+
// don't need to escape / when using new RegExp()
|
|
748
565
|
const qmark = '[^/]';
|
|
566
|
+
|
|
749
567
|
// * => any number of characters
|
|
750
568
|
const star = qmark + '*?';
|
|
751
|
-
|
|
752
|
-
//
|
|
753
|
-
|
|
754
|
-
//
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
569
|
+
|
|
570
|
+
// ** when dots are allowed. Anything goes, except .. and .
|
|
571
|
+
// not (^ or / followed by one or two dots followed by $ or /),
|
|
572
|
+
// followed by anything, any number of times.
|
|
573
|
+
const twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?';
|
|
574
|
+
|
|
575
|
+
// not a ^ or / followed by a dot,
|
|
576
|
+
// followed by anything, any number of times.
|
|
577
|
+
const twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?';
|
|
578
|
+
|
|
579
|
+
// "abc" -> { a:true, b:true, c:true }
|
|
580
|
+
const charSet = s => s.split('').reduce((set, c) => {
|
|
581
|
+
set[c] = true;
|
|
582
|
+
return set
|
|
583
|
+
}, {});
|
|
584
|
+
|
|
585
|
+
// characters that need to be escaped in RegExp.
|
|
586
|
+
const reSpecials = charSet('().*{}+?[]^$\\!');
|
|
587
|
+
|
|
588
|
+
// characters that indicate we have to add the pattern start
|
|
589
|
+
const addPatternStartSet = charSet('[.(');
|
|
590
|
+
|
|
591
|
+
// normalizes slashes.
|
|
592
|
+
const slashSplit = /\/+/;
|
|
593
|
+
|
|
594
|
+
minimatch.filter = (pattern, options = {}) =>
|
|
595
|
+
(p, i, list) => minimatch(p, pattern, options);
|
|
596
|
+
|
|
597
|
+
const ext = (a, b = {}) => {
|
|
598
|
+
const t = {};
|
|
599
|
+
Object.keys(a).forEach(k => t[k] = a[k]);
|
|
600
|
+
Object.keys(b).forEach(k => t[k] = b[k]);
|
|
601
|
+
return t
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
minimatch.defaults = def => {
|
|
605
|
+
if (!def || typeof def !== 'object' || !Object.keys(def).length) {
|
|
606
|
+
return minimatch
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
const orig = minimatch;
|
|
610
|
+
|
|
611
|
+
const m = (p, pattern, options) => orig(p, pattern, ext(def, options));
|
|
612
|
+
m.Minimatch = class Minimatch extends orig.Minimatch {
|
|
613
|
+
constructor (pattern, options) {
|
|
614
|
+
super(pattern, ext(def, options));
|
|
787
615
|
}
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
616
|
+
};
|
|
617
|
+
m.Minimatch.defaults = options => orig.defaults(ext(def, options)).Minimatch;
|
|
618
|
+
m.filter = (pattern, options) => orig.filter(pattern, ext(def, options));
|
|
619
|
+
m.defaults = options => orig.defaults(ext(def, options));
|
|
620
|
+
m.makeRe = (pattern, options) => orig.makeRe(pattern, ext(def, options));
|
|
621
|
+
m.braceExpand = (pattern, options) => orig.braceExpand(pattern, ext(def, options));
|
|
622
|
+
m.match = (list, pattern, options) => orig.match(list, pattern, ext(def, options));
|
|
623
|
+
|
|
624
|
+
return m
|
|
625
|
+
};
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
// Brace expansion:
|
|
632
|
+
// a{b,c}d -> abd acd
|
|
633
|
+
// a{b,}c -> abc ac
|
|
634
|
+
// a{0..3}d -> a0d a1d a2d a3d
|
|
635
|
+
// a{b,c{d,e}f}g -> abg acdfg acefg
|
|
636
|
+
// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
|
|
637
|
+
//
|
|
638
|
+
// Invalid sets are not expanded.
|
|
639
|
+
// a{2..}b -> a{2..}b
|
|
640
|
+
// a{b}c -> a{b}c
|
|
641
|
+
minimatch.braceExpand = (pattern, options) => braceExpand(pattern, options);
|
|
642
|
+
|
|
643
|
+
const braceExpand = (pattern, options = {}) => {
|
|
644
|
+
assertValidPattern(pattern);
|
|
645
|
+
|
|
646
|
+
// Thanks to Yeting Li <https://github.com/yetingli> for
|
|
647
|
+
// improving this regexp to avoid a ReDOS vulnerability.
|
|
648
|
+
if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
|
|
649
|
+
// shortcut. no need to expand.
|
|
650
|
+
return [pattern]
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
return expand(pattern)
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
const MAX_PATTERN_LENGTH = 1024 * 64;
|
|
657
|
+
const assertValidPattern = pattern => {
|
|
658
|
+
if (typeof pattern !== 'string') {
|
|
659
|
+
throw new TypeError('invalid pattern')
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
if (pattern.length > MAX_PATTERN_LENGTH) {
|
|
663
|
+
throw new TypeError('pattern is too long')
|
|
664
|
+
}
|
|
665
|
+
};
|
|
666
|
+
|
|
667
|
+
// parse a component of the expanded set.
|
|
668
|
+
// At this point, no pattern may contain "/" in it
|
|
669
|
+
// so we're going to return a 2d array, where each entry is the full
|
|
670
|
+
// pattern, split on '/', and then turned into a regular expression.
|
|
671
|
+
// A regexp is made at the end which joins each array with an
|
|
672
|
+
// escaped /, and another full one which joins each regexp with |.
|
|
673
|
+
//
|
|
674
|
+
// Following the lead of Bash 4.1, note that "**" only has special meaning
|
|
675
|
+
// when it is the *only* thing in a path portion. Otherwise, any series
|
|
676
|
+
// of * is equivalent to a single *. Globstar behavior is enabled by
|
|
677
|
+
// default, and can be disabled by setting options.noglobstar.
|
|
678
|
+
const SUBPARSE = Symbol('subparse');
|
|
679
|
+
|
|
680
|
+
minimatch.makeRe = (pattern, options) =>
|
|
681
|
+
new Minimatch(pattern, options || {}).makeRe();
|
|
682
|
+
|
|
683
|
+
minimatch.match = (list, pattern, options = {}) => {
|
|
684
|
+
const mm = new Minimatch(pattern, options);
|
|
685
|
+
list = list.filter(f => mm.match(f));
|
|
686
|
+
if (mm.options.nonull && !list.length) {
|
|
687
|
+
list.push(pattern);
|
|
688
|
+
}
|
|
689
|
+
return list
|
|
690
|
+
};
|
|
691
|
+
|
|
692
|
+
// replace stuff like \* with *
|
|
693
|
+
const globUnescape = s => s.replace(/\\(.)/g, '$1');
|
|
694
|
+
const charUnescape = s => s.replace(/\\([^-\]])/g, '$1');
|
|
695
|
+
const regExpEscape = s => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
|
696
|
+
const braExpEscape = s => s.replace(/[[\]\\]/g, '\\$&');
|
|
697
|
+
|
|
698
|
+
class Minimatch {
|
|
699
|
+
constructor (pattern, options) {
|
|
700
|
+
assertValidPattern(pattern);
|
|
701
|
+
|
|
702
|
+
if (!options) options = {};
|
|
703
|
+
|
|
704
|
+
this.options = options;
|
|
705
|
+
this.maxGlobstarRecursion = options.maxGlobstarRecursion !== undefined
|
|
706
|
+
? options.maxGlobstarRecursion : 200;
|
|
707
|
+
this.set = [];
|
|
708
|
+
this.pattern = pattern;
|
|
709
|
+
this.windowsPathsNoEscape = !!options.windowsPathsNoEscape ||
|
|
710
|
+
options.allowWindowsEscape === false;
|
|
711
|
+
if (this.windowsPathsNoEscape) {
|
|
712
|
+
this.pattern = this.pattern.replace(/\\/g, '/');
|
|
713
|
+
}
|
|
714
|
+
this.regexp = null;
|
|
715
|
+
this.negate = false;
|
|
716
|
+
this.comment = false;
|
|
717
|
+
this.empty = false;
|
|
718
|
+
this.partial = !!options.partial;
|
|
719
|
+
|
|
720
|
+
// make the set of regexps etc.
|
|
721
|
+
this.make();
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
debug () {}
|
|
725
|
+
|
|
726
|
+
make () {
|
|
727
|
+
const pattern = this.pattern;
|
|
728
|
+
const options = this.options;
|
|
729
|
+
|
|
730
|
+
// empty patterns and comments match nothing.
|
|
731
|
+
if (!options.nocomment && pattern.charAt(0) === '#') {
|
|
732
|
+
this.comment = true;
|
|
733
|
+
return
|
|
734
|
+
}
|
|
735
|
+
if (!pattern) {
|
|
736
|
+
this.empty = true;
|
|
737
|
+
return
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
// step 1: figure out negation, etc.
|
|
741
|
+
this.parseNegate();
|
|
742
|
+
|
|
743
|
+
// step 2: expand braces
|
|
744
|
+
let set = this.globSet = this.braceExpand();
|
|
745
|
+
|
|
746
|
+
if (options.debug) this.debug = (...args) => console.error(...args);
|
|
747
|
+
|
|
748
|
+
this.debug(this.pattern, set);
|
|
749
|
+
|
|
750
|
+
// step 3: now we have a set, so turn each one into a series of path-portion
|
|
751
|
+
// matching patterns.
|
|
752
|
+
// These will be regexps, except in the case of "**", which is
|
|
753
|
+
// set to the GLOBSTAR object for globstar behavior,
|
|
754
|
+
// and will not contain any / characters
|
|
755
|
+
set = this.globParts = set.map(s => s.split(slashSplit));
|
|
756
|
+
|
|
757
|
+
this.debug(this.pattern, set);
|
|
758
|
+
|
|
759
|
+
// glob --> regexps
|
|
760
|
+
set = set.map((s, si, set) => s.map(this.parse, this));
|
|
761
|
+
|
|
762
|
+
this.debug(this.pattern, set);
|
|
763
|
+
|
|
764
|
+
// filter out everything that didn't compile properly.
|
|
765
|
+
set = set.filter(s => s.indexOf(false) === -1);
|
|
766
|
+
|
|
767
|
+
this.debug(this.pattern, set);
|
|
768
|
+
|
|
769
|
+
this.set = set;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
parseNegate () {
|
|
773
|
+
if (this.options.nonegate) return
|
|
774
|
+
|
|
775
|
+
const pattern = this.pattern;
|
|
776
|
+
let negate = false;
|
|
777
|
+
let negateOffset = 0;
|
|
778
|
+
|
|
779
|
+
for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {
|
|
780
|
+
negate = !negate;
|
|
781
|
+
negateOffset++;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
if (negateOffset) this.pattern = pattern.slice(negateOffset);
|
|
785
|
+
this.negate = negate;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
// set partial to true to test if, for example,
|
|
789
|
+
// "/a/b" matches the start of "/*/b/*/d"
|
|
790
|
+
// Partial means, if you run out of file before you run
|
|
791
|
+
// out of pattern, then that's fine, as long as all
|
|
792
|
+
// the parts match.
|
|
793
|
+
matchOne (file, pattern, partial) {
|
|
794
|
+
if (pattern.indexOf(GLOBSTAR) !== -1) {
|
|
795
|
+
return this._matchGlobstar(file, pattern, partial, 0, 0)
|
|
796
|
+
}
|
|
797
|
+
return this._matchOne(file, pattern, partial, 0, 0)
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
_matchGlobstar (file, pattern, partial, fileIndex, patternIndex) {
|
|
801
|
+
// find first globstar from patternIndex
|
|
802
|
+
let firstgs = -1;
|
|
803
|
+
for (let i = patternIndex; i < pattern.length; i++) {
|
|
804
|
+
if (pattern[i] === GLOBSTAR) { firstgs = i; break }
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
// find last globstar
|
|
808
|
+
let lastgs = -1;
|
|
809
|
+
for (let i = pattern.length - 1; i >= 0; i--) {
|
|
810
|
+
if (pattern[i] === GLOBSTAR) { lastgs = i; break }
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
const head = pattern.slice(patternIndex, firstgs);
|
|
814
|
+
const body = partial ? pattern.slice(firstgs + 1) : pattern.slice(firstgs + 1, lastgs);
|
|
815
|
+
const tail = partial ? [] : pattern.slice(lastgs + 1);
|
|
816
|
+
|
|
817
|
+
// check the head
|
|
818
|
+
if (head.length) {
|
|
819
|
+
const fileHead = file.slice(fileIndex, fileIndex + head.length);
|
|
820
|
+
if (!this._matchOne(fileHead, head, partial, 0, 0)) {
|
|
821
|
+
return false
|
|
822
|
+
}
|
|
823
|
+
fileIndex += head.length;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// check the tail
|
|
827
|
+
let fileTailMatch = 0;
|
|
828
|
+
if (tail.length) {
|
|
829
|
+
if (tail.length + fileIndex > file.length) return false
|
|
830
|
+
|
|
831
|
+
const tailStart = file.length - tail.length;
|
|
832
|
+
if (this._matchOne(file, tail, partial, tailStart, 0)) {
|
|
833
|
+
fileTailMatch = tail.length;
|
|
834
|
+
} else {
|
|
835
|
+
// affordance for stuff like a/**/* matching a/b/
|
|
836
|
+
if (file[file.length - 1] !== '' ||
|
|
837
|
+
fileIndex + tail.length === file.length) {
|
|
838
|
+
return false
|
|
857
839
|
}
|
|
858
|
-
|
|
840
|
+
if (!this._matchOne(file, tail, partial, tailStart - 1, 0)) {
|
|
841
|
+
return false
|
|
842
|
+
}
|
|
843
|
+
fileTailMatch = tail.length + 1;
|
|
844
|
+
}
|
|
859
845
|
}
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
this.#parts.push(p);
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
toJSON() {
|
|
874
|
-
const ret = this.type === null ?
|
|
875
|
-
this.#parts
|
|
876
|
-
.slice()
|
|
877
|
-
.map(p => (typeof p === 'string' ? p : p.toJSON()))
|
|
878
|
-
: [this.type, ...this.#parts.map(p => p.toJSON())];
|
|
879
|
-
if (this.isStart() && !this.type)
|
|
880
|
-
ret.unshift([]);
|
|
881
|
-
if (this.isEnd() &&
|
|
882
|
-
(this === this.#root ||
|
|
883
|
-
(this.#root.#filledNegs && this.#parent?.type === '!'))) {
|
|
884
|
-
ret.push({});
|
|
885
|
-
}
|
|
886
|
-
return ret;
|
|
887
|
-
}
|
|
888
|
-
isStart() {
|
|
889
|
-
if (this.#root === this)
|
|
890
|
-
return true;
|
|
891
|
-
// if (this.type) return !!this.#parent?.isStart()
|
|
892
|
-
if (!this.#parent?.isStart())
|
|
893
|
-
return false;
|
|
894
|
-
if (this.#parentIndex === 0)
|
|
895
|
-
return true;
|
|
896
|
-
// if everything AHEAD of this is a negation, then it's still the "start"
|
|
897
|
-
const p = this.#parent;
|
|
898
|
-
for (let i = 0; i < this.#parentIndex; i++) {
|
|
899
|
-
const pp = p.#parts[i];
|
|
900
|
-
if (!(pp instanceof _a && pp.type === '!')) {
|
|
901
|
-
return false;
|
|
902
|
-
}
|
|
846
|
+
|
|
847
|
+
// if body is empty (single ** between head and tail)
|
|
848
|
+
if (!body.length) {
|
|
849
|
+
let sawSome = !!fileTailMatch;
|
|
850
|
+
for (let i = fileIndex; i < file.length - fileTailMatch; i++) {
|
|
851
|
+
const f = String(file[i]);
|
|
852
|
+
sawSome = true;
|
|
853
|
+
if (f === '.' || f === '..' ||
|
|
854
|
+
(!this.options.dot && f.charAt(0) === '.')) {
|
|
855
|
+
return false
|
|
903
856
|
}
|
|
904
|
-
|
|
857
|
+
}
|
|
858
|
+
return partial || sawSome
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
// split body into segments at each GLOBSTAR
|
|
862
|
+
const bodySegments = [[[], 0]];
|
|
863
|
+
let currentBody = bodySegments[0];
|
|
864
|
+
let nonGsParts = 0;
|
|
865
|
+
const nonGsPartsSums = [0];
|
|
866
|
+
for (const b of body) {
|
|
867
|
+
if (b === GLOBSTAR) {
|
|
868
|
+
nonGsPartsSums.push(nonGsParts);
|
|
869
|
+
currentBody = [[], 0];
|
|
870
|
+
bodySegments.push(currentBody);
|
|
871
|
+
} else {
|
|
872
|
+
currentBody[0].push(b);
|
|
873
|
+
nonGsParts++;
|
|
874
|
+
}
|
|
905
875
|
}
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
if (!this.#parent?.isEnd())
|
|
912
|
-
return false;
|
|
913
|
-
if (!this.type)
|
|
914
|
-
return this.#parent?.isEnd();
|
|
915
|
-
// if not root, it'll always have a parent
|
|
916
|
-
/* c8 ignore start */
|
|
917
|
-
const pl = this.#parent ? this.#parent.#parts.length : 0;
|
|
918
|
-
/* c8 ignore stop */
|
|
919
|
-
return this.#parentIndex === pl - 1;
|
|
876
|
+
|
|
877
|
+
let idx = bodySegments.length - 1;
|
|
878
|
+
const fileLength = file.length - fileTailMatch;
|
|
879
|
+
for (const b of bodySegments) {
|
|
880
|
+
b[1] = fileLength - (nonGsPartsSums[idx--] + b[0].length);
|
|
920
881
|
}
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
// outside of a extglob, append until we find a start
|
|
942
|
-
let i = pos;
|
|
943
|
-
let acc = '';
|
|
944
|
-
while (i < str.length) {
|
|
945
|
-
const c = str.charAt(i++);
|
|
946
|
-
// still accumulate escapes at this point, but we do ignore
|
|
947
|
-
// starts that are escaped
|
|
948
|
-
if (escaping || c === '\\') {
|
|
949
|
-
escaping = !escaping;
|
|
950
|
-
acc += c;
|
|
951
|
-
continue;
|
|
952
|
-
}
|
|
953
|
-
if (inBrace) {
|
|
954
|
-
if (i === braceStart + 1) {
|
|
955
|
-
if (c === '^' || c === '!') {
|
|
956
|
-
braceNeg = true;
|
|
957
|
-
}
|
|
958
|
-
}
|
|
959
|
-
else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {
|
|
960
|
-
inBrace = false;
|
|
961
|
-
}
|
|
962
|
-
acc += c;
|
|
963
|
-
continue;
|
|
964
|
-
}
|
|
965
|
-
else if (c === '[') {
|
|
966
|
-
inBrace = true;
|
|
967
|
-
braceStart = i;
|
|
968
|
-
braceNeg = false;
|
|
969
|
-
acc += c;
|
|
970
|
-
continue;
|
|
971
|
-
}
|
|
972
|
-
// we don't have to check for adoption here, because that's
|
|
973
|
-
// done at the other recursion point.
|
|
974
|
-
const doRecurse = !opt.noext &&
|
|
975
|
-
isExtglobType(c) &&
|
|
976
|
-
str.charAt(i) === '(' &&
|
|
977
|
-
extDepth <= maxDepth;
|
|
978
|
-
if (doRecurse) {
|
|
979
|
-
ast.push(acc);
|
|
980
|
-
acc = '';
|
|
981
|
-
const ext = new _a(c, ast);
|
|
982
|
-
i = _a.#parseAST(str, ext, i, opt, extDepth + 1);
|
|
983
|
-
ast.push(ext);
|
|
984
|
-
continue;
|
|
985
|
-
}
|
|
986
|
-
acc += c;
|
|
987
|
-
}
|
|
988
|
-
ast.push(acc);
|
|
989
|
-
return i;
|
|
882
|
+
|
|
883
|
+
return !!this._matchGlobStarBodySections(
|
|
884
|
+
file, bodySegments, fileIndex, 0, partial, 0, !!fileTailMatch
|
|
885
|
+
)
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
// return false for "nope, not matching"
|
|
889
|
+
// return null for "not matching, cannot keep trying"
|
|
890
|
+
_matchGlobStarBodySections (
|
|
891
|
+
file, bodySegments, fileIndex, bodyIndex, partial, globStarDepth, sawTail
|
|
892
|
+
) {
|
|
893
|
+
const bs = bodySegments[bodyIndex];
|
|
894
|
+
if (!bs) {
|
|
895
|
+
// just make sure there are no bad dots
|
|
896
|
+
for (let i = fileIndex; i < file.length; i++) {
|
|
897
|
+
sawTail = true;
|
|
898
|
+
const f = file[i];
|
|
899
|
+
if (f === '.' || f === '..' ||
|
|
900
|
+
(!this.options.dot && f.charAt(0) === '.')) {
|
|
901
|
+
return false
|
|
990
902
|
}
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
}
|
|
1015
|
-
acc += c;
|
|
1016
|
-
continue;
|
|
1017
|
-
}
|
|
1018
|
-
else if (c === '[') {
|
|
1019
|
-
inBrace = true;
|
|
1020
|
-
braceStart = i;
|
|
1021
|
-
braceNeg = false;
|
|
1022
|
-
acc += c;
|
|
1023
|
-
continue;
|
|
1024
|
-
}
|
|
1025
|
-
const doRecurse = !opt.noext &&
|
|
1026
|
-
isExtglobType(c) &&
|
|
1027
|
-
str.charAt(i) === '(' &&
|
|
1028
|
-
/* c8 ignore start - the maxDepth is sufficient here */
|
|
1029
|
-
(extDepth <= maxDepth || (ast && ast.#canAdoptType(c)));
|
|
1030
|
-
/* c8 ignore stop */
|
|
1031
|
-
if (doRecurse) {
|
|
1032
|
-
const depthAdd = ast && ast.#canAdoptType(c) ? 0 : 1;
|
|
1033
|
-
part.push(acc);
|
|
1034
|
-
acc = '';
|
|
1035
|
-
const ext = new _a(c, part);
|
|
1036
|
-
part.push(ext);
|
|
1037
|
-
i = _a.#parseAST(str, ext, i, opt, extDepth + depthAdd);
|
|
1038
|
-
continue;
|
|
1039
|
-
}
|
|
1040
|
-
if (c === '|') {
|
|
1041
|
-
part.push(acc);
|
|
1042
|
-
acc = '';
|
|
1043
|
-
parts.push(part);
|
|
1044
|
-
part = new _a(null, ast);
|
|
1045
|
-
continue;
|
|
1046
|
-
}
|
|
1047
|
-
if (c === ')') {
|
|
1048
|
-
if (acc === '' && ast.#parts.length === 0) {
|
|
1049
|
-
ast.#emptyExt = true;
|
|
1050
|
-
}
|
|
1051
|
-
part.push(acc);
|
|
1052
|
-
acc = '';
|
|
1053
|
-
ast.push(...parts, part);
|
|
1054
|
-
return i;
|
|
1055
|
-
}
|
|
1056
|
-
acc += c;
|
|
1057
|
-
}
|
|
1058
|
-
// unfinished extglob
|
|
1059
|
-
// if we got here, it was a malformed extglob! not an extglob, but
|
|
1060
|
-
// maybe something else in there.
|
|
1061
|
-
ast.type = null;
|
|
1062
|
-
ast.#hasMagic = undefined;
|
|
1063
|
-
ast.#parts = [str.substring(pos - 1)];
|
|
1064
|
-
return i;
|
|
1065
|
-
}
|
|
1066
|
-
#canAdoptWithSpace(child) {
|
|
1067
|
-
return this.#canAdopt(child, adoptionWithSpaceMap);
|
|
1068
|
-
}
|
|
1069
|
-
#canAdopt(child, map = adoptionMap) {
|
|
1070
|
-
if (!child ||
|
|
1071
|
-
typeof child !== 'object' ||
|
|
1072
|
-
child.type !== null ||
|
|
1073
|
-
child.#parts.length !== 1 ||
|
|
1074
|
-
this.type === null) {
|
|
1075
|
-
return false;
|
|
903
|
+
}
|
|
904
|
+
return sawTail
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
const [body, after] = bs;
|
|
908
|
+
while (fileIndex <= after) {
|
|
909
|
+
const m = this._matchOne(
|
|
910
|
+
file.slice(0, fileIndex + body.length),
|
|
911
|
+
body,
|
|
912
|
+
partial,
|
|
913
|
+
fileIndex,
|
|
914
|
+
0
|
|
915
|
+
);
|
|
916
|
+
// if limit exceeded, no match. intentional false negative,
|
|
917
|
+
// acceptable break in correctness for security.
|
|
918
|
+
if (m && globStarDepth < this.maxGlobstarRecursion) {
|
|
919
|
+
const sub = this._matchGlobStarBodySections(
|
|
920
|
+
file, bodySegments,
|
|
921
|
+
fileIndex + body.length, bodyIndex + 1,
|
|
922
|
+
partial, globStarDepth + 1, sawTail
|
|
923
|
+
);
|
|
924
|
+
if (sub !== false) {
|
|
925
|
+
return sub
|
|
1076
926
|
}
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
927
|
+
}
|
|
928
|
+
const f = file[fileIndex];
|
|
929
|
+
if (f === '.' || f === '..' ||
|
|
930
|
+
(!this.options.dot && f.charAt(0) === '.')) {
|
|
931
|
+
return false
|
|
932
|
+
}
|
|
933
|
+
fileIndex++;
|
|
934
|
+
}
|
|
935
|
+
return partial || null
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
_matchOne (file, pattern, partial, fileIndex, patternIndex) {
|
|
939
|
+
let fi, pi, fl, pl;
|
|
940
|
+
for (
|
|
941
|
+
fi = fileIndex, pi = patternIndex, fl = file.length, pl = pattern.length
|
|
942
|
+
; (fi < fl) && (pi < pl)
|
|
943
|
+
; fi++, pi++
|
|
944
|
+
) {
|
|
945
|
+
this.debug('matchOne loop');
|
|
946
|
+
const p = pattern[pi];
|
|
947
|
+
const f = file[fi];
|
|
948
|
+
|
|
949
|
+
this.debug(pattern, p, f);
|
|
950
|
+
|
|
951
|
+
// should be impossible.
|
|
952
|
+
// some invalid regexp stuff in the set.
|
|
953
|
+
/* istanbul ignore if */
|
|
954
|
+
if (p === false || p === GLOBSTAR) return false
|
|
955
|
+
|
|
956
|
+
// something other than **
|
|
957
|
+
// non-magic patterns just have to match exactly
|
|
958
|
+
// patterns with magic have been turned into regexps.
|
|
959
|
+
let hit;
|
|
960
|
+
if (typeof p === 'string') {
|
|
961
|
+
hit = f === p;
|
|
962
|
+
this.debug('string match', p, f, hit);
|
|
963
|
+
} else {
|
|
964
|
+
hit = f.match(p);
|
|
965
|
+
this.debug('pattern match', p, f, hit);
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
if (!hit) return false
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
// now either we fell off the end of the pattern, or we're done.
|
|
972
|
+
if (fi === fl && pi === pl) {
|
|
973
|
+
// ran out of pattern and filename at the same time.
|
|
974
|
+
// an exact hit!
|
|
975
|
+
return true
|
|
976
|
+
} else if (fi === fl) {
|
|
977
|
+
// ran out of file, but still had pattern left.
|
|
978
|
+
// this is ok if we're doing the match as part of
|
|
979
|
+
// a glob fs traversal.
|
|
980
|
+
return partial
|
|
981
|
+
} else /* istanbul ignore else */ if (pi === pl) {
|
|
982
|
+
// ran out of pattern, still have file left.
|
|
983
|
+
// this is only acceptable if we're on the very last
|
|
984
|
+
// empty segment of a file with a trailing slash.
|
|
985
|
+
// a/* should match a/b/
|
|
986
|
+
return (fi === fl - 1) && (file[fi] === '')
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
// should be unreachable.
|
|
990
|
+
/* istanbul ignore next */
|
|
991
|
+
throw new Error('wtf?')
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
braceExpand () {
|
|
995
|
+
return braceExpand(this.pattern, this.options)
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
parse (pattern, isSub) {
|
|
999
|
+
assertValidPattern(pattern);
|
|
1000
|
+
|
|
1001
|
+
const options = this.options;
|
|
1002
|
+
|
|
1003
|
+
// shortcuts
|
|
1004
|
+
if (pattern === '**') {
|
|
1005
|
+
if (!options.noglobstar)
|
|
1006
|
+
return GLOBSTAR
|
|
1007
|
+
else
|
|
1008
|
+
pattern = '*';
|
|
1009
|
+
}
|
|
1010
|
+
if (pattern === '') return ''
|
|
1011
|
+
|
|
1012
|
+
let re = '';
|
|
1013
|
+
let hasMagic = false;
|
|
1014
|
+
let escaping = false;
|
|
1015
|
+
// ? => one single character
|
|
1016
|
+
const patternListStack = [];
|
|
1017
|
+
const negativeLists = [];
|
|
1018
|
+
let stateChar;
|
|
1019
|
+
let inClass = false;
|
|
1020
|
+
let reClassStart = -1;
|
|
1021
|
+
let classStart = -1;
|
|
1022
|
+
let cs;
|
|
1023
|
+
let pl;
|
|
1024
|
+
let sp;
|
|
1025
|
+
// . and .. never match anything that doesn't start with .,
|
|
1026
|
+
// even when options.dot is set. However, if the pattern
|
|
1027
|
+
// starts with ., then traversal patterns can match.
|
|
1028
|
+
let dotTravAllowed = pattern.charAt(0) === '.';
|
|
1029
|
+
let dotFileAllowed = options.dot || dotTravAllowed;
|
|
1030
|
+
const patternStart = () =>
|
|
1031
|
+
dotTravAllowed
|
|
1032
|
+
? ''
|
|
1033
|
+
: dotFileAllowed
|
|
1034
|
+
? '(?!(?:^|\\/)\\.{1,2}(?:$|\\/))'
|
|
1035
|
+
: '(?!\\.)';
|
|
1036
|
+
const subPatternStart = (p) =>
|
|
1037
|
+
p.charAt(0) === '.'
|
|
1038
|
+
? ''
|
|
1039
|
+
: options.dot
|
|
1040
|
+
? '(?!(?:^|\\/)\\.{1,2}(?:$|\\/))'
|
|
1041
|
+
: '(?!\\.)';
|
|
1042
|
+
|
|
1043
|
+
|
|
1044
|
+
const clearStateChar = () => {
|
|
1045
|
+
if (stateChar) {
|
|
1046
|
+
// we had some state-tracking character
|
|
1047
|
+
// that wasn't consumed by this pass.
|
|
1048
|
+
switch (stateChar) {
|
|
1049
|
+
case '*':
|
|
1050
|
+
re += star;
|
|
1051
|
+
hasMagic = true;
|
|
1052
|
+
break
|
|
1053
|
+
case '?':
|
|
1054
|
+
re += qmark;
|
|
1055
|
+
hasMagic = true;
|
|
1056
|
+
break
|
|
1057
|
+
default:
|
|
1058
|
+
re += '\\' + stateChar;
|
|
1059
|
+
break
|
|
1080
1060
|
}
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
const gc = child.#parts[0];
|
|
1095
|
-
this.#parts.splice(index, 1, ...gc.#parts);
|
|
1096
|
-
for (const p of gc.#parts) {
|
|
1097
|
-
if (typeof p === 'object')
|
|
1098
|
-
p.#parent = this;
|
|
1099
|
-
}
|
|
1100
|
-
this.#toString = undefined;
|
|
1101
|
-
}
|
|
1102
|
-
#canUsurpType(c) {
|
|
1103
|
-
const m = usurpMap.get(this.type);
|
|
1104
|
-
return !!m?.has(c);
|
|
1105
|
-
}
|
|
1106
|
-
#canUsurp(child) {
|
|
1107
|
-
if (!child ||
|
|
1108
|
-
typeof child !== 'object' ||
|
|
1109
|
-
child.type !== null ||
|
|
1110
|
-
child.#parts.length !== 1 ||
|
|
1111
|
-
this.type === null ||
|
|
1112
|
-
this.#parts.length !== 1) {
|
|
1113
|
-
return false;
|
|
1061
|
+
this.debug('clearStateChar %j %j', stateChar, re);
|
|
1062
|
+
stateChar = false;
|
|
1063
|
+
}
|
|
1064
|
+
};
|
|
1065
|
+
|
|
1066
|
+
for (let i = 0, c; (i < pattern.length) && (c = pattern.charAt(i)); i++) {
|
|
1067
|
+
this.debug('%s\t%s %s %j', pattern, i, re, c);
|
|
1068
|
+
|
|
1069
|
+
// skip over any that are escaped.
|
|
1070
|
+
if (escaping) {
|
|
1071
|
+
/* istanbul ignore next - completely not allowed, even escaped. */
|
|
1072
|
+
if (c === '/') {
|
|
1073
|
+
return false
|
|
1114
1074
|
}
|
|
1115
|
-
|
|
1116
|
-
if (
|
|
1117
|
-
|
|
1075
|
+
|
|
1076
|
+
if (reSpecials[c]) {
|
|
1077
|
+
re += '\\';
|
|
1118
1078
|
}
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
/*
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
this.#parts = gc.#parts;
|
|
1130
|
-
for (const p of this.#parts) {
|
|
1131
|
-
if (typeof p === 'object') {
|
|
1132
|
-
p.#parent = this;
|
|
1133
|
-
}
|
|
1079
|
+
re += c;
|
|
1080
|
+
escaping = false;
|
|
1081
|
+
continue
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
switch (c) {
|
|
1085
|
+
/* istanbul ignore next */
|
|
1086
|
+
case '/': {
|
|
1087
|
+
// Should already be path-split by now.
|
|
1088
|
+
return false
|
|
1134
1089
|
}
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1090
|
+
|
|
1091
|
+
case '\\':
|
|
1092
|
+
if (inClass && pattern.charAt(i + 1) === '-') {
|
|
1093
|
+
re += c;
|
|
1094
|
+
continue
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
clearStateChar();
|
|
1098
|
+
escaping = true;
|
|
1099
|
+
continue
|
|
1100
|
+
|
|
1101
|
+
// the various stateChar values
|
|
1102
|
+
// for the "extglob" stuff.
|
|
1103
|
+
case '?':
|
|
1104
|
+
case '*':
|
|
1105
|
+
case '+':
|
|
1106
|
+
case '@':
|
|
1107
|
+
case '!':
|
|
1108
|
+
this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c);
|
|
1109
|
+
|
|
1110
|
+
// all of those are literals inside a class, except that
|
|
1111
|
+
// the glob [!a] means [^a] in regexp
|
|
1112
|
+
if (inClass) {
|
|
1113
|
+
this.debug(' in class');
|
|
1114
|
+
if (c === '!' && i === classStart + 1) c = '^';
|
|
1115
|
+
re += c;
|
|
1116
|
+
continue
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
// coalesce consecutive non-globstar * characters
|
|
1120
|
+
if (c === '*' && stateChar === '*') continue
|
|
1121
|
+
|
|
1122
|
+
// if we already have a stateChar, then it means
|
|
1123
|
+
// that there was something like ** or +? in there.
|
|
1124
|
+
// Handle the stateChar, then proceed with this one.
|
|
1125
|
+
this.debug('call clearStateChar %j', stateChar);
|
|
1126
|
+
clearStateChar();
|
|
1127
|
+
stateChar = c;
|
|
1128
|
+
// if extglob is disabled, then +(asdf|foo) isn't a thing.
|
|
1129
|
+
// just clear the statechar *now*, rather than even diving into
|
|
1130
|
+
// the patternList stuff.
|
|
1131
|
+
if (options.noext) clearStateChar();
|
|
1132
|
+
continue
|
|
1133
|
+
|
|
1134
|
+
case '(': {
|
|
1135
|
+
if (inClass) {
|
|
1136
|
+
re += '(';
|
|
1137
|
+
continue
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
if (!stateChar) {
|
|
1141
|
+
re += '\\(';
|
|
1142
|
+
continue
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
const plEntry = {
|
|
1146
|
+
type: stateChar,
|
|
1147
|
+
start: i - 1,
|
|
1148
|
+
reStart: re.length,
|
|
1149
|
+
open: plTypes[stateChar].open,
|
|
1150
|
+
close: plTypes[stateChar].close,
|
|
1151
|
+
};
|
|
1152
|
+
this.debug(this.pattern, '\t', plEntry);
|
|
1153
|
+
patternListStack.push(plEntry);
|
|
1154
|
+
// negation is (?:(?!(?:js)(?:<rest>))[^/]*)
|
|
1155
|
+
re += plEntry.open;
|
|
1156
|
+
// next entry starts with a dot maybe?
|
|
1157
|
+
if (plEntry.start === 0 && plEntry.type !== '!') {
|
|
1158
|
+
dotTravAllowed = true;
|
|
1159
|
+
re += subPatternStart(pattern.slice(i + 1));
|
|
1160
|
+
}
|
|
1161
|
+
this.debug('plType %j %j', stateChar, re);
|
|
1162
|
+
stateChar = false;
|
|
1163
|
+
continue
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
case ')': {
|
|
1167
|
+
const plEntry = patternListStack[patternListStack.length - 1];
|
|
1168
|
+
if (inClass || !plEntry) {
|
|
1169
|
+
re += '\\)';
|
|
1170
|
+
continue
|
|
1171
|
+
}
|
|
1172
|
+
patternListStack.pop();
|
|
1173
|
+
|
|
1174
|
+
// closing an extglob
|
|
1175
|
+
clearStateChar();
|
|
1176
|
+
hasMagic = true;
|
|
1177
|
+
pl = plEntry;
|
|
1178
|
+
// negation is (?:(?!js)[^/]*)
|
|
1179
|
+
// The others are (?:<pattern>)<type>
|
|
1180
|
+
re += pl.close;
|
|
1181
|
+
if (pl.type === '!') {
|
|
1182
|
+
negativeLists.push(Object.assign(pl, { reEnd: re.length }));
|
|
1183
|
+
}
|
|
1184
|
+
continue
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
case '|': {
|
|
1188
|
+
const plEntry = patternListStack[patternListStack.length - 1];
|
|
1189
|
+
if (inClass || !plEntry) {
|
|
1190
|
+
re += '\\|';
|
|
1191
|
+
continue
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
clearStateChar();
|
|
1195
|
+
re += '|';
|
|
1196
|
+
// next subpattern can start with a dot?
|
|
1197
|
+
if (plEntry.start === 0 && plEntry.type !== '!') {
|
|
1198
|
+
dotTravAllowed = true;
|
|
1199
|
+
re += subPatternStart(pattern.slice(i + 1));
|
|
1200
|
+
}
|
|
1201
|
+
continue
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
// these are mostly the same in regexp and glob
|
|
1205
|
+
case '[':
|
|
1206
|
+
// swallow any state-tracking char before the [
|
|
1207
|
+
clearStateChar();
|
|
1208
|
+
|
|
1209
|
+
if (inClass) {
|
|
1210
|
+
re += '\\' + c;
|
|
1211
|
+
continue
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
inClass = true;
|
|
1215
|
+
classStart = i;
|
|
1216
|
+
reClassStart = re.length;
|
|
1217
|
+
re += c;
|
|
1218
|
+
continue
|
|
1219
|
+
|
|
1220
|
+
case ']':
|
|
1221
|
+
// a right bracket shall lose its special
|
|
1222
|
+
// meaning and represent itself in
|
|
1223
|
+
// a bracket expression if it occurs
|
|
1224
|
+
// first in the list. -- POSIX.2 2.8.3.2
|
|
1225
|
+
if (i === classStart + 1 || !inClass) {
|
|
1226
|
+
re += '\\' + c;
|
|
1227
|
+
continue
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
// split where the last [ was, make sure we don't have
|
|
1231
|
+
// an invalid re. if so, re-walk the contents of the
|
|
1232
|
+
// would-be class to re-translate any characters that
|
|
1233
|
+
// were passed through as-is
|
|
1234
|
+
// TODO: It would probably be faster to determine this
|
|
1235
|
+
// without a try/catch and a new RegExp, but it's tricky
|
|
1236
|
+
// to do safely. For now, this is safe and works.
|
|
1237
|
+
cs = pattern.substring(classStart + 1, i);
|
|
1238
|
+
try {
|
|
1239
|
+
RegExp('[' + braExpEscape(charUnescape(cs)) + ']');
|
|
1240
|
+
// looks good, finish up the class.
|
|
1241
|
+
re += c;
|
|
1242
|
+
} catch (er) {
|
|
1243
|
+
// out of order ranges in JS are errors, but in glob syntax,
|
|
1244
|
+
// they're just a range that matches nothing.
|
|
1245
|
+
re = re.substring(0, reClassStart) + '(?:$.)'; // match nothing ever
|
|
1246
|
+
}
|
|
1247
|
+
hasMagic = true;
|
|
1248
|
+
inClass = false;
|
|
1249
|
+
continue
|
|
1250
|
+
|
|
1251
|
+
default:
|
|
1252
|
+
// swallow any state char that wasn't consumed
|
|
1253
|
+
clearStateChar();
|
|
1254
|
+
|
|
1255
|
+
if (reSpecials[c] && !(c === '^' && inClass)) {
|
|
1256
|
+
re += '\\';
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
re += c;
|
|
1260
|
+
break
|
|
1261
|
+
|
|
1262
|
+
} // switch
|
|
1263
|
+
} // for
|
|
1264
|
+
|
|
1265
|
+
// handle the case where we left a class open.
|
|
1266
|
+
// "[abc" is valid, equivalent to "\[abc"
|
|
1267
|
+
if (inClass) {
|
|
1268
|
+
// split where the last [ was, and escape it
|
|
1269
|
+
// this is a huge pita. We now have to re-walk
|
|
1270
|
+
// the contents of the would-be class to re-translate
|
|
1271
|
+
// any characters that were passed through as-is
|
|
1272
|
+
cs = pattern.slice(classStart + 1);
|
|
1273
|
+
sp = this.parse(cs, SUBPARSE);
|
|
1274
|
+
re = re.substring(0, reClassStart) + '\\[' + sp[0];
|
|
1275
|
+
hasMagic = hasMagic || sp[1];
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
// handle the case where we had a +( thing at the *end*
|
|
1279
|
+
// of the pattern.
|
|
1280
|
+
// each pattern list stack adds 3 chars, and we need to go through
|
|
1281
|
+
// and escape any | chars that were passed through as-is for the regexp.
|
|
1282
|
+
// Go through and escape them, taking care not to double-escape any
|
|
1283
|
+
// | chars that were already escaped.
|
|
1284
|
+
for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
|
|
1285
|
+
let tail;
|
|
1286
|
+
tail = re.slice(pl.reStart + pl.open.length);
|
|
1287
|
+
this.debug('setting tail', re, pl);
|
|
1288
|
+
// maybe some even number of \, then maybe 1 \, followed by a |
|
|
1289
|
+
tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, (_, $1, $2) => {
|
|
1290
|
+
/* istanbul ignore else - should already be done */
|
|
1291
|
+
if (!$2) {
|
|
1292
|
+
// the | isn't already escaped, so escape it.
|
|
1293
|
+
$2 = '\\';
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
// need to escape all those slashes *again*, without escaping the
|
|
1297
|
+
// one that we need for escaping the | character. As it works out,
|
|
1298
|
+
// escaping an even number of slashes can be done by simply repeating
|
|
1299
|
+
// it exactly after itself. That's why this trick works.
|
|
1300
|
+
//
|
|
1301
|
+
// I am sorry that you have to see this.
|
|
1302
|
+
return $1 + $1 + $2 + '|'
|
|
1303
|
+
});
|
|
1304
|
+
|
|
1305
|
+
this.debug('tail=%j\n %s', tail, tail, pl, re);
|
|
1306
|
+
const t = pl.type === '*' ? star
|
|
1307
|
+
: pl.type === '?' ? qmark
|
|
1308
|
+
: '\\' + pl.type;
|
|
1309
|
+
|
|
1310
|
+
hasMagic = true;
|
|
1311
|
+
re = re.slice(0, pl.reStart) + t + '\\(' + tail;
|
|
1143
1312
|
}
|
|
1144
|
-
|
|
1145
|
-
//
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
return this.#root.toMMPattern();
|
|
1151
|
-
/* c8 ignore stop */
|
|
1152
|
-
const glob = this.toString();
|
|
1153
|
-
const [re, body, hasMagic, uflag] = this.toRegExpSource();
|
|
1154
|
-
// if we're in nocase mode, and not nocaseMagicOnly, then we do
|
|
1155
|
-
// still need a regular expression if we have to case-insensitively
|
|
1156
|
-
// match capital/lowercase characters.
|
|
1157
|
-
const anyMagic = hasMagic ||
|
|
1158
|
-
this.#hasMagic ||
|
|
1159
|
-
(this.#options.nocase &&
|
|
1160
|
-
!this.#options.nocaseMagicOnly &&
|
|
1161
|
-
glob.toUpperCase() !== glob.toLowerCase());
|
|
1162
|
-
if (!anyMagic) {
|
|
1163
|
-
return body;
|
|
1164
|
-
}
|
|
1165
|
-
const flags = (this.#options.nocase ? 'i' : '') + (uflag ? 'u' : '');
|
|
1166
|
-
return Object.assign(new RegExp(`^${re}$`, flags), {
|
|
1167
|
-
_src: re,
|
|
1168
|
-
_glob: glob,
|
|
1169
|
-
});
|
|
1313
|
+
|
|
1314
|
+
// handle trailing things that only matter at the very end.
|
|
1315
|
+
clearStateChar();
|
|
1316
|
+
if (escaping) {
|
|
1317
|
+
// trailing \\
|
|
1318
|
+
re += '\\\\';
|
|
1170
1319
|
}
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
//
|
|
1177
|
-
//
|
|
1178
|
-
//
|
|
1179
|
-
//
|
|
1180
|
-
// (where we bind to (^|/), or a standalone matchPart context (where
|
|
1181
|
-
// we bind to ^, and not /). Otherwise slashes get duped!
|
|
1182
|
-
//
|
|
1183
|
-
// In part-matching mode, the start is:
|
|
1184
|
-
// - if not isStart: nothing
|
|
1185
|
-
// - if traversal possible, but not allowed: ^(?!\.\.?$)
|
|
1186
|
-
// - if dots allowed or not possible: ^
|
|
1187
|
-
// - if dots possible and not allowed: ^(?!\.)
|
|
1188
|
-
// end is:
|
|
1189
|
-
// - if not isEnd(): nothing
|
|
1190
|
-
// - else: $
|
|
1191
|
-
//
|
|
1192
|
-
// In full-path matching mode, we put the slash at the START of the
|
|
1193
|
-
// pattern, so start is:
|
|
1194
|
-
// - if first pattern: same as part-matching mode
|
|
1195
|
-
// - if not isStart(): nothing
|
|
1196
|
-
// - if traversal possible, but not allowed: /(?!\.\.?(?:$|/))
|
|
1197
|
-
// - if dots allowed or not possible: /
|
|
1198
|
-
// - if dots possible and not allowed: /(?!\.)
|
|
1199
|
-
// end is:
|
|
1200
|
-
// - if last pattern, same as part-matching mode
|
|
1201
|
-
// - else nothing
|
|
1202
|
-
//
|
|
1203
|
-
// Always put the (?:$|/) on negated tails, though, because that has to be
|
|
1204
|
-
// there to bind the end of the negated pattern portion, and it's easier to
|
|
1205
|
-
// just stick it in now rather than try to inject it later in the middle of
|
|
1320
|
+
|
|
1321
|
+
// only need to apply the nodot start if the re starts with
|
|
1322
|
+
// something that could conceivably capture a dot
|
|
1323
|
+
const addPatternStart = addPatternStartSet[re.charAt(0)];
|
|
1324
|
+
|
|
1325
|
+
// Hack to work around lack of negative lookbehind in JS
|
|
1326
|
+
// A pattern like: *.!(x).!(y|z) needs to ensure that a name
|
|
1327
|
+
// like 'a.xyz.yz' doesn't match. So, the first negative
|
|
1328
|
+
// lookahead, has to look ALL the way ahead, to the end of
|
|
1206
1329
|
// the pattern.
|
|
1330
|
+
for (let n = negativeLists.length - 1; n > -1; n--) {
|
|
1331
|
+
const nl = negativeLists[n];
|
|
1332
|
+
|
|
1333
|
+
const nlBefore = re.slice(0, nl.reStart);
|
|
1334
|
+
const nlFirst = re.slice(nl.reStart, nl.reEnd - 8);
|
|
1335
|
+
let nlAfter = re.slice(nl.reEnd);
|
|
1336
|
+
const nlLast = re.slice(nl.reEnd - 8, nl.reEnd) + nlAfter;
|
|
1337
|
+
|
|
1338
|
+
// Handle nested stuff like *(*.js|!(*.json)), where open parens
|
|
1339
|
+
// mean that we should *not* include the ) in the bit that is considered
|
|
1340
|
+
// "after" the negated section.
|
|
1341
|
+
const closeParensBefore = nlBefore.split(')').length;
|
|
1342
|
+
const openParensBefore = nlBefore.split('(').length - closeParensBefore;
|
|
1343
|
+
let cleanAfter = nlAfter;
|
|
1344
|
+
for (let i = 0; i < openParensBefore; i++) {
|
|
1345
|
+
cleanAfter = cleanAfter.replace(/\)[+*?]?/, '');
|
|
1346
|
+
}
|
|
1347
|
+
nlAfter = cleanAfter;
|
|
1348
|
+
|
|
1349
|
+
const dollar = nlAfter === '' && isSub !== SUBPARSE ? '(?:$|\\/)' : '';
|
|
1350
|
+
|
|
1351
|
+
re = nlBefore + nlFirst + nlAfter + dollar + nlLast;
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
// if the re is not "" at this point, then we need to make sure
|
|
1355
|
+
// it doesn't match against an empty path part.
|
|
1356
|
+
// Otherwise a/* will match a/, which it should not.
|
|
1357
|
+
if (re !== '' && hasMagic) {
|
|
1358
|
+
re = '(?=.)' + re;
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
if (addPatternStart) {
|
|
1362
|
+
re = patternStart() + re;
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
// parsing just a piece of a larger pattern.
|
|
1366
|
+
if (isSub === SUBPARSE) {
|
|
1367
|
+
return [re, hasMagic]
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
// if it's nocase, and the lcase/uppercase don't match, it's magic
|
|
1371
|
+
if (options.nocase && !hasMagic) {
|
|
1372
|
+
hasMagic = pattern.toUpperCase() !== pattern.toLowerCase();
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
// skip the regexp for non-magical patterns
|
|
1376
|
+
// unescape anything in it, though, so that it'll be
|
|
1377
|
+
// an exact match against a file etc.
|
|
1378
|
+
if (!hasMagic) {
|
|
1379
|
+
return globUnescape(pattern)
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
const flags = options.nocase ? 'i' : '';
|
|
1383
|
+
try {
|
|
1384
|
+
return Object.assign(new RegExp('^' + re + '$', flags), {
|
|
1385
|
+
_glob: pattern,
|
|
1386
|
+
_src: re,
|
|
1387
|
+
})
|
|
1388
|
+
} catch (er) /* istanbul ignore next - should be impossible */ {
|
|
1389
|
+
// If it was an invalid regular expression, then it can't match
|
|
1390
|
+
// anything. This trick looks for a character after the end of
|
|
1391
|
+
// the string, which is of course impossible, except in multi-line
|
|
1392
|
+
// mode, but it's not a /m regex.
|
|
1393
|
+
return new RegExp('$.')
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
makeRe () {
|
|
1398
|
+
if (this.regexp || this.regexp === false) return this.regexp
|
|
1399
|
+
|
|
1400
|
+
// at this point, this.set is a 2d array of partial
|
|
1401
|
+
// pattern strings, or "**".
|
|
1207
1402
|
//
|
|
1208
|
-
//
|
|
1209
|
-
//
|
|
1210
|
-
//
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
//
|
|
1225
|
-
//
|
|
1226
|
-
//
|
|
1227
|
-
//
|
|
1228
|
-
//
|
|
1229
|
-
//
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
if (
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
_a.#parseGlob(p, this.#hasMagic, noEmpty)
|
|
1257
|
-
: p.toRegExpSource(allowDot);
|
|
1258
|
-
this.#hasMagic = this.#hasMagic || hasMagic;
|
|
1259
|
-
this.#uflag = this.#uflag || uflag;
|
|
1260
|
-
return re;
|
|
1261
|
-
})
|
|
1262
|
-
.join('');
|
|
1263
|
-
let start = '';
|
|
1264
|
-
if (this.isStart()) {
|
|
1265
|
-
if (typeof this.#parts[0] === 'string') {
|
|
1266
|
-
// this is the string that will match the start of the pattern,
|
|
1267
|
-
// so we need to protect against dots and such.
|
|
1268
|
-
// '.' and '..' cannot match unless the pattern is that exactly,
|
|
1269
|
-
// even if it starts with . or dot:true is set.
|
|
1270
|
-
const dotTravAllowed = this.#parts.length === 1 && justDots.has(this.#parts[0]);
|
|
1271
|
-
if (!dotTravAllowed) {
|
|
1272
|
-
const aps = addPatternStart;
|
|
1273
|
-
// check if we have a possibility of matching . or ..,
|
|
1274
|
-
// and prevent that.
|
|
1275
|
-
const needNoTrav =
|
|
1276
|
-
// dots are allowed, and the pattern starts with [ or .
|
|
1277
|
-
(dot && aps.has(src.charAt(0))) ||
|
|
1278
|
-
// the pattern starts with \., and then [ or .
|
|
1279
|
-
(src.startsWith('\\.') && aps.has(src.charAt(2))) ||
|
|
1280
|
-
// the pattern starts with \.\., and then [ or .
|
|
1281
|
-
(src.startsWith('\\.\\.') && aps.has(src.charAt(4)));
|
|
1282
|
-
// no need to prevent dots if it can't match a dot, or if a
|
|
1283
|
-
// sub-pattern will be preventing it anyway.
|
|
1284
|
-
const needNoDot = !dot && !allowDot && aps.has(src.charAt(0));
|
|
1285
|
-
start =
|
|
1286
|
-
needNoTrav ? startNoTraversal
|
|
1287
|
-
: needNoDot ? startNoDot
|
|
1288
|
-
: '';
|
|
1289
|
-
}
|
|
1290
|
-
}
|
|
1291
|
-
}
|
|
1292
|
-
// append the "end of path portion" pattern to negation tails
|
|
1293
|
-
let end = '';
|
|
1294
|
-
if (this.isEnd() &&
|
|
1295
|
-
this.#root.#filledNegs &&
|
|
1296
|
-
this.#parent?.type === '!') {
|
|
1297
|
-
end = '(?:$|\\/)';
|
|
1298
|
-
}
|
|
1299
|
-
const final = start + src + end;
|
|
1300
|
-
return [
|
|
1301
|
-
final,
|
|
1302
|
-
(0, unescape_js_1.unescape)(src),
|
|
1303
|
-
(this.#hasMagic = !!this.#hasMagic),
|
|
1304
|
-
this.#uflag,
|
|
1305
|
-
];
|
|
1306
|
-
}
|
|
1307
|
-
// We need to calculate the body *twice* if it's a repeat pattern
|
|
1308
|
-
// at the start, once in nodot mode, then again in dot mode, so a
|
|
1309
|
-
// pattern like *(?) can match 'x.y'
|
|
1310
|
-
const repeated = this.type === '*' || this.type === '+';
|
|
1311
|
-
// some kind of extglob
|
|
1312
|
-
const start = this.type === '!' ? '(?:(?!(?:' : '(?:';
|
|
1313
|
-
let body = this.#partsToRegExp(dot);
|
|
1314
|
-
if (this.isStart() && this.isEnd() && !body && this.type !== '!') {
|
|
1315
|
-
// invalid extglob, has to at least be *something* present, if it's
|
|
1316
|
-
// the entire path portion.
|
|
1317
|
-
const s = this.toString();
|
|
1318
|
-
const me = this;
|
|
1319
|
-
me.#parts = [s];
|
|
1320
|
-
me.type = null;
|
|
1321
|
-
me.#hasMagic = undefined;
|
|
1322
|
-
return [s, (0, unescape_js_1.unescape)(this.toString()), false, false];
|
|
1323
|
-
}
|
|
1324
|
-
let bodyDotAllowed = !repeated || allowDot || dot || !startNoDot ?
|
|
1325
|
-
''
|
|
1326
|
-
: this.#partsToRegExp(true);
|
|
1327
|
-
if (bodyDotAllowed === body) {
|
|
1328
|
-
bodyDotAllowed = '';
|
|
1329
|
-
}
|
|
1330
|
-
if (bodyDotAllowed) {
|
|
1331
|
-
body = `(?:${body})(?:${bodyDotAllowed})*?`;
|
|
1332
|
-
}
|
|
1333
|
-
// an empty !() is exactly equivalent to a starNoEmpty
|
|
1334
|
-
let final = '';
|
|
1335
|
-
if (this.type === '!' && this.#emptyExt) {
|
|
1336
|
-
final = (this.isStart() && !dot ? startNoDot : '') + starNoEmpty;
|
|
1337
|
-
}
|
|
1338
|
-
else {
|
|
1339
|
-
const close = this.type === '!' ?
|
|
1340
|
-
// !() must match something,but !(x) can match ''
|
|
1341
|
-
'))' +
|
|
1342
|
-
(this.isStart() && !dot && !allowDot ? startNoDot : '') +
|
|
1343
|
-
star +
|
|
1344
|
-
')'
|
|
1345
|
-
: this.type === '@' ? ')'
|
|
1346
|
-
: this.type === '?' ? ')?'
|
|
1347
|
-
: this.type === '+' && bodyDotAllowed ? ')'
|
|
1348
|
-
: this.type === '*' && bodyDotAllowed ? `)?`
|
|
1349
|
-
: `)${this.type}`;
|
|
1350
|
-
final = start + body + close;
|
|
1403
|
+
// It's better to use .match(). This function shouldn't
|
|
1404
|
+
// be used, really, but it's pretty convenient sometimes,
|
|
1405
|
+
// when you just want to work with a regex.
|
|
1406
|
+
const set = this.set;
|
|
1407
|
+
|
|
1408
|
+
if (!set.length) {
|
|
1409
|
+
this.regexp = false;
|
|
1410
|
+
return this.regexp
|
|
1411
|
+
}
|
|
1412
|
+
const options = this.options;
|
|
1413
|
+
|
|
1414
|
+
const twoStar = options.noglobstar ? star
|
|
1415
|
+
: options.dot ? twoStarDot
|
|
1416
|
+
: twoStarNoDot;
|
|
1417
|
+
const flags = options.nocase ? 'i' : '';
|
|
1418
|
+
|
|
1419
|
+
// coalesce globstars and regexpify non-globstar patterns
|
|
1420
|
+
// if it's the only item, then we just do one twoStar
|
|
1421
|
+
// if it's the first, and there are more, prepend (\/|twoStar\/)? to next
|
|
1422
|
+
// if it's the last, append (\/twoStar|) to previous
|
|
1423
|
+
// if it's in the middle, append (\/|\/twoStar\/) to previous
|
|
1424
|
+
// then filter out GLOBSTAR symbols
|
|
1425
|
+
let re = set.map(pattern => {
|
|
1426
|
+
pattern = pattern.map(p =>
|
|
1427
|
+
typeof p === 'string' ? regExpEscape(p)
|
|
1428
|
+
: p === GLOBSTAR ? GLOBSTAR
|
|
1429
|
+
: p._src
|
|
1430
|
+
).reduce((set, p) => {
|
|
1431
|
+
if (!(set[set.length - 1] === GLOBSTAR && p === GLOBSTAR)) {
|
|
1432
|
+
set.push(p);
|
|
1433
|
+
}
|
|
1434
|
+
return set
|
|
1435
|
+
}, []);
|
|
1436
|
+
pattern.forEach((p, i) => {
|
|
1437
|
+
if (p !== GLOBSTAR || pattern[i-1] === GLOBSTAR) {
|
|
1438
|
+
return
|
|
1439
|
+
}
|
|
1440
|
+
if (i === 0) {
|
|
1441
|
+
if (pattern.length > 1) {
|
|
1442
|
+
pattern[i+1] = '(?:\\\/|' + twoStar + '\\\/)?' + pattern[i+1];
|
|
1443
|
+
} else {
|
|
1444
|
+
pattern[i] = twoStar;
|
|
1445
|
+
}
|
|
1446
|
+
} else if (i === pattern.length - 1) {
|
|
1447
|
+
pattern[i-1] += '(?:\\\/|' + twoStar + ')?';
|
|
1448
|
+
} else {
|
|
1449
|
+
pattern[i-1] += '(?:\\\/|\\\/' + twoStar + '\\\/)' + pattern[i+1];
|
|
1450
|
+
pattern[i+1] = GLOBSTAR;
|
|
1351
1451
|
}
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1452
|
+
});
|
|
1453
|
+
return pattern.filter(p => p !== GLOBSTAR).join('/')
|
|
1454
|
+
}).join('|');
|
|
1455
|
+
|
|
1456
|
+
// must match entire pattern
|
|
1457
|
+
// ending in a * or ** will make it less strict.
|
|
1458
|
+
re = '^(?:' + re + ')$';
|
|
1459
|
+
|
|
1460
|
+
// can match anything, as long as it's not this.
|
|
1461
|
+
if (this.negate) re = '^(?!' + re + ').*$';
|
|
1462
|
+
|
|
1463
|
+
try {
|
|
1464
|
+
this.regexp = new RegExp(re, flags);
|
|
1465
|
+
} catch (ex) /* istanbul ignore next - should be impossible */ {
|
|
1466
|
+
this.regexp = false;
|
|
1358
1467
|
}
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
c.#flatten();
|
|
1377
|
-
if (this.#canAdopt(c)) {
|
|
1378
|
-
done = false;
|
|
1379
|
-
this.#adopt(c, i);
|
|
1380
|
-
}
|
|
1381
|
-
else if (this.#canAdoptWithSpace(c)) {
|
|
1382
|
-
done = false;
|
|
1383
|
-
this.#adoptWithSpace(c, i);
|
|
1384
|
-
}
|
|
1385
|
-
else if (this.#canUsurp(c)) {
|
|
1386
|
-
done = false;
|
|
1387
|
-
this.#usurp(c);
|
|
1388
|
-
}
|
|
1389
|
-
}
|
|
1390
|
-
}
|
|
1391
|
-
} while (!done && ++iterations < 10);
|
|
1392
|
-
}
|
|
1393
|
-
this.#toString = undefined;
|
|
1394
|
-
}
|
|
1395
|
-
#partsToRegExp(dot) {
|
|
1396
|
-
return this.#parts
|
|
1397
|
-
.map(p => {
|
|
1398
|
-
// extglob ASTs should only contain parent ASTs
|
|
1399
|
-
/* c8 ignore start */
|
|
1400
|
-
if (typeof p === 'string') {
|
|
1401
|
-
throw new Error('string type in extglob ast??');
|
|
1402
|
-
}
|
|
1403
|
-
/* c8 ignore stop */
|
|
1404
|
-
// can ignore hasMagic, because extglobs are already always magic
|
|
1405
|
-
const [re, _, _hasMagic, uflag] = p.toRegExpSource(dot);
|
|
1406
|
-
this.#uflag = this.#uflag || uflag;
|
|
1407
|
-
return re;
|
|
1408
|
-
})
|
|
1409
|
-
.filter(p => !(this.isStart() && this.isEnd()) || !!p)
|
|
1410
|
-
.join('|');
|
|
1411
|
-
}
|
|
1412
|
-
static #parseGlob(glob, hasMagic, noEmpty = false) {
|
|
1413
|
-
let escaping = false;
|
|
1414
|
-
let re = '';
|
|
1415
|
-
let uflag = false;
|
|
1416
|
-
// multiple stars that aren't globstars coalesce into one *
|
|
1417
|
-
let inStar = false;
|
|
1418
|
-
for (let i = 0; i < glob.length; i++) {
|
|
1419
|
-
const c = glob.charAt(i);
|
|
1420
|
-
if (escaping) {
|
|
1421
|
-
escaping = false;
|
|
1422
|
-
re += (reSpecials.has(c) ? '\\' : '') + c;
|
|
1423
|
-
continue;
|
|
1424
|
-
}
|
|
1425
|
-
if (c === '*') {
|
|
1426
|
-
if (inStar)
|
|
1427
|
-
continue;
|
|
1428
|
-
inStar = true;
|
|
1429
|
-
re += noEmpty && /^[*]+$/.test(glob) ? starNoEmpty : star;
|
|
1430
|
-
hasMagic = true;
|
|
1431
|
-
continue;
|
|
1432
|
-
}
|
|
1433
|
-
else {
|
|
1434
|
-
inStar = false;
|
|
1435
|
-
}
|
|
1436
|
-
if (c === '\\') {
|
|
1437
|
-
if (i === glob.length - 1) {
|
|
1438
|
-
re += '\\\\';
|
|
1439
|
-
}
|
|
1440
|
-
else {
|
|
1441
|
-
escaping = true;
|
|
1442
|
-
}
|
|
1443
|
-
continue;
|
|
1444
|
-
}
|
|
1445
|
-
if (c === '[') {
|
|
1446
|
-
const [src, needUflag, consumed, magic] = (0, brace_expressions_js_1.parseClass)(glob, i);
|
|
1447
|
-
if (consumed) {
|
|
1448
|
-
re += src;
|
|
1449
|
-
uflag = uflag || needUflag;
|
|
1450
|
-
i += consumed - 1;
|
|
1451
|
-
hasMagic = hasMagic || magic;
|
|
1452
|
-
continue;
|
|
1453
|
-
}
|
|
1454
|
-
}
|
|
1455
|
-
if (c === '?') {
|
|
1456
|
-
re += qmark;
|
|
1457
|
-
hasMagic = true;
|
|
1458
|
-
continue;
|
|
1459
|
-
}
|
|
1460
|
-
re += regExpEscape(c);
|
|
1461
|
-
}
|
|
1462
|
-
return [re, (0, unescape_js_1.unescape)(glob), !!hasMagic, uflag];
|
|
1468
|
+
return this.regexp
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
match (f, partial = this.partial) {
|
|
1472
|
+
this.debug('match', f, this.pattern);
|
|
1473
|
+
// short-circuit in the case of busted things.
|
|
1474
|
+
// comments, etc.
|
|
1475
|
+
if (this.comment) return false
|
|
1476
|
+
if (this.empty) return f === ''
|
|
1477
|
+
|
|
1478
|
+
if (f === '/' && partial) return true
|
|
1479
|
+
|
|
1480
|
+
const options = this.options;
|
|
1481
|
+
|
|
1482
|
+
// windows: need to use /, not \
|
|
1483
|
+
if (path.sep !== '/') {
|
|
1484
|
+
f = f.split(path.sep).join('/');
|
|
1463
1485
|
}
|
|
1464
|
-
}
|
|
1465
|
-
ast.AST = AST;
|
|
1466
|
-
_a = AST;
|
|
1467
|
-
|
|
1468
|
-
return ast;
|
|
1469
|
-
}
|
|
1470
1486
|
|
|
1471
|
-
|
|
1487
|
+
// treat the test path as a set of pathparts.
|
|
1488
|
+
f = f.split(slashSplit);
|
|
1489
|
+
this.debug(this.pattern, 'split', f);
|
|
1472
1490
|
|
|
1473
|
-
|
|
1491
|
+
// just ONE of the pattern sets in this.set needs to match
|
|
1492
|
+
// in order for it to be valid. If negating, then just one
|
|
1493
|
+
// match means that we have failed.
|
|
1494
|
+
// Either way, return on the first hit.
|
|
1474
1495
|
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
hasRequired_escape = 1;
|
|
1478
|
-
Object.defineProperty(_escape, "__esModule", { value: true });
|
|
1479
|
-
_escape.escape = void 0;
|
|
1480
|
-
/**
|
|
1481
|
-
* Escape all magic characters in a glob pattern.
|
|
1482
|
-
*
|
|
1483
|
-
* If the {@link MinimatchOptions.windowsPathsNoEscape}
|
|
1484
|
-
* option is used, then characters are escaped by wrapping in `[]`, because
|
|
1485
|
-
* a magic character wrapped in a character class can only be satisfied by
|
|
1486
|
-
* that exact character. In this mode, `\` is _not_ escaped, because it is
|
|
1487
|
-
* not interpreted as a magic character, but instead as a path separator.
|
|
1488
|
-
*
|
|
1489
|
-
* If the {@link MinimatchOptions.magicalBraces} option is used,
|
|
1490
|
-
* then braces (`{` and `}`) will be escaped.
|
|
1491
|
-
*/
|
|
1492
|
-
const escape = (s, { windowsPathsNoEscape = false, magicalBraces = false, } = {}) => {
|
|
1493
|
-
// don't need to escape +@! because we escape the parens
|
|
1494
|
-
// that make those magic, and escaping ! as [!] isn't valid,
|
|
1495
|
-
// because [!]] is a valid glob class meaning not ']'.
|
|
1496
|
-
if (magicalBraces) {
|
|
1497
|
-
return windowsPathsNoEscape ?
|
|
1498
|
-
s.replace(/[?*()[\]{}]/g, '[$&]')
|
|
1499
|
-
: s.replace(/[?*()[\]\\{}]/g, '\\$&');
|
|
1500
|
-
}
|
|
1501
|
-
return windowsPathsNoEscape ?
|
|
1502
|
-
s.replace(/[?*()[\]]/g, '[$&]')
|
|
1503
|
-
: s.replace(/[?*()[\]\\]/g, '\\$&');
|
|
1504
|
-
};
|
|
1505
|
-
_escape.escape = escape;
|
|
1506
|
-
|
|
1507
|
-
return _escape;
|
|
1508
|
-
}
|
|
1496
|
+
const set = this.set;
|
|
1497
|
+
this.debug(this.pattern, 'set', set);
|
|
1509
1498
|
|
|
1510
|
-
|
|
1499
|
+
// Find the basename of the path by looking for the last non-empty segment
|
|
1500
|
+
let filename;
|
|
1501
|
+
for (let i = f.length - 1; i >= 0; i--) {
|
|
1502
|
+
filename = f[i];
|
|
1503
|
+
if (filename) break
|
|
1504
|
+
}
|
|
1511
1505
|
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
return (f) => !f.startsWith('.') && f.toLowerCase().endsWith(ext);
|
|
1539
|
-
};
|
|
1540
|
-
const starDotExtTestNocaseDot = (ext) => {
|
|
1541
|
-
ext = ext.toLowerCase();
|
|
1542
|
-
return (f) => f.toLowerCase().endsWith(ext);
|
|
1543
|
-
};
|
|
1544
|
-
const starDotStarRE = /^\*+\.\*+$/;
|
|
1545
|
-
const starDotStarTest = (f) => !f.startsWith('.') && f.includes('.');
|
|
1546
|
-
const starDotStarTestDot = (f) => f !== '.' && f !== '..' && f.includes('.');
|
|
1547
|
-
const dotStarRE = /^\.\*+$/;
|
|
1548
|
-
const dotStarTest = (f) => f !== '.' && f !== '..' && f.startsWith('.');
|
|
1549
|
-
const starRE = /^\*+$/;
|
|
1550
|
-
const starTest = (f) => f.length !== 0 && !f.startsWith('.');
|
|
1551
|
-
const starTestDot = (f) => f.length !== 0 && f !== '.' && f !== '..';
|
|
1552
|
-
const qmarksRE = /^\?+([^+@!?*[(]*)?$/;
|
|
1553
|
-
const qmarksTestNocase = ([$0, ext = '']) => {
|
|
1554
|
-
const noext = qmarksTestNoExt([$0]);
|
|
1555
|
-
if (!ext)
|
|
1556
|
-
return noext;
|
|
1557
|
-
ext = ext.toLowerCase();
|
|
1558
|
-
return (f) => noext(f) && f.toLowerCase().endsWith(ext);
|
|
1559
|
-
};
|
|
1560
|
-
const qmarksTestNocaseDot = ([$0, ext = '']) => {
|
|
1561
|
-
const noext = qmarksTestNoExtDot([$0]);
|
|
1562
|
-
if (!ext)
|
|
1563
|
-
return noext;
|
|
1564
|
-
ext = ext.toLowerCase();
|
|
1565
|
-
return (f) => noext(f) && f.toLowerCase().endsWith(ext);
|
|
1566
|
-
};
|
|
1567
|
-
const qmarksTestDot = ([$0, ext = '']) => {
|
|
1568
|
-
const noext = qmarksTestNoExtDot([$0]);
|
|
1569
|
-
return !ext ? noext : (f) => noext(f) && f.endsWith(ext);
|
|
1570
|
-
};
|
|
1571
|
-
const qmarksTest = ([$0, ext = '']) => {
|
|
1572
|
-
const noext = qmarksTestNoExt([$0]);
|
|
1573
|
-
return !ext ? noext : (f) => noext(f) && f.endsWith(ext);
|
|
1574
|
-
};
|
|
1575
|
-
const qmarksTestNoExt = ([$0]) => {
|
|
1576
|
-
const len = $0.length;
|
|
1577
|
-
return (f) => f.length === len && !f.startsWith('.');
|
|
1578
|
-
};
|
|
1579
|
-
const qmarksTestNoExtDot = ([$0]) => {
|
|
1580
|
-
const len = $0.length;
|
|
1581
|
-
return (f) => f.length === len && f !== '.' && f !== '..';
|
|
1582
|
-
};
|
|
1583
|
-
/* c8 ignore start */
|
|
1584
|
-
const defaultPlatform = (typeof process === 'object' && process ?
|
|
1585
|
-
(typeof process.env === 'object' &&
|
|
1586
|
-
process.env &&
|
|
1587
|
-
process.env.__MINIMATCH_TESTING_PLATFORM__) ||
|
|
1588
|
-
process.platform
|
|
1589
|
-
: 'posix');
|
|
1590
|
-
const path = {
|
|
1591
|
-
win32: { sep: '\\' },
|
|
1592
|
-
posix: { sep: '/' },
|
|
1593
|
-
};
|
|
1594
|
-
/* c8 ignore stop */
|
|
1595
|
-
exports.sep = defaultPlatform === 'win32' ? path.win32.sep : path.posix.sep;
|
|
1596
|
-
exports.minimatch.sep = exports.sep;
|
|
1597
|
-
exports.GLOBSTAR = Symbol('globstar **');
|
|
1598
|
-
exports.minimatch.GLOBSTAR = exports.GLOBSTAR;
|
|
1599
|
-
// any single thing other than /
|
|
1600
|
-
// don't need to escape / when using new RegExp()
|
|
1601
|
-
const qmark = '[^/]';
|
|
1602
|
-
// * => any number of characters
|
|
1603
|
-
const star = qmark + '*?';
|
|
1604
|
-
// ** when dots are allowed. Anything goes, except .. and .
|
|
1605
|
-
// not (^ or / followed by one or two dots followed by $ or /),
|
|
1606
|
-
// followed by anything, any number of times.
|
|
1607
|
-
const twoStarDot = '(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?';
|
|
1608
|
-
// not a ^ or / followed by a dot,
|
|
1609
|
-
// followed by anything, any number of times.
|
|
1610
|
-
const twoStarNoDot = '(?:(?!(?:\\/|^)\\.).)*?';
|
|
1611
|
-
const filter = (pattern, options = {}) => (p) => (0, exports.minimatch)(p, pattern, options);
|
|
1612
|
-
exports.filter = filter;
|
|
1613
|
-
exports.minimatch.filter = exports.filter;
|
|
1614
|
-
const ext = (a, b = {}) => Object.assign({}, a, b);
|
|
1615
|
-
const defaults = (def) => {
|
|
1616
|
-
if (!def || typeof def !== 'object' || !Object.keys(def).length) {
|
|
1617
|
-
return exports.minimatch;
|
|
1618
|
-
}
|
|
1619
|
-
const orig = exports.minimatch;
|
|
1620
|
-
const m = (p, pattern, options = {}) => orig(p, pattern, ext(def, options));
|
|
1621
|
-
return Object.assign(m, {
|
|
1622
|
-
Minimatch: class Minimatch extends orig.Minimatch {
|
|
1623
|
-
constructor(pattern, options = {}) {
|
|
1624
|
-
super(pattern, ext(def, options));
|
|
1625
|
-
}
|
|
1626
|
-
static defaults(options) {
|
|
1627
|
-
return orig.defaults(ext(def, options)).Minimatch;
|
|
1628
|
-
}
|
|
1629
|
-
},
|
|
1630
|
-
AST: class AST extends orig.AST {
|
|
1631
|
-
/* c8 ignore start */
|
|
1632
|
-
constructor(type, parent, options = {}) {
|
|
1633
|
-
super(type, parent, ext(def, options));
|
|
1634
|
-
}
|
|
1635
|
-
/* c8 ignore stop */
|
|
1636
|
-
static fromGlob(pattern, options = {}) {
|
|
1637
|
-
return orig.AST.fromGlob(pattern, ext(def, options));
|
|
1638
|
-
}
|
|
1639
|
-
},
|
|
1640
|
-
unescape: (s, options = {}) => orig.unescape(s, ext(def, options)),
|
|
1641
|
-
escape: (s, options = {}) => orig.escape(s, ext(def, options)),
|
|
1642
|
-
filter: (pattern, options = {}) => orig.filter(pattern, ext(def, options)),
|
|
1643
|
-
defaults: (options) => orig.defaults(ext(def, options)),
|
|
1644
|
-
makeRe: (pattern, options = {}) => orig.makeRe(pattern, ext(def, options)),
|
|
1645
|
-
braceExpand: (pattern, options = {}) => orig.braceExpand(pattern, ext(def, options)),
|
|
1646
|
-
match: (list, pattern, options = {}) => orig.match(list, pattern, ext(def, options)),
|
|
1647
|
-
sep: orig.sep,
|
|
1648
|
-
GLOBSTAR: exports.GLOBSTAR,
|
|
1649
|
-
});
|
|
1650
|
-
};
|
|
1651
|
-
exports.defaults = defaults;
|
|
1652
|
-
exports.minimatch.defaults = exports.defaults;
|
|
1653
|
-
// Brace expansion:
|
|
1654
|
-
// a{b,c}d -> abd acd
|
|
1655
|
-
// a{b,}c -> abc ac
|
|
1656
|
-
// a{0..3}d -> a0d a1d a2d a3d
|
|
1657
|
-
// a{b,c{d,e}f}g -> abg acdfg acefg
|
|
1658
|
-
// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
|
|
1659
|
-
//
|
|
1660
|
-
// Invalid sets are not expanded.
|
|
1661
|
-
// a{2..}b -> a{2..}b
|
|
1662
|
-
// a{b}c -> a{b}c
|
|
1663
|
-
const braceExpand = (pattern, options = {}) => {
|
|
1664
|
-
(0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
|
|
1665
|
-
// Thanks to Yeting Li <https://github.com/yetingli> for
|
|
1666
|
-
// improving this regexp to avoid a ReDOS vulnerability.
|
|
1667
|
-
if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
|
|
1668
|
-
// shortcut. no need to expand.
|
|
1669
|
-
return [pattern];
|
|
1670
|
-
}
|
|
1671
|
-
return (0, brace_expansion_1.expand)(pattern, { max: options.braceExpandMax });
|
|
1672
|
-
};
|
|
1673
|
-
exports.braceExpand = braceExpand;
|
|
1674
|
-
exports.minimatch.braceExpand = exports.braceExpand;
|
|
1675
|
-
// parse a component of the expanded set.
|
|
1676
|
-
// At this point, no pattern may contain "/" in it
|
|
1677
|
-
// so we're going to return a 2d array, where each entry is the full
|
|
1678
|
-
// pattern, split on '/', and then turned into a regular expression.
|
|
1679
|
-
// A regexp is made at the end which joins each array with an
|
|
1680
|
-
// escaped /, and another full one which joins each regexp with |.
|
|
1681
|
-
//
|
|
1682
|
-
// Following the lead of Bash 4.1, note that "**" only has special meaning
|
|
1683
|
-
// when it is the *only* thing in a path portion. Otherwise, any series
|
|
1684
|
-
// of * is equivalent to a single *. Globstar behavior is enabled by
|
|
1685
|
-
// default, and can be disabled by setting options.noglobstar.
|
|
1686
|
-
const makeRe = (pattern, options = {}) => new Minimatch(pattern, options).makeRe();
|
|
1687
|
-
exports.makeRe = makeRe;
|
|
1688
|
-
exports.minimatch.makeRe = exports.makeRe;
|
|
1689
|
-
const match = (list, pattern, options = {}) => {
|
|
1690
|
-
const mm = new Minimatch(pattern, options);
|
|
1691
|
-
list = list.filter(f => mm.match(f));
|
|
1692
|
-
if (mm.options.nonull && !list.length) {
|
|
1693
|
-
list.push(pattern);
|
|
1694
|
-
}
|
|
1695
|
-
return list;
|
|
1696
|
-
};
|
|
1697
|
-
exports.match = match;
|
|
1698
|
-
exports.minimatch.match = exports.match;
|
|
1699
|
-
// replace stuff like \* with *
|
|
1700
|
-
const globMagic = /[?*]|[+@!]\(.*?\)|\[|\]/;
|
|
1701
|
-
const regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
|
1702
|
-
class Minimatch {
|
|
1703
|
-
options;
|
|
1704
|
-
set;
|
|
1705
|
-
pattern;
|
|
1706
|
-
windowsPathsNoEscape;
|
|
1707
|
-
nonegate;
|
|
1708
|
-
negate;
|
|
1709
|
-
comment;
|
|
1710
|
-
empty;
|
|
1711
|
-
preserveMultipleSlashes;
|
|
1712
|
-
partial;
|
|
1713
|
-
globSet;
|
|
1714
|
-
globParts;
|
|
1715
|
-
nocase;
|
|
1716
|
-
isWindows;
|
|
1717
|
-
platform;
|
|
1718
|
-
windowsNoMagicRoot;
|
|
1719
|
-
maxGlobstarRecursion;
|
|
1720
|
-
regexp;
|
|
1721
|
-
constructor(pattern, options = {}) {
|
|
1722
|
-
(0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
|
|
1723
|
-
options = options || {};
|
|
1724
|
-
this.options = options;
|
|
1725
|
-
this.maxGlobstarRecursion = options.maxGlobstarRecursion ?? 200;
|
|
1726
|
-
this.pattern = pattern;
|
|
1727
|
-
this.platform = options.platform || defaultPlatform;
|
|
1728
|
-
this.isWindows = this.platform === 'win32';
|
|
1729
|
-
// avoid the annoying deprecation flag lol
|
|
1730
|
-
const awe = ('allowWindow' + 'sEscape');
|
|
1731
|
-
this.windowsPathsNoEscape =
|
|
1732
|
-
!!options.windowsPathsNoEscape || options[awe] === false;
|
|
1733
|
-
if (this.windowsPathsNoEscape) {
|
|
1734
|
-
this.pattern = this.pattern.replace(/\\/g, '/');
|
|
1735
|
-
}
|
|
1736
|
-
this.preserveMultipleSlashes = !!options.preserveMultipleSlashes;
|
|
1737
|
-
this.regexp = null;
|
|
1738
|
-
this.negate = false;
|
|
1739
|
-
this.nonegate = !!options.nonegate;
|
|
1740
|
-
this.comment = false;
|
|
1741
|
-
this.empty = false;
|
|
1742
|
-
this.partial = !!options.partial;
|
|
1743
|
-
this.nocase = !!this.options.nocase;
|
|
1744
|
-
this.windowsNoMagicRoot =
|
|
1745
|
-
options.windowsNoMagicRoot !== undefined ?
|
|
1746
|
-
options.windowsNoMagicRoot
|
|
1747
|
-
: !!(this.isWindows && this.nocase);
|
|
1748
|
-
this.globSet = [];
|
|
1749
|
-
this.globParts = [];
|
|
1750
|
-
this.set = [];
|
|
1751
|
-
// make the set of regexps etc.
|
|
1752
|
-
this.make();
|
|
1753
|
-
}
|
|
1754
|
-
hasMagic() {
|
|
1755
|
-
if (this.options.magicalBraces && this.set.length > 1) {
|
|
1756
|
-
return true;
|
|
1757
|
-
}
|
|
1758
|
-
for (const pattern of this.set) {
|
|
1759
|
-
for (const part of pattern) {
|
|
1760
|
-
if (typeof part !== 'string')
|
|
1761
|
-
return true;
|
|
1762
|
-
}
|
|
1763
|
-
}
|
|
1764
|
-
return false;
|
|
1765
|
-
}
|
|
1766
|
-
debug(..._) { }
|
|
1767
|
-
make() {
|
|
1768
|
-
const pattern = this.pattern;
|
|
1769
|
-
const options = this.options;
|
|
1770
|
-
// empty patterns and comments match nothing.
|
|
1771
|
-
if (!options.nocomment && pattern.charAt(0) === '#') {
|
|
1772
|
-
this.comment = true;
|
|
1773
|
-
return;
|
|
1774
|
-
}
|
|
1775
|
-
if (!pattern) {
|
|
1776
|
-
this.empty = true;
|
|
1777
|
-
return;
|
|
1778
|
-
}
|
|
1779
|
-
// step 1: figure out negation, etc.
|
|
1780
|
-
this.parseNegate();
|
|
1781
|
-
// step 2: expand braces
|
|
1782
|
-
this.globSet = [...new Set(this.braceExpand())];
|
|
1783
|
-
if (options.debug) {
|
|
1784
|
-
//oxlint-disable-next-line no-console
|
|
1785
|
-
this.debug = (...args) => console.error(...args);
|
|
1786
|
-
}
|
|
1787
|
-
this.debug(this.pattern, this.globSet);
|
|
1788
|
-
// step 3: now we have a set, so turn each one into a series of
|
|
1789
|
-
// path-portion matching patterns.
|
|
1790
|
-
// These will be regexps, except in the case of "**", which is
|
|
1791
|
-
// set to the GLOBSTAR object for globstar behavior,
|
|
1792
|
-
// and will not contain any / characters
|
|
1793
|
-
//
|
|
1794
|
-
// First, we preprocess to make the glob pattern sets a bit simpler
|
|
1795
|
-
// and deduped. There are some perf-killing patterns that can cause
|
|
1796
|
-
// problems with a glob walk, but we can simplify them down a bit.
|
|
1797
|
-
const rawGlobParts = this.globSet.map(s => this.slashSplit(s));
|
|
1798
|
-
this.globParts = this.preprocess(rawGlobParts);
|
|
1799
|
-
this.debug(this.pattern, this.globParts);
|
|
1800
|
-
// glob --> regexps
|
|
1801
|
-
let set = this.globParts.map((s, _, __) => {
|
|
1802
|
-
if (this.isWindows && this.windowsNoMagicRoot) {
|
|
1803
|
-
// check if it's a drive or unc path.
|
|
1804
|
-
const isUNC = s[0] === '' &&
|
|
1805
|
-
s[1] === '' &&
|
|
1806
|
-
(s[2] === '?' || !globMagic.test(s[2])) &&
|
|
1807
|
-
!globMagic.test(s[3]);
|
|
1808
|
-
const isDrive = /^[a-z]:/i.test(s[0]);
|
|
1809
|
-
if (isUNC) {
|
|
1810
|
-
return [
|
|
1811
|
-
...s.slice(0, 4),
|
|
1812
|
-
...s.slice(4).map(ss => this.parse(ss)),
|
|
1813
|
-
];
|
|
1814
|
-
}
|
|
1815
|
-
else if (isDrive) {
|
|
1816
|
-
return [s[0], ...s.slice(1).map(ss => this.parse(ss))];
|
|
1817
|
-
}
|
|
1818
|
-
}
|
|
1819
|
-
return s.map(ss => this.parse(ss));
|
|
1820
|
-
});
|
|
1821
|
-
this.debug(this.pattern, set);
|
|
1822
|
-
// filter out everything that didn't compile properly.
|
|
1823
|
-
this.set = set.filter(s => s.indexOf(false) === -1);
|
|
1824
|
-
// do not treat the ? in UNC paths as magic
|
|
1825
|
-
if (this.isWindows) {
|
|
1826
|
-
for (let i = 0; i < this.set.length; i++) {
|
|
1827
|
-
const p = this.set[i];
|
|
1828
|
-
if (p[0] === '' &&
|
|
1829
|
-
p[1] === '' &&
|
|
1830
|
-
this.globParts[i][2] === '?' &&
|
|
1831
|
-
typeof p[3] === 'string' &&
|
|
1832
|
-
/^[a-z]:$/i.test(p[3])) {
|
|
1833
|
-
p[2] = '?';
|
|
1834
|
-
}
|
|
1835
|
-
}
|
|
1836
|
-
}
|
|
1837
|
-
this.debug(this.pattern, this.set);
|
|
1838
|
-
}
|
|
1839
|
-
// various transforms to equivalent pattern sets that are
|
|
1840
|
-
// faster to process in a filesystem walk. The goal is to
|
|
1841
|
-
// eliminate what we can, and push all ** patterns as far
|
|
1842
|
-
// to the right as possible, even if it increases the number
|
|
1843
|
-
// of patterns that we have to process.
|
|
1844
|
-
preprocess(globParts) {
|
|
1845
|
-
// if we're not in globstar mode, then turn ** into *
|
|
1846
|
-
if (this.options.noglobstar) {
|
|
1847
|
-
for (const partset of globParts) {
|
|
1848
|
-
for (let j = 0; j < partset.length; j++) {
|
|
1849
|
-
if (partset[j] === '**') {
|
|
1850
|
-
partset[j] = '*';
|
|
1851
|
-
}
|
|
1852
|
-
}
|
|
1853
|
-
}
|
|
1854
|
-
}
|
|
1855
|
-
const { optimizationLevel = 1 } = this.options;
|
|
1856
|
-
if (optimizationLevel >= 2) {
|
|
1857
|
-
// aggressive optimization for the purpose of fs walking
|
|
1858
|
-
globParts = this.firstPhasePreProcess(globParts);
|
|
1859
|
-
globParts = this.secondPhasePreProcess(globParts);
|
|
1860
|
-
}
|
|
1861
|
-
else if (optimizationLevel >= 1) {
|
|
1862
|
-
// just basic optimizations to remove some .. parts
|
|
1863
|
-
globParts = this.levelOneOptimize(globParts);
|
|
1864
|
-
}
|
|
1865
|
-
else {
|
|
1866
|
-
// just collapse multiple ** portions into one
|
|
1867
|
-
globParts = this.adjascentGlobstarOptimize(globParts);
|
|
1868
|
-
}
|
|
1869
|
-
return globParts;
|
|
1870
|
-
}
|
|
1871
|
-
// just get rid of adjascent ** portions
|
|
1872
|
-
adjascentGlobstarOptimize(globParts) {
|
|
1873
|
-
return globParts.map(parts => {
|
|
1874
|
-
let gs = -1;
|
|
1875
|
-
while (-1 !== (gs = parts.indexOf('**', gs + 1))) {
|
|
1876
|
-
let i = gs;
|
|
1877
|
-
while (parts[i + 1] === '**') {
|
|
1878
|
-
i++;
|
|
1879
|
-
}
|
|
1880
|
-
if (i !== gs) {
|
|
1881
|
-
parts.splice(gs, i - gs);
|
|
1882
|
-
}
|
|
1883
|
-
}
|
|
1884
|
-
return parts;
|
|
1885
|
-
});
|
|
1886
|
-
}
|
|
1887
|
-
// get rid of adjascent ** and resolve .. portions
|
|
1888
|
-
levelOneOptimize(globParts) {
|
|
1889
|
-
return globParts.map(parts => {
|
|
1890
|
-
parts = parts.reduce((set, part) => {
|
|
1891
|
-
const prev = set[set.length - 1];
|
|
1892
|
-
if (part === '**' && prev === '**') {
|
|
1893
|
-
return set;
|
|
1894
|
-
}
|
|
1895
|
-
if (part === '..') {
|
|
1896
|
-
if (prev && prev !== '..' && prev !== '.' && prev !== '**') {
|
|
1897
|
-
set.pop();
|
|
1898
|
-
return set;
|
|
1899
|
-
}
|
|
1900
|
-
}
|
|
1901
|
-
set.push(part);
|
|
1902
|
-
return set;
|
|
1903
|
-
}, []);
|
|
1904
|
-
return parts.length === 0 ? [''] : parts;
|
|
1905
|
-
});
|
|
1906
|
-
}
|
|
1907
|
-
levelTwoFileOptimize(parts) {
|
|
1908
|
-
if (!Array.isArray(parts)) {
|
|
1909
|
-
parts = this.slashSplit(parts);
|
|
1910
|
-
}
|
|
1911
|
-
let didSomething = false;
|
|
1912
|
-
do {
|
|
1913
|
-
didSomething = false;
|
|
1914
|
-
// <pre>/<e>/<rest> -> <pre>/<rest>
|
|
1915
|
-
if (!this.preserveMultipleSlashes) {
|
|
1916
|
-
for (let i = 1; i < parts.length - 1; i++) {
|
|
1917
|
-
const p = parts[i];
|
|
1918
|
-
// don't squeeze out UNC patterns
|
|
1919
|
-
if (i === 1 && p === '' && parts[0] === '')
|
|
1920
|
-
continue;
|
|
1921
|
-
if (p === '.' || p === '') {
|
|
1922
|
-
didSomething = true;
|
|
1923
|
-
parts.splice(i, 1);
|
|
1924
|
-
i--;
|
|
1925
|
-
}
|
|
1926
|
-
}
|
|
1927
|
-
if (parts[0] === '.' &&
|
|
1928
|
-
parts.length === 2 &&
|
|
1929
|
-
(parts[1] === '.' || parts[1] === '')) {
|
|
1930
|
-
didSomething = true;
|
|
1931
|
-
parts.pop();
|
|
1932
|
-
}
|
|
1933
|
-
}
|
|
1934
|
-
// <pre>/<p>/../<rest> -> <pre>/<rest>
|
|
1935
|
-
let dd = 0;
|
|
1936
|
-
while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
|
|
1937
|
-
const p = parts[dd - 1];
|
|
1938
|
-
if (p &&
|
|
1939
|
-
p !== '.' &&
|
|
1940
|
-
p !== '..' &&
|
|
1941
|
-
p !== '**' &&
|
|
1942
|
-
!(this.isWindows && /^[a-z]:$/i.test(p))) {
|
|
1943
|
-
didSomething = true;
|
|
1944
|
-
parts.splice(dd - 1, 2);
|
|
1945
|
-
dd -= 2;
|
|
1946
|
-
}
|
|
1947
|
-
}
|
|
1948
|
-
} while (didSomething);
|
|
1949
|
-
return parts.length === 0 ? [''] : parts;
|
|
1950
|
-
}
|
|
1951
|
-
// First phase: single-pattern processing
|
|
1952
|
-
// <pre> is 1 or more portions
|
|
1953
|
-
// <rest> is 1 or more portions
|
|
1954
|
-
// <p> is any portion other than ., .., '', or **
|
|
1955
|
-
// <e> is . or ''
|
|
1956
|
-
//
|
|
1957
|
-
// **/.. is *brutal* for filesystem walking performance, because
|
|
1958
|
-
// it effectively resets the recursive walk each time it occurs,
|
|
1959
|
-
// and ** cannot be reduced out by a .. pattern part like a regexp
|
|
1960
|
-
// or most strings (other than .., ., and '') can be.
|
|
1961
|
-
//
|
|
1962
|
-
// <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}
|
|
1963
|
-
// <pre>/<e>/<rest> -> <pre>/<rest>
|
|
1964
|
-
// <pre>/<p>/../<rest> -> <pre>/<rest>
|
|
1965
|
-
// **/**/<rest> -> **/<rest>
|
|
1966
|
-
//
|
|
1967
|
-
// **/*/<rest> -> */**/<rest> <== not valid because ** doesn't follow
|
|
1968
|
-
// this WOULD be allowed if ** did follow symlinks, or * didn't
|
|
1969
|
-
firstPhasePreProcess(globParts) {
|
|
1970
|
-
let didSomething = false;
|
|
1971
|
-
do {
|
|
1972
|
-
didSomething = false;
|
|
1973
|
-
// <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}
|
|
1974
|
-
for (let parts of globParts) {
|
|
1975
|
-
let gs = -1;
|
|
1976
|
-
while (-1 !== (gs = parts.indexOf('**', gs + 1))) {
|
|
1977
|
-
let gss = gs;
|
|
1978
|
-
while (parts[gss + 1] === '**') {
|
|
1979
|
-
// <pre>/**/**/<rest> -> <pre>/**/<rest>
|
|
1980
|
-
gss++;
|
|
1981
|
-
}
|
|
1982
|
-
// eg, if gs is 2 and gss is 4, that means we have 3 **
|
|
1983
|
-
// parts, and can remove 2 of them.
|
|
1984
|
-
if (gss > gs) {
|
|
1985
|
-
parts.splice(gs + 1, gss - gs);
|
|
1986
|
-
}
|
|
1987
|
-
let next = parts[gs + 1];
|
|
1988
|
-
const p = parts[gs + 2];
|
|
1989
|
-
const p2 = parts[gs + 3];
|
|
1990
|
-
if (next !== '..')
|
|
1991
|
-
continue;
|
|
1992
|
-
if (!p ||
|
|
1993
|
-
p === '.' ||
|
|
1994
|
-
p === '..' ||
|
|
1995
|
-
!p2 ||
|
|
1996
|
-
p2 === '.' ||
|
|
1997
|
-
p2 === '..') {
|
|
1998
|
-
continue;
|
|
1999
|
-
}
|
|
2000
|
-
didSomething = true;
|
|
2001
|
-
// edit parts in place, and push the new one
|
|
2002
|
-
parts.splice(gs, 1);
|
|
2003
|
-
const other = parts.slice(0);
|
|
2004
|
-
other[gs] = '**';
|
|
2005
|
-
globParts.push(other);
|
|
2006
|
-
gs--;
|
|
2007
|
-
}
|
|
2008
|
-
// <pre>/<e>/<rest> -> <pre>/<rest>
|
|
2009
|
-
if (!this.preserveMultipleSlashes) {
|
|
2010
|
-
for (let i = 1; i < parts.length - 1; i++) {
|
|
2011
|
-
const p = parts[i];
|
|
2012
|
-
// don't squeeze out UNC patterns
|
|
2013
|
-
if (i === 1 && p === '' && parts[0] === '')
|
|
2014
|
-
continue;
|
|
2015
|
-
if (p === '.' || p === '') {
|
|
2016
|
-
didSomething = true;
|
|
2017
|
-
parts.splice(i, 1);
|
|
2018
|
-
i--;
|
|
2019
|
-
}
|
|
2020
|
-
}
|
|
2021
|
-
if (parts[0] === '.' &&
|
|
2022
|
-
parts.length === 2 &&
|
|
2023
|
-
(parts[1] === '.' || parts[1] === '')) {
|
|
2024
|
-
didSomething = true;
|
|
2025
|
-
parts.pop();
|
|
2026
|
-
}
|
|
2027
|
-
}
|
|
2028
|
-
// <pre>/<p>/../<rest> -> <pre>/<rest>
|
|
2029
|
-
let dd = 0;
|
|
2030
|
-
while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
|
|
2031
|
-
const p = parts[dd - 1];
|
|
2032
|
-
if (p && p !== '.' && p !== '..' && p !== '**') {
|
|
2033
|
-
didSomething = true;
|
|
2034
|
-
const needDot = dd === 1 && parts[dd + 1] === '**';
|
|
2035
|
-
const splin = needDot ? ['.'] : [];
|
|
2036
|
-
parts.splice(dd - 1, 2, ...splin);
|
|
2037
|
-
if (parts.length === 0)
|
|
2038
|
-
parts.push('');
|
|
2039
|
-
dd -= 2;
|
|
2040
|
-
}
|
|
2041
|
-
}
|
|
2042
|
-
}
|
|
2043
|
-
} while (didSomething);
|
|
2044
|
-
return globParts;
|
|
2045
|
-
}
|
|
2046
|
-
// second phase: multi-pattern dedupes
|
|
2047
|
-
// {<pre>/*/<rest>,<pre>/<p>/<rest>} -> <pre>/*/<rest>
|
|
2048
|
-
// {<pre>/<rest>,<pre>/<rest>} -> <pre>/<rest>
|
|
2049
|
-
// {<pre>/**/<rest>,<pre>/<rest>} -> <pre>/**/<rest>
|
|
2050
|
-
//
|
|
2051
|
-
// {<pre>/**/<rest>,<pre>/**/<p>/<rest>} -> <pre>/**/<rest>
|
|
2052
|
-
// ^-- not valid because ** doens't follow symlinks
|
|
2053
|
-
secondPhasePreProcess(globParts) {
|
|
2054
|
-
for (let i = 0; i < globParts.length - 1; i++) {
|
|
2055
|
-
for (let j = i + 1; j < globParts.length; j++) {
|
|
2056
|
-
const matched = this.partsMatch(globParts[i], globParts[j], !this.preserveMultipleSlashes);
|
|
2057
|
-
if (matched) {
|
|
2058
|
-
globParts[i] = [];
|
|
2059
|
-
globParts[j] = matched;
|
|
2060
|
-
break;
|
|
2061
|
-
}
|
|
2062
|
-
}
|
|
2063
|
-
}
|
|
2064
|
-
return globParts.filter(gs => gs.length);
|
|
2065
|
-
}
|
|
2066
|
-
partsMatch(a, b, emptyGSMatch = false) {
|
|
2067
|
-
let ai = 0;
|
|
2068
|
-
let bi = 0;
|
|
2069
|
-
let result = [];
|
|
2070
|
-
let which = '';
|
|
2071
|
-
while (ai < a.length && bi < b.length) {
|
|
2072
|
-
if (a[ai] === b[bi]) {
|
|
2073
|
-
result.push(which === 'b' ? b[bi] : a[ai]);
|
|
2074
|
-
ai++;
|
|
2075
|
-
bi++;
|
|
2076
|
-
}
|
|
2077
|
-
else if (emptyGSMatch && a[ai] === '**' && b[bi] === a[ai + 1]) {
|
|
2078
|
-
result.push(a[ai]);
|
|
2079
|
-
ai++;
|
|
2080
|
-
}
|
|
2081
|
-
else if (emptyGSMatch && b[bi] === '**' && a[ai] === b[bi + 1]) {
|
|
2082
|
-
result.push(b[bi]);
|
|
2083
|
-
bi++;
|
|
2084
|
-
}
|
|
2085
|
-
else if (a[ai] === '*' &&
|
|
2086
|
-
b[bi] &&
|
|
2087
|
-
(this.options.dot || !b[bi].startsWith('.')) &&
|
|
2088
|
-
b[bi] !== '**') {
|
|
2089
|
-
if (which === 'b')
|
|
2090
|
-
return false;
|
|
2091
|
-
which = 'a';
|
|
2092
|
-
result.push(a[ai]);
|
|
2093
|
-
ai++;
|
|
2094
|
-
bi++;
|
|
2095
|
-
}
|
|
2096
|
-
else if (b[bi] === '*' &&
|
|
2097
|
-
a[ai] &&
|
|
2098
|
-
(this.options.dot || !a[ai].startsWith('.')) &&
|
|
2099
|
-
a[ai] !== '**') {
|
|
2100
|
-
if (which === 'a')
|
|
2101
|
-
return false;
|
|
2102
|
-
which = 'b';
|
|
2103
|
-
result.push(b[bi]);
|
|
2104
|
-
ai++;
|
|
2105
|
-
bi++;
|
|
2106
|
-
}
|
|
2107
|
-
else {
|
|
2108
|
-
return false;
|
|
2109
|
-
}
|
|
2110
|
-
}
|
|
2111
|
-
// if we fall out of the loop, it means they two are identical
|
|
2112
|
-
// as long as their lengths match
|
|
2113
|
-
return a.length === b.length && result;
|
|
2114
|
-
}
|
|
2115
|
-
parseNegate() {
|
|
2116
|
-
if (this.nonegate)
|
|
2117
|
-
return;
|
|
2118
|
-
const pattern = this.pattern;
|
|
2119
|
-
let negate = false;
|
|
2120
|
-
let negateOffset = 0;
|
|
2121
|
-
for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {
|
|
2122
|
-
negate = !negate;
|
|
2123
|
-
negateOffset++;
|
|
2124
|
-
}
|
|
2125
|
-
if (negateOffset)
|
|
2126
|
-
this.pattern = pattern.slice(negateOffset);
|
|
2127
|
-
this.negate = negate;
|
|
2128
|
-
}
|
|
2129
|
-
// set partial to true to test if, for example,
|
|
2130
|
-
// "/a/b" matches the start of "/*/b/*/d"
|
|
2131
|
-
// Partial means, if you run out of file before you run
|
|
2132
|
-
// out of pattern, then that's fine, as long as all
|
|
2133
|
-
// the parts match.
|
|
2134
|
-
matchOne(file, pattern, partial = false) {
|
|
2135
|
-
let fileStartIndex = 0;
|
|
2136
|
-
let patternStartIndex = 0;
|
|
2137
|
-
// UNC paths like //?/X:/... can match X:/... and vice versa
|
|
2138
|
-
// Drive letters in absolute drive or unc paths are always compared
|
|
2139
|
-
// case-insensitively.
|
|
2140
|
-
if (this.isWindows) {
|
|
2141
|
-
const fileDrive = typeof file[0] === 'string' && /^[a-z]:$/i.test(file[0]);
|
|
2142
|
-
const fileUNC = !fileDrive &&
|
|
2143
|
-
file[0] === '' &&
|
|
2144
|
-
file[1] === '' &&
|
|
2145
|
-
file[2] === '?' &&
|
|
2146
|
-
/^[a-z]:$/i.test(file[3]);
|
|
2147
|
-
const patternDrive = typeof pattern[0] === 'string' && /^[a-z]:$/i.test(pattern[0]);
|
|
2148
|
-
const patternUNC = !patternDrive &&
|
|
2149
|
-
pattern[0] === '' &&
|
|
2150
|
-
pattern[1] === '' &&
|
|
2151
|
-
pattern[2] === '?' &&
|
|
2152
|
-
typeof pattern[3] === 'string' &&
|
|
2153
|
-
/^[a-z]:$/i.test(pattern[3]);
|
|
2154
|
-
const fdi = fileUNC ? 3
|
|
2155
|
-
: fileDrive ? 0
|
|
2156
|
-
: undefined;
|
|
2157
|
-
const pdi = patternUNC ? 3
|
|
2158
|
-
: patternDrive ? 0
|
|
2159
|
-
: undefined;
|
|
2160
|
-
if (typeof fdi === 'number' && typeof pdi === 'number') {
|
|
2161
|
-
const [fd, pd] = [
|
|
2162
|
-
file[fdi],
|
|
2163
|
-
pattern[pdi],
|
|
2164
|
-
];
|
|
2165
|
-
// start matching at the drive letter index of each
|
|
2166
|
-
if (fd.toLowerCase() === pd.toLowerCase()) {
|
|
2167
|
-
pattern[pdi] = fd;
|
|
2168
|
-
patternStartIndex = pdi;
|
|
2169
|
-
fileStartIndex = fdi;
|
|
2170
|
-
}
|
|
2171
|
-
}
|
|
2172
|
-
}
|
|
2173
|
-
// resolve and reduce . and .. portions in the file as well.
|
|
2174
|
-
// don't need to do the second phase, because it's only one string[]
|
|
2175
|
-
const { optimizationLevel = 1 } = this.options;
|
|
2176
|
-
if (optimizationLevel >= 2) {
|
|
2177
|
-
file = this.levelTwoFileOptimize(file);
|
|
2178
|
-
}
|
|
2179
|
-
if (pattern.includes(exports.GLOBSTAR)) {
|
|
2180
|
-
return this.#matchGlobstar(file, pattern, partial, fileStartIndex, patternStartIndex);
|
|
2181
|
-
}
|
|
2182
|
-
return this.#matchOne(file, pattern, partial, fileStartIndex, patternStartIndex);
|
|
2183
|
-
}
|
|
2184
|
-
#matchGlobstar(file, pattern, partial, fileIndex, patternIndex) {
|
|
2185
|
-
// split the pattern into head, tail, and middle of ** delimited parts
|
|
2186
|
-
const firstgs = pattern.indexOf(exports.GLOBSTAR, patternIndex);
|
|
2187
|
-
const lastgs = pattern.lastIndexOf(exports.GLOBSTAR);
|
|
2188
|
-
// split the pattern up into globstar-delimited sections
|
|
2189
|
-
// the tail has to be at the end, and the others just have
|
|
2190
|
-
// to be found in order from the head.
|
|
2191
|
-
const [head, body, tail] = partial ?
|
|
2192
|
-
[
|
|
2193
|
-
pattern.slice(patternIndex, firstgs),
|
|
2194
|
-
pattern.slice(firstgs + 1),
|
|
2195
|
-
[],
|
|
2196
|
-
]
|
|
2197
|
-
: [
|
|
2198
|
-
pattern.slice(patternIndex, firstgs),
|
|
2199
|
-
pattern.slice(firstgs + 1, lastgs),
|
|
2200
|
-
pattern.slice(lastgs + 1),
|
|
2201
|
-
];
|
|
2202
|
-
// check the head, from the current file/pattern index.
|
|
2203
|
-
if (head.length) {
|
|
2204
|
-
const fileHead = file.slice(fileIndex, fileIndex + head.length);
|
|
2205
|
-
if (!this.#matchOne(fileHead, head, partial, 0, 0)) {
|
|
2206
|
-
return false;
|
|
2207
|
-
}
|
|
2208
|
-
fileIndex += head.length;
|
|
2209
|
-
patternIndex += head.length;
|
|
2210
|
-
}
|
|
2211
|
-
// now we know the head matches!
|
|
2212
|
-
// if the last portion is not empty, it MUST match the end
|
|
2213
|
-
// check the tail
|
|
2214
|
-
let fileTailMatch = 0;
|
|
2215
|
-
if (tail.length) {
|
|
2216
|
-
// if head + tail > file, then we cannot possibly match
|
|
2217
|
-
if (tail.length + fileIndex > file.length)
|
|
2218
|
-
return false;
|
|
2219
|
-
// try to match the tail
|
|
2220
|
-
let tailStart = file.length - tail.length;
|
|
2221
|
-
if (this.#matchOne(file, tail, partial, tailStart, 0)) {
|
|
2222
|
-
fileTailMatch = tail.length;
|
|
2223
|
-
}
|
|
2224
|
-
else {
|
|
2225
|
-
// affordance for stuff like a/**/* matching a/b/
|
|
2226
|
-
// if the last file portion is '', and there's more to the pattern
|
|
2227
|
-
// then try without the '' bit.
|
|
2228
|
-
if (file[file.length - 1] !== '' ||
|
|
2229
|
-
fileIndex + tail.length === file.length) {
|
|
2230
|
-
return false;
|
|
2231
|
-
}
|
|
2232
|
-
tailStart--;
|
|
2233
|
-
if (!this.#matchOne(file, tail, partial, tailStart, 0)) {
|
|
2234
|
-
return false;
|
|
2235
|
-
}
|
|
2236
|
-
fileTailMatch = tail.length + 1;
|
|
2237
|
-
}
|
|
2238
|
-
}
|
|
2239
|
-
// now we know the tail matches!
|
|
2240
|
-
// the middle is zero or more portions wrapped in **, possibly
|
|
2241
|
-
// containing more ** sections.
|
|
2242
|
-
// so a/**/b/**/c/**/d has become **/b/**/c/**
|
|
2243
|
-
// if it's empty, it means a/**/b, just verify we have no bad dots
|
|
2244
|
-
// if there's no tail, so it ends on /**, then we must have *something*
|
|
2245
|
-
// after the head, or it's not a matc
|
|
2246
|
-
if (!body.length) {
|
|
2247
|
-
let sawSome = !!fileTailMatch;
|
|
2248
|
-
for (let i = fileIndex; i < file.length - fileTailMatch; i++) {
|
|
2249
|
-
const f = String(file[i]);
|
|
2250
|
-
sawSome = true;
|
|
2251
|
-
if (f === '.' ||
|
|
2252
|
-
f === '..' ||
|
|
2253
|
-
(!this.options.dot && f.startsWith('.'))) {
|
|
2254
|
-
return false;
|
|
2255
|
-
}
|
|
2256
|
-
}
|
|
2257
|
-
// in partial mode, we just need to get past all file parts
|
|
2258
|
-
return partial || sawSome;
|
|
2259
|
-
}
|
|
2260
|
-
// now we know that there's one or more body sections, which can
|
|
2261
|
-
// be matched anywhere from the 0 index (because the head was pruned)
|
|
2262
|
-
// through to the length-fileTailMatch index.
|
|
2263
|
-
// split the body up into sections, and note the minimum index it can
|
|
2264
|
-
// be found at (start with the length of all previous segments)
|
|
2265
|
-
// [section, before, after]
|
|
2266
|
-
const bodySegments = [[[], 0]];
|
|
2267
|
-
let currentBody = bodySegments[0];
|
|
2268
|
-
let nonGsParts = 0;
|
|
2269
|
-
const nonGsPartsSums = [0];
|
|
2270
|
-
for (const b of body) {
|
|
2271
|
-
if (b === exports.GLOBSTAR) {
|
|
2272
|
-
nonGsPartsSums.push(nonGsParts);
|
|
2273
|
-
currentBody = [[], 0];
|
|
2274
|
-
bodySegments.push(currentBody);
|
|
2275
|
-
}
|
|
2276
|
-
else {
|
|
2277
|
-
currentBody[0].push(b);
|
|
2278
|
-
nonGsParts++;
|
|
2279
|
-
}
|
|
2280
|
-
}
|
|
2281
|
-
let i = bodySegments.length - 1;
|
|
2282
|
-
const fileLength = file.length - fileTailMatch;
|
|
2283
|
-
for (const b of bodySegments) {
|
|
2284
|
-
b[1] = fileLength - (nonGsPartsSums[i--] + b[0].length);
|
|
2285
|
-
}
|
|
2286
|
-
return !!this.#matchGlobStarBodySections(file, bodySegments, fileIndex, 0, partial, 0, !!fileTailMatch);
|
|
2287
|
-
}
|
|
2288
|
-
// return false for "nope, not matching"
|
|
2289
|
-
// return null for "not matching, cannot keep trying"
|
|
2290
|
-
#matchGlobStarBodySections(file,
|
|
2291
|
-
// pattern section, last possible position for it
|
|
2292
|
-
bodySegments, fileIndex, bodyIndex, partial, globStarDepth, sawTail) {
|
|
2293
|
-
// take the first body segment, and walk from fileIndex to its "after"
|
|
2294
|
-
// value at the end
|
|
2295
|
-
// If it doesn't match at that position, we increment, until we hit
|
|
2296
|
-
// that final possible position, and give up.
|
|
2297
|
-
// If it does match, then advance and try to rest.
|
|
2298
|
-
// If any of them fail we keep walking forward.
|
|
2299
|
-
// this is still a bit recursively painful, but it's more constrained
|
|
2300
|
-
// than previous implementations, because we never test something that
|
|
2301
|
-
// can't possibly be a valid matching condition.
|
|
2302
|
-
const bs = bodySegments[bodyIndex];
|
|
2303
|
-
if (!bs) {
|
|
2304
|
-
// just make sure that there's no bad dots
|
|
2305
|
-
for (let i = fileIndex; i < file.length; i++) {
|
|
2306
|
-
sawTail = true;
|
|
2307
|
-
const f = file[i];
|
|
2308
|
-
if (f === '.' ||
|
|
2309
|
-
f === '..' ||
|
|
2310
|
-
(!this.options.dot && f.startsWith('.'))) {
|
|
2311
|
-
return false;
|
|
2312
|
-
}
|
|
2313
|
-
}
|
|
2314
|
-
return sawTail;
|
|
2315
|
-
}
|
|
2316
|
-
// have a non-globstar body section to test
|
|
2317
|
-
const [body, after] = bs;
|
|
2318
|
-
while (fileIndex <= after) {
|
|
2319
|
-
const m = this.#matchOne(file.slice(0, fileIndex + body.length), body, partial, fileIndex, 0);
|
|
2320
|
-
// if limit exceeded, no match. intentional false negative,
|
|
2321
|
-
// acceptable break in correctness for security.
|
|
2322
|
-
if (m && globStarDepth < this.maxGlobstarRecursion) {
|
|
2323
|
-
// match! see if the rest match. if so, we're done!
|
|
2324
|
-
const sub = this.#matchGlobStarBodySections(file, bodySegments, fileIndex + body.length, bodyIndex + 1, partial, globStarDepth + 1, sawTail);
|
|
2325
|
-
if (sub !== false) {
|
|
2326
|
-
return sub;
|
|
2327
|
-
}
|
|
2328
|
-
}
|
|
2329
|
-
const f = file[fileIndex];
|
|
2330
|
-
if (f === '.' ||
|
|
2331
|
-
f === '..' ||
|
|
2332
|
-
(!this.options.dot && f.startsWith('.'))) {
|
|
2333
|
-
return false;
|
|
2334
|
-
}
|
|
2335
|
-
fileIndex++;
|
|
2336
|
-
}
|
|
2337
|
-
// walked off. no point continuing
|
|
2338
|
-
return partial || null;
|
|
2339
|
-
}
|
|
2340
|
-
#matchOne(file, pattern, partial, fileIndex, patternIndex) {
|
|
2341
|
-
let fi;
|
|
2342
|
-
let pi;
|
|
2343
|
-
let pl;
|
|
2344
|
-
let fl;
|
|
2345
|
-
for (fi = fileIndex,
|
|
2346
|
-
pi = patternIndex,
|
|
2347
|
-
fl = file.length,
|
|
2348
|
-
pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
|
|
2349
|
-
this.debug('matchOne loop');
|
|
2350
|
-
let p = pattern[pi];
|
|
2351
|
-
let f = file[fi];
|
|
2352
|
-
this.debug(pattern, p, f);
|
|
2353
|
-
// should be impossible.
|
|
2354
|
-
// some invalid regexp stuff in the set.
|
|
2355
|
-
/* c8 ignore start */
|
|
2356
|
-
if (p === false || p === exports.GLOBSTAR) {
|
|
2357
|
-
return false;
|
|
2358
|
-
}
|
|
2359
|
-
/* c8 ignore stop */
|
|
2360
|
-
// something other than **
|
|
2361
|
-
// non-magic patterns just have to match exactly
|
|
2362
|
-
// patterns with magic have been turned into regexps.
|
|
2363
|
-
let hit;
|
|
2364
|
-
if (typeof p === 'string') {
|
|
2365
|
-
hit = f === p;
|
|
2366
|
-
this.debug('string match', p, f, hit);
|
|
2367
|
-
}
|
|
2368
|
-
else {
|
|
2369
|
-
hit = p.test(f);
|
|
2370
|
-
this.debug('pattern match', p, f, hit);
|
|
2371
|
-
}
|
|
2372
|
-
if (!hit)
|
|
2373
|
-
return false;
|
|
2374
|
-
}
|
|
2375
|
-
// Note: ending in / means that we'll get a final ""
|
|
2376
|
-
// at the end of the pattern. This can only match a
|
|
2377
|
-
// corresponding "" at the end of the file.
|
|
2378
|
-
// If the file ends in /, then it can only match a
|
|
2379
|
-
// a pattern that ends in /, unless the pattern just
|
|
2380
|
-
// doesn't have any more for it. But, a/b/ should *not*
|
|
2381
|
-
// match "a/b/*", even though "" matches against the
|
|
2382
|
-
// [^/]*? pattern, except in partial mode, where it might
|
|
2383
|
-
// simply not be reached yet.
|
|
2384
|
-
// However, a/b/ should still satisfy a/*
|
|
2385
|
-
// now either we fell off the end of the pattern, or we're done.
|
|
2386
|
-
if (fi === fl && pi === pl) {
|
|
2387
|
-
// ran out of pattern and filename at the same time.
|
|
2388
|
-
// an exact hit!
|
|
2389
|
-
return true;
|
|
2390
|
-
}
|
|
2391
|
-
else if (fi === fl) {
|
|
2392
|
-
// ran out of file, but still had pattern left.
|
|
2393
|
-
// this is ok if we're doing the match as part of
|
|
2394
|
-
// a glob fs traversal.
|
|
2395
|
-
return partial;
|
|
2396
|
-
}
|
|
2397
|
-
else if (pi === pl) {
|
|
2398
|
-
// ran out of pattern, still have file left.
|
|
2399
|
-
// this is only acceptable if we're on the very last
|
|
2400
|
-
// empty segment of a file with a trailing slash.
|
|
2401
|
-
// a/* should match a/b/
|
|
2402
|
-
return fi === fl - 1 && file[fi] === '';
|
|
2403
|
-
/* c8 ignore start */
|
|
2404
|
-
}
|
|
2405
|
-
else {
|
|
2406
|
-
// should be unreachable.
|
|
2407
|
-
throw new Error('wtf?');
|
|
2408
|
-
}
|
|
2409
|
-
/* c8 ignore stop */
|
|
2410
|
-
}
|
|
2411
|
-
braceExpand() {
|
|
2412
|
-
return (0, exports.braceExpand)(this.pattern, this.options);
|
|
2413
|
-
}
|
|
2414
|
-
parse(pattern) {
|
|
2415
|
-
(0, assert_valid_pattern_js_1.assertValidPattern)(pattern);
|
|
2416
|
-
const options = this.options;
|
|
2417
|
-
// shortcuts
|
|
2418
|
-
if (pattern === '**')
|
|
2419
|
-
return exports.GLOBSTAR;
|
|
2420
|
-
if (pattern === '')
|
|
2421
|
-
return '';
|
|
2422
|
-
// far and away, the most common glob pattern parts are
|
|
2423
|
-
// *, *.*, and *.<ext> Add a fast check method for those.
|
|
2424
|
-
let m;
|
|
2425
|
-
let fastTest = null;
|
|
2426
|
-
if ((m = pattern.match(starRE))) {
|
|
2427
|
-
fastTest = options.dot ? starTestDot : starTest;
|
|
2428
|
-
}
|
|
2429
|
-
else if ((m = pattern.match(starDotExtRE))) {
|
|
2430
|
-
fastTest = (options.nocase ?
|
|
2431
|
-
options.dot ?
|
|
2432
|
-
starDotExtTestNocaseDot
|
|
2433
|
-
: starDotExtTestNocase
|
|
2434
|
-
: options.dot ? starDotExtTestDot
|
|
2435
|
-
: starDotExtTest)(m[1]);
|
|
2436
|
-
}
|
|
2437
|
-
else if ((m = pattern.match(qmarksRE))) {
|
|
2438
|
-
fastTest = (options.nocase ?
|
|
2439
|
-
options.dot ?
|
|
2440
|
-
qmarksTestNocaseDot
|
|
2441
|
-
: qmarksTestNocase
|
|
2442
|
-
: options.dot ? qmarksTestDot
|
|
2443
|
-
: qmarksTest)(m);
|
|
2444
|
-
}
|
|
2445
|
-
else if ((m = pattern.match(starDotStarRE))) {
|
|
2446
|
-
fastTest = options.dot ? starDotStarTestDot : starDotStarTest;
|
|
2447
|
-
}
|
|
2448
|
-
else if ((m = pattern.match(dotStarRE))) {
|
|
2449
|
-
fastTest = dotStarTest;
|
|
2450
|
-
}
|
|
2451
|
-
const re = ast_js_1.AST.fromGlob(pattern, this.options).toMMPattern();
|
|
2452
|
-
if (fastTest && typeof re === 'object') {
|
|
2453
|
-
// Avoids overriding in frozen environments
|
|
2454
|
-
Reflect.defineProperty(re, 'test', { value: fastTest });
|
|
2455
|
-
}
|
|
2456
|
-
return re;
|
|
2457
|
-
}
|
|
2458
|
-
makeRe() {
|
|
2459
|
-
if (this.regexp || this.regexp === false)
|
|
2460
|
-
return this.regexp;
|
|
2461
|
-
// at this point, this.set is a 2d array of partial
|
|
2462
|
-
// pattern strings, or "**".
|
|
2463
|
-
//
|
|
2464
|
-
// It's better to use .match(). This function shouldn't
|
|
2465
|
-
// be used, really, but it's pretty convenient sometimes,
|
|
2466
|
-
// when you just want to work with a regex.
|
|
2467
|
-
const set = this.set;
|
|
2468
|
-
if (!set.length) {
|
|
2469
|
-
this.regexp = false;
|
|
2470
|
-
return this.regexp;
|
|
2471
|
-
}
|
|
2472
|
-
const options = this.options;
|
|
2473
|
-
const twoStar = options.noglobstar ? star
|
|
2474
|
-
: options.dot ? twoStarDot
|
|
2475
|
-
: twoStarNoDot;
|
|
2476
|
-
const flags = new Set(options.nocase ? ['i'] : []);
|
|
2477
|
-
// regexpify non-globstar patterns
|
|
2478
|
-
// if ** is only item, then we just do one twoStar
|
|
2479
|
-
// if ** is first, and there are more, prepend (\/|twoStar\/)? to next
|
|
2480
|
-
// if ** is last, append (\/twoStar|) to previous
|
|
2481
|
-
// if ** is in the middle, append (\/|\/twoStar\/) to previous
|
|
2482
|
-
// then filter out GLOBSTAR symbols
|
|
2483
|
-
let re = set
|
|
2484
|
-
.map(pattern => {
|
|
2485
|
-
const pp = pattern.map(p => {
|
|
2486
|
-
if (p instanceof RegExp) {
|
|
2487
|
-
for (const f of p.flags.split(''))
|
|
2488
|
-
flags.add(f);
|
|
2489
|
-
}
|
|
2490
|
-
return (typeof p === 'string' ? regExpEscape(p)
|
|
2491
|
-
: p === exports.GLOBSTAR ? exports.GLOBSTAR
|
|
2492
|
-
: p._src);
|
|
2493
|
-
});
|
|
2494
|
-
pp.forEach((p, i) => {
|
|
2495
|
-
const next = pp[i + 1];
|
|
2496
|
-
const prev = pp[i - 1];
|
|
2497
|
-
if (p !== exports.GLOBSTAR || prev === exports.GLOBSTAR) {
|
|
2498
|
-
return;
|
|
2499
|
-
}
|
|
2500
|
-
if (prev === undefined) {
|
|
2501
|
-
if (next !== undefined && next !== exports.GLOBSTAR) {
|
|
2502
|
-
pp[i + 1] = '(?:\\/|' + twoStar + '\\/)?' + next;
|
|
2503
|
-
}
|
|
2504
|
-
else {
|
|
2505
|
-
pp[i] = twoStar;
|
|
2506
|
-
}
|
|
2507
|
-
}
|
|
2508
|
-
else if (next === undefined) {
|
|
2509
|
-
pp[i - 1] = prev + '(?:\\/|\\/' + twoStar + ')?';
|
|
2510
|
-
}
|
|
2511
|
-
else if (next !== exports.GLOBSTAR) {
|
|
2512
|
-
pp[i - 1] = prev + '(?:\\/|\\/' + twoStar + '\\/)' + next;
|
|
2513
|
-
pp[i + 1] = exports.GLOBSTAR;
|
|
2514
|
-
}
|
|
2515
|
-
});
|
|
2516
|
-
const filtered = pp.filter(p => p !== exports.GLOBSTAR);
|
|
2517
|
-
// For partial matches, we need to make the pattern match
|
|
2518
|
-
// any prefix of the full path. We do this by generating
|
|
2519
|
-
// alternative patterns that match progressively longer prefixes.
|
|
2520
|
-
if (this.partial && filtered.length >= 1) {
|
|
2521
|
-
const prefixes = [];
|
|
2522
|
-
for (let i = 1; i <= filtered.length; i++) {
|
|
2523
|
-
prefixes.push(filtered.slice(0, i).join('/'));
|
|
2524
|
-
}
|
|
2525
|
-
return '(?:' + prefixes.join('|') + ')';
|
|
2526
|
-
}
|
|
2527
|
-
return filtered.join('/');
|
|
2528
|
-
})
|
|
2529
|
-
.join('|');
|
|
2530
|
-
// need to wrap in parens if we had more than one thing with |,
|
|
2531
|
-
// otherwise only the first will be anchored to ^ and the last to $
|
|
2532
|
-
const [open, close] = set.length > 1 ? ['(?:', ')'] : ['', ''];
|
|
2533
|
-
// must match entire pattern
|
|
2534
|
-
// ending in a * or ** will make it less strict.
|
|
2535
|
-
re = '^' + open + re + close + '$';
|
|
2536
|
-
// In partial mode, '/' should always match as it's a valid prefix for any pattern
|
|
2537
|
-
if (this.partial) {
|
|
2538
|
-
re = '^(?:\\/|' + open + re.slice(1, -1) + close + ')$';
|
|
2539
|
-
}
|
|
2540
|
-
// can match anything, as long as it's not this.
|
|
2541
|
-
if (this.negate)
|
|
2542
|
-
re = '^(?!' + re + ').+$';
|
|
2543
|
-
try {
|
|
2544
|
-
this.regexp = new RegExp(re, [...flags].join(''));
|
|
2545
|
-
/* c8 ignore start */
|
|
2546
|
-
}
|
|
2547
|
-
catch {
|
|
2548
|
-
// should be impossible
|
|
2549
|
-
this.regexp = false;
|
|
2550
|
-
}
|
|
2551
|
-
/* c8 ignore stop */
|
|
2552
|
-
return this.regexp;
|
|
2553
|
-
}
|
|
2554
|
-
slashSplit(p) {
|
|
2555
|
-
// if p starts with // on windows, we preserve that
|
|
2556
|
-
// so that UNC paths aren't broken. Otherwise, any number of
|
|
2557
|
-
// / characters are coalesced into one, unless
|
|
2558
|
-
// preserveMultipleSlashes is set to true.
|
|
2559
|
-
if (this.preserveMultipleSlashes) {
|
|
2560
|
-
return p.split('/');
|
|
2561
|
-
}
|
|
2562
|
-
else if (this.isWindows && /^\/\/[^/]+/.test(p)) {
|
|
2563
|
-
// add an extra '' for the one we lose
|
|
2564
|
-
return ['', ...p.split(/\/+/)];
|
|
2565
|
-
}
|
|
2566
|
-
else {
|
|
2567
|
-
return p.split(/\/+/);
|
|
2568
|
-
}
|
|
2569
|
-
}
|
|
2570
|
-
match(f, partial = this.partial) {
|
|
2571
|
-
this.debug('match', f, this.pattern);
|
|
2572
|
-
// short-circuit in the case of busted things.
|
|
2573
|
-
// comments, etc.
|
|
2574
|
-
if (this.comment) {
|
|
2575
|
-
return false;
|
|
2576
|
-
}
|
|
2577
|
-
if (this.empty) {
|
|
2578
|
-
return f === '';
|
|
2579
|
-
}
|
|
2580
|
-
if (f === '/' && partial) {
|
|
2581
|
-
return true;
|
|
2582
|
-
}
|
|
2583
|
-
const options = this.options;
|
|
2584
|
-
// windows: need to use /, not \
|
|
2585
|
-
if (this.isWindows) {
|
|
2586
|
-
f = f.split('\\').join('/');
|
|
2587
|
-
}
|
|
2588
|
-
// treat the test path as a set of pathparts.
|
|
2589
|
-
const ff = this.slashSplit(f);
|
|
2590
|
-
this.debug(this.pattern, 'split', ff);
|
|
2591
|
-
// just ONE of the pattern sets in this.set needs to match
|
|
2592
|
-
// in order for it to be valid. If negating, then just one
|
|
2593
|
-
// match means that we have failed.
|
|
2594
|
-
// Either way, return on the first hit.
|
|
2595
|
-
const set = this.set;
|
|
2596
|
-
this.debug(this.pattern, 'set', set);
|
|
2597
|
-
// Find the basename of the path by looking for the last non-empty segment
|
|
2598
|
-
let filename = ff[ff.length - 1];
|
|
2599
|
-
if (!filename) {
|
|
2600
|
-
for (let i = ff.length - 2; !filename && i >= 0; i--) {
|
|
2601
|
-
filename = ff[i];
|
|
2602
|
-
}
|
|
2603
|
-
}
|
|
2604
|
-
for (const pattern of set) {
|
|
2605
|
-
let file = ff;
|
|
2606
|
-
if (options.matchBase && pattern.length === 1) {
|
|
2607
|
-
file = [filename];
|
|
2608
|
-
}
|
|
2609
|
-
const hit = this.matchOne(file, pattern, partial);
|
|
2610
|
-
if (hit) {
|
|
2611
|
-
if (options.flipNegate) {
|
|
2612
|
-
return true;
|
|
2613
|
-
}
|
|
2614
|
-
return !this.negate;
|
|
2615
|
-
}
|
|
2616
|
-
}
|
|
2617
|
-
// didn't get any hits. this is success if it's a negative
|
|
2618
|
-
// pattern, failure otherwise.
|
|
2619
|
-
if (options.flipNegate) {
|
|
2620
|
-
return false;
|
|
2621
|
-
}
|
|
2622
|
-
return this.negate;
|
|
2623
|
-
}
|
|
2624
|
-
static defaults(def) {
|
|
2625
|
-
return exports.minimatch.defaults(def).Minimatch;
|
|
2626
|
-
}
|
|
2627
|
-
}
|
|
2628
|
-
exports.Minimatch = Minimatch;
|
|
2629
|
-
/* c8 ignore start */
|
|
2630
|
-
var ast_js_2 = requireAst();
|
|
2631
|
-
Object.defineProperty(exports, "AST", { enumerable: true, get: function () { return ast_js_2.AST; } });
|
|
2632
|
-
var escape_js_2 = require_escape();
|
|
2633
|
-
Object.defineProperty(exports, "escape", { enumerable: true, get: function () { return escape_js_2.escape; } });
|
|
2634
|
-
var unescape_js_2 = require_unescape();
|
|
2635
|
-
Object.defineProperty(exports, "unescape", { enumerable: true, get: function () { return unescape_js_2.unescape; } });
|
|
2636
|
-
/* c8 ignore stop */
|
|
2637
|
-
exports.minimatch.AST = ast_js_1.AST;
|
|
2638
|
-
exports.minimatch.Minimatch = Minimatch;
|
|
2639
|
-
exports.minimatch.escape = escape_js_1.escape;
|
|
2640
|
-
exports.minimatch.unescape = unescape_js_1.unescape;
|
|
2641
|
-
|
|
2642
|
-
} (commonjs$2));
|
|
2643
|
-
return commonjs$2;
|
|
1506
|
+
for (let i = 0; i < set.length; i++) {
|
|
1507
|
+
const pattern = set[i];
|
|
1508
|
+
let file = f;
|
|
1509
|
+
if (options.matchBase && pattern.length === 1) {
|
|
1510
|
+
file = [filename];
|
|
1511
|
+
}
|
|
1512
|
+
const hit = this.matchOne(file, pattern, partial);
|
|
1513
|
+
if (hit) {
|
|
1514
|
+
if (options.flipNegate) return true
|
|
1515
|
+
return !this.negate
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
// didn't get any hits. this is success if it's a negative
|
|
1520
|
+
// pattern, failure otherwise.
|
|
1521
|
+
if (options.flipNegate) return false
|
|
1522
|
+
return this.negate
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
static defaults (def) {
|
|
1526
|
+
return minimatch.defaults(def).Minimatch
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
minimatch.Minimatch = Minimatch;
|
|
1531
|
+
return minimatch_1;
|
|
2644
1532
|
}
|
|
2645
1533
|
|
|
2646
1534
|
var jsYaml$1 = {};
|
|
@@ -3760,7 +2648,7 @@ function requireOmap$1 () {
|
|
|
3760
2648
|
function resolveYamlOmap (data) {
|
|
3761
2649
|
if (data === null) return true
|
|
3762
2650
|
|
|
3763
|
-
const objectKeys =
|
|
2651
|
+
const objectKeys = {};
|
|
3764
2652
|
const object = data;
|
|
3765
2653
|
|
|
3766
2654
|
for (let index = 0, length = object.length; index < length; index += 1) {
|
|
@@ -3779,8 +2667,8 @@ function requireOmap$1 () {
|
|
|
3779
2667
|
|
|
3780
2668
|
if (!pairHasKey) return false
|
|
3781
2669
|
|
|
3782
|
-
if (
|
|
3783
|
-
|
|
2670
|
+
if (_hasOwnProperty.call(objectKeys, pairKey)) return false
|
|
2671
|
+
Object.defineProperty(objectKeys, pairKey, { value: true });
|
|
3784
2672
|
}
|
|
3785
2673
|
|
|
3786
2674
|
return true
|
|
@@ -4292,19 +3180,28 @@ function requireLoader$1 () {
|
|
|
4292
3180
|
}
|
|
4293
3181
|
}
|
|
4294
3182
|
|
|
3183
|
+
function chargeMergeWork (state) {
|
|
3184
|
+
state.totalMergeKeys++;
|
|
3185
|
+
|
|
3186
|
+
if (state.maxTotalMergeKeys !== -1 && state.totalMergeKeys > state.maxTotalMergeKeys) {
|
|
3187
|
+
throwError(state, 'merge keys exceeded maxTotalMergeKeys (' + state.maxTotalMergeKeys + ')');
|
|
3188
|
+
}
|
|
3189
|
+
}
|
|
3190
|
+
|
|
4295
3191
|
function mergeMappings (state, destination, source, overridableKeys) {
|
|
4296
3192
|
if (!common.isObject(source)) {
|
|
4297
3193
|
throwError(state, 'cannot merge mappings; the provided source object is unacceptable');
|
|
4298
3194
|
}
|
|
4299
3195
|
|
|
3196
|
+
// Count the source mapping itself to bound sequences of empty mappings.
|
|
3197
|
+
chargeMergeWork(state);
|
|
3198
|
+
|
|
4300
3199
|
const sourceKeys = Object.keys(source);
|
|
4301
3200
|
|
|
4302
3201
|
for (let index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {
|
|
4303
3202
|
const key = sourceKeys[index];
|
|
4304
3203
|
|
|
4305
|
-
|
|
4306
|
-
throwError(state, 'merge keys exceeded maxTotalMergeKeys (' + state.maxTotalMergeKeys + ')');
|
|
4307
|
-
}
|
|
3204
|
+
chargeMergeWork(state);
|
|
4308
3205
|
|
|
4309
3206
|
if (!_hasOwnProperty.call(destination, key)) {
|
|
4310
3207
|
setProperty(destination, key, source[key]);
|
|
@@ -4347,6 +3244,10 @@ function requireLoader$1 () {
|
|
|
4347
3244
|
|
|
4348
3245
|
if (keyTag === 'tag:yaml.org,2002:merge') {
|
|
4349
3246
|
if (Array.isArray(valueNode)) {
|
|
3247
|
+
if (valueNode.length > 100) {
|
|
3248
|
+
throwError(state, 'abnormal merge sequence size');
|
|
3249
|
+
}
|
|
3250
|
+
|
|
4350
3251
|
for (let index = 0, quantity = valueNode.length; index < quantity; index += 1) {
|
|
4351
3252
|
mergeMappings(state, _result, valueNode[index], overridableKeys);
|
|
4352
3253
|
}
|
|
@@ -9099,7 +8000,7 @@ function requireUtils$3 () {
|
|
|
9099
8000
|
exports.dequal = dequal;
|
|
9100
8001
|
const fs = require$$0$5;
|
|
9101
8002
|
const path_1 = require$$1$4;
|
|
9102
|
-
const minimatch =
|
|
8003
|
+
const minimatch = requireMinimatch();
|
|
9103
8004
|
const js_yaml_1 = requireJsYaml();
|
|
9104
8005
|
const env_1 = requireEnv();
|
|
9105
8006
|
const logger_1 = requireLogger();
|
|
@@ -13464,10 +12365,6 @@ const navItemSchema = {
|
|
|
13464
12365
|
},
|
|
13465
12366
|
// Allow users to eject the navbar and implement additional levels of nesting
|
|
13466
12367
|
items: { type: 'array', items: { type: 'object', additionalProperties: true } },
|
|
13467
|
-
rbac: {
|
|
13468
|
-
type: 'object',
|
|
13469
|
-
additionalProperties: { type: 'string' },
|
|
13470
|
-
},
|
|
13471
12368
|
},
|
|
13472
12369
|
};
|
|
13473
12370
|
const navItemsSchema = {
|
|
@@ -14745,7 +13642,9 @@ function requireOasTypes () {
|
|
|
14745
13642
|
if (typeof root.openapi === 'string' && root.openapi.startsWith('3.0')) {
|
|
14746
13643
|
return SpecVersion.OAS3_0;
|
|
14747
13644
|
}
|
|
14748
|
-
if (typeof root.openapi === 'string' &&
|
|
13645
|
+
if (typeof root.openapi === 'string' &&
|
|
13646
|
+
(root.openapi.startsWith('3.1') || root.openapi.startsWith('3.2')) // temporary support for 3.2
|
|
13647
|
+
) {
|
|
14749
13648
|
return SpecVersion.OAS3_1;
|
|
14750
13649
|
}
|
|
14751
13650
|
if (root.swagger && root.swagger === '2.0') {
|
|
@@ -30807,7 +29706,7 @@ var redocly = {};
|
|
|
30807
29706
|
var registryApi = {};
|
|
30808
29707
|
|
|
30809
29708
|
const name = "@redocly/openapi-core";
|
|
30810
|
-
const version = "1.34.
|
|
29709
|
+
const version = "1.34.19";
|
|
30811
29710
|
const description = "";
|
|
30812
29711
|
const main = "lib/index.js";
|
|
30813
29712
|
const engines = {
|
|
@@ -30842,14 +29741,14 @@ const contributors = [
|
|
|
30842
29741
|
"Roman Hotsiy <roman@redocly.com> (https://redocly.com/)"
|
|
30843
29742
|
];
|
|
30844
29743
|
const dependencies = {
|
|
30845
|
-
"@redocly/ajv": "
|
|
30846
|
-
"@redocly/config": "
|
|
30847
|
-
colorette: "
|
|
30848
|
-
"https-proxy-agent": "
|
|
30849
|
-
"js-levenshtein": "
|
|
30850
|
-
"js-yaml": "
|
|
30851
|
-
minimatch: "
|
|
30852
|
-
pluralize: "
|
|
29744
|
+
"@redocly/ajv": "8.11.2",
|
|
29745
|
+
"@redocly/config": "0.22.0",
|
|
29746
|
+
colorette: "1.4.0",
|
|
29747
|
+
"https-proxy-agent": "7.0.6",
|
|
29748
|
+
"js-levenshtein": "1.1.6",
|
|
29749
|
+
"js-yaml": "4.3.1",
|
|
29750
|
+
minimatch: "5.1.9",
|
|
29751
|
+
pluralize: "8.0.0",
|
|
30853
29752
|
"yaml-ast-parser": "0.0.43"
|
|
30854
29753
|
};
|
|
30855
29754
|
const devDependencies = {
|