UNPKG

198 kBJavaScriptView Raw
1/*
2 @license
3 Rollup.js v2.33.0
4 Sun, 01 Nov 2020 06:52:02 GMT - commit 3d719bb543063288e64035c5fcd7892e0d204533
5
6
7 https://github.com/rollup/rollup
8
9 Released under the MIT License.
10*/
11import { createCommonjsModule, defaultOnWarn, ensureArray as ensureArray$1, warnUnknownOptions, getAugmentedNamespace, fseventsImporter, rollupInternal } from './rollup.js';
12import sysPath, { sep, resolve } from 'path';
13import 'crypto';
14import fs from 'fs';
15import require$$0$2 from 'events';
16import util from 'util';
17import require$$0$1 from 'stream';
18import require$$1$1, { platform } from 'os';
19
20var utils = createCommonjsModule(function (module, exports) {
21
22exports.isInteger = num => {
23 if (typeof num === 'number') {
24 return Number.isInteger(num);
25 }
26 if (typeof num === 'string' && num.trim() !== '') {
27 return Number.isInteger(Number(num));
28 }
29 return false;
30};
31
32/**
33 * Find a node of the given type
34 */
35
36exports.find = (node, type) => node.nodes.find(node => node.type === type);
37
38/**
39 * Find a node of the given type
40 */
41
42exports.exceedsLimit = (min, max, step = 1, limit) => {
43 if (limit === false) return false;
44 if (!exports.isInteger(min) || !exports.isInteger(max)) return false;
45 return ((Number(max) - Number(min)) / Number(step)) >= limit;
46};
47
48/**
49 * Escape the given node with '\\' before node.value
50 */
51
52exports.escapeNode = (block, n = 0, type) => {
53 let node = block.nodes[n];
54 if (!node) return;
55
56 if ((type && node.type === type) || node.type === 'open' || node.type === 'close') {
57 if (node.escaped !== true) {
58 node.value = '\\' + node.value;
59 node.escaped = true;
60 }
61 }
62};
63
64/**
65 * Returns true if the given brace node should be enclosed in literal braces
66 */
67
68exports.encloseBrace = node => {
69 if (node.type !== 'brace') return false;
70 if ((node.commas >> 0 + node.ranges >> 0) === 0) {
71 node.invalid = true;
72 return true;
73 }
74 return false;
75};
76
77/**
78 * Returns true if a brace node is invalid.
79 */
80
81exports.isInvalidBrace = block => {
82 if (block.type !== 'brace') return false;
83 if (block.invalid === true || block.dollar) return true;
84 if ((block.commas >> 0 + block.ranges >> 0) === 0) {
85 block.invalid = true;
86 return true;
87 }
88 if (block.open !== true || block.close !== true) {
89 block.invalid = true;
90 return true;
91 }
92 return false;
93};
94
95/**
96 * Returns true if a node is an open or close node
97 */
98
99exports.isOpenOrClose = node => {
100 if (node.type === 'open' || node.type === 'close') {
101 return true;
102 }
103 return node.open === true || node.close === true;
104};
105
106/**
107 * Reduce an array of text nodes.
108 */
109
110exports.reduce = nodes => nodes.reduce((acc, node) => {
111 if (node.type === 'text') acc.push(node.value);
112 if (node.type === 'range') node.type = 'text';
113 return acc;
114}, []);
115
116/**
117 * Flatten an array
118 */
119
120exports.flatten = (...args) => {
121 const result = [];
122 const flat = arr => {
123 for (let i = 0; i < arr.length; i++) {
124 let ele = arr[i];
125 Array.isArray(ele) ? flat(ele) : ele !== void 0 && result.push(ele);
126 }
127 return result;
128 };
129 flat(args);
130 return result;
131};
132});
133
134var stringify = (ast, options = {}) => {
135 let stringify = (node, parent = {}) => {
136 let invalidBlock = options.escapeInvalid && utils.isInvalidBrace(parent);
137 let invalidNode = node.invalid === true && options.escapeInvalid === true;
138 let output = '';
139
140 if (node.value) {
141 if ((invalidBlock || invalidNode) && utils.isOpenOrClose(node)) {
142 return '\\' + node.value;
143 }
144 return node.value;
145 }
146
147 if (node.value) {
148 return node.value;
149 }
150
151 if (node.nodes) {
152 for (let child of node.nodes) {
153 output += stringify(child);
154 }
155 }
156 return output;
157 };
158
159 return stringify(ast);
160};
161
162/*!
163 * is-number <https://github.com/jonschlinkert/is-number>
164 *
165 * Copyright (c) 2014-present, Jon Schlinkert.
166 * Released under the MIT License.
167 */
168
169var isNumber = function(num) {
170 if (typeof num === 'number') {
171 return num - num === 0;
172 }
173 if (typeof num === 'string' && num.trim() !== '') {
174 return Number.isFinite ? Number.isFinite(+num) : isFinite(+num);
175 }
176 return false;
177};
178
179const toRegexRange = (min, max, options) => {
180 if (isNumber(min) === false) {
181 throw new TypeError('toRegexRange: expected the first argument to be a number');
182 }
183
184 if (max === void 0 || min === max) {
185 return String(min);
186 }
187
188 if (isNumber(max) === false) {
189 throw new TypeError('toRegexRange: expected the second argument to be a number.');
190 }
191
192 let opts = { relaxZeros: true, ...options };
193 if (typeof opts.strictZeros === 'boolean') {
194 opts.relaxZeros = opts.strictZeros === false;
195 }
196
197 let relax = String(opts.relaxZeros);
198 let shorthand = String(opts.shorthand);
199 let capture = String(opts.capture);
200 let wrap = String(opts.wrap);
201 let cacheKey = min + ':' + max + '=' + relax + shorthand + capture + wrap;
202
203 if (toRegexRange.cache.hasOwnProperty(cacheKey)) {
204 return toRegexRange.cache[cacheKey].result;
205 }
206
207 let a = Math.min(min, max);
208 let b = Math.max(min, max);
209
210 if (Math.abs(a - b) === 1) {
211 let result = min + '|' + max;
212 if (opts.capture) {
213 return `(${result})`;
214 }
215 if (opts.wrap === false) {
216 return result;
217 }
218 return `(?:${result})`;
219 }
220
221 let isPadded = hasPadding(min) || hasPadding(max);
222 let state = { min, max, a, b };
223 let positives = [];
224 let negatives = [];
225
226 if (isPadded) {
227 state.isPadded = isPadded;
228 state.maxLen = String(state.max).length;
229 }
230
231 if (a < 0) {
232 let newMin = b < 0 ? Math.abs(b) : 1;
233 negatives = splitToPatterns(newMin, Math.abs(a), state, opts);
234 a = state.a = 0;
235 }
236
237 if (b >= 0) {
238 positives = splitToPatterns(a, b, state, opts);
239 }
240
241 state.negatives = negatives;
242 state.positives = positives;
243 state.result = collatePatterns(negatives, positives);
244
245 if (opts.capture === true) {
246 state.result = `(${state.result})`;
247 } else if (opts.wrap !== false && (positives.length + negatives.length) > 1) {
248 state.result = `(?:${state.result})`;
249 }
250
251 toRegexRange.cache[cacheKey] = state;
252 return state.result;
253};
254
255function collatePatterns(neg, pos, options) {
256 let onlyNegative = filterPatterns(neg, pos, '-', false) || [];
257 let onlyPositive = filterPatterns(pos, neg, '', false) || [];
258 let intersected = filterPatterns(neg, pos, '-?', true) || [];
259 let subpatterns = onlyNegative.concat(intersected).concat(onlyPositive);
260 return subpatterns.join('|');
261}
262
263function splitToRanges(min, max) {
264 let nines = 1;
265 let zeros = 1;
266
267 let stop = countNines(min, nines);
268 let stops = new Set([max]);
269
270 while (min <= stop && stop <= max) {
271 stops.add(stop);
272 nines += 1;
273 stop = countNines(min, nines);
274 }
275
276 stop = countZeros(max + 1, zeros) - 1;
277
278 while (min < stop && stop <= max) {
279 stops.add(stop);
280 zeros += 1;
281 stop = countZeros(max + 1, zeros) - 1;
282 }
283
284 stops = [...stops];
285 stops.sort(compare);
286 return stops;
287}
288
289/**
290 * Convert a range to a regex pattern
291 * @param {Number} `start`
292 * @param {Number} `stop`
293 * @return {String}
294 */
295
296function rangeToPattern(start, stop, options) {
297 if (start === stop) {
298 return { pattern: start, count: [], digits: 0 };
299 }
300
301 let zipped = zip(start, stop);
302 let digits = zipped.length;
303 let pattern = '';
304 let count = 0;
305
306 for (let i = 0; i < digits; i++) {
307 let [startDigit, stopDigit] = zipped[i];
308
309 if (startDigit === stopDigit) {
310 pattern += startDigit;
311
312 } else if (startDigit !== '0' || stopDigit !== '9') {
313 pattern += toCharacterClass(startDigit, stopDigit);
314
315 } else {
316 count++;
317 }
318 }
319
320 if (count) {
321 pattern += options.shorthand === true ? '\\d' : '[0-9]';
322 }
323
324 return { pattern, count: [count], digits };
325}
326
327function splitToPatterns(min, max, tok, options) {
328 let ranges = splitToRanges(min, max);
329 let tokens = [];
330 let start = min;
331 let prev;
332
333 for (let i = 0; i < ranges.length; i++) {
334 let max = ranges[i];
335 let obj = rangeToPattern(String(start), String(max), options);
336 let zeros = '';
337
338 if (!tok.isPadded && prev && prev.pattern === obj.pattern) {
339 if (prev.count.length > 1) {
340 prev.count.pop();
341 }
342
343 prev.count.push(obj.count[0]);
344 prev.string = prev.pattern + toQuantifier(prev.count);
345 start = max + 1;
346 continue;
347 }
348
349 if (tok.isPadded) {
350 zeros = padZeros(max, tok, options);
351 }
352
353 obj.string = zeros + obj.pattern + toQuantifier(obj.count);
354 tokens.push(obj);
355 start = max + 1;
356 prev = obj;
357 }
358
359 return tokens;
360}
361
362function filterPatterns(arr, comparison, prefix, intersection, options) {
363 let result = [];
364
365 for (let ele of arr) {
366 let { string } = ele;
367
368 // only push if _both_ are negative...
369 if (!intersection && !contains(comparison, 'string', string)) {
370 result.push(prefix + string);
371 }
372
373 // or _both_ are positive
374 if (intersection && contains(comparison, 'string', string)) {
375 result.push(prefix + string);
376 }
377 }
378 return result;
379}
380
381/**
382 * Zip strings
383 */
384
385function zip(a, b) {
386 let arr = [];
387 for (let i = 0; i < a.length; i++) arr.push([a[i], b[i]]);
388 return arr;
389}
390
391function compare(a, b) {
392 return a > b ? 1 : b > a ? -1 : 0;
393}
394
395function contains(arr, key, val) {
396 return arr.some(ele => ele[key] === val);
397}
398
399function countNines(min, len) {
400 return Number(String(min).slice(0, -len) + '9'.repeat(len));
401}
402
403function countZeros(integer, zeros) {
404 return integer - (integer % Math.pow(10, zeros));
405}
406
407function toQuantifier(digits) {
408 let [start = 0, stop = ''] = digits;
409 if (stop || start > 1) {
410 return `{${start + (stop ? ',' + stop : '')}}`;
411 }
412 return '';
413}
414
415function toCharacterClass(a, b, options) {
416 return `[${a}${(b - a === 1) ? '' : '-'}${b}]`;
417}
418
419function hasPadding(str) {
420 return /^-?(0+)\d/.test(str);
421}
422
423function padZeros(value, tok, options) {
424 if (!tok.isPadded) {
425 return value;
426 }
427
428 let diff = Math.abs(tok.maxLen - String(value).length);
429 let relax = options.relaxZeros !== false;
430
431 switch (diff) {
432 case 0:
433 return '';
434 case 1:
435 return relax ? '0?' : '0';
436 case 2:
437 return relax ? '0{0,2}' : '00';
438 default: {
439 return relax ? `0{0,${diff}}` : `0{${diff}}`;
440 }
441 }
442}
443
444/**
445 * Cache
446 */
447
448toRegexRange.cache = {};
449toRegexRange.clearCache = () => (toRegexRange.cache = {});
450
451/**
452 * Expose `toRegexRange`
453 */
454
455var toRegexRange_1 = toRegexRange;
456
457const isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val);
458
459const transform = toNumber => {
460 return value => toNumber === true ? Number(value) : String(value);
461};
462
463const isValidValue = value => {
464 return typeof value === 'number' || (typeof value === 'string' && value !== '');
465};
466
467const isNumber$1 = num => Number.isInteger(+num);
468
469const zeros = input => {
470 let value = `${input}`;
471 let index = -1;
472 if (value[0] === '-') value = value.slice(1);
473 if (value === '0') return false;
474 while (value[++index] === '0');
475 return index > 0;
476};
477
478const stringify$1 = (start, end, options) => {
479 if (typeof start === 'string' || typeof end === 'string') {
480 return true;
481 }
482 return options.stringify === true;
483};
484
485const pad = (input, maxLength, toNumber) => {
486 if (maxLength > 0) {
487 let dash = input[0] === '-' ? '-' : '';
488 if (dash) input = input.slice(1);
489 input = (dash + input.padStart(dash ? maxLength - 1 : maxLength, '0'));
490 }
491 if (toNumber === false) {
492 return String(input);
493 }
494 return input;
495};
496
497const toMaxLen = (input, maxLength) => {
498 let negative = input[0] === '-' ? '-' : '';
499 if (negative) {
500 input = input.slice(1);
501 maxLength--;
502 }
503 while (input.length < maxLength) input = '0' + input;
504 return negative ? ('-' + input) : input;
505};
506
507const toSequence = (parts, options) => {
508 parts.negatives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
509 parts.positives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
510
511 let prefix = options.capture ? '' : '?:';
512 let positives = '';
513 let negatives = '';
514 let result;
515
516 if (parts.positives.length) {
517 positives = parts.positives.join('|');
518 }
519
520 if (parts.negatives.length) {
521 negatives = `-(${prefix}${parts.negatives.join('|')})`;
522 }
523
524 if (positives && negatives) {
525 result = `${positives}|${negatives}`;
526 } else {
527 result = positives || negatives;
528 }
529
530 if (options.wrap) {
531 return `(${prefix}${result})`;
532 }
533
534 return result;
535};
536
537const toRange = (a, b, isNumbers, options) => {
538 if (isNumbers) {
539 return toRegexRange_1(a, b, { wrap: false, ...options });
540 }
541
542 let start = String.fromCharCode(a);
543 if (a === b) return start;
544
545 let stop = String.fromCharCode(b);
546 return `[${start}-${stop}]`;
547};
548
549const toRegex = (start, end, options) => {
550 if (Array.isArray(start)) {
551 let wrap = options.wrap === true;
552 let prefix = options.capture ? '' : '?:';
553 return wrap ? `(${prefix}${start.join('|')})` : start.join('|');
554 }
555 return toRegexRange_1(start, end, options);
556};
557
558const rangeError = (...args) => {
559 return new RangeError('Invalid range arguments: ' + util.inspect(...args));
560};
561
562const invalidRange = (start, end, options) => {
563 if (options.strictRanges === true) throw rangeError([start, end]);
564 return [];
565};
566
567const invalidStep = (step, options) => {
568 if (options.strictRanges === true) {
569 throw new TypeError(`Expected step "${step}" to be a number`);
570 }
571 return [];
572};
573
574const fillNumbers = (start, end, step = 1, options = {}) => {
575 let a = Number(start);
576 let b = Number(end);
577
578 if (!Number.isInteger(a) || !Number.isInteger(b)) {
579 if (options.strictRanges === true) throw rangeError([start, end]);
580 return [];
581 }
582
583 // fix negative zero
584 if (a === 0) a = 0;
585 if (b === 0) b = 0;
586
587 let descending = a > b;
588 let startString = String(start);
589 let endString = String(end);
590 let stepString = String(step);
591 step = Math.max(Math.abs(step), 1);
592
593 let padded = zeros(startString) || zeros(endString) || zeros(stepString);
594 let maxLen = padded ? Math.max(startString.length, endString.length, stepString.length) : 0;
595 let toNumber = padded === false && stringify$1(start, end, options) === false;
596 let format = options.transform || transform(toNumber);
597
598 if (options.toRegex && step === 1) {
599 return toRange(toMaxLen(start, maxLen), toMaxLen(end, maxLen), true, options);
600 }
601
602 let parts = { negatives: [], positives: [] };
603 let push = num => parts[num < 0 ? 'negatives' : 'positives'].push(Math.abs(num));
604 let range = [];
605 let index = 0;
606
607 while (descending ? a >= b : a <= b) {
608 if (options.toRegex === true && step > 1) {
609 push(a);
610 } else {
611 range.push(pad(format(a, index), maxLen, toNumber));
612 }
613 a = descending ? a - step : a + step;
614 index++;
615 }
616
617 if (options.toRegex === true) {
618 return step > 1
619 ? toSequence(parts, options)
620 : toRegex(range, null, { wrap: false, ...options });
621 }
622
623 return range;
624};
625
626const fillLetters = (start, end, step = 1, options = {}) => {
627 if ((!isNumber$1(start) && start.length > 1) || (!isNumber$1(end) && end.length > 1)) {
628 return invalidRange(start, end, options);
629 }
630
631
632 let format = options.transform || (val => String.fromCharCode(val));
633 let a = `${start}`.charCodeAt(0);
634 let b = `${end}`.charCodeAt(0);
635
636 let descending = a > b;
637 let min = Math.min(a, b);
638 let max = Math.max(a, b);
639
640 if (options.toRegex && step === 1) {
641 return toRange(min, max, false, options);
642 }
643
644 let range = [];
645 let index = 0;
646
647 while (descending ? a >= b : a <= b) {
648 range.push(format(a, index));
649 a = descending ? a - step : a + step;
650 index++;
651 }
652
653 if (options.toRegex === true) {
654 return toRegex(range, null, { wrap: false, options });
655 }
656
657 return range;
658};
659
660const fill = (start, end, step, options = {}) => {
661 if (end == null && isValidValue(start)) {
662 return [start];
663 }
664
665 if (!isValidValue(start) || !isValidValue(end)) {
666 return invalidRange(start, end, options);
667 }
668
669 if (typeof step === 'function') {
670 return fill(start, end, 1, { transform: step });
671 }
672
673 if (isObject(step)) {
674 return fill(start, end, 0, step);
675 }
676
677 let opts = { ...options };
678 if (opts.capture === true) opts.wrap = true;
679 step = step || opts.step || 1;
680
681 if (!isNumber$1(step)) {
682 if (step != null && !isObject(step)) return invalidStep(step, opts);
683 return fill(start, end, 1, step);
684 }
685
686 if (isNumber$1(start) && isNumber$1(end)) {
687 return fillNumbers(start, end, step, opts);
688 }
689
690 return fillLetters(start, end, Math.max(Math.abs(step), 1), opts);
691};
692
693var fillRange = fill;
694
695const compile = (ast, options = {}) => {
696 let walk = (node, parent = {}) => {
697 let invalidBlock = utils.isInvalidBrace(parent);
698 let invalidNode = node.invalid === true && options.escapeInvalid === true;
699 let invalid = invalidBlock === true || invalidNode === true;
700 let prefix = options.escapeInvalid === true ? '\\' : '';
701 let output = '';
702
703 if (node.isOpen === true) {
704 return prefix + node.value;
705 }
706 if (node.isClose === true) {
707 return prefix + node.value;
708 }
709
710 if (node.type === 'open') {
711 return invalid ? (prefix + node.value) : '(';
712 }
713
714 if (node.type === 'close') {
715 return invalid ? (prefix + node.value) : ')';
716 }
717
718 if (node.type === 'comma') {
719 return node.prev.type === 'comma' ? '' : (invalid ? node.value : '|');
720 }
721
722 if (node.value) {
723 return node.value;
724 }
725
726 if (node.nodes && node.ranges > 0) {
727 let args = utils.reduce(node.nodes);
728 let range = fillRange(...args, { ...options, wrap: false, toRegex: true });
729
730 if (range.length !== 0) {
731 return args.length > 1 && range.length > 1 ? `(${range})` : range;
732 }
733 }
734
735 if (node.nodes) {
736 for (let child of node.nodes) {
737 output += walk(child, node);
738 }
739 }
740 return output;
741 };
742
743 return walk(ast);
744};
745
746var compile_1 = compile;
747
748const append = (queue = '', stash = '', enclose = false) => {
749 let result = [];
750
751 queue = [].concat(queue);
752 stash = [].concat(stash);
753
754 if (!stash.length) return queue;
755 if (!queue.length) {
756 return enclose ? utils.flatten(stash).map(ele => `{${ele}}`) : stash;
757 }
758
759 for (let item of queue) {
760 if (Array.isArray(item)) {
761 for (let value of item) {
762 result.push(append(value, stash, enclose));
763 }
764 } else {
765 for (let ele of stash) {
766 if (enclose === true && typeof ele === 'string') ele = `{${ele}}`;
767 result.push(Array.isArray(ele) ? append(item, ele, enclose) : (item + ele));
768 }
769 }
770 }
771 return utils.flatten(result);
772};
773
774const expand = (ast, options = {}) => {
775 let rangeLimit = options.rangeLimit === void 0 ? 1000 : options.rangeLimit;
776
777 let walk = (node, parent = {}) => {
778 node.queue = [];
779
780 let p = parent;
781 let q = parent.queue;
782
783 while (p.type !== 'brace' && p.type !== 'root' && p.parent) {
784 p = p.parent;
785 q = p.queue;
786 }
787
788 if (node.invalid || node.dollar) {
789 q.push(append(q.pop(), stringify(node, options)));
790 return;
791 }
792
793 if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) {
794 q.push(append(q.pop(), ['{}']));
795 return;
796 }
797
798 if (node.nodes && node.ranges > 0) {
799 let args = utils.reduce(node.nodes);
800
801 if (utils.exceedsLimit(...args, options.step, rangeLimit)) {
802 throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.');
803 }
804
805 let range = fillRange(...args, options);
806 if (range.length === 0) {
807 range = stringify(node, options);
808 }
809
810 q.push(append(q.pop(), range));
811 node.nodes = [];
812 return;
813 }
814
815 let enclose = utils.encloseBrace(node);
816 let queue = node.queue;
817 let block = node;
818
819 while (block.type !== 'brace' && block.type !== 'root' && block.parent) {
820 block = block.parent;
821 queue = block.queue;
822 }
823
824 for (let i = 0; i < node.nodes.length; i++) {
825 let child = node.nodes[i];
826
827 if (child.type === 'comma' && node.type === 'brace') {
828 if (i === 1) queue.push('');
829 queue.push('');
830 continue;
831 }
832
833 if (child.type === 'close') {
834 q.push(append(q.pop(), queue, enclose));
835 continue;
836 }
837
838 if (child.value && child.type !== 'open') {
839 queue.push(append(queue.pop(), child.value));
840 continue;
841 }
842
843 if (child.nodes) {
844 walk(child, node);
845 }
846 }
847
848 return queue;
849 };
850
851 return utils.flatten(walk(ast));
852};
853
854var expand_1 = expand;
855
856var constants = {
857 MAX_LENGTH: 1024 * 64,
858
859 // Digits
860 CHAR_0: '0', /* 0 */
861 CHAR_9: '9', /* 9 */
862
863 // Alphabet chars.
864 CHAR_UPPERCASE_A: 'A', /* A */
865 CHAR_LOWERCASE_A: 'a', /* a */
866 CHAR_UPPERCASE_Z: 'Z', /* Z */
867 CHAR_LOWERCASE_Z: 'z', /* z */
868
869 CHAR_LEFT_PARENTHESES: '(', /* ( */
870 CHAR_RIGHT_PARENTHESES: ')', /* ) */
871
872 CHAR_ASTERISK: '*', /* * */
873
874 // Non-alphabetic chars.
875 CHAR_AMPERSAND: '&', /* & */
876 CHAR_AT: '@', /* @ */
877 CHAR_BACKSLASH: '\\', /* \ */
878 CHAR_BACKTICK: '`', /* ` */
879 CHAR_CARRIAGE_RETURN: '\r', /* \r */
880 CHAR_CIRCUMFLEX_ACCENT: '^', /* ^ */
881 CHAR_COLON: ':', /* : */
882 CHAR_COMMA: ',', /* , */
883 CHAR_DOLLAR: '$', /* . */
884 CHAR_DOT: '.', /* . */
885 CHAR_DOUBLE_QUOTE: '"', /* " */
886 CHAR_EQUAL: '=', /* = */
887 CHAR_EXCLAMATION_MARK: '!', /* ! */
888 CHAR_FORM_FEED: '\f', /* \f */
889 CHAR_FORWARD_SLASH: '/', /* / */
890 CHAR_HASH: '#', /* # */
891 CHAR_HYPHEN_MINUS: '-', /* - */
892 CHAR_LEFT_ANGLE_BRACKET: '<', /* < */
893 CHAR_LEFT_CURLY_BRACE: '{', /* { */
894 CHAR_LEFT_SQUARE_BRACKET: '[', /* [ */
895 CHAR_LINE_FEED: '\n', /* \n */
896 CHAR_NO_BREAK_SPACE: '\u00A0', /* \u00A0 */
897 CHAR_PERCENT: '%', /* % */
898 CHAR_PLUS: '+', /* + */
899 CHAR_QUESTION_MARK: '?', /* ? */
900 CHAR_RIGHT_ANGLE_BRACKET: '>', /* > */
901 CHAR_RIGHT_CURLY_BRACE: '}', /* } */
902 CHAR_RIGHT_SQUARE_BRACKET: ']', /* ] */
903 CHAR_SEMICOLON: ';', /* ; */
904 CHAR_SINGLE_QUOTE: '\'', /* ' */
905 CHAR_SPACE: ' ', /* */
906 CHAR_TAB: '\t', /* \t */
907 CHAR_UNDERSCORE: '_', /* _ */
908 CHAR_VERTICAL_LINE: '|', /* | */
909 CHAR_ZERO_WIDTH_NOBREAK_SPACE: '\uFEFF' /* \uFEFF */
910};
911
912/**
913 * Constants
914 */
915
916const {
917 MAX_LENGTH,
918 CHAR_BACKSLASH, /* \ */
919 CHAR_BACKTICK, /* ` */
920 CHAR_COMMA, /* , */
921 CHAR_DOT, /* . */
922 CHAR_LEFT_PARENTHESES, /* ( */
923 CHAR_RIGHT_PARENTHESES, /* ) */
924 CHAR_LEFT_CURLY_BRACE, /* { */
925 CHAR_RIGHT_CURLY_BRACE, /* } */
926 CHAR_LEFT_SQUARE_BRACKET, /* [ */
927 CHAR_RIGHT_SQUARE_BRACKET, /* ] */
928 CHAR_DOUBLE_QUOTE, /* " */
929 CHAR_SINGLE_QUOTE, /* ' */
930 CHAR_NO_BREAK_SPACE,
931 CHAR_ZERO_WIDTH_NOBREAK_SPACE
932} = constants;
933
934/**
935 * parse
936 */
937
938const parse = (input, options = {}) => {
939 if (typeof input !== 'string') {
940 throw new TypeError('Expected a string');
941 }
942
943 let opts = options || {};
944 let max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
945 if (input.length > max) {
946 throw new SyntaxError(`Input length (${input.length}), exceeds max characters (${max})`);
947 }
948
949 let ast = { type: 'root', input, nodes: [] };
950 let stack = [ast];
951 let block = ast;
952 let prev = ast;
953 let brackets = 0;
954 let length = input.length;
955 let index = 0;
956 let depth = 0;
957 let value;
958
959 /**
960 * Helpers
961 */
962
963 const advance = () => input[index++];
964 const push = node => {
965 if (node.type === 'text' && prev.type === 'dot') {
966 prev.type = 'text';
967 }
968
969 if (prev && prev.type === 'text' && node.type === 'text') {
970 prev.value += node.value;
971 return;
972 }
973
974 block.nodes.push(node);
975 node.parent = block;
976 node.prev = prev;
977 prev = node;
978 return node;
979 };
980
981 push({ type: 'bos' });
982
983 while (index < length) {
984 block = stack[stack.length - 1];
985 value = advance();
986
987 /**
988 * Invalid chars
989 */
990
991 if (value === CHAR_ZERO_WIDTH_NOBREAK_SPACE || value === CHAR_NO_BREAK_SPACE) {
992 continue;
993 }
994
995 /**
996 * Escaped chars
997 */
998
999 if (value === CHAR_BACKSLASH) {
1000 push({ type: 'text', value: (options.keepEscaping ? value : '') + advance() });
1001 continue;
1002 }
1003
1004 /**
1005 * Right square bracket (literal): ']'
1006 */
1007
1008 if (value === CHAR_RIGHT_SQUARE_BRACKET) {
1009 push({ type: 'text', value: '\\' + value });
1010 continue;
1011 }
1012
1013 /**
1014 * Left square bracket: '['
1015 */
1016
1017 if (value === CHAR_LEFT_SQUARE_BRACKET) {
1018 brackets++;
1019 let next;
1020
1021 while (index < length && (next = advance())) {
1022 value += next;
1023
1024 if (next === CHAR_LEFT_SQUARE_BRACKET) {
1025 brackets++;
1026 continue;
1027 }
1028
1029 if (next === CHAR_BACKSLASH) {
1030 value += advance();
1031 continue;
1032 }
1033
1034 if (next === CHAR_RIGHT_SQUARE_BRACKET) {
1035 brackets--;
1036
1037 if (brackets === 0) {
1038 break;
1039 }
1040 }
1041 }
1042
1043 push({ type: 'text', value });
1044 continue;
1045 }
1046
1047 /**
1048 * Parentheses
1049 */
1050
1051 if (value === CHAR_LEFT_PARENTHESES) {
1052 block = push({ type: 'paren', nodes: [] });
1053 stack.push(block);
1054 push({ type: 'text', value });
1055 continue;
1056 }
1057
1058 if (value === CHAR_RIGHT_PARENTHESES) {
1059 if (block.type !== 'paren') {
1060 push({ type: 'text', value });
1061 continue;
1062 }
1063 block = stack.pop();
1064 push({ type: 'text', value });
1065 block = stack[stack.length - 1];
1066 continue;
1067 }
1068
1069 /**
1070 * Quotes: '|"|`
1071 */
1072
1073 if (value === CHAR_DOUBLE_QUOTE || value === CHAR_SINGLE_QUOTE || value === CHAR_BACKTICK) {
1074 let open = value;
1075 let next;
1076
1077 if (options.keepQuotes !== true) {
1078 value = '';
1079 }
1080
1081 while (index < length && (next = advance())) {
1082 if (next === CHAR_BACKSLASH) {
1083 value += next + advance();
1084 continue;
1085 }
1086
1087 if (next === open) {
1088 if (options.keepQuotes === true) value += next;
1089 break;
1090 }
1091
1092 value += next;
1093 }
1094
1095 push({ type: 'text', value });
1096 continue;
1097 }
1098
1099 /**
1100 * Left curly brace: '{'
1101 */
1102
1103 if (value === CHAR_LEFT_CURLY_BRACE) {
1104 depth++;
1105
1106 let dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true;
1107 let brace = {
1108 type: 'brace',
1109 open: true,
1110 close: false,
1111 dollar,
1112 depth,
1113 commas: 0,
1114 ranges: 0,
1115 nodes: []
1116 };
1117
1118 block = push(brace);
1119 stack.push(block);
1120 push({ type: 'open', value });
1121 continue;
1122 }
1123
1124 /**
1125 * Right curly brace: '}'
1126 */
1127
1128 if (value === CHAR_RIGHT_CURLY_BRACE) {
1129 if (block.type !== 'brace') {
1130 push({ type: 'text', value });
1131 continue;
1132 }
1133
1134 let type = 'close';
1135 block = stack.pop();
1136 block.close = true;
1137
1138 push({ type, value });
1139 depth--;
1140
1141 block = stack[stack.length - 1];
1142 continue;
1143 }
1144
1145 /**
1146 * Comma: ','
1147 */
1148
1149 if (value === CHAR_COMMA && depth > 0) {
1150 if (block.ranges > 0) {
1151 block.ranges = 0;
1152 let open = block.nodes.shift();
1153 block.nodes = [open, { type: 'text', value: stringify(block) }];
1154 }
1155
1156 push({ type: 'comma', value });
1157 block.commas++;
1158 continue;
1159 }
1160
1161 /**
1162 * Dot: '.'
1163 */
1164
1165 if (value === CHAR_DOT && depth > 0 && block.commas === 0) {
1166 let siblings = block.nodes;
1167
1168 if (depth === 0 || siblings.length === 0) {
1169 push({ type: 'text', value });
1170 continue;
1171 }
1172
1173 if (prev.type === 'dot') {
1174 block.range = [];
1175 prev.value += value;
1176 prev.type = 'range';
1177
1178 if (block.nodes.length !== 3 && block.nodes.length !== 5) {
1179 block.invalid = true;
1180 block.ranges = 0;
1181 prev.type = 'text';
1182 continue;
1183 }
1184
1185 block.ranges++;
1186 block.args = [];
1187 continue;
1188 }
1189
1190 if (prev.type === 'range') {
1191 siblings.pop();
1192
1193 let before = siblings[siblings.length - 1];
1194 before.value += prev.value + value;
1195 prev = before;
1196 block.ranges--;
1197 continue;
1198 }
1199
1200 push({ type: 'dot', value });
1201 continue;
1202 }
1203
1204 /**
1205 * Text
1206 */
1207
1208 push({ type: 'text', value });
1209 }
1210
1211 // Mark imbalanced braces and brackets as invalid
1212 do {
1213 block = stack.pop();
1214
1215 if (block.type !== 'root') {
1216 block.nodes.forEach(node => {
1217 if (!node.nodes) {
1218 if (node.type === 'open') node.isOpen = true;
1219 if (node.type === 'close') node.isClose = true;
1220 if (!node.nodes) node.type = 'text';
1221 node.invalid = true;
1222 }
1223 });
1224
1225 // get the location of the block on parent.nodes (block's siblings)
1226 let parent = stack[stack.length - 1];
1227 let index = parent.nodes.indexOf(block);
1228 // replace the (invalid) block with it's nodes
1229 parent.nodes.splice(index, 1, ...block.nodes);
1230 }
1231 } while (stack.length > 0);
1232
1233 push({ type: 'eos' });
1234 return ast;
1235};
1236
1237var parse_1 = parse;
1238
1239/**
1240 * Expand the given pattern or create a regex-compatible string.
1241 *
1242 * ```js
1243 * const braces = require('braces');
1244 * console.log(braces('{a,b,c}', { compile: true })); //=> ['(a|b|c)']
1245 * console.log(braces('{a,b,c}')); //=> ['a', 'b', 'c']
1246 * ```
1247 * @param {String} `str`
1248 * @param {Object} `options`
1249 * @return {String}
1250 * @api public
1251 */
1252
1253const braces = (input, options = {}) => {
1254 let output = [];
1255
1256 if (Array.isArray(input)) {
1257 for (let pattern of input) {
1258 let result = braces.create(pattern, options);
1259 if (Array.isArray(result)) {
1260 output.push(...result);
1261 } else {
1262 output.push(result);
1263 }
1264 }
1265 } else {
1266 output = [].concat(braces.create(input, options));
1267 }
1268
1269 if (options && options.expand === true && options.nodupes === true) {
1270 output = [...new Set(output)];
1271 }
1272 return output;
1273};
1274
1275/**
1276 * Parse the given `str` with the given `options`.
1277 *
1278 * ```js
1279 * // braces.parse(pattern, [, options]);
1280 * const ast = braces.parse('a/{b,c}/d');
1281 * console.log(ast);
1282 * ```
1283 * @param {String} pattern Brace pattern to parse
1284 * @param {Object} options
1285 * @return {Object} Returns an AST
1286 * @api public
1287 */
1288
1289braces.parse = (input, options = {}) => parse_1(input, options);
1290
1291/**
1292 * Creates a braces string from an AST, or an AST node.
1293 *
1294 * ```js
1295 * const braces = require('braces');
1296 * let ast = braces.parse('foo/{a,b}/bar');
1297 * console.log(stringify(ast.nodes[2])); //=> '{a,b}'
1298 * ```
1299 * @param {String} `input` Brace pattern or AST.
1300 * @param {Object} `options`
1301 * @return {Array} Returns an array of expanded values.
1302 * @api public
1303 */
1304
1305braces.stringify = (input, options = {}) => {
1306 if (typeof input === 'string') {
1307 return stringify(braces.parse(input, options), options);
1308 }
1309 return stringify(input, options);
1310};
1311
1312/**
1313 * Compiles a brace pattern into a regex-compatible, optimized string.
1314 * This method is called by the main [braces](#braces) function by default.
1315 *
1316 * ```js
1317 * const braces = require('braces');
1318 * console.log(braces.compile('a/{b,c}/d'));
1319 * //=> ['a/(b|c)/d']
1320 * ```
1321 * @param {String} `input` Brace pattern or AST.
1322 * @param {Object} `options`
1323 * @return {Array} Returns an array of expanded values.
1324 * @api public
1325 */
1326
1327braces.compile = (input, options = {}) => {
1328 if (typeof input === 'string') {
1329 input = braces.parse(input, options);
1330 }
1331 return compile_1(input, options);
1332};
1333
1334/**
1335 * Expands a brace pattern into an array. This method is called by the
1336 * main [braces](#braces) function when `options.expand` is true. Before
1337 * using this method it's recommended that you read the [performance notes](#performance))
1338 * and advantages of using [.compile](#compile) instead.
1339 *
1340 * ```js
1341 * const braces = require('braces');
1342 * console.log(braces.expand('a/{b,c}/d'));
1343 * //=> ['a/b/d', 'a/c/d'];
1344 * ```
1345 * @param {String} `pattern` Brace pattern
1346 * @param {Object} `options`
1347 * @return {Array} Returns an array of expanded values.
1348 * @api public
1349 */
1350
1351braces.expand = (input, options = {}) => {
1352 if (typeof input === 'string') {
1353 input = braces.parse(input, options);
1354 }
1355
1356 let result = expand_1(input, options);
1357
1358 // filter out empty strings if specified
1359 if (options.noempty === true) {
1360 result = result.filter(Boolean);
1361 }
1362
1363 // filter out duplicates if specified
1364 if (options.nodupes === true) {
1365 result = [...new Set(result)];
1366 }
1367
1368 return result;
1369};
1370
1371/**
1372 * Processes a brace pattern and returns either an expanded array
1373 * (if `options.expand` is true), a highly optimized regex-compatible string.
1374 * This method is called by the main [braces](#braces) function.
1375 *
1376 * ```js
1377 * const braces = require('braces');
1378 * console.log(braces.create('user-{200..300}/project-{a,b,c}-{1..10}'))
1379 * //=> 'user-(20[0-9]|2[1-9][0-9]|300)/project-(a|b|c)-([1-9]|10)'
1380 * ```
1381 * @param {String} `pattern` Brace pattern
1382 * @param {Object} `options`
1383 * @return {Array} Returns an array of expanded values.
1384 * @api public
1385 */
1386
1387braces.create = (input, options = {}) => {
1388 if (input === '' || input.length < 3) {
1389 return [input];
1390 }
1391
1392 return options.expand !== true
1393 ? braces.compile(input, options)
1394 : braces.expand(input, options);
1395};
1396
1397/**
1398 * Expose "braces"
1399 */
1400
1401var braces_1 = braces;
1402
1403const WIN_SLASH = '\\\\/';
1404const WIN_NO_SLASH = `[^${WIN_SLASH}]`;
1405
1406/**
1407 * Posix glob regex
1408 */
1409
1410const DOT_LITERAL = '\\.';
1411const PLUS_LITERAL = '\\+';
1412const QMARK_LITERAL = '\\?';
1413const SLASH_LITERAL = '\\/';
1414const ONE_CHAR = '(?=.)';
1415const QMARK = '[^/]';
1416const END_ANCHOR = `(?:${SLASH_LITERAL}|$)`;
1417const START_ANCHOR = `(?:^|${SLASH_LITERAL})`;
1418const DOTS_SLASH = `${DOT_LITERAL}{1,2}${END_ANCHOR}`;
1419const NO_DOT = `(?!${DOT_LITERAL})`;
1420const NO_DOTS = `(?!${START_ANCHOR}${DOTS_SLASH})`;
1421const NO_DOT_SLASH = `(?!${DOT_LITERAL}{0,1}${END_ANCHOR})`;
1422const NO_DOTS_SLASH = `(?!${DOTS_SLASH})`;
1423const QMARK_NO_DOT = `[^.${SLASH_LITERAL}]`;
1424const STAR = `${QMARK}*?`;
1425
1426const POSIX_CHARS = {
1427 DOT_LITERAL,
1428 PLUS_LITERAL,
1429 QMARK_LITERAL,
1430 SLASH_LITERAL,
1431 ONE_CHAR,
1432 QMARK,
1433 END_ANCHOR,
1434 DOTS_SLASH,
1435 NO_DOT,
1436 NO_DOTS,
1437 NO_DOT_SLASH,
1438 NO_DOTS_SLASH,
1439 QMARK_NO_DOT,
1440 STAR,
1441 START_ANCHOR
1442};
1443
1444/**
1445 * Windows glob regex
1446 */
1447
1448const WINDOWS_CHARS = {
1449 ...POSIX_CHARS,
1450
1451 SLASH_LITERAL: `[${WIN_SLASH}]`,
1452 QMARK: WIN_NO_SLASH,
1453 STAR: `${WIN_NO_SLASH}*?`,
1454 DOTS_SLASH: `${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$)`,
1455 NO_DOT: `(?!${DOT_LITERAL})`,
1456 NO_DOTS: `(?!(?:^|[${WIN_SLASH}])${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`,
1457 NO_DOT_SLASH: `(?!${DOT_LITERAL}{0,1}(?:[${WIN_SLASH}]|$))`,
1458 NO_DOTS_SLASH: `(?!${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`,
1459 QMARK_NO_DOT: `[^.${WIN_SLASH}]`,
1460 START_ANCHOR: `(?:^|[${WIN_SLASH}])`,
1461 END_ANCHOR: `(?:[${WIN_SLASH}]|$)`
1462};
1463
1464/**
1465 * POSIX Bracket Regex
1466 */
1467
1468const POSIX_REGEX_SOURCE = {
1469 alnum: 'a-zA-Z0-9',
1470 alpha: 'a-zA-Z',
1471 ascii: '\\x00-\\x7F',
1472 blank: ' \\t',
1473 cntrl: '\\x00-\\x1F\\x7F',
1474 digit: '0-9',
1475 graph: '\\x21-\\x7E',
1476 lower: 'a-z',
1477 print: '\\x20-\\x7E ',
1478 punct: '\\-!"#$%&\'()\\*+,./:;<=>?@[\\]^_`{|}~',
1479 space: ' \\t\\r\\n\\v\\f',
1480 upper: 'A-Z',
1481 word: 'A-Za-z0-9_',
1482 xdigit: 'A-Fa-f0-9'
1483};
1484
1485var constants$1 = {
1486 MAX_LENGTH: 1024 * 64,
1487 POSIX_REGEX_SOURCE,
1488
1489 // regular expressions
1490 REGEX_BACKSLASH: /\\(?![*+?^${}(|)[\]])/g,
1491 REGEX_NON_SPECIAL_CHARS: /^[^@![\].,$*+?^{}()|\\/]+/,
1492 REGEX_SPECIAL_CHARS: /[-*+?.^${}(|)[\]]/,
1493 REGEX_SPECIAL_CHARS_BACKREF: /(\\?)((\W)(\3*))/g,
1494 REGEX_SPECIAL_CHARS_GLOBAL: /([-*+?.^${}(|)[\]])/g,
1495 REGEX_REMOVE_BACKSLASH: /(?:\[.*?[^\\]\]|\\(?=.))/g,
1496
1497 // Replace globs with equivalent patterns to reduce parsing time.
1498 REPLACEMENTS: {
1499 '***': '*',
1500 '**/**': '**',
1501 '**/**/**': '**'
1502 },
1503
1504 // Digits
1505 CHAR_0: 48, /* 0 */
1506 CHAR_9: 57, /* 9 */
1507
1508 // Alphabet chars.
1509 CHAR_UPPERCASE_A: 65, /* A */
1510 CHAR_LOWERCASE_A: 97, /* a */
1511 CHAR_UPPERCASE_Z: 90, /* Z */
1512 CHAR_LOWERCASE_Z: 122, /* z */
1513
1514 CHAR_LEFT_PARENTHESES: 40, /* ( */
1515 CHAR_RIGHT_PARENTHESES: 41, /* ) */
1516
1517 CHAR_ASTERISK: 42, /* * */
1518
1519 // Non-alphabetic chars.
1520 CHAR_AMPERSAND: 38, /* & */
1521 CHAR_AT: 64, /* @ */
1522 CHAR_BACKWARD_SLASH: 92, /* \ */
1523 CHAR_CARRIAGE_RETURN: 13, /* \r */
1524 CHAR_CIRCUMFLEX_ACCENT: 94, /* ^ */
1525 CHAR_COLON: 58, /* : */
1526 CHAR_COMMA: 44, /* , */
1527 CHAR_DOT: 46, /* . */
1528 CHAR_DOUBLE_QUOTE: 34, /* " */
1529 CHAR_EQUAL: 61, /* = */
1530 CHAR_EXCLAMATION_MARK: 33, /* ! */
1531 CHAR_FORM_FEED: 12, /* \f */
1532 CHAR_FORWARD_SLASH: 47, /* / */
1533 CHAR_GRAVE_ACCENT: 96, /* ` */
1534 CHAR_HASH: 35, /* # */
1535 CHAR_HYPHEN_MINUS: 45, /* - */
1536 CHAR_LEFT_ANGLE_BRACKET: 60, /* < */
1537 CHAR_LEFT_CURLY_BRACE: 123, /* { */
1538 CHAR_LEFT_SQUARE_BRACKET: 91, /* [ */
1539 CHAR_LINE_FEED: 10, /* \n */
1540 CHAR_NO_BREAK_SPACE: 160, /* \u00A0 */
1541 CHAR_PERCENT: 37, /* % */
1542 CHAR_PLUS: 43, /* + */
1543 CHAR_QUESTION_MARK: 63, /* ? */
1544 CHAR_RIGHT_ANGLE_BRACKET: 62, /* > */
1545 CHAR_RIGHT_CURLY_BRACE: 125, /* } */
1546 CHAR_RIGHT_SQUARE_BRACKET: 93, /* ] */
1547 CHAR_SEMICOLON: 59, /* ; */
1548 CHAR_SINGLE_QUOTE: 39, /* ' */
1549 CHAR_SPACE: 32, /* */
1550 CHAR_TAB: 9, /* \t */
1551 CHAR_UNDERSCORE: 95, /* _ */
1552 CHAR_VERTICAL_LINE: 124, /* | */
1553 CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279, /* \uFEFF */
1554
1555 SEP: sysPath.sep,
1556
1557 /**
1558 * Create EXTGLOB_CHARS
1559 */
1560
1561 extglobChars(chars) {
1562 return {
1563 '!': { type: 'negate', open: '(?:(?!(?:', close: `))${chars.STAR})` },
1564 '?': { type: 'qmark', open: '(?:', close: ')?' },
1565 '+': { type: 'plus', open: '(?:', close: ')+' },
1566 '*': { type: 'star', open: '(?:', close: ')*' },
1567 '@': { type: 'at', open: '(?:', close: ')' }
1568 };
1569 },
1570
1571 /**
1572 * Create GLOB_CHARS
1573 */
1574
1575 globChars(win32) {
1576 return win32 === true ? WINDOWS_CHARS : POSIX_CHARS;
1577 }
1578};
1579
1580var utils$1 = createCommonjsModule(function (module, exports) {
1581
1582
1583const win32 = process.platform === 'win32';
1584const {
1585 REGEX_BACKSLASH,
1586 REGEX_REMOVE_BACKSLASH,
1587 REGEX_SPECIAL_CHARS,
1588 REGEX_SPECIAL_CHARS_GLOBAL
1589} = constants$1;
1590
1591exports.isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val);
1592exports.hasRegexChars = str => REGEX_SPECIAL_CHARS.test(str);
1593exports.isRegexChar = str => str.length === 1 && exports.hasRegexChars(str);
1594exports.escapeRegex = str => str.replace(REGEX_SPECIAL_CHARS_GLOBAL, '\\$1');
1595exports.toPosixSlashes = str => str.replace(REGEX_BACKSLASH, '/');
1596
1597exports.removeBackslashes = str => {
1598 return str.replace(REGEX_REMOVE_BACKSLASH, match => {
1599 return match === '\\' ? '' : match;
1600 });
1601};
1602
1603exports.supportsLookbehinds = () => {
1604 const segs = process.version.slice(1).split('.').map(Number);
1605 if (segs.length === 3 && segs[0] >= 9 || (segs[0] === 8 && segs[1] >= 10)) {
1606 return true;
1607 }
1608 return false;
1609};
1610
1611exports.isWindows = options => {
1612 if (options && typeof options.windows === 'boolean') {
1613 return options.windows;
1614 }
1615 return win32 === true || sysPath.sep === '\\';
1616};
1617
1618exports.escapeLast = (input, char, lastIdx) => {
1619 const idx = input.lastIndexOf(char, lastIdx);
1620 if (idx === -1) return input;
1621 if (input[idx - 1] === '\\') return exports.escapeLast(input, char, idx - 1);
1622 return `${input.slice(0, idx)}\\${input.slice(idx)}`;
1623};
1624
1625exports.removePrefix = (input, state = {}) => {
1626 let output = input;
1627 if (output.startsWith('./')) {
1628 output = output.slice(2);
1629 state.prefix = './';
1630 }
1631 return output;
1632};
1633
1634exports.wrapOutput = (input, state = {}, options = {}) => {
1635 const prepend = options.contains ? '' : '^';
1636 const append = options.contains ? '' : '$';
1637
1638 let output = `${prepend}(?:${input})${append}`;
1639 if (state.negated === true) {
1640 output = `(?:^(?!${output}).*$)`;
1641 }
1642 return output;
1643};
1644});
1645
1646const {
1647 CHAR_ASTERISK, /* * */
1648 CHAR_AT, /* @ */
1649 CHAR_BACKWARD_SLASH, /* \ */
1650 CHAR_COMMA: CHAR_COMMA$1, /* , */
1651 CHAR_DOT: CHAR_DOT$1, /* . */
1652 CHAR_EXCLAMATION_MARK, /* ! */
1653 CHAR_FORWARD_SLASH, /* / */
1654 CHAR_LEFT_CURLY_BRACE: CHAR_LEFT_CURLY_BRACE$1, /* { */
1655 CHAR_LEFT_PARENTHESES: CHAR_LEFT_PARENTHESES$1, /* ( */
1656 CHAR_LEFT_SQUARE_BRACKET: CHAR_LEFT_SQUARE_BRACKET$1, /* [ */
1657 CHAR_PLUS, /* + */
1658 CHAR_QUESTION_MARK, /* ? */
1659 CHAR_RIGHT_CURLY_BRACE: CHAR_RIGHT_CURLY_BRACE$1, /* } */
1660 CHAR_RIGHT_PARENTHESES: CHAR_RIGHT_PARENTHESES$1, /* ) */
1661 CHAR_RIGHT_SQUARE_BRACKET: CHAR_RIGHT_SQUARE_BRACKET$1 /* ] */
1662} = constants$1;
1663
1664const isPathSeparator = code => {
1665 return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH;
1666};
1667
1668const depth = token => {
1669 if (token.isPrefix !== true) {
1670 token.depth = token.isGlobstar ? Infinity : 1;
1671 }
1672};
1673
1674/**
1675 * Quickly scans a glob pattern and returns an object with a handful of
1676 * useful properties, like `isGlob`, `path` (the leading non-glob, if it exists),
1677 * `glob` (the actual pattern), and `negated` (true if the path starts with `!`).
1678 *
1679 * ```js
1680 * const pm = require('picomatch');
1681 * console.log(pm.scan('foo/bar/*.js'));
1682 * { isGlob: true, input: 'foo/bar/*.js', base: 'foo/bar', glob: '*.js' }
1683 * ```
1684 * @param {String} `str`
1685 * @param {Object} `options`
1686 * @return {Object} Returns an object with tokens and regex source string.
1687 * @api public
1688 */
1689
1690const scan = (input, options) => {
1691 const opts = options || {};
1692
1693 const length = input.length - 1;
1694 const scanToEnd = opts.parts === true || opts.scanToEnd === true;
1695 const slashes = [];
1696 const tokens = [];
1697 const parts = [];
1698
1699 let str = input;
1700 let index = -1;
1701 let start = 0;
1702 let lastIndex = 0;
1703 let isBrace = false;
1704 let isBracket = false;
1705 let isGlob = false;
1706 let isExtglob = false;
1707 let isGlobstar = false;
1708 let braceEscaped = false;
1709 let backslashes = false;
1710 let negated = false;
1711 let finished = false;
1712 let braces = 0;
1713 let prev;
1714 let code;
1715 let token = { value: '', depth: 0, isGlob: false };
1716
1717 const eos = () => index >= length;
1718 const peek = () => str.charCodeAt(index + 1);
1719 const advance = () => {
1720 prev = code;
1721 return str.charCodeAt(++index);
1722 };
1723
1724 while (index < length) {
1725 code = advance();
1726 let next;
1727
1728 if (code === CHAR_BACKWARD_SLASH) {
1729 backslashes = token.backslashes = true;
1730 code = advance();
1731
1732 if (code === CHAR_LEFT_CURLY_BRACE$1) {
1733 braceEscaped = true;
1734 }
1735 continue;
1736 }
1737
1738 if (braceEscaped === true || code === CHAR_LEFT_CURLY_BRACE$1) {
1739 braces++;
1740
1741 while (eos() !== true && (code = advance())) {
1742 if (code === CHAR_BACKWARD_SLASH) {
1743 backslashes = token.backslashes = true;
1744 advance();
1745 continue;
1746 }
1747
1748 if (code === CHAR_LEFT_CURLY_BRACE$1) {
1749 braces++;
1750 continue;
1751 }
1752
1753 if (braceEscaped !== true && code === CHAR_DOT$1 && (code = advance()) === CHAR_DOT$1) {
1754 isBrace = token.isBrace = true;
1755 isGlob = token.isGlob = true;
1756 finished = true;
1757
1758 if (scanToEnd === true) {
1759 continue;
1760 }
1761
1762 break;
1763 }
1764
1765 if (braceEscaped !== true && code === CHAR_COMMA$1) {
1766 isBrace = token.isBrace = true;
1767 isGlob = token.isGlob = true;
1768 finished = true;
1769
1770 if (scanToEnd === true) {
1771 continue;
1772 }
1773
1774 break;
1775 }
1776
1777 if (code === CHAR_RIGHT_CURLY_BRACE$1) {
1778 braces--;
1779
1780 if (braces === 0) {
1781 braceEscaped = false;
1782 isBrace = token.isBrace = true;
1783 finished = true;
1784 break;
1785 }
1786 }
1787 }
1788
1789 if (scanToEnd === true) {
1790 continue;
1791 }
1792
1793 break;
1794 }
1795
1796 if (code === CHAR_FORWARD_SLASH) {
1797 slashes.push(index);
1798 tokens.push(token);
1799 token = { value: '', depth: 0, isGlob: false };
1800
1801 if (finished === true) continue;
1802 if (prev === CHAR_DOT$1 && index === (start + 1)) {
1803 start += 2;
1804 continue;
1805 }
1806
1807 lastIndex = index + 1;
1808 continue;
1809 }
1810
1811 if (opts.noext !== true) {
1812 const isExtglobChar = code === CHAR_PLUS
1813 || code === CHAR_AT
1814 || code === CHAR_ASTERISK
1815 || code === CHAR_QUESTION_MARK
1816 || code === CHAR_EXCLAMATION_MARK;
1817
1818 if (isExtglobChar === true && peek() === CHAR_LEFT_PARENTHESES$1) {
1819 isGlob = token.isGlob = true;
1820 isExtglob = token.isExtglob = true;
1821 finished = true;
1822
1823 if (scanToEnd === true) {
1824 while (eos() !== true && (code = advance())) {
1825 if (code === CHAR_BACKWARD_SLASH) {
1826 backslashes = token.backslashes = true;
1827 code = advance();
1828 continue;
1829 }
1830
1831 if (code === CHAR_RIGHT_PARENTHESES$1) {
1832 isGlob = token.isGlob = true;
1833 finished = true;
1834 break;
1835 }
1836 }
1837 continue;
1838 }
1839 break;
1840 }
1841 }
1842
1843 if (code === CHAR_ASTERISK) {
1844 if (prev === CHAR_ASTERISK) isGlobstar = token.isGlobstar = true;
1845 isGlob = token.isGlob = true;
1846 finished = true;
1847
1848 if (scanToEnd === true) {
1849 continue;
1850 }
1851 break;
1852 }
1853
1854 if (code === CHAR_QUESTION_MARK) {
1855 isGlob = token.isGlob = true;
1856 finished = true;
1857
1858 if (scanToEnd === true) {
1859 continue;
1860 }
1861 break;
1862 }
1863
1864 if (code === CHAR_LEFT_SQUARE_BRACKET$1) {
1865 while (eos() !== true && (next = advance())) {
1866 if (next === CHAR_BACKWARD_SLASH) {
1867 backslashes = token.backslashes = true;
1868 advance();
1869 continue;
1870 }
1871
1872 if (next === CHAR_RIGHT_SQUARE_BRACKET$1) {
1873 isBracket = token.isBracket = true;
1874 isGlob = token.isGlob = true;
1875 finished = true;
1876
1877 if (scanToEnd === true) {
1878 continue;
1879 }
1880 break;
1881 }
1882 }
1883 }
1884
1885 if (opts.nonegate !== true && code === CHAR_EXCLAMATION_MARK && index === start) {
1886 negated = token.negated = true;
1887 start++;
1888 continue;
1889 }
1890
1891 if (opts.noparen !== true && code === CHAR_LEFT_PARENTHESES$1) {
1892 isGlob = token.isGlob = true;
1893
1894 if (scanToEnd === true) {
1895 while (eos() !== true && (code = advance())) {
1896 if (code === CHAR_LEFT_PARENTHESES$1) {
1897 backslashes = token.backslashes = true;
1898 code = advance();
1899 continue;
1900 }
1901
1902 if (code === CHAR_RIGHT_PARENTHESES$1) {
1903 finished = true;
1904 break;
1905 }
1906 }
1907 continue;
1908 }
1909 break;
1910 }
1911
1912 if (isGlob === true) {
1913 finished = true;
1914
1915 if (scanToEnd === true) {
1916 continue;
1917 }
1918
1919 break;
1920 }
1921 }
1922
1923 if (opts.noext === true) {
1924 isExtglob = false;
1925 isGlob = false;
1926 }
1927
1928 let base = str;
1929 let prefix = '';
1930 let glob = '';
1931
1932 if (start > 0) {
1933 prefix = str.slice(0, start);
1934 str = str.slice(start);
1935 lastIndex -= start;
1936 }
1937
1938 if (base && isGlob === true && lastIndex > 0) {
1939 base = str.slice(0, lastIndex);
1940 glob = str.slice(lastIndex);
1941 } else if (isGlob === true) {
1942 base = '';
1943 glob = str;
1944 } else {
1945 base = str;
1946 }
1947
1948 if (base && base !== '' && base !== '/' && base !== str) {
1949 if (isPathSeparator(base.charCodeAt(base.length - 1))) {
1950 base = base.slice(0, -1);
1951 }
1952 }
1953
1954 if (opts.unescape === true) {
1955 if (glob) glob = utils$1.removeBackslashes(glob);
1956
1957 if (base && backslashes === true) {
1958 base = utils$1.removeBackslashes(base);
1959 }
1960 }
1961
1962 const state = {
1963 prefix,
1964 input,
1965 start,
1966 base,
1967 glob,
1968 isBrace,
1969 isBracket,
1970 isGlob,
1971 isExtglob,
1972 isGlobstar,
1973 negated
1974 };
1975
1976 if (opts.tokens === true) {
1977 state.maxDepth = 0;
1978 if (!isPathSeparator(code)) {
1979 tokens.push(token);
1980 }
1981 state.tokens = tokens;
1982 }
1983
1984 if (opts.parts === true || opts.tokens === true) {
1985 let prevIndex;
1986
1987 for (let idx = 0; idx < slashes.length; idx++) {
1988 const n = prevIndex ? prevIndex + 1 : start;
1989 const i = slashes[idx];
1990 const value = input.slice(n, i);
1991 if (opts.tokens) {
1992 if (idx === 0 && start !== 0) {
1993 tokens[idx].isPrefix = true;
1994 tokens[idx].value = prefix;
1995 } else {
1996 tokens[idx].value = value;
1997 }
1998 depth(tokens[idx]);
1999 state.maxDepth += tokens[idx].depth;
2000 }
2001 if (idx !== 0 || value !== '') {
2002 parts.push(value);
2003 }
2004 prevIndex = i;
2005 }
2006
2007 if (prevIndex && prevIndex + 1 < input.length) {
2008 const value = input.slice(prevIndex + 1);
2009 parts.push(value);
2010
2011 if (opts.tokens) {
2012 tokens[tokens.length - 1].value = value;
2013 depth(tokens[tokens.length - 1]);
2014 state.maxDepth += tokens[tokens.length - 1].depth;
2015 }
2016 }
2017
2018 state.slashes = slashes;
2019 state.parts = parts;
2020 }
2021
2022 return state;
2023};
2024
2025var scan_1 = scan;
2026
2027/**
2028 * Constants
2029 */
2030
2031const {
2032 MAX_LENGTH: MAX_LENGTH$1,
2033 POSIX_REGEX_SOURCE: POSIX_REGEX_SOURCE$1,
2034 REGEX_NON_SPECIAL_CHARS,
2035 REGEX_SPECIAL_CHARS_BACKREF,
2036 REPLACEMENTS
2037} = constants$1;
2038
2039/**
2040 * Helpers
2041 */
2042
2043const expandRange = (args, options) => {
2044 if (typeof options.expandRange === 'function') {
2045 return options.expandRange(...args, options);
2046 }
2047
2048 args.sort();
2049 const value = `[${args.join('-')}]`;
2050
2051 return value;
2052};
2053
2054/**
2055 * Create the message for a syntax error
2056 */
2057
2058const syntaxError = (type, char) => {
2059 return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`;
2060};
2061
2062/**
2063 * Parse the given input string.
2064 * @param {String} input
2065 * @param {Object} options
2066 * @return {Object}
2067 */
2068
2069const parse$1 = (input, options) => {
2070 if (typeof input !== 'string') {
2071 throw new TypeError('Expected a string');
2072 }
2073
2074 input = REPLACEMENTS[input] || input;
2075
2076 const opts = { ...options };
2077 const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH$1, opts.maxLength) : MAX_LENGTH$1;
2078
2079 let len = input.length;
2080 if (len > max) {
2081 throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`);
2082 }
2083
2084 const bos = { type: 'bos', value: '', output: opts.prepend || '' };
2085 const tokens = [bos];
2086
2087 const capture = opts.capture ? '' : '?:';
2088 const win32 = utils$1.isWindows(options);
2089
2090 // create constants based on platform, for windows or posix
2091 const PLATFORM_CHARS = constants$1.globChars(win32);
2092 const EXTGLOB_CHARS = constants$1.extglobChars(PLATFORM_CHARS);
2093
2094 const {
2095 DOT_LITERAL,
2096 PLUS_LITERAL,
2097 SLASH_LITERAL,
2098 ONE_CHAR,
2099 DOTS_SLASH,
2100 NO_DOT,
2101 NO_DOT_SLASH,
2102 NO_DOTS_SLASH,
2103 QMARK,
2104 QMARK_NO_DOT,
2105 STAR,
2106 START_ANCHOR
2107 } = PLATFORM_CHARS;
2108
2109 const globstar = (opts) => {
2110 return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`;
2111 };
2112
2113 const nodot = opts.dot ? '' : NO_DOT;
2114 const qmarkNoDot = opts.dot ? QMARK : QMARK_NO_DOT;
2115 let star = opts.bash === true ? globstar(opts) : STAR;
2116
2117 if (opts.capture) {
2118 star = `(${star})`;
2119 }
2120
2121 // minimatch options support
2122 if (typeof opts.noext === 'boolean') {
2123 opts.noextglob = opts.noext;
2124 }
2125
2126 const state = {
2127 input,
2128 index: -1,
2129 start: 0,
2130 dot: opts.dot === true,
2131 consumed: '',
2132 output: '',
2133 prefix: '',
2134 backtrack: false,
2135 negated: false,
2136 brackets: 0,
2137 braces: 0,
2138 parens: 0,
2139 quotes: 0,
2140 globstar: false,
2141 tokens
2142 };
2143
2144 input = utils$1.removePrefix(input, state);
2145 len = input.length;
2146
2147 const extglobs = [];
2148 const braces = [];
2149 const stack = [];
2150 let prev = bos;
2151 let value;
2152
2153 /**
2154 * Tokenizing helpers
2155 */
2156
2157 const eos = () => state.index === len - 1;
2158 const peek = state.peek = (n = 1) => input[state.index + n];
2159 const advance = state.advance = () => input[++state.index];
2160 const remaining = () => input.slice(state.index + 1);
2161 const consume = (value = '', num = 0) => {
2162 state.consumed += value;
2163 state.index += num;
2164 };
2165 const append = token => {
2166 state.output += token.output != null ? token.output : token.value;
2167 consume(token.value);
2168 };
2169
2170 const negate = () => {
2171 let count = 1;
2172
2173 while (peek() === '!' && (peek(2) !== '(' || peek(3) === '?')) {
2174 advance();
2175 state.start++;
2176 count++;
2177 }
2178
2179 if (count % 2 === 0) {
2180 return false;
2181 }
2182
2183 state.negated = true;
2184 state.start++;
2185 return true;
2186 };
2187
2188 const increment = type => {
2189 state[type]++;
2190 stack.push(type);
2191 };
2192
2193 const decrement = type => {
2194 state[type]--;
2195 stack.pop();
2196 };
2197
2198 /**
2199 * Push tokens onto the tokens array. This helper speeds up
2200 * tokenizing by 1) helping us avoid backtracking as much as possible,
2201 * and 2) helping us avoid creating extra tokens when consecutive
2202 * characters are plain text. This improves performance and simplifies
2203 * lookbehinds.
2204 */
2205
2206 const push = tok => {
2207 if (prev.type === 'globstar') {
2208 const isBrace = state.braces > 0 && (tok.type === 'comma' || tok.type === 'brace');
2209 const isExtglob = tok.extglob === true || (extglobs.length && (tok.type === 'pipe' || tok.type === 'paren'));
2210
2211 if (tok.type !== 'slash' && tok.type !== 'paren' && !isBrace && !isExtglob) {
2212 state.output = state.output.slice(0, -prev.output.length);
2213 prev.type = 'star';
2214 prev.value = '*';
2215 prev.output = star;
2216 state.output += prev.output;
2217 }
2218 }
2219
2220 if (extglobs.length && tok.type !== 'paren' && !EXTGLOB_CHARS[tok.value]) {
2221 extglobs[extglobs.length - 1].inner += tok.value;
2222 }
2223
2224 if (tok.value || tok.output) append(tok);
2225 if (prev && prev.type === 'text' && tok.type === 'text') {
2226 prev.value += tok.value;
2227 prev.output = (prev.output || '') + tok.value;
2228 return;
2229 }
2230
2231 tok.prev = prev;
2232 tokens.push(tok);
2233 prev = tok;
2234 };
2235
2236 const extglobOpen = (type, value) => {
2237 const token = { ...EXTGLOB_CHARS[value], conditions: 1, inner: '' };
2238
2239 token.prev = prev;
2240 token.parens = state.parens;
2241 token.output = state.output;
2242 const output = (opts.capture ? '(' : '') + token.open;
2243
2244 increment('parens');
2245 push({ type, value, output: state.output ? '' : ONE_CHAR });
2246 push({ type: 'paren', extglob: true, value: advance(), output });
2247 extglobs.push(token);
2248 };
2249
2250 const extglobClose = token => {
2251 let output = token.close + (opts.capture ? ')' : '');
2252
2253 if (token.type === 'negate') {
2254 let extglobStar = star;
2255
2256 if (token.inner && token.inner.length > 1 && token.inner.includes('/')) {
2257 extglobStar = globstar(opts);
2258 }
2259
2260 if (extglobStar !== star || eos() || /^\)+$/.test(remaining())) {
2261 output = token.close = `)$))${extglobStar}`;
2262 }
2263
2264 if (token.prev.type === 'bos' && eos()) {
2265 state.negatedExtglob = true;
2266 }
2267 }
2268
2269 push({ type: 'paren', extglob: true, value, output });
2270 decrement('parens');
2271 };
2272
2273 /**
2274 * Fast paths
2275 */
2276
2277 if (opts.fastpaths !== false && !/(^[*!]|[/()[\]{}"])/.test(input)) {
2278 let backslashes = false;
2279
2280 let output = input.replace(REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index) => {
2281 if (first === '\\') {
2282 backslashes = true;
2283 return m;
2284 }
2285
2286 if (first === '?') {
2287 if (esc) {
2288 return esc + first + (rest ? QMARK.repeat(rest.length) : '');
2289 }
2290 if (index === 0) {
2291 return qmarkNoDot + (rest ? QMARK.repeat(rest.length) : '');
2292 }
2293 return QMARK.repeat(chars.length);
2294 }
2295
2296 if (first === '.') {
2297 return DOT_LITERAL.repeat(chars.length);
2298 }
2299
2300 if (first === '*') {
2301 if (esc) {
2302 return esc + first + (rest ? star : '');
2303 }
2304 return star;
2305 }
2306 return esc ? m : `\\${m}`;
2307 });
2308
2309 if (backslashes === true) {
2310 if (opts.unescape === true) {
2311 output = output.replace(/\\/g, '');
2312 } else {
2313 output = output.replace(/\\+/g, m => {
2314 return m.length % 2 === 0 ? '\\\\' : (m ? '\\' : '');
2315 });
2316 }
2317 }
2318
2319 if (output === input && opts.contains === true) {
2320 state.output = input;
2321 return state;
2322 }
2323
2324 state.output = utils$1.wrapOutput(output, state, options);
2325 return state;
2326 }
2327
2328 /**
2329 * Tokenize input until we reach end-of-string
2330 */
2331
2332 while (!eos()) {
2333 value = advance();
2334
2335 if (value === '\u0000') {
2336 continue;
2337 }
2338
2339 /**
2340 * Escaped characters
2341 */
2342
2343 if (value === '\\') {
2344 const next = peek();
2345
2346 if (next === '/' && opts.bash !== true) {
2347 continue;
2348 }
2349
2350 if (next === '.' || next === ';') {
2351 continue;
2352 }
2353
2354 if (!next) {
2355 value += '\\';
2356 push({ type: 'text', value });
2357 continue;
2358 }
2359
2360 // collapse slashes to reduce potential for exploits
2361 const match = /^\\+/.exec(remaining());
2362 let slashes = 0;
2363
2364 if (match && match[0].length > 2) {
2365 slashes = match[0].length;
2366 state.index += slashes;
2367 if (slashes % 2 !== 0) {
2368 value += '\\';
2369 }
2370 }
2371
2372 if (opts.unescape === true) {
2373 value = advance() || '';
2374 } else {
2375 value += advance() || '';
2376 }
2377
2378 if (state.brackets === 0) {
2379 push({ type: 'text', value });
2380 continue;
2381 }
2382 }
2383
2384 /**
2385 * If we're inside a regex character class, continue
2386 * until we reach the closing bracket.
2387 */
2388
2389 if (state.brackets > 0 && (value !== ']' || prev.value === '[' || prev.value === '[^')) {
2390 if (opts.posix !== false && value === ':') {
2391 const inner = prev.value.slice(1);
2392 if (inner.includes('[')) {
2393 prev.posix = true;
2394
2395 if (inner.includes(':')) {
2396 const idx = prev.value.lastIndexOf('[');
2397 const pre = prev.value.slice(0, idx);
2398 const rest = prev.value.slice(idx + 2);
2399 const posix = POSIX_REGEX_SOURCE$1[rest];
2400 if (posix) {
2401 prev.value = pre + posix;
2402 state.backtrack = true;
2403 advance();
2404
2405 if (!bos.output && tokens.indexOf(prev) === 1) {
2406 bos.output = ONE_CHAR;
2407 }
2408 continue;
2409 }
2410 }
2411 }
2412 }
2413
2414 if ((value === '[' && peek() !== ':') || (value === '-' && peek() === ']')) {
2415 value = `\\${value}`;
2416 }
2417
2418 if (value === ']' && (prev.value === '[' || prev.value === '[^')) {
2419 value = `\\${value}`;
2420 }
2421
2422 if (opts.posix === true && value === '!' && prev.value === '[') {
2423 value = '^';
2424 }
2425
2426 prev.value += value;
2427 append({ value });
2428 continue;
2429 }
2430
2431 /**
2432 * If we're inside a quoted string, continue
2433 * until we reach the closing double quote.
2434 */
2435
2436 if (state.quotes === 1 && value !== '"') {
2437 value = utils$1.escapeRegex(value);
2438 prev.value += value;
2439 append({ value });
2440 continue;
2441 }
2442
2443 /**
2444 * Double quotes
2445 */
2446
2447 if (value === '"') {
2448 state.quotes = state.quotes === 1 ? 0 : 1;
2449 if (opts.keepQuotes === true) {
2450 push({ type: 'text', value });
2451 }
2452 continue;
2453 }
2454
2455 /**
2456 * Parentheses
2457 */
2458
2459 if (value === '(') {
2460 increment('parens');
2461 push({ type: 'paren', value });
2462 continue;
2463 }
2464
2465 if (value === ')') {
2466 if (state.parens === 0 && opts.strictBrackets === true) {
2467 throw new SyntaxError(syntaxError('opening', '('));
2468 }
2469
2470 const extglob = extglobs[extglobs.length - 1];
2471 if (extglob && state.parens === extglob.parens + 1) {
2472 extglobClose(extglobs.pop());
2473 continue;
2474 }
2475
2476 push({ type: 'paren', value, output: state.parens ? ')' : '\\)' });
2477 decrement('parens');
2478 continue;
2479 }
2480
2481 /**
2482 * Square brackets
2483 */
2484
2485 if (value === '[') {
2486 if (opts.nobracket === true || !remaining().includes(']')) {
2487 if (opts.nobracket !== true && opts.strictBrackets === true) {
2488 throw new SyntaxError(syntaxError('closing', ']'));
2489 }
2490
2491 value = `\\${value}`;
2492 } else {
2493 increment('brackets');
2494 }
2495
2496 push({ type: 'bracket', value });
2497 continue;
2498 }
2499
2500 if (value === ']') {
2501 if (opts.nobracket === true || (prev && prev.type === 'bracket' && prev.value.length === 1)) {
2502 push({ type: 'text', value, output: `\\${value}` });
2503 continue;
2504 }
2505
2506 if (state.brackets === 0) {
2507 if (opts.strictBrackets === true) {
2508 throw new SyntaxError(syntaxError('opening', '['));
2509 }
2510
2511 push({ type: 'text', value, output: `\\${value}` });
2512 continue;
2513 }
2514
2515 decrement('brackets');
2516
2517 const prevValue = prev.value.slice(1);
2518 if (prev.posix !== true && prevValue[0] === '^' && !prevValue.includes('/')) {
2519 value = `/${value}`;
2520 }
2521
2522 prev.value += value;
2523 append({ value });
2524
2525 // when literal brackets are explicitly disabled
2526 // assume we should match with a regex character class
2527 if (opts.literalBrackets === false || utils$1.hasRegexChars(prevValue)) {
2528 continue;
2529 }
2530
2531 const escaped = utils$1.escapeRegex(prev.value);
2532 state.output = state.output.slice(0, -prev.value.length);
2533
2534 // when literal brackets are explicitly enabled
2535 // assume we should escape the brackets to match literal characters
2536 if (opts.literalBrackets === true) {
2537 state.output += escaped;
2538 prev.value = escaped;
2539 continue;
2540 }
2541
2542 // when the user specifies nothing, try to match both
2543 prev.value = `(${capture}${escaped}|${prev.value})`;
2544 state.output += prev.value;
2545 continue;
2546 }
2547
2548 /**
2549 * Braces
2550 */
2551
2552 if (value === '{' && opts.nobrace !== true) {
2553 increment('braces');
2554
2555 const open = {
2556 type: 'brace',
2557 value,
2558 output: '(',
2559 outputIndex: state.output.length,
2560 tokensIndex: state.tokens.length
2561 };
2562
2563 braces.push(open);
2564 push(open);
2565 continue;
2566 }
2567
2568 if (value === '}') {
2569 const brace = braces[braces.length - 1];
2570
2571 if (opts.nobrace === true || !brace) {
2572 push({ type: 'text', value, output: value });
2573 continue;
2574 }
2575
2576 let output = ')';
2577
2578 if (brace.dots === true) {
2579 const arr = tokens.slice();
2580 const range = [];
2581
2582 for (let i = arr.length - 1; i >= 0; i--) {
2583 tokens.pop();
2584 if (arr[i].type === 'brace') {
2585 break;
2586 }
2587 if (arr[i].type !== 'dots') {
2588 range.unshift(arr[i].value);
2589 }
2590 }
2591
2592 output = expandRange(range, opts);
2593 state.backtrack = true;
2594 }
2595
2596 if (brace.comma !== true && brace.dots !== true) {
2597 const out = state.output.slice(0, brace.outputIndex);
2598 const toks = state.tokens.slice(brace.tokensIndex);
2599 brace.value = brace.output = '\\{';
2600 value = output = '\\}';
2601 state.output = out;
2602 for (const t of toks) {
2603 state.output += (t.output || t.value);
2604 }
2605 }
2606
2607 push({ type: 'brace', value, output });
2608 decrement('braces');
2609 braces.pop();
2610 continue;
2611 }
2612
2613 /**
2614 * Pipes
2615 */
2616
2617 if (value === '|') {
2618 if (extglobs.length > 0) {
2619 extglobs[extglobs.length - 1].conditions++;
2620 }
2621 push({ type: 'text', value });
2622 continue;
2623 }
2624
2625 /**
2626 * Commas
2627 */
2628
2629 if (value === ',') {
2630 let output = value;
2631
2632 const brace = braces[braces.length - 1];
2633 if (brace && stack[stack.length - 1] === 'braces') {
2634 brace.comma = true;
2635 output = '|';
2636 }
2637
2638 push({ type: 'comma', value, output });
2639 continue;
2640 }
2641
2642 /**
2643 * Slashes
2644 */
2645
2646 if (value === '/') {
2647 // if the beginning of the glob is "./", advance the start
2648 // to the current index, and don't add the "./" characters
2649 // to the state. This greatly simplifies lookbehinds when
2650 // checking for BOS characters like "!" and "." (not "./")
2651 if (prev.type === 'dot' && state.index === state.start + 1) {
2652 state.start = state.index + 1;
2653 state.consumed = '';
2654 state.output = '';
2655 tokens.pop();
2656 prev = bos; // reset "prev" to the first token
2657 continue;
2658 }
2659
2660 push({ type: 'slash', value, output: SLASH_LITERAL });
2661 continue;
2662 }
2663
2664 /**
2665 * Dots
2666 */
2667
2668 if (value === '.') {
2669 if (state.braces > 0 && prev.type === 'dot') {
2670 if (prev.value === '.') prev.output = DOT_LITERAL;
2671 const brace = braces[braces.length - 1];
2672 prev.type = 'dots';
2673 prev.output += value;
2674 prev.value += value;
2675 brace.dots = true;
2676 continue;
2677 }
2678
2679 if ((state.braces + state.parens) === 0 && prev.type !== 'bos' && prev.type !== 'slash') {
2680 push({ type: 'text', value, output: DOT_LITERAL });
2681 continue;
2682 }
2683
2684 push({ type: 'dot', value, output: DOT_LITERAL });
2685 continue;
2686 }
2687
2688 /**
2689 * Question marks
2690 */
2691
2692 if (value === '?') {
2693 const isGroup = prev && prev.value === '(';
2694 if (!isGroup && opts.noextglob !== true && peek() === '(' && peek(2) !== '?') {
2695 extglobOpen('qmark', value);
2696 continue;
2697 }
2698
2699 if (prev && prev.type === 'paren') {
2700 const next = peek();
2701 let output = value;
2702
2703 if (next === '<' && !utils$1.supportsLookbehinds()) {
2704 throw new Error('Node.js v10 or higher is required for regex lookbehinds');
2705 }
2706
2707 if ((prev.value === '(' && !/[!=<:]/.test(next)) || (next === '<' && !/<([!=]|\w+>)/.test(remaining()))) {
2708 output = `\\${value}`;
2709 }
2710
2711 push({ type: 'text', value, output });
2712 continue;
2713 }
2714
2715 if (opts.dot !== true && (prev.type === 'slash' || prev.type === 'bos')) {
2716 push({ type: 'qmark', value, output: QMARK_NO_DOT });
2717 continue;
2718 }
2719
2720 push({ type: 'qmark', value, output: QMARK });
2721 continue;
2722 }
2723
2724 /**
2725 * Exclamation
2726 */
2727
2728 if (value === '!') {
2729 if (opts.noextglob !== true && peek() === '(') {
2730 if (peek(2) !== '?' || !/[!=<:]/.test(peek(3))) {
2731 extglobOpen('negate', value);
2732 continue;
2733 }
2734 }
2735
2736 if (opts.nonegate !== true && state.index === 0) {
2737 negate();
2738 continue;
2739 }
2740 }
2741
2742 /**
2743 * Plus
2744 */
2745
2746 if (value === '+') {
2747 if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') {
2748 extglobOpen('plus', value);
2749 continue;
2750 }
2751
2752 if ((prev && prev.value === '(') || opts.regex === false) {
2753 push({ type: 'plus', value, output: PLUS_LITERAL });
2754 continue;
2755 }
2756
2757 if ((prev && (prev.type === 'bracket' || prev.type === 'paren' || prev.type === 'brace')) || state.parens > 0) {
2758 push({ type: 'plus', value });
2759 continue;
2760 }
2761
2762 push({ type: 'plus', value: PLUS_LITERAL });
2763 continue;
2764 }
2765
2766 /**
2767 * Plain text
2768 */
2769
2770 if (value === '@') {
2771 if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') {
2772 push({ type: 'at', extglob: true, value, output: '' });
2773 continue;
2774 }
2775
2776 push({ type: 'text', value });
2777 continue;
2778 }
2779
2780 /**
2781 * Plain text
2782 */
2783
2784 if (value !== '*') {
2785 if (value === '$' || value === '^') {
2786 value = `\\${value}`;
2787 }
2788
2789 const match = REGEX_NON_SPECIAL_CHARS.exec(remaining());
2790 if (match) {
2791 value += match[0];
2792 state.index += match[0].length;
2793 }
2794
2795 push({ type: 'text', value });
2796 continue;
2797 }
2798
2799 /**
2800 * Stars
2801 */
2802
2803 if (prev && (prev.type === 'globstar' || prev.star === true)) {
2804 prev.type = 'star';
2805 prev.star = true;
2806 prev.value += value;
2807 prev.output = star;
2808 state.backtrack = true;
2809 state.globstar = true;
2810 consume(value);
2811 continue;
2812 }
2813
2814 let rest = remaining();
2815 if (opts.noextglob !== true && /^\([^?]/.test(rest)) {
2816 extglobOpen('star', value);
2817 continue;
2818 }
2819
2820 if (prev.type === 'star') {
2821 if (opts.noglobstar === true) {
2822 consume(value);
2823 continue;
2824 }
2825
2826 const prior = prev.prev;
2827 const before = prior.prev;
2828 const isStart = prior.type === 'slash' || prior.type === 'bos';
2829 const afterStar = before && (before.type === 'star' || before.type === 'globstar');
2830
2831 if (opts.bash === true && (!isStart || (rest[0] && rest[0] !== '/'))) {
2832 push({ type: 'star', value, output: '' });
2833 continue;
2834 }
2835
2836 const isBrace = state.braces > 0 && (prior.type === 'comma' || prior.type === 'brace');
2837 const isExtglob = extglobs.length && (prior.type === 'pipe' || prior.type === 'paren');
2838 if (!isStart && prior.type !== 'paren' && !isBrace && !isExtglob) {
2839 push({ type: 'star', value, output: '' });
2840 continue;
2841 }
2842
2843 // strip consecutive `/**/`
2844 while (rest.slice(0, 3) === '/**') {
2845 const after = input[state.index + 4];
2846 if (after && after !== '/') {
2847 break;
2848 }
2849 rest = rest.slice(3);
2850 consume('/**', 3);
2851 }
2852
2853 if (prior.type === 'bos' && eos()) {
2854 prev.type = 'globstar';
2855 prev.value += value;
2856 prev.output = globstar(opts);
2857 state.output = prev.output;
2858 state.globstar = true;
2859 consume(value);
2860 continue;
2861 }
2862
2863 if (prior.type === 'slash' && prior.prev.type !== 'bos' && !afterStar && eos()) {
2864 state.output = state.output.slice(0, -(prior.output + prev.output).length);
2865 prior.output = `(?:${prior.output}`;
2866
2867 prev.type = 'globstar';
2868 prev.output = globstar(opts) + (opts.strictSlashes ? ')' : '|$)');
2869 prev.value += value;
2870 state.globstar = true;
2871 state.output += prior.output + prev.output;
2872 consume(value);
2873 continue;
2874 }
2875
2876 if (prior.type === 'slash' && prior.prev.type !== 'bos' && rest[0] === '/') {
2877 const end = rest[1] !== void 0 ? '|$' : '';
2878
2879 state.output = state.output.slice(0, -(prior.output + prev.output).length);
2880 prior.output = `(?:${prior.output}`;
2881
2882 prev.type = 'globstar';
2883 prev.output = `${globstar(opts)}${SLASH_LITERAL}|${SLASH_LITERAL}${end})`;
2884 prev.value += value;
2885
2886 state.output += prior.output + prev.output;
2887 state.globstar = true;
2888
2889 consume(value + advance());
2890
2891 push({ type: 'slash', value: '/', output: '' });
2892 continue;
2893 }
2894
2895 if (prior.type === 'bos' && rest[0] === '/') {
2896 prev.type = 'globstar';
2897 prev.value += value;
2898 prev.output = `(?:^|${SLASH_LITERAL}|${globstar(opts)}${SLASH_LITERAL})`;
2899 state.output = prev.output;
2900 state.globstar = true;
2901 consume(value + advance());
2902 push({ type: 'slash', value: '/', output: '' });
2903 continue;
2904 }
2905
2906 // remove single star from output
2907 state.output = state.output.slice(0, -prev.output.length);
2908
2909 // reset previous token to globstar
2910 prev.type = 'globstar';
2911 prev.output = globstar(opts);
2912 prev.value += value;
2913
2914 // reset output with globstar
2915 state.output += prev.output;
2916 state.globstar = true;
2917 consume(value);
2918 continue;
2919 }
2920
2921 const token = { type: 'star', value, output: star };
2922
2923 if (opts.bash === true) {
2924 token.output = '.*?';
2925 if (prev.type === 'bos' || prev.type === 'slash') {
2926 token.output = nodot + token.output;
2927 }
2928 push(token);
2929 continue;
2930 }
2931
2932 if (prev && (prev.type === 'bracket' || prev.type === 'paren') && opts.regex === true) {
2933 token.output = value;
2934 push(token);
2935 continue;
2936 }
2937
2938 if (state.index === state.start || prev.type === 'slash' || prev.type === 'dot') {
2939 if (prev.type === 'dot') {
2940 state.output += NO_DOT_SLASH;
2941 prev.output += NO_DOT_SLASH;
2942
2943 } else if (opts.dot === true) {
2944 state.output += NO_DOTS_SLASH;
2945 prev.output += NO_DOTS_SLASH;
2946
2947 } else {
2948 state.output += nodot;
2949 prev.output += nodot;
2950 }
2951
2952 if (peek() !== '*') {
2953 state.output += ONE_CHAR;
2954 prev.output += ONE_CHAR;
2955 }
2956 }
2957
2958 push(token);
2959 }
2960
2961 while (state.brackets > 0) {
2962 if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ']'));
2963 state.output = utils$1.escapeLast(state.output, '[');
2964 decrement('brackets');
2965 }
2966
2967 while (state.parens > 0) {
2968 if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ')'));
2969 state.output = utils$1.escapeLast(state.output, '(');
2970 decrement('parens');
2971 }
2972
2973 while (state.braces > 0) {
2974 if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', '}'));
2975 state.output = utils$1.escapeLast(state.output, '{');
2976 decrement('braces');
2977 }
2978
2979 if (opts.strictSlashes !== true && (prev.type === 'star' || prev.type === 'bracket')) {
2980 push({ type: 'maybe_slash', value: '', output: `${SLASH_LITERAL}?` });
2981 }
2982
2983 // rebuild the output if we had to backtrack at any point
2984 if (state.backtrack === true) {
2985 state.output = '';
2986
2987 for (const token of state.tokens) {
2988 state.output += token.output != null ? token.output : token.value;
2989
2990 if (token.suffix) {
2991 state.output += token.suffix;
2992 }
2993 }
2994 }
2995
2996 return state;
2997};
2998
2999/**
3000 * Fast paths for creating regular expressions for common glob patterns.
3001 * This can significantly speed up processing and has very little downside
3002 * impact when none of the fast paths match.
3003 */
3004
3005parse$1.fastpaths = (input, options) => {
3006 const opts = { ...options };
3007 const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH$1, opts.maxLength) : MAX_LENGTH$1;
3008 const len = input.length;
3009 if (len > max) {
3010 throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`);
3011 }
3012
3013 input = REPLACEMENTS[input] || input;
3014 const win32 = utils$1.isWindows(options);
3015
3016 // create constants based on platform, for windows or posix
3017 const {
3018 DOT_LITERAL,
3019 SLASH_LITERAL,
3020 ONE_CHAR,
3021 DOTS_SLASH,
3022 NO_DOT,
3023 NO_DOTS,
3024 NO_DOTS_SLASH,
3025 STAR,
3026 START_ANCHOR
3027 } = constants$1.globChars(win32);
3028
3029 const nodot = opts.dot ? NO_DOTS : NO_DOT;
3030 const slashDot = opts.dot ? NO_DOTS_SLASH : NO_DOT;
3031 const capture = opts.capture ? '' : '?:';
3032 const state = { negated: false, prefix: '' };
3033 let star = opts.bash === true ? '.*?' : STAR;
3034
3035 if (opts.capture) {
3036 star = `(${star})`;
3037 }
3038
3039 const globstar = (opts) => {
3040 if (opts.noglobstar === true) return star;
3041 return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`;
3042 };
3043
3044 const create = str => {
3045 switch (str) {
3046 case '*':
3047 return `${nodot}${ONE_CHAR}${star}`;
3048
3049 case '.*':
3050 return `${DOT_LITERAL}${ONE_CHAR}${star}`;
3051
3052 case '*.*':
3053 return `${nodot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`;
3054
3055 case '*/*':
3056 return `${nodot}${star}${SLASH_LITERAL}${ONE_CHAR}${slashDot}${star}`;
3057
3058 case '**':
3059 return nodot + globstar(opts);
3060
3061 case '**/*':
3062 return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${ONE_CHAR}${star}`;
3063
3064 case '**/*.*':
3065 return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`;
3066
3067 case '**/.*':
3068 return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${DOT_LITERAL}${ONE_CHAR}${star}`;
3069
3070 default: {
3071 const match = /^(.*?)\.(\w+)$/.exec(str);
3072 if (!match) return;
3073
3074 const source = create(match[1]);
3075 if (!source) return;
3076
3077 return source + DOT_LITERAL + match[2];
3078 }
3079 }
3080 };
3081
3082 const output = utils$1.removePrefix(input, state);
3083 let source = create(output);
3084
3085 if (source && opts.strictSlashes !== true) {
3086 source += `${SLASH_LITERAL}?`;
3087 }
3088
3089 return source;
3090};
3091
3092var parse_1$1 = parse$1;
3093
3094const isObject$1 = val => val && typeof val === 'object' && !Array.isArray(val);
3095
3096/**
3097 * Creates a matcher function from one or more glob patterns. The
3098 * returned function takes a string to match as its first argument,
3099 * and returns true if the string is a match. The returned matcher
3100 * function also takes a boolean as the second argument that, when true,
3101 * returns an object with additional information.
3102 *
3103 * ```js
3104 * const picomatch = require('picomatch');
3105 * // picomatch(glob[, options]);
3106 *
3107 * const isMatch = picomatch('*.!(*a)');
3108 * console.log(isMatch('a.a')); //=> false
3109 * console.log(isMatch('a.b')); //=> true
3110 * ```
3111 * @name picomatch
3112 * @param {String|Array} `globs` One or more glob patterns.
3113 * @param {Object=} `options`
3114 * @return {Function=} Returns a matcher function.
3115 * @api public
3116 */
3117
3118const picomatch = (glob, options, returnState = false) => {
3119 if (Array.isArray(glob)) {
3120 const fns = glob.map(input => picomatch(input, options, returnState));
3121 const arrayMatcher = str => {
3122 for (const isMatch of fns) {
3123 const state = isMatch(str);
3124 if (state) return state;
3125 }
3126 return false;
3127 };
3128 return arrayMatcher;
3129 }
3130
3131 const isState = isObject$1(glob) && glob.tokens && glob.input;
3132
3133 if (glob === '' || (typeof glob !== 'string' && !isState)) {
3134 throw new TypeError('Expected pattern to be a non-empty string');
3135 }
3136
3137 const opts = options || {};
3138 const posix = utils$1.isWindows(options);
3139 const regex = isState
3140 ? picomatch.compileRe(glob, options)
3141 : picomatch.makeRe(glob, options, false, true);
3142
3143 const state = regex.state;
3144 delete regex.state;
3145
3146 let isIgnored = () => false;
3147 if (opts.ignore) {
3148 const ignoreOpts = { ...options, ignore: null, onMatch: null, onResult: null };
3149 isIgnored = picomatch(opts.ignore, ignoreOpts, returnState);
3150 }
3151
3152 const matcher = (input, returnObject = false) => {
3153 const { isMatch, match, output } = picomatch.test(input, regex, options, { glob, posix });
3154 const result = { glob, state, regex, posix, input, output, match, isMatch };
3155
3156 if (typeof opts.onResult === 'function') {
3157 opts.onResult(result);
3158 }
3159
3160 if (isMatch === false) {
3161 result.isMatch = false;
3162 return returnObject ? result : false;
3163 }
3164
3165 if (isIgnored(input)) {
3166 if (typeof opts.onIgnore === 'function') {
3167 opts.onIgnore(result);
3168 }
3169 result.isMatch = false;
3170 return returnObject ? result : false;
3171 }
3172
3173 if (typeof opts.onMatch === 'function') {
3174 opts.onMatch(result);
3175 }
3176 return returnObject ? result : true;
3177 };
3178
3179 if (returnState) {
3180 matcher.state = state;
3181 }
3182
3183 return matcher;
3184};
3185
3186/**
3187 * Test `input` with the given `regex`. This is used by the main
3188 * `picomatch()` function to test the input string.
3189 *
3190 * ```js
3191 * const picomatch = require('picomatch');
3192 * // picomatch.test(input, regex[, options]);
3193 *
3194 * console.log(picomatch.test('foo/bar', /^(?:([^/]*?)\/([^/]*?))$/));
3195 * // { isMatch: true, match: [ 'foo/', 'foo', 'bar' ], output: 'foo/bar' }
3196 * ```
3197 * @param {String} `input` String to test.
3198 * @param {RegExp} `regex`
3199 * @return {Object} Returns an object with matching info.
3200 * @api public
3201 */
3202
3203picomatch.test = (input, regex, options, { glob, posix } = {}) => {
3204 if (typeof input !== 'string') {
3205 throw new TypeError('Expected input to be a string');
3206 }
3207
3208 if (input === '') {
3209 return { isMatch: false, output: '' };
3210 }
3211
3212 const opts = options || {};
3213 const format = opts.format || (posix ? utils$1.toPosixSlashes : null);
3214 let match = input === glob;
3215 let output = (match && format) ? format(input) : input;
3216
3217 if (match === false) {
3218 output = format ? format(input) : input;
3219 match = output === glob;
3220 }
3221
3222 if (match === false || opts.capture === true) {
3223 if (opts.matchBase === true || opts.basename === true) {
3224 match = picomatch.matchBase(input, regex, options, posix);
3225 } else {
3226 match = regex.exec(output);
3227 }
3228 }
3229
3230 return { isMatch: Boolean(match), match, output };
3231};
3232
3233/**
3234 * Match the basename of a filepath.
3235 *
3236 * ```js
3237 * const picomatch = require('picomatch');
3238 * // picomatch.matchBase(input, glob[, options]);
3239 * console.log(picomatch.matchBase('foo/bar.js', '*.js'); // true
3240 * ```
3241 * @param {String} `input` String to test.
3242 * @param {RegExp|String} `glob` Glob pattern or regex created by [.makeRe](#makeRe).
3243 * @return {Boolean}
3244 * @api public
3245 */
3246
3247picomatch.matchBase = (input, glob, options, posix = utils$1.isWindows(options)) => {
3248 const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options);
3249 return regex.test(sysPath.basename(input));
3250};
3251
3252/**
3253 * Returns true if **any** of the given glob `patterns` match the specified `string`.
3254 *
3255 * ```js
3256 * const picomatch = require('picomatch');
3257 * // picomatch.isMatch(string, patterns[, options]);
3258 *
3259 * console.log(picomatch.isMatch('a.a', ['b.*', '*.a'])); //=> true
3260 * console.log(picomatch.isMatch('a.a', 'b.*')); //=> false
3261 * ```
3262 * @param {String|Array} str The string to test.
3263 * @param {String|Array} patterns One or more glob patterns to use for matching.
3264 * @param {Object} [options] See available [options](#options).
3265 * @return {Boolean} Returns true if any patterns match `str`
3266 * @api public
3267 */
3268
3269picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str);
3270
3271/**
3272 * Parse a glob pattern to create the source string for a regular
3273 * expression.
3274 *
3275 * ```js
3276 * const picomatch = require('picomatch');
3277 * const result = picomatch.parse(pattern[, options]);
3278 * ```
3279 * @param {String} `pattern`
3280 * @param {Object} `options`
3281 * @return {Object} Returns an object with useful properties and output to be used as a regex source string.
3282 * @api public
3283 */
3284
3285picomatch.parse = (pattern, options) => {
3286 if (Array.isArray(pattern)) return pattern.map(p => picomatch.parse(p, options));
3287 return parse_1$1(pattern, { ...options, fastpaths: false });
3288};
3289
3290/**
3291 * Scan a glob pattern to separate the pattern into segments.
3292 *
3293 * ```js
3294 * const picomatch = require('picomatch');
3295 * // picomatch.scan(input[, options]);
3296 *
3297 * const result = picomatch.scan('!./foo/*.js');
3298 * console.log(result);
3299 * { prefix: '!./',
3300 * input: '!./foo/*.js',
3301 * start: 3,
3302 * base: 'foo',
3303 * glob: '*.js',
3304 * isBrace: false,
3305 * isBracket: false,
3306 * isGlob: true,
3307 * isExtglob: false,
3308 * isGlobstar: false,
3309 * negated: true }
3310 * ```
3311 * @param {String} `input` Glob pattern to scan.
3312 * @param {Object} `options`
3313 * @return {Object} Returns an object with
3314 * @api public
3315 */
3316
3317picomatch.scan = (input, options) => scan_1(input, options);
3318
3319/**
3320 * Create a regular expression from a parsed glob pattern.
3321 *
3322 * ```js
3323 * const picomatch = require('picomatch');
3324 * const state = picomatch.parse('*.js');
3325 * // picomatch.compileRe(state[, options]);
3326 *
3327 * console.log(picomatch.compileRe(state));
3328 * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/
3329 * ```
3330 * @param {String} `state` The object returned from the `.parse` method.
3331 * @param {Object} `options`
3332 * @return {RegExp} Returns a regex created from the given pattern.
3333 * @api public
3334 */
3335
3336picomatch.compileRe = (parsed, options, returnOutput = false, returnState = false) => {
3337 if (returnOutput === true) {
3338 return parsed.output;
3339 }
3340
3341 const opts = options || {};
3342 const prepend = opts.contains ? '' : '^';
3343 const append = opts.contains ? '' : '$';
3344
3345 let source = `${prepend}(?:${parsed.output})${append}`;
3346 if (parsed && parsed.negated === true) {
3347 source = `^(?!${source}).*$`;
3348 }
3349
3350 const regex = picomatch.toRegex(source, options);
3351 if (returnState === true) {
3352 regex.state = parsed;
3353 }
3354
3355 return regex;
3356};
3357
3358picomatch.makeRe = (input, options, returnOutput = false, returnState = false) => {
3359 if (!input || typeof input !== 'string') {
3360 throw new TypeError('Expected a non-empty string');
3361 }
3362
3363 const opts = options || {};
3364 let parsed = { negated: false, fastpaths: true };
3365 let prefix = '';
3366 let output;
3367
3368 if (input.startsWith('./')) {
3369 input = input.slice(2);
3370 prefix = parsed.prefix = './';
3371 }
3372
3373 if (opts.fastpaths !== false && (input[0] === '.' || input[0] === '*')) {
3374 output = parse_1$1.fastpaths(input, options);
3375 }
3376
3377 if (output === undefined) {
3378 parsed = parse_1$1(input, options);
3379 parsed.prefix = prefix + (parsed.prefix || '');
3380 } else {
3381 parsed.output = output;
3382 }
3383
3384 return picomatch.compileRe(parsed, options, returnOutput, returnState);
3385};
3386
3387/**
3388 * Create a regular expression from the given regex source string.
3389 *
3390 * ```js
3391 * const picomatch = require('picomatch');
3392 * // picomatch.toRegex(source[, options]);
3393 *
3394 * const { output } = picomatch.parse('*.js');
3395 * console.log(picomatch.toRegex(output));
3396 * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/
3397 * ```
3398 * @param {String} `source` Regular expression source string.
3399 * @param {Object} `options`
3400 * @return {RegExp}
3401 * @api public
3402 */
3403
3404picomatch.toRegex = (source, options) => {
3405 try {
3406 const opts = options || {};
3407 return new RegExp(source, opts.flags || (opts.nocase ? 'i' : ''));
3408 } catch (err) {
3409 if (options && options.debug === true) throw err;
3410 return /$^/;
3411 }
3412};
3413
3414/**
3415 * Picomatch constants.
3416 * @return {Object}
3417 */
3418
3419picomatch.constants = constants$1;
3420
3421/**
3422 * Expose "picomatch"
3423 */
3424
3425var picomatch_1 = picomatch;
3426
3427var picomatch$1 = picomatch_1;
3428
3429const isEmptyString = val => typeof val === 'string' && (val === '' || val === './');
3430
3431/**
3432 * Returns an array of strings that match one or more glob patterns.
3433 *
3434 * ```js
3435 * const mm = require('micromatch');
3436 * // mm(list, patterns[, options]);
3437 *
3438 * console.log(mm(['a.js', 'a.txt'], ['*.js']));
3439 * //=> [ 'a.js' ]
3440 * ```
3441 * @param {String|Array<string>} list List of strings to match.
3442 * @param {String|Array<string>} patterns One or more glob patterns to use for matching.
3443 * @param {Object} options See available [options](#options)
3444 * @return {Array} Returns an array of matches
3445 * @summary false
3446 * @api public
3447 */
3448
3449const micromatch = (list, patterns, options) => {
3450 patterns = [].concat(patterns);
3451 list = [].concat(list);
3452
3453 let omit = new Set();
3454 let keep = new Set();
3455 let items = new Set();
3456 let negatives = 0;
3457
3458 let onResult = state => {
3459 items.add(state.output);
3460 if (options && options.onResult) {
3461 options.onResult(state);
3462 }
3463 };
3464
3465 for (let i = 0; i < patterns.length; i++) {
3466 let isMatch = picomatch$1(String(patterns[i]), { ...options, onResult }, true);
3467 let negated = isMatch.state.negated || isMatch.state.negatedExtglob;
3468 if (negated) negatives++;
3469
3470 for (let item of list) {
3471 let matched = isMatch(item, true);
3472
3473 let match = negated ? !matched.isMatch : matched.isMatch;
3474 if (!match) continue;
3475
3476 if (negated) {
3477 omit.add(matched.output);
3478 } else {
3479 omit.delete(matched.output);
3480 keep.add(matched.output);
3481 }
3482 }
3483 }
3484
3485 let result = negatives === patterns.length ? [...items] : [...keep];
3486 let matches = result.filter(item => !omit.has(item));
3487
3488 if (options && matches.length === 0) {
3489 if (options.failglob === true) {
3490 throw new Error(`No matches found for "${patterns.join(', ')}"`);
3491 }
3492
3493 if (options.nonull === true || options.nullglob === true) {
3494 return options.unescape ? patterns.map(p => p.replace(/\\/g, '')) : patterns;
3495 }
3496 }
3497
3498 return matches;
3499};
3500
3501/**
3502 * Backwards compatibility
3503 */
3504
3505micromatch.match = micromatch;
3506
3507/**
3508 * Returns a matcher function from the given glob `pattern` and `options`.
3509 * The returned function takes a string to match as its only argument and returns
3510 * true if the string is a match.
3511 *
3512 * ```js
3513 * const mm = require('micromatch');
3514 * // mm.matcher(pattern[, options]);
3515 *
3516 * const isMatch = mm.matcher('*.!(*a)');
3517 * console.log(isMatch('a.a')); //=> false
3518 * console.log(isMatch('a.b')); //=> true
3519 * ```
3520 * @param {String} `pattern` Glob pattern
3521 * @param {Object} `options`
3522 * @return {Function} Returns a matcher function.
3523 * @api public
3524 */
3525
3526micromatch.matcher = (pattern, options) => picomatch$1(pattern, options);
3527
3528/**
3529 * Returns true if **any** of the given glob `patterns` match the specified `string`.
3530 *
3531 * ```js
3532 * const mm = require('micromatch');
3533 * // mm.isMatch(string, patterns[, options]);
3534 *
3535 * console.log(mm.isMatch('a.a', ['b.*', '*.a'])); //=> true
3536 * console.log(mm.isMatch('a.a', 'b.*')); //=> false
3537 * ```
3538 * @param {String} str The string to test.
3539 * @param {String|Array} patterns One or more glob patterns to use for matching.
3540 * @param {Object} [options] See available [options](#options).
3541 * @return {Boolean} Returns true if any patterns match `str`
3542 * @api public
3543 */
3544
3545micromatch.isMatch = (str, patterns, options) => picomatch$1(patterns, options)(str);
3546
3547/**
3548 * Backwards compatibility
3549 */
3550
3551micromatch.any = micromatch.isMatch;
3552
3553/**
3554 * Returns a list of strings that _**do not match any**_ of the given `patterns`.
3555 *
3556 * ```js
3557 * const mm = require('micromatch');
3558 * // mm.not(list, patterns[, options]);
3559 *
3560 * console.log(mm.not(['a.a', 'b.b', 'c.c'], '*.a'));
3561 * //=> ['b.b', 'c.c']
3562 * ```
3563 * @param {Array} `list` Array of strings to match.
3564 * @param {String|Array} `patterns` One or more glob pattern to use for matching.
3565 * @param {Object} `options` See available [options](#options) for changing how matches are performed
3566 * @return {Array} Returns an array of strings that **do not match** the given patterns.
3567 * @api public
3568 */
3569
3570micromatch.not = (list, patterns, options = {}) => {
3571 patterns = [].concat(patterns).map(String);
3572 let result = new Set();
3573 let items = [];
3574
3575 let onResult = state => {
3576 if (options.onResult) options.onResult(state);
3577 items.push(state.output);
3578 };
3579
3580 let matches = micromatch(list, patterns, { ...options, onResult });
3581
3582 for (let item of items) {
3583 if (!matches.includes(item)) {
3584 result.add(item);
3585 }
3586 }
3587 return [...result];
3588};
3589
3590/**
3591 * Returns true if the given `string` contains the given pattern. Similar
3592 * to [.isMatch](#isMatch) but the pattern can match any part of the string.
3593 *
3594 * ```js
3595 * var mm = require('micromatch');
3596 * // mm.contains(string, pattern[, options]);
3597 *
3598 * console.log(mm.contains('aa/bb/cc', '*b'));
3599 * //=> true
3600 * console.log(mm.contains('aa/bb/cc', '*d'));
3601 * //=> false
3602 * ```
3603 * @param {String} `str` The string to match.
3604 * @param {String|Array} `patterns` Glob pattern to use for matching.
3605 * @param {Object} `options` See available [options](#options) for changing how matches are performed
3606 * @return {Boolean} Returns true if the patter matches any part of `str`.
3607 * @api public
3608 */
3609
3610micromatch.contains = (str, pattern, options) => {
3611 if (typeof str !== 'string') {
3612 throw new TypeError(`Expected a string: "${util.inspect(str)}"`);
3613 }
3614
3615 if (Array.isArray(pattern)) {
3616 return pattern.some(p => micromatch.contains(str, p, options));
3617 }
3618
3619 if (typeof pattern === 'string') {
3620 if (isEmptyString(str) || isEmptyString(pattern)) {
3621 return false;
3622 }
3623
3624 if (str.includes(pattern) || (str.startsWith('./') && str.slice(2).includes(pattern))) {
3625 return true;
3626 }
3627 }
3628
3629 return micromatch.isMatch(str, pattern, { ...options, contains: true });
3630};
3631
3632/**
3633 * Filter the keys of the given object with the given `glob` pattern
3634 * and `options`. Does not attempt to match nested keys. If you need this feature,
3635 * use [glob-object][] instead.
3636 *
3637 * ```js
3638 * const mm = require('micromatch');
3639 * // mm.matchKeys(object, patterns[, options]);
3640 *
3641 * const obj = { aa: 'a', ab: 'b', ac: 'c' };
3642 * console.log(mm.matchKeys(obj, '*b'));
3643 * //=> { ab: 'b' }
3644 * ```
3645 * @param {Object} `object` The object with keys to filter.
3646 * @param {String|Array} `patterns` One or more glob patterns to use for matching.
3647 * @param {Object} `options` See available [options](#options) for changing how matches are performed
3648 * @return {Object} Returns an object with only keys that match the given patterns.
3649 * @api public
3650 */
3651
3652micromatch.matchKeys = (obj, patterns, options) => {
3653 if (!utils$1.isObject(obj)) {
3654 throw new TypeError('Expected the first argument to be an object');
3655 }
3656 let keys = micromatch(Object.keys(obj), patterns, options);
3657 let res = {};
3658 for (let key of keys) res[key] = obj[key];
3659 return res;
3660};
3661
3662/**
3663 * Returns true if some of the strings in the given `list` match any of the given glob `patterns`.
3664 *
3665 * ```js
3666 * const mm = require('micromatch');
3667 * // mm.some(list, patterns[, options]);
3668 *
3669 * console.log(mm.some(['foo.js', 'bar.js'], ['*.js', '!foo.js']));
3670 * // true
3671 * console.log(mm.some(['foo.js'], ['*.js', '!foo.js']));
3672 * // false
3673 * ```
3674 * @param {String|Array} `list` The string or array of strings to test. Returns as soon as the first match is found.
3675 * @param {String|Array} `patterns` One or more glob patterns to use for matching.
3676 * @param {Object} `options` See available [options](#options) for changing how matches are performed
3677 * @return {Boolean} Returns true if any patterns match `str`
3678 * @api public
3679 */
3680
3681micromatch.some = (list, patterns, options) => {
3682 let items = [].concat(list);
3683
3684 for (let pattern of [].concat(patterns)) {
3685 let isMatch = picomatch$1(String(pattern), options);
3686 if (items.some(item => isMatch(item))) {
3687 return true;
3688 }
3689 }
3690 return false;
3691};
3692
3693/**
3694 * Returns true if every string in the given `list` matches
3695 * any of the given glob `patterns`.
3696 *
3697 * ```js
3698 * const mm = require('micromatch');
3699 * // mm.every(list, patterns[, options]);
3700 *
3701 * console.log(mm.every('foo.js', ['foo.js']));
3702 * // true
3703 * console.log(mm.every(['foo.js', 'bar.js'], ['*.js']));
3704 * // true
3705 * console.log(mm.every(['foo.js', 'bar.js'], ['*.js', '!foo.js']));
3706 * // false
3707 * console.log(mm.every(['foo.js'], ['*.js', '!foo.js']));
3708 * // false
3709 * ```
3710 * @param {String|Array} `list` The string or array of strings to test.
3711 * @param {String|Array} `patterns` One or more glob patterns to use for matching.
3712 * @param {Object} `options` See available [options](#options) for changing how matches are performed
3713 * @return {Boolean} Returns true if any patterns match `str`
3714 * @api public
3715 */
3716
3717micromatch.every = (list, patterns, options) => {
3718 let items = [].concat(list);
3719
3720 for (let pattern of [].concat(patterns)) {
3721 let isMatch = picomatch$1(String(pattern), options);
3722 if (!items.every(item => isMatch(item))) {
3723 return false;
3724 }
3725 }
3726 return true;
3727};
3728
3729/**
3730 * Returns true if **all** of the given `patterns` match
3731 * the specified string.
3732 *
3733 * ```js
3734 * const mm = require('micromatch');
3735 * // mm.all(string, patterns[, options]);
3736 *
3737 * console.log(mm.all('foo.js', ['foo.js']));
3738 * // true
3739 *
3740 * console.log(mm.all('foo.js', ['*.js', '!foo.js']));
3741 * // false
3742 *
3743 * console.log(mm.all('foo.js', ['*.js', 'foo.js']));
3744 * // true
3745 *
3746 * console.log(mm.all('foo.js', ['*.js', 'f*', '*o*', '*o.js']));
3747 * // true
3748 * ```
3749 * @param {String|Array} `str` The string to test.
3750 * @param {String|Array} `patterns` One or more glob patterns to use for matching.
3751 * @param {Object} `options` See available [options](#options) for changing how matches are performed
3752 * @return {Boolean} Returns true if any patterns match `str`
3753 * @api public
3754 */
3755
3756micromatch.all = (str, patterns, options) => {
3757 if (typeof str !== 'string') {
3758 throw new TypeError(`Expected a string: "${util.inspect(str)}"`);
3759 }
3760
3761 return [].concat(patterns).every(p => picomatch$1(p, options)(str));
3762};
3763
3764/**
3765 * Returns an array of matches captured by `pattern` in `string, or `null` if the pattern did not match.
3766 *
3767 * ```js
3768 * const mm = require('micromatch');
3769 * // mm.capture(pattern, string[, options]);
3770 *
3771 * console.log(mm.capture('test/*.js', 'test/foo.js'));
3772 * //=> ['foo']
3773 * console.log(mm.capture('test/*.js', 'foo/bar.css'));
3774 * //=> null
3775 * ```
3776 * @param {String} `glob` Glob pattern to use for matching.
3777 * @param {String} `input` String to match
3778 * @param {Object} `options` See available [options](#options) for changing how matches are performed
3779 * @return {Boolean} Returns an array of captures if the input matches the glob pattern, otherwise `null`.
3780 * @api public
3781 */
3782
3783micromatch.capture = (glob, input, options) => {
3784 let posix = utils$1.isWindows(options);
3785 let regex = picomatch$1.makeRe(String(glob), { ...options, capture: true });
3786 let match = regex.exec(posix ? utils$1.toPosixSlashes(input) : input);
3787
3788 if (match) {
3789 return match.slice(1).map(v => v === void 0 ? '' : v);
3790 }
3791};
3792
3793/**
3794 * Create a regular expression from the given glob `pattern`.
3795 *
3796 * ```js
3797 * const mm = require('micromatch');
3798 * // mm.makeRe(pattern[, options]);
3799 *
3800 * console.log(mm.makeRe('*.js'));
3801 * //=> /^(?:(\.[\\\/])?(?!\.)(?=.)[^\/]*?\.js)$/
3802 * ```
3803 * @param {String} `pattern` A glob pattern to convert to regex.
3804 * @param {Object} `options`
3805 * @return {RegExp} Returns a regex created from the given pattern.
3806 * @api public
3807 */
3808
3809micromatch.makeRe = (...args) => picomatch$1.makeRe(...args);
3810
3811/**
3812 * Scan a glob pattern to separate the pattern into segments. Used
3813 * by the [split](#split) method.
3814 *
3815 * ```js
3816 * const mm = require('micromatch');
3817 * const state = mm.scan(pattern[, options]);
3818 * ```
3819 * @param {String} `pattern`
3820 * @param {Object} `options`
3821 * @return {Object} Returns an object with
3822 * @api public
3823 */
3824
3825micromatch.scan = (...args) => picomatch$1.scan(...args);
3826
3827/**
3828 * Parse a glob pattern to create the source string for a regular
3829 * expression.
3830 *
3831 * ```js
3832 * const mm = require('micromatch');
3833 * const state = mm(pattern[, options]);
3834 * ```
3835 * @param {String} `glob`
3836 * @param {Object} `options`
3837 * @return {Object} Returns an object with useful properties and output to be used as regex source string.
3838 * @api public
3839 */
3840
3841micromatch.parse = (patterns, options) => {
3842 let res = [];
3843 for (let pattern of [].concat(patterns || [])) {
3844 for (let str of braces_1(String(pattern), options)) {
3845 res.push(picomatch$1.parse(str, options));
3846 }
3847 }
3848 return res;
3849};
3850
3851/**
3852 * Process the given brace `pattern`.
3853 *
3854 * ```js
3855 * const { braces } = require('micromatch');
3856 * console.log(braces('foo/{a,b,c}/bar'));
3857 * //=> [ 'foo/(a|b|c)/bar' ]
3858 *
3859 * console.log(braces('foo/{a,b,c}/bar', { expand: true }));
3860 * //=> [ 'foo/a/bar', 'foo/b/bar', 'foo/c/bar' ]
3861 * ```
3862 * @param {String} `pattern` String with brace pattern to process.
3863 * @param {Object} `options` Any [options](#options) to change how expansion is performed. See the [braces][] library for all available options.
3864 * @return {Array}
3865 * @api public
3866 */
3867
3868micromatch.braces = (pattern, options) => {
3869 if (typeof pattern !== 'string') throw new TypeError('Expected a string');
3870 if ((options && options.nobrace === true) || !/\{.*\}/.test(pattern)) {
3871 return [pattern];
3872 }
3873 return braces_1(pattern, options);
3874};
3875
3876/**
3877 * Expand braces
3878 */
3879
3880micromatch.braceExpand = (pattern, options) => {
3881 if (typeof pattern !== 'string') throw new TypeError('Expected a string');
3882 return micromatch.braces(pattern, { ...options, expand: true });
3883};
3884
3885/**
3886 * Expose micromatch
3887 */
3888
3889var micromatch_1 = micromatch;
3890
3891function ensureArray(thing) {
3892 if (Array.isArray(thing))
3893 return thing;
3894 if (thing == undefined)
3895 return [];
3896 return [thing];
3897}
3898
3899function getMatcherString(id, resolutionBase) {
3900 if (resolutionBase === false) {
3901 return id;
3902 }
3903 return resolve(...(typeof resolutionBase === 'string' ? [resolutionBase, id] : [id]));
3904}
3905const createFilter = function createFilter(include, exclude, options) {
3906 const resolutionBase = options && options.resolve;
3907 const getMatcher = (id) => {
3908 return id instanceof RegExp
3909 ? id
3910 : {
3911 test: micromatch_1.matcher(getMatcherString(id, resolutionBase)
3912 .split(sep)
3913 .join('/'), { dot: true })
3914 };
3915 };
3916 const includeMatchers = ensureArray(include).map(getMatcher);
3917 const excludeMatchers = ensureArray(exclude).map(getMatcher);
3918 return function (id) {
3919 if (typeof id !== 'string')
3920 return false;
3921 if (/\0/.test(id))
3922 return false;
3923 id = id.split(sep).join('/');
3924 for (let i = 0; i < excludeMatchers.length; ++i) {
3925 const matcher = excludeMatchers[i];
3926 if (matcher.test(id))
3927 return false;
3928 }
3929 for (let i = 0; i < includeMatchers.length; ++i) {
3930 const matcher = includeMatchers[i];
3931 if (matcher.test(id))
3932 return true;
3933 }
3934 return !includeMatchers.length;
3935 };
3936};
3937
3938const commandAliases = {
3939 c: 'config',
3940 d: 'dir',
3941 e: 'external',
3942 f: 'format',
3943 g: 'globals',
3944 h: 'help',
3945 i: 'input',
3946 m: 'sourcemap',
3947 n: 'name',
3948 o: 'file',
3949 p: 'plugin',
3950 v: 'version',
3951 w: 'watch'
3952};
3953function mergeOptions(config, rawCommandOptions = { external: [], globals: undefined }, defaultOnWarnHandler = defaultOnWarn) {
3954 const command = getCommandOptions(rawCommandOptions);
3955 const inputOptions = mergeInputOptions(config, command, defaultOnWarnHandler);
3956 const warn = inputOptions.onwarn;
3957 if (command.output) {
3958 Object.assign(command, command.output);
3959 }
3960 const outputOptionsArray = ensureArray$1(config.output);
3961 if (outputOptionsArray.length === 0)
3962 outputOptionsArray.push({});
3963 const outputOptions = outputOptionsArray.map(singleOutputOptions => mergeOutputOptions(singleOutputOptions, command, warn));
3964 warnUnknownOptions(command, Object.keys(inputOptions).concat(Object.keys(outputOptions[0]).filter(option => option !== 'sourcemapPathTransform'), Object.keys(commandAliases), 'config', 'environment', 'plugin', 'silent', 'failAfterWarnings', 'stdin', 'waitForBundleInput'), 'CLI flags', warn, /^_$|output$|config/);
3965 inputOptions.output = outputOptions;
3966 return inputOptions;
3967}
3968function getCommandOptions(rawCommandOptions) {
3969 const external = rawCommandOptions.external && typeof rawCommandOptions.external === 'string'
3970 ? rawCommandOptions.external.split(',')
3971 : [];
3972 return {
3973 ...rawCommandOptions,
3974 external,
3975 globals: typeof rawCommandOptions.globals === 'string'
3976 ? rawCommandOptions.globals.split(',').reduce((globals, globalDefinition) => {
3977 const [id, variableName] = globalDefinition.split(':');
3978 globals[id] = variableName;
3979 if (external.indexOf(id) === -1) {
3980 external.push(id);
3981 }
3982 return globals;
3983 }, Object.create(null))
3984 : undefined
3985 };
3986}
3987function mergeInputOptions(config, overrides, defaultOnWarnHandler) {
3988 const getOption = (name) => { var _a; return (_a = overrides[name]) !== null && _a !== void 0 ? _a : config[name]; };
3989 const inputOptions = {
3990 acorn: getOption('acorn'),
3991 acornInjectPlugins: config.acornInjectPlugins,
3992 cache: config.cache,
3993 context: getOption('context'),
3994 experimentalCacheExpiry: getOption('experimentalCacheExpiry'),
3995 external: getExternal(config, overrides),
3996 inlineDynamicImports: getOption('inlineDynamicImports'),
3997 input: getOption('input') || [],
3998 manualChunks: getOption('manualChunks'),
3999 moduleContext: getOption('moduleContext'),
4000 onwarn: getOnWarn(config, defaultOnWarnHandler),
4001 perf: getOption('perf'),
4002 plugins: ensureArray$1(config.plugins),
4003 preserveEntrySignatures: getOption('preserveEntrySignatures'),
4004 preserveModules: getOption('preserveModules'),
4005 preserveSymlinks: getOption('preserveSymlinks'),
4006 shimMissingExports: getOption('shimMissingExports'),
4007 strictDeprecations: getOption('strictDeprecations'),
4008 treeshake: getObjectOption(config, overrides, 'treeshake'),
4009 watch: getWatch(config, overrides, 'watch')
4010 };
4011 warnUnknownOptions(config, Object.keys(inputOptions), 'input options', inputOptions.onwarn, /^output$/);
4012 return inputOptions;
4013}
4014const getExternal = (config, overrides) => {
4015 const configExternal = config.external;
4016 return typeof configExternal === 'function'
4017 ? (source, importer, isResolved) => configExternal(source, importer, isResolved) || overrides.external.indexOf(source) !== -1
4018 : ensureArray$1(configExternal).concat(overrides.external);
4019};
4020const getOnWarn = (config, defaultOnWarnHandler) => config.onwarn
4021 ? warning => config.onwarn(warning, defaultOnWarnHandler)
4022 : defaultOnWarnHandler;
4023const getObjectOption = (config, overrides, name) => {
4024 const commandOption = normalizeObjectOptionValue(overrides[name]);
4025 const configOption = normalizeObjectOptionValue(config[name]);
4026 if (commandOption !== undefined) {
4027 return commandOption && { ...configOption, ...commandOption };
4028 }
4029 return configOption;
4030};
4031const getWatch = (config, overrides, name) => config.watch !== false && getObjectOption(config, overrides, name);
4032const normalizeObjectOptionValue = (optionValue) => {
4033 if (!optionValue) {
4034 return optionValue;
4035 }
4036 if (Array.isArray(optionValue)) {
4037 return optionValue.reduce((result, value) => value && result && { ...result, ...value }, {});
4038 }
4039 if (typeof optionValue !== 'object') {
4040 return {};
4041 }
4042 return optionValue;
4043};
4044function mergeOutputOptions(config, overrides, warn) {
4045 const getOption = (name) => { var _a; return (_a = overrides[name]) !== null && _a !== void 0 ? _a : config[name]; };
4046 const outputOptions = {
4047 amd: getObjectOption(config, overrides, 'amd'),
4048 assetFileNames: getOption('assetFileNames'),
4049 banner: getOption('banner'),
4050 chunkFileNames: getOption('chunkFileNames'),
4051 compact: getOption('compact'),
4052 dir: getOption('dir'),
4053 dynamicImportFunction: getOption('dynamicImportFunction'),
4054 entryFileNames: getOption('entryFileNames'),
4055 esModule: getOption('esModule'),
4056 exports: getOption('exports'),
4057 extend: getOption('extend'),
4058 externalLiveBindings: getOption('externalLiveBindings'),
4059 file: getOption('file'),
4060 footer: getOption('footer'),
4061 format: getOption('format'),
4062 freeze: getOption('freeze'),
4063 globals: getOption('globals'),
4064 hoistTransitiveImports: getOption('hoistTransitiveImports'),
4065 indent: getOption('indent'),
4066 inlineDynamicImports: getOption('inlineDynamicImports'),
4067 interop: getOption('interop'),
4068 intro: getOption('intro'),
4069 manualChunks: getOption('manualChunks'),
4070 minifyInternalExports: getOption('minifyInternalExports'),
4071 name: getOption('name'),
4072 namespaceToStringTag: getOption('namespaceToStringTag'),
4073 noConflict: getOption('noConflict'),
4074 outro: getOption('outro'),
4075 paths: getOption('paths'),
4076 plugins: ensureArray$1(config.plugins),
4077 preferConst: getOption('preferConst'),
4078 preserveModules: getOption('preserveModules'),
4079 preserveModulesRoot: getOption('preserveModulesRoot'),
4080 sourcemap: getOption('sourcemap'),
4081 sourcemapExcludeSources: getOption('sourcemapExcludeSources'),
4082 sourcemapFile: getOption('sourcemapFile'),
4083 sourcemapPathTransform: getOption('sourcemapPathTransform'),
4084 strict: getOption('strict'),
4085 systemNullSetters: getOption('systemNullSetters')
4086 };
4087 warnUnknownOptions(config, Object.keys(outputOptions), 'output options', warn);
4088 return outputOptions;
4089}
4090
4091const { Readable } = require$$0$1;
4092
4093const { promisify } = util;
4094
4095
4096const readdir = promisify(fs.readdir);
4097const stat = promisify(fs.stat);
4098const lstat = promisify(fs.lstat);
4099const realpath = promisify(fs.realpath);
4100
4101/**
4102 * @typedef {Object} EntryInfo
4103 * @property {String} path
4104 * @property {String} fullPath
4105 * @property {fs.Stats=} stats
4106 * @property {fs.Dirent=} dirent
4107 * @property {String} basename
4108 */
4109
4110const BANG = '!';
4111const NORMAL_FLOW_ERRORS = new Set(['ENOENT', 'EPERM', 'EACCES', 'ELOOP']);
4112const FILE_TYPE = 'files';
4113const DIR_TYPE = 'directories';
4114const FILE_DIR_TYPE = 'files_directories';
4115const EVERYTHING_TYPE = 'all';
4116const ALL_TYPES = [FILE_TYPE, DIR_TYPE, FILE_DIR_TYPE, EVERYTHING_TYPE];
4117
4118const isNormalFlowError = error => NORMAL_FLOW_ERRORS.has(error.code);
4119
4120const normalizeFilter = filter => {
4121 if (filter === undefined) return;
4122 if (typeof filter === 'function') return filter;
4123
4124 if (typeof filter === 'string') {
4125 const glob = picomatch$1(filter.trim());
4126 return entry => glob(entry.basename);
4127 }
4128
4129 if (Array.isArray(filter)) {
4130 const positive = [];
4131 const negative = [];
4132 for (const item of filter) {
4133 const trimmed = item.trim();
4134 if (trimmed.charAt(0) === BANG) {
4135 negative.push(picomatch$1(trimmed.slice(1)));
4136 } else {
4137 positive.push(picomatch$1(trimmed));
4138 }
4139 }
4140
4141 if (negative.length > 0) {
4142 if (positive.length > 0) {
4143 return entry =>
4144 positive.some(f => f(entry.basename)) && !negative.some(f => f(entry.basename));
4145 }
4146 return entry => !negative.some(f => f(entry.basename));
4147 }
4148 return entry => positive.some(f => f(entry.basename));
4149 }
4150};
4151
4152class ReaddirpStream extends Readable {
4153 static get defaultOptions() {
4154 return {
4155 root: '.',
4156 /* eslint-disable no-unused-vars */
4157 fileFilter: (path) => true,
4158 directoryFilter: (path) => true,
4159 /* eslint-enable no-unused-vars */
4160 type: FILE_TYPE,
4161 lstat: false,
4162 depth: 2147483648,
4163 alwaysStat: false
4164 };
4165 }
4166
4167 constructor(options = {}) {
4168 super({
4169 objectMode: true,
4170 autoDestroy: true,
4171 highWaterMark: options.highWaterMark || 4096
4172 });
4173 const opts = { ...ReaddirpStream.defaultOptions, ...options };
4174 const { root, type } = opts;
4175
4176 this._fileFilter = normalizeFilter(opts.fileFilter);
4177 this._directoryFilter = normalizeFilter(opts.directoryFilter);
4178
4179 const statMethod = opts.lstat ? lstat : stat;
4180 // Use bigint stats if it's windows and stat() supports options (node 10+).
4181 if (process.platform === 'win32' && stat.length === 3) {
4182 this._stat = path => statMethod(path, { bigint: true });
4183 } else {
4184 this._stat = statMethod;
4185 }
4186
4187 this._maxDepth = opts.depth;
4188 this._wantsDir = [DIR_TYPE, FILE_DIR_TYPE, EVERYTHING_TYPE].includes(type);
4189 this._wantsFile = [FILE_TYPE, FILE_DIR_TYPE, EVERYTHING_TYPE].includes(type);
4190 this._wantsEverything = type === EVERYTHING_TYPE;
4191 this._root = sysPath.resolve(root);
4192 this._isDirent = ('Dirent' in fs) && !opts.alwaysStat;
4193 this._statsProp = this._isDirent ? 'dirent' : 'stats';
4194 this._rdOptions = { encoding: 'utf8', withFileTypes: this._isDirent };
4195
4196 // Launch stream with one parent, the root dir.
4197 this.parents = [this._exploreDir(root, 1)];
4198 this.reading = false;
4199 this.parent = undefined;
4200 }
4201
4202 async _read(batch) {
4203 if (this.reading) return;
4204 this.reading = true;
4205
4206 try {
4207 while (!this.destroyed && batch > 0) {
4208 const { path, depth, files = [] } = this.parent || {};
4209
4210 if (files.length > 0) {
4211 const slice = files.splice(0, batch).map(dirent => this._formatEntry(dirent, path));
4212 for (const entry of await Promise.all(slice)) {
4213 if (this.destroyed) return;
4214
4215 const entryType = await this._getEntryType(entry);
4216 if (entryType === 'directory' && this._directoryFilter(entry)) {
4217 if (depth <= this._maxDepth) {
4218 this.parents.push(this._exploreDir(entry.fullPath, depth + 1));
4219 }
4220
4221 if (this._wantsDir) {
4222 this.push(entry);
4223 batch--;
4224 }
4225 } else if ((entryType === 'file' || this._includeAsFile(entry)) && this._fileFilter(entry)) {
4226 if (this._wantsFile) {
4227 this.push(entry);
4228 batch--;
4229 }
4230 }
4231 }
4232 } else {
4233 const parent = this.parents.pop();
4234 if (!parent) {
4235 this.push(null);
4236 break;
4237 }
4238 this.parent = await parent;
4239 if (this.destroyed) return;
4240 }
4241 }
4242 } catch (error) {
4243 this.destroy(error);
4244 } finally {
4245 this.reading = false;
4246 }
4247 }
4248
4249 async _exploreDir(path, depth) {
4250 let files;
4251 try {
4252 files = await readdir(path, this._rdOptions);
4253 } catch (error) {
4254 this._onError(error);
4255 }
4256 return {files, depth, path};
4257 }
4258
4259 async _formatEntry(dirent, path) {
4260 let entry;
4261 try {
4262 const basename = this._isDirent ? dirent.name : dirent;
4263 const fullPath = sysPath.resolve(sysPath.join(path, basename));
4264 entry = {path: sysPath.relative(this._root, fullPath), fullPath, basename};
4265 entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
4266 } catch (err) {
4267 this._onError(err);
4268 }
4269 return entry;
4270 }
4271
4272 _onError(err) {
4273 if (isNormalFlowError(err) && !this.destroyed) {
4274 this.emit('warn', err);
4275 } else {
4276 this.destroy(err);
4277 }
4278 }
4279
4280 async _getEntryType(entry) {
4281 // entry may be undefined, because a warning or an error were emitted
4282 // and the statsProp is undefined
4283 const stats = entry && entry[this._statsProp];
4284 if (!stats) {
4285 return;
4286 }
4287 if (stats.isFile()) {
4288 return 'file';
4289 }
4290 if (stats.isDirectory()) {
4291 return 'directory';
4292 }
4293 if (stats && stats.isSymbolicLink()) {
4294 try {
4295 const entryRealPath = await realpath(entry.fullPath);
4296 const entryRealPathStats = await lstat(entryRealPath);
4297 if (entryRealPathStats.isFile()) {
4298 return 'file';
4299 }
4300 if (entryRealPathStats.isDirectory()) {
4301 return 'directory';
4302 }
4303 } catch (error) {
4304 this._onError(error);
4305 }
4306 }
4307 }
4308
4309 _includeAsFile(entry) {
4310 const stats = entry && entry[this._statsProp];
4311
4312 return stats && this._wantsEverything && !stats.isDirectory();
4313 }
4314}
4315
4316/**
4317 * @typedef {Object} ReaddirpArguments
4318 * @property {Function=} fileFilter
4319 * @property {Function=} directoryFilter
4320 * @property {String=} type
4321 * @property {Number=} depth
4322 * @property {String=} root
4323 * @property {Boolean=} lstat
4324 * @property {Boolean=} bigint
4325 */
4326
4327/**
4328 * Main function which ends up calling readdirRec and reads all files and directories in given root recursively.
4329 * @param {String} root Root directory
4330 * @param {ReaddirpArguments=} options Options to specify root (start directory), filters and recursion depth
4331 */
4332const readdirp = (root, options = {}) => {
4333 let type = options.entryType || options.type;
4334 if (type === 'both') type = FILE_DIR_TYPE; // backwards-compatibility
4335 if (type) options.type = type;
4336 if (!root) {
4337 throw new Error('readdirp: root argument is required. Usage: readdirp(root, options)');
4338 } else if (typeof root !== 'string') {
4339 throw new TypeError('readdirp: root argument must be a string. Usage: readdirp(root, options)');
4340 } else if (type && !ALL_TYPES.includes(type)) {
4341 throw new Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(', ')}`);
4342 }
4343
4344 options.root = root;
4345 return new ReaddirpStream(options);
4346};
4347
4348const readdirpPromise = (root, options = {}) => {
4349 return new Promise((resolve, reject) => {
4350 const files = [];
4351 readdirp(root, options)
4352 .on('data', entry => files.push(entry))
4353 .on('end', () => resolve(files))
4354 .on('error', error => reject(error));
4355 });
4356};
4357
4358readdirp.promise = readdirpPromise;
4359readdirp.ReaddirpStream = ReaddirpStream;
4360readdirp.default = readdirp;
4361
4362var readdirp_1 = readdirp;
4363
4364/*!
4365 * normalize-path <https://github.com/jonschlinkert/normalize-path>
4366 *
4367 * Copyright (c) 2014-2018, Jon Schlinkert.
4368 * Released under the MIT License.
4369 */
4370
4371var normalizePath = function(path, stripTrailing) {
4372 if (typeof path !== 'string') {
4373 throw new TypeError('expected path to be a string');
4374 }
4375
4376 if (path === '\\' || path === '/') return '/';
4377
4378 var len = path.length;
4379 if (len <= 1) return path;
4380
4381 // ensure that win32 namespaces has two leading slashes, so that the path is
4382 // handled properly by the win32 version of path.parse() after being normalized
4383 // https://msdn.microsoft.com/library/windows/desktop/aa365247(v=vs.85).aspx#namespaces
4384 var prefix = '';
4385 if (len > 4 && path[3] === '\\') {
4386 var ch = path[2];
4387 if ((ch === '?' || ch === '.') && path.slice(0, 2) === '\\\\') {
4388 path = path.slice(2);
4389 prefix = '//';
4390 }
4391 }
4392
4393 var segs = path.split(/[/\\]+/);
4394 if (stripTrailing !== false && segs[segs.length - 1] === '') {
4395 segs.pop();
4396 }
4397 return prefix + segs.join('/');
4398};
4399
4400var anymatch_1 = createCommonjsModule(function (module, exports) {
4401
4402Object.defineProperty(exports, "__esModule", { value: true });
4403
4404
4405
4406
4407/**
4408 * @typedef {(testString: string) => boolean} AnymatchFn
4409 * @typedef {string|RegExp|AnymatchFn} AnymatchPattern
4410 * @typedef {AnymatchPattern|AnymatchPattern[]} AnymatchMatcher
4411 */
4412const BANG = '!';
4413const DEFAULT_OPTIONS = {returnIndex: false};
4414const arrify = (item) => Array.isArray(item) ? item : [item];
4415
4416/**
4417 * @param {AnymatchPattern} matcher
4418 * @param {object} options
4419 * @returns {AnymatchFn}
4420 */
4421const createPattern = (matcher, options) => {
4422 if (typeof matcher === 'function') {
4423 return matcher;
4424 }
4425 if (typeof matcher === 'string') {
4426 const glob = picomatch$1(matcher, options);
4427 return (string) => matcher === string || glob(string);
4428 }
4429 if (matcher instanceof RegExp) {
4430 return (string) => matcher.test(string);
4431 }
4432 return (string) => false;
4433};
4434
4435/**
4436 * @param {Array<Function>} patterns
4437 * @param {Array<Function>} negPatterns
4438 * @param {String|Array} args
4439 * @param {Boolean} returnIndex
4440 * @returns {boolean|number}
4441 */
4442const matchPatterns = (patterns, negPatterns, args, returnIndex) => {
4443 const isList = Array.isArray(args);
4444 const _path = isList ? args[0] : args;
4445 if (!isList && typeof _path !== 'string') {
4446 throw new TypeError('anymatch: second argument must be a string: got ' +
4447 Object.prototype.toString.call(_path))
4448 }
4449 const path = normalizePath(_path);
4450
4451 for (let index = 0; index < negPatterns.length; index++) {
4452 const nglob = negPatterns[index];
4453 if (nglob(path)) {
4454 return returnIndex ? -1 : false;
4455 }
4456 }
4457
4458 const applied = isList && [path].concat(args.slice(1));
4459 for (let index = 0; index < patterns.length; index++) {
4460 const pattern = patterns[index];
4461 if (isList ? pattern(...applied) : pattern(path)) {
4462 return returnIndex ? index : true;
4463 }
4464 }
4465
4466 return returnIndex ? -1 : false;
4467};
4468
4469/**
4470 * @param {AnymatchMatcher} matchers
4471 * @param {Array|string} testString
4472 * @param {object} options
4473 * @returns {boolean|number|Function}
4474 */
4475const anymatch = (matchers, testString, options = DEFAULT_OPTIONS) => {
4476 if (matchers == null) {
4477 throw new TypeError('anymatch: specify first argument');
4478 }
4479 const opts = typeof options === 'boolean' ? {returnIndex: options} : options;
4480 const returnIndex = opts.returnIndex || false;
4481
4482 // Early cache for matchers.
4483 const mtchers = arrify(matchers);
4484 const negatedGlobs = mtchers
4485 .filter(item => typeof item === 'string' && item.charAt(0) === BANG)
4486 .map(item => item.slice(1))
4487 .map(item => picomatch$1(item, opts));
4488 const patterns = mtchers.map(matcher => createPattern(matcher, opts));
4489
4490 if (testString == null) {
4491 return (testString, ri = false) => {
4492 const returnIndex = typeof ri === 'boolean' ? ri : false;
4493 return matchPatterns(patterns, negatedGlobs, testString, returnIndex);
4494 }
4495 }
4496
4497 return matchPatterns(patterns, negatedGlobs, testString, returnIndex);
4498};
4499
4500anymatch.default = anymatch;
4501module.exports = anymatch;
4502});
4503
4504/*!
4505 * is-extglob <https://github.com/jonschlinkert/is-extglob>
4506 *
4507 * Copyright (c) 2014-2016, Jon Schlinkert.
4508 * Licensed under the MIT License.
4509 */
4510
4511var isExtglob = function isExtglob(str) {
4512 if (typeof str !== 'string' || str === '') {
4513 return false;
4514 }
4515
4516 var match;
4517 while ((match = /(\\).|([@?!+*]\(.*\))/g.exec(str))) {
4518 if (match[2]) return true;
4519 str = str.slice(match.index + match[0].length);
4520 }
4521
4522 return false;
4523};
4524
4525/*!
4526 * is-glob <https://github.com/jonschlinkert/is-glob>
4527 *
4528 * Copyright (c) 2014-2017, Jon Schlinkert.
4529 * Released under the MIT License.
4530 */
4531
4532
4533var chars = { '{': '}', '(': ')', '[': ']'};
4534var strictRegex = /\\(.)|(^!|\*|[\].+)]\?|\[[^\\\]]+\]|\{[^\\}]+\}|\(\?[:!=][^\\)]+\)|\([^|]+\|[^\\)]+\))/;
4535var relaxedRegex = /\\(.)|(^!|[*?{}()[\]]|\(\?)/;
4536
4537var isGlob = function isGlob(str, options) {
4538 if (typeof str !== 'string' || str === '') {
4539 return false;
4540 }
4541
4542 if (isExtglob(str)) {
4543 return true;
4544 }
4545
4546 var regex = strictRegex;
4547 var match;
4548
4549 // optionally relax regex
4550 if (options && options.strict === false) {
4551 regex = relaxedRegex;
4552 }
4553
4554 while ((match = regex.exec(str))) {
4555 if (match[2]) return true;
4556 var idx = match.index + match[0].length;
4557
4558 // if an open bracket/brace/paren is escaped,
4559 // set the index to the next closing character
4560 var open = match[1];
4561 var close = open ? chars[open] : null;
4562 if (open && close) {
4563 var n = str.indexOf(close, idx);
4564 if (n !== -1) {
4565 idx = n + 1;
4566 }
4567 }
4568
4569 str = str.slice(idx);
4570 }
4571 return false;
4572};
4573
4574var pathPosixDirname = sysPath.posix.dirname;
4575var isWin32 = require$$1$1.platform() === 'win32';
4576
4577var slash = '/';
4578var backslash = /\\/g;
4579var enclosure = /[\{\[].*[\/]*.*[\}\]]$/;
4580var globby = /(^|[^\\])([\{\[]|\([^\)]+$)/;
4581var escaped = /\\([\!\*\?\|\[\]\(\)\{\}])/g;
4582
4583/**
4584 * @param {string} str
4585 * @param {Object} opts
4586 * @param {boolean} [opts.flipBackslashes=true]
4587 */
4588var globParent = function globParent(str, opts) {
4589 var options = Object.assign({ flipBackslashes: true }, opts);
4590
4591 // flip windows path separators
4592 if (options.flipBackslashes && isWin32 && str.indexOf(slash) < 0) {
4593 str = str.replace(backslash, slash);
4594 }
4595
4596 // special case for strings ending in enclosure containing path separator
4597 if (enclosure.test(str)) {
4598 str += slash;
4599 }
4600
4601 // preserves full path in case of trailing path separator
4602 str += 'a';
4603
4604 // remove path parts that are globby
4605 do {
4606 str = pathPosixDirname(str);
4607 } while (isGlob(str) || globby.test(str));
4608
4609 // remove escape chars and return result
4610 return str.replace(escaped, '$1');
4611};
4612
4613var require$$0 = [
4614 "3dm",
4615 "3ds",
4616 "3g2",
4617 "3gp",
4618 "7z",
4619 "a",
4620 "aac",
4621 "adp",
4622 "ai",
4623 "aif",
4624 "aiff",
4625 "alz",
4626 "ape",
4627 "apk",
4628 "appimage",
4629 "ar",
4630 "arj",
4631 "asf",
4632 "au",
4633 "avi",
4634 "bak",
4635 "baml",
4636 "bh",
4637 "bin",
4638 "bk",
4639 "bmp",
4640 "btif",
4641 "bz2",
4642 "bzip2",
4643 "cab",
4644 "caf",
4645 "cgm",
4646 "class",
4647 "cmx",
4648 "cpio",
4649 "cr2",
4650 "cur",
4651 "dat",
4652 "dcm",
4653 "deb",
4654 "dex",
4655 "djvu",
4656 "dll",
4657 "dmg",
4658 "dng",
4659 "doc",
4660 "docm",
4661 "docx",
4662 "dot",
4663 "dotm",
4664 "dra",
4665 "DS_Store",
4666 "dsk",
4667 "dts",
4668 "dtshd",
4669 "dvb",
4670 "dwg",
4671 "dxf",
4672 "ecelp4800",
4673 "ecelp7470",
4674 "ecelp9600",
4675 "egg",
4676 "eol",
4677 "eot",
4678 "epub",
4679 "exe",
4680 "f4v",
4681 "fbs",
4682 "fh",
4683 "fla",
4684 "flac",
4685 "flatpak",
4686 "fli",
4687 "flv",
4688 "fpx",
4689 "fst",
4690 "fvt",
4691 "g3",
4692 "gh",
4693 "gif",
4694 "graffle",
4695 "gz",
4696 "gzip",
4697 "h261",
4698 "h263",
4699 "h264",
4700 "icns",
4701 "ico",
4702 "ief",
4703 "img",
4704 "ipa",
4705 "iso",
4706 "jar",
4707 "jpeg",
4708 "jpg",
4709 "jpgv",
4710 "jpm",
4711 "jxr",
4712 "key",
4713 "ktx",
4714 "lha",
4715 "lib",
4716 "lvp",
4717 "lz",
4718 "lzh",
4719 "lzma",
4720 "lzo",
4721 "m3u",
4722 "m4a",
4723 "m4v",
4724 "mar",
4725 "mdi",
4726 "mht",
4727 "mid",
4728 "midi",
4729 "mj2",
4730 "mka",
4731 "mkv",
4732 "mmr",
4733 "mng",
4734 "mobi",
4735 "mov",
4736 "movie",
4737 "mp3",
4738 "mp4",
4739 "mp4a",
4740 "mpeg",
4741 "mpg",
4742 "mpga",
4743 "mxu",
4744 "nef",
4745 "npx",
4746 "numbers",
4747 "nupkg",
4748 "o",
4749 "oga",
4750 "ogg",
4751 "ogv",
4752 "otf",
4753 "pages",
4754 "pbm",
4755 "pcx",
4756 "pdb",
4757 "pdf",
4758 "pea",
4759 "pgm",
4760 "pic",
4761 "png",
4762 "pnm",
4763 "pot",
4764 "potm",
4765 "potx",
4766 "ppa",
4767 "ppam",
4768 "ppm",
4769 "pps",
4770 "ppsm",
4771 "ppsx",
4772 "ppt",
4773 "pptm",
4774 "pptx",
4775 "psd",
4776 "pya",
4777 "pyc",
4778 "pyo",
4779 "pyv",
4780 "qt",
4781 "rar",
4782 "ras",
4783 "raw",
4784 "resources",
4785 "rgb",
4786 "rip",
4787 "rlc",
4788 "rmf",
4789 "rmvb",
4790 "rpm",
4791 "rtf",
4792 "rz",
4793 "s3m",
4794 "s7z",
4795 "scpt",
4796 "sgi",
4797 "shar",
4798 "snap",
4799 "sil",
4800 "sketch",
4801 "slk",
4802 "smv",
4803 "snk",
4804 "so",
4805 "stl",
4806 "suo",
4807 "sub",
4808 "swf",
4809 "tar",
4810 "tbz",
4811 "tbz2",
4812 "tga",
4813 "tgz",
4814 "thmx",
4815 "tif",
4816 "tiff",
4817 "tlz",
4818 "ttc",
4819 "ttf",
4820 "txz",
4821 "udf",
4822 "uvh",
4823 "uvi",
4824 "uvm",
4825 "uvp",
4826 "uvs",
4827 "uvu",
4828 "viv",
4829 "vob",
4830 "war",
4831 "wav",
4832 "wax",
4833 "wbmp",
4834 "wdp",
4835 "weba",
4836 "webm",
4837 "webp",
4838 "whl",
4839 "wim",
4840 "wm",
4841 "wma",
4842 "wmv",
4843 "wmx",
4844 "woff",
4845 "woff2",
4846 "wrm",
4847 "wvx",
4848 "xbm",
4849 "xif",
4850 "xla",
4851 "xlam",
4852 "xls",
4853 "xlsb",
4854 "xlsm",
4855 "xlsx",
4856 "xlt",
4857 "xltm",
4858 "xltx",
4859 "xm",
4860 "xmind",
4861 "xpi",
4862 "xpm",
4863 "xwd",
4864 "xz",
4865 "z",
4866 "zip",
4867 "zipx"
4868];
4869
4870var binaryExtensions = require$$0;
4871
4872const extensions = new Set(binaryExtensions);
4873
4874var isBinaryPath = filePath => extensions.has(sysPath.extname(filePath).slice(1).toLowerCase());
4875
4876var constants$2 = createCommonjsModule(function (module, exports) {
4877
4878const {sep} = sysPath;
4879const {platform} = process;
4880
4881exports.EV_ALL = 'all';
4882exports.EV_READY = 'ready';
4883exports.EV_ADD = 'add';
4884exports.EV_CHANGE = 'change';
4885exports.EV_ADD_DIR = 'addDir';
4886exports.EV_UNLINK = 'unlink';
4887exports.EV_UNLINK_DIR = 'unlinkDir';
4888exports.EV_RAW = 'raw';
4889exports.EV_ERROR = 'error';
4890
4891exports.STR_DATA = 'data';
4892exports.STR_END = 'end';
4893exports.STR_CLOSE = 'close';
4894
4895exports.FSEVENT_CREATED = 'created';
4896exports.FSEVENT_MODIFIED = 'modified';
4897exports.FSEVENT_DELETED = 'deleted';
4898exports.FSEVENT_MOVED = 'moved';
4899exports.FSEVENT_CLONED = 'cloned';
4900exports.FSEVENT_UNKNOWN = 'unknown';
4901exports.FSEVENT_TYPE_FILE = 'file';
4902exports.FSEVENT_TYPE_DIRECTORY = 'directory';
4903exports.FSEVENT_TYPE_SYMLINK = 'symlink';
4904
4905exports.KEY_LISTENERS = 'listeners';
4906exports.KEY_ERR = 'errHandlers';
4907exports.KEY_RAW = 'rawEmitters';
4908exports.HANDLER_KEYS = [exports.KEY_LISTENERS, exports.KEY_ERR, exports.KEY_RAW];
4909
4910exports.DOT_SLASH = `.${sep}`;
4911
4912exports.BACK_SLASH_RE = /\\/g;
4913exports.DOUBLE_SLASH_RE = /\/\//;
4914exports.SLASH_OR_BACK_SLASH_RE = /[/\\]/;
4915exports.DOT_RE = /\..*\.(sw[px])$|~$|\.subl.*\.tmp/;
4916exports.REPLACER_RE = /^\.[/\\]/;
4917
4918exports.SLASH = '/';
4919exports.SLASH_SLASH = '//';
4920exports.BRACE_START = '{';
4921exports.BANG = '!';
4922exports.ONE_DOT = '.';
4923exports.TWO_DOTS = '..';
4924exports.STAR = '*';
4925exports.GLOBSTAR = '**';
4926exports.ROOT_GLOBSTAR = '/**/*';
4927exports.SLASH_GLOBSTAR = '/**';
4928exports.DIR_SUFFIX = 'Dir';
4929exports.ANYMATCH_OPTS = {dot: true};
4930exports.STRING_TYPE = 'string';
4931exports.FUNCTION_TYPE = 'function';
4932exports.EMPTY_STR = '';
4933exports.EMPTY_FN = () => {};
4934exports.IDENTITY_FN = val => val;
4935
4936exports.isWindows = platform === 'win32';
4937exports.isMacos = platform === 'darwin';
4938exports.isLinux = platform === 'linux';
4939});
4940
4941const { promisify: promisify$1 } = util;
4942
4943const {
4944 isWindows,
4945 isLinux,
4946 EMPTY_FN,
4947 EMPTY_STR,
4948 KEY_LISTENERS,
4949 KEY_ERR,
4950 KEY_RAW,
4951 HANDLER_KEYS,
4952 EV_CHANGE,
4953 EV_ADD,
4954 EV_ADD_DIR,
4955 EV_ERROR,
4956 STR_DATA,
4957 STR_END,
4958 BRACE_START,
4959 STAR: STAR$1
4960} = constants$2;
4961
4962const THROTTLE_MODE_WATCH = 'watch';
4963
4964const open = promisify$1(fs.open);
4965const stat$1 = promisify$1(fs.stat);
4966const lstat$1 = promisify$1(fs.lstat);
4967const close = promisify$1(fs.close);
4968const fsrealpath = promisify$1(fs.realpath);
4969
4970const statMethods = { lstat: lstat$1, stat: stat$1 };
4971
4972// TODO: emit errors properly. Example: EMFILE on Macos.
4973const foreach = (val, fn) => {
4974 if (val instanceof Set) {
4975 val.forEach(fn);
4976 } else {
4977 fn(val);
4978 }
4979};
4980
4981const addAndConvert = (main, prop, item) => {
4982 let container = main[prop];
4983 if (!(container instanceof Set)) {
4984 main[prop] = container = new Set([container]);
4985 }
4986 container.add(item);
4987};
4988
4989const clearItem = cont => key => {
4990 const set = cont[key];
4991 if (set instanceof Set) {
4992 set.clear();
4993 } else {
4994 delete cont[key];
4995 }
4996};
4997
4998const delFromSet = (main, prop, item) => {
4999 const container = main[prop];
5000 if (container instanceof Set) {
5001 container.delete(item);
5002 } else if (container === item) {
5003 delete main[prop];
5004 }
5005};
5006
5007const isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
5008
5009/**
5010 * @typedef {String} Path
5011 */
5012
5013// fs_watch helpers
5014
5015// object to hold per-process fs_watch instances
5016// (may be shared across chokidar FSWatcher instances)
5017
5018/**
5019 * @typedef {Object} FsWatchContainer
5020 * @property {Set} listeners
5021 * @property {Set} errHandlers
5022 * @property {Set} rawEmitters
5023 * @property {fs.FSWatcher=} watcher
5024 * @property {Boolean=} watcherUnusable
5025 */
5026
5027/**
5028 * @type {Map<String,FsWatchContainer>}
5029 */
5030const FsWatchInstances = new Map();
5031
5032/**
5033 * Instantiates the fs_watch interface
5034 * @param {String} path to be watched
5035 * @param {Object} options to be passed to fs_watch
5036 * @param {Function} listener main event handler
5037 * @param {Function} errHandler emits info about errors
5038 * @param {Function} emitRaw emits raw event data
5039 * @returns {fs.FSWatcher} new fsevents instance
5040 */
5041function createFsWatchInstance(path, options, listener, errHandler, emitRaw) {
5042 const handleEvent = (rawEvent, evPath) => {
5043 listener(path);
5044 emitRaw(rawEvent, evPath, {watchedPath: path});
5045
5046 // emit based on events occurring for files from a directory's watcher in
5047 // case the file's watcher misses it (and rely on throttling to de-dupe)
5048 if (evPath && path !== evPath) {
5049 fsWatchBroadcast(
5050 sysPath.resolve(path, evPath), KEY_LISTENERS, sysPath.join(path, evPath)
5051 );
5052 }
5053 };
5054 try {
5055 return fs.watch(path, options, handleEvent);
5056 } catch (error) {
5057 errHandler(error);
5058 }
5059}
5060
5061/**
5062 * Helper for passing fs_watch event data to a collection of listeners
5063 * @param {Path} fullPath absolute path bound to fs_watch instance
5064 * @param {String} type listener type
5065 * @param {*=} val1 arguments to be passed to listeners
5066 * @param {*=} val2
5067 * @param {*=} val3
5068 */
5069const fsWatchBroadcast = (fullPath, type, val1, val2, val3) => {
5070 const cont = FsWatchInstances.get(fullPath);
5071 if (!cont) return;
5072 foreach(cont[type], (listener) => {
5073 listener(val1, val2, val3);
5074 });
5075};
5076
5077/**
5078 * Instantiates the fs_watch interface or binds listeners
5079 * to an existing one covering the same file system entry
5080 * @param {String} path
5081 * @param {String} fullPath absolute path
5082 * @param {Object} options to be passed to fs_watch
5083 * @param {Object} handlers container for event listener functions
5084 */
5085const setFsWatchListener = (path, fullPath, options, handlers) => {
5086 const {listener, errHandler, rawEmitter} = handlers;
5087 let cont = FsWatchInstances.get(fullPath);
5088
5089 /** @type {fs.FSWatcher=} */
5090 let watcher;
5091 if (!options.persistent) {
5092 watcher = createFsWatchInstance(
5093 path, options, listener, errHandler, rawEmitter
5094 );
5095 return watcher.close.bind(watcher);
5096 }
5097 if (cont) {
5098 addAndConvert(cont, KEY_LISTENERS, listener);
5099 addAndConvert(cont, KEY_ERR, errHandler);
5100 addAndConvert(cont, KEY_RAW, rawEmitter);
5101 } else {
5102 watcher = createFsWatchInstance(
5103 path,
5104 options,
5105 fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
5106 errHandler, // no need to use broadcast here
5107 fsWatchBroadcast.bind(null, fullPath, KEY_RAW)
5108 );
5109 if (!watcher) return;
5110 watcher.on(EV_ERROR, async (error) => {
5111 const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR);
5112 cont.watcherUnusable = true; // documented since Node 10.4.1
5113 // Workaround for https://github.com/joyent/node/issues/4337
5114 if (isWindows && error.code === 'EPERM') {
5115 try {
5116 const fd = await open(path, 'r');
5117 await close(fd);
5118 broadcastErr(error);
5119 } catch (err) {}
5120 } else {
5121 broadcastErr(error);
5122 }
5123 });
5124 cont = {
5125 listeners: listener,
5126 errHandlers: errHandler,
5127 rawEmitters: rawEmitter,
5128 watcher
5129 };
5130 FsWatchInstances.set(fullPath, cont);
5131 }
5132 // const index = cont.listeners.indexOf(listener);
5133
5134 // removes this instance's listeners and closes the underlying fs_watch
5135 // instance if there are no more listeners left
5136 return () => {
5137 delFromSet(cont, KEY_LISTENERS, listener);
5138 delFromSet(cont, KEY_ERR, errHandler);
5139 delFromSet(cont, KEY_RAW, rawEmitter);
5140 if (isEmptySet(cont.listeners)) {
5141 // Check to protect against issue gh-730.
5142 // if (cont.watcherUnusable) {
5143 cont.watcher.close();
5144 // }
5145 FsWatchInstances.delete(fullPath);
5146 HANDLER_KEYS.forEach(clearItem(cont));
5147 cont.watcher = undefined;
5148 Object.freeze(cont);
5149 }
5150 };
5151};
5152
5153// fs_watchFile helpers
5154
5155// object to hold per-process fs_watchFile instances
5156// (may be shared across chokidar FSWatcher instances)
5157const FsWatchFileInstances = new Map();
5158
5159/**
5160 * Instantiates the fs_watchFile interface or binds listeners
5161 * to an existing one covering the same file system entry
5162 * @param {String} path to be watched
5163 * @param {String} fullPath absolute path
5164 * @param {Object} options options to be passed to fs_watchFile
5165 * @param {Object} handlers container for event listener functions
5166 * @returns {Function} closer
5167 */
5168const setFsWatchFileListener = (path, fullPath, options, handlers) => {
5169 const {listener, rawEmitter} = handlers;
5170 let cont = FsWatchFileInstances.get(fullPath);
5171
5172 const copts = cont && cont.options;
5173 if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {
5174 fs.unwatchFile(fullPath);
5175 cont = undefined;
5176 }
5177
5178 /* eslint-enable no-unused-vars, prefer-destructuring */
5179
5180 if (cont) {
5181 addAndConvert(cont, KEY_LISTENERS, listener);
5182 addAndConvert(cont, KEY_RAW, rawEmitter);
5183 } else {
5184 // TODO
5185 // listeners.add(listener);
5186 // rawEmitters.add(rawEmitter);
5187 cont = {
5188 listeners: listener,
5189 rawEmitters: rawEmitter,
5190 options,
5191 watcher: fs.watchFile(fullPath, options, (curr, prev) => {
5192 foreach(cont.rawEmitters, (rawEmitter) => {
5193 rawEmitter(EV_CHANGE, fullPath, {curr, prev});
5194 });
5195 const currmtime = curr.mtimeMs;
5196 if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
5197 foreach(cont.listeners, (listener) => listener(path, curr));
5198 }
5199 })
5200 };
5201 FsWatchFileInstances.set(fullPath, cont);
5202 }
5203 // const index = cont.listeners.indexOf(listener);
5204
5205 // Removes this instance's listeners and closes the underlying fs_watchFile
5206 // instance if there are no more listeners left.
5207 return () => {
5208 delFromSet(cont, KEY_LISTENERS, listener);
5209 delFromSet(cont, KEY_RAW, rawEmitter);
5210 if (isEmptySet(cont.listeners)) {
5211 FsWatchFileInstances.delete(fullPath);
5212 fs.unwatchFile(fullPath);
5213 cont.options = cont.watcher = undefined;
5214 Object.freeze(cont);
5215 }
5216 };
5217};
5218
5219/**
5220 * @mixin
5221 */
5222class NodeFsHandler {
5223
5224/**
5225 * @param {import("../index").FSWatcher} fsW
5226 */
5227constructor(fsW) {
5228 this.fsw = fsW;
5229 this._boundHandleError = (error) => fsW._handleError(error);
5230}
5231
5232/**
5233 * Watch file for changes with fs_watchFile or fs_watch.
5234 * @param {String} path to file or dir
5235 * @param {Function} listener on fs change
5236 * @returns {Function} closer for the watcher instance
5237 */
5238_watchWithNodeFs(path, listener) {
5239 const opts = this.fsw.options;
5240 const directory = sysPath.dirname(path);
5241 const basename = sysPath.basename(path);
5242 const parent = this.fsw._getWatchedDir(directory);
5243 parent.add(basename);
5244 const absolutePath = sysPath.resolve(path);
5245 const options = {persistent: opts.persistent};
5246 if (!listener) listener = EMPTY_FN;
5247
5248 let closer;
5249 if (opts.usePolling) {
5250 options.interval = opts.enableBinaryInterval && isBinaryPath(basename) ?
5251 opts.binaryInterval : opts.interval;
5252 closer = setFsWatchFileListener(path, absolutePath, options, {
5253 listener,
5254 rawEmitter: this.fsw._emitRaw
5255 });
5256 } else {
5257 closer = setFsWatchListener(path, absolutePath, options, {
5258 listener,
5259 errHandler: this._boundHandleError,
5260 rawEmitter: this.fsw._emitRaw
5261 });
5262 }
5263 return closer;
5264}
5265
5266/**
5267 * Watch a file and emit add event if warranted.
5268 * @param {Path} file Path
5269 * @param {fs.Stats} stats result of fs_stat
5270 * @param {Boolean} initialAdd was the file added at watch instantiation?
5271 * @returns {Function} closer for the watcher instance
5272 */
5273_handleFile(file, stats, initialAdd) {
5274 if (this.fsw.closed) {
5275 return;
5276 }
5277 const dirname = sysPath.dirname(file);
5278 const basename = sysPath.basename(file);
5279 const parent = this.fsw._getWatchedDir(dirname);
5280 // stats is always present
5281 let prevStats = stats;
5282
5283 // if the file is already being watched, do nothing
5284 if (parent.has(basename)) return;
5285
5286 const listener = async (path, newStats) => {
5287 if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5)) return;
5288 if (!newStats || newStats.mtimeMs === 0) {
5289 try {
5290 const newStats = await stat$1(file);
5291 if (this.fsw.closed) return;
5292 // Check that change event was not fired because of changed only accessTime.
5293 const at = newStats.atimeMs;
5294 const mt = newStats.mtimeMs;
5295 if (!at || at <= mt || mt !== prevStats.mtimeMs) {
5296 this.fsw._emit(EV_CHANGE, file, newStats);
5297 }
5298 if (isLinux && prevStats.ino !== newStats.ino) {
5299 this.fsw._closeFile(path);
5300 prevStats = newStats;
5301 this.fsw._addPathCloser(path, this._watchWithNodeFs(file, listener));
5302 } else {
5303 prevStats = newStats;
5304 }
5305 } catch (error) {
5306 // Fix issues where mtime is null but file is still present
5307 this.fsw._remove(dirname, basename);
5308 }
5309 // add is about to be emitted if file not already tracked in parent
5310 } else if (parent.has(basename)) {
5311 // Check that change event was not fired because of changed only accessTime.
5312 const at = newStats.atimeMs;
5313 const mt = newStats.mtimeMs;
5314 if (!at || at <= mt || mt !== prevStats.mtimeMs) {
5315 this.fsw._emit(EV_CHANGE, file, newStats);
5316 }
5317 prevStats = newStats;
5318 }
5319 };
5320 // kick off the watcher
5321 const closer = this._watchWithNodeFs(file, listener);
5322
5323 // emit an add event if we're supposed to
5324 if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file)) {
5325 if (!this.fsw._throttle(EV_ADD, file, 0)) return;
5326 this.fsw._emit(EV_ADD, file, stats);
5327 }
5328
5329 return closer;
5330}
5331
5332/**
5333 * Handle symlinks encountered while reading a dir.
5334 * @param {Object} entry returned by readdirp
5335 * @param {String} directory path of dir being read
5336 * @param {String} path of this item
5337 * @param {String} item basename of this item
5338 * @returns {Promise<Boolean>} true if no more processing is needed for this entry.
5339 */
5340async _handleSymlink(entry, directory, path, item) {
5341 if (this.fsw.closed) {
5342 return;
5343 }
5344 const full = entry.fullPath;
5345 const dir = this.fsw._getWatchedDir(directory);
5346
5347 if (!this.fsw.options.followSymlinks) {
5348 // watch symlink directly (don't follow) and detect changes
5349 this.fsw._incrReadyCount();
5350 const linkPath = await fsrealpath(path);
5351 if (this.fsw.closed) return;
5352 if (dir.has(item)) {
5353 if (this.fsw._symlinkPaths.get(full) !== linkPath) {
5354 this.fsw._symlinkPaths.set(full, linkPath);
5355 this.fsw._emit(EV_CHANGE, path, entry.stats);
5356 }
5357 } else {
5358 dir.add(item);
5359 this.fsw._symlinkPaths.set(full, linkPath);
5360 this.fsw._emit(EV_ADD, path, entry.stats);
5361 }
5362 this.fsw._emitReady();
5363 return true;
5364 }
5365
5366 // don't follow the same symlink more than once
5367 if (this.fsw._symlinkPaths.has(full)) {
5368 return true;
5369 }
5370
5371 this.fsw._symlinkPaths.set(full, true);
5372}
5373
5374_handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {
5375 // Normalize the directory name on Windows
5376 directory = sysPath.join(directory, EMPTY_STR);
5377
5378 if (!wh.hasGlob) {
5379 throttler = this.fsw._throttle('readdir', directory, 1000);
5380 if (!throttler) return;
5381 }
5382
5383 const previous = this.fsw._getWatchedDir(wh.path);
5384 const current = new Set();
5385
5386 let stream = this.fsw._readdirp(directory, {
5387 fileFilter: entry => wh.filterPath(entry),
5388 directoryFilter: entry => wh.filterDir(entry),
5389 depth: 0
5390 }).on(STR_DATA, async (entry) => {
5391 if (this.fsw.closed) {
5392 stream = undefined;
5393 return;
5394 }
5395 const item = entry.path;
5396 let path = sysPath.join(directory, item);
5397 current.add(item);
5398
5399 if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path, item)) {
5400 return;
5401 }
5402
5403 if (this.fsw.closed) {
5404 stream = undefined;
5405 return;
5406 }
5407 // Files that present in current directory snapshot
5408 // but absent in previous are added to watch list and
5409 // emit `add` event.
5410 if (item === target || !target && !previous.has(item)) {
5411 this.fsw._incrReadyCount();
5412
5413 // ensure relativeness of path is preserved in case of watcher reuse
5414 path = sysPath.join(dir, sysPath.relative(dir, path));
5415
5416 this._addToNodeFs(path, initialAdd, wh, depth + 1);
5417 }
5418 }).on(EV_ERROR, this._boundHandleError);
5419
5420 return new Promise(resolve =>
5421 stream.once(STR_END, () => {
5422 if (this.fsw.closed) {
5423 stream = undefined;
5424 return;
5425 }
5426 const wasThrottled = throttler ? throttler.clear() : false;
5427
5428 resolve();
5429
5430 // Files that absent in current directory snapshot
5431 // but present in previous emit `remove` event
5432 // and are removed from @watched[directory].
5433 previous.getChildren().filter((item) => {
5434 return item !== directory &&
5435 !current.has(item) &&
5436 // in case of intersecting globs;
5437 // a path may have been filtered out of this readdir, but
5438 // shouldn't be removed because it matches a different glob
5439 (!wh.hasGlob || wh.filterPath({
5440 fullPath: sysPath.resolve(directory, item)
5441 }));
5442 }).forEach((item) => {
5443 this.fsw._remove(directory, item);
5444 });
5445
5446 stream = undefined;
5447
5448 // one more time for any missed in case changes came in extremely quickly
5449 if (wasThrottled) this._handleRead(directory, false, wh, target, dir, depth, throttler);
5450 })
5451 );
5452}
5453
5454/**
5455 * Read directory to add / remove files from `@watched` list and re-read it on change.
5456 * @param {String} dir fs path
5457 * @param {fs.Stats} stats
5458 * @param {Boolean} initialAdd
5459 * @param {Number} depth relative to user-supplied path
5460 * @param {String} target child path targeted for watch
5461 * @param {Object} wh Common watch helpers for this path
5462 * @param {String} realpath
5463 * @returns {Promise<Function>} closer for the watcher instance.
5464 */
5465async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath) {
5466 const parentDir = this.fsw._getWatchedDir(sysPath.dirname(dir));
5467 const tracked = parentDir.has(sysPath.basename(dir));
5468 if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {
5469 if (!wh.hasGlob || wh.globFilter(dir)) this.fsw._emit(EV_ADD_DIR, dir, stats);
5470 }
5471
5472 // ensure dir is tracked (harmless if redundant)
5473 parentDir.add(sysPath.basename(dir));
5474 this.fsw._getWatchedDir(dir);
5475 let throttler;
5476 let closer;
5477
5478 const oDepth = this.fsw.options.depth;
5479 if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath)) {
5480 if (!target) {
5481 await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler);
5482 if (this.fsw.closed) return;
5483 }
5484
5485 closer = this._watchWithNodeFs(dir, (dirPath, stats) => {
5486 // if current directory is removed, do nothing
5487 if (stats && stats.mtimeMs === 0) return;
5488
5489 this._handleRead(dirPath, false, wh, target, dir, depth, throttler);
5490 });
5491 }
5492 return closer;
5493}
5494
5495/**
5496 * Handle added file, directory, or glob pattern.
5497 * Delegates call to _handleFile / _handleDir after checks.
5498 * @param {String} path to file or ir
5499 * @param {Boolean} initialAdd was the file added at watch instantiation?
5500 * @param {Object} priorWh depth relative to user-supplied path
5501 * @param {Number} depth Child path actually targeted for watch
5502 * @param {String=} target Child path actually targeted for watch
5503 * @returns {Promise}
5504 */
5505async _addToNodeFs(path, initialAdd, priorWh, depth, target) {
5506 const ready = this.fsw._emitReady;
5507 if (this.fsw._isIgnored(path) || this.fsw.closed) {
5508 ready();
5509 return false;
5510 }
5511
5512 const wh = this.fsw._getWatchHelpers(path, depth);
5513 if (!wh.hasGlob && priorWh) {
5514 wh.hasGlob = priorWh.hasGlob;
5515 wh.globFilter = priorWh.globFilter;
5516 wh.filterPath = entry => priorWh.filterPath(entry);
5517 wh.filterDir = entry => priorWh.filterDir(entry);
5518 }
5519
5520 // evaluate what is at the path we're being asked to watch
5521 try {
5522 const stats = await statMethods[wh.statMethod](wh.watchPath);
5523 if (this.fsw.closed) return;
5524 if (this.fsw._isIgnored(wh.watchPath, stats)) {
5525 ready();
5526 return false;
5527 }
5528
5529 const follow = this.fsw.options.followSymlinks && !path.includes(STAR$1) && !path.includes(BRACE_START);
5530 let closer;
5531 if (stats.isDirectory()) {
5532 const targetPath = follow ? await fsrealpath(path) : path;
5533 if (this.fsw.closed) return;
5534 closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
5535 if (this.fsw.closed) return;
5536 // preserve this symlink's target path
5537 if (path !== targetPath && targetPath !== undefined) {
5538 this.fsw._symlinkPaths.set(targetPath, true);
5539 }
5540 } else if (stats.isSymbolicLink()) {
5541 const targetPath = follow ? await fsrealpath(path) : path;
5542 if (this.fsw.closed) return;
5543 const parent = sysPath.dirname(wh.watchPath);
5544 this.fsw._getWatchedDir(parent).add(wh.watchPath);
5545 this.fsw._emit(EV_ADD, wh.watchPath, stats);
5546 closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);
5547 if (this.fsw.closed) return;
5548
5549 // preserve this symlink's target path
5550 if (targetPath !== undefined) {
5551 this.fsw._symlinkPaths.set(sysPath.resolve(path), targetPath);
5552 }
5553 } else {
5554 closer = this._handleFile(wh.watchPath, stats, initialAdd);
5555 }
5556 ready();
5557
5558 this.fsw._addPathCloser(path, closer);
5559 return false;
5560
5561 } catch (error) {
5562 if (this.fsw._handleError(error)) {
5563 ready();
5564 return path;
5565 }
5566 }
5567}
5568
5569}
5570
5571var nodefsHandler = NodeFsHandler;
5572
5573var require$$1 = /*@__PURE__*/getAugmentedNamespace(fseventsImporter);
5574
5575const { promisify: promisify$2 } = util;
5576
5577let fsevents;
5578try {
5579 fsevents = require$$1.getFsEvents();
5580} catch (error) {
5581 if (process.env.CHOKIDAR_PRINT_FSEVENTS_REQUIRE_ERROR) console.error(error);
5582}
5583
5584if (fsevents) {
5585 // TODO: real check
5586 const mtch = process.version.match(/v(\d+)\.(\d+)/);
5587 if (mtch && mtch[1] && mtch[2]) {
5588 const maj = Number.parseInt(mtch[1], 10);
5589 const min = Number.parseInt(mtch[2], 10);
5590 if (maj === 8 && min < 16) {
5591 fsevents = undefined;
5592 }
5593 }
5594}
5595
5596const {
5597 EV_ADD: EV_ADD$1,
5598 EV_CHANGE: EV_CHANGE$1,
5599 EV_ADD_DIR: EV_ADD_DIR$1,
5600 EV_UNLINK,
5601 EV_ERROR: EV_ERROR$1,
5602 STR_DATA: STR_DATA$1,
5603 STR_END: STR_END$1,
5604 FSEVENT_CREATED,
5605 FSEVENT_MODIFIED,
5606 FSEVENT_DELETED,
5607 FSEVENT_MOVED,
5608 // FSEVENT_CLONED,
5609 FSEVENT_UNKNOWN,
5610 FSEVENT_TYPE_FILE,
5611 FSEVENT_TYPE_DIRECTORY,
5612 FSEVENT_TYPE_SYMLINK,
5613
5614 ROOT_GLOBSTAR,
5615 DIR_SUFFIX,
5616 DOT_SLASH,
5617 FUNCTION_TYPE,
5618 EMPTY_FN: EMPTY_FN$1,
5619 IDENTITY_FN
5620} = constants$2;
5621
5622const Depth = (value) => isNaN(value) ? {} : {depth: value};
5623
5624const stat$2 = promisify$2(fs.stat);
5625const lstat$2 = promisify$2(fs.lstat);
5626const realpath$1 = promisify$2(fs.realpath);
5627
5628const statMethods$1 = { stat: stat$2, lstat: lstat$2 };
5629
5630/**
5631 * @typedef {String} Path
5632 */
5633
5634/**
5635 * @typedef {Object} FsEventsWatchContainer
5636 * @property {Set<Function>} listeners
5637 * @property {Function} rawEmitter
5638 * @property {{stop: Function}} watcher
5639 */
5640
5641// fsevents instance helper functions
5642/**
5643 * Object to hold per-process fsevents instances (may be shared across chokidar FSWatcher instances)
5644 * @type {Map<Path,FsEventsWatchContainer>}
5645 */
5646const FSEventsWatchers = new Map();
5647
5648// Threshold of duplicate path prefixes at which to start
5649// consolidating going forward
5650const consolidateThreshhold = 10;
5651
5652const wrongEventFlags = new Set([
5653 69888, 70400, 71424, 72704, 73472, 131328, 131840, 262912
5654]);
5655
5656/**
5657 * Instantiates the fsevents interface
5658 * @param {Path} path path to be watched
5659 * @param {Function} callback called when fsevents is bound and ready
5660 * @returns {{stop: Function}} new fsevents instance
5661 */
5662const createFSEventsInstance = (path, callback) => {
5663 const stop = fsevents.watch(path, callback);
5664 return {stop};
5665};
5666
5667/**
5668 * Instantiates the fsevents interface or binds listeners to an existing one covering
5669 * the same file tree.
5670 * @param {Path} path - to be watched
5671 * @param {Path} realPath - real path for symlinks
5672 * @param {Function} listener - called when fsevents emits events
5673 * @param {Function} rawEmitter - passes data to listeners of the 'raw' event
5674 * @returns {Function} closer
5675 */
5676function setFSEventsListener(path, realPath, listener, rawEmitter) {
5677 let watchPath = sysPath.extname(path) ? sysPath.dirname(path) : path;
5678 const parentPath = sysPath.dirname(watchPath);
5679 let cont = FSEventsWatchers.get(watchPath);
5680
5681 // If we've accumulated a substantial number of paths that
5682 // could have been consolidated by watching one directory
5683 // above the current one, create a watcher on the parent
5684 // path instead, so that we do consolidate going forward.
5685 if (couldConsolidate(parentPath)) {
5686 watchPath = parentPath;
5687 }
5688
5689 const resolvedPath = sysPath.resolve(path);
5690 const hasSymlink = resolvedPath !== realPath;
5691
5692 const filteredListener = (fullPath, flags, info) => {
5693 if (hasSymlink) fullPath = fullPath.replace(realPath, resolvedPath);
5694 if (
5695 fullPath === resolvedPath ||
5696 !fullPath.indexOf(resolvedPath + sysPath.sep)
5697 ) listener(fullPath, flags, info);
5698 };
5699
5700 // check if there is already a watcher on a parent path
5701 // modifies `watchPath` to the parent path when it finds a match
5702 let watchedParent = false;
5703 for (const watchedPath of FSEventsWatchers.keys()) {
5704 if (realPath.indexOf(sysPath.resolve(watchedPath) + sysPath.sep) === 0) {
5705 watchPath = watchedPath;
5706 cont = FSEventsWatchers.get(watchPath);
5707 watchedParent = true;
5708 break;
5709 }
5710 }
5711
5712 if (cont || watchedParent) {
5713 cont.listeners.add(filteredListener);
5714 } else {
5715 cont = {
5716 listeners: new Set([filteredListener]),
5717 rawEmitter,
5718 watcher: createFSEventsInstance(watchPath, (fullPath, flags) => {
5719 if (!cont.listeners.size) return;
5720 const info = fsevents.getInfo(fullPath, flags);
5721 cont.listeners.forEach(list => {
5722 list(fullPath, flags, info);
5723 });
5724
5725 cont.rawEmitter(info.event, fullPath, info);
5726 })
5727 };
5728 FSEventsWatchers.set(watchPath, cont);
5729 }
5730
5731 // removes this instance's listeners and closes the underlying fsevents
5732 // instance if there are no more listeners left
5733 return () => {
5734 const lst = cont.listeners;
5735
5736 lst.delete(filteredListener);
5737 if (!lst.size) {
5738 FSEventsWatchers.delete(watchPath);
5739 if (cont.watcher) return cont.watcher.stop().then(() => {
5740 cont.rawEmitter = cont.watcher = undefined;
5741 Object.freeze(cont);
5742 });
5743 }
5744 };
5745}
5746
5747// Decide whether or not we should start a new higher-level
5748// parent watcher
5749const couldConsolidate = (path) => {
5750 let count = 0;
5751 for (const watchPath of FSEventsWatchers.keys()) {
5752 if (watchPath.indexOf(path) === 0) {
5753 count++;
5754 if (count >= consolidateThreshhold) {
5755 return true;
5756 }
5757 }
5758 }
5759
5760 return false;
5761};
5762
5763// returns boolean indicating whether fsevents can be used
5764const canUse = () => fsevents && FSEventsWatchers.size < 128;
5765
5766// determines subdirectory traversal levels from root to path
5767const calcDepth = (path, root) => {
5768 let i = 0;
5769 while (!path.indexOf(root) && (path = sysPath.dirname(path)) !== root) i++;
5770 return i;
5771};
5772
5773// returns boolean indicating whether the fsevents' event info has the same type
5774// as the one returned by fs.stat
5775const sameTypes = (info, stats) => (
5776 info.type === FSEVENT_TYPE_DIRECTORY && stats.isDirectory() ||
5777 info.type === FSEVENT_TYPE_SYMLINK && stats.isSymbolicLink() ||
5778 info.type === FSEVENT_TYPE_FILE && stats.isFile()
5779);
5780
5781/**
5782 * @mixin
5783 */
5784class FsEventsHandler {
5785
5786/**
5787 * @param {import('../index').FSWatcher} fsw
5788 */
5789constructor(fsw) {
5790 this.fsw = fsw;
5791}
5792checkIgnored(path, stats) {
5793 const ipaths = this.fsw._ignoredPaths;
5794 if (this.fsw._isIgnored(path, stats)) {
5795 ipaths.add(path);
5796 if (stats && stats.isDirectory()) {
5797 ipaths.add(path + ROOT_GLOBSTAR);
5798 }
5799 return true;
5800 }
5801
5802 ipaths.delete(path);
5803 ipaths.delete(path + ROOT_GLOBSTAR);
5804}
5805
5806addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts) {
5807 const event = watchedDir.has(item) ? EV_CHANGE$1 : EV_ADD$1;
5808 this.handleEvent(event, path, fullPath, realPath, parent, watchedDir, item, info, opts);
5809}
5810
5811async checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts) {
5812 try {
5813 const stats = await stat$2(path);
5814 if (this.fsw.closed) return;
5815 if (sameTypes(info, stats)) {
5816 this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts);
5817 } else {
5818 this.handleEvent(EV_UNLINK, path, fullPath, realPath, parent, watchedDir, item, info, opts);
5819 }
5820 } catch (error) {
5821 if (error.code === 'EACCES') {
5822 this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts);
5823 } else {
5824 this.handleEvent(EV_UNLINK, path, fullPath, realPath, parent, watchedDir, item, info, opts);
5825 }
5826 }
5827}
5828
5829handleEvent(event, path, fullPath, realPath, parent, watchedDir, item, info, opts) {
5830 if (this.fsw.closed || this.checkIgnored(path)) return;
5831
5832 if (event === EV_UNLINK) {
5833 const isDirectory = info.type === FSEVENT_TYPE_DIRECTORY;
5834 // suppress unlink events on never before seen files
5835 if (isDirectory || watchedDir.has(item)) {
5836 this.fsw._remove(parent, item, isDirectory);
5837 }
5838 } else {
5839 if (event === EV_ADD$1) {
5840 // track new directories
5841 if (info.type === FSEVENT_TYPE_DIRECTORY) this.fsw._getWatchedDir(path);
5842
5843 if (info.type === FSEVENT_TYPE_SYMLINK && opts.followSymlinks) {
5844 // push symlinks back to the top of the stack to get handled
5845 const curDepth = opts.depth === undefined ?
5846 undefined : calcDepth(fullPath, realPath) + 1;
5847 return this._addToFsEvents(path, false, true, curDepth);
5848 }
5849
5850 // track new paths
5851 // (other than symlinks being followed, which will be tracked soon)
5852 this.fsw._getWatchedDir(parent).add(item);
5853 }
5854 /**
5855 * @type {'add'|'addDir'|'unlink'|'unlinkDir'}
5856 */
5857 const eventName = info.type === FSEVENT_TYPE_DIRECTORY ? event + DIR_SUFFIX : event;
5858 this.fsw._emit(eventName, path);
5859 if (eventName === EV_ADD_DIR$1) this._addToFsEvents(path, false, true);
5860 }
5861}
5862
5863/**
5864 * Handle symlinks encountered during directory scan
5865 * @param {String} watchPath - file/dir path to be watched with fsevents
5866 * @param {String} realPath - real path (in case of symlinks)
5867 * @param {Function} transform - path transformer
5868 * @param {Function} globFilter - path filter in case a glob pattern was provided
5869 * @returns {Function} closer for the watcher instance
5870*/
5871_watchWithFsEvents(watchPath, realPath, transform, globFilter) {
5872 if (this.fsw.closed) return;
5873 if (this.fsw._isIgnored(watchPath)) return;
5874 const opts = this.fsw.options;
5875 const watchCallback = async (fullPath, flags, info) => {
5876 if (this.fsw.closed) return;
5877 if (
5878 opts.depth !== undefined &&
5879 calcDepth(fullPath, realPath) > opts.depth
5880 ) return;
5881 const path = transform(sysPath.join(
5882 watchPath, sysPath.relative(watchPath, fullPath)
5883 ));
5884 if (globFilter && !globFilter(path)) return;
5885 // ensure directories are tracked
5886 const parent = sysPath.dirname(path);
5887 const item = sysPath.basename(path);
5888 const watchedDir = this.fsw._getWatchedDir(
5889 info.type === FSEVENT_TYPE_DIRECTORY ? path : parent
5890 );
5891
5892 // correct for wrong events emitted
5893 if (wrongEventFlags.has(flags) || info.event === FSEVENT_UNKNOWN) {
5894 if (typeof opts.ignored === FUNCTION_TYPE) {
5895 let stats;
5896 try {
5897 stats = await stat$2(path);
5898 } catch (error) {}
5899 if (this.fsw.closed) return;
5900 if (this.checkIgnored(path, stats)) return;
5901 if (sameTypes(info, stats)) {
5902 this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts);
5903 } else {
5904 this.handleEvent(EV_UNLINK, path, fullPath, realPath, parent, watchedDir, item, info, opts);
5905 }
5906 } else {
5907 this.checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts);
5908 }
5909 } else {
5910 switch (info.event) {
5911 case FSEVENT_CREATED:
5912 case FSEVENT_MODIFIED:
5913 return this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts);
5914 case FSEVENT_DELETED:
5915 case FSEVENT_MOVED:
5916 return this.checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts);
5917 }
5918 }
5919 };
5920
5921 const closer = setFSEventsListener(
5922 watchPath,
5923 realPath,
5924 watchCallback,
5925 this.fsw._emitRaw
5926 );
5927
5928 this.fsw._emitReady();
5929 return closer;
5930}
5931
5932/**
5933 * Handle symlinks encountered during directory scan
5934 * @param {String} linkPath path to symlink
5935 * @param {String} fullPath absolute path to the symlink
5936 * @param {Function} transform pre-existing path transformer
5937 * @param {Number} curDepth level of subdirectories traversed to where symlink is
5938 * @returns {Promise<void>}
5939 */
5940async _handleFsEventsSymlink(linkPath, fullPath, transform, curDepth) {
5941 // don't follow the same symlink more than once
5942 if (this.fsw.closed || this.fsw._symlinkPaths.has(fullPath)) return;
5943
5944 this.fsw._symlinkPaths.set(fullPath, true);
5945 this.fsw._incrReadyCount();
5946
5947 try {
5948 const linkTarget = await realpath$1(linkPath);
5949 if (this.fsw.closed) return;
5950 if (this.fsw._isIgnored(linkTarget)) {
5951 return this.fsw._emitReady();
5952 }
5953
5954 this.fsw._incrReadyCount();
5955
5956 // add the linkTarget for watching with a wrapper for transform
5957 // that causes emitted paths to incorporate the link's path
5958 this._addToFsEvents(linkTarget || linkPath, (path) => {
5959 let aliasedPath = linkPath;
5960 if (linkTarget && linkTarget !== DOT_SLASH) {
5961 aliasedPath = path.replace(linkTarget, linkPath);
5962 } else if (path !== DOT_SLASH) {
5963 aliasedPath = sysPath.join(linkPath, path);
5964 }
5965 return transform(aliasedPath);
5966 }, false, curDepth);
5967 } catch(error) {
5968 if (this.fsw._handleError(error)) {
5969 return this.fsw._emitReady();
5970 }
5971 }
5972}
5973
5974/**
5975 *
5976 * @param {Path} newPath
5977 * @param {fs.Stats} stats
5978 */
5979emitAdd(newPath, stats, processPath, opts, forceAdd) {
5980 const pp = processPath(newPath);
5981 const isDir = stats.isDirectory();
5982 const dirObj = this.fsw._getWatchedDir(sysPath.dirname(pp));
5983 const base = sysPath.basename(pp);
5984
5985 // ensure empty dirs get tracked
5986 if (isDir) this.fsw._getWatchedDir(pp);
5987 if (dirObj.has(base)) return;
5988 dirObj.add(base);
5989
5990 if (!opts.ignoreInitial || forceAdd === true) {
5991 this.fsw._emit(isDir ? EV_ADD_DIR$1 : EV_ADD$1, pp, stats);
5992 }
5993}
5994
5995initWatch(realPath, path, wh, processPath) {
5996 if (this.fsw.closed) return;
5997 const closer = this._watchWithFsEvents(
5998 wh.watchPath,
5999 sysPath.resolve(realPath || wh.watchPath),
6000 processPath,
6001 wh.globFilter
6002 );
6003 this.fsw._addPathCloser(path, closer);
6004}
6005
6006/**
6007 * Handle added path with fsevents
6008 * @param {String} path file/dir path or glob pattern
6009 * @param {Function|Boolean=} transform converts working path to what the user expects
6010 * @param {Boolean=} forceAdd ensure add is emitted
6011 * @param {Number=} priorDepth Level of subdirectories already traversed.
6012 * @returns {Promise<void>}
6013 */
6014async _addToFsEvents(path, transform, forceAdd, priorDepth) {
6015 if (this.fsw.closed) {
6016 return;
6017 }
6018 const opts = this.fsw.options;
6019 const processPath = typeof transform === FUNCTION_TYPE ? transform : IDENTITY_FN;
6020
6021 const wh = this.fsw._getWatchHelpers(path);
6022
6023 // evaluate what is at the path we're being asked to watch
6024 try {
6025 const stats = await statMethods$1[wh.statMethod](wh.watchPath);
6026 if (this.fsw.closed) return;
6027 if (this.fsw._isIgnored(wh.watchPath, stats)) {
6028 throw null;
6029 }
6030 if (stats.isDirectory()) {
6031 // emit addDir unless this is a glob parent
6032 if (!wh.globFilter) this.emitAdd(processPath(path), stats, processPath, opts, forceAdd);
6033
6034 // don't recurse further if it would exceed depth setting
6035 if (priorDepth && priorDepth > opts.depth) return;
6036
6037 // scan the contents of the dir
6038 this.fsw._readdirp(wh.watchPath, {
6039 fileFilter: entry => wh.filterPath(entry),
6040 directoryFilter: entry => wh.filterDir(entry),
6041 ...Depth(opts.depth - (priorDepth || 0))
6042 }).on(STR_DATA$1, (entry) => {
6043 // need to check filterPath on dirs b/c filterDir is less restrictive
6044 if (this.fsw.closed) {
6045 return;
6046 }
6047 if (entry.stats.isDirectory() && !wh.filterPath(entry)) return;
6048
6049 const joinedPath = sysPath.join(wh.watchPath, entry.path);
6050 const {fullPath} = entry;
6051
6052 if (wh.followSymlinks && entry.stats.isSymbolicLink()) {
6053 // preserve the current depth here since it can't be derived from
6054 // real paths past the symlink
6055 const curDepth = opts.depth === undefined ?
6056 undefined : calcDepth(joinedPath, sysPath.resolve(wh.watchPath)) + 1;
6057
6058 this._handleFsEventsSymlink(joinedPath, fullPath, processPath, curDepth);
6059 } else {
6060 this.emitAdd(joinedPath, entry.stats, processPath, opts, forceAdd);
6061 }
6062 }).on(EV_ERROR$1, EMPTY_FN$1).on(STR_END$1, () => {
6063 this.fsw._emitReady();
6064 });
6065 } else {
6066 this.emitAdd(wh.watchPath, stats, processPath, opts, forceAdd);
6067 this.fsw._emitReady();
6068 }
6069 } catch (error) {
6070 if (!error || this.fsw._handleError(error)) {
6071 // TODO: Strange thing: "should not choke on an ignored watch path" will be failed without 2 ready calls -__-
6072 this.fsw._emitReady();
6073 this.fsw._emitReady();
6074 }
6075 }
6076
6077 if (opts.persistent && forceAdd !== true) {
6078 if (typeof transform === FUNCTION_TYPE) {
6079 // realpath has already been resolved
6080 this.initWatch(undefined, path, wh, processPath);
6081 } else {
6082 let realPath;
6083 try {
6084 realPath = await realpath$1(wh.watchPath);
6085 } catch (e) {}
6086 this.initWatch(realPath, path, wh, processPath);
6087 }
6088 }
6089}
6090
6091}
6092
6093var fseventsHandler = FsEventsHandler;
6094var canUse_1 = canUse;
6095fseventsHandler.canUse = canUse_1;
6096
6097const { EventEmitter } = require$$0$2;
6098
6099
6100const { promisify: promisify$3 } = util;
6101
6102const anymatch = anymatch_1.default;
6103
6104
6105
6106
6107
6108
6109
6110const {
6111 EV_ALL,
6112 EV_READY,
6113 EV_ADD: EV_ADD$2,
6114 EV_CHANGE: EV_CHANGE$2,
6115 EV_UNLINK: EV_UNLINK$1,
6116 EV_ADD_DIR: EV_ADD_DIR$2,
6117 EV_UNLINK_DIR,
6118 EV_RAW,
6119 EV_ERROR: EV_ERROR$2,
6120
6121 STR_CLOSE,
6122 STR_END: STR_END$2,
6123
6124 BACK_SLASH_RE,
6125 DOUBLE_SLASH_RE,
6126 SLASH_OR_BACK_SLASH_RE,
6127 DOT_RE,
6128 REPLACER_RE,
6129
6130 SLASH,
6131 SLASH_SLASH,
6132 BRACE_START: BRACE_START$1,
6133 BANG: BANG$1,
6134 ONE_DOT,
6135 TWO_DOTS,
6136 GLOBSTAR,
6137 SLASH_GLOBSTAR,
6138 ANYMATCH_OPTS,
6139 STRING_TYPE,
6140 FUNCTION_TYPE: FUNCTION_TYPE$1,
6141 EMPTY_STR: EMPTY_STR$1,
6142 EMPTY_FN: EMPTY_FN$2,
6143
6144 isWindows: isWindows$1,
6145 isMacos
6146} = constants$2;
6147
6148const stat$3 = promisify$3(fs.stat);
6149const readdir$1 = promisify$3(fs.readdir);
6150
6151/**
6152 * @typedef {String} Path
6153 * @typedef {'all'|'add'|'addDir'|'change'|'unlink'|'unlinkDir'|'raw'|'error'|'ready'} EventName
6154 * @typedef {'readdir'|'watch'|'add'|'remove'|'change'} ThrottleType
6155 */
6156
6157/**
6158 *
6159 * @typedef {Object} WatchHelpers
6160 * @property {Boolean} followSymlinks
6161 * @property {'stat'|'lstat'} statMethod
6162 * @property {Path} path
6163 * @property {Path} watchPath
6164 * @property {Function} entryPath
6165 * @property {Boolean} hasGlob
6166 * @property {Object} globFilter
6167 * @property {Function} filterPath
6168 * @property {Function} filterDir
6169 */
6170
6171const arrify = (value = []) => Array.isArray(value) ? value : [value];
6172const flatten = (list, result = []) => {
6173 list.forEach(item => {
6174 if (Array.isArray(item)) {
6175 flatten(item, result);
6176 } else {
6177 result.push(item);
6178 }
6179 });
6180 return result;
6181};
6182
6183const unifyPaths = (paths_) => {
6184 /**
6185 * @type {Array<String>}
6186 */
6187 const paths = flatten(arrify(paths_));
6188 if (!paths.every(p => typeof p === STRING_TYPE)) {
6189 throw new TypeError(`Non-string provided as watch path: ${paths}`);
6190 }
6191 return paths.map(normalizePathToUnix);
6192};
6193
6194// If SLASH_SLASH occurs at the beginning of path, it is not replaced
6195// because "//StoragePC/DrivePool/Movies" is a valid network path
6196const toUnix = (string) => {
6197 let str = string.replace(BACK_SLASH_RE, SLASH);
6198 let prepend = false;
6199 if (str.startsWith(SLASH_SLASH)) {
6200 prepend = true;
6201 }
6202 while (str.match(DOUBLE_SLASH_RE)) {
6203 str = str.replace(DOUBLE_SLASH_RE, SLASH);
6204 }
6205 if (prepend) {
6206 str = SLASH + str;
6207 }
6208 return str;
6209};
6210
6211// Our version of upath.normalize
6212// TODO: this is not equal to path-normalize module - investigate why
6213const normalizePathToUnix = (path) => toUnix(sysPath.normalize(toUnix(path)));
6214
6215const normalizeIgnored = (cwd = EMPTY_STR$1) => (path) => {
6216 if (typeof path !== STRING_TYPE) return path;
6217 return normalizePathToUnix(sysPath.isAbsolute(path) ? path : sysPath.join(cwd, path));
6218};
6219
6220const getAbsolutePath = (path, cwd) => {
6221 if (sysPath.isAbsolute(path)) {
6222 return path;
6223 }
6224 if (path.startsWith(BANG$1)) {
6225 return BANG$1 + sysPath.join(cwd, path.slice(1));
6226 }
6227 return sysPath.join(cwd, path);
6228};
6229
6230const undef = (opts, key) => opts[key] === undefined;
6231
6232/**
6233 * Directory entry.
6234 * @property {Path} path
6235 * @property {Set<Path>} items
6236 */
6237class DirEntry {
6238 /**
6239 * @param {Path} dir
6240 * @param {Function} removeWatcher
6241 */
6242 constructor(dir, removeWatcher) {
6243 this.path = dir;
6244 this._removeWatcher = removeWatcher;
6245 /** @type {Set<Path>} */
6246 this.items = new Set();
6247 }
6248
6249 add(item) {
6250 const {items} = this;
6251 if (!items) return;
6252 if (item !== ONE_DOT && item !== TWO_DOTS) items.add(item);
6253 }
6254
6255 async remove(item) {
6256 const {items} = this;
6257 if (!items) return;
6258 items.delete(item);
6259 if (items.size > 0) return;
6260
6261 const dir = this.path;
6262 try {
6263 await readdir$1(dir);
6264 } catch (err) {
6265 if (this._removeWatcher) {
6266 this._removeWatcher(sysPath.dirname(dir), sysPath.basename(dir));
6267 }
6268 }
6269 }
6270
6271 has(item) {
6272 const {items} = this;
6273 if (!items) return;
6274 return items.has(item);
6275 }
6276
6277 /**
6278 * @returns {Array<String>}
6279 */
6280 getChildren() {
6281 const {items} = this;
6282 if (!items) return;
6283 return [...items.values()];
6284 }
6285
6286 dispose() {
6287 this.items.clear();
6288 delete this.path;
6289 delete this._removeWatcher;
6290 delete this.items;
6291 Object.freeze(this);
6292 }
6293}
6294
6295const STAT_METHOD_F = 'stat';
6296const STAT_METHOD_L = 'lstat';
6297class WatchHelper {
6298 constructor(path, watchPath, follow, fsw) {
6299 this.fsw = fsw;
6300 this.path = path = path.replace(REPLACER_RE, EMPTY_STR$1);
6301 this.watchPath = watchPath;
6302 this.fullWatchPath = sysPath.resolve(watchPath);
6303 this.hasGlob = watchPath !== path;
6304 /** @type {object|boolean} */
6305 if (path === EMPTY_STR$1) this.hasGlob = false;
6306 this.globSymlink = this.hasGlob && follow ? undefined : false;
6307 this.globFilter = this.hasGlob ? anymatch(path, undefined, ANYMATCH_OPTS) : false;
6308 this.dirParts = this.getDirParts(path);
6309 this.dirParts.forEach((parts) => {
6310 if (parts.length > 1) parts.pop();
6311 });
6312 this.followSymlinks = follow;
6313 this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;
6314 }
6315
6316 checkGlobSymlink(entry) {
6317 // only need to resolve once
6318 // first entry should always have entry.parentDir === EMPTY_STR
6319 if (this.globSymlink === undefined) {
6320 this.globSymlink = entry.fullParentDir === this.fullWatchPath ?
6321 false : {realPath: entry.fullParentDir, linkPath: this.fullWatchPath};
6322 }
6323
6324 if (this.globSymlink) {
6325 return entry.fullPath.replace(this.globSymlink.realPath, this.globSymlink.linkPath);
6326 }
6327
6328 return entry.fullPath;
6329 }
6330
6331 entryPath(entry) {
6332 return sysPath.join(this.watchPath,
6333 sysPath.relative(this.watchPath, this.checkGlobSymlink(entry))
6334 );
6335 }
6336
6337 filterPath(entry) {
6338 const {stats} = entry;
6339 if (stats && stats.isSymbolicLink()) return this.filterDir(entry);
6340 const resolvedPath = this.entryPath(entry);
6341 const matchesGlob = this.hasGlob && typeof this.globFilter === FUNCTION_TYPE$1 ?
6342 this.globFilter(resolvedPath) : true;
6343 return matchesGlob &&
6344 this.fsw._isntIgnored(resolvedPath, stats) &&
6345 this.fsw._hasReadPermissions(stats);
6346 }
6347
6348 getDirParts(path) {
6349 if (!this.hasGlob) return [];
6350 const parts = [];
6351 const expandedPath = path.includes(BRACE_START$1) ? braces_1.expand(path) : [path];
6352 expandedPath.forEach((path) => {
6353 parts.push(sysPath.relative(this.watchPath, path).split(SLASH_OR_BACK_SLASH_RE));
6354 });
6355 return parts;
6356 }
6357
6358 filterDir(entry) {
6359 if (this.hasGlob) {
6360 const entryParts = this.getDirParts(this.checkGlobSymlink(entry));
6361 let globstar = false;
6362 this.unmatchedGlob = !this.dirParts.some((parts) => {
6363 return parts.every((part, i) => {
6364 if (part === GLOBSTAR) globstar = true;
6365 return globstar || !entryParts[0][i] || anymatch(part, entryParts[0][i], ANYMATCH_OPTS);
6366 });
6367 });
6368 }
6369 return !this.unmatchedGlob && this.fsw._isntIgnored(this.entryPath(entry), entry.stats);
6370 }
6371}
6372
6373/**
6374 * Watches files & directories for changes. Emitted events:
6375 * `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `all`, `error`
6376 *
6377 * new FSWatcher()
6378 * .add(directories)
6379 * .on('add', path => log('File', path, 'was added'))
6380 */
6381class FSWatcher extends EventEmitter {
6382// Not indenting methods for history sake; for now.
6383constructor(_opts) {
6384 super();
6385
6386 const opts = {};
6387 if (_opts) Object.assign(opts, _opts); // for frozen objects
6388
6389 /** @type {Map<String, DirEntry>} */
6390 this._watched = new Map();
6391 /** @type {Map<String, Array>} */
6392 this._closers = new Map();
6393 /** @type {Set<String>} */
6394 this._ignoredPaths = new Set();
6395
6396 /** @type {Map<ThrottleType, Map>} */
6397 this._throttled = new Map();
6398
6399 /** @type {Map<Path, String|Boolean>} */
6400 this._symlinkPaths = new Map();
6401
6402 this._streams = new Set();
6403 this.closed = false;
6404
6405 // Set up default options.
6406 if (undef(opts, 'persistent')) opts.persistent = true;
6407 if (undef(opts, 'ignoreInitial')) opts.ignoreInitial = false;
6408 if (undef(opts, 'ignorePermissionErrors')) opts.ignorePermissionErrors = false;
6409 if (undef(opts, 'interval')) opts.interval = 100;
6410 if (undef(opts, 'binaryInterval')) opts.binaryInterval = 300;
6411 if (undef(opts, 'disableGlobbing')) opts.disableGlobbing = false;
6412 opts.enableBinaryInterval = opts.binaryInterval !== opts.interval;
6413
6414 // Enable fsevents on OS X when polling isn't explicitly enabled.
6415 if (undef(opts, 'useFsEvents')) opts.useFsEvents = !opts.usePolling;
6416
6417 // If we can't use fsevents, ensure the options reflect it's disabled.
6418 const canUseFsEvents = fseventsHandler.canUse();
6419 if (!canUseFsEvents) opts.useFsEvents = false;
6420
6421 // Use polling on Mac if not using fsevents.
6422 // Other platforms use non-polling fs_watch.
6423 if (undef(opts, 'usePolling') && !opts.useFsEvents) {
6424 opts.usePolling = isMacos;
6425 }
6426
6427 // Global override (useful for end-developers that need to force polling for all
6428 // instances of chokidar, regardless of usage/dependency depth)
6429 const envPoll = process.env.CHOKIDAR_USEPOLLING;
6430 if (envPoll !== undefined) {
6431 const envLower = envPoll.toLowerCase();
6432
6433 if (envLower === 'false' || envLower === '0') {
6434 opts.usePolling = false;
6435 } else if (envLower === 'true' || envLower === '1') {
6436 opts.usePolling = true;
6437 } else {
6438 opts.usePolling = !!envLower;
6439 }
6440 }
6441 const envInterval = process.env.CHOKIDAR_INTERVAL;
6442 if (envInterval) {
6443 opts.interval = Number.parseInt(envInterval, 10);
6444 }
6445
6446 // Editor atomic write normalization enabled by default with fs.watch
6447 if (undef(opts, 'atomic')) opts.atomic = !opts.usePolling && !opts.useFsEvents;
6448 if (opts.atomic) this._pendingUnlinks = new Map();
6449
6450 if (undef(opts, 'followSymlinks')) opts.followSymlinks = true;
6451
6452 if (undef(opts, 'awaitWriteFinish')) opts.awaitWriteFinish = false;
6453 if (opts.awaitWriteFinish === true) opts.awaitWriteFinish = {};
6454 const awf = opts.awaitWriteFinish;
6455 if (awf) {
6456 if (!awf.stabilityThreshold) awf.stabilityThreshold = 2000;
6457 if (!awf.pollInterval) awf.pollInterval = 100;
6458 this._pendingWrites = new Map();
6459 }
6460 if (opts.ignored) opts.ignored = arrify(opts.ignored);
6461
6462 let readyCalls = 0;
6463 this._emitReady = () => {
6464 readyCalls++;
6465 if (readyCalls >= this._readyCount) {
6466 this._emitReady = EMPTY_FN$2;
6467 this._readyEmitted = true;
6468 // use process.nextTick to allow time for listener to be bound
6469 process.nextTick(() => this.emit(EV_READY));
6470 }
6471 };
6472 this._emitRaw = (...args) => this.emit(EV_RAW, ...args);
6473 this._readyEmitted = false;
6474 this.options = opts;
6475
6476 // Initialize with proper watcher.
6477 if (opts.useFsEvents) {
6478 this._fsEventsHandler = new fseventsHandler(this);
6479 } else {
6480 this._nodeFsHandler = new nodefsHandler(this);
6481 }
6482
6483 // You’re frozen when your heart’s not open.
6484 Object.freeze(opts);
6485}
6486
6487// Public methods
6488
6489/**
6490 * Adds paths to be watched on an existing FSWatcher instance
6491 * @param {Path|Array<Path>} paths_
6492 * @param {String=} _origAdd private; for handling non-existent paths to be watched
6493 * @param {Boolean=} _internal private; indicates a non-user add
6494 * @returns {FSWatcher} for chaining
6495 */
6496add(paths_, _origAdd, _internal) {
6497 const {cwd, disableGlobbing} = this.options;
6498 this.closed = false;
6499 let paths = unifyPaths(paths_);
6500 if (cwd) {
6501 paths = paths.map((path) => {
6502 const absPath = getAbsolutePath(path, cwd);
6503
6504 // Check `path` instead of `absPath` because the cwd portion can't be a glob
6505 if (disableGlobbing || !isGlob(path)) {
6506 return absPath;
6507 }
6508 return normalizePath(absPath);
6509 });
6510 }
6511
6512 // set aside negated glob strings
6513 paths = paths.filter((path) => {
6514 if (path.startsWith(BANG$1)) {
6515 this._ignoredPaths.add(path.slice(1));
6516 return false;
6517 }
6518
6519 // if a path is being added that was previously ignored, stop ignoring it
6520 this._ignoredPaths.delete(path);
6521 this._ignoredPaths.delete(path + SLASH_GLOBSTAR);
6522
6523 // reset the cached userIgnored anymatch fn
6524 // to make ignoredPaths changes effective
6525 this._userIgnored = undefined;
6526
6527 return true;
6528 });
6529
6530 if (this.options.useFsEvents && this._fsEventsHandler) {
6531 if (!this._readyCount) this._readyCount = paths.length;
6532 if (this.options.persistent) this._readyCount *= 2;
6533 paths.forEach((path) => this._fsEventsHandler._addToFsEvents(path));
6534 } else {
6535 if (!this._readyCount) this._readyCount = 0;
6536 this._readyCount += paths.length;
6537 Promise.all(
6538 paths.map(async path => {
6539 const res = await this._nodeFsHandler._addToNodeFs(path, !_internal, 0, 0, _origAdd);
6540 if (res) this._emitReady();
6541 return res;
6542 })
6543 ).then(results => {
6544 if (this.closed) return;
6545 results.filter(item => item).forEach(item => {
6546 this.add(sysPath.dirname(item), sysPath.basename(_origAdd || item));
6547 });
6548 });
6549 }
6550
6551 return this;
6552}
6553
6554/**
6555 * Close watchers or start ignoring events from specified paths.
6556 * @param {Path|Array<Path>} paths_ - string or array of strings, file/directory paths and/or globs
6557 * @returns {FSWatcher} for chaining
6558*/
6559unwatch(paths_) {
6560 if (this.closed) return this;
6561 const paths = unifyPaths(paths_);
6562 const {cwd} = this.options;
6563
6564 paths.forEach((path) => {
6565 // convert to absolute path unless relative path already matches
6566 if (!sysPath.isAbsolute(path) && !this._closers.has(path)) {
6567 if (cwd) path = sysPath.join(cwd, path);
6568 path = sysPath.resolve(path);
6569 }
6570
6571 this._closePath(path);
6572
6573 this._ignoredPaths.add(path);
6574 if (this._watched.has(path)) {
6575 this._ignoredPaths.add(path + SLASH_GLOBSTAR);
6576 }
6577
6578 // reset the cached userIgnored anymatch fn
6579 // to make ignoredPaths changes effective
6580 this._userIgnored = undefined;
6581 });
6582
6583 return this;
6584}
6585
6586/**
6587 * Close watchers and remove all listeners from watched paths.
6588 * @returns {Promise<void>}.
6589*/
6590close() {
6591 if (this.closed) return this._closePromise;
6592 this.closed = true;
6593
6594 // Memory management.
6595 this.removeAllListeners();
6596 const closers = [];
6597 this._closers.forEach(closerList => closerList.forEach(closer => {
6598 const promise = closer();
6599 if (promise instanceof Promise) closers.push(promise);
6600 }));
6601 this._streams.forEach(stream => stream.destroy());
6602 this._userIgnored = undefined;
6603 this._readyCount = 0;
6604 this._readyEmitted = false;
6605 this._watched.forEach(dirent => dirent.dispose());
6606 ['closers', 'watched', 'streams', 'symlinkPaths', 'throttled'].forEach(key => {
6607 this[`_${key}`].clear();
6608 });
6609
6610 this._closePromise = closers.length ? Promise.all(closers).then(() => undefined) : Promise.resolve();
6611 return this._closePromise;
6612}
6613
6614/**
6615 * Expose list of watched paths
6616 * @returns {Object} for chaining
6617*/
6618getWatched() {
6619 const watchList = {};
6620 this._watched.forEach((entry, dir) => {
6621 const key = this.options.cwd ? sysPath.relative(this.options.cwd, dir) : dir;
6622 watchList[key || ONE_DOT] = entry.getChildren().sort();
6623 });
6624 return watchList;
6625}
6626
6627emitWithAll(event, args) {
6628 this.emit(...args);
6629 if (event !== EV_ERROR$2) this.emit(EV_ALL, ...args);
6630}
6631
6632// Common helpers
6633// --------------
6634
6635/**
6636 * Normalize and emit events.
6637 * Calling _emit DOES NOT MEAN emit() would be called!
6638 * @param {EventName} event Type of event
6639 * @param {Path} path File or directory path
6640 * @param {*=} val1 arguments to be passed with event
6641 * @param {*=} val2
6642 * @param {*=} val3
6643 * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
6644 */
6645async _emit(event, path, val1, val2, val3) {
6646 if (this.closed) return;
6647
6648 const opts = this.options;
6649 if (isWindows$1) path = sysPath.normalize(path);
6650 if (opts.cwd) path = sysPath.relative(opts.cwd, path);
6651 /** @type Array<any> */
6652 const args = [event, path];
6653 if (val3 !== undefined) args.push(val1, val2, val3);
6654 else if (val2 !== undefined) args.push(val1, val2);
6655 else if (val1 !== undefined) args.push(val1);
6656
6657 const awf = opts.awaitWriteFinish;
6658 let pw;
6659 if (awf && (pw = this._pendingWrites.get(path))) {
6660 pw.lastChange = new Date();
6661 return this;
6662 }
6663
6664 if (opts.atomic) {
6665 if (event === EV_UNLINK$1) {
6666 this._pendingUnlinks.set(path, args);
6667 setTimeout(() => {
6668 this._pendingUnlinks.forEach((entry, path) => {
6669 this.emit(...entry);
6670 this.emit(EV_ALL, ...entry);
6671 this._pendingUnlinks.delete(path);
6672 });
6673 }, typeof opts.atomic === 'number' ? opts.atomic : 100);
6674 return this;
6675 }
6676 if (event === EV_ADD$2 && this._pendingUnlinks.has(path)) {
6677 event = args[0] = EV_CHANGE$2;
6678 this._pendingUnlinks.delete(path);
6679 }
6680 }
6681
6682 if (awf && (event === EV_ADD$2 || event === EV_CHANGE$2) && this._readyEmitted) {
6683 const awfEmit = (err, stats) => {
6684 if (err) {
6685 event = args[0] = EV_ERROR$2;
6686 args[1] = err;
6687 this.emitWithAll(event, args);
6688 } else if (stats) {
6689 // if stats doesn't exist the file must have been deleted
6690 if (args.length > 2) {
6691 args[2] = stats;
6692 } else {
6693 args.push(stats);
6694 }
6695 this.emitWithAll(event, args);
6696 }
6697 };
6698
6699 this._awaitWriteFinish(path, awf.stabilityThreshold, event, awfEmit);
6700 return this;
6701 }
6702
6703 if (event === EV_CHANGE$2) {
6704 const isThrottled = !this._throttle(EV_CHANGE$2, path, 50);
6705 if (isThrottled) return this;
6706 }
6707
6708 if (opts.alwaysStat && val1 === undefined &&
6709 (event === EV_ADD$2 || event === EV_ADD_DIR$2 || event === EV_CHANGE$2)
6710 ) {
6711 const fullPath = opts.cwd ? sysPath.join(opts.cwd, path) : path;
6712 let stats;
6713 try {
6714 stats = await stat$3(fullPath);
6715 } catch (err) {}
6716 // Suppress event when fs_stat fails, to avoid sending undefined 'stat'
6717 if (!stats || this.closed) return;
6718 args.push(stats);
6719 }
6720 this.emitWithAll(event, args);
6721
6722 return this;
6723}
6724
6725/**
6726 * Common handler for errors
6727 * @param {Error} error
6728 * @returns {Error|Boolean} The error if defined, otherwise the value of the FSWatcher instance's `closed` flag
6729 */
6730_handleError(error) {
6731 const code = error && error.code;
6732 if (error && code !== 'ENOENT' && code !== 'ENOTDIR' &&
6733 (!this.options.ignorePermissionErrors || (code !== 'EPERM' && code !== 'EACCES'))
6734 ) {
6735 this.emit(EV_ERROR$2, error);
6736 }
6737 return error || this.closed;
6738}
6739
6740/**
6741 * Helper utility for throttling
6742 * @param {ThrottleType} actionType type being throttled
6743 * @param {Path} path being acted upon
6744 * @param {Number} timeout duration of time to suppress duplicate actions
6745 * @returns {Object|false} tracking object or false if action should be suppressed
6746 */
6747_throttle(actionType, path, timeout) {
6748 if (!this._throttled.has(actionType)) {
6749 this._throttled.set(actionType, new Map());
6750 }
6751
6752 /** @type {Map<Path, Object>} */
6753 const action = this._throttled.get(actionType);
6754 /** @type {Object} */
6755 const actionPath = action.get(path);
6756
6757 if (actionPath) {
6758 actionPath.count++;
6759 return false;
6760 }
6761
6762 let timeoutObject;
6763 const clear = () => {
6764 const item = action.get(path);
6765 const count = item ? item.count : 0;
6766 action.delete(path);
6767 clearTimeout(timeoutObject);
6768 if (item) clearTimeout(item.timeoutObject);
6769 return count;
6770 };
6771 timeoutObject = setTimeout(clear, timeout);
6772 const thr = {timeoutObject, clear, count: 0};
6773 action.set(path, thr);
6774 return thr;
6775}
6776
6777_incrReadyCount() {
6778 return this._readyCount++;
6779}
6780
6781/**
6782 * Awaits write operation to finish.
6783 * Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback.
6784 * @param {Path} path being acted upon
6785 * @param {Number} threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished
6786 * @param {EventName} event
6787 * @param {Function} awfEmit Callback to be called when ready for event to be emitted.
6788 */
6789_awaitWriteFinish(path, threshold, event, awfEmit) {
6790 let timeoutHandler;
6791
6792 let fullPath = path;
6793 if (this.options.cwd && !sysPath.isAbsolute(path)) {
6794 fullPath = sysPath.join(this.options.cwd, path);
6795 }
6796
6797 const now = new Date();
6798
6799 const awaitWriteFinish = (prevStat) => {
6800 fs.stat(fullPath, (err, curStat) => {
6801 if (err || !this._pendingWrites.has(path)) {
6802 if (err && err.code !== 'ENOENT') awfEmit(err);
6803 return;
6804 }
6805
6806 const now = Number(new Date());
6807
6808 if (prevStat && curStat.size !== prevStat.size) {
6809 this._pendingWrites.get(path).lastChange = now;
6810 }
6811 const pw = this._pendingWrites.get(path);
6812 const df = now - pw.lastChange;
6813
6814 if (df >= threshold) {
6815 this._pendingWrites.delete(path);
6816 awfEmit(undefined, curStat);
6817 } else {
6818 timeoutHandler = setTimeout(
6819 awaitWriteFinish,
6820 this.options.awaitWriteFinish.pollInterval,
6821 curStat
6822 );
6823 }
6824 });
6825 };
6826
6827 if (!this._pendingWrites.has(path)) {
6828 this._pendingWrites.set(path, {
6829 lastChange: now,
6830 cancelWait: () => {
6831 this._pendingWrites.delete(path);
6832 clearTimeout(timeoutHandler);
6833 return event;
6834 }
6835 });
6836 timeoutHandler = setTimeout(
6837 awaitWriteFinish,
6838 this.options.awaitWriteFinish.pollInterval
6839 );
6840 }
6841}
6842
6843_getGlobIgnored() {
6844 return [...this._ignoredPaths.values()];
6845}
6846
6847/**
6848 * Determines whether user has asked to ignore this path.
6849 * @param {Path} path filepath or dir
6850 * @param {fs.Stats=} stats result of fs.stat
6851 * @returns {Boolean}
6852 */
6853_isIgnored(path, stats) {
6854 if (this.options.atomic && DOT_RE.test(path)) return true;
6855 if (!this._userIgnored) {
6856 const {cwd} = this.options;
6857 const ign = this.options.ignored;
6858
6859 const ignored = ign && ign.map(normalizeIgnored(cwd));
6860 const paths = arrify(ignored)
6861 .filter((path) => typeof path === STRING_TYPE && !isGlob(path))
6862 .map((path) => path + SLASH_GLOBSTAR);
6863 const list = this._getGlobIgnored().map(normalizeIgnored(cwd)).concat(ignored, paths);
6864 this._userIgnored = anymatch(list, undefined, ANYMATCH_OPTS);
6865 }
6866
6867 return this._userIgnored([path, stats]);
6868}
6869
6870_isntIgnored(path, stat) {
6871 return !this._isIgnored(path, stat);
6872}
6873
6874/**
6875 * Provides a set of common helpers and properties relating to symlink and glob handling.
6876 * @param {Path} path file, directory, or glob pattern being watched
6877 * @param {Number=} depth at any depth > 0, this isn't a glob
6878 * @returns {WatchHelper} object containing helpers for this path
6879 */
6880_getWatchHelpers(path, depth) {
6881 const watchPath = depth || this.options.disableGlobbing || !isGlob(path) ? path : globParent(path);
6882 const follow = this.options.followSymlinks;
6883
6884 return new WatchHelper(path, watchPath, follow, this);
6885}
6886
6887// Directory helpers
6888// -----------------
6889
6890/**
6891 * Provides directory tracking objects
6892 * @param {String} directory path of the directory
6893 * @returns {DirEntry} the directory's tracking object
6894 */
6895_getWatchedDir(directory) {
6896 if (!this._boundRemove) this._boundRemove = this._remove.bind(this);
6897 const dir = sysPath.resolve(directory);
6898 if (!this._watched.has(dir)) this._watched.set(dir, new DirEntry(dir, this._boundRemove));
6899 return this._watched.get(dir);
6900}
6901
6902// File helpers
6903// ------------
6904
6905/**
6906 * Check for read permissions.
6907 * Based on this answer on SO: https://stackoverflow.com/a/11781404/1358405
6908 * @param {fs.Stats} stats - object, result of fs_stat
6909 * @returns {Boolean} indicates whether the file can be read
6910*/
6911_hasReadPermissions(stats) {
6912 if (this.options.ignorePermissionErrors) return true;
6913
6914 // stats.mode may be bigint
6915 const md = stats && Number.parseInt(stats.mode, 10);
6916 const st = md & 0o777;
6917 const it = Number.parseInt(st.toString(8)[0], 10);
6918 return Boolean(4 & it);
6919}
6920
6921/**
6922 * Handles emitting unlink events for
6923 * files and directories, and via recursion, for
6924 * files and directories within directories that are unlinked
6925 * @param {String} directory within which the following item is located
6926 * @param {String} item base path of item/directory
6927 * @returns {void}
6928*/
6929_remove(directory, item, isDirectory) {
6930 // if what is being deleted is a directory, get that directory's paths
6931 // for recursive deleting and cleaning of watched object
6932 // if it is not a directory, nestedDirectoryChildren will be empty array
6933 const path = sysPath.join(directory, item);
6934 const fullPath = sysPath.resolve(path);
6935 isDirectory = isDirectory != null
6936 ? isDirectory
6937 : this._watched.has(path) || this._watched.has(fullPath);
6938
6939 // prevent duplicate handling in case of arriving here nearly simultaneously
6940 // via multiple paths (such as _handleFile and _handleDir)
6941 if (!this._throttle('remove', path, 100)) return;
6942
6943 // if the only watched file is removed, watch for its return
6944 if (!isDirectory && !this.options.useFsEvents && this._watched.size === 1) {
6945 this.add(directory, item, true);
6946 }
6947
6948 // This will create a new entry in the watched object in either case
6949 // so we got to do the directory check beforehand
6950 const wp = this._getWatchedDir(path);
6951 const nestedDirectoryChildren = wp.getChildren();
6952
6953 // Recursively remove children directories / files.
6954 nestedDirectoryChildren.forEach(nested => this._remove(path, nested));
6955
6956 // Check if item was on the watched list and remove it
6957 const parent = this._getWatchedDir(directory);
6958 const wasTracked = parent.has(item);
6959 parent.remove(item);
6960
6961 // If we wait for this file to be fully written, cancel the wait.
6962 let relPath = path;
6963 if (this.options.cwd) relPath = sysPath.relative(this.options.cwd, path);
6964 if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
6965 const event = this._pendingWrites.get(relPath).cancelWait();
6966 if (event === EV_ADD$2) return;
6967 }
6968
6969 // The Entry will either be a directory that just got removed
6970 // or a bogus entry to a file, in either case we have to remove it
6971 this._watched.delete(path);
6972 this._watched.delete(fullPath);
6973 const eventName = isDirectory ? EV_UNLINK_DIR : EV_UNLINK$1;
6974 if (wasTracked && !this._isIgnored(path)) this._emit(eventName, path);
6975
6976 // Avoid conflicts if we later create another file with the same name
6977 if (!this.options.useFsEvents) {
6978 this._closePath(path);
6979 }
6980}
6981
6982/**
6983 * Closes all watchers for a path
6984 * @param {Path} path
6985 */
6986_closePath(path) {
6987 this._closeFile(path);
6988 const dir = sysPath.dirname(path);
6989 this._getWatchedDir(dir).remove(sysPath.basename(path));
6990}
6991
6992/**
6993 * Closes only file-specific watchers
6994 * @param {Path} path
6995 */
6996_closeFile(path) {
6997 const closers = this._closers.get(path);
6998 if (!closers) return;
6999 closers.forEach(closer => closer());
7000 this._closers.delete(path);
7001}
7002
7003/**
7004 *
7005 * @param {Path} path
7006 * @param {Function} closer
7007 */
7008_addPathCloser(path, closer) {
7009 if (!closer) return;
7010 let list = this._closers.get(path);
7011 if (!list) {
7012 list = [];
7013 this._closers.set(path, list);
7014 }
7015 list.push(closer);
7016}
7017
7018_readdirp(root, opts) {
7019 if (this.closed) return;
7020 const options = {type: EV_ALL, alwaysStat: true, lstat: true, ...opts};
7021 let stream = readdirp_1(root, options);
7022 this._streams.add(stream);
7023 stream.once(STR_CLOSE, () => {
7024 stream = undefined;
7025 });
7026 stream.once(STR_END$2, () => {
7027 if (stream) {
7028 this._streams.delete(stream);
7029 stream = undefined;
7030 }
7031 });
7032 return stream;
7033}
7034
7035}
7036
7037// Export FSWatcher class
7038var FSWatcher_1 = FSWatcher;
7039
7040/**
7041 * Instantiates watcher with paths to be tracked.
7042 * @param {String|Array<String>} paths file/directory paths and/or globs
7043 * @param {Object=} options chokidar opts
7044 * @returns an instance of FSWatcher for chaining.
7045 */
7046const watch = (paths, options) => {
7047 const watcher = new FSWatcher(options);
7048 watcher.add(paths);
7049 return watcher;
7050};
7051
7052var watch_1 = watch;
7053
7054var chokidar = {
7055 FSWatcher: FSWatcher_1,
7056 watch: watch_1
7057};
7058
7059class FileWatcher {
7060 constructor(task, chokidarOptions) {
7061 this.transformWatchers = new Map();
7062 this.chokidarOptions = chokidarOptions;
7063 this.task = task;
7064 this.watcher = this.createWatcher(null);
7065 }
7066 close() {
7067 this.watcher.close();
7068 for (const watcher of this.transformWatchers.values()) {
7069 watcher.close();
7070 }
7071 }
7072 unwatch(id) {
7073 this.watcher.unwatch(id);
7074 const transformWatcher = this.transformWatchers.get(id);
7075 if (transformWatcher) {
7076 this.transformWatchers.delete(id);
7077 transformWatcher.close();
7078 }
7079 }
7080 watch(id, isTransformDependency) {
7081 if (isTransformDependency) {
7082 const watcher = this.transformWatchers.get(id) || this.createWatcher(id);
7083 watcher.add(id);
7084 this.transformWatchers.set(id, watcher);
7085 }
7086 else {
7087 this.watcher.add(id);
7088 }
7089 }
7090 createWatcher(transformWatcherId) {
7091 const task = this.task;
7092 const isLinux = platform() === 'linux';
7093 const isTransformDependency = transformWatcherId !== null;
7094 const handleChange = (id, event) => {
7095 const changedId = transformWatcherId || id;
7096 if (isLinux) {
7097 // unwatching and watching fixes an issue with chokidar where on certain systems,
7098 // a file that was unlinked and immediately recreated would create a change event
7099 // but then no longer any further events
7100 watcher.unwatch(changedId);
7101 watcher.add(changedId);
7102 }
7103 task.invalidate(changedId, { isTransformDependency, event });
7104 };
7105 const watcher = chokidar
7106 .watch([], this.chokidarOptions)
7107 .on('add', id => handleChange(id, 'create'))
7108 .on('change', id => handleChange(id, 'update'))
7109 .on('unlink', id => handleChange(id, 'delete'));
7110 return watcher;
7111 }
7112}
7113
7114const eventsRewrites = {
7115 create: {
7116 create: 'buggy',
7117 delete: null,
7118 update: 'create',
7119 },
7120 delete: {
7121 create: 'update',
7122 delete: 'buggy',
7123 update: 'buggy',
7124 },
7125 update: {
7126 create: 'buggy',
7127 delete: 'delete',
7128 update: 'update',
7129 }
7130};
7131class Watcher {
7132 constructor(configs, emitter) {
7133 this.buildDelay = 0;
7134 this.buildTimeout = null;
7135 this.invalidatedIds = new Map();
7136 this.rerun = false;
7137 this.emitter = emitter;
7138 emitter.close = this.close.bind(this);
7139 this.tasks = configs.map(config => new Task(this, config));
7140 this.buildDelay = configs.reduce((buildDelay, { watch }) => watch && typeof watch.buildDelay === 'number'
7141 ? Math.max(buildDelay, watch.buildDelay)
7142 : buildDelay, this.buildDelay);
7143 this.running = true;
7144 process.nextTick(() => this.run());
7145 }
7146 close() {
7147 if (this.buildTimeout)
7148 clearTimeout(this.buildTimeout);
7149 for (const task of this.tasks) {
7150 task.close();
7151 }
7152 this.emitter.emit('close');
7153 this.emitter.removeAllListeners();
7154 }
7155 invalidate(file) {
7156 if (file) {
7157 const prevEvent = this.invalidatedIds.get(file.id);
7158 const event = prevEvent
7159 ? eventsRewrites[prevEvent][file.event]
7160 : file.event;
7161 if (event === 'buggy') {
7162 //TODO: throws or warn? Currently just ignore, uses new event
7163 this.invalidatedIds.set(file.id, file.event);
7164 }
7165 else if (event === null) {
7166 this.invalidatedIds.delete(file.id);
7167 }
7168 else {
7169 this.invalidatedIds.set(file.id, event);
7170 }
7171 }
7172 if (this.running) {
7173 this.rerun = true;
7174 return;
7175 }
7176 if (this.buildTimeout)
7177 clearTimeout(this.buildTimeout);
7178 this.buildTimeout = setTimeout(() => {
7179 this.buildTimeout = null;
7180 for (const [id, event] of this.invalidatedIds.entries()) {
7181 this.emitter.emit('change', id, { event });
7182 }
7183 this.invalidatedIds.clear();
7184 this.emitter.emit('restart');
7185 this.run();
7186 }, this.buildDelay);
7187 }
7188 async run() {
7189 this.running = true;
7190 this.emitter.emit('event', {
7191 code: 'START'
7192 });
7193 try {
7194 for (const task of this.tasks) {
7195 await task.run();
7196 }
7197 this.running = false;
7198 this.emitter.emit('event', {
7199 code: 'END'
7200 });
7201 }
7202 catch (error) {
7203 this.running = false;
7204 this.emitter.emit('event', {
7205 code: 'ERROR',
7206 error
7207 });
7208 }
7209 if (this.rerun) {
7210 this.rerun = false;
7211 this.invalidate();
7212 }
7213 }
7214}
7215class Task {
7216 constructor(watcher, config) {
7217 this.cache = { modules: [] };
7218 this.watchFiles = [];
7219 this.invalidated = true;
7220 this.watcher = watcher;
7221 this.closed = false;
7222 this.watched = new Set();
7223 this.skipWrite = config.watch && !!config.watch.skipWrite;
7224 this.options = mergeOptions(config);
7225 this.outputs = this.options.output;
7226 this.outputFiles = this.outputs.map(output => {
7227 if (output.file || output.dir)
7228 return resolve(output.file || output.dir);
7229 return undefined;
7230 });
7231 const watchOptions = this.options.watch || {};
7232 this.filter = createFilter(watchOptions.include, watchOptions.exclude);
7233 this.fileWatcher = new FileWatcher(this, {
7234 ...watchOptions.chokidar,
7235 disableGlobbing: true,
7236 ignoreInitial: true
7237 });
7238 }
7239 close() {
7240 this.closed = true;
7241 this.fileWatcher.close();
7242 }
7243 invalidate(id, details) {
7244 this.invalidated = true;
7245 if (details.isTransformDependency) {
7246 for (const module of this.cache.modules) {
7247 if (module.transformDependencies.indexOf(id) === -1)
7248 continue;
7249 // effective invalidation
7250 module.originalCode = null;
7251 }
7252 }
7253 this.watcher.invalidate({ id, event: details.event });
7254 }
7255 async run() {
7256 if (!this.invalidated)
7257 return;
7258 this.invalidated = false;
7259 const options = {
7260 ...this.options,
7261 cache: this.cache
7262 };
7263 const start = Date.now();
7264 this.watcher.emitter.emit('event', {
7265 code: 'BUNDLE_START',
7266 input: this.options.input,
7267 output: this.outputFiles
7268 });
7269 try {
7270 const result = await rollupInternal(options, this.watcher.emitter);
7271 if (this.closed) {
7272 return;
7273 }
7274 this.updateWatchedFiles(result);
7275 this.skipWrite || (await Promise.all(this.outputs.map(output => result.write(output))));
7276 this.watcher.emitter.emit('event', {
7277 code: 'BUNDLE_END',
7278 duration: Date.now() - start,
7279 input: this.options.input,
7280 output: this.outputFiles,
7281 result
7282 });
7283 }
7284 catch (error) {
7285 if (this.closed) {
7286 return;
7287 }
7288 if (Array.isArray(error.watchFiles)) {
7289 for (const id of error.watchFiles) {
7290 this.watchFile(id);
7291 }
7292 }
7293 if (error.id) {
7294 this.cache.modules = this.cache.modules.filter(module => module.id !== error.id);
7295 }
7296 throw error;
7297 }
7298 }
7299 updateWatchedFiles(result) {
7300 const previouslyWatched = this.watched;
7301 this.watched = new Set();
7302 this.watchFiles = result.watchFiles;
7303 this.cache = result.cache;
7304 for (const id of this.watchFiles) {
7305 this.watchFile(id);
7306 }
7307 for (const module of this.cache.modules) {
7308 for (const depId of module.transformDependencies) {
7309 this.watchFile(depId, true);
7310 }
7311 }
7312 for (const id of previouslyWatched) {
7313 if (!this.watched.has(id)) {
7314 this.fileWatcher.unwatch(id);
7315 }
7316 }
7317 }
7318 watchFile(id, isTransformDependency = false) {
7319 if (!this.filter(id))
7320 return;
7321 this.watched.add(id);
7322 if (this.outputFiles.some(file => file === id)) {
7323 throw new Error('Cannot import the generated bundle');
7324 }
7325 // this is necessary to ensure that any 'renamed' files
7326 // continue to be watched following an error
7327 this.fileWatcher.watch(id, isTransformDependency);
7328 }
7329}
7330
7331export { Task, Watcher };