UNPKG

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