vite-plugin-vue-devtools 0.4.10 → 0.4.11

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.
Files changed (40) hide show
  1. package/README.md +9 -2
  2. package/dist/client/assets/{IframeView.vue_vue_type_script_setup_true_lang-e86027e5.js → IframeView.vue_vue_type_script_setup_true_lang-fd720d18.js} +1 -1
  3. package/dist/client/assets/{StateFields.vue_vue_type_script_setup_true_lang-a78e5cb0.js → StateFields.vue_vue_type_script_setup_true_lang-0e4af331.js} +8 -8
  4. package/dist/client/assets/{VIcon.vue_vue_type_script_setup_true_lang-82a30fea.js → VIcon.vue_vue_type_script_setup_true_lang-d1646658.js} +1 -1
  5. package/dist/client/assets/{VIconButton.vue_vue_type_script_setup_true_lang-fe1578eb.js → VIconButton.vue_vue_type_script_setup_true_lang-5c7fa25b.js} +2 -2
  6. package/dist/client/assets/{VIconTitle.vue_vue_type_script_setup_true_lang-53c720d3.js → VIconTitle.vue_vue_type_script_setup_true_lang-3af9d81d.js} +1 -1
  7. package/dist/client/assets/{VPanelGrids-dc69b639.js → VPanelGrids-08ef47ce.js} +1 -1
  8. package/dist/client/assets/{VSectionBlock-57ec7b68.js → VSectionBlock-44a9204b.js} +3 -3
  9. package/dist/client/assets/VSwitch.vue_vue_type_script_setup_true_lang-b1b6daad.js +88 -0
  10. package/dist/client/assets/{VTextInput.vue_vue_type_script_setup_true_lang-c7c2878d.js → VTextInput.vue_vue_type_script_setup_true_lang-4df2a1eb.js} +2 -2
  11. package/dist/client/assets/{__eyedropper-c3a23916.js → __eyedropper-9aeb7406.js} +2 -2
  12. package/dist/client/assets/{assets-2b8518ac.js → assets-4ff4283a.js} +17 -10
  13. package/dist/client/assets/component-docs-1e5f0727.js +1748 -0
  14. package/dist/client/assets/{components-433e30b5.js → components-5011f272.js} +7 -7
  15. package/dist/client/assets/{documentations-a41234ba.js → documentations-ec90fa66.js} +3 -3
  16. package/dist/client/assets/{graph-d61217d6.js → graph-c8cae02e.js} +2422 -61
  17. package/dist/client/assets/{index-07396aec.js → index-37b80b18.js} +1 -1
  18. package/dist/client/assets/{index-b8a9099c.js → index-793e4620.js} +1019 -2617
  19. package/dist/client/assets/index-ee2ca8be.css +474 -0
  20. package/dist/client/assets/{inspect-2b7bf157.js → inspect-c464cac5.js} +3 -3
  21. package/dist/client/assets/{npm-125f4259.css → npm-832f3f2c.css} +20 -2
  22. package/dist/client/assets/npm-de038c5b.js +537 -0
  23. package/dist/client/assets/{overview-95247458.js → overview-fc79467d.js} +5 -5
  24. package/dist/client/assets/{pages-72e88bdb.js → pages-d51e51ec.js} +5 -5
  25. package/dist/client/assets/{pinia-55c3fcd8.js → pinia-e230dd12.js} +6 -6
  26. package/dist/client/assets/{routes-ab38a14f.js → routes-7d3d04cf.js} +7 -7
  27. package/dist/client/assets/{rpc-cf3bd0fc.js → rpc-d8afe028.js} +1 -1
  28. package/dist/client/assets/{settings-c390240d.js → settings-2e4656aa.js} +36 -119
  29. package/dist/client/assets/{splitpanes.es-dd27b7fe.js → splitpanes.es-8a68d356.js} +1 -1
  30. package/dist/client/assets/{timeline-5fa02442.js → timeline-202ca852.js} +8 -8
  31. package/dist/client/index.html +2 -2
  32. package/dist/index.cjs +1238 -1162
  33. package/dist/index.mjs +1235 -1159
  34. package/package.json +35 -31
  35. package/src/node/views/Main.vue +9 -2
  36. package/src/node/views/composables.ts +26 -1
  37. package/src/node/views/utils.ts +4 -0
  38. package/dist/client/assets/component-docs-e06030af.js +0 -1748
  39. package/dist/client/assets/index-5221558c.css +0 -472
  40. package/dist/client/assets/npm-62fb6b03.js +0 -537
@@ -1,104 +1,2376 @@
1
- import { a$ as ref, ch as useStorage, a1 as computed, v as defineComponent, o as openBlock, e as createElementBlock, d as withDirectives, bu as vModelText, z as unref, x as createBaseVNode, aC as isRef, bq as vModelCheckbox, ci as useDark, aP as onMounted, by as watch, u as createVNode } from './index-b8a9099c.js';
1
+ import { a$ as ref, ch as useLocalStorage, a1 as computed, aN as onDeactivated, aL as onBeforeUnmount, v as defineComponent, o as openBlock, c as createBlock, h as withCtx, x as createBaseVNode, e as createElementBlock, i as renderList, F as Fragment, z as unref, aC as isRef, bM as _sfc_main$3, y as toDisplayString, g as createCommentVNode, j as resolveDynamicComponent, u as createVNode, aF as isVNode, ci as useStorage, d as withDirectives, bu as vModelText, bq as vModelCheckbox, f as renderSlot, cj as useDark, b8 as shallowRef, ck as useMagicKeys, aP as onMounted, by as watch, q as normalizeClass, cl as useDevtoolsClient } from './index-793e4620.js';
2
+ import { a as _sfc_main$4, _ as _sfc_main$5 } from './VSwitch.vue_vue_type_script_setup_true_lang-b1b6daad.js';
2
3
  import { F as Fuse } from './fuse.esm-c317b696.js';
3
- import { r as rpc } from './rpc-cf3bd0fc.js';
4
+ import { g as getDefaultExportFromCjs$2 } from './_commonjsHelpers-65004790.js';
5
+ import { r as rpc } from './rpc-d8afe028.js';
6
+ import './VIcon.vue_vue_type_script_setup_true_lang-d1646658.js';
7
+
8
+ const showGraphSetting = ref(false);
9
+ const graphSettingsInStorage = useLocalStorage("__vue-devtools-graph-settings__", {
10
+ hoverPathLevel: "root",
11
+ hoverPathLevelCustom: 4,
12
+ clickOpenInEditor: true,
13
+ highlightSelection: true,
14
+ enableUserDefinedGlob: false
15
+ }, { mergeDefaults: true });
16
+ const graphSettings$1 = computed(() => graphSettingsInStorage.value);
17
+ function useGraphSettings() {
18
+ onDeactivated(() => showGraphSetting.value = false);
19
+ onBeforeUnmount(() => showGraphSetting.value = false);
20
+ return {
21
+ showGraphSetting,
22
+ graphSettings: graphSettings$1
23
+ };
24
+ }
25
+
26
+ /* Injected with object hook! */
27
+
28
+ const _hoisted_1$2 = {
29
+ flex: "~",
30
+ "items-center": "",
31
+ "justify-between": ""
32
+ };
33
+ const _hoisted_2$2 = /*#__PURE__*/createBaseVNode("h1", {
34
+ m: "!0",
35
+ "text-2xl": ""
36
+ }, " Graph Settings ", -1);
37
+ const _hoisted_3$2 = {
38
+ "aria-label": "Close graph settings"
39
+ };
40
+ const _hoisted_4$1 = {
41
+ flex: "~ col",
42
+ gap4: ""
43
+ };
44
+ const _hoisted_5$1 = {
45
+ flex: "~ col",
46
+ "gap-5px": ""
47
+ };
48
+ const _hoisted_6$1 = {
49
+ "text-4": ""
50
+ };
51
+ const _hoisted_7$1 = {
52
+ key: 0,
53
+ "text-sm": "",
54
+ "text-secondary": ""
55
+ };
56
+ const _hoisted_8$1 = {
57
+ flex: "",
58
+ "gap-1": ""
59
+ };
60
+ function _isSlot(s) {
61
+ return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
62
+ }
63
+ const _sfc_main$2 = /*#__PURE__*/defineComponent({
64
+ __name: 'GraphSettings',
65
+ setup(__props) {
66
+ const {
67
+ showGraphSetting,
68
+ graphSettings
69
+ } = useGraphSettings();
70
+ const graphHoverPathLevel = [['Root in vite config', 'root'], ['Custom level', 'custom'], ['Absolute', 'absolute']];
71
+ const graphHoverPathLevelCustom = [['2', 2], ['3', 3], ['4', 4], ['5', 5], ['6', 6]];
72
+ const settings = [{
73
+ name: 'Path level',
74
+ description: 'Display the path level of the hovered node',
75
+ comp: () => {
76
+ let _slot, _slot2;
77
+ return createVNode(Fragment, null, [createVNode(_sfc_main$4, {
78
+ "modelValue": graphSettings.value.hoverPathLevel,
79
+ "onUpdate:modelValue": $event => graphSettings.value.hoverPathLevel = $event,
80
+ "class": "n-primary"
81
+ }, _isSlot(_slot = graphHoverPathLevel.map(([key, value]) => createVNode("option", {
82
+ "key": key
83
+ }, [value]))) ? _slot : {
84
+ default: () => [_slot]
85
+ }), graphSettings.value.hoverPathLevel === 'custom' && createVNode(_sfc_main$4, {
86
+ "modelValue": graphSettings.value.hoverPathLevelCustom,
87
+ "onUpdate:modelValue": $event => graphSettings.value.hoverPathLevelCustom = $event,
88
+ "class": "n-primary"
89
+ }, _isSlot(_slot2 = graphHoverPathLevelCustom.map(([key, value]) => createVNode("option", {
90
+ "key": key
91
+ }, [value]))) ? _slot2 : {
92
+ default: () => [_slot2]
93
+ })]);
94
+ }
95
+ }, {
96
+ name: 'Open in editor',
97
+ description: 'Press Alt/Cmd + click on a node to open the file in editor',
98
+ comp: () => createVNode(_sfc_main$5, {
99
+ "modelValue": graphSettings.value.clickOpenInEditor,
100
+ "onUpdate:modelValue": $event => graphSettings.value.clickOpenInEditor = $event,
101
+ "class": "n-primary"
102
+ }, null)
103
+ }, {
104
+ name: 'Highlight related node',
105
+ description: 'Highlight the directly related node when clicking on a node',
106
+ comp: () => createVNode(_sfc_main$5, {
107
+ "modelValue": graphSettings.value.highlightSelection,
108
+ "onUpdate:modelValue": $event => graphSettings.value.highlightSelection = $event,
109
+ "class": "n-primary"
110
+ }, null)
111
+ }, {
112
+ name: 'Glob pattern',
113
+ description: 'Enable glob pattern to pre-filter modules. Use dot + space(", ") to separate multiple patterns.',
114
+ comp: () => createVNode(_sfc_main$5, {
115
+ "modelValue": graphSettings.value.enableUserDefinedGlob,
116
+ "onUpdate:modelValue": $event => graphSettings.value.enableUserDefinedGlob = $event,
117
+ "class": "n-primary"
118
+ }, null)
119
+ }];
120
+ return (_ctx, _cache) => {
121
+ const _component_VDialog = _sfc_main$3;
122
+ return openBlock(), createBlock(_component_VDialog, {
123
+ modelValue: unref(showGraphSetting),
124
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = $event => isRef(showGraphSetting) ? showGraphSetting.value = $event : null),
125
+ class: "z-2000 min-w-500px w-50vw flex flex-col gap6 p6",
126
+ onClose: _cache[2] || (_cache[2] = $event => showGraphSetting.value = false)
127
+ }, {
128
+ default: withCtx(() => [createBaseVNode("div", _hoisted_1$2, [_hoisted_2$2, createBaseVNode("button", _hoisted_3$2, [createBaseVNode("div", {
129
+ "i-carbon-close": "",
130
+ "text-2xl": "",
131
+ hover: "color-primary",
132
+ "transition-colors": "",
133
+ onClick: _cache[0] || (_cache[0] = $event => showGraphSetting.value = false)
134
+ })])]), createBaseVNode("div", _hoisted_4$1, [(openBlock(), createElementBlock(Fragment, null, renderList(settings, setting => {
135
+ return createBaseVNode("div", {
136
+ key: setting.name,
137
+ flex: "~",
138
+ "items-center": "",
139
+ "justify-between": ""
140
+ }, [createBaseVNode("div", _hoisted_5$1, [createBaseVNode("p", _hoisted_6$1, toDisplayString(setting.name), 1), setting.description ? (openBlock(), createElementBlock("p", _hoisted_7$1, toDisplayString(setting.description), 1)) : createCommentVNode("", true)]), createBaseVNode("div", _hoisted_8$1, [(openBlock(), createBlock(resolveDynamicComponent(setting.comp)))])]);
141
+ }), 64))])]),
142
+ _: 1
143
+ }, 8, ["modelValue"]);
144
+ };
145
+ }
146
+ });
147
+ /* Injected with object hook! */
148
+
149
+ var balancedMatch = balanced$1;
150
+ function balanced$1(a, b, str) {
151
+ if (a instanceof RegExp) a = maybeMatch(a, str);
152
+ if (b instanceof RegExp) b = maybeMatch(b, str);
153
+
154
+ var r = range(a, b, str);
155
+
156
+ return r && {
157
+ start: r[0],
158
+ end: r[1],
159
+ pre: str.slice(0, r[0]),
160
+ body: str.slice(r[0] + a.length, r[1]),
161
+ post: str.slice(r[1] + b.length)
162
+ };
163
+ }
164
+
165
+ function maybeMatch(reg, str) {
166
+ var m = str.match(reg);
167
+ return m ? m[0] : null;
168
+ }
169
+
170
+ balanced$1.range = range;
171
+ function range(a, b, str) {
172
+ var begs, beg, left, right, result;
173
+ var ai = str.indexOf(a);
174
+ var bi = str.indexOf(b, ai + 1);
175
+ var i = ai;
176
+
177
+ if (ai >= 0 && bi > 0) {
178
+ if(a===b) {
179
+ return [ai, bi];
180
+ }
181
+ begs = [];
182
+ left = str.length;
183
+
184
+ while (i >= 0 && !result) {
185
+ if (i == ai) {
186
+ begs.push(i);
187
+ ai = str.indexOf(a, i + 1);
188
+ } else if (begs.length == 1) {
189
+ result = [ begs.pop(), bi ];
190
+ } else {
191
+ beg = begs.pop();
192
+ if (beg < left) {
193
+ left = beg;
194
+ right = bi;
195
+ }
196
+
197
+ bi = str.indexOf(b, i + 1);
198
+ }
199
+
200
+ i = ai < bi && ai >= 0 ? ai : bi;
201
+ }
202
+
203
+ if (begs.length) {
204
+ result = [ left, right ];
205
+ }
206
+ }
207
+
208
+ return result;
209
+ }
210
+ /* Injected with object hook! */
211
+
212
+ var balanced = balancedMatch;
213
+
214
+ var braceExpansion = expandTop;
215
+
216
+ var escSlash = '\0SLASH'+Math.random()+'\0';
217
+ var escOpen = '\0OPEN'+Math.random()+'\0';
218
+ var escClose = '\0CLOSE'+Math.random()+'\0';
219
+ var escComma = '\0COMMA'+Math.random()+'\0';
220
+ var escPeriod = '\0PERIOD'+Math.random()+'\0';
221
+
222
+ function numeric(str) {
223
+ return parseInt(str, 10) == str
224
+ ? parseInt(str, 10)
225
+ : str.charCodeAt(0);
226
+ }
227
+
228
+ function escapeBraces(str) {
229
+ return str.split('\\\\').join(escSlash)
230
+ .split('\\{').join(escOpen)
231
+ .split('\\}').join(escClose)
232
+ .split('\\,').join(escComma)
233
+ .split('\\.').join(escPeriod);
234
+ }
235
+
236
+ function unescapeBraces(str) {
237
+ return str.split(escSlash).join('\\')
238
+ .split(escOpen).join('{')
239
+ .split(escClose).join('}')
240
+ .split(escComma).join(',')
241
+ .split(escPeriod).join('.');
242
+ }
243
+
244
+
245
+ // Basically just str.split(","), but handling cases
246
+ // where we have nested braced sections, which should be
247
+ // treated as individual members, like {a,{b,c},d}
248
+ function parseCommaParts(str) {
249
+ if (!str)
250
+ return [''];
251
+
252
+ var parts = [];
253
+ var m = balanced('{', '}', str);
254
+
255
+ if (!m)
256
+ return str.split(',');
257
+
258
+ var pre = m.pre;
259
+ var body = m.body;
260
+ var post = m.post;
261
+ var p = pre.split(',');
262
+
263
+ p[p.length-1] += '{' + body + '}';
264
+ var postParts = parseCommaParts(post);
265
+ if (post.length) {
266
+ p[p.length-1] += postParts.shift();
267
+ p.push.apply(p, postParts);
268
+ }
269
+
270
+ parts.push.apply(parts, p);
271
+
272
+ return parts;
273
+ }
274
+
275
+ function expandTop(str) {
276
+ if (!str)
277
+ return [];
278
+
279
+ // I don't know why Bash 4.3 does this, but it does.
280
+ // Anything starting with {} will have the first two bytes preserved
281
+ // but *only* at the top level, so {},a}b will not expand to anything,
282
+ // but a{},b}c will be expanded to [a}c,abc].
283
+ // One could argue that this is a bug in Bash, but since the goal of
284
+ // this module is to match Bash's rules, we escape a leading {}
285
+ if (str.substr(0, 2) === '{}') {
286
+ str = '\\{\\}' + str.substr(2);
287
+ }
288
+
289
+ return expand(escapeBraces(str), true).map(unescapeBraces);
290
+ }
291
+
292
+ function embrace(str) {
293
+ return '{' + str + '}';
294
+ }
295
+ function isPadded(el) {
296
+ return /^-?0\d/.test(el);
297
+ }
298
+
299
+ function lte(i, y) {
300
+ return i <= y;
301
+ }
302
+ function gte(i, y) {
303
+ return i >= y;
304
+ }
305
+
306
+ function expand(str, isTop) {
307
+ var expansions = [];
308
+
309
+ var m = balanced('{', '}', str);
310
+ if (!m) return [str];
311
+
312
+ // no need to expand pre, since it is guaranteed to be free of brace-sets
313
+ var pre = m.pre;
314
+ var post = m.post.length
315
+ ? expand(m.post, false)
316
+ : [''];
317
+
318
+ if (/\$$/.test(m.pre)) {
319
+ for (var k = 0; k < post.length; k++) {
320
+ var expansion = pre+ '{' + m.body + '}' + post[k];
321
+ expansions.push(expansion);
322
+ }
323
+ } else {
324
+ var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
325
+ var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
326
+ var isSequence = isNumericSequence || isAlphaSequence;
327
+ var isOptions = m.body.indexOf(',') >= 0;
328
+ if (!isSequence && !isOptions) {
329
+ // {a},b}
330
+ if (m.post.match(/,.*\}/)) {
331
+ str = m.pre + '{' + m.body + escClose + m.post;
332
+ return expand(str);
333
+ }
334
+ return [str];
335
+ }
336
+
337
+ var n;
338
+ if (isSequence) {
339
+ n = m.body.split(/\.\./);
340
+ } else {
341
+ n = parseCommaParts(m.body);
342
+ if (n.length === 1) {
343
+ // x{{a,b}}y ==> x{a}y x{b}y
344
+ n = expand(n[0], false).map(embrace);
345
+ if (n.length === 1) {
346
+ return post.map(function(p) {
347
+ return m.pre + n[0] + p;
348
+ });
349
+ }
350
+ }
351
+ }
352
+
353
+ // at this point, n is the parts, and we know it's not a comma set
354
+ // with a single entry.
355
+ var N;
356
+
357
+ if (isSequence) {
358
+ var x = numeric(n[0]);
359
+ var y = numeric(n[1]);
360
+ var width = Math.max(n[0].length, n[1].length);
361
+ var incr = n.length == 3
362
+ ? Math.abs(numeric(n[2]))
363
+ : 1;
364
+ var test = lte;
365
+ var reverse = y < x;
366
+ if (reverse) {
367
+ incr *= -1;
368
+ test = gte;
369
+ }
370
+ var pad = n.some(isPadded);
371
+
372
+ N = [];
373
+
374
+ for (var i = x; test(i, y); i += incr) {
375
+ var c;
376
+ if (isAlphaSequence) {
377
+ c = String.fromCharCode(i);
378
+ if (c === '\\')
379
+ c = '';
380
+ } else {
381
+ c = String(i);
382
+ if (pad) {
383
+ var need = width - c.length;
384
+ if (need > 0) {
385
+ var z = new Array(need + 1).join('0');
386
+ if (i < 0)
387
+ c = '-' + z + c.slice(1);
388
+ else
389
+ c = z + c;
390
+ }
391
+ }
392
+ }
393
+ N.push(c);
394
+ }
395
+ } else {
396
+ N = [];
397
+
398
+ for (var j = 0; j < n.length; j++) {
399
+ N.push.apply(N, expand(n[j], false));
400
+ }
401
+ }
402
+
403
+ for (var j = 0; j < N.length; j++) {
404
+ for (var k = 0; k < post.length; k++) {
405
+ var expansion = pre + N[j] + post[k];
406
+ if (!isTop || isSequence || expansion)
407
+ expansions.push(expansion);
408
+ }
409
+ }
410
+ }
411
+
412
+ return expansions;
413
+ }
414
+
415
+ const expand$1 = /*@__PURE__*/getDefaultExportFromCjs$2(braceExpansion);
416
+ /* Injected with object hook! */
417
+
418
+ const MAX_PATTERN_LENGTH = 1024 * 64;
419
+ const assertValidPattern = (pattern) => {
420
+ if (typeof pattern !== 'string') {
421
+ throw new TypeError('invalid pattern');
422
+ }
423
+ if (pattern.length > MAX_PATTERN_LENGTH) {
424
+ throw new TypeError('pattern is too long');
425
+ }
426
+ };
427
+
428
+ /* Injected with object hook! */
429
+
430
+ // translate the various posix character classes into unicode properties
431
+ // this works across all unicode locales
432
+ // { <posix class>: [<translation>, /u flag required, negated]
433
+ const posixClasses = {
434
+ '[:alnum:]': ['\\p{L}\\p{Nl}\\p{Nd}', true],
435
+ '[:alpha:]': ['\\p{L}\\p{Nl}', true],
436
+ '[:ascii:]': ['\\x' + '00-\\x' + '7f', false],
437
+ '[:blank:]': ['\\p{Zs}\\t', true],
438
+ '[:cntrl:]': ['\\p{Cc}', true],
439
+ '[:digit:]': ['\\p{Nd}', true],
440
+ '[:graph:]': ['\\p{Z}\\p{C}', true, true],
441
+ '[:lower:]': ['\\p{Ll}', true],
442
+ '[:print:]': ['\\p{C}', true],
443
+ '[:punct:]': ['\\p{P}', true],
444
+ '[:space:]': ['\\p{Z}\\t\\r\\n\\v\\f', true],
445
+ '[:upper:]': ['\\p{Lu}', true],
446
+ '[:word:]': ['\\p{L}\\p{Nl}\\p{Nd}\\p{Pc}', true],
447
+ '[:xdigit:]': ['A-Fa-f0-9', false],
448
+ };
449
+ // only need to escape a few things inside of brace expressions
450
+ // escapes: [ \ ] -
451
+ const braceEscape = (s) => s.replace(/[[\]\\-]/g, '\\$&');
452
+ // escape all regexp magic characters
453
+ const regexpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
454
+ // everything has already been escaped, we just have to join
455
+ const rangesToString = (ranges) => ranges.join('');
456
+ // takes a glob string at a posix brace expression, and returns
457
+ // an equivalent regular expression source, and boolean indicating
458
+ // whether the /u flag needs to be applied, and the number of chars
459
+ // consumed to parse the character class.
460
+ // This also removes out of order ranges, and returns ($.) if the
461
+ // entire class just no good.
462
+ const parseClass = (glob, position) => {
463
+ const pos = position;
464
+ /* c8 ignore start */
465
+ if (glob.charAt(pos) !== '[') {
466
+ throw new Error('not in a brace expression');
467
+ }
468
+ /* c8 ignore stop */
469
+ const ranges = [];
470
+ const negs = [];
471
+ let i = pos + 1;
472
+ let sawStart = false;
473
+ let uflag = false;
474
+ let escaping = false;
475
+ let negate = false;
476
+ let endPos = pos;
477
+ let rangeStart = '';
478
+ WHILE: while (i < glob.length) {
479
+ const c = glob.charAt(i);
480
+ if ((c === '!' || c === '^') && i === pos + 1) {
481
+ negate = true;
482
+ i++;
483
+ continue;
484
+ }
485
+ if (c === ']' && sawStart && !escaping) {
486
+ endPos = i + 1;
487
+ break;
488
+ }
489
+ sawStart = true;
490
+ if (c === '\\') {
491
+ if (!escaping) {
492
+ escaping = true;
493
+ i++;
494
+ continue;
495
+ }
496
+ // escaped \ char, fall through and treat like normal char
497
+ }
498
+ if (c === '[' && !escaping) {
499
+ // either a posix class, a collation equivalent, or just a [
500
+ for (const [cls, [unip, u, neg]] of Object.entries(posixClasses)) {
501
+ if (glob.startsWith(cls, i)) {
502
+ // invalid, [a-[] is fine, but not [a-[:alpha]]
503
+ if (rangeStart) {
504
+ return ['$.', false, glob.length - pos, true];
505
+ }
506
+ i += cls.length;
507
+ if (neg)
508
+ negs.push(unip);
509
+ else
510
+ ranges.push(unip);
511
+ uflag = uflag || u;
512
+ continue WHILE;
513
+ }
514
+ }
515
+ }
516
+ // now it's just a normal character, effectively
517
+ escaping = false;
518
+ if (rangeStart) {
519
+ // throw this range away if it's not valid, but others
520
+ // can still match.
521
+ if (c > rangeStart) {
522
+ ranges.push(braceEscape(rangeStart) + '-' + braceEscape(c));
523
+ }
524
+ else if (c === rangeStart) {
525
+ ranges.push(braceEscape(c));
526
+ }
527
+ rangeStart = '';
528
+ i++;
529
+ continue;
530
+ }
531
+ // now might be the start of a range.
532
+ // can be either c-d or c-] or c<more...>] or c] at this point
533
+ if (glob.startsWith('-]', i + 1)) {
534
+ ranges.push(braceEscape(c + '-'));
535
+ i += 2;
536
+ continue;
537
+ }
538
+ if (glob.startsWith('-', i + 1)) {
539
+ rangeStart = c;
540
+ i += 2;
541
+ continue;
542
+ }
543
+ // not the start of a range, just a single character
544
+ ranges.push(braceEscape(c));
545
+ i++;
546
+ }
547
+ if (endPos < i) {
548
+ // didn't see the end of the class, not a valid class,
549
+ // but might still be valid as a literal match.
550
+ return ['', false, 0, false];
551
+ }
552
+ // if we got no ranges and no negates, then we have a range that
553
+ // cannot possibly match anything, and that poisons the whole glob
554
+ if (!ranges.length && !negs.length) {
555
+ return ['$.', false, glob.length - pos, true];
556
+ }
557
+ // if we got one positive range, and it's a single character, then that's
558
+ // not actually a magic pattern, it's just that one literal character.
559
+ // we should not treat that as "magic", we should just return the literal
560
+ // character. [_] is a perfectly valid way to escape glob magic chars.
561
+ if (negs.length === 0 &&
562
+ ranges.length === 1 &&
563
+ /^\\?.$/.test(ranges[0]) &&
564
+ !negate) {
565
+ const r = ranges[0].length === 2 ? ranges[0].slice(-1) : ranges[0];
566
+ return [regexpEscape(r), false, endPos - pos, false];
567
+ }
568
+ const sranges = '[' + (negate ? '^' : '') + rangesToString(ranges) + ']';
569
+ const snegs = '[' + (negate ? '' : '^') + rangesToString(negs) + ']';
570
+ const comb = ranges.length && negs.length
571
+ ? '(' + sranges + '|' + snegs + ')'
572
+ : ranges.length
573
+ ? sranges
574
+ : snegs;
575
+ return [comb, uflag, endPos - pos, true];
576
+ };
577
+
578
+ /* Injected with object hook! */
579
+
580
+ /**
581
+ * Un-escape a string that has been escaped with {@link escape}.
582
+ *
583
+ * If the {@link windowsPathsNoEscape} option is used, then square-brace
584
+ * escapes are removed, but not backslash escapes. For example, it will turn
585
+ * the string `'[*]'` into `*`, but it will not turn `'\\*'` into `'*'`,
586
+ * becuase `\` is a path separator in `windowsPathsNoEscape` mode.
587
+ *
588
+ * When `windowsPathsNoEscape` is not set, then both brace escapes and
589
+ * backslash escapes are removed.
590
+ *
591
+ * Slashes (and backslashes in `windowsPathsNoEscape` mode) cannot be escaped
592
+ * or unescaped.
593
+ */
594
+ const unescape = (s, { windowsPathsNoEscape = false, } = {}) => {
595
+ return windowsPathsNoEscape
596
+ ? s.replace(/\[([^\/\\])\]/g, '$1')
597
+ : s.replace(/((?!\\).|^)\[([^\/\\])\]/g, '$1$2').replace(/\\([^\/])/g, '$1');
598
+ };
599
+
600
+ /* Injected with object hook! */
601
+
602
+ // parse a single path portion
603
+ const types = new Set(['!', '?', '+', '*', '@']);
604
+ const isExtglobType = (c) => types.has(c);
605
+ // Patterns that get prepended to bind to the start of either the
606
+ // entire string, or just a single path portion, to prevent dots
607
+ // and/or traversal patterns, when needed.
608
+ // Exts don't need the ^ or / bit, because the root binds that already.
609
+ const startNoTraversal = '(?!(?:^|/)\\.\\.?(?:$|/))';
610
+ const startNoDot = '(?!\\.)';
611
+ // characters that indicate a start of pattern needs the "no dots" bit,
612
+ // because a dot *might* be matched. ( is not in the list, because in
613
+ // the case of a child extglob, it will handle the prevention itself.
614
+ const addPatternStart = new Set(['[', '.']);
615
+ // cases where traversal is A-OK, no dot prevention needed
616
+ const justDots = new Set(['..', '.']);
617
+ const reSpecials = new Set('().*{}+?[]^$\\!');
618
+ const regExpEscape$1 = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
619
+ // any single thing other than /
620
+ const qmark$1 = '[^/]';
621
+ // * => any number of characters
622
+ const star$1 = qmark$1 + '*?';
623
+ // use + when we need to ensure that *something* matches, because the * is
624
+ // the only thing in the path portion.
625
+ const starNoEmpty = qmark$1 + '+?';
626
+ // remove the \ chars that we added if we end up doing a nonmagic compare
627
+ // const deslash = (s: string) => s.replace(/\\(.)/g, '$1')
628
+ class AST {
629
+ type;
630
+ #root;
631
+ #hasMagic;
632
+ #uflag = false;
633
+ #parts = [];
634
+ #parent;
635
+ #parentIndex;
636
+ #negs;
637
+ #filledNegs = false;
638
+ #options;
639
+ #toString;
640
+ // set to true if it's an extglob with no children
641
+ // (which really means one child of '')
642
+ #emptyExt = false;
643
+ constructor(type, parent, options = {}) {
644
+ this.type = type;
645
+ // extglobs are inherently magical
646
+ if (type)
647
+ this.#hasMagic = true;
648
+ this.#parent = parent;
649
+ this.#root = this.#parent ? this.#parent.#root : this;
650
+ this.#options = this.#root === this ? options : this.#root.#options;
651
+ this.#negs = this.#root === this ? [] : this.#root.#negs;
652
+ if (type === '!' && !this.#root.#filledNegs)
653
+ this.#negs.push(this);
654
+ this.#parentIndex = this.#parent ? this.#parent.#parts.length : 0;
655
+ }
656
+ get hasMagic() {
657
+ /* c8 ignore start */
658
+ if (this.#hasMagic !== undefined)
659
+ return this.#hasMagic;
660
+ /* c8 ignore stop */
661
+ for (const p of this.#parts) {
662
+ if (typeof p === 'string')
663
+ continue;
664
+ if (p.type || p.hasMagic)
665
+ return (this.#hasMagic = true);
666
+ }
667
+ // note: will be undefined until we generate the regexp src and find out
668
+ return this.#hasMagic;
669
+ }
670
+ // reconstructs the pattern
671
+ toString() {
672
+ if (this.#toString !== undefined)
673
+ return this.#toString;
674
+ if (!this.type) {
675
+ return (this.#toString = this.#parts.map(p => String(p)).join(''));
676
+ }
677
+ else {
678
+ return (this.#toString =
679
+ this.type + '(' + this.#parts.map(p => String(p)).join('|') + ')');
680
+ }
681
+ }
682
+ #fillNegs() {
683
+ /* c8 ignore start */
684
+ if (this !== this.#root)
685
+ throw new Error('should only call on root');
686
+ if (this.#filledNegs)
687
+ return this;
688
+ /* c8 ignore stop */
689
+ // call toString() once to fill this out
690
+ this.toString();
691
+ this.#filledNegs = true;
692
+ let n;
693
+ while ((n = this.#negs.pop())) {
694
+ if (n.type !== '!')
695
+ continue;
696
+ // walk up the tree, appending everthing that comes AFTER parentIndex
697
+ let p = n;
698
+ let pp = p.#parent;
699
+ while (pp) {
700
+ for (let i = p.#parentIndex + 1; !pp.type && i < pp.#parts.length; i++) {
701
+ for (const part of n.#parts) {
702
+ /* c8 ignore start */
703
+ if (typeof part === 'string') {
704
+ throw new Error('string part in extglob AST??');
705
+ }
706
+ /* c8 ignore stop */
707
+ part.copyIn(pp.#parts[i]);
708
+ }
709
+ }
710
+ p = pp;
711
+ pp = p.#parent;
712
+ }
713
+ }
714
+ return this;
715
+ }
716
+ push(...parts) {
717
+ for (const p of parts) {
718
+ if (p === '')
719
+ continue;
720
+ /* c8 ignore start */
721
+ if (typeof p !== 'string' && !(p instanceof AST && p.#parent === this)) {
722
+ throw new Error('invalid part: ' + p);
723
+ }
724
+ /* c8 ignore stop */
725
+ this.#parts.push(p);
726
+ }
727
+ }
728
+ toJSON() {
729
+ const ret = this.type === null
730
+ ? this.#parts.slice().map(p => (typeof p === 'string' ? p : p.toJSON()))
731
+ : [this.type, ...this.#parts.map(p => p.toJSON())];
732
+ if (this.isStart() && !this.type)
733
+ ret.unshift([]);
734
+ if (this.isEnd() &&
735
+ (this === this.#root ||
736
+ (this.#root.#filledNegs && this.#parent?.type === '!'))) {
737
+ ret.push({});
738
+ }
739
+ return ret;
740
+ }
741
+ isStart() {
742
+ if (this.#root === this)
743
+ return true;
744
+ // if (this.type) return !!this.#parent?.isStart()
745
+ if (!this.#parent?.isStart())
746
+ return false;
747
+ if (this.#parentIndex === 0)
748
+ return true;
749
+ // if everything AHEAD of this is a negation, then it's still the "start"
750
+ const p = this.#parent;
751
+ for (let i = 0; i < this.#parentIndex; i++) {
752
+ const pp = p.#parts[i];
753
+ if (!(pp instanceof AST && pp.type === '!')) {
754
+ return false;
755
+ }
756
+ }
757
+ return true;
758
+ }
759
+ isEnd() {
760
+ if (this.#root === this)
761
+ return true;
762
+ if (this.#parent?.type === '!')
763
+ return true;
764
+ if (!this.#parent?.isEnd())
765
+ return false;
766
+ if (!this.type)
767
+ return this.#parent?.isEnd();
768
+ // if not root, it'll always have a parent
769
+ /* c8 ignore start */
770
+ const pl = this.#parent ? this.#parent.#parts.length : 0;
771
+ /* c8 ignore stop */
772
+ return this.#parentIndex === pl - 1;
773
+ }
774
+ copyIn(part) {
775
+ if (typeof part === 'string')
776
+ this.push(part);
777
+ else
778
+ this.push(part.clone(this));
779
+ }
780
+ clone(parent) {
781
+ const c = new AST(this.type, parent);
782
+ for (const p of this.#parts) {
783
+ c.copyIn(p);
784
+ }
785
+ return c;
786
+ }
787
+ static #parseAST(str, ast, pos, opt) {
788
+ let escaping = false;
789
+ let inBrace = false;
790
+ let braceStart = -1;
791
+ let braceNeg = false;
792
+ if (ast.type === null) {
793
+ // outside of a extglob, append until we find a start
794
+ let i = pos;
795
+ let acc = '';
796
+ while (i < str.length) {
797
+ const c = str.charAt(i++);
798
+ // still accumulate escapes at this point, but we do ignore
799
+ // starts that are escaped
800
+ if (escaping || c === '\\') {
801
+ escaping = !escaping;
802
+ acc += c;
803
+ continue;
804
+ }
805
+ if (inBrace) {
806
+ if (i === braceStart + 1) {
807
+ if (c === '^' || c === '!') {
808
+ braceNeg = true;
809
+ }
810
+ }
811
+ else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {
812
+ inBrace = false;
813
+ }
814
+ acc += c;
815
+ continue;
816
+ }
817
+ else if (c === '[') {
818
+ inBrace = true;
819
+ braceStart = i;
820
+ braceNeg = false;
821
+ acc += c;
822
+ continue;
823
+ }
824
+ if (!opt.noext && isExtglobType(c) && str.charAt(i) === '(') {
825
+ ast.push(acc);
826
+ acc = '';
827
+ const ext = new AST(c, ast);
828
+ i = AST.#parseAST(str, ext, i, opt);
829
+ ast.push(ext);
830
+ continue;
831
+ }
832
+ acc += c;
833
+ }
834
+ ast.push(acc);
835
+ return i;
836
+ }
837
+ // some kind of extglob, pos is at the (
838
+ // find the next | or )
839
+ let i = pos + 1;
840
+ let part = new AST(null, ast);
841
+ const parts = [];
842
+ let acc = '';
843
+ while (i < str.length) {
844
+ const c = str.charAt(i++);
845
+ // still accumulate escapes at this point, but we do ignore
846
+ // starts that are escaped
847
+ if (escaping || c === '\\') {
848
+ escaping = !escaping;
849
+ acc += c;
850
+ continue;
851
+ }
852
+ if (inBrace) {
853
+ if (i === braceStart + 1) {
854
+ if (c === '^' || c === '!') {
855
+ braceNeg = true;
856
+ }
857
+ }
858
+ else if (c === ']' && !(i === braceStart + 2 && braceNeg)) {
859
+ inBrace = false;
860
+ }
861
+ acc += c;
862
+ continue;
863
+ }
864
+ else if (c === '[') {
865
+ inBrace = true;
866
+ braceStart = i;
867
+ braceNeg = false;
868
+ acc += c;
869
+ continue;
870
+ }
871
+ if (isExtglobType(c) && str.charAt(i) === '(') {
872
+ part.push(acc);
873
+ acc = '';
874
+ const ext = new AST(c, part);
875
+ part.push(ext);
876
+ i = AST.#parseAST(str, ext, i, opt);
877
+ continue;
878
+ }
879
+ if (c === '|') {
880
+ part.push(acc);
881
+ acc = '';
882
+ parts.push(part);
883
+ part = new AST(null, ast);
884
+ continue;
885
+ }
886
+ if (c === ')') {
887
+ if (acc === '' && ast.#parts.length === 0) {
888
+ ast.#emptyExt = true;
889
+ }
890
+ part.push(acc);
891
+ acc = '';
892
+ ast.push(...parts, part);
893
+ return i;
894
+ }
895
+ acc += c;
896
+ }
897
+ // unfinished extglob
898
+ // if we got here, it was a malformed extglob! not an extglob, but
899
+ // maybe something else in there.
900
+ ast.type = null;
901
+ ast.#hasMagic = undefined;
902
+ ast.#parts = [str.substring(pos - 1)];
903
+ return i;
904
+ }
905
+ static fromGlob(pattern, options = {}) {
906
+ const ast = new AST(null, undefined, options);
907
+ AST.#parseAST(pattern, ast, 0, options);
908
+ return ast;
909
+ }
910
+ // returns the regular expression if there's magic, or the unescaped
911
+ // string if not.
912
+ toMMPattern() {
913
+ // should only be called on root
914
+ /* c8 ignore start */
915
+ if (this !== this.#root)
916
+ return this.#root.toMMPattern();
917
+ /* c8 ignore stop */
918
+ const glob = this.toString();
919
+ const [re, body, hasMagic, uflag] = this.toRegExpSource();
920
+ // if we're in nocase mode, and not nocaseMagicOnly, then we do
921
+ // still need a regular expression if we have to case-insensitively
922
+ // match capital/lowercase characters.
923
+ const anyMagic = hasMagic ||
924
+ this.#hasMagic ||
925
+ (this.#options.nocase &&
926
+ !this.#options.nocaseMagicOnly &&
927
+ glob.toUpperCase() !== glob.toLowerCase());
928
+ if (!anyMagic) {
929
+ return body;
930
+ }
931
+ const flags = (this.#options.nocase ? 'i' : '') + (uflag ? 'u' : '');
932
+ return Object.assign(new RegExp(`^${re}$`, flags), {
933
+ _src: re,
934
+ _glob: glob,
935
+ });
936
+ }
937
+ // returns the string match, the regexp source, whether there's magic
938
+ // in the regexp (so a regular expression is required) and whether or
939
+ // not the uflag is needed for the regular expression (for posix classes)
940
+ // TODO: instead of injecting the start/end at this point, just return
941
+ // the BODY of the regexp, along with the start/end portions suitable
942
+ // for binding the start/end in either a joined full-path makeRe context
943
+ // (where we bind to (^|/), or a standalone matchPart context (where
944
+ // we bind to ^, and not /). Otherwise slashes get duped!
945
+ //
946
+ // In part-matching mode, the start is:
947
+ // - if not isStart: nothing
948
+ // - if traversal possible, but not allowed: ^(?!\.\.?$)
949
+ // - if dots allowed or not possible: ^
950
+ // - if dots possible and not allowed: ^(?!\.)
951
+ // end is:
952
+ // - if not isEnd(): nothing
953
+ // - else: $
954
+ //
955
+ // In full-path matching mode, we put the slash at the START of the
956
+ // pattern, so start is:
957
+ // - if first pattern: same as part-matching mode
958
+ // - if not isStart(): nothing
959
+ // - if traversal possible, but not allowed: /(?!\.\.?(?:$|/))
960
+ // - if dots allowed or not possible: /
961
+ // - if dots possible and not allowed: /(?!\.)
962
+ // end is:
963
+ // - if last pattern, same as part-matching mode
964
+ // - else nothing
965
+ //
966
+ // Always put the (?:$|/) on negated tails, though, because that has to be
967
+ // there to bind the end of the negated pattern portion, and it's easier to
968
+ // just stick it in now rather than try to inject it later in the middle of
969
+ // the pattern.
970
+ //
971
+ // We can just always return the same end, and leave it up to the caller
972
+ // to know whether it's going to be used joined or in parts.
973
+ // And, if the start is adjusted slightly, can do the same there:
974
+ // - if not isStart: nothing
975
+ // - if traversal possible, but not allowed: (?:/|^)(?!\.\.?$)
976
+ // - if dots allowed or not possible: (?:/|^)
977
+ // - if dots possible and not allowed: (?:/|^)(?!\.)
978
+ //
979
+ // But it's better to have a simpler binding without a conditional, for
980
+ // performance, so probably better to return both start options.
981
+ //
982
+ // Then the caller just ignores the end if it's not the first pattern,
983
+ // and the start always gets applied.
984
+ //
985
+ // But that's always going to be $ if it's the ending pattern, or nothing,
986
+ // so the caller can just attach $ at the end of the pattern when building.
987
+ //
988
+ // So the todo is:
989
+ // - better detect what kind of start is needed
990
+ // - return both flavors of starting pattern
991
+ // - attach $ at the end of the pattern when creating the actual RegExp
992
+ //
993
+ // Ah, but wait, no, that all only applies to the root when the first pattern
994
+ // is not an extglob. If the first pattern IS an extglob, then we need all
995
+ // that dot prevention biz to live in the extglob portions, because eg
996
+ // +(*|.x*) can match .xy but not .yx.
997
+ //
998
+ // So, return the two flavors if it's #root and the first child is not an
999
+ // AST, otherwise leave it to the child AST to handle it, and there,
1000
+ // use the (?:^|/) style of start binding.
1001
+ //
1002
+ // Even simplified further:
1003
+ // - Since the start for a join is eg /(?!\.) and the start for a part
1004
+ // is ^(?!\.), we can just prepend (?!\.) to the pattern (either root
1005
+ // or start or whatever) and prepend ^ or / at the Regexp construction.
1006
+ toRegExpSource(allowDot) {
1007
+ const dot = allowDot ?? !!this.#options.dot;
1008
+ if (this.#root === this)
1009
+ this.#fillNegs();
1010
+ if (!this.type) {
1011
+ const noEmpty = this.isStart() && this.isEnd();
1012
+ const src = this.#parts
1013
+ .map(p => {
1014
+ const [re, _, hasMagic, uflag] = typeof p === 'string'
1015
+ ? AST.#parseGlob(p, this.#hasMagic, noEmpty)
1016
+ : p.toRegExpSource(allowDot);
1017
+ this.#hasMagic = this.#hasMagic || hasMagic;
1018
+ this.#uflag = this.#uflag || uflag;
1019
+ return re;
1020
+ })
1021
+ .join('');
1022
+ let start = '';
1023
+ if (this.isStart()) {
1024
+ if (typeof this.#parts[0] === 'string') {
1025
+ // this is the string that will match the start of the pattern,
1026
+ // so we need to protect against dots and such.
1027
+ // '.' and '..' cannot match unless the pattern is that exactly,
1028
+ // even if it starts with . or dot:true is set.
1029
+ const dotTravAllowed = this.#parts.length === 1 && justDots.has(this.#parts[0]);
1030
+ if (!dotTravAllowed) {
1031
+ const aps = addPatternStart;
1032
+ // check if we have a possibility of matching . or ..,
1033
+ // and prevent that.
1034
+ const needNoTrav =
1035
+ // dots are allowed, and the pattern starts with [ or .
1036
+ (dot && aps.has(src.charAt(0))) ||
1037
+ // the pattern starts with \., and then [ or .
1038
+ (src.startsWith('\\.') && aps.has(src.charAt(2))) ||
1039
+ // the pattern starts with \.\., and then [ or .
1040
+ (src.startsWith('\\.\\.') && aps.has(src.charAt(4)));
1041
+ // no need to prevent dots if it can't match a dot, or if a
1042
+ // sub-pattern will be preventing it anyway.
1043
+ const needNoDot = !dot && !allowDot && aps.has(src.charAt(0));
1044
+ start = needNoTrav ? startNoTraversal : needNoDot ? startNoDot : '';
1045
+ }
1046
+ }
1047
+ }
1048
+ // append the "end of path portion" pattern to negation tails
1049
+ let end = '';
1050
+ if (this.isEnd() &&
1051
+ this.#root.#filledNegs &&
1052
+ this.#parent?.type === '!') {
1053
+ end = '(?:$|\\/)';
1054
+ }
1055
+ const final = start + src + end;
1056
+ return [
1057
+ final,
1058
+ unescape(src),
1059
+ (this.#hasMagic = !!this.#hasMagic),
1060
+ this.#uflag,
1061
+ ];
1062
+ }
1063
+ // We need to calculate the body *twice* if it's a repeat pattern
1064
+ // at the start, once in nodot mode, then again in dot mode, so a
1065
+ // pattern like *(?) can match 'x.y'
1066
+ const repeated = this.type === '*' || this.type === '+';
1067
+ // some kind of extglob
1068
+ const start = this.type === '!' ? '(?:(?!(?:' : '(?:';
1069
+ let body = this.#partsToRegExp(dot);
1070
+ if (this.isStart() && this.isEnd() && !body && this.type !== '!') {
1071
+ // invalid extglob, has to at least be *something* present, if it's
1072
+ // the entire path portion.
1073
+ const s = this.toString();
1074
+ this.#parts = [s];
1075
+ this.type = null;
1076
+ this.#hasMagic = undefined;
1077
+ return [s, unescape(this.toString()), false, false];
1078
+ }
1079
+ // XXX abstract out this map method
1080
+ let bodyDotAllowed = !repeated || allowDot || dot || !startNoDot
1081
+ ? ''
1082
+ : this.#partsToRegExp(true);
1083
+ if (bodyDotAllowed === body) {
1084
+ bodyDotAllowed = '';
1085
+ }
1086
+ if (bodyDotAllowed) {
1087
+ body = `(?:${body})(?:${bodyDotAllowed})*?`;
1088
+ }
1089
+ // an empty !() is exactly equivalent to a starNoEmpty
1090
+ let final = '';
1091
+ if (this.type === '!' && this.#emptyExt) {
1092
+ final = (this.isStart() && !dot ? startNoDot : '') + starNoEmpty;
1093
+ }
1094
+ else {
1095
+ const close = this.type === '!'
1096
+ ? // !() must match something,but !(x) can match ''
1097
+ '))' +
1098
+ (this.isStart() && !dot && !allowDot ? startNoDot : '') +
1099
+ star$1 +
1100
+ ')'
1101
+ : this.type === '@'
1102
+ ? ')'
1103
+ : this.type === '?'
1104
+ ? ')?'
1105
+ : this.type === '+' && bodyDotAllowed
1106
+ ? ')'
1107
+ : this.type === '*' && bodyDotAllowed
1108
+ ? `)?`
1109
+ : `)${this.type}`;
1110
+ final = start + body + close;
1111
+ }
1112
+ return [
1113
+ final,
1114
+ unescape(body),
1115
+ (this.#hasMagic = !!this.#hasMagic),
1116
+ this.#uflag,
1117
+ ];
1118
+ }
1119
+ #partsToRegExp(dot) {
1120
+ return this.#parts
1121
+ .map(p => {
1122
+ // extglob ASTs should only contain parent ASTs
1123
+ /* c8 ignore start */
1124
+ if (typeof p === 'string') {
1125
+ throw new Error('string type in extglob ast??');
1126
+ }
1127
+ /* c8 ignore stop */
1128
+ // can ignore hasMagic, because extglobs are already always magic
1129
+ const [re, _, _hasMagic, uflag] = p.toRegExpSource(dot);
1130
+ this.#uflag = this.#uflag || uflag;
1131
+ return re;
1132
+ })
1133
+ .filter(p => !(this.isStart() && this.isEnd()) || !!p)
1134
+ .join('|');
1135
+ }
1136
+ static #parseGlob(glob, hasMagic, noEmpty = false) {
1137
+ let escaping = false;
1138
+ let re = '';
1139
+ let uflag = false;
1140
+ for (let i = 0; i < glob.length; i++) {
1141
+ const c = glob.charAt(i);
1142
+ if (escaping) {
1143
+ escaping = false;
1144
+ re += (reSpecials.has(c) ? '\\' : '') + c;
1145
+ continue;
1146
+ }
1147
+ if (c === '\\') {
1148
+ if (i === glob.length - 1) {
1149
+ re += '\\\\';
1150
+ }
1151
+ else {
1152
+ escaping = true;
1153
+ }
1154
+ continue;
1155
+ }
1156
+ if (c === '[') {
1157
+ const [src, needUflag, consumed, magic] = parseClass(glob, i);
1158
+ if (consumed) {
1159
+ re += src;
1160
+ uflag = uflag || needUflag;
1161
+ i += consumed - 1;
1162
+ hasMagic = hasMagic || magic;
1163
+ continue;
1164
+ }
1165
+ }
1166
+ if (c === '*') {
1167
+ if (noEmpty && glob === '*')
1168
+ re += starNoEmpty;
1169
+ else
1170
+ re += star$1;
1171
+ hasMagic = true;
1172
+ continue;
1173
+ }
1174
+ if (c === '?') {
1175
+ re += qmark$1;
1176
+ hasMagic = true;
1177
+ continue;
1178
+ }
1179
+ re += regExpEscape$1(c);
1180
+ }
1181
+ return [re, unescape(glob), !!hasMagic, uflag];
1182
+ }
1183
+ }
1184
+
1185
+ /* Injected with object hook! */
1186
+
1187
+ /**
1188
+ * Escape all magic characters in a glob pattern.
1189
+ *
1190
+ * If the {@link windowsPathsNoEscape | GlobOptions.windowsPathsNoEscape}
1191
+ * option is used, then characters are escaped by wrapping in `[]`, because
1192
+ * a magic character wrapped in a character class can only be satisfied by
1193
+ * that exact character. In this mode, `\` is _not_ escaped, because it is
1194
+ * not interpreted as a magic character, but instead as a path separator.
1195
+ */
1196
+ const escape = (s, { windowsPathsNoEscape = false, } = {}) => {
1197
+ // don't need to escape +@! because we escape the parens
1198
+ // that make those magic, and escaping ! as [!] isn't valid,
1199
+ // because [!]] is a valid glob class meaning not ']'.
1200
+ return windowsPathsNoEscape
1201
+ ? s.replace(/[?*()[\]]/g, '[$&]')
1202
+ : s.replace(/[?*()[\]\\]/g, '\\$&');
1203
+ };
1204
+
1205
+ /* Injected with object hook! */
1206
+
1207
+ const minimatch = (p, pattern, options = {}) => {
1208
+ assertValidPattern(pattern);
1209
+ // shortcut: comments match nothing.
1210
+ if (!options.nocomment && pattern.charAt(0) === '#') {
1211
+ return false;
1212
+ }
1213
+ return new Minimatch(pattern, options).match(p);
1214
+ };
1215
+ // Optimized checking for the most common glob patterns.
1216
+ const starDotExtRE = /^\*+([^+@!?\*\[\(]*)$/;
1217
+ const starDotExtTest = (ext) => (f) => !f.startsWith('.') && f.endsWith(ext);
1218
+ const starDotExtTestDot = (ext) => (f) => f.endsWith(ext);
1219
+ const starDotExtTestNocase = (ext) => {
1220
+ ext = ext.toLowerCase();
1221
+ return (f) => !f.startsWith('.') && f.toLowerCase().endsWith(ext);
1222
+ };
1223
+ const starDotExtTestNocaseDot = (ext) => {
1224
+ ext = ext.toLowerCase();
1225
+ return (f) => f.toLowerCase().endsWith(ext);
1226
+ };
1227
+ const starDotStarRE = /^\*+\.\*+$/;
1228
+ const starDotStarTest = (f) => !f.startsWith('.') && f.includes('.');
1229
+ const starDotStarTestDot = (f) => f !== '.' && f !== '..' && f.includes('.');
1230
+ const dotStarRE = /^\.\*+$/;
1231
+ const dotStarTest = (f) => f !== '.' && f !== '..' && f.startsWith('.');
1232
+ const starRE = /^\*+$/;
1233
+ const starTest = (f) => f.length !== 0 && !f.startsWith('.');
1234
+ const starTestDot = (f) => f.length !== 0 && f !== '.' && f !== '..';
1235
+ const qmarksRE = /^\?+([^+@!?\*\[\(]*)?$/;
1236
+ const qmarksTestNocase = ([$0, ext = '']) => {
1237
+ const noext = qmarksTestNoExt([$0]);
1238
+ if (!ext)
1239
+ return noext;
1240
+ ext = ext.toLowerCase();
1241
+ return (f) => noext(f) && f.toLowerCase().endsWith(ext);
1242
+ };
1243
+ const qmarksTestNocaseDot = ([$0, ext = '']) => {
1244
+ const noext = qmarksTestNoExtDot([$0]);
1245
+ if (!ext)
1246
+ return noext;
1247
+ ext = ext.toLowerCase();
1248
+ return (f) => noext(f) && f.toLowerCase().endsWith(ext);
1249
+ };
1250
+ const qmarksTestDot = ([$0, ext = '']) => {
1251
+ const noext = qmarksTestNoExtDot([$0]);
1252
+ return !ext ? noext : (f) => noext(f) && f.endsWith(ext);
1253
+ };
1254
+ const qmarksTest = ([$0, ext = '']) => {
1255
+ const noext = qmarksTestNoExt([$0]);
1256
+ return !ext ? noext : (f) => noext(f) && f.endsWith(ext);
1257
+ };
1258
+ const qmarksTestNoExt = ([$0]) => {
1259
+ const len = $0.length;
1260
+ return (f) => f.length === len && !f.startsWith('.');
1261
+ };
1262
+ const qmarksTestNoExtDot = ([$0]) => {
1263
+ const len = $0.length;
1264
+ return (f) => f.length === len && f !== '.' && f !== '..';
1265
+ };
1266
+ /* c8 ignore start */
1267
+ const defaultPlatform = (typeof process === 'object' && process
1268
+ ? (typeof process.env === 'object' &&
1269
+ process.env &&
1270
+ ({}).__MINIMATCH_TESTING_PLATFORM__) ||
1271
+ process.platform
1272
+ : 'posix');
1273
+ const path$A = {
1274
+ win32: { sep: '\\' },
1275
+ posix: { sep: '/' },
1276
+ };
1277
+ /* c8 ignore stop */
1278
+ const sep = defaultPlatform === 'win32' ? path$A.win32.sep : path$A.posix.sep;
1279
+ minimatch.sep = sep;
1280
+ const GLOBSTAR = Symbol('globstar **');
1281
+ minimatch.GLOBSTAR = GLOBSTAR;
1282
+ // any single thing other than /
1283
+ // don't need to escape / when using new RegExp()
1284
+ const qmark = '[^/]';
1285
+ // * => any number of characters
1286
+ const star = qmark + '*?';
1287
+ // ** when dots are allowed. Anything goes, except .. and .
1288
+ // not (^ or / followed by one or two dots followed by $ or /),
1289
+ // followed by anything, any number of times.
1290
+ const twoStarDot = '(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?';
1291
+ // not a ^ or / followed by a dot,
1292
+ // followed by anything, any number of times.
1293
+ const twoStarNoDot = '(?:(?!(?:\\/|^)\\.).)*?';
1294
+ const filter$5 = (pattern, options = {}) => (p) => minimatch(p, pattern, options);
1295
+ minimatch.filter = filter$5;
1296
+ const ext = (a, b = {}) => Object.assign({}, a, b);
1297
+ const defaults$2 = (def) => {
1298
+ if (!def || typeof def !== 'object' || !Object.keys(def).length) {
1299
+ return minimatch;
1300
+ }
1301
+ const orig = minimatch;
1302
+ const m = (p, pattern, options = {}) => orig(p, pattern, ext(def, options));
1303
+ return Object.assign(m, {
1304
+ Minimatch: class Minimatch extends orig.Minimatch {
1305
+ constructor(pattern, options = {}) {
1306
+ super(pattern, ext(def, options));
1307
+ }
1308
+ static defaults(options) {
1309
+ return orig.defaults(ext(def, options)).Minimatch;
1310
+ }
1311
+ },
1312
+ AST: class AST extends orig.AST {
1313
+ /* c8 ignore start */
1314
+ constructor(type, parent, options = {}) {
1315
+ super(type, parent, ext(def, options));
1316
+ }
1317
+ /* c8 ignore stop */
1318
+ static fromGlob(pattern, options = {}) {
1319
+ return orig.AST.fromGlob(pattern, ext(def, options));
1320
+ }
1321
+ },
1322
+ unescape: (s, options = {}) => orig.unescape(s, ext(def, options)),
1323
+ escape: (s, options = {}) => orig.escape(s, ext(def, options)),
1324
+ filter: (pattern, options = {}) => orig.filter(pattern, ext(def, options)),
1325
+ defaults: (options) => orig.defaults(ext(def, options)),
1326
+ makeRe: (pattern, options = {}) => orig.makeRe(pattern, ext(def, options)),
1327
+ braceExpand: (pattern, options = {}) => orig.braceExpand(pattern, ext(def, options)),
1328
+ match: (list, pattern, options = {}) => orig.match(list, pattern, ext(def, options)),
1329
+ sep: orig.sep,
1330
+ GLOBSTAR: GLOBSTAR,
1331
+ });
1332
+ };
1333
+ minimatch.defaults = defaults$2;
1334
+ // Brace expansion:
1335
+ // a{b,c}d -> abd acd
1336
+ // a{b,}c -> abc ac
1337
+ // a{0..3}d -> a0d a1d a2d a3d
1338
+ // a{b,c{d,e}f}g -> abg acdfg acefg
1339
+ // a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
1340
+ //
1341
+ // Invalid sets are not expanded.
1342
+ // a{2..}b -> a{2..}b
1343
+ // a{b}c -> a{b}c
1344
+ const braceExpand = (pattern, options = {}) => {
1345
+ assertValidPattern(pattern);
1346
+ // Thanks to Yeting Li <https://github.com/yetingli> for
1347
+ // improving this regexp to avoid a ReDOS vulnerability.
1348
+ if (options.nobrace || !/\{(?:(?!\{).)*\}/.test(pattern)) {
1349
+ // shortcut. no need to expand.
1350
+ return [pattern];
1351
+ }
1352
+ return expand$1(pattern);
1353
+ };
1354
+ minimatch.braceExpand = braceExpand;
1355
+ // parse a component of the expanded set.
1356
+ // At this point, no pattern may contain "/" in it
1357
+ // so we're going to return a 2d array, where each entry is the full
1358
+ // pattern, split on '/', and then turned into a regular expression.
1359
+ // A regexp is made at the end which joins each array with an
1360
+ // escaped /, and another full one which joins each regexp with |.
1361
+ //
1362
+ // Following the lead of Bash 4.1, note that "**" only has special meaning
1363
+ // when it is the *only* thing in a path portion. Otherwise, any series
1364
+ // of * is equivalent to a single *. Globstar behavior is enabled by
1365
+ // default, and can be disabled by setting options.noglobstar.
1366
+ const makeRe = (pattern, options = {}) => new Minimatch(pattern, options).makeRe();
1367
+ minimatch.makeRe = makeRe;
1368
+ const match$2 = (list, pattern, options = {}) => {
1369
+ const mm = new Minimatch(pattern, options);
1370
+ list = list.filter(f => mm.match(f));
1371
+ if (mm.options.nonull && !list.length) {
1372
+ list.push(pattern);
1373
+ }
1374
+ return list;
1375
+ };
1376
+ minimatch.match = match$2;
1377
+ // replace stuff like \* with *
1378
+ const globMagic = /[?*]|[+@!]\(.*?\)|\[|\]/;
1379
+ const regExpEscape = (s) => s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
1380
+ class Minimatch {
1381
+ options;
1382
+ set;
1383
+ pattern;
1384
+ windowsPathsNoEscape;
1385
+ nonegate;
1386
+ negate;
1387
+ comment;
1388
+ empty;
1389
+ preserveMultipleSlashes;
1390
+ partial;
1391
+ globSet;
1392
+ globParts;
1393
+ nocase;
1394
+ isWindows;
1395
+ platform;
1396
+ windowsNoMagicRoot;
1397
+ regexp;
1398
+ constructor(pattern, options = {}) {
1399
+ assertValidPattern(pattern);
1400
+ options = options || {};
1401
+ this.options = options;
1402
+ this.pattern = pattern;
1403
+ this.platform = options.platform || defaultPlatform;
1404
+ this.isWindows = this.platform === 'win32';
1405
+ this.windowsPathsNoEscape =
1406
+ !!options.windowsPathsNoEscape || options.allowWindowsEscape === false;
1407
+ if (this.windowsPathsNoEscape) {
1408
+ this.pattern = this.pattern.replace(/\\/g, '/');
1409
+ }
1410
+ this.preserveMultipleSlashes = !!options.preserveMultipleSlashes;
1411
+ this.regexp = null;
1412
+ this.negate = false;
1413
+ this.nonegate = !!options.nonegate;
1414
+ this.comment = false;
1415
+ this.empty = false;
1416
+ this.partial = !!options.partial;
1417
+ this.nocase = !!this.options.nocase;
1418
+ this.windowsNoMagicRoot =
1419
+ options.windowsNoMagicRoot !== undefined
1420
+ ? options.windowsNoMagicRoot
1421
+ : !!(this.isWindows && this.nocase);
1422
+ this.globSet = [];
1423
+ this.globParts = [];
1424
+ this.set = [];
1425
+ // make the set of regexps etc.
1426
+ this.make();
1427
+ }
1428
+ hasMagic() {
1429
+ if (this.options.magicalBraces && this.set.length > 1) {
1430
+ return true;
1431
+ }
1432
+ for (const pattern of this.set) {
1433
+ for (const part of pattern) {
1434
+ if (typeof part !== 'string')
1435
+ return true;
1436
+ }
1437
+ }
1438
+ return false;
1439
+ }
1440
+ debug(..._) { }
1441
+ make() {
1442
+ const pattern = this.pattern;
1443
+ const options = this.options;
1444
+ // empty patterns and comments match nothing.
1445
+ if (!options.nocomment && pattern.charAt(0) === '#') {
1446
+ this.comment = true;
1447
+ return;
1448
+ }
1449
+ if (!pattern) {
1450
+ this.empty = true;
1451
+ return;
1452
+ }
1453
+ // step 1: figure out negation, etc.
1454
+ this.parseNegate();
1455
+ // step 2: expand braces
1456
+ this.globSet = [...new Set(this.braceExpand())];
1457
+ if (options.debug) {
1458
+ this.debug = (...args) => console.error(...args);
1459
+ }
1460
+ this.debug(this.pattern, this.globSet);
1461
+ // step 3: now we have a set, so turn each one into a series of
1462
+ // path-portion matching patterns.
1463
+ // These will be regexps, except in the case of "**", which is
1464
+ // set to the GLOBSTAR object for globstar behavior,
1465
+ // and will not contain any / characters
1466
+ //
1467
+ // First, we preprocess to make the glob pattern sets a bit simpler
1468
+ // and deduped. There are some perf-killing patterns that can cause
1469
+ // problems with a glob walk, but we can simplify them down a bit.
1470
+ const rawGlobParts = this.globSet.map(s => this.slashSplit(s));
1471
+ this.globParts = this.preprocess(rawGlobParts);
1472
+ this.debug(this.pattern, this.globParts);
1473
+ // glob --> regexps
1474
+ let set = this.globParts.map((s, _, __) => {
1475
+ if (this.isWindows && this.windowsNoMagicRoot) {
1476
+ // check if it's a drive or unc path.
1477
+ const isUNC = s[0] === '' &&
1478
+ s[1] === '' &&
1479
+ (s[2] === '?' || !globMagic.test(s[2])) &&
1480
+ !globMagic.test(s[3]);
1481
+ const isDrive = /^[a-z]:/i.test(s[0]);
1482
+ if (isUNC) {
1483
+ return [...s.slice(0, 4), ...s.slice(4).map(ss => this.parse(ss))];
1484
+ }
1485
+ else if (isDrive) {
1486
+ return [s[0], ...s.slice(1).map(ss => this.parse(ss))];
1487
+ }
1488
+ }
1489
+ return s.map(ss => this.parse(ss));
1490
+ });
1491
+ this.debug(this.pattern, set);
1492
+ // filter out everything that didn't compile properly.
1493
+ this.set = set.filter(s => s.indexOf(false) === -1);
1494
+ // do not treat the ? in UNC paths as magic
1495
+ if (this.isWindows) {
1496
+ for (let i = 0; i < this.set.length; i++) {
1497
+ const p = this.set[i];
1498
+ if (p[0] === '' &&
1499
+ p[1] === '' &&
1500
+ this.globParts[i][2] === '?' &&
1501
+ typeof p[3] === 'string' &&
1502
+ /^[a-z]:$/i.test(p[3])) {
1503
+ p[2] = '?';
1504
+ }
1505
+ }
1506
+ }
1507
+ this.debug(this.pattern, this.set);
1508
+ }
1509
+ // various transforms to equivalent pattern sets that are
1510
+ // faster to process in a filesystem walk. The goal is to
1511
+ // eliminate what we can, and push all ** patterns as far
1512
+ // to the right as possible, even if it increases the number
1513
+ // of patterns that we have to process.
1514
+ preprocess(globParts) {
1515
+ // if we're not in globstar mode, then turn all ** into *
1516
+ if (this.options.noglobstar) {
1517
+ for (let i = 0; i < globParts.length; i++) {
1518
+ for (let j = 0; j < globParts[i].length; j++) {
1519
+ if (globParts[i][j] === '**') {
1520
+ globParts[i][j] = '*';
1521
+ }
1522
+ }
1523
+ }
1524
+ }
1525
+ const { optimizationLevel = 1 } = this.options;
1526
+ if (optimizationLevel >= 2) {
1527
+ // aggressive optimization for the purpose of fs walking
1528
+ globParts = this.firstPhasePreProcess(globParts);
1529
+ globParts = this.secondPhasePreProcess(globParts);
1530
+ }
1531
+ else if (optimizationLevel >= 1) {
1532
+ // just basic optimizations to remove some .. parts
1533
+ globParts = this.levelOneOptimize(globParts);
1534
+ }
1535
+ else {
1536
+ globParts = this.adjascentGlobstarOptimize(globParts);
1537
+ }
1538
+ return globParts;
1539
+ }
1540
+ // just get rid of adjascent ** portions
1541
+ adjascentGlobstarOptimize(globParts) {
1542
+ return globParts.map(parts => {
1543
+ let gs = -1;
1544
+ while (-1 !== (gs = parts.indexOf('**', gs + 1))) {
1545
+ let i = gs;
1546
+ while (parts[i + 1] === '**') {
1547
+ i++;
1548
+ }
1549
+ if (i !== gs) {
1550
+ parts.splice(gs, i - gs);
1551
+ }
1552
+ }
1553
+ return parts;
1554
+ });
1555
+ }
1556
+ // get rid of adjascent ** and resolve .. portions
1557
+ levelOneOptimize(globParts) {
1558
+ return globParts.map(parts => {
1559
+ parts = parts.reduce((set, part) => {
1560
+ const prev = set[set.length - 1];
1561
+ if (part === '**' && prev === '**') {
1562
+ return set;
1563
+ }
1564
+ if (part === '..') {
1565
+ if (prev && prev !== '..' && prev !== '.' && prev !== '**') {
1566
+ set.pop();
1567
+ return set;
1568
+ }
1569
+ }
1570
+ set.push(part);
1571
+ return set;
1572
+ }, []);
1573
+ return parts.length === 0 ? [''] : parts;
1574
+ });
1575
+ }
1576
+ levelTwoFileOptimize(parts) {
1577
+ if (!Array.isArray(parts)) {
1578
+ parts = this.slashSplit(parts);
1579
+ }
1580
+ let didSomething = false;
1581
+ do {
1582
+ didSomething = false;
1583
+ // <pre>/<e>/<rest> -> <pre>/<rest>
1584
+ if (!this.preserveMultipleSlashes) {
1585
+ for (let i = 1; i < parts.length - 1; i++) {
1586
+ const p = parts[i];
1587
+ // don't squeeze out UNC patterns
1588
+ if (i === 1 && p === '' && parts[0] === '')
1589
+ continue;
1590
+ if (p === '.' || p === '') {
1591
+ didSomething = true;
1592
+ parts.splice(i, 1);
1593
+ i--;
1594
+ }
1595
+ }
1596
+ if (parts[0] === '.' &&
1597
+ parts.length === 2 &&
1598
+ (parts[1] === '.' || parts[1] === '')) {
1599
+ didSomething = true;
1600
+ parts.pop();
1601
+ }
1602
+ }
1603
+ // <pre>/<p>/../<rest> -> <pre>/<rest>
1604
+ let dd = 0;
1605
+ while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
1606
+ const p = parts[dd - 1];
1607
+ if (p && p !== '.' && p !== '..' && p !== '**') {
1608
+ didSomething = true;
1609
+ parts.splice(dd - 1, 2);
1610
+ dd -= 2;
1611
+ }
1612
+ }
1613
+ } while (didSomething);
1614
+ return parts.length === 0 ? [''] : parts;
1615
+ }
1616
+ // First phase: single-pattern processing
1617
+ // <pre> is 1 or more portions
1618
+ // <rest> is 1 or more portions
1619
+ // <p> is any portion other than ., .., '', or **
1620
+ // <e> is . or ''
1621
+ //
1622
+ // **/.. is *brutal* for filesystem walking performance, because
1623
+ // it effectively resets the recursive walk each time it occurs,
1624
+ // and ** cannot be reduced out by a .. pattern part like a regexp
1625
+ // or most strings (other than .., ., and '') can be.
1626
+ //
1627
+ // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}
1628
+ // <pre>/<e>/<rest> -> <pre>/<rest>
1629
+ // <pre>/<p>/../<rest> -> <pre>/<rest>
1630
+ // **/**/<rest> -> **/<rest>
1631
+ //
1632
+ // **/*/<rest> -> */**/<rest> <== not valid because ** doesn't follow
1633
+ // this WOULD be allowed if ** did follow symlinks, or * didn't
1634
+ firstPhasePreProcess(globParts) {
1635
+ let didSomething = false;
1636
+ do {
1637
+ didSomething = false;
1638
+ // <pre>/**/../<p>/<p>/<rest> -> {<pre>/../<p>/<p>/<rest>,<pre>/**/<p>/<p>/<rest>}
1639
+ for (let parts of globParts) {
1640
+ let gs = -1;
1641
+ while (-1 !== (gs = parts.indexOf('**', gs + 1))) {
1642
+ let gss = gs;
1643
+ while (parts[gss + 1] === '**') {
1644
+ // <pre>/**/**/<rest> -> <pre>/**/<rest>
1645
+ gss++;
1646
+ }
1647
+ // eg, if gs is 2 and gss is 4, that means we have 3 **
1648
+ // parts, and can remove 2 of them.
1649
+ if (gss > gs) {
1650
+ parts.splice(gs + 1, gss - gs);
1651
+ }
1652
+ let next = parts[gs + 1];
1653
+ const p = parts[gs + 2];
1654
+ const p2 = parts[gs + 3];
1655
+ if (next !== '..')
1656
+ continue;
1657
+ if (!p ||
1658
+ p === '.' ||
1659
+ p === '..' ||
1660
+ !p2 ||
1661
+ p2 === '.' ||
1662
+ p2 === '..') {
1663
+ continue;
1664
+ }
1665
+ didSomething = true;
1666
+ // edit parts in place, and push the new one
1667
+ parts.splice(gs, 1);
1668
+ const other = parts.slice(0);
1669
+ other[gs] = '**';
1670
+ globParts.push(other);
1671
+ gs--;
1672
+ }
1673
+ // <pre>/<e>/<rest> -> <pre>/<rest>
1674
+ if (!this.preserveMultipleSlashes) {
1675
+ for (let i = 1; i < parts.length - 1; i++) {
1676
+ const p = parts[i];
1677
+ // don't squeeze out UNC patterns
1678
+ if (i === 1 && p === '' && parts[0] === '')
1679
+ continue;
1680
+ if (p === '.' || p === '') {
1681
+ didSomething = true;
1682
+ parts.splice(i, 1);
1683
+ i--;
1684
+ }
1685
+ }
1686
+ if (parts[0] === '.' &&
1687
+ parts.length === 2 &&
1688
+ (parts[1] === '.' || parts[1] === '')) {
1689
+ didSomething = true;
1690
+ parts.pop();
1691
+ }
1692
+ }
1693
+ // <pre>/<p>/../<rest> -> <pre>/<rest>
1694
+ let dd = 0;
1695
+ while (-1 !== (dd = parts.indexOf('..', dd + 1))) {
1696
+ const p = parts[dd - 1];
1697
+ if (p && p !== '.' && p !== '..' && p !== '**') {
1698
+ didSomething = true;
1699
+ const needDot = dd === 1 && parts[dd + 1] === '**';
1700
+ const splin = needDot ? ['.'] : [];
1701
+ parts.splice(dd - 1, 2, ...splin);
1702
+ if (parts.length === 0)
1703
+ parts.push('');
1704
+ dd -= 2;
1705
+ }
1706
+ }
1707
+ }
1708
+ } while (didSomething);
1709
+ return globParts;
1710
+ }
1711
+ // second phase: multi-pattern dedupes
1712
+ // {<pre>/*/<rest>,<pre>/<p>/<rest>} -> <pre>/*/<rest>
1713
+ // {<pre>/<rest>,<pre>/<rest>} -> <pre>/<rest>
1714
+ // {<pre>/**/<rest>,<pre>/<rest>} -> <pre>/**/<rest>
1715
+ //
1716
+ // {<pre>/**/<rest>,<pre>/**/<p>/<rest>} -> <pre>/**/<rest>
1717
+ // ^-- not valid because ** doens't follow symlinks
1718
+ secondPhasePreProcess(globParts) {
1719
+ for (let i = 0; i < globParts.length - 1; i++) {
1720
+ for (let j = i + 1; j < globParts.length; j++) {
1721
+ const matched = this.partsMatch(globParts[i], globParts[j], !this.preserveMultipleSlashes);
1722
+ if (!matched)
1723
+ continue;
1724
+ globParts[i] = matched;
1725
+ globParts[j] = [];
1726
+ }
1727
+ }
1728
+ return globParts.filter(gs => gs.length);
1729
+ }
1730
+ partsMatch(a, b, emptyGSMatch = false) {
1731
+ let ai = 0;
1732
+ let bi = 0;
1733
+ let result = [];
1734
+ let which = '';
1735
+ while (ai < a.length && bi < b.length) {
1736
+ if (a[ai] === b[bi]) {
1737
+ result.push(which === 'b' ? b[bi] : a[ai]);
1738
+ ai++;
1739
+ bi++;
1740
+ }
1741
+ else if (emptyGSMatch && a[ai] === '**' && b[bi] === a[ai + 1]) {
1742
+ result.push(a[ai]);
1743
+ ai++;
1744
+ }
1745
+ else if (emptyGSMatch && b[bi] === '**' && a[ai] === b[bi + 1]) {
1746
+ result.push(b[bi]);
1747
+ bi++;
1748
+ }
1749
+ else if (a[ai] === '*' &&
1750
+ b[bi] &&
1751
+ (this.options.dot || !b[bi].startsWith('.')) &&
1752
+ b[bi] !== '**') {
1753
+ if (which === 'b')
1754
+ return false;
1755
+ which = 'a';
1756
+ result.push(a[ai]);
1757
+ ai++;
1758
+ bi++;
1759
+ }
1760
+ else if (b[bi] === '*' &&
1761
+ a[ai] &&
1762
+ (this.options.dot || !a[ai].startsWith('.')) &&
1763
+ a[ai] !== '**') {
1764
+ if (which === 'a')
1765
+ return false;
1766
+ which = 'b';
1767
+ result.push(b[bi]);
1768
+ ai++;
1769
+ bi++;
1770
+ }
1771
+ else {
1772
+ return false;
1773
+ }
1774
+ }
1775
+ // if we fall out of the loop, it means they two are identical
1776
+ // as long as their lengths match
1777
+ return a.length === b.length && result;
1778
+ }
1779
+ parseNegate() {
1780
+ if (this.nonegate)
1781
+ return;
1782
+ const pattern = this.pattern;
1783
+ let negate = false;
1784
+ let negateOffset = 0;
1785
+ for (let i = 0; i < pattern.length && pattern.charAt(i) === '!'; i++) {
1786
+ negate = !negate;
1787
+ negateOffset++;
1788
+ }
1789
+ if (negateOffset)
1790
+ this.pattern = pattern.slice(negateOffset);
1791
+ this.negate = negate;
1792
+ }
1793
+ // set partial to true to test if, for example,
1794
+ // "/a/b" matches the start of "/*/b/*/d"
1795
+ // Partial means, if you run out of file before you run
1796
+ // out of pattern, then that's fine, as long as all
1797
+ // the parts match.
1798
+ matchOne(file, pattern, partial = false) {
1799
+ const options = this.options;
1800
+ // UNC paths like //?/X:/... can match X:/... and vice versa
1801
+ // Drive letters in absolute drive or unc paths are always compared
1802
+ // case-insensitively.
1803
+ if (this.isWindows) {
1804
+ const fileDrive = typeof file[0] === 'string' && /^[a-z]:$/i.test(file[0]);
1805
+ const fileUNC = !fileDrive &&
1806
+ file[0] === '' &&
1807
+ file[1] === '' &&
1808
+ file[2] === '?' &&
1809
+ /^[a-z]:$/i.test(file[3]);
1810
+ const patternDrive = typeof pattern[0] === 'string' && /^[a-z]:$/i.test(pattern[0]);
1811
+ const patternUNC = !patternDrive &&
1812
+ pattern[0] === '' &&
1813
+ pattern[1] === '' &&
1814
+ pattern[2] === '?' &&
1815
+ typeof pattern[3] === 'string' &&
1816
+ /^[a-z]:$/i.test(pattern[3]);
1817
+ const fdi = fileUNC ? 3 : fileDrive ? 0 : undefined;
1818
+ const pdi = patternUNC ? 3 : patternDrive ? 0 : undefined;
1819
+ if (typeof fdi === 'number' && typeof pdi === 'number') {
1820
+ const [fd, pd] = [file[fdi], pattern[pdi]];
1821
+ if (fd.toLowerCase() === pd.toLowerCase()) {
1822
+ pattern[pdi] = fd;
1823
+ if (pdi > fdi) {
1824
+ pattern = pattern.slice(pdi);
1825
+ }
1826
+ else if (fdi > pdi) {
1827
+ file = file.slice(fdi);
1828
+ }
1829
+ }
1830
+ }
1831
+ }
1832
+ // resolve and reduce . and .. portions in the file as well.
1833
+ // dont' need to do the second phase, because it's only one string[]
1834
+ const { optimizationLevel = 1 } = this.options;
1835
+ if (optimizationLevel >= 2) {
1836
+ file = this.levelTwoFileOptimize(file);
1837
+ }
1838
+ this.debug('matchOne', this, { file, pattern });
1839
+ this.debug('matchOne', file.length, pattern.length);
1840
+ for (var fi = 0, pi = 0, fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
1841
+ this.debug('matchOne loop');
1842
+ var p = pattern[pi];
1843
+ var f = file[fi];
1844
+ this.debug(pattern, p, f);
1845
+ // should be impossible.
1846
+ // some invalid regexp stuff in the set.
1847
+ /* c8 ignore start */
1848
+ if (p === false) {
1849
+ return false;
1850
+ }
1851
+ /* c8 ignore stop */
1852
+ if (p === GLOBSTAR) {
1853
+ this.debug('GLOBSTAR', [pattern, p, f]);
1854
+ // "**"
1855
+ // a/**/b/**/c would match the following:
1856
+ // a/b/x/y/z/c
1857
+ // a/x/y/z/b/c
1858
+ // a/b/x/b/x/c
1859
+ // a/b/c
1860
+ // To do this, take the rest of the pattern after
1861
+ // the **, and see if it would match the file remainder.
1862
+ // If so, return success.
1863
+ // If not, the ** "swallows" a segment, and try again.
1864
+ // This is recursively awful.
1865
+ //
1866
+ // a/**/b/**/c matching a/b/x/y/z/c
1867
+ // - a matches a
1868
+ // - doublestar
1869
+ // - matchOne(b/x/y/z/c, b/**/c)
1870
+ // - b matches b
1871
+ // - doublestar
1872
+ // - matchOne(x/y/z/c, c) -> no
1873
+ // - matchOne(y/z/c, c) -> no
1874
+ // - matchOne(z/c, c) -> no
1875
+ // - matchOne(c, c) yes, hit
1876
+ var fr = fi;
1877
+ var pr = pi + 1;
1878
+ if (pr === pl) {
1879
+ this.debug('** at the end');
1880
+ // a ** at the end will just swallow the rest.
1881
+ // We have found a match.
1882
+ // however, it will not swallow /.x, unless
1883
+ // options.dot is set.
1884
+ // . and .. are *never* matched by **, for explosively
1885
+ // exponential reasons.
1886
+ for (; fi < fl; fi++) {
1887
+ if (file[fi] === '.' ||
1888
+ file[fi] === '..' ||
1889
+ (!options.dot && file[fi].charAt(0) === '.'))
1890
+ return false;
1891
+ }
1892
+ return true;
1893
+ }
1894
+ // ok, let's see if we can swallow whatever we can.
1895
+ while (fr < fl) {
1896
+ var swallowee = file[fr];
1897
+ this.debug('\nglobstar while', file, fr, pattern, pr, swallowee);
1898
+ // XXX remove this slice. Just pass the start index.
1899
+ if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
1900
+ this.debug('globstar found match!', fr, fl, swallowee);
1901
+ // found a match.
1902
+ return true;
1903
+ }
1904
+ else {
1905
+ // can't swallow "." or ".." ever.
1906
+ // can only swallow ".foo" when explicitly asked.
1907
+ if (swallowee === '.' ||
1908
+ swallowee === '..' ||
1909
+ (!options.dot && swallowee.charAt(0) === '.')) {
1910
+ this.debug('dot detected!', file, fr, pattern, pr);
1911
+ break;
1912
+ }
1913
+ // ** swallows a segment, and continue.
1914
+ this.debug('globstar swallow a segment, and continue');
1915
+ fr++;
1916
+ }
1917
+ }
1918
+ // no match was found.
1919
+ // However, in partial mode, we can't say this is necessarily over.
1920
+ /* c8 ignore start */
1921
+ if (partial) {
1922
+ // ran out of file
1923
+ this.debug('\n>>> no match, partial?', file, fr, pattern, pr);
1924
+ if (fr === fl) {
1925
+ return true;
1926
+ }
1927
+ }
1928
+ /* c8 ignore stop */
1929
+ return false;
1930
+ }
1931
+ // something other than **
1932
+ // non-magic patterns just have to match exactly
1933
+ // patterns with magic have been turned into regexps.
1934
+ let hit;
1935
+ if (typeof p === 'string') {
1936
+ hit = f === p;
1937
+ this.debug('string match', p, f, hit);
1938
+ }
1939
+ else {
1940
+ hit = p.test(f);
1941
+ this.debug('pattern match', p, f, hit);
1942
+ }
1943
+ if (!hit)
1944
+ return false;
1945
+ }
1946
+ // Note: ending in / means that we'll get a final ""
1947
+ // at the end of the pattern. This can only match a
1948
+ // corresponding "" at the end of the file.
1949
+ // If the file ends in /, then it can only match a
1950
+ // a pattern that ends in /, unless the pattern just
1951
+ // doesn't have any more for it. But, a/b/ should *not*
1952
+ // match "a/b/*", even though "" matches against the
1953
+ // [^/]*? pattern, except in partial mode, where it might
1954
+ // simply not be reached yet.
1955
+ // However, a/b/ should still satisfy a/*
1956
+ // now either we fell off the end of the pattern, or we're done.
1957
+ if (fi === fl && pi === pl) {
1958
+ // ran out of pattern and filename at the same time.
1959
+ // an exact hit!
1960
+ return true;
1961
+ }
1962
+ else if (fi === fl) {
1963
+ // ran out of file, but still had pattern left.
1964
+ // this is ok if we're doing the match as part of
1965
+ // a glob fs traversal.
1966
+ return partial;
1967
+ }
1968
+ else if (pi === pl) {
1969
+ // ran out of pattern, still have file left.
1970
+ // this is only acceptable if we're on the very last
1971
+ // empty segment of a file with a trailing slash.
1972
+ // a/* should match a/b/
1973
+ return fi === fl - 1 && file[fi] === '';
1974
+ /* c8 ignore start */
1975
+ }
1976
+ else {
1977
+ // should be unreachable.
1978
+ throw new Error('wtf?');
1979
+ }
1980
+ /* c8 ignore stop */
1981
+ }
1982
+ braceExpand() {
1983
+ return braceExpand(this.pattern, this.options);
1984
+ }
1985
+ parse(pattern) {
1986
+ assertValidPattern(pattern);
1987
+ const options = this.options;
1988
+ // shortcuts
1989
+ if (pattern === '**')
1990
+ return GLOBSTAR;
1991
+ if (pattern === '')
1992
+ return '';
1993
+ // far and away, the most common glob pattern parts are
1994
+ // *, *.*, and *.<ext> Add a fast check method for those.
1995
+ let m;
1996
+ let fastTest = null;
1997
+ if ((m = pattern.match(starRE))) {
1998
+ fastTest = options.dot ? starTestDot : starTest;
1999
+ }
2000
+ else if ((m = pattern.match(starDotExtRE))) {
2001
+ fastTest = (options.nocase
2002
+ ? options.dot
2003
+ ? starDotExtTestNocaseDot
2004
+ : starDotExtTestNocase
2005
+ : options.dot
2006
+ ? starDotExtTestDot
2007
+ : starDotExtTest)(m[1]);
2008
+ }
2009
+ else if ((m = pattern.match(qmarksRE))) {
2010
+ fastTest = (options.nocase
2011
+ ? options.dot
2012
+ ? qmarksTestNocaseDot
2013
+ : qmarksTestNocase
2014
+ : options.dot
2015
+ ? qmarksTestDot
2016
+ : qmarksTest)(m);
2017
+ }
2018
+ else if ((m = pattern.match(starDotStarRE))) {
2019
+ fastTest = options.dot ? starDotStarTestDot : starDotStarTest;
2020
+ }
2021
+ else if ((m = pattern.match(dotStarRE))) {
2022
+ fastTest = dotStarTest;
2023
+ }
2024
+ const re = AST.fromGlob(pattern, this.options).toMMPattern();
2025
+ return fastTest ? Object.assign(re, { test: fastTest }) : re;
2026
+ }
2027
+ makeRe() {
2028
+ if (this.regexp || this.regexp === false)
2029
+ return this.regexp;
2030
+ // at this point, this.set is a 2d array of partial
2031
+ // pattern strings, or "**".
2032
+ //
2033
+ // It's better to use .match(). This function shouldn't
2034
+ // be used, really, but it's pretty convenient sometimes,
2035
+ // when you just want to work with a regex.
2036
+ const set = this.set;
2037
+ if (!set.length) {
2038
+ this.regexp = false;
2039
+ return this.regexp;
2040
+ }
2041
+ const options = this.options;
2042
+ const twoStar = options.noglobstar
2043
+ ? star
2044
+ : options.dot
2045
+ ? twoStarDot
2046
+ : twoStarNoDot;
2047
+ const flags = new Set(options.nocase ? ['i'] : []);
2048
+ // regexpify non-globstar patterns
2049
+ // if ** is only item, then we just do one twoStar
2050
+ // if ** is first, and there are more, prepend (\/|twoStar\/)? to next
2051
+ // if ** is last, append (\/twoStar|) to previous
2052
+ // if ** is in the middle, append (\/|\/twoStar\/) to previous
2053
+ // then filter out GLOBSTAR symbols
2054
+ let re = set
2055
+ .map(pattern => {
2056
+ const pp = pattern.map(p => {
2057
+ if (p instanceof RegExp) {
2058
+ for (const f of p.flags.split(''))
2059
+ flags.add(f);
2060
+ }
2061
+ return typeof p === 'string'
2062
+ ? regExpEscape(p)
2063
+ : p === GLOBSTAR
2064
+ ? GLOBSTAR
2065
+ : p._src;
2066
+ });
2067
+ pp.forEach((p, i) => {
2068
+ const next = pp[i + 1];
2069
+ const prev = pp[i - 1];
2070
+ if (p !== GLOBSTAR || prev === GLOBSTAR) {
2071
+ return;
2072
+ }
2073
+ if (prev === undefined) {
2074
+ if (next !== undefined && next !== GLOBSTAR) {
2075
+ pp[i + 1] = '(?:\\/|' + twoStar + '\\/)?' + next;
2076
+ }
2077
+ else {
2078
+ pp[i] = twoStar;
2079
+ }
2080
+ }
2081
+ else if (next === undefined) {
2082
+ pp[i - 1] = prev + '(?:\\/|' + twoStar + ')?';
2083
+ }
2084
+ else if (next !== GLOBSTAR) {
2085
+ pp[i - 1] = prev + '(?:\\/|\\/' + twoStar + '\\/)' + next;
2086
+ pp[i + 1] = GLOBSTAR;
2087
+ }
2088
+ });
2089
+ return pp.filter(p => p !== GLOBSTAR).join('/');
2090
+ })
2091
+ .join('|');
2092
+ // need to wrap in parens if we had more than one thing with |,
2093
+ // otherwise only the first will be anchored to ^ and the last to $
2094
+ const [open, close] = set.length > 1 ? ['(?:', ')'] : ['', ''];
2095
+ // must match entire pattern
2096
+ // ending in a * or ** will make it less strict.
2097
+ re = '^' + open + re + close + '$';
2098
+ // can match anything, as long as it's not this.
2099
+ if (this.negate)
2100
+ re = '^(?!' + re + ').+$';
2101
+ try {
2102
+ this.regexp = new RegExp(re, [...flags].join(''));
2103
+ /* c8 ignore start */
2104
+ }
2105
+ catch (ex) {
2106
+ // should be impossible
2107
+ this.regexp = false;
2108
+ }
2109
+ /* c8 ignore stop */
2110
+ return this.regexp;
2111
+ }
2112
+ slashSplit(p) {
2113
+ // if p starts with // on windows, we preserve that
2114
+ // so that UNC paths aren't broken. Otherwise, any number of
2115
+ // / characters are coalesced into one, unless
2116
+ // preserveMultipleSlashes is set to true.
2117
+ if (this.preserveMultipleSlashes) {
2118
+ return p.split('/');
2119
+ }
2120
+ else if (this.isWindows && /^\/\/[^\/]+/.test(p)) {
2121
+ // add an extra '' for the one we lose
2122
+ return ['', ...p.split(/\/+/)];
2123
+ }
2124
+ else {
2125
+ return p.split(/\/+/);
2126
+ }
2127
+ }
2128
+ match(f, partial = this.partial) {
2129
+ this.debug('match', f, this.pattern);
2130
+ // short-circuit in the case of busted things.
2131
+ // comments, etc.
2132
+ if (this.comment) {
2133
+ return false;
2134
+ }
2135
+ if (this.empty) {
2136
+ return f === '';
2137
+ }
2138
+ if (f === '/' && partial) {
2139
+ return true;
2140
+ }
2141
+ const options = this.options;
2142
+ // windows: need to use /, not \
2143
+ if (this.isWindows) {
2144
+ f = f.split('\\').join('/');
2145
+ }
2146
+ // treat the test path as a set of pathparts.
2147
+ const ff = this.slashSplit(f);
2148
+ this.debug(this.pattern, 'split', ff);
2149
+ // just ONE of the pattern sets in this.set needs to match
2150
+ // in order for it to be valid. If negating, then just one
2151
+ // match means that we have failed.
2152
+ // Either way, return on the first hit.
2153
+ const set = this.set;
2154
+ this.debug(this.pattern, 'set', set);
2155
+ // Find the basename of the path by looking for the last non-empty segment
2156
+ let filename = ff[ff.length - 1];
2157
+ if (!filename) {
2158
+ for (let i = ff.length - 2; !filename && i >= 0; i--) {
2159
+ filename = ff[i];
2160
+ }
2161
+ }
2162
+ for (let i = 0; i < set.length; i++) {
2163
+ const pattern = set[i];
2164
+ let file = ff;
2165
+ if (options.matchBase && pattern.length === 1) {
2166
+ file = [filename];
2167
+ }
2168
+ const hit = this.matchOne(file, pattern, partial);
2169
+ if (hit) {
2170
+ if (options.flipNegate) {
2171
+ return true;
2172
+ }
2173
+ return !this.negate;
2174
+ }
2175
+ }
2176
+ // didn't get any hits. this is success if it's a negative
2177
+ // pattern, failure otherwise.
2178
+ if (options.flipNegate) {
2179
+ return false;
2180
+ }
2181
+ return this.negate;
2182
+ }
2183
+ static defaults(def) {
2184
+ return minimatch.defaults(def).Minimatch;
2185
+ }
2186
+ }
2187
+ /* c8 ignore stop */
2188
+ minimatch.AST = AST;
2189
+ minimatch.Minimatch = Minimatch;
2190
+ minimatch.escape = escape;
2191
+ minimatch.unescape = unescape;
2192
+
2193
+ /* Injected with object hook! */
4
2194
 
5
2195
  const list = ref(await rpc.componentGraph());
6
2196
  const searchText = useStorage("vite-inspect-search-text", "");
7
2197
  const includeNodeModules = useStorage("vite-inspect-include-node-modules", false);
8
2198
  const includeVirtual = useStorage("vite-inspect-include-virtual", false);
9
- const exactSearch = useStorage("vite-inspect-exact-search", false);
2199
+ const rootPath = ref(await rpc.root());
2200
+ const userCustomGlobPattern = useStorage("__vue-devtools-graph-glob__", "");
2201
+ function getDepsByExactId(data, searchId) {
2202
+ const result = /* @__PURE__ */ new Set();
2203
+ const queue = [];
2204
+ const idToDepsMap = {};
2205
+ data.forEach((item) => {
2206
+ if (item.deps.length > 0)
2207
+ idToDepsMap[item.id] = item.deps;
2208
+ });
2209
+ data.forEach((item) => {
2210
+ if (item.id === searchId || item.id in idToDepsMap && item.deps.includes(searchId)) {
2211
+ queue.push(item.id);
2212
+ result.add(item);
2213
+ }
2214
+ });
2215
+ while (queue.length > 0) {
2216
+ const currentId = queue.shift();
2217
+ const referencedIds = idToDepsMap[currentId];
2218
+ if (referencedIds) {
2219
+ referencedIds.forEach((referencedId) => {
2220
+ const item = data.find((item2) => item2.id === referencedId);
2221
+ if (!result.has(item)) {
2222
+ queue.push(referencedId);
2223
+ result.add(item);
2224
+ }
2225
+ });
2226
+ }
2227
+ }
2228
+ return Array.from(result);
2229
+ }
2230
+ function uniqById(data) {
2231
+ const uniqueSet = /* @__PURE__ */ new Set();
2232
+ const uniqueArray = [];
2233
+ for (const item of data) {
2234
+ if (!item)
2235
+ continue;
2236
+ if (!uniqueSet.has(item.id)) {
2237
+ uniqueSet.add(item.id);
2238
+ uniqueArray.push(item);
2239
+ }
2240
+ }
2241
+ return uniqueArray;
2242
+ }
2243
+ function fuzzySearchDeps(data, id) {
2244
+ const fuzzySearcher = new Fuse(data, {
2245
+ ignoreLocation: true,
2246
+ keys: ["id"],
2247
+ shouldSort: true,
2248
+ threshold: 0.1
2249
+ });
2250
+ const result = fuzzySearcher.search(id).map((i) => i.item);
2251
+ if (!result) {
2252
+ return {
2253
+ main: [],
2254
+ allWithDeps: []
2255
+ };
2256
+ }
2257
+ return {
2258
+ main: result,
2259
+ allWithDeps: uniqById(result.flatMap((item) => getDepsByExactId(data, item.id)))
2260
+ };
2261
+ }
2262
+ function filterByUserDefinedGlob(data) {
2263
+ if (!userCustomGlobPattern.value.trim().length)
2264
+ return data;
2265
+ const globPattern = userCustomGlobPattern.value.trim().split(", ");
2266
+ const globInstances = new Map(globPattern.map((pattern) => [pattern, new Minimatch(pattern, { matchBase: true })]));
2267
+ return data.filter((item) => globPattern.every(
2268
+ (pattern) => globInstances.get(pattern).match(item.id)
2269
+ ));
2270
+ }
2271
+ const { graphSettings } = useGraphSettings();
10
2272
  const searchResults = computed(() => {
11
2273
  let data = list.value || [];
12
2274
  if (!includeNodeModules.value)
13
2275
  data = data.filter((item) => !item.id.includes("/node_modules/"));
14
2276
  if (!includeVirtual.value)
15
2277
  data = data.filter((item) => !item.virtual);
16
- if (!searchText.value)
17
- return data;
18
- if (exactSearch.value) {
19
- return data.filter(
20
- (item) => item.id.includes(searchText.value) || item.plugins.some((plugin) => plugin.name.includes(searchText.value))
21
- );
22
- } else {
23
- const fuse = new Fuse(data, {
24
- shouldSort: true,
25
- keys: ["id", "plugins"]
26
- });
27
- return fuse.search(searchText.value).map((i) => i.item);
2278
+ if (graphSettings.value.enableUserDefinedGlob)
2279
+ data = filterByUserDefinedGlob(data);
2280
+ if (!searchText.value) {
2281
+ return {
2282
+ main: [],
2283
+ data
2284
+ };
28
2285
  }
2286
+ const { main, allWithDeps } = fuzzySearchDeps(data, searchText.value.trim());
2287
+ return {
2288
+ main,
2289
+ data: allWithDeps
2290
+ };
29
2291
  });
30
2292
 
31
2293
  /* Injected with object hook! */
32
2294
 
33
2295
  const _hoisted_1$1 = {
34
- "h-54px": "",
35
- flex: "~ none gap-4",
2296
+ flex: "~ justify-between items-center",
36
2297
  border: "b base",
37
2298
  "pl-4": "",
38
2299
  "pr-6": "",
39
2300
  "font-light": "",
40
2301
  "children:my-auto": ""
41
2302
  };
42
- const _hoisted_2 = /* @__PURE__ */ createBaseVNode("div", {
2303
+ const _hoisted_2$1 = {
2304
+ flex: "~ gap-4 items-center",
2305
+ "h-54px": ""
2306
+ };
2307
+ const _hoisted_3$1 = /* @__PURE__ */ createBaseVNode("div", {
43
2308
  "i-carbon-ibm-watson-discovery": "",
44
2309
  title: "Vite Inspect",
45
2310
  "text-xl": ""
46
2311
  }, null, -1);
47
- const _hoisted_3 = { class: "h-min flex flex-col select-none text-xs" };
48
- const _hoisted_4 = { class: "flex" };
49
- const _hoisted_5 = /* @__PURE__ */ createBaseVNode("div", { class: "ml-1" }, "node_modules", -1);
50
- const _hoisted_6 = { class: "flex gap-2" };
2312
+ const _hoisted_4 = { class: "h-min flex flex-col select-none text-xs" };
2313
+ const _hoisted_5 = { class: "flex" };
2314
+ const _hoisted_6 = /* @__PURE__ */ createBaseVNode("div", { class: "ml-1" }, "node_modules", -1);
51
2315
  const _hoisted_7 = { class: "flex" };
52
2316
  const _hoisted_8 = /* @__PURE__ */ createBaseVNode("div", { class: "ml-1" }, "virtual", -1);
53
- const _hoisted_9 = { class: "flex" };
54
- const _hoisted_10 = /* @__PURE__ */ createBaseVNode("div", { class: "ml-1" }, "exact search", -1);
2317
+ const _hoisted_9 = /* @__PURE__ */ createBaseVNode("div", {
2318
+ "i-mdi-regex": "",
2319
+ title: "Glob pattern",
2320
+ "text-xl": ""
2321
+ }, null, -1);
55
2322
  const _sfc_main$1 = /* @__PURE__ */ defineComponent({
56
2323
  __name: "SearchBox",
57
2324
  setup(__props) {
2325
+ const { graphSettings } = useGraphSettings();
58
2326
  return (_ctx, _cache) => {
59
2327
  return openBlock(), createElementBlock("nav", _hoisted_1$1, [
60
- _hoisted_2,
61
- withDirectives(createBaseVNode("input", {
62
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isRef(searchText) ? searchText.value = $event : null),
63
- type: "text",
64
- class: "border border-base rounded bg-transparent px-3 py-1 !outline-none",
65
- placeholder: "Search..."
66
- }, null, 512), [
67
- [vModelText, unref(searchText)]
68
- ]),
69
- createBaseVNode("div", _hoisted_3, [
70
- createBaseVNode("label", _hoisted_4, [
71
- withDirectives(createBaseVNode("input", {
72
- "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => isRef(includeNodeModules) ? includeNodeModules.value = $event : null),
73
- type: "checkbox",
74
- class: "my-auto"
75
- }, null, 512), [
76
- [vModelCheckbox, unref(includeNodeModules)]
77
- ]),
78
- _hoisted_5
2328
+ createBaseVNode("div", _hoisted_2$1, [
2329
+ _hoisted_3$1,
2330
+ withDirectives(createBaseVNode("input", {
2331
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isRef(searchText) ? searchText.value = $event : null),
2332
+ type: "text",
2333
+ class: "border border-base rounded bg-transparent px-3 py-1 !outline-none",
2334
+ placeholder: "Search..."
2335
+ }, null, 512), [
2336
+ [vModelText, unref(searchText)]
79
2337
  ]),
80
- createBaseVNode("div", _hoisted_6, [
81
- createBaseVNode("label", _hoisted_7, [
2338
+ createBaseVNode("div", _hoisted_4, [
2339
+ createBaseVNode("label", _hoisted_5, [
82
2340
  withDirectives(createBaseVNode("input", {
83
- "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => isRef(includeVirtual) ? includeVirtual.value = $event : null),
2341
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => isRef(includeNodeModules) ? includeNodeModules.value = $event : null),
84
2342
  type: "checkbox",
85
2343
  class: "my-auto"
86
2344
  }, null, 512), [
87
- [vModelCheckbox, unref(includeVirtual)]
2345
+ [vModelCheckbox, unref(includeNodeModules)]
88
2346
  ]),
89
- _hoisted_8
2347
+ _hoisted_6
90
2348
  ]),
91
- createBaseVNode("label", _hoisted_9, [
2349
+ createBaseVNode("label", _hoisted_7, [
92
2350
  withDirectives(createBaseVNode("input", {
93
- "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => isRef(exactSearch) ? exactSearch.value = $event : null),
2351
+ "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => isRef(includeVirtual) ? includeVirtual.value = $event : null),
94
2352
  type: "checkbox",
95
2353
  class: "my-auto"
96
2354
  }, null, 512), [
97
- [vModelCheckbox, unref(exactSearch)]
2355
+ [vModelCheckbox, unref(includeVirtual)]
98
2356
  ]),
99
- _hoisted_10
2357
+ _hoisted_8
2358
+ ])
2359
+ ]),
2360
+ unref(graphSettings).enableUserDefinedGlob ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
2361
+ _hoisted_9,
2362
+ withDirectives(createBaseVNode("input", {
2363
+ "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => isRef(userCustomGlobPattern) ? userCustomGlobPattern.value = $event : null),
2364
+ type: "text",
2365
+ class: "w-300px border border-base rounded bg-transparent px-3 py-1 !outline-none",
2366
+ placeholder: "Your custom glob pattern"
2367
+ }, null, 512), [
2368
+ [vModelText, unref(userCustomGlobPattern)]
100
2369
  ])
101
- ])
2370
+ ], 64)) : createCommentVNode("", true)
2371
+ ]),
2372
+ createBaseVNode("div", null, [
2373
+ renderSlot(_ctx.$slots, "right")
102
2374
  ])
103
2375
  ]);
104
2376
  };
@@ -52149,30 +54421,68 @@ Network.prototype.getOptionsFromConfigurator = function () {
52149
54421
  /* Injected with object hook! */
52150
54422
 
52151
54423
  const _hoisted_1 = {
54424
+ relative: "",
52152
54425
  "h-screen": "",
52153
54426
  "w-full": "",
52154
54427
  flex: "",
52155
54428
  "flex-col": "",
52156
54429
  "n-panel-grids": ""
52157
54430
  };
54431
+ const _hoisted_2 = /* @__PURE__ */ createBaseVNode("div", { "i-carbon-settings": "" }, null, -1);
54432
+ const _hoisted_3 = [
54433
+ _hoisted_2
54434
+ ];
52158
54435
  const _sfc_main = /* @__PURE__ */ defineComponent({
52159
54436
  __name: "graph",
52160
54437
  setup(__props) {
52161
54438
  const isDark = useDark();
52162
54439
  const container = ref();
54440
+ const modulesMap = shallowRef(/* @__PURE__ */ new Map());
54441
+ const settings = useGraphSettings();
54442
+ const { meta: metaKeyPressed } = useMagicKeys({
54443
+ passive: true
54444
+ });
54445
+ const isHoveringNode = ref(false);
54446
+ const lastSelectedNode = ref();
54447
+ const client = useDevtoolsClient();
54448
+ function getHoverPath(level, fullPath, rootPath2) {
54449
+ switch (level) {
54450
+ case "absolute":
54451
+ return fullPath;
54452
+ case "custom":
54453
+ return fullPath.split("/").slice(-settings.graphSettings.value.hoverPathLevelCustom).join("/");
54454
+ case "root":
54455
+ default:
54456
+ return fullPath.replace(rootPath2, "");
54457
+ }
54458
+ }
52163
54459
  const data = computed(() => {
52164
- const nodes = searchResults.value?.map((mod) => {
54460
+ const { data: data2, main } = searchResults.value;
54461
+ if (!data2)
54462
+ return { node: [], edges: [] };
54463
+ const nodes = data2.map((mod) => {
52165
54464
  const path = mod.id.replace(/\?.*$/, "").replace(/\#.*$/, "");
54465
+ const pathSegments = path.split("/");
54466
+ const id = mod.id;
54467
+ if (!modulesMap.value.has(id))
54468
+ modulesMap.value.set(id, { filePath: path });
54469
+ else
54470
+ modulesMap.value.get(id).filePath = path;
54471
+ const isInMain = !!main.find((i) => i.id === id);
52166
54472
  return {
52167
- id: mod.id,
52168
- label: path.split("/").splice(-1)[0],
54473
+ id,
54474
+ label: isInMain ? `<b>${pathSegments.at(-1)}</b>` : pathSegments.at(-1),
54475
+ title: getHoverPath(settings.graphSettings.value.hoverPathLevel, path, rootPath.value),
52169
54476
  group: path.match(/\.(\w+)$/)?.[1] || "unknown",
52170
54477
  size: 15 + Math.min(mod.deps.length / 2, 8),
52171
- font: { color: isDark.value ? "white" : "black" },
54478
+ font: {
54479
+ color: isInMain ? "#F19B4A" : isDark.value ? "white" : "black",
54480
+ multi: "html"
54481
+ },
52172
54482
  shape: mod.id.includes("/node_modules/") ? "hexagon" : mod.virtual ? "diamond" : "dot"
52173
54483
  };
52174
54484
  });
52175
- const edges = searchResults.value?.flatMap((mod) => mod.deps.map((dep) => ({
54485
+ const edges = data2.flatMap((mod) => mod.deps.map((dep) => ({
52176
54486
  from: mod.id,
52177
54487
  to: dep,
52178
54488
  arrows: {
@@ -52193,6 +54503,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
52193
54503
  shape: "dot",
52194
54504
  size: 16
52195
54505
  },
54506
+ interaction: {
54507
+ hover: true
54508
+ },
52196
54509
  physics: {
52197
54510
  maxVelocity: 146,
52198
54511
  solver: "forceAtlas2Based",
@@ -52233,19 +54546,67 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
52233
54546
  }
52234
54547
  };
52235
54548
  const network = new Network(container.value, data.value, options);
54549
+ const resetNodeStyle = () => {
54550
+ if (!settings.graphSettings.value.highlightSelection)
54551
+ return;
54552
+ network.body.data.nodes.update(network.body.data.nodes.getIds().map((id) => ({ id, size: 16 })));
54553
+ network.body.data.edges.update(network.body.data.edges.getIds().map((id) => {
54554
+ const group = network.body.data.nodes.get(network.body.data.edges.get(id).from).group;
54555
+ return {
54556
+ id,
54557
+ // default unknown group color
54558
+ color: options.groups[group]?.color ?? "#97C2FC"
54559
+ };
54560
+ }));
54561
+ };
54562
+ network.on("click", (params) => {
54563
+ const nodeId = params.nodes?.[0];
54564
+ if (!nodeId)
54565
+ return resetNodeStyle();
54566
+ if (settings.graphSettings.value.clickOpenInEditor && metaKeyPressed.value)
54567
+ return client.value.openInEditor(modulesMap.value.get(nodeId).filePath);
54568
+ if (lastSelectedNode.value && lastSelectedNode.value !== nodeId)
54569
+ resetNodeStyle();
54570
+ if (!settings.graphSettings.value.highlightSelection)
54571
+ return;
54572
+ const nonConnectedNodes = network.body.data.nodes.getIds().filter((id) => !network.getConnectedNodes(nodeId).includes(id) && nodeId !== id);
54573
+ const nonConnectedEdges = network.body.data.edges.getIds().filter((id) => !network.getConnectedEdges(nodeId).includes(id));
54574
+ network.body.data.nodes.update(nonConnectedNodes.map((id) => ({ id, color: "rgb(69,69,69,.3)" })));
54575
+ network.body.data.edges.update(nonConnectedEdges.map((id) => ({ id, color: "rgb(69,69,69,.3)" })));
54576
+ network.body.data.nodes.update([{ id: nodeId, color: options.groups[network.body.data.nodes.get(nodeId).group]?.color, size: 26 }]);
54577
+ lastSelectedNode.value = nodeId;
54578
+ });
54579
+ network.on("hoverNode", () => {
54580
+ isHoveringNode.value = true;
54581
+ });
54582
+ network.on("blurNode", () => {
54583
+ isHoveringNode.value = false;
54584
+ });
52236
54585
  watch(data, () => {
52237
54586
  network.setData(data.value);
52238
54587
  });
52239
54588
  });
54589
+ const { showGraphSetting } = useGraphSettings();
52240
54590
  return (_ctx, _cache) => {
52241
54591
  const _component_SearchBox = _sfc_main$1;
54592
+ const _component_GraphSettings = _sfc_main$2;
52242
54593
  return openBlock(), createElementBlock("div", _hoisted_1, [
52243
- createVNode(_component_SearchBox),
54594
+ createVNode(_component_SearchBox, null, {
54595
+ right: withCtx(() => [
54596
+ createBaseVNode("button", {
54597
+ "aria-label": "Open graph settings",
54598
+ onClick: _cache[0] || (_cache[0] = ($event) => showGraphSetting.value = true)
54599
+ }, _hoisted_3)
54600
+ ]),
54601
+ _: 1
54602
+ }),
52244
54603
  createBaseVNode("div", {
52245
54604
  ref_key: "container",
52246
54605
  ref: container,
52247
- flex: "1"
52248
- }, null, 512)
54606
+ flex: "1",
54607
+ class: normalizeClass([unref(isHoveringNode) && unref(metaKeyPressed) ? "cursor-pointer" : ""])
54608
+ }, null, 2),
54609
+ createVNode(_component_GraphSettings)
52249
54610
  ]);
52250
54611
  };
52251
54612
  }