Legend:
- Unmodified
- Added
- Removed
-
imaps-frontend/node_modules/rollup/dist/es/shared/watch.js
rd565449 r0c6b92a 1 1 /* 2 2 @license 3 Rollup.js v4.2 0.04 Sat, 03 Aug 2024 04:48:21 GMT - commit df12edfea6e9c1a71bda1a01bed1ab787b7514d53 Rollup.js v4.27.4 4 Sat, 23 Nov 2024 06:59:50 GMT - commit e805b546405a4e6cfccd3fe73e9f4df770023824 5 5 6 6 https://github.com/rollup/rollup … … 8 8 Released under the MIT License. 9 9 */ 10 import path$1 from 'node:path'; 10 import { getAugmentedNamespace, fseventsImporter, getDefaultExportFromCjs, createFilter, rollupInternal } from './node-entry.js'; 11 import path from 'node:path'; 11 12 import process$1 from 'node:process'; 12 import { picomatch as picomatch$2, getAugmentedNamespace, fseventsImporter, createFilter, rollupInternal } from './node-entry.js'; 13 import { platform } from 'node:os'; 14 import require$$0$1 from 'fs'; 13 import require$$0$1 from 'path'; 14 import require$$0$2 from 'fs'; 15 15 import require$$2 from 'util'; 16 16 import require$$1 from 'stream'; 17 import require$$0$2 from 'path';18 17 import require$$2$1 from 'os'; 19 18 import require$$0$3 from 'events'; 19 import { platform } from 'node:os'; 20 20 import './parseAst.js'; 21 21 import '../../native.js'; … … 24 24 import 'tty'; 25 25 26 var chokidar = {}; 27 28 const fs$3 = require$$0$1; 29 const { Readable } = require$$1; 30 const sysPath$3 = require$$0$2; 31 const { promisify: promisify$3 } = require$$2; 32 const picomatch$1 = picomatch$2; 33 34 const readdir$1 = promisify$3(fs$3.readdir); 35 const stat$3 = promisify$3(fs$3.stat); 36 const lstat$2 = promisify$3(fs$3.lstat); 37 const realpath$1 = promisify$3(fs$3.realpath); 38 39 /** 40 * @typedef {Object} EntryInfo 41 * @property {String} path 42 * @property {String} fullPath 43 * @property {fs.Stats=} stats 44 * @property {fs.Dirent=} dirent 45 * @property {String} basename 46 */ 47 48 const BANG$2 = '!'; 49 const RECURSIVE_ERROR_CODE = 'READDIRP_RECURSIVE_ERROR'; 50 const NORMAL_FLOW_ERRORS = new Set(['ENOENT', 'EPERM', 'EACCES', 'ELOOP', RECURSIVE_ERROR_CODE]); 51 const FILE_TYPE = 'files'; 52 const DIR_TYPE = 'directories'; 53 const FILE_DIR_TYPE = 'files_directories'; 54 const EVERYTHING_TYPE = 'all'; 55 const ALL_TYPES = [FILE_TYPE, DIR_TYPE, FILE_DIR_TYPE, EVERYTHING_TYPE]; 56 57 const isNormalFlowError = error => NORMAL_FLOW_ERRORS.has(error.code); 58 const [maj, min] = process.versions.node.split('.').slice(0, 2).map(n => Number.parseInt(n, 10)); 59 const wantBigintFsStats = process.platform === 'win32' && (maj > 10 || (maj === 10 && min >= 5)); 60 61 const normalizeFilter = filter => { 62 if (filter === undefined) return; 63 if (typeof filter === 'function') return filter; 64 65 if (typeof filter === 'string') { 66 const glob = picomatch$1(filter.trim()); 67 return entry => glob(entry.basename); 68 } 69 70 if (Array.isArray(filter)) { 71 const positive = []; 72 const negative = []; 73 for (const item of filter) { 74 const trimmed = item.trim(); 75 if (trimmed.charAt(0) === BANG$2) { 76 negative.push(picomatch$1(trimmed.slice(1))); 77 } else { 78 positive.push(picomatch$1(trimmed)); 79 } 80 } 81 82 if (negative.length > 0) { 83 if (positive.length > 0) { 84 return entry => 85 positive.some(f => f(entry.basename)) && !negative.some(f => f(entry.basename)); 86 } 87 return entry => !negative.some(f => f(entry.basename)); 88 } 89 return entry => positive.some(f => f(entry.basename)); 90 } 91 }; 92 93 class ReaddirpStream extends Readable { 94 static get defaultOptions() { 95 return { 96 root: '.', 97 /* eslint-disable no-unused-vars */ 98 fileFilter: (path) => true, 99 directoryFilter: (path) => true, 100 /* eslint-enable no-unused-vars */ 101 type: FILE_TYPE, 102 lstat: false, 103 depth: 2147483648, 104 alwaysStat: false 105 }; 106 } 107 108 constructor(options = {}) { 109 super({ 110 objectMode: true, 111 autoDestroy: true, 112 highWaterMark: options.highWaterMark || 4096 113 }); 114 const opts = { ...ReaddirpStream.defaultOptions, ...options }; 115 const { root, type } = opts; 116 117 this._fileFilter = normalizeFilter(opts.fileFilter); 118 this._directoryFilter = normalizeFilter(opts.directoryFilter); 119 120 const statMethod = opts.lstat ? lstat$2 : stat$3; 121 // Use bigint stats if it's windows and stat() supports options (node 10+). 122 if (wantBigintFsStats) { 123 this._stat = path => statMethod(path, { bigint: true }); 124 } else { 125 this._stat = statMethod; 126 } 127 128 this._maxDepth = opts.depth; 129 this._wantsDir = [DIR_TYPE, FILE_DIR_TYPE, EVERYTHING_TYPE].includes(type); 130 this._wantsFile = [FILE_TYPE, FILE_DIR_TYPE, EVERYTHING_TYPE].includes(type); 131 this._wantsEverything = type === EVERYTHING_TYPE; 132 this._root = sysPath$3.resolve(root); 133 this._isDirent = ('Dirent' in fs$3) && !opts.alwaysStat; 134 this._statsProp = this._isDirent ? 'dirent' : 'stats'; 135 this._rdOptions = { encoding: 'utf8', withFileTypes: this._isDirent }; 136 137 // Launch stream with one parent, the root dir. 138 this.parents = [this._exploreDir(root, 1)]; 139 this.reading = false; 140 this.parent = undefined; 141 } 142 143 async _read(batch) { 144 if (this.reading) return; 145 this.reading = true; 146 147 try { 148 while (!this.destroyed && batch > 0) { 149 const { path, depth, files = [] } = this.parent || {}; 150 151 if (files.length > 0) { 152 const slice = files.splice(0, batch).map(dirent => this._formatEntry(dirent, path)); 153 for (const entry of await Promise.all(slice)) { 154 if (this.destroyed) return; 155 156 const entryType = await this._getEntryType(entry); 157 if (entryType === 'directory' && this._directoryFilter(entry)) { 158 if (depth <= this._maxDepth) { 159 this.parents.push(this._exploreDir(entry.fullPath, depth + 1)); 160 } 161 162 if (this._wantsDir) { 163 this.push(entry); 164 batch--; 165 } 166 } else if ((entryType === 'file' || this._includeAsFile(entry)) && this._fileFilter(entry)) { 167 if (this._wantsFile) { 168 this.push(entry); 169 batch--; 170 } 171 } 172 } 173 } else { 174 const parent = this.parents.pop(); 175 if (!parent) { 176 this.push(null); 177 break; 178 } 179 this.parent = await parent; 180 if (this.destroyed) return; 181 } 182 } 183 } catch (error) { 184 this.destroy(error); 185 } finally { 186 this.reading = false; 187 } 188 } 189 190 async _exploreDir(path, depth) { 191 let files; 192 try { 193 files = await readdir$1(path, this._rdOptions); 194 } catch (error) { 195 this._onError(error); 196 } 197 return { files, depth, path }; 198 } 199 200 async _formatEntry(dirent, path) { 201 let entry; 202 try { 203 const basename = this._isDirent ? dirent.name : dirent; 204 const fullPath = sysPath$3.resolve(sysPath$3.join(path, basename)); 205 entry = { path: sysPath$3.relative(this._root, fullPath), fullPath, basename }; 206 entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath); 207 } catch (err) { 208 this._onError(err); 209 } 210 return entry; 211 } 212 213 _onError(err) { 214 if (isNormalFlowError(err) && !this.destroyed) { 215 this.emit('warn', err); 216 } else { 217 this.destroy(err); 218 } 219 } 220 221 async _getEntryType(entry) { 222 // entry may be undefined, because a warning or an error were emitted 223 // and the statsProp is undefined 224 const stats = entry && entry[this._statsProp]; 225 if (!stats) { 226 return; 227 } 228 if (stats.isFile()) { 229 return 'file'; 230 } 231 if (stats.isDirectory()) { 232 return 'directory'; 233 } 234 if (stats && stats.isSymbolicLink()) { 235 const full = entry.fullPath; 236 try { 237 const entryRealPath = await realpath$1(full); 238 const entryRealPathStats = await lstat$2(entryRealPath); 239 if (entryRealPathStats.isFile()) { 240 return 'file'; 241 } 242 if (entryRealPathStats.isDirectory()) { 243 const len = entryRealPath.length; 244 if (full.startsWith(entryRealPath) && full.substr(len, 1) === sysPath$3.sep) { 245 const recursiveError = new Error( 246 `Circular symlink detected: "${full}" points to "${entryRealPath}"` 247 ); 248 recursiveError.code = RECURSIVE_ERROR_CODE; 249 return this._onError(recursiveError); 250 } 251 return 'directory'; 252 } 253 } catch (error) { 254 this._onError(error); 255 } 256 } 257 } 258 259 _includeAsFile(entry) { 260 const stats = entry && entry[this._statsProp]; 261 262 return stats && this._wantsEverything && !stats.isDirectory(); 263 } 26 var chokidar$1 = {}; 27 28 var utils$2 = {}; 29 30 var constants$3; 31 var hasRequiredConstants$3; 32 33 function requireConstants$3 () { 34 if (hasRequiredConstants$3) return constants$3; 35 hasRequiredConstants$3 = 1; 36 37 const path = require$$0$1; 38 const WIN_SLASH = '\\\\/'; 39 const WIN_NO_SLASH = `[^${WIN_SLASH}]`; 40 41 /** 42 * Posix glob regex 43 */ 44 45 const DOT_LITERAL = '\\.'; 46 const PLUS_LITERAL = '\\+'; 47 const QMARK_LITERAL = '\\?'; 48 const SLASH_LITERAL = '\\/'; 49 const ONE_CHAR = '(?=.)'; 50 const QMARK = '[^/]'; 51 const END_ANCHOR = `(?:${SLASH_LITERAL}|$)`; 52 const START_ANCHOR = `(?:^|${SLASH_LITERAL})`; 53 const DOTS_SLASH = `${DOT_LITERAL}{1,2}${END_ANCHOR}`; 54 const NO_DOT = `(?!${DOT_LITERAL})`; 55 const NO_DOTS = `(?!${START_ANCHOR}${DOTS_SLASH})`; 56 const NO_DOT_SLASH = `(?!${DOT_LITERAL}{0,1}${END_ANCHOR})`; 57 const NO_DOTS_SLASH = `(?!${DOTS_SLASH})`; 58 const QMARK_NO_DOT = `[^.${SLASH_LITERAL}]`; 59 const STAR = `${QMARK}*?`; 60 61 const POSIX_CHARS = { 62 DOT_LITERAL, 63 PLUS_LITERAL, 64 QMARK_LITERAL, 65 SLASH_LITERAL, 66 ONE_CHAR, 67 QMARK, 68 END_ANCHOR, 69 DOTS_SLASH, 70 NO_DOT, 71 NO_DOTS, 72 NO_DOT_SLASH, 73 NO_DOTS_SLASH, 74 QMARK_NO_DOT, 75 STAR, 76 START_ANCHOR 77 }; 78 79 /** 80 * Windows glob regex 81 */ 82 83 const WINDOWS_CHARS = { 84 ...POSIX_CHARS, 85 86 SLASH_LITERAL: `[${WIN_SLASH}]`, 87 QMARK: WIN_NO_SLASH, 88 STAR: `${WIN_NO_SLASH}*?`, 89 DOTS_SLASH: `${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$)`, 90 NO_DOT: `(?!${DOT_LITERAL})`, 91 NO_DOTS: `(?!(?:^|[${WIN_SLASH}])${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`, 92 NO_DOT_SLASH: `(?!${DOT_LITERAL}{0,1}(?:[${WIN_SLASH}]|$))`, 93 NO_DOTS_SLASH: `(?!${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`, 94 QMARK_NO_DOT: `[^.${WIN_SLASH}]`, 95 START_ANCHOR: `(?:^|[${WIN_SLASH}])`, 96 END_ANCHOR: `(?:[${WIN_SLASH}]|$)` 97 }; 98 99 /** 100 * POSIX Bracket Regex 101 */ 102 103 const POSIX_REGEX_SOURCE = { 104 alnum: 'a-zA-Z0-9', 105 alpha: 'a-zA-Z', 106 ascii: '\\x00-\\x7F', 107 blank: ' \\t', 108 cntrl: '\\x00-\\x1F\\x7F', 109 digit: '0-9', 110 graph: '\\x21-\\x7E', 111 lower: 'a-z', 112 print: '\\x20-\\x7E ', 113 punct: '\\-!"#$%&\'()\\*+,./:;<=>?@[\\]^_`{|}~', 114 space: ' \\t\\r\\n\\v\\f', 115 upper: 'A-Z', 116 word: 'A-Za-z0-9_', 117 xdigit: 'A-Fa-f0-9' 118 }; 119 120 constants$3 = { 121 MAX_LENGTH: 1024 * 64, 122 POSIX_REGEX_SOURCE, 123 124 // regular expressions 125 REGEX_BACKSLASH: /\\(?![*+?^${}(|)[\]])/g, 126 REGEX_NON_SPECIAL_CHARS: /^[^@![\].,$*+?^{}()|\\/]+/, 127 REGEX_SPECIAL_CHARS: /[-*+?.^${}(|)[\]]/, 128 REGEX_SPECIAL_CHARS_BACKREF: /(\\?)((\W)(\3*))/g, 129 REGEX_SPECIAL_CHARS_GLOBAL: /([-*+?.^${}(|)[\]])/g, 130 REGEX_REMOVE_BACKSLASH: /(?:\[.*?[^\\]\]|\\(?=.))/g, 131 132 // Replace globs with equivalent patterns to reduce parsing time. 133 REPLACEMENTS: { 134 '***': '*', 135 '**/**': '**', 136 '**/**/**': '**' 137 }, 138 139 // Digits 140 CHAR_0: 48, /* 0 */ 141 CHAR_9: 57, /* 9 */ 142 143 // Alphabet chars. 144 CHAR_UPPERCASE_A: 65, /* A */ 145 CHAR_LOWERCASE_A: 97, /* a */ 146 CHAR_UPPERCASE_Z: 90, /* Z */ 147 CHAR_LOWERCASE_Z: 122, /* z */ 148 149 CHAR_LEFT_PARENTHESES: 40, /* ( */ 150 CHAR_RIGHT_PARENTHESES: 41, /* ) */ 151 152 CHAR_ASTERISK: 42, /* * */ 153 154 // Non-alphabetic chars. 155 CHAR_AMPERSAND: 38, /* & */ 156 CHAR_AT: 64, /* @ */ 157 CHAR_BACKWARD_SLASH: 92, /* \ */ 158 CHAR_CARRIAGE_RETURN: 13, /* \r */ 159 CHAR_CIRCUMFLEX_ACCENT: 94, /* ^ */ 160 CHAR_COLON: 58, /* : */ 161 CHAR_COMMA: 44, /* , */ 162 CHAR_DOT: 46, /* . */ 163 CHAR_DOUBLE_QUOTE: 34, /* " */ 164 CHAR_EQUAL: 61, /* = */ 165 CHAR_EXCLAMATION_MARK: 33, /* ! */ 166 CHAR_FORM_FEED: 12, /* \f */ 167 CHAR_FORWARD_SLASH: 47, /* / */ 168 CHAR_GRAVE_ACCENT: 96, /* ` */ 169 CHAR_HASH: 35, /* # */ 170 CHAR_HYPHEN_MINUS: 45, /* - */ 171 CHAR_LEFT_ANGLE_BRACKET: 60, /* < */ 172 CHAR_LEFT_CURLY_BRACE: 123, /* { */ 173 CHAR_LEFT_SQUARE_BRACKET: 91, /* [ */ 174 CHAR_LINE_FEED: 10, /* \n */ 175 CHAR_NO_BREAK_SPACE: 160, /* \u00A0 */ 176 CHAR_PERCENT: 37, /* % */ 177 CHAR_PLUS: 43, /* + */ 178 CHAR_QUESTION_MARK: 63, /* ? */ 179 CHAR_RIGHT_ANGLE_BRACKET: 62, /* > */ 180 CHAR_RIGHT_CURLY_BRACE: 125, /* } */ 181 CHAR_RIGHT_SQUARE_BRACKET: 93, /* ] */ 182 CHAR_SEMICOLON: 59, /* ; */ 183 CHAR_SINGLE_QUOTE: 39, /* ' */ 184 CHAR_SPACE: 32, /* */ 185 CHAR_TAB: 9, /* \t */ 186 CHAR_UNDERSCORE: 95, /* _ */ 187 CHAR_VERTICAL_LINE: 124, /* | */ 188 CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279, /* \uFEFF */ 189 190 SEP: path.sep, 191 192 /** 193 * Create EXTGLOB_CHARS 194 */ 195 196 extglobChars(chars) { 197 return { 198 '!': { type: 'negate', open: '(?:(?!(?:', close: `))${chars.STAR})` }, 199 '?': { type: 'qmark', open: '(?:', close: ')?' }, 200 '+': { type: 'plus', open: '(?:', close: ')+' }, 201 '*': { type: 'star', open: '(?:', close: ')*' }, 202 '@': { type: 'at', open: '(?:', close: ')' } 203 }; 204 }, 205 206 /** 207 * Create GLOB_CHARS 208 */ 209 210 globChars(win32) { 211 return win32 === true ? WINDOWS_CHARS : POSIX_CHARS; 212 } 213 }; 214 return constants$3; 264 215 } 265 216 266 /** 267 * @typedef {Object} ReaddirpArguments 268 * @property {Function=} fileFilter 269 * @property {Function=} directoryFilter 270 * @property {String=} type 271 * @property {Number=} depth 272 * @property {String=} root 273 * @property {Boolean=} lstat 274 * @property {Boolean=} bigint 275 */ 276 277 /** 278 * Main function which ends up calling readdirRec and reads all files and directories in given root recursively. 279 * @param {String} root Root directory 280 * @param {ReaddirpArguments=} options Options to specify root (start directory), filters and recursion depth 281 */ 282 const readdirp$1 = (root, options = {}) => { 283 let type = options.entryType || options.type; 284 if (type === 'both') type = FILE_DIR_TYPE; // backwards-compatibility 285 if (type) options.type = type; 286 if (!root) { 287 throw new Error('readdirp: root argument is required. Usage: readdirp(root, options)'); 288 } else if (typeof root !== 'string') { 289 throw new TypeError('readdirp: root argument must be a string. Usage: readdirp(root, options)'); 290 } else if (type && !ALL_TYPES.includes(type)) { 291 throw new Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(', ')}`); 292 } 293 294 options.root = root; 295 return new ReaddirpStream(options); 296 }; 297 298 const readdirpPromise = (root, options = {}) => { 299 return new Promise((resolve, reject) => { 300 const files = []; 301 readdirp$1(root, options) 302 .on('data', entry => files.push(entry)) 303 .on('end', () => resolve(files)) 304 .on('error', error => reject(error)); 305 }); 306 }; 307 308 readdirp$1.promise = readdirpPromise; 309 readdirp$1.ReaddirpStream = ReaddirpStream; 310 readdirp$1.default = readdirp$1; 311 312 var readdirp_1 = readdirp$1; 313 314 var anymatch$2 = {exports: {}}; 217 var hasRequiredUtils$2; 218 219 function requireUtils$2 () { 220 if (hasRequiredUtils$2) return utils$2; 221 hasRequiredUtils$2 = 1; 222 (function (exports) { 223 224 const path = require$$0$1; 225 const win32 = process.platform === 'win32'; 226 const { 227 REGEX_BACKSLASH, 228 REGEX_REMOVE_BACKSLASH, 229 REGEX_SPECIAL_CHARS, 230 REGEX_SPECIAL_CHARS_GLOBAL 231 } = /*@__PURE__*/ requireConstants$3(); 232 233 exports.isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); 234 exports.hasRegexChars = str => REGEX_SPECIAL_CHARS.test(str); 235 exports.isRegexChar = str => str.length === 1 && exports.hasRegexChars(str); 236 exports.escapeRegex = str => str.replace(REGEX_SPECIAL_CHARS_GLOBAL, '\\$1'); 237 exports.toPosixSlashes = str => str.replace(REGEX_BACKSLASH, '/'); 238 239 exports.removeBackslashes = str => { 240 return str.replace(REGEX_REMOVE_BACKSLASH, match => { 241 return match === '\\' ? '' : match; 242 }); 243 }; 244 245 exports.supportsLookbehinds = () => { 246 const segs = process.version.slice(1).split('.').map(Number); 247 if (segs.length === 3 && segs[0] >= 9 || (segs[0] === 8 && segs[1] >= 10)) { 248 return true; 249 } 250 return false; 251 }; 252 253 exports.isWindows = options => { 254 if (options && typeof options.windows === 'boolean') { 255 return options.windows; 256 } 257 return win32 === true || path.sep === '\\'; 258 }; 259 260 exports.escapeLast = (input, char, lastIdx) => { 261 const idx = input.lastIndexOf(char, lastIdx); 262 if (idx === -1) return input; 263 if (input[idx - 1] === '\\') return exports.escapeLast(input, char, idx - 1); 264 return `${input.slice(0, idx)}\\${input.slice(idx)}`; 265 }; 266 267 exports.removePrefix = (input, state = {}) => { 268 let output = input; 269 if (output.startsWith('./')) { 270 output = output.slice(2); 271 state.prefix = './'; 272 } 273 return output; 274 }; 275 276 exports.wrapOutput = (input, state = {}, options = {}) => { 277 const prepend = options.contains ? '' : '^'; 278 const append = options.contains ? '' : '$'; 279 280 let output = `${prepend}(?:${input})${append}`; 281 if (state.negated === true) { 282 output = `(?:^(?!${output}).*$)`; 283 } 284 return output; 285 }; 286 } (utils$2)); 287 return utils$2; 288 } 289 290 var scan_1$1; 291 var hasRequiredScan$1; 292 293 function requireScan$1 () { 294 if (hasRequiredScan$1) return scan_1$1; 295 hasRequiredScan$1 = 1; 296 297 const utils = /*@__PURE__*/ requireUtils$2(); 298 const { 299 CHAR_ASTERISK, /* * */ 300 CHAR_AT, /* @ */ 301 CHAR_BACKWARD_SLASH, /* \ */ 302 CHAR_COMMA, /* , */ 303 CHAR_DOT, /* . */ 304 CHAR_EXCLAMATION_MARK, /* ! */ 305 CHAR_FORWARD_SLASH, /* / */ 306 CHAR_LEFT_CURLY_BRACE, /* { */ 307 CHAR_LEFT_PARENTHESES, /* ( */ 308 CHAR_LEFT_SQUARE_BRACKET, /* [ */ 309 CHAR_PLUS, /* + */ 310 CHAR_QUESTION_MARK, /* ? */ 311 CHAR_RIGHT_CURLY_BRACE, /* } */ 312 CHAR_RIGHT_PARENTHESES, /* ) */ 313 CHAR_RIGHT_SQUARE_BRACKET /* ] */ 314 } = /*@__PURE__*/ requireConstants$3(); 315 316 const isPathSeparator = code => { 317 return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; 318 }; 319 320 const depth = token => { 321 if (token.isPrefix !== true) { 322 token.depth = token.isGlobstar ? Infinity : 1; 323 } 324 }; 325 326 /** 327 * Quickly scans a glob pattern and returns an object with a handful of 328 * useful properties, like `isGlob`, `path` (the leading non-glob, if it exists), 329 * `glob` (the actual pattern), `negated` (true if the path starts with `!` but not 330 * with `!(`) and `negatedExtglob` (true if the path starts with `!(`). 331 * 332 * ```js 333 * const pm = require('picomatch'); 334 * console.log(pm.scan('foo/bar/*.js')); 335 * { isGlob: true, input: 'foo/bar/*.js', base: 'foo/bar', glob: '*.js' } 336 * ``` 337 * @param {String} `str` 338 * @param {Object} `options` 339 * @return {Object} Returns an object with tokens and regex source string. 340 * @api public 341 */ 342 343 const scan = (input, options) => { 344 const opts = options || {}; 345 346 const length = input.length - 1; 347 const scanToEnd = opts.parts === true || opts.scanToEnd === true; 348 const slashes = []; 349 const tokens = []; 350 const parts = []; 351 352 let str = input; 353 let index = -1; 354 let start = 0; 355 let lastIndex = 0; 356 let isBrace = false; 357 let isBracket = false; 358 let isGlob = false; 359 let isExtglob = false; 360 let isGlobstar = false; 361 let braceEscaped = false; 362 let backslashes = false; 363 let negated = false; 364 let negatedExtglob = false; 365 let finished = false; 366 let braces = 0; 367 let prev; 368 let code; 369 let token = { value: '', depth: 0, isGlob: false }; 370 371 const eos = () => index >= length; 372 const peek = () => str.charCodeAt(index + 1); 373 const advance = () => { 374 prev = code; 375 return str.charCodeAt(++index); 376 }; 377 378 while (index < length) { 379 code = advance(); 380 let next; 381 382 if (code === CHAR_BACKWARD_SLASH) { 383 backslashes = token.backslashes = true; 384 code = advance(); 385 386 if (code === CHAR_LEFT_CURLY_BRACE) { 387 braceEscaped = true; 388 } 389 continue; 390 } 391 392 if (braceEscaped === true || code === CHAR_LEFT_CURLY_BRACE) { 393 braces++; 394 395 while (eos() !== true && (code = advance())) { 396 if (code === CHAR_BACKWARD_SLASH) { 397 backslashes = token.backslashes = true; 398 advance(); 399 continue; 400 } 401 402 if (code === CHAR_LEFT_CURLY_BRACE) { 403 braces++; 404 continue; 405 } 406 407 if (braceEscaped !== true && code === CHAR_DOT && (code = advance()) === CHAR_DOT) { 408 isBrace = token.isBrace = true; 409 isGlob = token.isGlob = true; 410 finished = true; 411 412 if (scanToEnd === true) { 413 continue; 414 } 415 416 break; 417 } 418 419 if (braceEscaped !== true && code === CHAR_COMMA) { 420 isBrace = token.isBrace = true; 421 isGlob = token.isGlob = true; 422 finished = true; 423 424 if (scanToEnd === true) { 425 continue; 426 } 427 428 break; 429 } 430 431 if (code === CHAR_RIGHT_CURLY_BRACE) { 432 braces--; 433 434 if (braces === 0) { 435 braceEscaped = false; 436 isBrace = token.isBrace = true; 437 finished = true; 438 break; 439 } 440 } 441 } 442 443 if (scanToEnd === true) { 444 continue; 445 } 446 447 break; 448 } 449 450 if (code === CHAR_FORWARD_SLASH) { 451 slashes.push(index); 452 tokens.push(token); 453 token = { value: '', depth: 0, isGlob: false }; 454 455 if (finished === true) continue; 456 if (prev === CHAR_DOT && index === (start + 1)) { 457 start += 2; 458 continue; 459 } 460 461 lastIndex = index + 1; 462 continue; 463 } 464 465 if (opts.noext !== true) { 466 const isExtglobChar = code === CHAR_PLUS 467 || code === CHAR_AT 468 || code === CHAR_ASTERISK 469 || code === CHAR_QUESTION_MARK 470 || code === CHAR_EXCLAMATION_MARK; 471 472 if (isExtglobChar === true && peek() === CHAR_LEFT_PARENTHESES) { 473 isGlob = token.isGlob = true; 474 isExtglob = token.isExtglob = true; 475 finished = true; 476 if (code === CHAR_EXCLAMATION_MARK && index === start) { 477 negatedExtglob = true; 478 } 479 480 if (scanToEnd === true) { 481 while (eos() !== true && (code = advance())) { 482 if (code === CHAR_BACKWARD_SLASH) { 483 backslashes = token.backslashes = true; 484 code = advance(); 485 continue; 486 } 487 488 if (code === CHAR_RIGHT_PARENTHESES) { 489 isGlob = token.isGlob = true; 490 finished = true; 491 break; 492 } 493 } 494 continue; 495 } 496 break; 497 } 498 } 499 500 if (code === CHAR_ASTERISK) { 501 if (prev === CHAR_ASTERISK) isGlobstar = token.isGlobstar = true; 502 isGlob = token.isGlob = true; 503 finished = true; 504 505 if (scanToEnd === true) { 506 continue; 507 } 508 break; 509 } 510 511 if (code === CHAR_QUESTION_MARK) { 512 isGlob = token.isGlob = true; 513 finished = true; 514 515 if (scanToEnd === true) { 516 continue; 517 } 518 break; 519 } 520 521 if (code === CHAR_LEFT_SQUARE_BRACKET) { 522 while (eos() !== true && (next = advance())) { 523 if (next === CHAR_BACKWARD_SLASH) { 524 backslashes = token.backslashes = true; 525 advance(); 526 continue; 527 } 528 529 if (next === CHAR_RIGHT_SQUARE_BRACKET) { 530 isBracket = token.isBracket = true; 531 isGlob = token.isGlob = true; 532 finished = true; 533 break; 534 } 535 } 536 537 if (scanToEnd === true) { 538 continue; 539 } 540 541 break; 542 } 543 544 if (opts.nonegate !== true && code === CHAR_EXCLAMATION_MARK && index === start) { 545 negated = token.negated = true; 546 start++; 547 continue; 548 } 549 550 if (opts.noparen !== true && code === CHAR_LEFT_PARENTHESES) { 551 isGlob = token.isGlob = true; 552 553 if (scanToEnd === true) { 554 while (eos() !== true && (code = advance())) { 555 if (code === CHAR_LEFT_PARENTHESES) { 556 backslashes = token.backslashes = true; 557 code = advance(); 558 continue; 559 } 560 561 if (code === CHAR_RIGHT_PARENTHESES) { 562 finished = true; 563 break; 564 } 565 } 566 continue; 567 } 568 break; 569 } 570 571 if (isGlob === true) { 572 finished = true; 573 574 if (scanToEnd === true) { 575 continue; 576 } 577 578 break; 579 } 580 } 581 582 if (opts.noext === true) { 583 isExtglob = false; 584 isGlob = false; 585 } 586 587 let base = str; 588 let prefix = ''; 589 let glob = ''; 590 591 if (start > 0) { 592 prefix = str.slice(0, start); 593 str = str.slice(start); 594 lastIndex -= start; 595 } 596 597 if (base && isGlob === true && lastIndex > 0) { 598 base = str.slice(0, lastIndex); 599 glob = str.slice(lastIndex); 600 } else if (isGlob === true) { 601 base = ''; 602 glob = str; 603 } else { 604 base = str; 605 } 606 607 if (base && base !== '' && base !== '/' && base !== str) { 608 if (isPathSeparator(base.charCodeAt(base.length - 1))) { 609 base = base.slice(0, -1); 610 } 611 } 612 613 if (opts.unescape === true) { 614 if (glob) glob = utils.removeBackslashes(glob); 615 616 if (base && backslashes === true) { 617 base = utils.removeBackslashes(base); 618 } 619 } 620 621 const state = { 622 prefix, 623 input, 624 start, 625 base, 626 glob, 627 isBrace, 628 isBracket, 629 isGlob, 630 isExtglob, 631 isGlobstar, 632 negated, 633 negatedExtglob 634 }; 635 636 if (opts.tokens === true) { 637 state.maxDepth = 0; 638 if (!isPathSeparator(code)) { 639 tokens.push(token); 640 } 641 state.tokens = tokens; 642 } 643 644 if (opts.parts === true || opts.tokens === true) { 645 let prevIndex; 646 647 for (let idx = 0; idx < slashes.length; idx++) { 648 const n = prevIndex ? prevIndex + 1 : start; 649 const i = slashes[idx]; 650 const value = input.slice(n, i); 651 if (opts.tokens) { 652 if (idx === 0 && start !== 0) { 653 tokens[idx].isPrefix = true; 654 tokens[idx].value = prefix; 655 } else { 656 tokens[idx].value = value; 657 } 658 depth(tokens[idx]); 659 state.maxDepth += tokens[idx].depth; 660 } 661 if (idx !== 0 || value !== '') { 662 parts.push(value); 663 } 664 prevIndex = i; 665 } 666 667 if (prevIndex && prevIndex + 1 < input.length) { 668 const value = input.slice(prevIndex + 1); 669 parts.push(value); 670 671 if (opts.tokens) { 672 tokens[tokens.length - 1].value = value; 673 depth(tokens[tokens.length - 1]); 674 state.maxDepth += tokens[tokens.length - 1].depth; 675 } 676 } 677 678 state.slashes = slashes; 679 state.parts = parts; 680 } 681 682 return state; 683 }; 684 685 scan_1$1 = scan; 686 return scan_1$1; 687 } 688 689 var parse_1$2; 690 var hasRequiredParse$2; 691 692 function requireParse$2 () { 693 if (hasRequiredParse$2) return parse_1$2; 694 hasRequiredParse$2 = 1; 695 696 const constants = /*@__PURE__*/ requireConstants$3(); 697 const utils = /*@__PURE__*/ requireUtils$2(); 698 699 /** 700 * Constants 701 */ 702 703 const { 704 MAX_LENGTH, 705 POSIX_REGEX_SOURCE, 706 REGEX_NON_SPECIAL_CHARS, 707 REGEX_SPECIAL_CHARS_BACKREF, 708 REPLACEMENTS 709 } = constants; 710 711 /** 712 * Helpers 713 */ 714 715 const expandRange = (args, options) => { 716 if (typeof options.expandRange === 'function') { 717 return options.expandRange(...args, options); 718 } 719 720 args.sort(); 721 const value = `[${args.join('-')}]`; 722 723 return value; 724 }; 725 726 /** 727 * Create the message for a syntax error 728 */ 729 730 const syntaxError = (type, char) => { 731 return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`; 732 }; 733 734 /** 735 * Parse the given input string. 736 * @param {String} input 737 * @param {Object} options 738 * @return {Object} 739 */ 740 741 const parse = (input, options) => { 742 if (typeof input !== 'string') { 743 throw new TypeError('Expected a string'); 744 } 745 746 input = REPLACEMENTS[input] || input; 747 748 const opts = { ...options }; 749 const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; 750 751 let len = input.length; 752 if (len > max) { 753 throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); 754 } 755 756 const bos = { type: 'bos', value: '', output: opts.prepend || '' }; 757 const tokens = [bos]; 758 759 const capture = opts.capture ? '' : '?:'; 760 const win32 = utils.isWindows(options); 761 762 // create constants based on platform, for windows or posix 763 const PLATFORM_CHARS = constants.globChars(win32); 764 const EXTGLOB_CHARS = constants.extglobChars(PLATFORM_CHARS); 765 766 const { 767 DOT_LITERAL, 768 PLUS_LITERAL, 769 SLASH_LITERAL, 770 ONE_CHAR, 771 DOTS_SLASH, 772 NO_DOT, 773 NO_DOT_SLASH, 774 NO_DOTS_SLASH, 775 QMARK, 776 QMARK_NO_DOT, 777 STAR, 778 START_ANCHOR 779 } = PLATFORM_CHARS; 780 781 const globstar = opts => { 782 return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`; 783 }; 784 785 const nodot = opts.dot ? '' : NO_DOT; 786 const qmarkNoDot = opts.dot ? QMARK : QMARK_NO_DOT; 787 let star = opts.bash === true ? globstar(opts) : STAR; 788 789 if (opts.capture) { 790 star = `(${star})`; 791 } 792 793 // minimatch options support 794 if (typeof opts.noext === 'boolean') { 795 opts.noextglob = opts.noext; 796 } 797 798 const state = { 799 input, 800 index: -1, 801 start: 0, 802 dot: opts.dot === true, 803 consumed: '', 804 output: '', 805 prefix: '', 806 backtrack: false, 807 negated: false, 808 brackets: 0, 809 braces: 0, 810 parens: 0, 811 quotes: 0, 812 globstar: false, 813 tokens 814 }; 815 816 input = utils.removePrefix(input, state); 817 len = input.length; 818 819 const extglobs = []; 820 const braces = []; 821 const stack = []; 822 let prev = bos; 823 let value; 824 825 /** 826 * Tokenizing helpers 827 */ 828 829 const eos = () => state.index === len - 1; 830 const peek = state.peek = (n = 1) => input[state.index + n]; 831 const advance = state.advance = () => input[++state.index] || ''; 832 const remaining = () => input.slice(state.index + 1); 833 const consume = (value = '', num = 0) => { 834 state.consumed += value; 835 state.index += num; 836 }; 837 838 const append = token => { 839 state.output += token.output != null ? token.output : token.value; 840 consume(token.value); 841 }; 842 843 const negate = () => { 844 let count = 1; 845 846 while (peek() === '!' && (peek(2) !== '(' || peek(3) === '?')) { 847 advance(); 848 state.start++; 849 count++; 850 } 851 852 if (count % 2 === 0) { 853 return false; 854 } 855 856 state.negated = true; 857 state.start++; 858 return true; 859 }; 860 861 const increment = type => { 862 state[type]++; 863 stack.push(type); 864 }; 865 866 const decrement = type => { 867 state[type]--; 868 stack.pop(); 869 }; 870 871 /** 872 * Push tokens onto the tokens array. This helper speeds up 873 * tokenizing by 1) helping us avoid backtracking as much as possible, 874 * and 2) helping us avoid creating extra tokens when consecutive 875 * characters are plain text. This improves performance and simplifies 876 * lookbehinds. 877 */ 878 879 const push = tok => { 880 if (prev.type === 'globstar') { 881 const isBrace = state.braces > 0 && (tok.type === 'comma' || tok.type === 'brace'); 882 const isExtglob = tok.extglob === true || (extglobs.length && (tok.type === 'pipe' || tok.type === 'paren')); 883 884 if (tok.type !== 'slash' && tok.type !== 'paren' && !isBrace && !isExtglob) { 885 state.output = state.output.slice(0, -prev.output.length); 886 prev.type = 'star'; 887 prev.value = '*'; 888 prev.output = star; 889 state.output += prev.output; 890 } 891 } 892 893 if (extglobs.length && tok.type !== 'paren') { 894 extglobs[extglobs.length - 1].inner += tok.value; 895 } 896 897 if (tok.value || tok.output) append(tok); 898 if (prev && prev.type === 'text' && tok.type === 'text') { 899 prev.value += tok.value; 900 prev.output = (prev.output || '') + tok.value; 901 return; 902 } 903 904 tok.prev = prev; 905 tokens.push(tok); 906 prev = tok; 907 }; 908 909 const extglobOpen = (type, value) => { 910 const token = { ...EXTGLOB_CHARS[value], conditions: 1, inner: '' }; 911 912 token.prev = prev; 913 token.parens = state.parens; 914 token.output = state.output; 915 const output = (opts.capture ? '(' : '') + token.open; 916 917 increment('parens'); 918 push({ type, value, output: state.output ? '' : ONE_CHAR }); 919 push({ type: 'paren', extglob: true, value: advance(), output }); 920 extglobs.push(token); 921 }; 922 923 const extglobClose = token => { 924 let output = token.close + (opts.capture ? ')' : ''); 925 let rest; 926 927 if (token.type === 'negate') { 928 let extglobStar = star; 929 930 if (token.inner && token.inner.length > 1 && token.inner.includes('/')) { 931 extglobStar = globstar(opts); 932 } 933 934 if (extglobStar !== star || eos() || /^\)+$/.test(remaining())) { 935 output = token.close = `)$))${extglobStar}`; 936 } 937 938 if (token.inner.includes('*') && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) { 939 // Any non-magical string (`.ts`) or even nested expression (`.{ts,tsx}`) can follow after the closing parenthesis. 940 // In this case, we need to parse the string and use it in the output of the original pattern. 941 // Suitable patterns: `/!(*.d).ts`, `/!(*.d).{ts,tsx}`, `**/!(*-dbg).@(js)`. 942 // 943 // Disabling the `fastpaths` option due to a problem with parsing strings as `.ts` in the pattern like `**/!(*.d).ts`. 944 const expression = parse(rest, { ...options, fastpaths: false }).output; 945 946 output = token.close = `)${expression})${extglobStar})`; 947 } 948 949 if (token.prev.type === 'bos') { 950 state.negatedExtglob = true; 951 } 952 } 953 954 push({ type: 'paren', extglob: true, value, output }); 955 decrement('parens'); 956 }; 957 958 /** 959 * Fast paths 960 */ 961 962 if (opts.fastpaths !== false && !/(^[*!]|[/()[\]{}"])/.test(input)) { 963 let backslashes = false; 964 965 let output = input.replace(REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index) => { 966 if (first === '\\') { 967 backslashes = true; 968 return m; 969 } 970 971 if (first === '?') { 972 if (esc) { 973 return esc + first + (rest ? QMARK.repeat(rest.length) : ''); 974 } 975 if (index === 0) { 976 return qmarkNoDot + (rest ? QMARK.repeat(rest.length) : ''); 977 } 978 return QMARK.repeat(chars.length); 979 } 980 981 if (first === '.') { 982 return DOT_LITERAL.repeat(chars.length); 983 } 984 985 if (first === '*') { 986 if (esc) { 987 return esc + first + (rest ? star : ''); 988 } 989 return star; 990 } 991 return esc ? m : `\\${m}`; 992 }); 993 994 if (backslashes === true) { 995 if (opts.unescape === true) { 996 output = output.replace(/\\/g, ''); 997 } else { 998 output = output.replace(/\\+/g, m => { 999 return m.length % 2 === 0 ? '\\\\' : (m ? '\\' : ''); 1000 }); 1001 } 1002 } 1003 1004 if (output === input && opts.contains === true) { 1005 state.output = input; 1006 return state; 1007 } 1008 1009 state.output = utils.wrapOutput(output, state, options); 1010 return state; 1011 } 1012 1013 /** 1014 * Tokenize input until we reach end-of-string 1015 */ 1016 1017 while (!eos()) { 1018 value = advance(); 1019 1020 if (value === '\u0000') { 1021 continue; 1022 } 1023 1024 /** 1025 * Escaped characters 1026 */ 1027 1028 if (value === '\\') { 1029 const next = peek(); 1030 1031 if (next === '/' && opts.bash !== true) { 1032 continue; 1033 } 1034 1035 if (next === '.' || next === ';') { 1036 continue; 1037 } 1038 1039 if (!next) { 1040 value += '\\'; 1041 push({ type: 'text', value }); 1042 continue; 1043 } 1044 1045 // collapse slashes to reduce potential for exploits 1046 const match = /^\\+/.exec(remaining()); 1047 let slashes = 0; 1048 1049 if (match && match[0].length > 2) { 1050 slashes = match[0].length; 1051 state.index += slashes; 1052 if (slashes % 2 !== 0) { 1053 value += '\\'; 1054 } 1055 } 1056 1057 if (opts.unescape === true) { 1058 value = advance(); 1059 } else { 1060 value += advance(); 1061 } 1062 1063 if (state.brackets === 0) { 1064 push({ type: 'text', value }); 1065 continue; 1066 } 1067 } 1068 1069 /** 1070 * If we're inside a regex character class, continue 1071 * until we reach the closing bracket. 1072 */ 1073 1074 if (state.brackets > 0 && (value !== ']' || prev.value === '[' || prev.value === '[^')) { 1075 if (opts.posix !== false && value === ':') { 1076 const inner = prev.value.slice(1); 1077 if (inner.includes('[')) { 1078 prev.posix = true; 1079 1080 if (inner.includes(':')) { 1081 const idx = prev.value.lastIndexOf('['); 1082 const pre = prev.value.slice(0, idx); 1083 const rest = prev.value.slice(idx + 2); 1084 const posix = POSIX_REGEX_SOURCE[rest]; 1085 if (posix) { 1086 prev.value = pre + posix; 1087 state.backtrack = true; 1088 advance(); 1089 1090 if (!bos.output && tokens.indexOf(prev) === 1) { 1091 bos.output = ONE_CHAR; 1092 } 1093 continue; 1094 } 1095 } 1096 } 1097 } 1098 1099 if ((value === '[' && peek() !== ':') || (value === '-' && peek() === ']')) { 1100 value = `\\${value}`; 1101 } 1102 1103 if (value === ']' && (prev.value === '[' || prev.value === '[^')) { 1104 value = `\\${value}`; 1105 } 1106 1107 if (opts.posix === true && value === '!' && prev.value === '[') { 1108 value = '^'; 1109 } 1110 1111 prev.value += value; 1112 append({ value }); 1113 continue; 1114 } 1115 1116 /** 1117 * If we're inside a quoted string, continue 1118 * until we reach the closing double quote. 1119 */ 1120 1121 if (state.quotes === 1 && value !== '"') { 1122 value = utils.escapeRegex(value); 1123 prev.value += value; 1124 append({ value }); 1125 continue; 1126 } 1127 1128 /** 1129 * Double quotes 1130 */ 1131 1132 if (value === '"') { 1133 state.quotes = state.quotes === 1 ? 0 : 1; 1134 if (opts.keepQuotes === true) { 1135 push({ type: 'text', value }); 1136 } 1137 continue; 1138 } 1139 1140 /** 1141 * Parentheses 1142 */ 1143 1144 if (value === '(') { 1145 increment('parens'); 1146 push({ type: 'paren', value }); 1147 continue; 1148 } 1149 1150 if (value === ')') { 1151 if (state.parens === 0 && opts.strictBrackets === true) { 1152 throw new SyntaxError(syntaxError('opening', '(')); 1153 } 1154 1155 const extglob = extglobs[extglobs.length - 1]; 1156 if (extglob && state.parens === extglob.parens + 1) { 1157 extglobClose(extglobs.pop()); 1158 continue; 1159 } 1160 1161 push({ type: 'paren', value, output: state.parens ? ')' : '\\)' }); 1162 decrement('parens'); 1163 continue; 1164 } 1165 1166 /** 1167 * Square brackets 1168 */ 1169 1170 if (value === '[') { 1171 if (opts.nobracket === true || !remaining().includes(']')) { 1172 if (opts.nobracket !== true && opts.strictBrackets === true) { 1173 throw new SyntaxError(syntaxError('closing', ']')); 1174 } 1175 1176 value = `\\${value}`; 1177 } else { 1178 increment('brackets'); 1179 } 1180 1181 push({ type: 'bracket', value }); 1182 continue; 1183 } 1184 1185 if (value === ']') { 1186 if (opts.nobracket === true || (prev && prev.type === 'bracket' && prev.value.length === 1)) { 1187 push({ type: 'text', value, output: `\\${value}` }); 1188 continue; 1189 } 1190 1191 if (state.brackets === 0) { 1192 if (opts.strictBrackets === true) { 1193 throw new SyntaxError(syntaxError('opening', '[')); 1194 } 1195 1196 push({ type: 'text', value, output: `\\${value}` }); 1197 continue; 1198 } 1199 1200 decrement('brackets'); 1201 1202 const prevValue = prev.value.slice(1); 1203 if (prev.posix !== true && prevValue[0] === '^' && !prevValue.includes('/')) { 1204 value = `/${value}`; 1205 } 1206 1207 prev.value += value; 1208 append({ value }); 1209 1210 // when literal brackets are explicitly disabled 1211 // assume we should match with a regex character class 1212 if (opts.literalBrackets === false || utils.hasRegexChars(prevValue)) { 1213 continue; 1214 } 1215 1216 const escaped = utils.escapeRegex(prev.value); 1217 state.output = state.output.slice(0, -prev.value.length); 1218 1219 // when literal brackets are explicitly enabled 1220 // assume we should escape the brackets to match literal characters 1221 if (opts.literalBrackets === true) { 1222 state.output += escaped; 1223 prev.value = escaped; 1224 continue; 1225 } 1226 1227 // when the user specifies nothing, try to match both 1228 prev.value = `(${capture}${escaped}|${prev.value})`; 1229 state.output += prev.value; 1230 continue; 1231 } 1232 1233 /** 1234 * Braces 1235 */ 1236 1237 if (value === '{' && opts.nobrace !== true) { 1238 increment('braces'); 1239 1240 const open = { 1241 type: 'brace', 1242 value, 1243 output: '(', 1244 outputIndex: state.output.length, 1245 tokensIndex: state.tokens.length 1246 }; 1247 1248 braces.push(open); 1249 push(open); 1250 continue; 1251 } 1252 1253 if (value === '}') { 1254 const brace = braces[braces.length - 1]; 1255 1256 if (opts.nobrace === true || !brace) { 1257 push({ type: 'text', value, output: value }); 1258 continue; 1259 } 1260 1261 let output = ')'; 1262 1263 if (brace.dots === true) { 1264 const arr = tokens.slice(); 1265 const range = []; 1266 1267 for (let i = arr.length - 1; i >= 0; i--) { 1268 tokens.pop(); 1269 if (arr[i].type === 'brace') { 1270 break; 1271 } 1272 if (arr[i].type !== 'dots') { 1273 range.unshift(arr[i].value); 1274 } 1275 } 1276 1277 output = expandRange(range, opts); 1278 state.backtrack = true; 1279 } 1280 1281 if (brace.comma !== true && brace.dots !== true) { 1282 const out = state.output.slice(0, brace.outputIndex); 1283 const toks = state.tokens.slice(brace.tokensIndex); 1284 brace.value = brace.output = '\\{'; 1285 value = output = '\\}'; 1286 state.output = out; 1287 for (const t of toks) { 1288 state.output += (t.output || t.value); 1289 } 1290 } 1291 1292 push({ type: 'brace', value, output }); 1293 decrement('braces'); 1294 braces.pop(); 1295 continue; 1296 } 1297 1298 /** 1299 * Pipes 1300 */ 1301 1302 if (value === '|') { 1303 if (extglobs.length > 0) { 1304 extglobs[extglobs.length - 1].conditions++; 1305 } 1306 push({ type: 'text', value }); 1307 continue; 1308 } 1309 1310 /** 1311 * Commas 1312 */ 1313 1314 if (value === ',') { 1315 let output = value; 1316 1317 const brace = braces[braces.length - 1]; 1318 if (brace && stack[stack.length - 1] === 'braces') { 1319 brace.comma = true; 1320 output = '|'; 1321 } 1322 1323 push({ type: 'comma', value, output }); 1324 continue; 1325 } 1326 1327 /** 1328 * Slashes 1329 */ 1330 1331 if (value === '/') { 1332 // if the beginning of the glob is "./", advance the start 1333 // to the current index, and don't add the "./" characters 1334 // to the state. This greatly simplifies lookbehinds when 1335 // checking for BOS characters like "!" and "." (not "./") 1336 if (prev.type === 'dot' && state.index === state.start + 1) { 1337 state.start = state.index + 1; 1338 state.consumed = ''; 1339 state.output = ''; 1340 tokens.pop(); 1341 prev = bos; // reset "prev" to the first token 1342 continue; 1343 } 1344 1345 push({ type: 'slash', value, output: SLASH_LITERAL }); 1346 continue; 1347 } 1348 1349 /** 1350 * Dots 1351 */ 1352 1353 if (value === '.') { 1354 if (state.braces > 0 && prev.type === 'dot') { 1355 if (prev.value === '.') prev.output = DOT_LITERAL; 1356 const brace = braces[braces.length - 1]; 1357 prev.type = 'dots'; 1358 prev.output += value; 1359 prev.value += value; 1360 brace.dots = true; 1361 continue; 1362 } 1363 1364 if ((state.braces + state.parens) === 0 && prev.type !== 'bos' && prev.type !== 'slash') { 1365 push({ type: 'text', value, output: DOT_LITERAL }); 1366 continue; 1367 } 1368 1369 push({ type: 'dot', value, output: DOT_LITERAL }); 1370 continue; 1371 } 1372 1373 /** 1374 * Question marks 1375 */ 1376 1377 if (value === '?') { 1378 const isGroup = prev && prev.value === '('; 1379 if (!isGroup && opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { 1380 extglobOpen('qmark', value); 1381 continue; 1382 } 1383 1384 if (prev && prev.type === 'paren') { 1385 const next = peek(); 1386 let output = value; 1387 1388 if (next === '<' && !utils.supportsLookbehinds()) { 1389 throw new Error('Node.js v10 or higher is required for regex lookbehinds'); 1390 } 1391 1392 if ((prev.value === '(' && !/[!=<:]/.test(next)) || (next === '<' && !/<([!=]|\w+>)/.test(remaining()))) { 1393 output = `\\${value}`; 1394 } 1395 1396 push({ type: 'text', value, output }); 1397 continue; 1398 } 1399 1400 if (opts.dot !== true && (prev.type === 'slash' || prev.type === 'bos')) { 1401 push({ type: 'qmark', value, output: QMARK_NO_DOT }); 1402 continue; 1403 } 1404 1405 push({ type: 'qmark', value, output: QMARK }); 1406 continue; 1407 } 1408 1409 /** 1410 * Exclamation 1411 */ 1412 1413 if (value === '!') { 1414 if (opts.noextglob !== true && peek() === '(') { 1415 if (peek(2) !== '?' || !/[!=<:]/.test(peek(3))) { 1416 extglobOpen('negate', value); 1417 continue; 1418 } 1419 } 1420 1421 if (opts.nonegate !== true && state.index === 0) { 1422 negate(); 1423 continue; 1424 } 1425 } 1426 1427 /** 1428 * Plus 1429 */ 1430 1431 if (value === '+') { 1432 if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { 1433 extglobOpen('plus', value); 1434 continue; 1435 } 1436 1437 if ((prev && prev.value === '(') || opts.regex === false) { 1438 push({ type: 'plus', value, output: PLUS_LITERAL }); 1439 continue; 1440 } 1441 1442 if ((prev && (prev.type === 'bracket' || prev.type === 'paren' || prev.type === 'brace')) || state.parens > 0) { 1443 push({ type: 'plus', value }); 1444 continue; 1445 } 1446 1447 push({ type: 'plus', value: PLUS_LITERAL }); 1448 continue; 1449 } 1450 1451 /** 1452 * Plain text 1453 */ 1454 1455 if (value === '@') { 1456 if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { 1457 push({ type: 'at', extglob: true, value, output: '' }); 1458 continue; 1459 } 1460 1461 push({ type: 'text', value }); 1462 continue; 1463 } 1464 1465 /** 1466 * Plain text 1467 */ 1468 1469 if (value !== '*') { 1470 if (value === '$' || value === '^') { 1471 value = `\\${value}`; 1472 } 1473 1474 const match = REGEX_NON_SPECIAL_CHARS.exec(remaining()); 1475 if (match) { 1476 value += match[0]; 1477 state.index += match[0].length; 1478 } 1479 1480 push({ type: 'text', value }); 1481 continue; 1482 } 1483 1484 /** 1485 * Stars 1486 */ 1487 1488 if (prev && (prev.type === 'globstar' || prev.star === true)) { 1489 prev.type = 'star'; 1490 prev.star = true; 1491 prev.value += value; 1492 prev.output = star; 1493 state.backtrack = true; 1494 state.globstar = true; 1495 consume(value); 1496 continue; 1497 } 1498 1499 let rest = remaining(); 1500 if (opts.noextglob !== true && /^\([^?]/.test(rest)) { 1501 extglobOpen('star', value); 1502 continue; 1503 } 1504 1505 if (prev.type === 'star') { 1506 if (opts.noglobstar === true) { 1507 consume(value); 1508 continue; 1509 } 1510 1511 const prior = prev.prev; 1512 const before = prior.prev; 1513 const isStart = prior.type === 'slash' || prior.type === 'bos'; 1514 const afterStar = before && (before.type === 'star' || before.type === 'globstar'); 1515 1516 if (opts.bash === true && (!isStart || (rest[0] && rest[0] !== '/'))) { 1517 push({ type: 'star', value, output: '' }); 1518 continue; 1519 } 1520 1521 const isBrace = state.braces > 0 && (prior.type === 'comma' || prior.type === 'brace'); 1522 const isExtglob = extglobs.length && (prior.type === 'pipe' || prior.type === 'paren'); 1523 if (!isStart && prior.type !== 'paren' && !isBrace && !isExtglob) { 1524 push({ type: 'star', value, output: '' }); 1525 continue; 1526 } 1527 1528 // strip consecutive `/**/` 1529 while (rest.slice(0, 3) === '/**') { 1530 const after = input[state.index + 4]; 1531 if (after && after !== '/') { 1532 break; 1533 } 1534 rest = rest.slice(3); 1535 consume('/**', 3); 1536 } 1537 1538 if (prior.type === 'bos' && eos()) { 1539 prev.type = 'globstar'; 1540 prev.value += value; 1541 prev.output = globstar(opts); 1542 state.output = prev.output; 1543 state.globstar = true; 1544 consume(value); 1545 continue; 1546 } 1547 1548 if (prior.type === 'slash' && prior.prev.type !== 'bos' && !afterStar && eos()) { 1549 state.output = state.output.slice(0, -(prior.output + prev.output).length); 1550 prior.output = `(?:${prior.output}`; 1551 1552 prev.type = 'globstar'; 1553 prev.output = globstar(opts) + (opts.strictSlashes ? ')' : '|$)'); 1554 prev.value += value; 1555 state.globstar = true; 1556 state.output += prior.output + prev.output; 1557 consume(value); 1558 continue; 1559 } 1560 1561 if (prior.type === 'slash' && prior.prev.type !== 'bos' && rest[0] === '/') { 1562 const end = rest[1] !== void 0 ? '|$' : ''; 1563 1564 state.output = state.output.slice(0, -(prior.output + prev.output).length); 1565 prior.output = `(?:${prior.output}`; 1566 1567 prev.type = 'globstar'; 1568 prev.output = `${globstar(opts)}${SLASH_LITERAL}|${SLASH_LITERAL}${end})`; 1569 prev.value += value; 1570 1571 state.output += prior.output + prev.output; 1572 state.globstar = true; 1573 1574 consume(value + advance()); 1575 1576 push({ type: 'slash', value: '/', output: '' }); 1577 continue; 1578 } 1579 1580 if (prior.type === 'bos' && rest[0] === '/') { 1581 prev.type = 'globstar'; 1582 prev.value += value; 1583 prev.output = `(?:^|${SLASH_LITERAL}|${globstar(opts)}${SLASH_LITERAL})`; 1584 state.output = prev.output; 1585 state.globstar = true; 1586 consume(value + advance()); 1587 push({ type: 'slash', value: '/', output: '' }); 1588 continue; 1589 } 1590 1591 // remove single star from output 1592 state.output = state.output.slice(0, -prev.output.length); 1593 1594 // reset previous token to globstar 1595 prev.type = 'globstar'; 1596 prev.output = globstar(opts); 1597 prev.value += value; 1598 1599 // reset output with globstar 1600 state.output += prev.output; 1601 state.globstar = true; 1602 consume(value); 1603 continue; 1604 } 1605 1606 const token = { type: 'star', value, output: star }; 1607 1608 if (opts.bash === true) { 1609 token.output = '.*?'; 1610 if (prev.type === 'bos' || prev.type === 'slash') { 1611 token.output = nodot + token.output; 1612 } 1613 push(token); 1614 continue; 1615 } 1616 1617 if (prev && (prev.type === 'bracket' || prev.type === 'paren') && opts.regex === true) { 1618 token.output = value; 1619 push(token); 1620 continue; 1621 } 1622 1623 if (state.index === state.start || prev.type === 'slash' || prev.type === 'dot') { 1624 if (prev.type === 'dot') { 1625 state.output += NO_DOT_SLASH; 1626 prev.output += NO_DOT_SLASH; 1627 1628 } else if (opts.dot === true) { 1629 state.output += NO_DOTS_SLASH; 1630 prev.output += NO_DOTS_SLASH; 1631 1632 } else { 1633 state.output += nodot; 1634 prev.output += nodot; 1635 } 1636 1637 if (peek() !== '*') { 1638 state.output += ONE_CHAR; 1639 prev.output += ONE_CHAR; 1640 } 1641 } 1642 1643 push(token); 1644 } 1645 1646 while (state.brackets > 0) { 1647 if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ']')); 1648 state.output = utils.escapeLast(state.output, '['); 1649 decrement('brackets'); 1650 } 1651 1652 while (state.parens > 0) { 1653 if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ')')); 1654 state.output = utils.escapeLast(state.output, '('); 1655 decrement('parens'); 1656 } 1657 1658 while (state.braces > 0) { 1659 if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', '}')); 1660 state.output = utils.escapeLast(state.output, '{'); 1661 decrement('braces'); 1662 } 1663 1664 if (opts.strictSlashes !== true && (prev.type === 'star' || prev.type === 'bracket')) { 1665 push({ type: 'maybe_slash', value: '', output: `${SLASH_LITERAL}?` }); 1666 } 1667 1668 // rebuild the output if we had to backtrack at any point 1669 if (state.backtrack === true) { 1670 state.output = ''; 1671 1672 for (const token of state.tokens) { 1673 state.output += token.output != null ? token.output : token.value; 1674 1675 if (token.suffix) { 1676 state.output += token.suffix; 1677 } 1678 } 1679 } 1680 1681 return state; 1682 }; 1683 1684 /** 1685 * Fast paths for creating regular expressions for common glob patterns. 1686 * This can significantly speed up processing and has very little downside 1687 * impact when none of the fast paths match. 1688 */ 1689 1690 parse.fastpaths = (input, options) => { 1691 const opts = { ...options }; 1692 const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; 1693 const len = input.length; 1694 if (len > max) { 1695 throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); 1696 } 1697 1698 input = REPLACEMENTS[input] || input; 1699 const win32 = utils.isWindows(options); 1700 1701 // create constants based on platform, for windows or posix 1702 const { 1703 DOT_LITERAL, 1704 SLASH_LITERAL, 1705 ONE_CHAR, 1706 DOTS_SLASH, 1707 NO_DOT, 1708 NO_DOTS, 1709 NO_DOTS_SLASH, 1710 STAR, 1711 START_ANCHOR 1712 } = constants.globChars(win32); 1713 1714 const nodot = opts.dot ? NO_DOTS : NO_DOT; 1715 const slashDot = opts.dot ? NO_DOTS_SLASH : NO_DOT; 1716 const capture = opts.capture ? '' : '?:'; 1717 const state = { negated: false, prefix: '' }; 1718 let star = opts.bash === true ? '.*?' : STAR; 1719 1720 if (opts.capture) { 1721 star = `(${star})`; 1722 } 1723 1724 const globstar = opts => { 1725 if (opts.noglobstar === true) return star; 1726 return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`; 1727 }; 1728 1729 const create = str => { 1730 switch (str) { 1731 case '*': 1732 return `${nodot}${ONE_CHAR}${star}`; 1733 1734 case '.*': 1735 return `${DOT_LITERAL}${ONE_CHAR}${star}`; 1736 1737 case '*.*': 1738 return `${nodot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`; 1739 1740 case '*/*': 1741 return `${nodot}${star}${SLASH_LITERAL}${ONE_CHAR}${slashDot}${star}`; 1742 1743 case '**': 1744 return nodot + globstar(opts); 1745 1746 case '**/*': 1747 return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${ONE_CHAR}${star}`; 1748 1749 case '**/*.*': 1750 return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`; 1751 1752 case '**/.*': 1753 return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${DOT_LITERAL}${ONE_CHAR}${star}`; 1754 1755 default: { 1756 const match = /^(.*?)\.(\w+)$/.exec(str); 1757 if (!match) return; 1758 1759 const source = create(match[1]); 1760 if (!source) return; 1761 1762 return source + DOT_LITERAL + match[2]; 1763 } 1764 } 1765 }; 1766 1767 const output = utils.removePrefix(input, state); 1768 let source = create(output); 1769 1770 if (source && opts.strictSlashes !== true) { 1771 source += `${SLASH_LITERAL}?`; 1772 } 1773 1774 return source; 1775 }; 1776 1777 parse_1$2 = parse; 1778 return parse_1$2; 1779 } 1780 1781 var picomatch_1$1; 1782 var hasRequiredPicomatch$3; 1783 1784 function requirePicomatch$3 () { 1785 if (hasRequiredPicomatch$3) return picomatch_1$1; 1786 hasRequiredPicomatch$3 = 1; 1787 1788 const path = require$$0$1; 1789 const scan = /*@__PURE__*/ requireScan$1(); 1790 const parse = /*@__PURE__*/ requireParse$2(); 1791 const utils = /*@__PURE__*/ requireUtils$2(); 1792 const constants = /*@__PURE__*/ requireConstants$3(); 1793 const isObject = val => val && typeof val === 'object' && !Array.isArray(val); 1794 1795 /** 1796 * Creates a matcher function from one or more glob patterns. The 1797 * returned function takes a string to match as its first argument, 1798 * and returns true if the string is a match. The returned matcher 1799 * function also takes a boolean as the second argument that, when true, 1800 * returns an object with additional information. 1801 * 1802 * ```js 1803 * const picomatch = require('picomatch'); 1804 * // picomatch(glob[, options]); 1805 * 1806 * const isMatch = picomatch('*.!(*a)'); 1807 * console.log(isMatch('a.a')); //=> false 1808 * console.log(isMatch('a.b')); //=> true 1809 * ``` 1810 * @name picomatch 1811 * @param {String|Array} `globs` One or more glob patterns. 1812 * @param {Object=} `options` 1813 * @return {Function=} Returns a matcher function. 1814 * @api public 1815 */ 1816 1817 const picomatch = (glob, options, returnState = false) => { 1818 if (Array.isArray(glob)) { 1819 const fns = glob.map(input => picomatch(input, options, returnState)); 1820 const arrayMatcher = str => { 1821 for (const isMatch of fns) { 1822 const state = isMatch(str); 1823 if (state) return state; 1824 } 1825 return false; 1826 }; 1827 return arrayMatcher; 1828 } 1829 1830 const isState = isObject(glob) && glob.tokens && glob.input; 1831 1832 if (glob === '' || (typeof glob !== 'string' && !isState)) { 1833 throw new TypeError('Expected pattern to be a non-empty string'); 1834 } 1835 1836 const opts = options || {}; 1837 const posix = utils.isWindows(options); 1838 const regex = isState 1839 ? picomatch.compileRe(glob, options) 1840 : picomatch.makeRe(glob, options, false, true); 1841 1842 const state = regex.state; 1843 delete regex.state; 1844 1845 let isIgnored = () => false; 1846 if (opts.ignore) { 1847 const ignoreOpts = { ...options, ignore: null, onMatch: null, onResult: null }; 1848 isIgnored = picomatch(opts.ignore, ignoreOpts, returnState); 1849 } 1850 1851 const matcher = (input, returnObject = false) => { 1852 const { isMatch, match, output } = picomatch.test(input, regex, options, { glob, posix }); 1853 const result = { glob, state, regex, posix, input, output, match, isMatch }; 1854 1855 if (typeof opts.onResult === 'function') { 1856 opts.onResult(result); 1857 } 1858 1859 if (isMatch === false) { 1860 result.isMatch = false; 1861 return returnObject ? result : false; 1862 } 1863 1864 if (isIgnored(input)) { 1865 if (typeof opts.onIgnore === 'function') { 1866 opts.onIgnore(result); 1867 } 1868 result.isMatch = false; 1869 return returnObject ? result : false; 1870 } 1871 1872 if (typeof opts.onMatch === 'function') { 1873 opts.onMatch(result); 1874 } 1875 return returnObject ? result : true; 1876 }; 1877 1878 if (returnState) { 1879 matcher.state = state; 1880 } 1881 1882 return matcher; 1883 }; 1884 1885 /** 1886 * Test `input` with the given `regex`. This is used by the main 1887 * `picomatch()` function to test the input string. 1888 * 1889 * ```js 1890 * const picomatch = require('picomatch'); 1891 * // picomatch.test(input, regex[, options]); 1892 * 1893 * console.log(picomatch.test('foo/bar', /^(?:([^/]*?)\/([^/]*?))$/)); 1894 * // { isMatch: true, match: [ 'foo/', 'foo', 'bar' ], output: 'foo/bar' } 1895 * ``` 1896 * @param {String} `input` String to test. 1897 * @param {RegExp} `regex` 1898 * @return {Object} Returns an object with matching info. 1899 * @api public 1900 */ 1901 1902 picomatch.test = (input, regex, options, { glob, posix } = {}) => { 1903 if (typeof input !== 'string') { 1904 throw new TypeError('Expected input to be a string'); 1905 } 1906 1907 if (input === '') { 1908 return { isMatch: false, output: '' }; 1909 } 1910 1911 const opts = options || {}; 1912 const format = opts.format || (posix ? utils.toPosixSlashes : null); 1913 let match = input === glob; 1914 let output = (match && format) ? format(input) : input; 1915 1916 if (match === false) { 1917 output = format ? format(input) : input; 1918 match = output === glob; 1919 } 1920 1921 if (match === false || opts.capture === true) { 1922 if (opts.matchBase === true || opts.basename === true) { 1923 match = picomatch.matchBase(input, regex, options, posix); 1924 } else { 1925 match = regex.exec(output); 1926 } 1927 } 1928 1929 return { isMatch: Boolean(match), match, output }; 1930 }; 1931 1932 /** 1933 * Match the basename of a filepath. 1934 * 1935 * ```js 1936 * const picomatch = require('picomatch'); 1937 * // picomatch.matchBase(input, glob[, options]); 1938 * console.log(picomatch.matchBase('foo/bar.js', '*.js'); // true 1939 * ``` 1940 * @param {String} `input` String to test. 1941 * @param {RegExp|String} `glob` Glob pattern or regex created by [.makeRe](#makeRe). 1942 * @return {Boolean} 1943 * @api public 1944 */ 1945 1946 picomatch.matchBase = (input, glob, options, posix = utils.isWindows(options)) => { 1947 const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options); 1948 return regex.test(path.basename(input)); 1949 }; 1950 1951 /** 1952 * Returns true if **any** of the given glob `patterns` match the specified `string`. 1953 * 1954 * ```js 1955 * const picomatch = require('picomatch'); 1956 * // picomatch.isMatch(string, patterns[, options]); 1957 * 1958 * console.log(picomatch.isMatch('a.a', ['b.*', '*.a'])); //=> true 1959 * console.log(picomatch.isMatch('a.a', 'b.*')); //=> false 1960 * ``` 1961 * @param {String|Array} str The string to test. 1962 * @param {String|Array} patterns One or more glob patterns to use for matching. 1963 * @param {Object} [options] See available [options](#options). 1964 * @return {Boolean} Returns true if any patterns match `str` 1965 * @api public 1966 */ 1967 1968 picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str); 1969 1970 /** 1971 * Parse a glob pattern to create the source string for a regular 1972 * expression. 1973 * 1974 * ```js 1975 * const picomatch = require('picomatch'); 1976 * const result = picomatch.parse(pattern[, options]); 1977 * ``` 1978 * @param {String} `pattern` 1979 * @param {Object} `options` 1980 * @return {Object} Returns an object with useful properties and output to be used as a regex source string. 1981 * @api public 1982 */ 1983 1984 picomatch.parse = (pattern, options) => { 1985 if (Array.isArray(pattern)) return pattern.map(p => picomatch.parse(p, options)); 1986 return parse(pattern, { ...options, fastpaths: false }); 1987 }; 1988 1989 /** 1990 * Scan a glob pattern to separate the pattern into segments. 1991 * 1992 * ```js 1993 * const picomatch = require('picomatch'); 1994 * // picomatch.scan(input[, options]); 1995 * 1996 * const result = picomatch.scan('!./foo/*.js'); 1997 * console.log(result); 1998 * { prefix: '!./', 1999 * input: '!./foo/*.js', 2000 * start: 3, 2001 * base: 'foo', 2002 * glob: '*.js', 2003 * isBrace: false, 2004 * isBracket: false, 2005 * isGlob: true, 2006 * isExtglob: false, 2007 * isGlobstar: false, 2008 * negated: true } 2009 * ``` 2010 * @param {String} `input` Glob pattern to scan. 2011 * @param {Object} `options` 2012 * @return {Object} Returns an object with 2013 * @api public 2014 */ 2015 2016 picomatch.scan = (input, options) => scan(input, options); 2017 2018 /** 2019 * Compile a regular expression from the `state` object returned by the 2020 * [parse()](#parse) method. 2021 * 2022 * @param {Object} `state` 2023 * @param {Object} `options` 2024 * @param {Boolean} `returnOutput` Intended for implementors, this argument allows you to return the raw output from the parser. 2025 * @param {Boolean} `returnState` Adds the state to a `state` property on the returned regex. Useful for implementors and debugging. 2026 * @return {RegExp} 2027 * @api public 2028 */ 2029 2030 picomatch.compileRe = (state, options, returnOutput = false, returnState = false) => { 2031 if (returnOutput === true) { 2032 return state.output; 2033 } 2034 2035 const opts = options || {}; 2036 const prepend = opts.contains ? '' : '^'; 2037 const append = opts.contains ? '' : '$'; 2038 2039 let source = `${prepend}(?:${state.output})${append}`; 2040 if (state && state.negated === true) { 2041 source = `^(?!${source}).*$`; 2042 } 2043 2044 const regex = picomatch.toRegex(source, options); 2045 if (returnState === true) { 2046 regex.state = state; 2047 } 2048 2049 return regex; 2050 }; 2051 2052 /** 2053 * Create a regular expression from a parsed glob pattern. 2054 * 2055 * ```js 2056 * const picomatch = require('picomatch'); 2057 * const state = picomatch.parse('*.js'); 2058 * // picomatch.compileRe(state[, options]); 2059 * 2060 * console.log(picomatch.compileRe(state)); 2061 * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/ 2062 * ``` 2063 * @param {String} `state` The object returned from the `.parse` method. 2064 * @param {Object} `options` 2065 * @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. 2066 * @param {Boolean} `returnState` Implementors may use this argument to return the state from the parsed glob with the returned regular expression. 2067 * @return {RegExp} Returns a regex created from the given pattern. 2068 * @api public 2069 */ 2070 2071 picomatch.makeRe = (input, options = {}, returnOutput = false, returnState = false) => { 2072 if (!input || typeof input !== 'string') { 2073 throw new TypeError('Expected a non-empty string'); 2074 } 2075 2076 let parsed = { negated: false, fastpaths: true }; 2077 2078 if (options.fastpaths !== false && (input[0] === '.' || input[0] === '*')) { 2079 parsed.output = parse.fastpaths(input, options); 2080 } 2081 2082 if (!parsed.output) { 2083 parsed = parse(input, options); 2084 } 2085 2086 return picomatch.compileRe(parsed, options, returnOutput, returnState); 2087 }; 2088 2089 /** 2090 * Create a regular expression from the given regex source string. 2091 * 2092 * ```js 2093 * const picomatch = require('picomatch'); 2094 * // picomatch.toRegex(source[, options]); 2095 * 2096 * const { output } = picomatch.parse('*.js'); 2097 * console.log(picomatch.toRegex(output)); 2098 * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/ 2099 * ``` 2100 * @param {String} `source` Regular expression source string. 2101 * @param {Object} `options` 2102 * @return {RegExp} 2103 * @api public 2104 */ 2105 2106 picomatch.toRegex = (source, options) => { 2107 try { 2108 const opts = options || {}; 2109 return new RegExp(source, opts.flags || (opts.nocase ? 'i' : '')); 2110 } catch (err) { 2111 if (options && options.debug === true) throw err; 2112 return /$^/; 2113 } 2114 }; 2115 2116 /** 2117 * Picomatch constants. 2118 * @return {Object} 2119 */ 2120 2121 picomatch.constants = constants; 2122 2123 /** 2124 * Expose "picomatch" 2125 */ 2126 2127 picomatch_1$1 = picomatch; 2128 return picomatch_1$1; 2129 } 2130 2131 var picomatch$1; 2132 var hasRequiredPicomatch$2; 2133 2134 function requirePicomatch$2 () { 2135 if (hasRequiredPicomatch$2) return picomatch$1; 2136 hasRequiredPicomatch$2 = 1; 2137 2138 picomatch$1 = /*@__PURE__*/ requirePicomatch$3(); 2139 return picomatch$1; 2140 } 2141 2142 var readdirp_1; 2143 var hasRequiredReaddirp; 2144 2145 function requireReaddirp () { 2146 if (hasRequiredReaddirp) return readdirp_1; 2147 hasRequiredReaddirp = 1; 2148 2149 const fs = require$$0$2; 2150 const { Readable } = require$$1; 2151 const sysPath = require$$0$1; 2152 const { promisify } = require$$2; 2153 const picomatch = /*@__PURE__*/ requirePicomatch$2(); 2154 2155 const readdir = promisify(fs.readdir); 2156 const stat = promisify(fs.stat); 2157 const lstat = promisify(fs.lstat); 2158 const realpath = promisify(fs.realpath); 2159 2160 /** 2161 * @typedef {Object} EntryInfo 2162 * @property {String} path 2163 * @property {String} fullPath 2164 * @property {fs.Stats=} stats 2165 * @property {fs.Dirent=} dirent 2166 * @property {String} basename 2167 */ 2168 2169 const BANG = '!'; 2170 const RECURSIVE_ERROR_CODE = 'READDIRP_RECURSIVE_ERROR'; 2171 const NORMAL_FLOW_ERRORS = new Set(['ENOENT', 'EPERM', 'EACCES', 'ELOOP', RECURSIVE_ERROR_CODE]); 2172 const FILE_TYPE = 'files'; 2173 const DIR_TYPE = 'directories'; 2174 const FILE_DIR_TYPE = 'files_directories'; 2175 const EVERYTHING_TYPE = 'all'; 2176 const ALL_TYPES = [FILE_TYPE, DIR_TYPE, FILE_DIR_TYPE, EVERYTHING_TYPE]; 2177 2178 const isNormalFlowError = error => NORMAL_FLOW_ERRORS.has(error.code); 2179 const [maj, min] = process.versions.node.split('.').slice(0, 2).map(n => Number.parseInt(n, 10)); 2180 const wantBigintFsStats = process.platform === 'win32' && (maj > 10 || (maj === 10 && min >= 5)); 2181 2182 const normalizeFilter = filter => { 2183 if (filter === undefined) return; 2184 if (typeof filter === 'function') return filter; 2185 2186 if (typeof filter === 'string') { 2187 const glob = picomatch(filter.trim()); 2188 return entry => glob(entry.basename); 2189 } 2190 2191 if (Array.isArray(filter)) { 2192 const positive = []; 2193 const negative = []; 2194 for (const item of filter) { 2195 const trimmed = item.trim(); 2196 if (trimmed.charAt(0) === BANG) { 2197 negative.push(picomatch(trimmed.slice(1))); 2198 } else { 2199 positive.push(picomatch(trimmed)); 2200 } 2201 } 2202 2203 if (negative.length > 0) { 2204 if (positive.length > 0) { 2205 return entry => 2206 positive.some(f => f(entry.basename)) && !negative.some(f => f(entry.basename)); 2207 } 2208 return entry => !negative.some(f => f(entry.basename)); 2209 } 2210 return entry => positive.some(f => f(entry.basename)); 2211 } 2212 }; 2213 2214 class ReaddirpStream extends Readable { 2215 static get defaultOptions() { 2216 return { 2217 root: '.', 2218 /* eslint-disable no-unused-vars */ 2219 fileFilter: (path) => true, 2220 directoryFilter: (path) => true, 2221 /* eslint-enable no-unused-vars */ 2222 type: FILE_TYPE, 2223 lstat: false, 2224 depth: 2147483648, 2225 alwaysStat: false 2226 }; 2227 } 2228 2229 constructor(options = {}) { 2230 super({ 2231 objectMode: true, 2232 autoDestroy: true, 2233 highWaterMark: options.highWaterMark || 4096 2234 }); 2235 const opts = { ...ReaddirpStream.defaultOptions, ...options }; 2236 const { root, type } = opts; 2237 2238 this._fileFilter = normalizeFilter(opts.fileFilter); 2239 this._directoryFilter = normalizeFilter(opts.directoryFilter); 2240 2241 const statMethod = opts.lstat ? lstat : stat; 2242 // Use bigint stats if it's windows and stat() supports options (node 10+). 2243 if (wantBigintFsStats) { 2244 this._stat = path => statMethod(path, { bigint: true }); 2245 } else { 2246 this._stat = statMethod; 2247 } 2248 2249 this._maxDepth = opts.depth; 2250 this._wantsDir = [DIR_TYPE, FILE_DIR_TYPE, EVERYTHING_TYPE].includes(type); 2251 this._wantsFile = [FILE_TYPE, FILE_DIR_TYPE, EVERYTHING_TYPE].includes(type); 2252 this._wantsEverything = type === EVERYTHING_TYPE; 2253 this._root = sysPath.resolve(root); 2254 this._isDirent = ('Dirent' in fs) && !opts.alwaysStat; 2255 this._statsProp = this._isDirent ? 'dirent' : 'stats'; 2256 this._rdOptions = { encoding: 'utf8', withFileTypes: this._isDirent }; 2257 2258 // Launch stream with one parent, the root dir. 2259 this.parents = [this._exploreDir(root, 1)]; 2260 this.reading = false; 2261 this.parent = undefined; 2262 } 2263 2264 async _read(batch) { 2265 if (this.reading) return; 2266 this.reading = true; 2267 2268 try { 2269 while (!this.destroyed && batch > 0) { 2270 const { path, depth, files = [] } = this.parent || {}; 2271 2272 if (files.length > 0) { 2273 const slice = files.splice(0, batch).map(dirent => this._formatEntry(dirent, path)); 2274 for (const entry of await Promise.all(slice)) { 2275 if (this.destroyed) return; 2276 2277 const entryType = await this._getEntryType(entry); 2278 if (entryType === 'directory' && this._directoryFilter(entry)) { 2279 if (depth <= this._maxDepth) { 2280 this.parents.push(this._exploreDir(entry.fullPath, depth + 1)); 2281 } 2282 2283 if (this._wantsDir) { 2284 this.push(entry); 2285 batch--; 2286 } 2287 } else if ((entryType === 'file' || this._includeAsFile(entry)) && this._fileFilter(entry)) { 2288 if (this._wantsFile) { 2289 this.push(entry); 2290 batch--; 2291 } 2292 } 2293 } 2294 } else { 2295 const parent = this.parents.pop(); 2296 if (!parent) { 2297 this.push(null); 2298 break; 2299 } 2300 this.parent = await parent; 2301 if (this.destroyed) return; 2302 } 2303 } 2304 } catch (error) { 2305 this.destroy(error); 2306 } finally { 2307 this.reading = false; 2308 } 2309 } 2310 2311 async _exploreDir(path, depth) { 2312 let files; 2313 try { 2314 files = await readdir(path, this._rdOptions); 2315 } catch (error) { 2316 this._onError(error); 2317 } 2318 return { files, depth, path }; 2319 } 2320 2321 async _formatEntry(dirent, path) { 2322 let entry; 2323 try { 2324 const basename = this._isDirent ? dirent.name : dirent; 2325 const fullPath = sysPath.resolve(sysPath.join(path, basename)); 2326 entry = { path: sysPath.relative(this._root, fullPath), fullPath, basename }; 2327 entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath); 2328 } catch (err) { 2329 this._onError(err); 2330 } 2331 return entry; 2332 } 2333 2334 _onError(err) { 2335 if (isNormalFlowError(err) && !this.destroyed) { 2336 this.emit('warn', err); 2337 } else { 2338 this.destroy(err); 2339 } 2340 } 2341 2342 async _getEntryType(entry) { 2343 // entry may be undefined, because a warning or an error were emitted 2344 // and the statsProp is undefined 2345 const stats = entry && entry[this._statsProp]; 2346 if (!stats) { 2347 return; 2348 } 2349 if (stats.isFile()) { 2350 return 'file'; 2351 } 2352 if (stats.isDirectory()) { 2353 return 'directory'; 2354 } 2355 if (stats && stats.isSymbolicLink()) { 2356 const full = entry.fullPath; 2357 try { 2358 const entryRealPath = await realpath(full); 2359 const entryRealPathStats = await lstat(entryRealPath); 2360 if (entryRealPathStats.isFile()) { 2361 return 'file'; 2362 } 2363 if (entryRealPathStats.isDirectory()) { 2364 const len = entryRealPath.length; 2365 if (full.startsWith(entryRealPath) && full.substr(len, 1) === sysPath.sep) { 2366 const recursiveError = new Error( 2367 `Circular symlink detected: "${full}" points to "${entryRealPath}"` 2368 ); 2369 recursiveError.code = RECURSIVE_ERROR_CODE; 2370 return this._onError(recursiveError); 2371 } 2372 return 'directory'; 2373 } 2374 } catch (error) { 2375 this._onError(error); 2376 } 2377 } 2378 } 2379 2380 _includeAsFile(entry) { 2381 const stats = entry && entry[this._statsProp]; 2382 2383 return stats && this._wantsEverything && !stats.isDirectory(); 2384 } 2385 } 2386 2387 /** 2388 * @typedef {Object} ReaddirpArguments 2389 * @property {Function=} fileFilter 2390 * @property {Function=} directoryFilter 2391 * @property {String=} type 2392 * @property {Number=} depth 2393 * @property {String=} root 2394 * @property {Boolean=} lstat 2395 * @property {Boolean=} bigint 2396 */ 2397 2398 /** 2399 * Main function which ends up calling readdirRec and reads all files and directories in given root recursively. 2400 * @param {String} root Root directory 2401 * @param {ReaddirpArguments=} options Options to specify root (start directory), filters and recursion depth 2402 */ 2403 const readdirp = (root, options = {}) => { 2404 let type = options.entryType || options.type; 2405 if (type === 'both') type = FILE_DIR_TYPE; // backwards-compatibility 2406 if (type) options.type = type; 2407 if (!root) { 2408 throw new Error('readdirp: root argument is required. Usage: readdirp(root, options)'); 2409 } else if (typeof root !== 'string') { 2410 throw new TypeError('readdirp: root argument must be a string. Usage: readdirp(root, options)'); 2411 } else if (type && !ALL_TYPES.includes(type)) { 2412 throw new Error(`readdirp: Invalid type passed. Use one of ${ALL_TYPES.join(', ')}`); 2413 } 2414 2415 options.root = root; 2416 return new ReaddirpStream(options); 2417 }; 2418 2419 const readdirpPromise = (root, options = {}) => { 2420 return new Promise((resolve, reject) => { 2421 const files = []; 2422 readdirp(root, options) 2423 .on('data', entry => files.push(entry)) 2424 .on('end', () => resolve(files)) 2425 .on('error', error => reject(error)); 2426 }); 2427 }; 2428 2429 readdirp.promise = readdirpPromise; 2430 readdirp.ReaddirpStream = ReaddirpStream; 2431 readdirp.default = readdirp; 2432 2433 readdirp_1 = readdirp; 2434 return readdirp_1; 2435 } 2436 2437 var anymatch = {exports: {}}; 2438 2439 var utils$1 = {}; 2440 2441 var constants$2; 2442 var hasRequiredConstants$2; 2443 2444 function requireConstants$2 () { 2445 if (hasRequiredConstants$2) return constants$2; 2446 hasRequiredConstants$2 = 1; 2447 2448 const path = require$$0$1; 2449 const WIN_SLASH = '\\\\/'; 2450 const WIN_NO_SLASH = `[^${WIN_SLASH}]`; 2451 2452 /** 2453 * Posix glob regex 2454 */ 2455 2456 const DOT_LITERAL = '\\.'; 2457 const PLUS_LITERAL = '\\+'; 2458 const QMARK_LITERAL = '\\?'; 2459 const SLASH_LITERAL = '\\/'; 2460 const ONE_CHAR = '(?=.)'; 2461 const QMARK = '[^/]'; 2462 const END_ANCHOR = `(?:${SLASH_LITERAL}|$)`; 2463 const START_ANCHOR = `(?:^|${SLASH_LITERAL})`; 2464 const DOTS_SLASH = `${DOT_LITERAL}{1,2}${END_ANCHOR}`; 2465 const NO_DOT = `(?!${DOT_LITERAL})`; 2466 const NO_DOTS = `(?!${START_ANCHOR}${DOTS_SLASH})`; 2467 const NO_DOT_SLASH = `(?!${DOT_LITERAL}{0,1}${END_ANCHOR})`; 2468 const NO_DOTS_SLASH = `(?!${DOTS_SLASH})`; 2469 const QMARK_NO_DOT = `[^.${SLASH_LITERAL}]`; 2470 const STAR = `${QMARK}*?`; 2471 2472 const POSIX_CHARS = { 2473 DOT_LITERAL, 2474 PLUS_LITERAL, 2475 QMARK_LITERAL, 2476 SLASH_LITERAL, 2477 ONE_CHAR, 2478 QMARK, 2479 END_ANCHOR, 2480 DOTS_SLASH, 2481 NO_DOT, 2482 NO_DOTS, 2483 NO_DOT_SLASH, 2484 NO_DOTS_SLASH, 2485 QMARK_NO_DOT, 2486 STAR, 2487 START_ANCHOR 2488 }; 2489 2490 /** 2491 * Windows glob regex 2492 */ 2493 2494 const WINDOWS_CHARS = { 2495 ...POSIX_CHARS, 2496 2497 SLASH_LITERAL: `[${WIN_SLASH}]`, 2498 QMARK: WIN_NO_SLASH, 2499 STAR: `${WIN_NO_SLASH}*?`, 2500 DOTS_SLASH: `${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$)`, 2501 NO_DOT: `(?!${DOT_LITERAL})`, 2502 NO_DOTS: `(?!(?:^|[${WIN_SLASH}])${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`, 2503 NO_DOT_SLASH: `(?!${DOT_LITERAL}{0,1}(?:[${WIN_SLASH}]|$))`, 2504 NO_DOTS_SLASH: `(?!${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`, 2505 QMARK_NO_DOT: `[^.${WIN_SLASH}]`, 2506 START_ANCHOR: `(?:^|[${WIN_SLASH}])`, 2507 END_ANCHOR: `(?:[${WIN_SLASH}]|$)` 2508 }; 2509 2510 /** 2511 * POSIX Bracket Regex 2512 */ 2513 2514 const POSIX_REGEX_SOURCE = { 2515 alnum: 'a-zA-Z0-9', 2516 alpha: 'a-zA-Z', 2517 ascii: '\\x00-\\x7F', 2518 blank: ' \\t', 2519 cntrl: '\\x00-\\x1F\\x7F', 2520 digit: '0-9', 2521 graph: '\\x21-\\x7E', 2522 lower: 'a-z', 2523 print: '\\x20-\\x7E ', 2524 punct: '\\-!"#$%&\'()\\*+,./:;<=>?@[\\]^_`{|}~', 2525 space: ' \\t\\r\\n\\v\\f', 2526 upper: 'A-Z', 2527 word: 'A-Za-z0-9_', 2528 xdigit: 'A-Fa-f0-9' 2529 }; 2530 2531 constants$2 = { 2532 MAX_LENGTH: 1024 * 64, 2533 POSIX_REGEX_SOURCE, 2534 2535 // regular expressions 2536 REGEX_BACKSLASH: /\\(?![*+?^${}(|)[\]])/g, 2537 REGEX_NON_SPECIAL_CHARS: /^[^@![\].,$*+?^{}()|\\/]+/, 2538 REGEX_SPECIAL_CHARS: /[-*+?.^${}(|)[\]]/, 2539 REGEX_SPECIAL_CHARS_BACKREF: /(\\?)((\W)(\3*))/g, 2540 REGEX_SPECIAL_CHARS_GLOBAL: /([-*+?.^${}(|)[\]])/g, 2541 REGEX_REMOVE_BACKSLASH: /(?:\[.*?[^\\]\]|\\(?=.))/g, 2542 2543 // Replace globs with equivalent patterns to reduce parsing time. 2544 REPLACEMENTS: { 2545 '***': '*', 2546 '**/**': '**', 2547 '**/**/**': '**' 2548 }, 2549 2550 // Digits 2551 CHAR_0: 48, /* 0 */ 2552 CHAR_9: 57, /* 9 */ 2553 2554 // Alphabet chars. 2555 CHAR_UPPERCASE_A: 65, /* A */ 2556 CHAR_LOWERCASE_A: 97, /* a */ 2557 CHAR_UPPERCASE_Z: 90, /* Z */ 2558 CHAR_LOWERCASE_Z: 122, /* z */ 2559 2560 CHAR_LEFT_PARENTHESES: 40, /* ( */ 2561 CHAR_RIGHT_PARENTHESES: 41, /* ) */ 2562 2563 CHAR_ASTERISK: 42, /* * */ 2564 2565 // Non-alphabetic chars. 2566 CHAR_AMPERSAND: 38, /* & */ 2567 CHAR_AT: 64, /* @ */ 2568 CHAR_BACKWARD_SLASH: 92, /* \ */ 2569 CHAR_CARRIAGE_RETURN: 13, /* \r */ 2570 CHAR_CIRCUMFLEX_ACCENT: 94, /* ^ */ 2571 CHAR_COLON: 58, /* : */ 2572 CHAR_COMMA: 44, /* , */ 2573 CHAR_DOT: 46, /* . */ 2574 CHAR_DOUBLE_QUOTE: 34, /* " */ 2575 CHAR_EQUAL: 61, /* = */ 2576 CHAR_EXCLAMATION_MARK: 33, /* ! */ 2577 CHAR_FORM_FEED: 12, /* \f */ 2578 CHAR_FORWARD_SLASH: 47, /* / */ 2579 CHAR_GRAVE_ACCENT: 96, /* ` */ 2580 CHAR_HASH: 35, /* # */ 2581 CHAR_HYPHEN_MINUS: 45, /* - */ 2582 CHAR_LEFT_ANGLE_BRACKET: 60, /* < */ 2583 CHAR_LEFT_CURLY_BRACE: 123, /* { */ 2584 CHAR_LEFT_SQUARE_BRACKET: 91, /* [ */ 2585 CHAR_LINE_FEED: 10, /* \n */ 2586 CHAR_NO_BREAK_SPACE: 160, /* \u00A0 */ 2587 CHAR_PERCENT: 37, /* % */ 2588 CHAR_PLUS: 43, /* + */ 2589 CHAR_QUESTION_MARK: 63, /* ? */ 2590 CHAR_RIGHT_ANGLE_BRACKET: 62, /* > */ 2591 CHAR_RIGHT_CURLY_BRACE: 125, /* } */ 2592 CHAR_RIGHT_SQUARE_BRACKET: 93, /* ] */ 2593 CHAR_SEMICOLON: 59, /* ; */ 2594 CHAR_SINGLE_QUOTE: 39, /* ' */ 2595 CHAR_SPACE: 32, /* */ 2596 CHAR_TAB: 9, /* \t */ 2597 CHAR_UNDERSCORE: 95, /* _ */ 2598 CHAR_VERTICAL_LINE: 124, /* | */ 2599 CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279, /* \uFEFF */ 2600 2601 SEP: path.sep, 2602 2603 /** 2604 * Create EXTGLOB_CHARS 2605 */ 2606 2607 extglobChars(chars) { 2608 return { 2609 '!': { type: 'negate', open: '(?:(?!(?:', close: `))${chars.STAR})` }, 2610 '?': { type: 'qmark', open: '(?:', close: ')?' }, 2611 '+': { type: 'plus', open: '(?:', close: ')+' }, 2612 '*': { type: 'star', open: '(?:', close: ')*' }, 2613 '@': { type: 'at', open: '(?:', close: ')' } 2614 }; 2615 }, 2616 2617 /** 2618 * Create GLOB_CHARS 2619 */ 2620 2621 globChars(win32) { 2622 return win32 === true ? WINDOWS_CHARS : POSIX_CHARS; 2623 } 2624 }; 2625 return constants$2; 2626 } 2627 2628 var hasRequiredUtils$1; 2629 2630 function requireUtils$1 () { 2631 if (hasRequiredUtils$1) return utils$1; 2632 hasRequiredUtils$1 = 1; 2633 (function (exports) { 2634 2635 const path = require$$0$1; 2636 const win32 = process.platform === 'win32'; 2637 const { 2638 REGEX_BACKSLASH, 2639 REGEX_REMOVE_BACKSLASH, 2640 REGEX_SPECIAL_CHARS, 2641 REGEX_SPECIAL_CHARS_GLOBAL 2642 } = /*@__PURE__*/ requireConstants$2(); 2643 2644 exports.isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); 2645 exports.hasRegexChars = str => REGEX_SPECIAL_CHARS.test(str); 2646 exports.isRegexChar = str => str.length === 1 && exports.hasRegexChars(str); 2647 exports.escapeRegex = str => str.replace(REGEX_SPECIAL_CHARS_GLOBAL, '\\$1'); 2648 exports.toPosixSlashes = str => str.replace(REGEX_BACKSLASH, '/'); 2649 2650 exports.removeBackslashes = str => { 2651 return str.replace(REGEX_REMOVE_BACKSLASH, match => { 2652 return match === '\\' ? '' : match; 2653 }); 2654 }; 2655 2656 exports.supportsLookbehinds = () => { 2657 const segs = process.version.slice(1).split('.').map(Number); 2658 if (segs.length === 3 && segs[0] >= 9 || (segs[0] === 8 && segs[1] >= 10)) { 2659 return true; 2660 } 2661 return false; 2662 }; 2663 2664 exports.isWindows = options => { 2665 if (options && typeof options.windows === 'boolean') { 2666 return options.windows; 2667 } 2668 return win32 === true || path.sep === '\\'; 2669 }; 2670 2671 exports.escapeLast = (input, char, lastIdx) => { 2672 const idx = input.lastIndexOf(char, lastIdx); 2673 if (idx === -1) return input; 2674 if (input[idx - 1] === '\\') return exports.escapeLast(input, char, idx - 1); 2675 return `${input.slice(0, idx)}\\${input.slice(idx)}`; 2676 }; 2677 2678 exports.removePrefix = (input, state = {}) => { 2679 let output = input; 2680 if (output.startsWith('./')) { 2681 output = output.slice(2); 2682 state.prefix = './'; 2683 } 2684 return output; 2685 }; 2686 2687 exports.wrapOutput = (input, state = {}, options = {}) => { 2688 const prepend = options.contains ? '' : '^'; 2689 const append = options.contains ? '' : '$'; 2690 2691 let output = `${prepend}(?:${input})${append}`; 2692 if (state.negated === true) { 2693 output = `(?:^(?!${output}).*$)`; 2694 } 2695 return output; 2696 }; 2697 } (utils$1)); 2698 return utils$1; 2699 } 2700 2701 var scan_1; 2702 var hasRequiredScan; 2703 2704 function requireScan () { 2705 if (hasRequiredScan) return scan_1; 2706 hasRequiredScan = 1; 2707 2708 const utils = /*@__PURE__*/ requireUtils$1(); 2709 const { 2710 CHAR_ASTERISK, /* * */ 2711 CHAR_AT, /* @ */ 2712 CHAR_BACKWARD_SLASH, /* \ */ 2713 CHAR_COMMA, /* , */ 2714 CHAR_DOT, /* . */ 2715 CHAR_EXCLAMATION_MARK, /* ! */ 2716 CHAR_FORWARD_SLASH, /* / */ 2717 CHAR_LEFT_CURLY_BRACE, /* { */ 2718 CHAR_LEFT_PARENTHESES, /* ( */ 2719 CHAR_LEFT_SQUARE_BRACKET, /* [ */ 2720 CHAR_PLUS, /* + */ 2721 CHAR_QUESTION_MARK, /* ? */ 2722 CHAR_RIGHT_CURLY_BRACE, /* } */ 2723 CHAR_RIGHT_PARENTHESES, /* ) */ 2724 CHAR_RIGHT_SQUARE_BRACKET /* ] */ 2725 } = /*@__PURE__*/ requireConstants$2(); 2726 2727 const isPathSeparator = code => { 2728 return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; 2729 }; 2730 2731 const depth = token => { 2732 if (token.isPrefix !== true) { 2733 token.depth = token.isGlobstar ? Infinity : 1; 2734 } 2735 }; 2736 2737 /** 2738 * Quickly scans a glob pattern and returns an object with a handful of 2739 * useful properties, like `isGlob`, `path` (the leading non-glob, if it exists), 2740 * `glob` (the actual pattern), `negated` (true if the path starts with `!` but not 2741 * with `!(`) and `negatedExtglob` (true if the path starts with `!(`). 2742 * 2743 * ```js 2744 * const pm = require('picomatch'); 2745 * console.log(pm.scan('foo/bar/*.js')); 2746 * { isGlob: true, input: 'foo/bar/*.js', base: 'foo/bar', glob: '*.js' } 2747 * ``` 2748 * @param {String} `str` 2749 * @param {Object} `options` 2750 * @return {Object} Returns an object with tokens and regex source string. 2751 * @api public 2752 */ 2753 2754 const scan = (input, options) => { 2755 const opts = options || {}; 2756 2757 const length = input.length - 1; 2758 const scanToEnd = opts.parts === true || opts.scanToEnd === true; 2759 const slashes = []; 2760 const tokens = []; 2761 const parts = []; 2762 2763 let str = input; 2764 let index = -1; 2765 let start = 0; 2766 let lastIndex = 0; 2767 let isBrace = false; 2768 let isBracket = false; 2769 let isGlob = false; 2770 let isExtglob = false; 2771 let isGlobstar = false; 2772 let braceEscaped = false; 2773 let backslashes = false; 2774 let negated = false; 2775 let negatedExtglob = false; 2776 let finished = false; 2777 let braces = 0; 2778 let prev; 2779 let code; 2780 let token = { value: '', depth: 0, isGlob: false }; 2781 2782 const eos = () => index >= length; 2783 const peek = () => str.charCodeAt(index + 1); 2784 const advance = () => { 2785 prev = code; 2786 return str.charCodeAt(++index); 2787 }; 2788 2789 while (index < length) { 2790 code = advance(); 2791 let next; 2792 2793 if (code === CHAR_BACKWARD_SLASH) { 2794 backslashes = token.backslashes = true; 2795 code = advance(); 2796 2797 if (code === CHAR_LEFT_CURLY_BRACE) { 2798 braceEscaped = true; 2799 } 2800 continue; 2801 } 2802 2803 if (braceEscaped === true || code === CHAR_LEFT_CURLY_BRACE) { 2804 braces++; 2805 2806 while (eos() !== true && (code = advance())) { 2807 if (code === CHAR_BACKWARD_SLASH) { 2808 backslashes = token.backslashes = true; 2809 advance(); 2810 continue; 2811 } 2812 2813 if (code === CHAR_LEFT_CURLY_BRACE) { 2814 braces++; 2815 continue; 2816 } 2817 2818 if (braceEscaped !== true && code === CHAR_DOT && (code = advance()) === CHAR_DOT) { 2819 isBrace = token.isBrace = true; 2820 isGlob = token.isGlob = true; 2821 finished = true; 2822 2823 if (scanToEnd === true) { 2824 continue; 2825 } 2826 2827 break; 2828 } 2829 2830 if (braceEscaped !== true && code === CHAR_COMMA) { 2831 isBrace = token.isBrace = true; 2832 isGlob = token.isGlob = true; 2833 finished = true; 2834 2835 if (scanToEnd === true) { 2836 continue; 2837 } 2838 2839 break; 2840 } 2841 2842 if (code === CHAR_RIGHT_CURLY_BRACE) { 2843 braces--; 2844 2845 if (braces === 0) { 2846 braceEscaped = false; 2847 isBrace = token.isBrace = true; 2848 finished = true; 2849 break; 2850 } 2851 } 2852 } 2853 2854 if (scanToEnd === true) { 2855 continue; 2856 } 2857 2858 break; 2859 } 2860 2861 if (code === CHAR_FORWARD_SLASH) { 2862 slashes.push(index); 2863 tokens.push(token); 2864 token = { value: '', depth: 0, isGlob: false }; 2865 2866 if (finished === true) continue; 2867 if (prev === CHAR_DOT && index === (start + 1)) { 2868 start += 2; 2869 continue; 2870 } 2871 2872 lastIndex = index + 1; 2873 continue; 2874 } 2875 2876 if (opts.noext !== true) { 2877 const isExtglobChar = code === CHAR_PLUS 2878 || code === CHAR_AT 2879 || code === CHAR_ASTERISK 2880 || code === CHAR_QUESTION_MARK 2881 || code === CHAR_EXCLAMATION_MARK; 2882 2883 if (isExtglobChar === true && peek() === CHAR_LEFT_PARENTHESES) { 2884 isGlob = token.isGlob = true; 2885 isExtglob = token.isExtglob = true; 2886 finished = true; 2887 if (code === CHAR_EXCLAMATION_MARK && index === start) { 2888 negatedExtglob = true; 2889 } 2890 2891 if (scanToEnd === true) { 2892 while (eos() !== true && (code = advance())) { 2893 if (code === CHAR_BACKWARD_SLASH) { 2894 backslashes = token.backslashes = true; 2895 code = advance(); 2896 continue; 2897 } 2898 2899 if (code === CHAR_RIGHT_PARENTHESES) { 2900 isGlob = token.isGlob = true; 2901 finished = true; 2902 break; 2903 } 2904 } 2905 continue; 2906 } 2907 break; 2908 } 2909 } 2910 2911 if (code === CHAR_ASTERISK) { 2912 if (prev === CHAR_ASTERISK) isGlobstar = token.isGlobstar = true; 2913 isGlob = token.isGlob = true; 2914 finished = true; 2915 2916 if (scanToEnd === true) { 2917 continue; 2918 } 2919 break; 2920 } 2921 2922 if (code === CHAR_QUESTION_MARK) { 2923 isGlob = token.isGlob = true; 2924 finished = true; 2925 2926 if (scanToEnd === true) { 2927 continue; 2928 } 2929 break; 2930 } 2931 2932 if (code === CHAR_LEFT_SQUARE_BRACKET) { 2933 while (eos() !== true && (next = advance())) { 2934 if (next === CHAR_BACKWARD_SLASH) { 2935 backslashes = token.backslashes = true; 2936 advance(); 2937 continue; 2938 } 2939 2940 if (next === CHAR_RIGHT_SQUARE_BRACKET) { 2941 isBracket = token.isBracket = true; 2942 isGlob = token.isGlob = true; 2943 finished = true; 2944 break; 2945 } 2946 } 2947 2948 if (scanToEnd === true) { 2949 continue; 2950 } 2951 2952 break; 2953 } 2954 2955 if (opts.nonegate !== true && code === CHAR_EXCLAMATION_MARK && index === start) { 2956 negated = token.negated = true; 2957 start++; 2958 continue; 2959 } 2960 2961 if (opts.noparen !== true && code === CHAR_LEFT_PARENTHESES) { 2962 isGlob = token.isGlob = true; 2963 2964 if (scanToEnd === true) { 2965 while (eos() !== true && (code = advance())) { 2966 if (code === CHAR_LEFT_PARENTHESES) { 2967 backslashes = token.backslashes = true; 2968 code = advance(); 2969 continue; 2970 } 2971 2972 if (code === CHAR_RIGHT_PARENTHESES) { 2973 finished = true; 2974 break; 2975 } 2976 } 2977 continue; 2978 } 2979 break; 2980 } 2981 2982 if (isGlob === true) { 2983 finished = true; 2984 2985 if (scanToEnd === true) { 2986 continue; 2987 } 2988 2989 break; 2990 } 2991 } 2992 2993 if (opts.noext === true) { 2994 isExtglob = false; 2995 isGlob = false; 2996 } 2997 2998 let base = str; 2999 let prefix = ''; 3000 let glob = ''; 3001 3002 if (start > 0) { 3003 prefix = str.slice(0, start); 3004 str = str.slice(start); 3005 lastIndex -= start; 3006 } 3007 3008 if (base && isGlob === true && lastIndex > 0) { 3009 base = str.slice(0, lastIndex); 3010 glob = str.slice(lastIndex); 3011 } else if (isGlob === true) { 3012 base = ''; 3013 glob = str; 3014 } else { 3015 base = str; 3016 } 3017 3018 if (base && base !== '' && base !== '/' && base !== str) { 3019 if (isPathSeparator(base.charCodeAt(base.length - 1))) { 3020 base = base.slice(0, -1); 3021 } 3022 } 3023 3024 if (opts.unescape === true) { 3025 if (glob) glob = utils.removeBackslashes(glob); 3026 3027 if (base && backslashes === true) { 3028 base = utils.removeBackslashes(base); 3029 } 3030 } 3031 3032 const state = { 3033 prefix, 3034 input, 3035 start, 3036 base, 3037 glob, 3038 isBrace, 3039 isBracket, 3040 isGlob, 3041 isExtglob, 3042 isGlobstar, 3043 negated, 3044 negatedExtglob 3045 }; 3046 3047 if (opts.tokens === true) { 3048 state.maxDepth = 0; 3049 if (!isPathSeparator(code)) { 3050 tokens.push(token); 3051 } 3052 state.tokens = tokens; 3053 } 3054 3055 if (opts.parts === true || opts.tokens === true) { 3056 let prevIndex; 3057 3058 for (let idx = 0; idx < slashes.length; idx++) { 3059 const n = prevIndex ? prevIndex + 1 : start; 3060 const i = slashes[idx]; 3061 const value = input.slice(n, i); 3062 if (opts.tokens) { 3063 if (idx === 0 && start !== 0) { 3064 tokens[idx].isPrefix = true; 3065 tokens[idx].value = prefix; 3066 } else { 3067 tokens[idx].value = value; 3068 } 3069 depth(tokens[idx]); 3070 state.maxDepth += tokens[idx].depth; 3071 } 3072 if (idx !== 0 || value !== '') { 3073 parts.push(value); 3074 } 3075 prevIndex = i; 3076 } 3077 3078 if (prevIndex && prevIndex + 1 < input.length) { 3079 const value = input.slice(prevIndex + 1); 3080 parts.push(value); 3081 3082 if (opts.tokens) { 3083 tokens[tokens.length - 1].value = value; 3084 depth(tokens[tokens.length - 1]); 3085 state.maxDepth += tokens[tokens.length - 1].depth; 3086 } 3087 } 3088 3089 state.slashes = slashes; 3090 state.parts = parts; 3091 } 3092 3093 return state; 3094 }; 3095 3096 scan_1 = scan; 3097 return scan_1; 3098 } 3099 3100 var parse_1$1; 3101 var hasRequiredParse$1; 3102 3103 function requireParse$1 () { 3104 if (hasRequiredParse$1) return parse_1$1; 3105 hasRequiredParse$1 = 1; 3106 3107 const constants = /*@__PURE__*/ requireConstants$2(); 3108 const utils = /*@__PURE__*/ requireUtils$1(); 3109 3110 /** 3111 * Constants 3112 */ 3113 3114 const { 3115 MAX_LENGTH, 3116 POSIX_REGEX_SOURCE, 3117 REGEX_NON_SPECIAL_CHARS, 3118 REGEX_SPECIAL_CHARS_BACKREF, 3119 REPLACEMENTS 3120 } = constants; 3121 3122 /** 3123 * Helpers 3124 */ 3125 3126 const expandRange = (args, options) => { 3127 if (typeof options.expandRange === 'function') { 3128 return options.expandRange(...args, options); 3129 } 3130 3131 args.sort(); 3132 const value = `[${args.join('-')}]`; 3133 3134 return value; 3135 }; 3136 3137 /** 3138 * Create the message for a syntax error 3139 */ 3140 3141 const syntaxError = (type, char) => { 3142 return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`; 3143 }; 3144 3145 /** 3146 * Parse the given input string. 3147 * @param {String} input 3148 * @param {Object} options 3149 * @return {Object} 3150 */ 3151 3152 const parse = (input, options) => { 3153 if (typeof input !== 'string') { 3154 throw new TypeError('Expected a string'); 3155 } 3156 3157 input = REPLACEMENTS[input] || input; 3158 3159 const opts = { ...options }; 3160 const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; 3161 3162 let len = input.length; 3163 if (len > max) { 3164 throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); 3165 } 3166 3167 const bos = { type: 'bos', value: '', output: opts.prepend || '' }; 3168 const tokens = [bos]; 3169 3170 const capture = opts.capture ? '' : '?:'; 3171 const win32 = utils.isWindows(options); 3172 3173 // create constants based on platform, for windows or posix 3174 const PLATFORM_CHARS = constants.globChars(win32); 3175 const EXTGLOB_CHARS = constants.extglobChars(PLATFORM_CHARS); 3176 3177 const { 3178 DOT_LITERAL, 3179 PLUS_LITERAL, 3180 SLASH_LITERAL, 3181 ONE_CHAR, 3182 DOTS_SLASH, 3183 NO_DOT, 3184 NO_DOT_SLASH, 3185 NO_DOTS_SLASH, 3186 QMARK, 3187 QMARK_NO_DOT, 3188 STAR, 3189 START_ANCHOR 3190 } = PLATFORM_CHARS; 3191 3192 const globstar = opts => { 3193 return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`; 3194 }; 3195 3196 const nodot = opts.dot ? '' : NO_DOT; 3197 const qmarkNoDot = opts.dot ? QMARK : QMARK_NO_DOT; 3198 let star = opts.bash === true ? globstar(opts) : STAR; 3199 3200 if (opts.capture) { 3201 star = `(${star})`; 3202 } 3203 3204 // minimatch options support 3205 if (typeof opts.noext === 'boolean') { 3206 opts.noextglob = opts.noext; 3207 } 3208 3209 const state = { 3210 input, 3211 index: -1, 3212 start: 0, 3213 dot: opts.dot === true, 3214 consumed: '', 3215 output: '', 3216 prefix: '', 3217 backtrack: false, 3218 negated: false, 3219 brackets: 0, 3220 braces: 0, 3221 parens: 0, 3222 quotes: 0, 3223 globstar: false, 3224 tokens 3225 }; 3226 3227 input = utils.removePrefix(input, state); 3228 len = input.length; 3229 3230 const extglobs = []; 3231 const braces = []; 3232 const stack = []; 3233 let prev = bos; 3234 let value; 3235 3236 /** 3237 * Tokenizing helpers 3238 */ 3239 3240 const eos = () => state.index === len - 1; 3241 const peek = state.peek = (n = 1) => input[state.index + n]; 3242 const advance = state.advance = () => input[++state.index] || ''; 3243 const remaining = () => input.slice(state.index + 1); 3244 const consume = (value = '', num = 0) => { 3245 state.consumed += value; 3246 state.index += num; 3247 }; 3248 3249 const append = token => { 3250 state.output += token.output != null ? token.output : token.value; 3251 consume(token.value); 3252 }; 3253 3254 const negate = () => { 3255 let count = 1; 3256 3257 while (peek() === '!' && (peek(2) !== '(' || peek(3) === '?')) { 3258 advance(); 3259 state.start++; 3260 count++; 3261 } 3262 3263 if (count % 2 === 0) { 3264 return false; 3265 } 3266 3267 state.negated = true; 3268 state.start++; 3269 return true; 3270 }; 3271 3272 const increment = type => { 3273 state[type]++; 3274 stack.push(type); 3275 }; 3276 3277 const decrement = type => { 3278 state[type]--; 3279 stack.pop(); 3280 }; 3281 3282 /** 3283 * Push tokens onto the tokens array. This helper speeds up 3284 * tokenizing by 1) helping us avoid backtracking as much as possible, 3285 * and 2) helping us avoid creating extra tokens when consecutive 3286 * characters are plain text. This improves performance and simplifies 3287 * lookbehinds. 3288 */ 3289 3290 const push = tok => { 3291 if (prev.type === 'globstar') { 3292 const isBrace = state.braces > 0 && (tok.type === 'comma' || tok.type === 'brace'); 3293 const isExtglob = tok.extglob === true || (extglobs.length && (tok.type === 'pipe' || tok.type === 'paren')); 3294 3295 if (tok.type !== 'slash' && tok.type !== 'paren' && !isBrace && !isExtglob) { 3296 state.output = state.output.slice(0, -prev.output.length); 3297 prev.type = 'star'; 3298 prev.value = '*'; 3299 prev.output = star; 3300 state.output += prev.output; 3301 } 3302 } 3303 3304 if (extglobs.length && tok.type !== 'paren') { 3305 extglobs[extglobs.length - 1].inner += tok.value; 3306 } 3307 3308 if (tok.value || tok.output) append(tok); 3309 if (prev && prev.type === 'text' && tok.type === 'text') { 3310 prev.value += tok.value; 3311 prev.output = (prev.output || '') + tok.value; 3312 return; 3313 } 3314 3315 tok.prev = prev; 3316 tokens.push(tok); 3317 prev = tok; 3318 }; 3319 3320 const extglobOpen = (type, value) => { 3321 const token = { ...EXTGLOB_CHARS[value], conditions: 1, inner: '' }; 3322 3323 token.prev = prev; 3324 token.parens = state.parens; 3325 token.output = state.output; 3326 const output = (opts.capture ? '(' : '') + token.open; 3327 3328 increment('parens'); 3329 push({ type, value, output: state.output ? '' : ONE_CHAR }); 3330 push({ type: 'paren', extglob: true, value: advance(), output }); 3331 extglobs.push(token); 3332 }; 3333 3334 const extglobClose = token => { 3335 let output = token.close + (opts.capture ? ')' : ''); 3336 let rest; 3337 3338 if (token.type === 'negate') { 3339 let extglobStar = star; 3340 3341 if (token.inner && token.inner.length > 1 && token.inner.includes('/')) { 3342 extglobStar = globstar(opts); 3343 } 3344 3345 if (extglobStar !== star || eos() || /^\)+$/.test(remaining())) { 3346 output = token.close = `)$))${extglobStar}`; 3347 } 3348 3349 if (token.inner.includes('*') && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) { 3350 // Any non-magical string (`.ts`) or even nested expression (`.{ts,tsx}`) can follow after the closing parenthesis. 3351 // In this case, we need to parse the string and use it in the output of the original pattern. 3352 // Suitable patterns: `/!(*.d).ts`, `/!(*.d).{ts,tsx}`, `**/!(*-dbg).@(js)`. 3353 // 3354 // Disabling the `fastpaths` option due to a problem with parsing strings as `.ts` in the pattern like `**/!(*.d).ts`. 3355 const expression = parse(rest, { ...options, fastpaths: false }).output; 3356 3357 output = token.close = `)${expression})${extglobStar})`; 3358 } 3359 3360 if (token.prev.type === 'bos') { 3361 state.negatedExtglob = true; 3362 } 3363 } 3364 3365 push({ type: 'paren', extglob: true, value, output }); 3366 decrement('parens'); 3367 }; 3368 3369 /** 3370 * Fast paths 3371 */ 3372 3373 if (opts.fastpaths !== false && !/(^[*!]|[/()[\]{}"])/.test(input)) { 3374 let backslashes = false; 3375 3376 let output = input.replace(REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index) => { 3377 if (first === '\\') { 3378 backslashes = true; 3379 return m; 3380 } 3381 3382 if (first === '?') { 3383 if (esc) { 3384 return esc + first + (rest ? QMARK.repeat(rest.length) : ''); 3385 } 3386 if (index === 0) { 3387 return qmarkNoDot + (rest ? QMARK.repeat(rest.length) : ''); 3388 } 3389 return QMARK.repeat(chars.length); 3390 } 3391 3392 if (first === '.') { 3393 return DOT_LITERAL.repeat(chars.length); 3394 } 3395 3396 if (first === '*') { 3397 if (esc) { 3398 return esc + first + (rest ? star : ''); 3399 } 3400 return star; 3401 } 3402 return esc ? m : `\\${m}`; 3403 }); 3404 3405 if (backslashes === true) { 3406 if (opts.unescape === true) { 3407 output = output.replace(/\\/g, ''); 3408 } else { 3409 output = output.replace(/\\+/g, m => { 3410 return m.length % 2 === 0 ? '\\\\' : (m ? '\\' : ''); 3411 }); 3412 } 3413 } 3414 3415 if (output === input && opts.contains === true) { 3416 state.output = input; 3417 return state; 3418 } 3419 3420 state.output = utils.wrapOutput(output, state, options); 3421 return state; 3422 } 3423 3424 /** 3425 * Tokenize input until we reach end-of-string 3426 */ 3427 3428 while (!eos()) { 3429 value = advance(); 3430 3431 if (value === '\u0000') { 3432 continue; 3433 } 3434 3435 /** 3436 * Escaped characters 3437 */ 3438 3439 if (value === '\\') { 3440 const next = peek(); 3441 3442 if (next === '/' && opts.bash !== true) { 3443 continue; 3444 } 3445 3446 if (next === '.' || next === ';') { 3447 continue; 3448 } 3449 3450 if (!next) { 3451 value += '\\'; 3452 push({ type: 'text', value }); 3453 continue; 3454 } 3455 3456 // collapse slashes to reduce potential for exploits 3457 const match = /^\\+/.exec(remaining()); 3458 let slashes = 0; 3459 3460 if (match && match[0].length > 2) { 3461 slashes = match[0].length; 3462 state.index += slashes; 3463 if (slashes % 2 !== 0) { 3464 value += '\\'; 3465 } 3466 } 3467 3468 if (opts.unescape === true) { 3469 value = advance(); 3470 } else { 3471 value += advance(); 3472 } 3473 3474 if (state.brackets === 0) { 3475 push({ type: 'text', value }); 3476 continue; 3477 } 3478 } 3479 3480 /** 3481 * If we're inside a regex character class, continue 3482 * until we reach the closing bracket. 3483 */ 3484 3485 if (state.brackets > 0 && (value !== ']' || prev.value === '[' || prev.value === '[^')) { 3486 if (opts.posix !== false && value === ':') { 3487 const inner = prev.value.slice(1); 3488 if (inner.includes('[')) { 3489 prev.posix = true; 3490 3491 if (inner.includes(':')) { 3492 const idx = prev.value.lastIndexOf('['); 3493 const pre = prev.value.slice(0, idx); 3494 const rest = prev.value.slice(idx + 2); 3495 const posix = POSIX_REGEX_SOURCE[rest]; 3496 if (posix) { 3497 prev.value = pre + posix; 3498 state.backtrack = true; 3499 advance(); 3500 3501 if (!bos.output && tokens.indexOf(prev) === 1) { 3502 bos.output = ONE_CHAR; 3503 } 3504 continue; 3505 } 3506 } 3507 } 3508 } 3509 3510 if ((value === '[' && peek() !== ':') || (value === '-' && peek() === ']')) { 3511 value = `\\${value}`; 3512 } 3513 3514 if (value === ']' && (prev.value === '[' || prev.value === '[^')) { 3515 value = `\\${value}`; 3516 } 3517 3518 if (opts.posix === true && value === '!' && prev.value === '[') { 3519 value = '^'; 3520 } 3521 3522 prev.value += value; 3523 append({ value }); 3524 continue; 3525 } 3526 3527 /** 3528 * If we're inside a quoted string, continue 3529 * until we reach the closing double quote. 3530 */ 3531 3532 if (state.quotes === 1 && value !== '"') { 3533 value = utils.escapeRegex(value); 3534 prev.value += value; 3535 append({ value }); 3536 continue; 3537 } 3538 3539 /** 3540 * Double quotes 3541 */ 3542 3543 if (value === '"') { 3544 state.quotes = state.quotes === 1 ? 0 : 1; 3545 if (opts.keepQuotes === true) { 3546 push({ type: 'text', value }); 3547 } 3548 continue; 3549 } 3550 3551 /** 3552 * Parentheses 3553 */ 3554 3555 if (value === '(') { 3556 increment('parens'); 3557 push({ type: 'paren', value }); 3558 continue; 3559 } 3560 3561 if (value === ')') { 3562 if (state.parens === 0 && opts.strictBrackets === true) { 3563 throw new SyntaxError(syntaxError('opening', '(')); 3564 } 3565 3566 const extglob = extglobs[extglobs.length - 1]; 3567 if (extglob && state.parens === extglob.parens + 1) { 3568 extglobClose(extglobs.pop()); 3569 continue; 3570 } 3571 3572 push({ type: 'paren', value, output: state.parens ? ')' : '\\)' }); 3573 decrement('parens'); 3574 continue; 3575 } 3576 3577 /** 3578 * Square brackets 3579 */ 3580 3581 if (value === '[') { 3582 if (opts.nobracket === true || !remaining().includes(']')) { 3583 if (opts.nobracket !== true && opts.strictBrackets === true) { 3584 throw new SyntaxError(syntaxError('closing', ']')); 3585 } 3586 3587 value = `\\${value}`; 3588 } else { 3589 increment('brackets'); 3590 } 3591 3592 push({ type: 'bracket', value }); 3593 continue; 3594 } 3595 3596 if (value === ']') { 3597 if (opts.nobracket === true || (prev && prev.type === 'bracket' && prev.value.length === 1)) { 3598 push({ type: 'text', value, output: `\\${value}` }); 3599 continue; 3600 } 3601 3602 if (state.brackets === 0) { 3603 if (opts.strictBrackets === true) { 3604 throw new SyntaxError(syntaxError('opening', '[')); 3605 } 3606 3607 push({ type: 'text', value, output: `\\${value}` }); 3608 continue; 3609 } 3610 3611 decrement('brackets'); 3612 3613 const prevValue = prev.value.slice(1); 3614 if (prev.posix !== true && prevValue[0] === '^' && !prevValue.includes('/')) { 3615 value = `/${value}`; 3616 } 3617 3618 prev.value += value; 3619 append({ value }); 3620 3621 // when literal brackets are explicitly disabled 3622 // assume we should match with a regex character class 3623 if (opts.literalBrackets === false || utils.hasRegexChars(prevValue)) { 3624 continue; 3625 } 3626 3627 const escaped = utils.escapeRegex(prev.value); 3628 state.output = state.output.slice(0, -prev.value.length); 3629 3630 // when literal brackets are explicitly enabled 3631 // assume we should escape the brackets to match literal characters 3632 if (opts.literalBrackets === true) { 3633 state.output += escaped; 3634 prev.value = escaped; 3635 continue; 3636 } 3637 3638 // when the user specifies nothing, try to match both 3639 prev.value = `(${capture}${escaped}|${prev.value})`; 3640 state.output += prev.value; 3641 continue; 3642 } 3643 3644 /** 3645 * Braces 3646 */ 3647 3648 if (value === '{' && opts.nobrace !== true) { 3649 increment('braces'); 3650 3651 const open = { 3652 type: 'brace', 3653 value, 3654 output: '(', 3655 outputIndex: state.output.length, 3656 tokensIndex: state.tokens.length 3657 }; 3658 3659 braces.push(open); 3660 push(open); 3661 continue; 3662 } 3663 3664 if (value === '}') { 3665 const brace = braces[braces.length - 1]; 3666 3667 if (opts.nobrace === true || !brace) { 3668 push({ type: 'text', value, output: value }); 3669 continue; 3670 } 3671 3672 let output = ')'; 3673 3674 if (brace.dots === true) { 3675 const arr = tokens.slice(); 3676 const range = []; 3677 3678 for (let i = arr.length - 1; i >= 0; i--) { 3679 tokens.pop(); 3680 if (arr[i].type === 'brace') { 3681 break; 3682 } 3683 if (arr[i].type !== 'dots') { 3684 range.unshift(arr[i].value); 3685 } 3686 } 3687 3688 output = expandRange(range, opts); 3689 state.backtrack = true; 3690 } 3691 3692 if (brace.comma !== true && brace.dots !== true) { 3693 const out = state.output.slice(0, brace.outputIndex); 3694 const toks = state.tokens.slice(brace.tokensIndex); 3695 brace.value = brace.output = '\\{'; 3696 value = output = '\\}'; 3697 state.output = out; 3698 for (const t of toks) { 3699 state.output += (t.output || t.value); 3700 } 3701 } 3702 3703 push({ type: 'brace', value, output }); 3704 decrement('braces'); 3705 braces.pop(); 3706 continue; 3707 } 3708 3709 /** 3710 * Pipes 3711 */ 3712 3713 if (value === '|') { 3714 if (extglobs.length > 0) { 3715 extglobs[extglobs.length - 1].conditions++; 3716 } 3717 push({ type: 'text', value }); 3718 continue; 3719 } 3720 3721 /** 3722 * Commas 3723 */ 3724 3725 if (value === ',') { 3726 let output = value; 3727 3728 const brace = braces[braces.length - 1]; 3729 if (brace && stack[stack.length - 1] === 'braces') { 3730 brace.comma = true; 3731 output = '|'; 3732 } 3733 3734 push({ type: 'comma', value, output }); 3735 continue; 3736 } 3737 3738 /** 3739 * Slashes 3740 */ 3741 3742 if (value === '/') { 3743 // if the beginning of the glob is "./", advance the start 3744 // to the current index, and don't add the "./" characters 3745 // to the state. This greatly simplifies lookbehinds when 3746 // checking for BOS characters like "!" and "." (not "./") 3747 if (prev.type === 'dot' && state.index === state.start + 1) { 3748 state.start = state.index + 1; 3749 state.consumed = ''; 3750 state.output = ''; 3751 tokens.pop(); 3752 prev = bos; // reset "prev" to the first token 3753 continue; 3754 } 3755 3756 push({ type: 'slash', value, output: SLASH_LITERAL }); 3757 continue; 3758 } 3759 3760 /** 3761 * Dots 3762 */ 3763 3764 if (value === '.') { 3765 if (state.braces > 0 && prev.type === 'dot') { 3766 if (prev.value === '.') prev.output = DOT_LITERAL; 3767 const brace = braces[braces.length - 1]; 3768 prev.type = 'dots'; 3769 prev.output += value; 3770 prev.value += value; 3771 brace.dots = true; 3772 continue; 3773 } 3774 3775 if ((state.braces + state.parens) === 0 && prev.type !== 'bos' && prev.type !== 'slash') { 3776 push({ type: 'text', value, output: DOT_LITERAL }); 3777 continue; 3778 } 3779 3780 push({ type: 'dot', value, output: DOT_LITERAL }); 3781 continue; 3782 } 3783 3784 /** 3785 * Question marks 3786 */ 3787 3788 if (value === '?') { 3789 const isGroup = prev && prev.value === '('; 3790 if (!isGroup && opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { 3791 extglobOpen('qmark', value); 3792 continue; 3793 } 3794 3795 if (prev && prev.type === 'paren') { 3796 const next = peek(); 3797 let output = value; 3798 3799 if (next === '<' && !utils.supportsLookbehinds()) { 3800 throw new Error('Node.js v10 or higher is required for regex lookbehinds'); 3801 } 3802 3803 if ((prev.value === '(' && !/[!=<:]/.test(next)) || (next === '<' && !/<([!=]|\w+>)/.test(remaining()))) { 3804 output = `\\${value}`; 3805 } 3806 3807 push({ type: 'text', value, output }); 3808 continue; 3809 } 3810 3811 if (opts.dot !== true && (prev.type === 'slash' || prev.type === 'bos')) { 3812 push({ type: 'qmark', value, output: QMARK_NO_DOT }); 3813 continue; 3814 } 3815 3816 push({ type: 'qmark', value, output: QMARK }); 3817 continue; 3818 } 3819 3820 /** 3821 * Exclamation 3822 */ 3823 3824 if (value === '!') { 3825 if (opts.noextglob !== true && peek() === '(') { 3826 if (peek(2) !== '?' || !/[!=<:]/.test(peek(3))) { 3827 extglobOpen('negate', value); 3828 continue; 3829 } 3830 } 3831 3832 if (opts.nonegate !== true && state.index === 0) { 3833 negate(); 3834 continue; 3835 } 3836 } 3837 3838 /** 3839 * Plus 3840 */ 3841 3842 if (value === '+') { 3843 if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { 3844 extglobOpen('plus', value); 3845 continue; 3846 } 3847 3848 if ((prev && prev.value === '(') || opts.regex === false) { 3849 push({ type: 'plus', value, output: PLUS_LITERAL }); 3850 continue; 3851 } 3852 3853 if ((prev && (prev.type === 'bracket' || prev.type === 'paren' || prev.type === 'brace')) || state.parens > 0) { 3854 push({ type: 'plus', value }); 3855 continue; 3856 } 3857 3858 push({ type: 'plus', value: PLUS_LITERAL }); 3859 continue; 3860 } 3861 3862 /** 3863 * Plain text 3864 */ 3865 3866 if (value === '@') { 3867 if (opts.noextglob !== true && peek() === '(' && peek(2) !== '?') { 3868 push({ type: 'at', extglob: true, value, output: '' }); 3869 continue; 3870 } 3871 3872 push({ type: 'text', value }); 3873 continue; 3874 } 3875 3876 /** 3877 * Plain text 3878 */ 3879 3880 if (value !== '*') { 3881 if (value === '$' || value === '^') { 3882 value = `\\${value}`; 3883 } 3884 3885 const match = REGEX_NON_SPECIAL_CHARS.exec(remaining()); 3886 if (match) { 3887 value += match[0]; 3888 state.index += match[0].length; 3889 } 3890 3891 push({ type: 'text', value }); 3892 continue; 3893 } 3894 3895 /** 3896 * Stars 3897 */ 3898 3899 if (prev && (prev.type === 'globstar' || prev.star === true)) { 3900 prev.type = 'star'; 3901 prev.star = true; 3902 prev.value += value; 3903 prev.output = star; 3904 state.backtrack = true; 3905 state.globstar = true; 3906 consume(value); 3907 continue; 3908 } 3909 3910 let rest = remaining(); 3911 if (opts.noextglob !== true && /^\([^?]/.test(rest)) { 3912 extglobOpen('star', value); 3913 continue; 3914 } 3915 3916 if (prev.type === 'star') { 3917 if (opts.noglobstar === true) { 3918 consume(value); 3919 continue; 3920 } 3921 3922 const prior = prev.prev; 3923 const before = prior.prev; 3924 const isStart = prior.type === 'slash' || prior.type === 'bos'; 3925 const afterStar = before && (before.type === 'star' || before.type === 'globstar'); 3926 3927 if (opts.bash === true && (!isStart || (rest[0] && rest[0] !== '/'))) { 3928 push({ type: 'star', value, output: '' }); 3929 continue; 3930 } 3931 3932 const isBrace = state.braces > 0 && (prior.type === 'comma' || prior.type === 'brace'); 3933 const isExtglob = extglobs.length && (prior.type === 'pipe' || prior.type === 'paren'); 3934 if (!isStart && prior.type !== 'paren' && !isBrace && !isExtglob) { 3935 push({ type: 'star', value, output: '' }); 3936 continue; 3937 } 3938 3939 // strip consecutive `/**/` 3940 while (rest.slice(0, 3) === '/**') { 3941 const after = input[state.index + 4]; 3942 if (after && after !== '/') { 3943 break; 3944 } 3945 rest = rest.slice(3); 3946 consume('/**', 3); 3947 } 3948 3949 if (prior.type === 'bos' && eos()) { 3950 prev.type = 'globstar'; 3951 prev.value += value; 3952 prev.output = globstar(opts); 3953 state.output = prev.output; 3954 state.globstar = true; 3955 consume(value); 3956 continue; 3957 } 3958 3959 if (prior.type === 'slash' && prior.prev.type !== 'bos' && !afterStar && eos()) { 3960 state.output = state.output.slice(0, -(prior.output + prev.output).length); 3961 prior.output = `(?:${prior.output}`; 3962 3963 prev.type = 'globstar'; 3964 prev.output = globstar(opts) + (opts.strictSlashes ? ')' : '|$)'); 3965 prev.value += value; 3966 state.globstar = true; 3967 state.output += prior.output + prev.output; 3968 consume(value); 3969 continue; 3970 } 3971 3972 if (prior.type === 'slash' && prior.prev.type !== 'bos' && rest[0] === '/') { 3973 const end = rest[1] !== void 0 ? '|$' : ''; 3974 3975 state.output = state.output.slice(0, -(prior.output + prev.output).length); 3976 prior.output = `(?:${prior.output}`; 3977 3978 prev.type = 'globstar'; 3979 prev.output = `${globstar(opts)}${SLASH_LITERAL}|${SLASH_LITERAL}${end})`; 3980 prev.value += value; 3981 3982 state.output += prior.output + prev.output; 3983 state.globstar = true; 3984 3985 consume(value + advance()); 3986 3987 push({ type: 'slash', value: '/', output: '' }); 3988 continue; 3989 } 3990 3991 if (prior.type === 'bos' && rest[0] === '/') { 3992 prev.type = 'globstar'; 3993 prev.value += value; 3994 prev.output = `(?:^|${SLASH_LITERAL}|${globstar(opts)}${SLASH_LITERAL})`; 3995 state.output = prev.output; 3996 state.globstar = true; 3997 consume(value + advance()); 3998 push({ type: 'slash', value: '/', output: '' }); 3999 continue; 4000 } 4001 4002 // remove single star from output 4003 state.output = state.output.slice(0, -prev.output.length); 4004 4005 // reset previous token to globstar 4006 prev.type = 'globstar'; 4007 prev.output = globstar(opts); 4008 prev.value += value; 4009 4010 // reset output with globstar 4011 state.output += prev.output; 4012 state.globstar = true; 4013 consume(value); 4014 continue; 4015 } 4016 4017 const token = { type: 'star', value, output: star }; 4018 4019 if (opts.bash === true) { 4020 token.output = '.*?'; 4021 if (prev.type === 'bos' || prev.type === 'slash') { 4022 token.output = nodot + token.output; 4023 } 4024 push(token); 4025 continue; 4026 } 4027 4028 if (prev && (prev.type === 'bracket' || prev.type === 'paren') && opts.regex === true) { 4029 token.output = value; 4030 push(token); 4031 continue; 4032 } 4033 4034 if (state.index === state.start || prev.type === 'slash' || prev.type === 'dot') { 4035 if (prev.type === 'dot') { 4036 state.output += NO_DOT_SLASH; 4037 prev.output += NO_DOT_SLASH; 4038 4039 } else if (opts.dot === true) { 4040 state.output += NO_DOTS_SLASH; 4041 prev.output += NO_DOTS_SLASH; 4042 4043 } else { 4044 state.output += nodot; 4045 prev.output += nodot; 4046 } 4047 4048 if (peek() !== '*') { 4049 state.output += ONE_CHAR; 4050 prev.output += ONE_CHAR; 4051 } 4052 } 4053 4054 push(token); 4055 } 4056 4057 while (state.brackets > 0) { 4058 if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ']')); 4059 state.output = utils.escapeLast(state.output, '['); 4060 decrement('brackets'); 4061 } 4062 4063 while (state.parens > 0) { 4064 if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', ')')); 4065 state.output = utils.escapeLast(state.output, '('); 4066 decrement('parens'); 4067 } 4068 4069 while (state.braces > 0) { 4070 if (opts.strictBrackets === true) throw new SyntaxError(syntaxError('closing', '}')); 4071 state.output = utils.escapeLast(state.output, '{'); 4072 decrement('braces'); 4073 } 4074 4075 if (opts.strictSlashes !== true && (prev.type === 'star' || prev.type === 'bracket')) { 4076 push({ type: 'maybe_slash', value: '', output: `${SLASH_LITERAL}?` }); 4077 } 4078 4079 // rebuild the output if we had to backtrack at any point 4080 if (state.backtrack === true) { 4081 state.output = ''; 4082 4083 for (const token of state.tokens) { 4084 state.output += token.output != null ? token.output : token.value; 4085 4086 if (token.suffix) { 4087 state.output += token.suffix; 4088 } 4089 } 4090 } 4091 4092 return state; 4093 }; 4094 4095 /** 4096 * Fast paths for creating regular expressions for common glob patterns. 4097 * This can significantly speed up processing and has very little downside 4098 * impact when none of the fast paths match. 4099 */ 4100 4101 parse.fastpaths = (input, options) => { 4102 const opts = { ...options }; 4103 const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; 4104 const len = input.length; 4105 if (len > max) { 4106 throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); 4107 } 4108 4109 input = REPLACEMENTS[input] || input; 4110 const win32 = utils.isWindows(options); 4111 4112 // create constants based on platform, for windows or posix 4113 const { 4114 DOT_LITERAL, 4115 SLASH_LITERAL, 4116 ONE_CHAR, 4117 DOTS_SLASH, 4118 NO_DOT, 4119 NO_DOTS, 4120 NO_DOTS_SLASH, 4121 STAR, 4122 START_ANCHOR 4123 } = constants.globChars(win32); 4124 4125 const nodot = opts.dot ? NO_DOTS : NO_DOT; 4126 const slashDot = opts.dot ? NO_DOTS_SLASH : NO_DOT; 4127 const capture = opts.capture ? '' : '?:'; 4128 const state = { negated: false, prefix: '' }; 4129 let star = opts.bash === true ? '.*?' : STAR; 4130 4131 if (opts.capture) { 4132 star = `(${star})`; 4133 } 4134 4135 const globstar = opts => { 4136 if (opts.noglobstar === true) return star; 4137 return `(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`; 4138 }; 4139 4140 const create = str => { 4141 switch (str) { 4142 case '*': 4143 return `${nodot}${ONE_CHAR}${star}`; 4144 4145 case '.*': 4146 return `${DOT_LITERAL}${ONE_CHAR}${star}`; 4147 4148 case '*.*': 4149 return `${nodot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`; 4150 4151 case '*/*': 4152 return `${nodot}${star}${SLASH_LITERAL}${ONE_CHAR}${slashDot}${star}`; 4153 4154 case '**': 4155 return nodot + globstar(opts); 4156 4157 case '**/*': 4158 return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${ONE_CHAR}${star}`; 4159 4160 case '**/*.*': 4161 return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${slashDot}${star}${DOT_LITERAL}${ONE_CHAR}${star}`; 4162 4163 case '**/.*': 4164 return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL})?${DOT_LITERAL}${ONE_CHAR}${star}`; 4165 4166 default: { 4167 const match = /^(.*?)\.(\w+)$/.exec(str); 4168 if (!match) return; 4169 4170 const source = create(match[1]); 4171 if (!source) return; 4172 4173 return source + DOT_LITERAL + match[2]; 4174 } 4175 } 4176 }; 4177 4178 const output = utils.removePrefix(input, state); 4179 let source = create(output); 4180 4181 if (source && opts.strictSlashes !== true) { 4182 source += `${SLASH_LITERAL}?`; 4183 } 4184 4185 return source; 4186 }; 4187 4188 parse_1$1 = parse; 4189 return parse_1$1; 4190 } 4191 4192 var picomatch_1; 4193 var hasRequiredPicomatch$1; 4194 4195 function requirePicomatch$1 () { 4196 if (hasRequiredPicomatch$1) return picomatch_1; 4197 hasRequiredPicomatch$1 = 1; 4198 4199 const path = require$$0$1; 4200 const scan = /*@__PURE__*/ requireScan(); 4201 const parse = /*@__PURE__*/ requireParse$1(); 4202 const utils = /*@__PURE__*/ requireUtils$1(); 4203 const constants = /*@__PURE__*/ requireConstants$2(); 4204 const isObject = val => val && typeof val === 'object' && !Array.isArray(val); 4205 4206 /** 4207 * Creates a matcher function from one or more glob patterns. The 4208 * returned function takes a string to match as its first argument, 4209 * and returns true if the string is a match. The returned matcher 4210 * function also takes a boolean as the second argument that, when true, 4211 * returns an object with additional information. 4212 * 4213 * ```js 4214 * const picomatch = require('picomatch'); 4215 * // picomatch(glob[, options]); 4216 * 4217 * const isMatch = picomatch('*.!(*a)'); 4218 * console.log(isMatch('a.a')); //=> false 4219 * console.log(isMatch('a.b')); //=> true 4220 * ``` 4221 * @name picomatch 4222 * @param {String|Array} `globs` One or more glob patterns. 4223 * @param {Object=} `options` 4224 * @return {Function=} Returns a matcher function. 4225 * @api public 4226 */ 4227 4228 const picomatch = (glob, options, returnState = false) => { 4229 if (Array.isArray(glob)) { 4230 const fns = glob.map(input => picomatch(input, options, returnState)); 4231 const arrayMatcher = str => { 4232 for (const isMatch of fns) { 4233 const state = isMatch(str); 4234 if (state) return state; 4235 } 4236 return false; 4237 }; 4238 return arrayMatcher; 4239 } 4240 4241 const isState = isObject(glob) && glob.tokens && glob.input; 4242 4243 if (glob === '' || (typeof glob !== 'string' && !isState)) { 4244 throw new TypeError('Expected pattern to be a non-empty string'); 4245 } 4246 4247 const opts = options || {}; 4248 const posix = utils.isWindows(options); 4249 const regex = isState 4250 ? picomatch.compileRe(glob, options) 4251 : picomatch.makeRe(glob, options, false, true); 4252 4253 const state = regex.state; 4254 delete regex.state; 4255 4256 let isIgnored = () => false; 4257 if (opts.ignore) { 4258 const ignoreOpts = { ...options, ignore: null, onMatch: null, onResult: null }; 4259 isIgnored = picomatch(opts.ignore, ignoreOpts, returnState); 4260 } 4261 4262 const matcher = (input, returnObject = false) => { 4263 const { isMatch, match, output } = picomatch.test(input, regex, options, { glob, posix }); 4264 const result = { glob, state, regex, posix, input, output, match, isMatch }; 4265 4266 if (typeof opts.onResult === 'function') { 4267 opts.onResult(result); 4268 } 4269 4270 if (isMatch === false) { 4271 result.isMatch = false; 4272 return returnObject ? result : false; 4273 } 4274 4275 if (isIgnored(input)) { 4276 if (typeof opts.onIgnore === 'function') { 4277 opts.onIgnore(result); 4278 } 4279 result.isMatch = false; 4280 return returnObject ? result : false; 4281 } 4282 4283 if (typeof opts.onMatch === 'function') { 4284 opts.onMatch(result); 4285 } 4286 return returnObject ? result : true; 4287 }; 4288 4289 if (returnState) { 4290 matcher.state = state; 4291 } 4292 4293 return matcher; 4294 }; 4295 4296 /** 4297 * Test `input` with the given `regex`. This is used by the main 4298 * `picomatch()` function to test the input string. 4299 * 4300 * ```js 4301 * const picomatch = require('picomatch'); 4302 * // picomatch.test(input, regex[, options]); 4303 * 4304 * console.log(picomatch.test('foo/bar', /^(?:([^/]*?)\/([^/]*?))$/)); 4305 * // { isMatch: true, match: [ 'foo/', 'foo', 'bar' ], output: 'foo/bar' } 4306 * ``` 4307 * @param {String} `input` String to test. 4308 * @param {RegExp} `regex` 4309 * @return {Object} Returns an object with matching info. 4310 * @api public 4311 */ 4312 4313 picomatch.test = (input, regex, options, { glob, posix } = {}) => { 4314 if (typeof input !== 'string') { 4315 throw new TypeError('Expected input to be a string'); 4316 } 4317 4318 if (input === '') { 4319 return { isMatch: false, output: '' }; 4320 } 4321 4322 const opts = options || {}; 4323 const format = opts.format || (posix ? utils.toPosixSlashes : null); 4324 let match = input === glob; 4325 let output = (match && format) ? format(input) : input; 4326 4327 if (match === false) { 4328 output = format ? format(input) : input; 4329 match = output === glob; 4330 } 4331 4332 if (match === false || opts.capture === true) { 4333 if (opts.matchBase === true || opts.basename === true) { 4334 match = picomatch.matchBase(input, regex, options, posix); 4335 } else { 4336 match = regex.exec(output); 4337 } 4338 } 4339 4340 return { isMatch: Boolean(match), match, output }; 4341 }; 4342 4343 /** 4344 * Match the basename of a filepath. 4345 * 4346 * ```js 4347 * const picomatch = require('picomatch'); 4348 * // picomatch.matchBase(input, glob[, options]); 4349 * console.log(picomatch.matchBase('foo/bar.js', '*.js'); // true 4350 * ``` 4351 * @param {String} `input` String to test. 4352 * @param {RegExp|String} `glob` Glob pattern or regex created by [.makeRe](#makeRe). 4353 * @return {Boolean} 4354 * @api public 4355 */ 4356 4357 picomatch.matchBase = (input, glob, options, posix = utils.isWindows(options)) => { 4358 const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options); 4359 return regex.test(path.basename(input)); 4360 }; 4361 4362 /** 4363 * Returns true if **any** of the given glob `patterns` match the specified `string`. 4364 * 4365 * ```js 4366 * const picomatch = require('picomatch'); 4367 * // picomatch.isMatch(string, patterns[, options]); 4368 * 4369 * console.log(picomatch.isMatch('a.a', ['b.*', '*.a'])); //=> true 4370 * console.log(picomatch.isMatch('a.a', 'b.*')); //=> false 4371 * ``` 4372 * @param {String|Array} str The string to test. 4373 * @param {String|Array} patterns One or more glob patterns to use for matching. 4374 * @param {Object} [options] See available [options](#options). 4375 * @return {Boolean} Returns true if any patterns match `str` 4376 * @api public 4377 */ 4378 4379 picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str); 4380 4381 /** 4382 * Parse a glob pattern to create the source string for a regular 4383 * expression. 4384 * 4385 * ```js 4386 * const picomatch = require('picomatch'); 4387 * const result = picomatch.parse(pattern[, options]); 4388 * ``` 4389 * @param {String} `pattern` 4390 * @param {Object} `options` 4391 * @return {Object} Returns an object with useful properties and output to be used as a regex source string. 4392 * @api public 4393 */ 4394 4395 picomatch.parse = (pattern, options) => { 4396 if (Array.isArray(pattern)) return pattern.map(p => picomatch.parse(p, options)); 4397 return parse(pattern, { ...options, fastpaths: false }); 4398 }; 4399 4400 /** 4401 * Scan a glob pattern to separate the pattern into segments. 4402 * 4403 * ```js 4404 * const picomatch = require('picomatch'); 4405 * // picomatch.scan(input[, options]); 4406 * 4407 * const result = picomatch.scan('!./foo/*.js'); 4408 * console.log(result); 4409 * { prefix: '!./', 4410 * input: '!./foo/*.js', 4411 * start: 3, 4412 * base: 'foo', 4413 * glob: '*.js', 4414 * isBrace: false, 4415 * isBracket: false, 4416 * isGlob: true, 4417 * isExtglob: false, 4418 * isGlobstar: false, 4419 * negated: true } 4420 * ``` 4421 * @param {String} `input` Glob pattern to scan. 4422 * @param {Object} `options` 4423 * @return {Object} Returns an object with 4424 * @api public 4425 */ 4426 4427 picomatch.scan = (input, options) => scan(input, options); 4428 4429 /** 4430 * Compile a regular expression from the `state` object returned by the 4431 * [parse()](#parse) method. 4432 * 4433 * @param {Object} `state` 4434 * @param {Object} `options` 4435 * @param {Boolean} `returnOutput` Intended for implementors, this argument allows you to return the raw output from the parser. 4436 * @param {Boolean} `returnState` Adds the state to a `state` property on the returned regex. Useful for implementors and debugging. 4437 * @return {RegExp} 4438 * @api public 4439 */ 4440 4441 picomatch.compileRe = (state, options, returnOutput = false, returnState = false) => { 4442 if (returnOutput === true) { 4443 return state.output; 4444 } 4445 4446 const opts = options || {}; 4447 const prepend = opts.contains ? '' : '^'; 4448 const append = opts.contains ? '' : '$'; 4449 4450 let source = `${prepend}(?:${state.output})${append}`; 4451 if (state && state.negated === true) { 4452 source = `^(?!${source}).*$`; 4453 } 4454 4455 const regex = picomatch.toRegex(source, options); 4456 if (returnState === true) { 4457 regex.state = state; 4458 } 4459 4460 return regex; 4461 }; 4462 4463 /** 4464 * Create a regular expression from a parsed glob pattern. 4465 * 4466 * ```js 4467 * const picomatch = require('picomatch'); 4468 * const state = picomatch.parse('*.js'); 4469 * // picomatch.compileRe(state[, options]); 4470 * 4471 * console.log(picomatch.compileRe(state)); 4472 * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/ 4473 * ``` 4474 * @param {String} `state` The object returned from the `.parse` method. 4475 * @param {Object} `options` 4476 * @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. 4477 * @param {Boolean} `returnState` Implementors may use this argument to return the state from the parsed glob with the returned regular expression. 4478 * @return {RegExp} Returns a regex created from the given pattern. 4479 * @api public 4480 */ 4481 4482 picomatch.makeRe = (input, options = {}, returnOutput = false, returnState = false) => { 4483 if (!input || typeof input !== 'string') { 4484 throw new TypeError('Expected a non-empty string'); 4485 } 4486 4487 let parsed = { negated: false, fastpaths: true }; 4488 4489 if (options.fastpaths !== false && (input[0] === '.' || input[0] === '*')) { 4490 parsed.output = parse.fastpaths(input, options); 4491 } 4492 4493 if (!parsed.output) { 4494 parsed = parse(input, options); 4495 } 4496 4497 return picomatch.compileRe(parsed, options, returnOutput, returnState); 4498 }; 4499 4500 /** 4501 * Create a regular expression from the given regex source string. 4502 * 4503 * ```js 4504 * const picomatch = require('picomatch'); 4505 * // picomatch.toRegex(source[, options]); 4506 * 4507 * const { output } = picomatch.parse('*.js'); 4508 * console.log(picomatch.toRegex(output)); 4509 * //=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/ 4510 * ``` 4511 * @param {String} `source` Regular expression source string. 4512 * @param {Object} `options` 4513 * @return {RegExp} 4514 * @api public 4515 */ 4516 4517 picomatch.toRegex = (source, options) => { 4518 try { 4519 const opts = options || {}; 4520 return new RegExp(source, opts.flags || (opts.nocase ? 'i' : '')); 4521 } catch (err) { 4522 if (options && options.debug === true) throw err; 4523 return /$^/; 4524 } 4525 }; 4526 4527 /** 4528 * Picomatch constants. 4529 * @return {Object} 4530 */ 4531 4532 picomatch.constants = constants; 4533 4534 /** 4535 * Expose "picomatch" 4536 */ 4537 4538 picomatch_1 = picomatch; 4539 return picomatch_1; 4540 } 4541 4542 var picomatch; 4543 var hasRequiredPicomatch; 4544 4545 function requirePicomatch () { 4546 if (hasRequiredPicomatch) return picomatch; 4547 hasRequiredPicomatch = 1; 4548 4549 picomatch = /*@__PURE__*/ requirePicomatch$1(); 4550 return picomatch; 4551 } 315 4552 316 4553 /*! … … 321 4558 */ 322 4559 323 var normalizePath$2 = function(path, stripTrailing) { 324 if (typeof path !== 'string') { 325 throw new TypeError('expected path to be a string'); 326 } 327 328 if (path === '\\' || path === '/') return '/'; 329 330 var len = path.length; 331 if (len <= 1) return path; 332 333 // ensure that win32 namespaces has two leading slashes, so that the path is 334 // handled properly by the win32 version of path.parse() after being normalized 335 // https://msdn.microsoft.com/library/windows/desktop/aa365247(v=vs.85).aspx#namespaces 336 var prefix = ''; 337 if (len > 4 && path[3] === '\\') { 338 var ch = path[2]; 339 if ((ch === '?' || ch === '.') && path.slice(0, 2) === '\\\\') { 340 path = path.slice(2); 341 prefix = '//'; 342 } 343 } 344 345 var segs = path.split(/[/\\]+/); 346 if (stripTrailing !== false && segs[segs.length - 1] === '') { 347 segs.pop(); 348 } 349 return prefix + segs.join('/'); 350 }; 351 352 var anymatch_1 = anymatch$2.exports; 353 354 Object.defineProperty(anymatch_1, "__esModule", { value: true }); 355 356 const picomatch = picomatch$2; 357 const normalizePath$1 = normalizePath$2; 358 359 /** 360 * @typedef {(testString: string) => boolean} AnymatchFn 361 * @typedef {string|RegExp|AnymatchFn} AnymatchPattern 362 * @typedef {AnymatchPattern|AnymatchPattern[]} AnymatchMatcher 363 */ 364 const BANG$1 = '!'; 365 const DEFAULT_OPTIONS = {returnIndex: false}; 366 const arrify$1 = (item) => Array.isArray(item) ? item : [item]; 367 368 /** 369 * @param {AnymatchPattern} matcher 370 * @param {object} options 371 * @returns {AnymatchFn} 372 */ 373 const createPattern = (matcher, options) => { 374 if (typeof matcher === 'function') { 375 return matcher; 376 } 377 if (typeof matcher === 'string') { 378 const glob = picomatch(matcher, options); 379 return (string) => matcher === string || glob(string); 380 } 381 if (matcher instanceof RegExp) { 382 return (string) => matcher.test(string); 383 } 384 return (string) => false; 385 }; 386 387 /** 388 * @param {Array<Function>} patterns 389 * @param {Array<Function>} negPatterns 390 * @param {String|Array} args 391 * @param {Boolean} returnIndex 392 * @returns {boolean|number} 393 */ 394 const matchPatterns = (patterns, negPatterns, args, returnIndex) => { 395 const isList = Array.isArray(args); 396 const _path = isList ? args[0] : args; 397 if (!isList && typeof _path !== 'string') { 398 throw new TypeError('anymatch: second argument must be a string: got ' + 399 Object.prototype.toString.call(_path)) 400 } 401 const path = normalizePath$1(_path, false); 402 403 for (let index = 0; index < negPatterns.length; index++) { 404 const nglob = negPatterns[index]; 405 if (nglob(path)) { 406 return returnIndex ? -1 : false; 407 } 408 } 409 410 const applied = isList && [path].concat(args.slice(1)); 411 for (let index = 0; index < patterns.length; index++) { 412 const pattern = patterns[index]; 413 if (isList ? pattern(...applied) : pattern(path)) { 414 return returnIndex ? index : true; 415 } 416 } 417 418 return returnIndex ? -1 : false; 419 }; 420 421 /** 422 * @param {AnymatchMatcher} matchers 423 * @param {Array|string} testString 424 * @param {object} options 425 * @returns {boolean|number|Function} 426 */ 427 const anymatch$1 = (matchers, testString, options = DEFAULT_OPTIONS) => { 428 if (matchers == null) { 429 throw new TypeError('anymatch: specify first argument'); 430 } 431 const opts = typeof options === 'boolean' ? {returnIndex: options} : options; 432 const returnIndex = opts.returnIndex || false; 433 434 // Early cache for matchers. 435 const mtchers = arrify$1(matchers); 436 const negatedGlobs = mtchers 437 .filter(item => typeof item === 'string' && item.charAt(0) === BANG$1) 438 .map(item => item.slice(1)) 439 .map(item => picomatch(item, opts)); 440 const patterns = mtchers 441 .filter(item => typeof item !== 'string' || (typeof item === 'string' && item.charAt(0) !== BANG$1)) 442 .map(matcher => createPattern(matcher, opts)); 443 444 if (testString == null) { 445 return (testString, ri = false) => { 446 const returnIndex = typeof ri === 'boolean' ? ri : false; 447 return matchPatterns(patterns, negatedGlobs, testString, returnIndex); 448 } 449 } 450 451 return matchPatterns(patterns, negatedGlobs, testString, returnIndex); 452 }; 453 454 anymatch$1.default = anymatch$1; 455 anymatch$2.exports = anymatch$1; 456 457 var anymatchExports = anymatch$2.exports; 4560 var normalizePath; 4561 var hasRequiredNormalizePath; 4562 4563 function requireNormalizePath () { 4564 if (hasRequiredNormalizePath) return normalizePath; 4565 hasRequiredNormalizePath = 1; 4566 normalizePath = function(path, stripTrailing) { 4567 if (typeof path !== 'string') { 4568 throw new TypeError('expected path to be a string'); 4569 } 4570 4571 if (path === '\\' || path === '/') return '/'; 4572 4573 var len = path.length; 4574 if (len <= 1) return path; 4575 4576 // ensure that win32 namespaces has two leading slashes, so that the path is 4577 // handled properly by the win32 version of path.parse() after being normalized 4578 // https://msdn.microsoft.com/library/windows/desktop/aa365247(v=vs.85).aspx#namespaces 4579 var prefix = ''; 4580 if (len > 4 && path[3] === '\\') { 4581 var ch = path[2]; 4582 if ((ch === '?' || ch === '.') && path.slice(0, 2) === '\\\\') { 4583 path = path.slice(2); 4584 prefix = '//'; 4585 } 4586 } 4587 4588 var segs = path.split(/[/\\]+/); 4589 if (stripTrailing !== false && segs[segs.length - 1] === '') { 4590 segs.pop(); 4591 } 4592 return prefix + segs.join('/'); 4593 }; 4594 return normalizePath; 4595 } 4596 4597 var anymatch_1 = anymatch.exports; 4598 4599 var hasRequiredAnymatch; 4600 4601 function requireAnymatch () { 4602 if (hasRequiredAnymatch) return anymatch.exports; 4603 hasRequiredAnymatch = 1; 4604 4605 Object.defineProperty(anymatch_1, "__esModule", { value: true }); 4606 4607 const picomatch = /*@__PURE__*/ requirePicomatch(); 4608 const normalizePath = /*@__PURE__*/ requireNormalizePath(); 4609 4610 /** 4611 * @typedef {(testString: string) => boolean} AnymatchFn 4612 * @typedef {string|RegExp|AnymatchFn} AnymatchPattern 4613 * @typedef {AnymatchPattern|AnymatchPattern[]} AnymatchMatcher 4614 */ 4615 const BANG = '!'; 4616 const DEFAULT_OPTIONS = {returnIndex: false}; 4617 const arrify = (item) => Array.isArray(item) ? item : [item]; 4618 4619 /** 4620 * @param {AnymatchPattern} matcher 4621 * @param {object} options 4622 * @returns {AnymatchFn} 4623 */ 4624 const createPattern = (matcher, options) => { 4625 if (typeof matcher === 'function') { 4626 return matcher; 4627 } 4628 if (typeof matcher === 'string') { 4629 const glob = picomatch(matcher, options); 4630 return (string) => matcher === string || glob(string); 4631 } 4632 if (matcher instanceof RegExp) { 4633 return (string) => matcher.test(string); 4634 } 4635 return (string) => false; 4636 }; 4637 4638 /** 4639 * @param {Array<Function>} patterns 4640 * @param {Array<Function>} negPatterns 4641 * @param {String|Array} args 4642 * @param {Boolean} returnIndex 4643 * @returns {boolean|number} 4644 */ 4645 const matchPatterns = (patterns, negPatterns, args, returnIndex) => { 4646 const isList = Array.isArray(args); 4647 const _path = isList ? args[0] : args; 4648 if (!isList && typeof _path !== 'string') { 4649 throw new TypeError('anymatch: second argument must be a string: got ' + 4650 Object.prototype.toString.call(_path)) 4651 } 4652 const path = normalizePath(_path, false); 4653 4654 for (let index = 0; index < negPatterns.length; index++) { 4655 const nglob = negPatterns[index]; 4656 if (nglob(path)) { 4657 return returnIndex ? -1 : false; 4658 } 4659 } 4660 4661 const applied = isList && [path].concat(args.slice(1)); 4662 for (let index = 0; index < patterns.length; index++) { 4663 const pattern = patterns[index]; 4664 if (isList ? pattern(...applied) : pattern(path)) { 4665 return returnIndex ? index : true; 4666 } 4667 } 4668 4669 return returnIndex ? -1 : false; 4670 }; 4671 4672 /** 4673 * @param {AnymatchMatcher} matchers 4674 * @param {Array|string} testString 4675 * @param {object} options 4676 * @returns {boolean|number|Function} 4677 */ 4678 const anymatch$1 = (matchers, testString, options = DEFAULT_OPTIONS) => { 4679 if (matchers == null) { 4680 throw new TypeError('anymatch: specify first argument'); 4681 } 4682 const opts = typeof options === 'boolean' ? {returnIndex: options} : options; 4683 const returnIndex = opts.returnIndex || false; 4684 4685 // Early cache for matchers. 4686 const mtchers = arrify(matchers); 4687 const negatedGlobs = mtchers 4688 .filter(item => typeof item === 'string' && item.charAt(0) === BANG) 4689 .map(item => item.slice(1)) 4690 .map(item => picomatch(item, opts)); 4691 const patterns = mtchers 4692 .filter(item => typeof item !== 'string' || (typeof item === 'string' && item.charAt(0) !== BANG)) 4693 .map(matcher => createPattern(matcher, opts)); 4694 4695 if (testString == null) { 4696 return (testString, ri = false) => { 4697 const returnIndex = typeof ri === 'boolean' ? ri : false; 4698 return matchPatterns(patterns, negatedGlobs, testString, returnIndex); 4699 } 4700 } 4701 4702 return matchPatterns(patterns, negatedGlobs, testString, returnIndex); 4703 }; 4704 4705 anymatch$1.default = anymatch$1; 4706 anymatch.exports = anymatch$1; 4707 return anymatch.exports; 4708 } 458 4709 459 4710 /*! … … 464 4715 */ 465 4716 466 var isExtglob$1 = function isExtglob(str) { 467 if (typeof str !== 'string' || str === '') { 468 return false; 469 } 470 471 var match; 472 while ((match = /(\\).|([@?!+*]\(.*\))/g.exec(str))) { 473 if (match[2]) return true; 474 str = str.slice(match.index + match[0].length); 475 } 476 477 return false; 478 }; 4717 var isExtglob; 4718 var hasRequiredIsExtglob; 4719 4720 function requireIsExtglob () { 4721 if (hasRequiredIsExtglob) return isExtglob; 4722 hasRequiredIsExtglob = 1; 4723 isExtglob = function isExtglob(str) { 4724 if (typeof str !== 'string' || str === '') { 4725 return false; 4726 } 4727 4728 var match; 4729 while ((match = /(\\).|([@?!+*]\(.*\))/g.exec(str))) { 4730 if (match[2]) return true; 4731 str = str.slice(match.index + match[0].length); 4732 } 4733 4734 return false; 4735 }; 4736 return isExtglob; 4737 } 479 4738 480 4739 /*! … … 485 4744 */ 486 4745 487 var isExtglob = isExtglob$1; 488 var chars = { '{': '}', '(': ')', '[': ']'}; 489 var strictCheck = function(str) { 490 if (str[0] === '!') { 491 return true; 492 } 493 var index = 0; 494 var pipeIndex = -2; 495 var closeSquareIndex = -2; 496 var closeCurlyIndex = -2; 497 var closeParenIndex = -2; 498 var backSlashIndex = -2; 499 while (index < str.length) { 500 if (str[index] === '*') { 501 return true; 502 } 503 504 if (str[index + 1] === '?' && /[\].+)]/.test(str[index])) { 505 return true; 506 } 507 508 if (closeSquareIndex !== -1 && str[index] === '[' && str[index + 1] !== ']') { 509 if (closeSquareIndex < index) { 510 closeSquareIndex = str.indexOf(']', index); 511 } 512 if (closeSquareIndex > index) { 513 if (backSlashIndex === -1 || backSlashIndex > closeSquareIndex) { 514 return true; 515 } 516 backSlashIndex = str.indexOf('\\', index); 517 if (backSlashIndex === -1 || backSlashIndex > closeSquareIndex) { 518 return true; 519 } 520 } 521 } 522 523 if (closeCurlyIndex !== -1 && str[index] === '{' && str[index + 1] !== '}') { 524 closeCurlyIndex = str.indexOf('}', index); 525 if (closeCurlyIndex > index) { 526 backSlashIndex = str.indexOf('\\', index); 527 if (backSlashIndex === -1 || backSlashIndex > closeCurlyIndex) { 528 return true; 529 } 530 } 531 } 532 533 if (closeParenIndex !== -1 && str[index] === '(' && str[index + 1] === '?' && /[:!=]/.test(str[index + 2]) && str[index + 3] !== ')') { 534 closeParenIndex = str.indexOf(')', index); 535 if (closeParenIndex > index) { 536 backSlashIndex = str.indexOf('\\', index); 537 if (backSlashIndex === -1 || backSlashIndex > closeParenIndex) { 538 return true; 539 } 540 } 541 } 542 543 if (pipeIndex !== -1 && str[index] === '(' && str[index + 1] !== '|') { 544 if (pipeIndex < index) { 545 pipeIndex = str.indexOf('|', index); 546 } 547 if (pipeIndex !== -1 && str[pipeIndex + 1] !== ')') { 548 closeParenIndex = str.indexOf(')', pipeIndex); 549 if (closeParenIndex > pipeIndex) { 550 backSlashIndex = str.indexOf('\\', pipeIndex); 551 if (backSlashIndex === -1 || backSlashIndex > closeParenIndex) { 552 return true; 553 } 554 } 555 } 556 } 557 558 if (str[index] === '\\') { 559 var open = str[index + 1]; 560 index += 2; 561 var close = chars[open]; 562 563 if (close) { 564 var n = str.indexOf(close, index); 565 if (n !== -1) { 566 index = n + 1; 567 } 568 } 569 570 if (str[index] === '!') { 571 return true; 572 } 573 } else { 574 index++; 575 } 576 } 577 return false; 578 }; 579 580 var relaxedCheck = function(str) { 581 if (str[0] === '!') { 582 return true; 583 } 584 var index = 0; 585 while (index < str.length) { 586 if (/[*?{}()[\]]/.test(str[index])) { 587 return true; 588 } 589 590 if (str[index] === '\\') { 591 var open = str[index + 1]; 592 index += 2; 593 var close = chars[open]; 594 595 if (close) { 596 var n = str.indexOf(close, index); 597 if (n !== -1) { 598 index = n + 1; 599 } 600 } 601 602 if (str[index] === '!') { 603 return true; 604 } 605 } else { 606 index++; 607 } 608 } 609 return false; 610 }; 611 612 var isGlob$2 = function isGlob(str, options) { 613 if (typeof str !== 'string' || str === '') { 614 return false; 615 } 616 617 if (isExtglob(str)) { 618 return true; 619 } 620 621 var check = strictCheck; 622 623 // optionally relax check 624 if (options && options.strict === false) { 625 check = relaxedCheck; 626 } 627 628 return check(str); 629 }; 630 631 var isGlob$1 = isGlob$2; 632 var pathPosixDirname = require$$0$2.posix.dirname; 633 var isWin32 = require$$2$1.platform() === 'win32'; 634 635 var slash = '/'; 636 var backslash = /\\/g; 637 var enclosure = /[\{\[].*[\}\]]$/; 638 var globby = /(^|[^\\])([\{\[]|\([^\)]+$)/; 639 var escaped = /\\([\!\*\?\|\[\]\(\)\{\}])/g; 640 641 /** 642 * @param {string} str 643 * @param {Object} opts 644 * @param {boolean} [opts.flipBackslashes=true] 645 * @returns {string} 646 */ 647 var globParent$1 = function globParent(str, opts) { 648 var options = Object.assign({ flipBackslashes: true }, opts); 649 650 // flip windows path separators 651 if (options.flipBackslashes && isWin32 && str.indexOf(slash) < 0) { 652 str = str.replace(backslash, slash); 653 } 654 655 // special case for strings ending in enclosure containing path separator 656 if (enclosure.test(str)) { 657 str += slash; 658 } 659 660 // preserves full path in case of trailing path separator 661 str += 'a'; 662 663 // remove path parts that are globby 664 do { 665 str = pathPosixDirname(str); 666 } while (isGlob$1(str) || globby.test(str)); 667 668 // remove escape chars and return result 669 return str.replace(escaped, '$1'); 670 }; 671 672 var utils$3 = {}; 673 674 (function (exports) { 675 676 exports.isInteger = num => { 677 if (typeof num === 'number') { 678 return Number.isInteger(num); 679 } 680 if (typeof num === 'string' && num.trim() !== '') { 681 return Number.isInteger(Number(num)); 4746 var isGlob; 4747 var hasRequiredIsGlob; 4748 4749 function requireIsGlob () { 4750 if (hasRequiredIsGlob) return isGlob; 4751 hasRequiredIsGlob = 1; 4752 var isExtglob = /*@__PURE__*/ requireIsExtglob(); 4753 var chars = { '{': '}', '(': ')', '[': ']'}; 4754 var strictCheck = function(str) { 4755 if (str[0] === '!') { 4756 return true; 4757 } 4758 var index = 0; 4759 var pipeIndex = -2; 4760 var closeSquareIndex = -2; 4761 var closeCurlyIndex = -2; 4762 var closeParenIndex = -2; 4763 var backSlashIndex = -2; 4764 while (index < str.length) { 4765 if (str[index] === '*') { 4766 return true; 4767 } 4768 4769 if (str[index + 1] === '?' && /[\].+)]/.test(str[index])) { 4770 return true; 4771 } 4772 4773 if (closeSquareIndex !== -1 && str[index] === '[' && str[index + 1] !== ']') { 4774 if (closeSquareIndex < index) { 4775 closeSquareIndex = str.indexOf(']', index); 4776 } 4777 if (closeSquareIndex > index) { 4778 if (backSlashIndex === -1 || backSlashIndex > closeSquareIndex) { 4779 return true; 4780 } 4781 backSlashIndex = str.indexOf('\\', index); 4782 if (backSlashIndex === -1 || backSlashIndex > closeSquareIndex) { 4783 return true; 4784 } 4785 } 4786 } 4787 4788 if (closeCurlyIndex !== -1 && str[index] === '{' && str[index + 1] !== '}') { 4789 closeCurlyIndex = str.indexOf('}', index); 4790 if (closeCurlyIndex > index) { 4791 backSlashIndex = str.indexOf('\\', index); 4792 if (backSlashIndex === -1 || backSlashIndex > closeCurlyIndex) { 4793 return true; 4794 } 4795 } 4796 } 4797 4798 if (closeParenIndex !== -1 && str[index] === '(' && str[index + 1] === '?' && /[:!=]/.test(str[index + 2]) && str[index + 3] !== ')') { 4799 closeParenIndex = str.indexOf(')', index); 4800 if (closeParenIndex > index) { 4801 backSlashIndex = str.indexOf('\\', index); 4802 if (backSlashIndex === -1 || backSlashIndex > closeParenIndex) { 4803 return true; 4804 } 4805 } 4806 } 4807 4808 if (pipeIndex !== -1 && str[index] === '(' && str[index + 1] !== '|') { 4809 if (pipeIndex < index) { 4810 pipeIndex = str.indexOf('|', index); 4811 } 4812 if (pipeIndex !== -1 && str[pipeIndex + 1] !== ')') { 4813 closeParenIndex = str.indexOf(')', pipeIndex); 4814 if (closeParenIndex > pipeIndex) { 4815 backSlashIndex = str.indexOf('\\', pipeIndex); 4816 if (backSlashIndex === -1 || backSlashIndex > closeParenIndex) { 4817 return true; 4818 } 4819 } 4820 } 4821 } 4822 4823 if (str[index] === '\\') { 4824 var open = str[index + 1]; 4825 index += 2; 4826 var close = chars[open]; 4827 4828 if (close) { 4829 var n = str.indexOf(close, index); 4830 if (n !== -1) { 4831 index = n + 1; 4832 } 4833 } 4834 4835 if (str[index] === '!') { 4836 return true; 4837 } 4838 } else { 4839 index++; 4840 } 682 4841 } 683 4842 return false; 684 4843 }; 685 4844 686 /** 687 * Find a node of the given type 688 */ 689 690 exports.find = (node, type) => node.nodes.find(node => node.type === type); 691 692 /** 693 * Find a node of the given type 694 */ 695 696 exports.exceedsLimit = (min, max, step = 1, limit) => { 697 if (limit === false) return false; 698 if (!exports.isInteger(min) || !exports.isInteger(max)) return false; 699 return ((Number(max) - Number(min)) / Number(step)) >= limit; 700 }; 701 702 /** 703 * Escape the given node with '\\' before node.value 704 */ 705 706 exports.escapeNode = (block, n = 0, type) => { 707 const node = block.nodes[n]; 708 if (!node) return; 709 710 if ((type && node.type === type) || node.type === 'open' || node.type === 'close') { 711 if (node.escaped !== true) { 712 node.value = '\\' + node.value; 713 node.escaped = true; 714 } 715 } 716 }; 717 718 /** 719 * Returns true if the given brace node should be enclosed in literal braces 720 */ 721 722 exports.encloseBrace = node => { 723 if (node.type !== 'brace') return false; 724 if ((node.commas >> 0 + node.ranges >> 0) === 0) { 725 node.invalid = true; 4845 var relaxedCheck = function(str) { 4846 if (str[0] === '!') { 726 4847 return true; 4848 } 4849 var index = 0; 4850 while (index < str.length) { 4851 if (/[*?{}()[\]]/.test(str[index])) { 4852 return true; 4853 } 4854 4855 if (str[index] === '\\') { 4856 var open = str[index + 1]; 4857 index += 2; 4858 var close = chars[open]; 4859 4860 if (close) { 4861 var n = str.indexOf(close, index); 4862 if (n !== -1) { 4863 index = n + 1; 4864 } 4865 } 4866 4867 if (str[index] === '!') { 4868 return true; 4869 } 4870 } else { 4871 index++; 4872 } 727 4873 } 728 4874 return false; 729 4875 }; 730 4876 731 /** 732 * Returns true if a brace node is invalid. 733 */ 734 735 exports.isInvalidBrace = block => { 736 if (block.type !== 'brace') return false; 737 if (block.invalid === true || block.dollar) return true; 738 if ((block.commas >> 0 + block.ranges >> 0) === 0) { 739 block.invalid = true; 4877 isGlob = function isGlob(str, options) { 4878 if (typeof str !== 'string' || str === '') { 4879 return false; 4880 } 4881 4882 if (isExtglob(str)) { 740 4883 return true; 741 4884 } 742 if (block.open !== true || block.close !== true) { 743 block.invalid = true; 744 return true; 745 } 746 return false; 4885 4886 var check = strictCheck; 4887 4888 // optionally relax check 4889 if (options && options.strict === false) { 4890 check = relaxedCheck; 4891 } 4892 4893 return check(str); 747 4894 }; 748 749 /** 750 * Returns true if a node is an open or close node 751 */ 752 753 exports.isOpenOrClose = node => { 754 if (node.type === 'open' || node.type === 'close') { 755 return true; 756 } 757 return node.open === true || node.close === true; 4895 return isGlob; 4896 } 4897 4898 var globParent; 4899 var hasRequiredGlobParent; 4900 4901 function requireGlobParent () { 4902 if (hasRequiredGlobParent) return globParent; 4903 hasRequiredGlobParent = 1; 4904 4905 var isGlob = /*@__PURE__*/ requireIsGlob(); 4906 var pathPosixDirname = require$$0$1.posix.dirname; 4907 var isWin32 = require$$2$1.platform() === 'win32'; 4908 4909 var slash = '/'; 4910 var backslash = /\\/g; 4911 var enclosure = /[\{\[].*[\}\]]$/; 4912 var globby = /(^|[^\\])([\{\[]|\([^\)]+$)/; 4913 var escaped = /\\([\!\*\?\|\[\]\(\)\{\}])/g; 4914 4915 /** 4916 * @param {string} str 4917 * @param {Object} opts 4918 * @param {boolean} [opts.flipBackslashes=true] 4919 * @returns {string} 4920 */ 4921 globParent = function globParent(str, opts) { 4922 var options = Object.assign({ flipBackslashes: true }, opts); 4923 4924 // flip windows path separators 4925 if (options.flipBackslashes && isWin32 && str.indexOf(slash) < 0) { 4926 str = str.replace(backslash, slash); 4927 } 4928 4929 // special case for strings ending in enclosure containing path separator 4930 if (enclosure.test(str)) { 4931 str += slash; 4932 } 4933 4934 // preserves full path in case of trailing path separator 4935 str += 'a'; 4936 4937 // remove path parts that are globby 4938 do { 4939 str = pathPosixDirname(str); 4940 } while (isGlob(str) || globby.test(str)); 4941 4942 // remove escape chars and return result 4943 return str.replace(escaped, '$1'); 758 4944 }; 759 760 /** 761 * Reduce an array of text nodes. 762 */ 763 764 exports.reduce = nodes => nodes.reduce((acc, node) => { 765 if (node.type === 'text') acc.push(node.value); 766 if (node.type === 'range') node.type = 'text'; 767 return acc; 768 }, []); 769 770 /** 771 * Flatten an array 772 */ 773 774 exports.flatten = (...args) => { 775 const result = []; 776 777 const flat = arr => { 778 for (let i = 0; i < arr.length; i++) { 779 const ele = arr[i]; 780 781 if (Array.isArray(ele)) { 782 flat(ele); 783 continue; 784 } 785 786 if (ele !== undefined) { 787 result.push(ele); 788 } 789 } 790 return result; 4945 return globParent; 4946 } 4947 4948 var utils = {}; 4949 4950 var hasRequiredUtils; 4951 4952 function requireUtils () { 4953 if (hasRequiredUtils) return utils; 4954 hasRequiredUtils = 1; 4955 (function (exports) { 4956 4957 exports.isInteger = num => { 4958 if (typeof num === 'number') { 4959 return Number.isInteger(num); 4960 } 4961 if (typeof num === 'string' && num.trim() !== '') { 4962 return Number.isInteger(Number(num)); 4963 } 4964 return false; 4965 }; 4966 4967 /** 4968 * Find a node of the given type 4969 */ 4970 4971 exports.find = (node, type) => node.nodes.find(node => node.type === type); 4972 4973 /** 4974 * Find a node of the given type 4975 */ 4976 4977 exports.exceedsLimit = (min, max, step = 1, limit) => { 4978 if (limit === false) return false; 4979 if (!exports.isInteger(min) || !exports.isInteger(max)) return false; 4980 return ((Number(max) - Number(min)) / Number(step)) >= limit; 4981 }; 4982 4983 /** 4984 * Escape the given node with '\\' before node.value 4985 */ 4986 4987 exports.escapeNode = (block, n = 0, type) => { 4988 const node = block.nodes[n]; 4989 if (!node) return; 4990 4991 if ((type && node.type === type) || node.type === 'open' || node.type === 'close') { 4992 if (node.escaped !== true) { 4993 node.value = '\\' + node.value; 4994 node.escaped = true; 4995 } 4996 } 4997 }; 4998 4999 /** 5000 * Returns true if the given brace node should be enclosed in literal braces 5001 */ 5002 5003 exports.encloseBrace = node => { 5004 if (node.type !== 'brace') return false; 5005 if ((node.commas >> 0 + node.ranges >> 0) === 0) { 5006 node.invalid = true; 5007 return true; 5008 } 5009 return false; 5010 }; 5011 5012 /** 5013 * Returns true if a brace node is invalid. 5014 */ 5015 5016 exports.isInvalidBrace = block => { 5017 if (block.type !== 'brace') return false; 5018 if (block.invalid === true || block.dollar) return true; 5019 if ((block.commas >> 0 + block.ranges >> 0) === 0) { 5020 block.invalid = true; 5021 return true; 5022 } 5023 if (block.open !== true || block.close !== true) { 5024 block.invalid = true; 5025 return true; 5026 } 5027 return false; 5028 }; 5029 5030 /** 5031 * Returns true if a node is an open or close node 5032 */ 5033 5034 exports.isOpenOrClose = node => { 5035 if (node.type === 'open' || node.type === 'close') { 5036 return true; 5037 } 5038 return node.open === true || node.close === true; 5039 }; 5040 5041 /** 5042 * Reduce an array of text nodes. 5043 */ 5044 5045 exports.reduce = nodes => nodes.reduce((acc, node) => { 5046 if (node.type === 'text') acc.push(node.value); 5047 if (node.type === 'range') node.type = 'text'; 5048 return acc; 5049 }, []); 5050 5051 /** 5052 * Flatten an array 5053 */ 5054 5055 exports.flatten = (...args) => { 5056 const result = []; 5057 5058 const flat = arr => { 5059 for (let i = 0; i < arr.length; i++) { 5060 const ele = arr[i]; 5061 5062 if (Array.isArray(ele)) { 5063 flat(ele); 5064 continue; 5065 } 5066 5067 if (ele !== undefined) { 5068 result.push(ele); 5069 } 5070 } 5071 return result; 5072 }; 5073 5074 flat(args); 5075 return result; 5076 }; 5077 } (utils)); 5078 return utils; 5079 } 5080 5081 var stringify; 5082 var hasRequiredStringify; 5083 5084 function requireStringify () { 5085 if (hasRequiredStringify) return stringify; 5086 hasRequiredStringify = 1; 5087 5088 const utils = /*@__PURE__*/ requireUtils(); 5089 5090 stringify = (ast, options = {}) => { 5091 const stringify = (node, parent = {}) => { 5092 const invalidBlock = options.escapeInvalid && utils.isInvalidBrace(parent); 5093 const invalidNode = node.invalid === true && options.escapeInvalid === true; 5094 let output = ''; 5095 5096 if (node.value) { 5097 if ((invalidBlock || invalidNode) && utils.isOpenOrClose(node)) { 5098 return '\\' + node.value; 5099 } 5100 return node.value; 5101 } 5102 5103 if (node.value) { 5104 return node.value; 5105 } 5106 5107 if (node.nodes) { 5108 for (const child of node.nodes) { 5109 output += stringify(child); 5110 } 5111 } 5112 return output; 791 5113 }; 792 5114 793 flat(args); 794 return result; 795 }; 796 } (utils$3)); 797 798 const utils$2 = utils$3; 799 800 var stringify$4 = (ast, options = {}) => { 801 const stringify = (node, parent = {}) => { 802 const invalidBlock = options.escapeInvalid && utils$2.isInvalidBrace(parent); 803 const invalidNode = node.invalid === true && options.escapeInvalid === true; 804 let output = ''; 805 806 if (node.value) { 807 if ((invalidBlock || invalidNode) && utils$2.isOpenOrClose(node)) { 808 return '\\' + node.value; 809 } 810 return node.value; 811 } 812 813 if (node.value) { 814 return node.value; 815 } 816 817 if (node.nodes) { 818 for (const child of node.nodes) { 819 output += stringify(child); 820 } 821 } 822 return output; 823 }; 824 825 return stringify(ast); 826 }; 5115 return stringify(ast); 5116 }; 5117 return stringify; 5118 } 827 5119 828 5120 /*! … … 833 5125 */ 834 5126 835 var isNumber$2 = function(num) { 836 if (typeof num === 'number') { 837 return num - num === 0; 838 } 839 if (typeof num === 'string' && num.trim() !== '') { 840 return Number.isFinite ? Number.isFinite(+num) : isFinite(+num); 841 } 842 return false; 843 }; 5127 var isNumber; 5128 var hasRequiredIsNumber; 5129 5130 function requireIsNumber () { 5131 if (hasRequiredIsNumber) return isNumber; 5132 hasRequiredIsNumber = 1; 5133 5134 isNumber = function(num) { 5135 if (typeof num === 'number') { 5136 return num - num === 0; 5137 } 5138 if (typeof num === 'string' && num.trim() !== '') { 5139 return Number.isFinite ? Number.isFinite(+num) : isFinite(+num); 5140 } 5141 return false; 5142 }; 5143 return isNumber; 5144 } 844 5145 845 5146 /*! … … 850 5151 */ 851 5152 852 const isNumber$1 = isNumber$2; 853 854 const toRegexRange$1 = (min, max, options) => { 855 if (isNumber$1(min) === false) { 856 throw new TypeError('toRegexRange: expected the first argument to be a number'); 857 } 858 859 if (max === void 0 || min === max) { 860 return String(min); 861 } 862 863 if (isNumber$1(max) === false) { 864 throw new TypeError('toRegexRange: expected the second argument to be a number.'); 865 } 866 867 let opts = { relaxZeros: true, ...options }; 868 if (typeof opts.strictZeros === 'boolean') { 869 opts.relaxZeros = opts.strictZeros === false; 870 } 871 872 let relax = String(opts.relaxZeros); 873 let shorthand = String(opts.shorthand); 874 let capture = String(opts.capture); 875 let wrap = String(opts.wrap); 876 let cacheKey = min + ':' + max + '=' + relax + shorthand + capture + wrap; 877 878 if (toRegexRange$1.cache.hasOwnProperty(cacheKey)) { 879 return toRegexRange$1.cache[cacheKey].result; 880 } 881 882 let a = Math.min(min, max); 883 let b = Math.max(min, max); 884 885 if (Math.abs(a - b) === 1) { 886 let result = min + '|' + max; 887 if (opts.capture) { 888 return `(${result})`; 889 } 890 if (opts.wrap === false) { 891 return result; 892 } 893 return `(?:${result})`; 894 } 895 896 let isPadded = hasPadding(min) || hasPadding(max); 897 let state = { min, max, a, b }; 898 let positives = []; 899 let negatives = []; 900 901 if (isPadded) { 902 state.isPadded = isPadded; 903 state.maxLen = String(state.max).length; 904 } 905 906 if (a < 0) { 907 let newMin = b < 0 ? Math.abs(b) : 1; 908 negatives = splitToPatterns(newMin, Math.abs(a), state, opts); 909 a = state.a = 0; 910 } 911 912 if (b >= 0) { 913 positives = splitToPatterns(a, b, state, opts); 914 } 915 916 state.negatives = negatives; 917 state.positives = positives; 918 state.result = collatePatterns(negatives, positives); 919 920 if (opts.capture === true) { 921 state.result = `(${state.result})`; 922 } else if (opts.wrap !== false && (positives.length + negatives.length) > 1) { 923 state.result = `(?:${state.result})`; 924 } 925 926 toRegexRange$1.cache[cacheKey] = state; 927 return state.result; 928 }; 929 930 function collatePatterns(neg, pos, options) { 931 let onlyNegative = filterPatterns(neg, pos, '-', false) || []; 932 let onlyPositive = filterPatterns(pos, neg, '', false) || []; 933 let intersected = filterPatterns(neg, pos, '-?', true) || []; 934 let subpatterns = onlyNegative.concat(intersected).concat(onlyPositive); 935 return subpatterns.join('|'); 5153 var toRegexRange_1; 5154 var hasRequiredToRegexRange; 5155 5156 function requireToRegexRange () { 5157 if (hasRequiredToRegexRange) return toRegexRange_1; 5158 hasRequiredToRegexRange = 1; 5159 5160 const isNumber = /*@__PURE__*/ requireIsNumber(); 5161 5162 const toRegexRange = (min, max, options) => { 5163 if (isNumber(min) === false) { 5164 throw new TypeError('toRegexRange: expected the first argument to be a number'); 5165 } 5166 5167 if (max === void 0 || min === max) { 5168 return String(min); 5169 } 5170 5171 if (isNumber(max) === false) { 5172 throw new TypeError('toRegexRange: expected the second argument to be a number.'); 5173 } 5174 5175 let opts = { relaxZeros: true, ...options }; 5176 if (typeof opts.strictZeros === 'boolean') { 5177 opts.relaxZeros = opts.strictZeros === false; 5178 } 5179 5180 let relax = String(opts.relaxZeros); 5181 let shorthand = String(opts.shorthand); 5182 let capture = String(opts.capture); 5183 let wrap = String(opts.wrap); 5184 let cacheKey = min + ':' + max + '=' + relax + shorthand + capture + wrap; 5185 5186 if (toRegexRange.cache.hasOwnProperty(cacheKey)) { 5187 return toRegexRange.cache[cacheKey].result; 5188 } 5189 5190 let a = Math.min(min, max); 5191 let b = Math.max(min, max); 5192 5193 if (Math.abs(a - b) === 1) { 5194 let result = min + '|' + max; 5195 if (opts.capture) { 5196 return `(${result})`; 5197 } 5198 if (opts.wrap === false) { 5199 return result; 5200 } 5201 return `(?:${result})`; 5202 } 5203 5204 let isPadded = hasPadding(min) || hasPadding(max); 5205 let state = { min, max, a, b }; 5206 let positives = []; 5207 let negatives = []; 5208 5209 if (isPadded) { 5210 state.isPadded = isPadded; 5211 state.maxLen = String(state.max).length; 5212 } 5213 5214 if (a < 0) { 5215 let newMin = b < 0 ? Math.abs(b) : 1; 5216 negatives = splitToPatterns(newMin, Math.abs(a), state, opts); 5217 a = state.a = 0; 5218 } 5219 5220 if (b >= 0) { 5221 positives = splitToPatterns(a, b, state, opts); 5222 } 5223 5224 state.negatives = negatives; 5225 state.positives = positives; 5226 state.result = collatePatterns(negatives, positives); 5227 5228 if (opts.capture === true) { 5229 state.result = `(${state.result})`; 5230 } else if (opts.wrap !== false && (positives.length + negatives.length) > 1) { 5231 state.result = `(?:${state.result})`; 5232 } 5233 5234 toRegexRange.cache[cacheKey] = state; 5235 return state.result; 5236 }; 5237 5238 function collatePatterns(neg, pos, options) { 5239 let onlyNegative = filterPatterns(neg, pos, '-', false) || []; 5240 let onlyPositive = filterPatterns(pos, neg, '', false) || []; 5241 let intersected = filterPatterns(neg, pos, '-?', true) || []; 5242 let subpatterns = onlyNegative.concat(intersected).concat(onlyPositive); 5243 return subpatterns.join('|'); 5244 } 5245 5246 function splitToRanges(min, max) { 5247 let nines = 1; 5248 let zeros = 1; 5249 5250 let stop = countNines(min, nines); 5251 let stops = new Set([max]); 5252 5253 while (min <= stop && stop <= max) { 5254 stops.add(stop); 5255 nines += 1; 5256 stop = countNines(min, nines); 5257 } 5258 5259 stop = countZeros(max + 1, zeros) - 1; 5260 5261 while (min < stop && stop <= max) { 5262 stops.add(stop); 5263 zeros += 1; 5264 stop = countZeros(max + 1, zeros) - 1; 5265 } 5266 5267 stops = [...stops]; 5268 stops.sort(compare); 5269 return stops; 5270 } 5271 5272 /** 5273 * Convert a range to a regex pattern 5274 * @param {Number} `start` 5275 * @param {Number} `stop` 5276 * @return {String} 5277 */ 5278 5279 function rangeToPattern(start, stop, options) { 5280 if (start === stop) { 5281 return { pattern: start, count: [], digits: 0 }; 5282 } 5283 5284 let zipped = zip(start, stop); 5285 let digits = zipped.length; 5286 let pattern = ''; 5287 let count = 0; 5288 5289 for (let i = 0; i < digits; i++) { 5290 let [startDigit, stopDigit] = zipped[i]; 5291 5292 if (startDigit === stopDigit) { 5293 pattern += startDigit; 5294 5295 } else if (startDigit !== '0' || stopDigit !== '9') { 5296 pattern += toCharacterClass(startDigit, stopDigit); 5297 5298 } else { 5299 count++; 5300 } 5301 } 5302 5303 if (count) { 5304 pattern += options.shorthand === true ? '\\d' : '[0-9]'; 5305 } 5306 5307 return { pattern, count: [count], digits }; 5308 } 5309 5310 function splitToPatterns(min, max, tok, options) { 5311 let ranges = splitToRanges(min, max); 5312 let tokens = []; 5313 let start = min; 5314 let prev; 5315 5316 for (let i = 0; i < ranges.length; i++) { 5317 let max = ranges[i]; 5318 let obj = rangeToPattern(String(start), String(max), options); 5319 let zeros = ''; 5320 5321 if (!tok.isPadded && prev && prev.pattern === obj.pattern) { 5322 if (prev.count.length > 1) { 5323 prev.count.pop(); 5324 } 5325 5326 prev.count.push(obj.count[0]); 5327 prev.string = prev.pattern + toQuantifier(prev.count); 5328 start = max + 1; 5329 continue; 5330 } 5331 5332 if (tok.isPadded) { 5333 zeros = padZeros(max, tok, options); 5334 } 5335 5336 obj.string = zeros + obj.pattern + toQuantifier(obj.count); 5337 tokens.push(obj); 5338 start = max + 1; 5339 prev = obj; 5340 } 5341 5342 return tokens; 5343 } 5344 5345 function filterPatterns(arr, comparison, prefix, intersection, options) { 5346 let result = []; 5347 5348 for (let ele of arr) { 5349 let { string } = ele; 5350 5351 // only push if _both_ are negative... 5352 if (!intersection && !contains(comparison, 'string', string)) { 5353 result.push(prefix + string); 5354 } 5355 5356 // or _both_ are positive 5357 if (intersection && contains(comparison, 'string', string)) { 5358 result.push(prefix + string); 5359 } 5360 } 5361 return result; 5362 } 5363 5364 /** 5365 * Zip strings 5366 */ 5367 5368 function zip(a, b) { 5369 let arr = []; 5370 for (let i = 0; i < a.length; i++) arr.push([a[i], b[i]]); 5371 return arr; 5372 } 5373 5374 function compare(a, b) { 5375 return a > b ? 1 : b > a ? -1 : 0; 5376 } 5377 5378 function contains(arr, key, val) { 5379 return arr.some(ele => ele[key] === val); 5380 } 5381 5382 function countNines(min, len) { 5383 return Number(String(min).slice(0, -len) + '9'.repeat(len)); 5384 } 5385 5386 function countZeros(integer, zeros) { 5387 return integer - (integer % Math.pow(10, zeros)); 5388 } 5389 5390 function toQuantifier(digits) { 5391 let [start = 0, stop = ''] = digits; 5392 if (stop || start > 1) { 5393 return `{${start + (stop ? ',' + stop : '')}}`; 5394 } 5395 return ''; 5396 } 5397 5398 function toCharacterClass(a, b, options) { 5399 return `[${a}${(b - a === 1) ? '' : '-'}${b}]`; 5400 } 5401 5402 function hasPadding(str) { 5403 return /^-?(0+)\d/.test(str); 5404 } 5405 5406 function padZeros(value, tok, options) { 5407 if (!tok.isPadded) { 5408 return value; 5409 } 5410 5411 let diff = Math.abs(tok.maxLen - String(value).length); 5412 let relax = options.relaxZeros !== false; 5413 5414 switch (diff) { 5415 case 0: 5416 return ''; 5417 case 1: 5418 return relax ? '0?' : '0'; 5419 case 2: 5420 return relax ? '0{0,2}' : '00'; 5421 default: { 5422 return relax ? `0{0,${diff}}` : `0{${diff}}`; 5423 } 5424 } 5425 } 5426 5427 /** 5428 * Cache 5429 */ 5430 5431 toRegexRange.cache = {}; 5432 toRegexRange.clearCache = () => (toRegexRange.cache = {}); 5433 5434 /** 5435 * Expose `toRegexRange` 5436 */ 5437 5438 toRegexRange_1 = toRegexRange; 5439 return toRegexRange_1; 936 5440 } 937 938 function splitToRanges(min, max) {939 let nines = 1;940 let zeros = 1;941 942 let stop = countNines(min, nines);943 let stops = new Set([max]);944 945 while (min <= stop && stop <= max) {946 stops.add(stop);947 nines += 1;948 stop = countNines(min, nines);949 }950 951 stop = countZeros(max + 1, zeros) - 1;952 953 while (min < stop && stop <= max) {954 stops.add(stop);955 zeros += 1;956 stop = countZeros(max + 1, zeros) - 1;957 }958 959 stops = [...stops];960 stops.sort(compare);961 return stops;962 }963 964 /**965 * Convert a range to a regex pattern966 * @param {Number} `start`967 * @param {Number} `stop`968 * @return {String}969 */970 971 function rangeToPattern(start, stop, options) {972 if (start === stop) {973 return { pattern: start, count: [], digits: 0 };974 }975 976 let zipped = zip(start, stop);977 let digits = zipped.length;978 let pattern = '';979 let count = 0;980 981 for (let i = 0; i < digits; i++) {982 let [startDigit, stopDigit] = zipped[i];983 984 if (startDigit === stopDigit) {985 pattern += startDigit;986 987 } else if (startDigit !== '0' || stopDigit !== '9') {988 pattern += toCharacterClass(startDigit, stopDigit);989 990 } else {991 count++;992 }993 }994 995 if (count) {996 pattern += options.shorthand === true ? '\\d' : '[0-9]';997 }998 999 return { pattern, count: [count], digits };1000 }1001 1002 function splitToPatterns(min, max, tok, options) {1003 let ranges = splitToRanges(min, max);1004 let tokens = [];1005 let start = min;1006 let prev;1007 1008 for (let i = 0; i < ranges.length; i++) {1009 let max = ranges[i];1010 let obj = rangeToPattern(String(start), String(max), options);1011 let zeros = '';1012 1013 if (!tok.isPadded && prev && prev.pattern === obj.pattern) {1014 if (prev.count.length > 1) {1015 prev.count.pop();1016 }1017 1018 prev.count.push(obj.count[0]);1019 prev.string = prev.pattern + toQuantifier(prev.count);1020 start = max + 1;1021 continue;1022 }1023 1024 if (tok.isPadded) {1025 zeros = padZeros(max, tok, options);1026 }1027 1028 obj.string = zeros + obj.pattern + toQuantifier(obj.count);1029 tokens.push(obj);1030 start = max + 1;1031 prev = obj;1032 }1033 1034 return tokens;1035 }1036 1037 function filterPatterns(arr, comparison, prefix, intersection, options) {1038 let result = [];1039 1040 for (let ele of arr) {1041 let { string } = ele;1042 1043 // only push if _both_ are negative...1044 if (!intersection && !contains(comparison, 'string', string)) {1045 result.push(prefix + string);1046 }1047 1048 // or _both_ are positive1049 if (intersection && contains(comparison, 'string', string)) {1050 result.push(prefix + string);1051 }1052 }1053 return result;1054 }1055 1056 /**1057 * Zip strings1058 */1059 1060 function zip(a, b) {1061 let arr = [];1062 for (let i = 0; i < a.length; i++) arr.push([a[i], b[i]]);1063 return arr;1064 }1065 1066 function compare(a, b) {1067 return a > b ? 1 : b > a ? -1 : 0;1068 }1069 1070 function contains(arr, key, val) {1071 return arr.some(ele => ele[key] === val);1072 }1073 1074 function countNines(min, len) {1075 return Number(String(min).slice(0, -len) + '9'.repeat(len));1076 }1077 1078 function countZeros(integer, zeros) {1079 return integer - (integer % Math.pow(10, zeros));1080 }1081 1082 function toQuantifier(digits) {1083 let [start = 0, stop = ''] = digits;1084 if (stop || start > 1) {1085 return `{${start + (stop ? ',' + stop : '')}}`;1086 }1087 return '';1088 }1089 1090 function toCharacterClass(a, b, options) {1091 return `[${a}${(b - a === 1) ? '' : '-'}${b}]`;1092 }1093 1094 function hasPadding(str) {1095 return /^-?(0+)\d/.test(str);1096 }1097 1098 function padZeros(value, tok, options) {1099 if (!tok.isPadded) {1100 return value;1101 }1102 1103 let diff = Math.abs(tok.maxLen - String(value).length);1104 let relax = options.relaxZeros !== false;1105 1106 switch (diff) {1107 case 0:1108 return '';1109 case 1:1110 return relax ? '0?' : '0';1111 case 2:1112 return relax ? '0{0,2}' : '00';1113 default: {1114 return relax ? `0{0,${diff}}` : `0{${diff}}`;1115 }1116 }1117 }1118 1119 /**1120 * Cache1121 */1122 1123 toRegexRange$1.cache = {};1124 toRegexRange$1.clearCache = () => (toRegexRange$1.cache = {});1125 1126 /**1127 * Expose `toRegexRange`1128 */1129 1130 var toRegexRange_1 = toRegexRange$1;1131 5441 1132 5442 /*! … … 1137 5447 */ 1138 5448 1139 const util = require$$2; 1140 const toRegexRange = toRegexRange_1; 1141 1142 const isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); 1143 1144 const transform = toNumber => { 1145 return value => toNumber === true ? Number(value) : String(value); 1146 }; 1147 1148 const isValidValue = value => { 1149 return typeof value === 'number' || (typeof value === 'string' && value !== ''); 1150 }; 1151 1152 const isNumber = num => Number.isInteger(+num); 1153 1154 const zeros = input => { 1155 let value = `${input}`; 1156 let index = -1; 1157 if (value[0] === '-') value = value.slice(1); 1158 if (value === '0') return false; 1159 while (value[++index] === '0'); 1160 return index > 0; 1161 }; 1162 1163 const stringify$3 = (start, end, options) => { 1164 if (typeof start === 'string' || typeof end === 'string') { 1165 return true; 1166 } 1167 return options.stringify === true; 1168 }; 1169 1170 const pad = (input, maxLength, toNumber) => { 1171 if (maxLength > 0) { 1172 let dash = input[0] === '-' ? '-' : ''; 1173 if (dash) input = input.slice(1); 1174 input = (dash + input.padStart(dash ? maxLength - 1 : maxLength, '0')); 1175 } 1176 if (toNumber === false) { 1177 return String(input); 1178 } 1179 return input; 1180 }; 1181 1182 const toMaxLen = (input, maxLength) => { 1183 let negative = input[0] === '-' ? '-' : ''; 1184 if (negative) { 1185 input = input.slice(1); 1186 maxLength--; 1187 } 1188 while (input.length < maxLength) input = '0' + input; 1189 return negative ? ('-' + input) : input; 1190 }; 1191 1192 const toSequence = (parts, options, maxLen) => { 1193 parts.negatives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); 1194 parts.positives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); 1195 1196 let prefix = options.capture ? '' : '?:'; 1197 let positives = ''; 1198 let negatives = ''; 1199 let result; 1200 1201 if (parts.positives.length) { 1202 positives = parts.positives.map(v => toMaxLen(String(v), maxLen)).join('|'); 1203 } 1204 1205 if (parts.negatives.length) { 1206 negatives = `-(${prefix}${parts.negatives.map(v => toMaxLen(String(v), maxLen)).join('|')})`; 1207 } 1208 1209 if (positives && negatives) { 1210 result = `${positives}|${negatives}`; 1211 } else { 1212 result = positives || negatives; 1213 } 1214 1215 if (options.wrap) { 1216 return `(${prefix}${result})`; 1217 } 1218 1219 return result; 1220 }; 1221 1222 const toRange = (a, b, isNumbers, options) => { 1223 if (isNumbers) { 1224 return toRegexRange(a, b, { wrap: false, ...options }); 1225 } 1226 1227 let start = String.fromCharCode(a); 1228 if (a === b) return start; 1229 1230 let stop = String.fromCharCode(b); 1231 return `[${start}-${stop}]`; 1232 }; 1233 1234 const toRegex = (start, end, options) => { 1235 if (Array.isArray(start)) { 1236 let wrap = options.wrap === true; 1237 let prefix = options.capture ? '' : '?:'; 1238 return wrap ? `(${prefix}${start.join('|')})` : start.join('|'); 1239 } 1240 return toRegexRange(start, end, options); 1241 }; 1242 1243 const rangeError = (...args) => { 1244 return new RangeError('Invalid range arguments: ' + util.inspect(...args)); 1245 }; 1246 1247 const invalidRange = (start, end, options) => { 1248 if (options.strictRanges === true) throw rangeError([start, end]); 1249 return []; 1250 }; 1251 1252 const invalidStep = (step, options) => { 1253 if (options.strictRanges === true) { 1254 throw new TypeError(`Expected step "${step}" to be a number`); 1255 } 1256 return []; 1257 }; 1258 1259 const fillNumbers = (start, end, step = 1, options = {}) => { 1260 let a = Number(start); 1261 let b = Number(end); 1262 1263 if (!Number.isInteger(a) || !Number.isInteger(b)) { 1264 if (options.strictRanges === true) throw rangeError([start, end]); 1265 return []; 1266 } 1267 1268 // fix negative zero 1269 if (a === 0) a = 0; 1270 if (b === 0) b = 0; 1271 1272 let descending = a > b; 1273 let startString = String(start); 1274 let endString = String(end); 1275 let stepString = String(step); 1276 step = Math.max(Math.abs(step), 1); 1277 1278 let padded = zeros(startString) || zeros(endString) || zeros(stepString); 1279 let maxLen = padded ? Math.max(startString.length, endString.length, stepString.length) : 0; 1280 let toNumber = padded === false && stringify$3(start, end, options) === false; 1281 let format = options.transform || transform(toNumber); 1282 1283 if (options.toRegex && step === 1) { 1284 return toRange(toMaxLen(start, maxLen), toMaxLen(end, maxLen), true, options); 1285 } 1286 1287 let parts = { negatives: [], positives: [] }; 1288 let push = num => parts[num < 0 ? 'negatives' : 'positives'].push(Math.abs(num)); 1289 let range = []; 1290 let index = 0; 1291 1292 while (descending ? a >= b : a <= b) { 1293 if (options.toRegex === true && step > 1) { 1294 push(a); 1295 } else { 1296 range.push(pad(format(a, index), maxLen, toNumber)); 1297 } 1298 a = descending ? a - step : a + step; 1299 index++; 1300 } 1301 1302 if (options.toRegex === true) { 1303 return step > 1 1304 ? toSequence(parts, options, maxLen) 1305 : toRegex(range, null, { wrap: false, ...options }); 1306 } 1307 1308 return range; 1309 }; 1310 1311 const fillLetters = (start, end, step = 1, options = {}) => { 1312 if ((!isNumber(start) && start.length > 1) || (!isNumber(end) && end.length > 1)) { 1313 return invalidRange(start, end, options); 1314 } 1315 1316 let format = options.transform || (val => String.fromCharCode(val)); 1317 let a = `${start}`.charCodeAt(0); 1318 let b = `${end}`.charCodeAt(0); 1319 1320 let descending = a > b; 1321 let min = Math.min(a, b); 1322 let max = Math.max(a, b); 1323 1324 if (options.toRegex && step === 1) { 1325 return toRange(min, max, false, options); 1326 } 1327 1328 let range = []; 1329 let index = 0; 1330 1331 while (descending ? a >= b : a <= b) { 1332 range.push(format(a, index)); 1333 a = descending ? a - step : a + step; 1334 index++; 1335 } 1336 1337 if (options.toRegex === true) { 1338 return toRegex(range, null, { wrap: false, options }); 1339 } 1340 1341 return range; 1342 }; 1343 1344 const fill$2 = (start, end, step, options = {}) => { 1345 if (end == null && isValidValue(start)) { 1346 return [start]; 1347 } 1348 1349 if (!isValidValue(start) || !isValidValue(end)) { 1350 return invalidRange(start, end, options); 1351 } 1352 1353 if (typeof step === 'function') { 1354 return fill$2(start, end, 1, { transform: step }); 1355 } 1356 1357 if (isObject(step)) { 1358 return fill$2(start, end, 0, step); 1359 } 1360 1361 let opts = { ...options }; 1362 if (opts.capture === true) opts.wrap = true; 1363 step = step || opts.step || 1; 1364 1365 if (!isNumber(step)) { 1366 if (step != null && !isObject(step)) return invalidStep(step, opts); 1367 return fill$2(start, end, 1, step); 1368 } 1369 1370 if (isNumber(start) && isNumber(end)) { 1371 return fillNumbers(start, end, step, opts); 1372 } 1373 1374 return fillLetters(start, end, Math.max(Math.abs(step), 1), opts); 1375 }; 1376 1377 var fillRange = fill$2; 1378 1379 const fill$1 = fillRange; 1380 const utils$1 = utils$3; 1381 1382 const compile$1 = (ast, options = {}) => { 1383 const walk = (node, parent = {}) => { 1384 const invalidBlock = utils$1.isInvalidBrace(parent); 1385 const invalidNode = node.invalid === true && options.escapeInvalid === true; 1386 const invalid = invalidBlock === true || invalidNode === true; 1387 const prefix = options.escapeInvalid === true ? '\\' : ''; 1388 let output = ''; 1389 1390 if (node.isOpen === true) { 1391 return prefix + node.value; 1392 } 1393 1394 if (node.isClose === true) { 1395 console.log('node.isClose', prefix, node.value); 1396 return prefix + node.value; 1397 } 1398 1399 if (node.type === 'open') { 1400 return invalid ? prefix + node.value : '('; 1401 } 1402 1403 if (node.type === 'close') { 1404 return invalid ? prefix + node.value : ')'; 1405 } 1406 1407 if (node.type === 'comma') { 1408 return node.prev.type === 'comma' ? '' : invalid ? node.value : '|'; 1409 } 1410 1411 if (node.value) { 1412 return node.value; 1413 } 1414 1415 if (node.nodes && node.ranges > 0) { 1416 const args = utils$1.reduce(node.nodes); 1417 const range = fill$1(...args, { ...options, wrap: false, toRegex: true, strictZeros: true }); 1418 1419 if (range.length !== 0) { 1420 return args.length > 1 && range.length > 1 ? `(${range})` : range; 1421 } 1422 } 1423 1424 if (node.nodes) { 1425 for (const child of node.nodes) { 1426 output += walk(child, node); 1427 } 1428 } 1429 1430 return output; 1431 }; 1432 1433 return walk(ast); 1434 }; 1435 1436 var compile_1 = compile$1; 1437 1438 const fill = fillRange; 1439 const stringify$2 = stringify$4; 1440 const utils = utils$3; 1441 1442 const append = (queue = '', stash = '', enclose = false) => { 1443 const result = []; 1444 1445 queue = [].concat(queue); 1446 stash = [].concat(stash); 1447 1448 if (!stash.length) return queue; 1449 if (!queue.length) { 1450 return enclose ? utils.flatten(stash).map(ele => `{${ele}}`) : stash; 1451 } 1452 1453 for (const item of queue) { 1454 if (Array.isArray(item)) { 1455 for (const value of item) { 1456 result.push(append(value, stash, enclose)); 1457 } 1458 } else { 1459 for (let ele of stash) { 1460 if (enclose === true && typeof ele === 'string') ele = `{${ele}}`; 1461 result.push(Array.isArray(ele) ? append(item, ele, enclose) : item + ele); 1462 } 1463 } 1464 } 1465 return utils.flatten(result); 1466 }; 1467 1468 const expand$1 = (ast, options = {}) => { 1469 const rangeLimit = options.rangeLimit === undefined ? 1000 : options.rangeLimit; 1470 1471 const walk = (node, parent = {}) => { 1472 node.queue = []; 1473 1474 let p = parent; 1475 let q = parent.queue; 1476 1477 while (p.type !== 'brace' && p.type !== 'root' && p.parent) { 1478 p = p.parent; 1479 q = p.queue; 1480 } 1481 1482 if (node.invalid || node.dollar) { 1483 q.push(append(q.pop(), stringify$2(node, options))); 1484 return; 1485 } 1486 1487 if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) { 1488 q.push(append(q.pop(), ['{}'])); 1489 return; 1490 } 1491 1492 if (node.nodes && node.ranges > 0) { 1493 const args = utils.reduce(node.nodes); 1494 1495 if (utils.exceedsLimit(...args, options.step, rangeLimit)) { 1496 throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.'); 1497 } 1498 1499 let range = fill(...args, options); 1500 if (range.length === 0) { 1501 range = stringify$2(node, options); 1502 } 1503 1504 q.push(append(q.pop(), range)); 1505 node.nodes = []; 1506 return; 1507 } 1508 1509 const enclose = utils.encloseBrace(node); 1510 let queue = node.queue; 1511 let block = node; 1512 1513 while (block.type !== 'brace' && block.type !== 'root' && block.parent) { 1514 block = block.parent; 1515 queue = block.queue; 1516 } 1517 1518 for (let i = 0; i < node.nodes.length; i++) { 1519 const child = node.nodes[i]; 1520 1521 if (child.type === 'comma' && node.type === 'brace') { 1522 if (i === 1) queue.push(''); 1523 queue.push(''); 1524 continue; 1525 } 1526 1527 if (child.type === 'close') { 1528 q.push(append(q.pop(), queue, enclose)); 1529 continue; 1530 } 1531 1532 if (child.value && child.type !== 'open') { 1533 queue.push(append(queue.pop(), child.value)); 1534 continue; 1535 } 1536 1537 if (child.nodes) { 1538 walk(child, node); 1539 } 1540 } 1541 1542 return queue; 1543 }; 1544 1545 return utils.flatten(walk(ast)); 1546 }; 1547 1548 var expand_1 = expand$1; 1549 1550 var constants$1 = { 1551 MAX_LENGTH: 10000, 1552 1553 // Digits 1554 CHAR_0: '0', /* 0 */ 1555 CHAR_9: '9', /* 9 */ 1556 1557 // Alphabet chars. 1558 CHAR_UPPERCASE_A: 'A', /* A */ 1559 CHAR_LOWERCASE_A: 'a', /* a */ 1560 CHAR_UPPERCASE_Z: 'Z', /* Z */ 1561 CHAR_LOWERCASE_Z: 'z', /* z */ 1562 1563 CHAR_LEFT_PARENTHESES: '(', /* ( */ 1564 CHAR_RIGHT_PARENTHESES: ')', /* ) */ 1565 1566 CHAR_ASTERISK: '*', /* * */ 1567 1568 // Non-alphabetic chars. 1569 CHAR_AMPERSAND: '&', /* & */ 1570 CHAR_AT: '@', /* @ */ 1571 CHAR_BACKSLASH: '\\', /* \ */ 1572 CHAR_BACKTICK: '`', /* ` */ 1573 CHAR_CARRIAGE_RETURN: '\r', /* \r */ 1574 CHAR_CIRCUMFLEX_ACCENT: '^', /* ^ */ 1575 CHAR_COLON: ':', /* : */ 1576 CHAR_COMMA: ',', /* , */ 1577 CHAR_DOLLAR: '$', /* . */ 1578 CHAR_DOT: '.', /* . */ 1579 CHAR_DOUBLE_QUOTE: '"', /* " */ 1580 CHAR_EQUAL: '=', /* = */ 1581 CHAR_EXCLAMATION_MARK: '!', /* ! */ 1582 CHAR_FORM_FEED: '\f', /* \f */ 1583 CHAR_FORWARD_SLASH: '/', /* / */ 1584 CHAR_HASH: '#', /* # */ 1585 CHAR_HYPHEN_MINUS: '-', /* - */ 1586 CHAR_LEFT_ANGLE_BRACKET: '<', /* < */ 1587 CHAR_LEFT_CURLY_BRACE: '{', /* { */ 1588 CHAR_LEFT_SQUARE_BRACKET: '[', /* [ */ 1589 CHAR_LINE_FEED: '\n', /* \n */ 1590 CHAR_NO_BREAK_SPACE: '\u00A0', /* \u00A0 */ 1591 CHAR_PERCENT: '%', /* % */ 1592 CHAR_PLUS: '+', /* + */ 1593 CHAR_QUESTION_MARK: '?', /* ? */ 1594 CHAR_RIGHT_ANGLE_BRACKET: '>', /* > */ 1595 CHAR_RIGHT_CURLY_BRACE: '}', /* } */ 1596 CHAR_RIGHT_SQUARE_BRACKET: ']', /* ] */ 1597 CHAR_SEMICOLON: ';', /* ; */ 1598 CHAR_SINGLE_QUOTE: '\'', /* ' */ 1599 CHAR_SPACE: ' ', /* */ 1600 CHAR_TAB: '\t', /* \t */ 1601 CHAR_UNDERSCORE: '_', /* _ */ 1602 CHAR_VERTICAL_LINE: '|', /* | */ 1603 CHAR_ZERO_WIDTH_NOBREAK_SPACE: '\uFEFF' /* \uFEFF */ 1604 }; 1605 1606 const stringify$1 = stringify$4; 1607 1608 /** 1609 * Constants 1610 */ 1611 1612 const { 1613 MAX_LENGTH, 1614 CHAR_BACKSLASH, /* \ */ 1615 CHAR_BACKTICK, /* ` */ 1616 CHAR_COMMA, /* , */ 1617 CHAR_DOT, /* . */ 1618 CHAR_LEFT_PARENTHESES, /* ( */ 1619 CHAR_RIGHT_PARENTHESES, /* ) */ 1620 CHAR_LEFT_CURLY_BRACE, /* { */ 1621 CHAR_RIGHT_CURLY_BRACE, /* } */ 1622 CHAR_LEFT_SQUARE_BRACKET, /* [ */ 1623 CHAR_RIGHT_SQUARE_BRACKET, /* ] */ 1624 CHAR_DOUBLE_QUOTE, /* " */ 1625 CHAR_SINGLE_QUOTE, /* ' */ 1626 CHAR_NO_BREAK_SPACE, 1627 CHAR_ZERO_WIDTH_NOBREAK_SPACE 1628 } = constants$1; 1629 1630 /** 1631 * parse 1632 */ 1633 1634 const parse$1 = (input, options = {}) => { 1635 if (typeof input !== 'string') { 1636 throw new TypeError('Expected a string'); 1637 } 1638 1639 const opts = options || {}; 1640 const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; 1641 if (input.length > max) { 1642 throw new SyntaxError(`Input length (${input.length}), exceeds max characters (${max})`); 1643 } 1644 1645 const ast = { type: 'root', input, nodes: [] }; 1646 const stack = [ast]; 1647 let block = ast; 1648 let prev = ast; 1649 let brackets = 0; 1650 const length = input.length; 1651 let index = 0; 1652 let depth = 0; 1653 let value; 1654 1655 /** 1656 * Helpers 1657 */ 1658 1659 const advance = () => input[index++]; 1660 const push = node => { 1661 if (node.type === 'text' && prev.type === 'dot') { 1662 prev.type = 'text'; 1663 } 1664 1665 if (prev && prev.type === 'text' && node.type === 'text') { 1666 prev.value += node.value; 1667 return; 1668 } 1669 1670 block.nodes.push(node); 1671 node.parent = block; 1672 node.prev = prev; 1673 prev = node; 1674 return node; 1675 }; 1676 1677 push({ type: 'bos' }); 1678 1679 while (index < length) { 1680 block = stack[stack.length - 1]; 1681 value = advance(); 1682 1683 /** 1684 * Invalid chars 1685 */ 1686 1687 if (value === CHAR_ZERO_WIDTH_NOBREAK_SPACE || value === CHAR_NO_BREAK_SPACE) { 1688 continue; 1689 } 1690 1691 /** 1692 * Escaped chars 1693 */ 1694 1695 if (value === CHAR_BACKSLASH) { 1696 push({ type: 'text', value: (options.keepEscaping ? value : '') + advance() }); 1697 continue; 1698 } 1699 1700 /** 1701 * Right square bracket (literal): ']' 1702 */ 1703 1704 if (value === CHAR_RIGHT_SQUARE_BRACKET) { 1705 push({ type: 'text', value: '\\' + value }); 1706 continue; 1707 } 1708 1709 /** 1710 * Left square bracket: '[' 1711 */ 1712 1713 if (value === CHAR_LEFT_SQUARE_BRACKET) { 1714 brackets++; 1715 1716 let next; 1717 1718 while (index < length && (next = advance())) { 1719 value += next; 1720 1721 if (next === CHAR_LEFT_SQUARE_BRACKET) { 1722 brackets++; 1723 continue; 1724 } 1725 1726 if (next === CHAR_BACKSLASH) { 1727 value += advance(); 1728 continue; 1729 } 1730 1731 if (next === CHAR_RIGHT_SQUARE_BRACKET) { 1732 brackets--; 1733 1734 if (brackets === 0) { 1735 break; 1736 } 1737 } 1738 } 1739 1740 push({ type: 'text', value }); 1741 continue; 1742 } 1743 1744 /** 1745 * Parentheses 1746 */ 1747 1748 if (value === CHAR_LEFT_PARENTHESES) { 1749 block = push({ type: 'paren', nodes: [] }); 1750 stack.push(block); 1751 push({ type: 'text', value }); 1752 continue; 1753 } 1754 1755 if (value === CHAR_RIGHT_PARENTHESES) { 1756 if (block.type !== 'paren') { 1757 push({ type: 'text', value }); 1758 continue; 1759 } 1760 block = stack.pop(); 1761 push({ type: 'text', value }); 1762 block = stack[stack.length - 1]; 1763 continue; 1764 } 1765 1766 /** 1767 * Quotes: '|"|` 1768 */ 1769 1770 if (value === CHAR_DOUBLE_QUOTE || value === CHAR_SINGLE_QUOTE || value === CHAR_BACKTICK) { 1771 const open = value; 1772 let next; 1773 1774 if (options.keepQuotes !== true) { 1775 value = ''; 1776 } 1777 1778 while (index < length && (next = advance())) { 1779 if (next === CHAR_BACKSLASH) { 1780 value += next + advance(); 1781 continue; 1782 } 1783 1784 if (next === open) { 1785 if (options.keepQuotes === true) value += next; 1786 break; 1787 } 1788 1789 value += next; 1790 } 1791 1792 push({ type: 'text', value }); 1793 continue; 1794 } 1795 1796 /** 1797 * Left curly brace: '{' 1798 */ 1799 1800 if (value === CHAR_LEFT_CURLY_BRACE) { 1801 depth++; 1802 1803 const dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true; 1804 const brace = { 1805 type: 'brace', 1806 open: true, 1807 close: false, 1808 dollar, 1809 depth, 1810 commas: 0, 1811 ranges: 0, 1812 nodes: [] 1813 }; 1814 1815 block = push(brace); 1816 stack.push(block); 1817 push({ type: 'open', value }); 1818 continue; 1819 } 1820 1821 /** 1822 * Right curly brace: '}' 1823 */ 1824 1825 if (value === CHAR_RIGHT_CURLY_BRACE) { 1826 if (block.type !== 'brace') { 1827 push({ type: 'text', value }); 1828 continue; 1829 } 1830 1831 const type = 'close'; 1832 block = stack.pop(); 1833 block.close = true; 1834 1835 push({ type, value }); 1836 depth--; 1837 1838 block = stack[stack.length - 1]; 1839 continue; 1840 } 1841 1842 /** 1843 * Comma: ',' 1844 */ 1845 1846 if (value === CHAR_COMMA && depth > 0) { 1847 if (block.ranges > 0) { 1848 block.ranges = 0; 1849 const open = block.nodes.shift(); 1850 block.nodes = [open, { type: 'text', value: stringify$1(block) }]; 1851 } 1852 1853 push({ type: 'comma', value }); 1854 block.commas++; 1855 continue; 1856 } 1857 1858 /** 1859 * Dot: '.' 1860 */ 1861 1862 if (value === CHAR_DOT && depth > 0 && block.commas === 0) { 1863 const siblings = block.nodes; 1864 1865 if (depth === 0 || siblings.length === 0) { 1866 push({ type: 'text', value }); 1867 continue; 1868 } 1869 1870 if (prev.type === 'dot') { 1871 block.range = []; 1872 prev.value += value; 1873 prev.type = 'range'; 1874 1875 if (block.nodes.length !== 3 && block.nodes.length !== 5) { 1876 block.invalid = true; 1877 block.ranges = 0; 1878 prev.type = 'text'; 1879 continue; 1880 } 1881 1882 block.ranges++; 1883 block.args = []; 1884 continue; 1885 } 1886 1887 if (prev.type === 'range') { 1888 siblings.pop(); 1889 1890 const before = siblings[siblings.length - 1]; 1891 before.value += prev.value + value; 1892 prev = before; 1893 block.ranges--; 1894 continue; 1895 } 1896 1897 push({ type: 'dot', value }); 1898 continue; 1899 } 1900 1901 /** 1902 * Text 1903 */ 1904 1905 push({ type: 'text', value }); 1906 } 1907 1908 // Mark imbalanced braces and brackets as invalid 1909 do { 1910 block = stack.pop(); 1911 1912 if (block.type !== 'root') { 1913 block.nodes.forEach(node => { 1914 if (!node.nodes) { 1915 if (node.type === 'open') node.isOpen = true; 1916 if (node.type === 'close') node.isClose = true; 1917 if (!node.nodes) node.type = 'text'; 1918 node.invalid = true; 1919 } 1920 }); 1921 1922 // get the location of the block on parent.nodes (block's siblings) 1923 const parent = stack[stack.length - 1]; 1924 const index = parent.nodes.indexOf(block); 1925 // replace the (invalid) block with it's nodes 1926 parent.nodes.splice(index, 1, ...block.nodes); 1927 } 1928 } while (stack.length > 0); 1929 1930 push({ type: 'eos' }); 1931 return ast; 1932 }; 1933 1934 var parse_1 = parse$1; 1935 1936 const stringify = stringify$4; 1937 const compile = compile_1; 1938 const expand = expand_1; 1939 const parse = parse_1; 1940 1941 /** 1942 * Expand the given pattern or create a regex-compatible string. 1943 * 1944 * ```js 1945 * const braces = require('braces'); 1946 * console.log(braces('{a,b,c}', { compile: true })); //=> ['(a|b|c)'] 1947 * console.log(braces('{a,b,c}')); //=> ['a', 'b', 'c'] 1948 * ``` 1949 * @param {String} `str` 1950 * @param {Object} `options` 1951 * @return {String} 1952 * @api public 1953 */ 1954 1955 const braces$1 = (input, options = {}) => { 1956 let output = []; 1957 1958 if (Array.isArray(input)) { 1959 for (const pattern of input) { 1960 const result = braces$1.create(pattern, options); 1961 if (Array.isArray(result)) { 1962 output.push(...result); 1963 } else { 1964 output.push(result); 1965 } 1966 } 1967 } else { 1968 output = [].concat(braces$1.create(input, options)); 1969 } 1970 1971 if (options && options.expand === true && options.nodupes === true) { 1972 output = [...new Set(output)]; 1973 } 1974 return output; 1975 }; 1976 1977 /** 1978 * Parse the given `str` with the given `options`. 1979 * 1980 * ```js 1981 * // braces.parse(pattern, [, options]); 1982 * const ast = braces.parse('a/{b,c}/d'); 1983 * console.log(ast); 1984 * ``` 1985 * @param {String} pattern Brace pattern to parse 1986 * @param {Object} options 1987 * @return {Object} Returns an AST 1988 * @api public 1989 */ 1990 1991 braces$1.parse = (input, options = {}) => parse(input, options); 1992 1993 /** 1994 * Creates a braces string from an AST, or an AST node. 1995 * 1996 * ```js 1997 * const braces = require('braces'); 1998 * let ast = braces.parse('foo/{a,b}/bar'); 1999 * console.log(stringify(ast.nodes[2])); //=> '{a,b}' 2000 * ``` 2001 * @param {String} `input` Brace pattern or AST. 2002 * @param {Object} `options` 2003 * @return {Array} Returns an array of expanded values. 2004 * @api public 2005 */ 2006 2007 braces$1.stringify = (input, options = {}) => { 2008 if (typeof input === 'string') { 2009 return stringify(braces$1.parse(input, options), options); 2010 } 2011 return stringify(input, options); 2012 }; 2013 2014 /** 2015 * Compiles a brace pattern into a regex-compatible, optimized string. 2016 * This method is called by the main [braces](#braces) function by default. 2017 * 2018 * ```js 2019 * const braces = require('braces'); 2020 * console.log(braces.compile('a/{b,c}/d')); 2021 * //=> ['a/(b|c)/d'] 2022 * ``` 2023 * @param {String} `input` Brace pattern or AST. 2024 * @param {Object} `options` 2025 * @return {Array} Returns an array of expanded values. 2026 * @api public 2027 */ 2028 2029 braces$1.compile = (input, options = {}) => { 2030 if (typeof input === 'string') { 2031 input = braces$1.parse(input, options); 2032 } 2033 return compile(input, options); 2034 }; 2035 2036 /** 2037 * Expands a brace pattern into an array. This method is called by the 2038 * main [braces](#braces) function when `options.expand` is true. Before 2039 * using this method it's recommended that you read the [performance notes](#performance)) 2040 * and advantages of using [.compile](#compile) instead. 2041 * 2042 * ```js 2043 * const braces = require('braces'); 2044 * console.log(braces.expand('a/{b,c}/d')); 2045 * //=> ['a/b/d', 'a/c/d']; 2046 * ``` 2047 * @param {String} `pattern` Brace pattern 2048 * @param {Object} `options` 2049 * @return {Array} Returns an array of expanded values. 2050 * @api public 2051 */ 2052 2053 braces$1.expand = (input, options = {}) => { 2054 if (typeof input === 'string') { 2055 input = braces$1.parse(input, options); 2056 } 2057 2058 let result = expand(input, options); 2059 2060 // filter out empty strings if specified 2061 if (options.noempty === true) { 2062 result = result.filter(Boolean); 2063 } 2064 2065 // filter out duplicates if specified 2066 if (options.nodupes === true) { 2067 result = [...new Set(result)]; 2068 } 2069 2070 return result; 2071 }; 2072 2073 /** 2074 * Processes a brace pattern and returns either an expanded array 2075 * (if `options.expand` is true), a highly optimized regex-compatible string. 2076 * This method is called by the main [braces](#braces) function. 2077 * 2078 * ```js 2079 * const braces = require('braces'); 2080 * console.log(braces.create('user-{200..300}/project-{a,b,c}-{1..10}')) 2081 * //=> 'user-(20[0-9]|2[1-9][0-9]|300)/project-(a|b|c)-([1-9]|10)' 2082 * ``` 2083 * @param {String} `pattern` Brace pattern 2084 * @param {Object} `options` 2085 * @return {Array} Returns an array of expanded values. 2086 * @api public 2087 */ 2088 2089 braces$1.create = (input, options = {}) => { 2090 if (input === '' || input.length < 3) { 2091 return [input]; 2092 } 2093 2094 return options.expand !== true 2095 ? braces$1.compile(input, options) 2096 : braces$1.expand(input, options); 2097 }; 2098 2099 /** 2100 * Expose "braces" 2101 */ 2102 2103 var braces_1 = braces$1; 5449 var fillRange; 5450 var hasRequiredFillRange; 5451 5452 function requireFillRange () { 5453 if (hasRequiredFillRange) return fillRange; 5454 hasRequiredFillRange = 1; 5455 5456 const util = require$$2; 5457 const toRegexRange = /*@__PURE__*/ requireToRegexRange(); 5458 5459 const isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); 5460 5461 const transform = toNumber => { 5462 return value => toNumber === true ? Number(value) : String(value); 5463 }; 5464 5465 const isValidValue = value => { 5466 return typeof value === 'number' || (typeof value === 'string' && value !== ''); 5467 }; 5468 5469 const isNumber = num => Number.isInteger(+num); 5470 5471 const zeros = input => { 5472 let value = `${input}`; 5473 let index = -1; 5474 if (value[0] === '-') value = value.slice(1); 5475 if (value === '0') return false; 5476 while (value[++index] === '0'); 5477 return index > 0; 5478 }; 5479 5480 const stringify = (start, end, options) => { 5481 if (typeof start === 'string' || typeof end === 'string') { 5482 return true; 5483 } 5484 return options.stringify === true; 5485 }; 5486 5487 const pad = (input, maxLength, toNumber) => { 5488 if (maxLength > 0) { 5489 let dash = input[0] === '-' ? '-' : ''; 5490 if (dash) input = input.slice(1); 5491 input = (dash + input.padStart(dash ? maxLength - 1 : maxLength, '0')); 5492 } 5493 if (toNumber === false) { 5494 return String(input); 5495 } 5496 return input; 5497 }; 5498 5499 const toMaxLen = (input, maxLength) => { 5500 let negative = input[0] === '-' ? '-' : ''; 5501 if (negative) { 5502 input = input.slice(1); 5503 maxLength--; 5504 } 5505 while (input.length < maxLength) input = '0' + input; 5506 return negative ? ('-' + input) : input; 5507 }; 5508 5509 const toSequence = (parts, options, maxLen) => { 5510 parts.negatives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); 5511 parts.positives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); 5512 5513 let prefix = options.capture ? '' : '?:'; 5514 let positives = ''; 5515 let negatives = ''; 5516 let result; 5517 5518 if (parts.positives.length) { 5519 positives = parts.positives.map(v => toMaxLen(String(v), maxLen)).join('|'); 5520 } 5521 5522 if (parts.negatives.length) { 5523 negatives = `-(${prefix}${parts.negatives.map(v => toMaxLen(String(v), maxLen)).join('|')})`; 5524 } 5525 5526 if (positives && negatives) { 5527 result = `${positives}|${negatives}`; 5528 } else { 5529 result = positives || negatives; 5530 } 5531 5532 if (options.wrap) { 5533 return `(${prefix}${result})`; 5534 } 5535 5536 return result; 5537 }; 5538 5539 const toRange = (a, b, isNumbers, options) => { 5540 if (isNumbers) { 5541 return toRegexRange(a, b, { wrap: false, ...options }); 5542 } 5543 5544 let start = String.fromCharCode(a); 5545 if (a === b) return start; 5546 5547 let stop = String.fromCharCode(b); 5548 return `[${start}-${stop}]`; 5549 }; 5550 5551 const toRegex = (start, end, options) => { 5552 if (Array.isArray(start)) { 5553 let wrap = options.wrap === true; 5554 let prefix = options.capture ? '' : '?:'; 5555 return wrap ? `(${prefix}${start.join('|')})` : start.join('|'); 5556 } 5557 return toRegexRange(start, end, options); 5558 }; 5559 5560 const rangeError = (...args) => { 5561 return new RangeError('Invalid range arguments: ' + util.inspect(...args)); 5562 }; 5563 5564 const invalidRange = (start, end, options) => { 5565 if (options.strictRanges === true) throw rangeError([start, end]); 5566 return []; 5567 }; 5568 5569 const invalidStep = (step, options) => { 5570 if (options.strictRanges === true) { 5571 throw new TypeError(`Expected step "${step}" to be a number`); 5572 } 5573 return []; 5574 }; 5575 5576 const fillNumbers = (start, end, step = 1, options = {}) => { 5577 let a = Number(start); 5578 let b = Number(end); 5579 5580 if (!Number.isInteger(a) || !Number.isInteger(b)) { 5581 if (options.strictRanges === true) throw rangeError([start, end]); 5582 return []; 5583 } 5584 5585 // fix negative zero 5586 if (a === 0) a = 0; 5587 if (b === 0) b = 0; 5588 5589 let descending = a > b; 5590 let startString = String(start); 5591 let endString = String(end); 5592 let stepString = String(step); 5593 step = Math.max(Math.abs(step), 1); 5594 5595 let padded = zeros(startString) || zeros(endString) || zeros(stepString); 5596 let maxLen = padded ? Math.max(startString.length, endString.length, stepString.length) : 0; 5597 let toNumber = padded === false && stringify(start, end, options) === false; 5598 let format = options.transform || transform(toNumber); 5599 5600 if (options.toRegex && step === 1) { 5601 return toRange(toMaxLen(start, maxLen), toMaxLen(end, maxLen), true, options); 5602 } 5603 5604 let parts = { negatives: [], positives: [] }; 5605 let push = num => parts[num < 0 ? 'negatives' : 'positives'].push(Math.abs(num)); 5606 let range = []; 5607 let index = 0; 5608 5609 while (descending ? a >= b : a <= b) { 5610 if (options.toRegex === true && step > 1) { 5611 push(a); 5612 } else { 5613 range.push(pad(format(a, index), maxLen, toNumber)); 5614 } 5615 a = descending ? a - step : a + step; 5616 index++; 5617 } 5618 5619 if (options.toRegex === true) { 5620 return step > 1 5621 ? toSequence(parts, options, maxLen) 5622 : toRegex(range, null, { wrap: false, ...options }); 5623 } 5624 5625 return range; 5626 }; 5627 5628 const fillLetters = (start, end, step = 1, options = {}) => { 5629 if ((!isNumber(start) && start.length > 1) || (!isNumber(end) && end.length > 1)) { 5630 return invalidRange(start, end, options); 5631 } 5632 5633 let format = options.transform || (val => String.fromCharCode(val)); 5634 let a = `${start}`.charCodeAt(0); 5635 let b = `${end}`.charCodeAt(0); 5636 5637 let descending = a > b; 5638 let min = Math.min(a, b); 5639 let max = Math.max(a, b); 5640 5641 if (options.toRegex && step === 1) { 5642 return toRange(min, max, false, options); 5643 } 5644 5645 let range = []; 5646 let index = 0; 5647 5648 while (descending ? a >= b : a <= b) { 5649 range.push(format(a, index)); 5650 a = descending ? a - step : a + step; 5651 index++; 5652 } 5653 5654 if (options.toRegex === true) { 5655 return toRegex(range, null, { wrap: false, options }); 5656 } 5657 5658 return range; 5659 }; 5660 5661 const fill = (start, end, step, options = {}) => { 5662 if (end == null && isValidValue(start)) { 5663 return [start]; 5664 } 5665 5666 if (!isValidValue(start) || !isValidValue(end)) { 5667 return invalidRange(start, end, options); 5668 } 5669 5670 if (typeof step === 'function') { 5671 return fill(start, end, 1, { transform: step }); 5672 } 5673 5674 if (isObject(step)) { 5675 return fill(start, end, 0, step); 5676 } 5677 5678 let opts = { ...options }; 5679 if (opts.capture === true) opts.wrap = true; 5680 step = step || opts.step || 1; 5681 5682 if (!isNumber(step)) { 5683 if (step != null && !isObject(step)) return invalidStep(step, opts); 5684 return fill(start, end, 1, step); 5685 } 5686 5687 if (isNumber(start) && isNumber(end)) { 5688 return fillNumbers(start, end, step, opts); 5689 } 5690 5691 return fillLetters(start, end, Math.max(Math.abs(step), 1), opts); 5692 }; 5693 5694 fillRange = fill; 5695 return fillRange; 5696 } 5697 5698 var compile_1; 5699 var hasRequiredCompile; 5700 5701 function requireCompile () { 5702 if (hasRequiredCompile) return compile_1; 5703 hasRequiredCompile = 1; 5704 5705 const fill = /*@__PURE__*/ requireFillRange(); 5706 const utils = /*@__PURE__*/ requireUtils(); 5707 5708 const compile = (ast, options = {}) => { 5709 const walk = (node, parent = {}) => { 5710 const invalidBlock = utils.isInvalidBrace(parent); 5711 const invalidNode = node.invalid === true && options.escapeInvalid === true; 5712 const invalid = invalidBlock === true || invalidNode === true; 5713 const prefix = options.escapeInvalid === true ? '\\' : ''; 5714 let output = ''; 5715 5716 if (node.isOpen === true) { 5717 return prefix + node.value; 5718 } 5719 5720 if (node.isClose === true) { 5721 console.log('node.isClose', prefix, node.value); 5722 return prefix + node.value; 5723 } 5724 5725 if (node.type === 'open') { 5726 return invalid ? prefix + node.value : '('; 5727 } 5728 5729 if (node.type === 'close') { 5730 return invalid ? prefix + node.value : ')'; 5731 } 5732 5733 if (node.type === 'comma') { 5734 return node.prev.type === 'comma' ? '' : invalid ? node.value : '|'; 5735 } 5736 5737 if (node.value) { 5738 return node.value; 5739 } 5740 5741 if (node.nodes && node.ranges > 0) { 5742 const args = utils.reduce(node.nodes); 5743 const range = fill(...args, { ...options, wrap: false, toRegex: true, strictZeros: true }); 5744 5745 if (range.length !== 0) { 5746 return args.length > 1 && range.length > 1 ? `(${range})` : range; 5747 } 5748 } 5749 5750 if (node.nodes) { 5751 for (const child of node.nodes) { 5752 output += walk(child, node); 5753 } 5754 } 5755 5756 return output; 5757 }; 5758 5759 return walk(ast); 5760 }; 5761 5762 compile_1 = compile; 5763 return compile_1; 5764 } 5765 5766 var expand_1; 5767 var hasRequiredExpand; 5768 5769 function requireExpand () { 5770 if (hasRequiredExpand) return expand_1; 5771 hasRequiredExpand = 1; 5772 5773 const fill = /*@__PURE__*/ requireFillRange(); 5774 const stringify = /*@__PURE__*/ requireStringify(); 5775 const utils = /*@__PURE__*/ requireUtils(); 5776 5777 const append = (queue = '', stash = '', enclose = false) => { 5778 const result = []; 5779 5780 queue = [].concat(queue); 5781 stash = [].concat(stash); 5782 5783 if (!stash.length) return queue; 5784 if (!queue.length) { 5785 return enclose ? utils.flatten(stash).map(ele => `{${ele}}`) : stash; 5786 } 5787 5788 for (const item of queue) { 5789 if (Array.isArray(item)) { 5790 for (const value of item) { 5791 result.push(append(value, stash, enclose)); 5792 } 5793 } else { 5794 for (let ele of stash) { 5795 if (enclose === true && typeof ele === 'string') ele = `{${ele}}`; 5796 result.push(Array.isArray(ele) ? append(item, ele, enclose) : item + ele); 5797 } 5798 } 5799 } 5800 return utils.flatten(result); 5801 }; 5802 5803 const expand = (ast, options = {}) => { 5804 const rangeLimit = options.rangeLimit === undefined ? 1000 : options.rangeLimit; 5805 5806 const walk = (node, parent = {}) => { 5807 node.queue = []; 5808 5809 let p = parent; 5810 let q = parent.queue; 5811 5812 while (p.type !== 'brace' && p.type !== 'root' && p.parent) { 5813 p = p.parent; 5814 q = p.queue; 5815 } 5816 5817 if (node.invalid || node.dollar) { 5818 q.push(append(q.pop(), stringify(node, options))); 5819 return; 5820 } 5821 5822 if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) { 5823 q.push(append(q.pop(), ['{}'])); 5824 return; 5825 } 5826 5827 if (node.nodes && node.ranges > 0) { 5828 const args = utils.reduce(node.nodes); 5829 5830 if (utils.exceedsLimit(...args, options.step, rangeLimit)) { 5831 throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.'); 5832 } 5833 5834 let range = fill(...args, options); 5835 if (range.length === 0) { 5836 range = stringify(node, options); 5837 } 5838 5839 q.push(append(q.pop(), range)); 5840 node.nodes = []; 5841 return; 5842 } 5843 5844 const enclose = utils.encloseBrace(node); 5845 let queue = node.queue; 5846 let block = node; 5847 5848 while (block.type !== 'brace' && block.type !== 'root' && block.parent) { 5849 block = block.parent; 5850 queue = block.queue; 5851 } 5852 5853 for (let i = 0; i < node.nodes.length; i++) { 5854 const child = node.nodes[i]; 5855 5856 if (child.type === 'comma' && node.type === 'brace') { 5857 if (i === 1) queue.push(''); 5858 queue.push(''); 5859 continue; 5860 } 5861 5862 if (child.type === 'close') { 5863 q.push(append(q.pop(), queue, enclose)); 5864 continue; 5865 } 5866 5867 if (child.value && child.type !== 'open') { 5868 queue.push(append(queue.pop(), child.value)); 5869 continue; 5870 } 5871 5872 if (child.nodes) { 5873 walk(child, node); 5874 } 5875 } 5876 5877 return queue; 5878 }; 5879 5880 return utils.flatten(walk(ast)); 5881 }; 5882 5883 expand_1 = expand; 5884 return expand_1; 5885 } 5886 5887 var constants$1; 5888 var hasRequiredConstants$1; 5889 5890 function requireConstants$1 () { 5891 if (hasRequiredConstants$1) return constants$1; 5892 hasRequiredConstants$1 = 1; 5893 5894 constants$1 = { 5895 MAX_LENGTH: 10000, 5896 5897 // Digits 5898 CHAR_0: '0', /* 0 */ 5899 CHAR_9: '9', /* 9 */ 5900 5901 // Alphabet chars. 5902 CHAR_UPPERCASE_A: 'A', /* A */ 5903 CHAR_LOWERCASE_A: 'a', /* a */ 5904 CHAR_UPPERCASE_Z: 'Z', /* Z */ 5905 CHAR_LOWERCASE_Z: 'z', /* z */ 5906 5907 CHAR_LEFT_PARENTHESES: '(', /* ( */ 5908 CHAR_RIGHT_PARENTHESES: ')', /* ) */ 5909 5910 CHAR_ASTERISK: '*', /* * */ 5911 5912 // Non-alphabetic chars. 5913 CHAR_AMPERSAND: '&', /* & */ 5914 CHAR_AT: '@', /* @ */ 5915 CHAR_BACKSLASH: '\\', /* \ */ 5916 CHAR_BACKTICK: '`', /* ` */ 5917 CHAR_CARRIAGE_RETURN: '\r', /* \r */ 5918 CHAR_CIRCUMFLEX_ACCENT: '^', /* ^ */ 5919 CHAR_COLON: ':', /* : */ 5920 CHAR_COMMA: ',', /* , */ 5921 CHAR_DOLLAR: '$', /* . */ 5922 CHAR_DOT: '.', /* . */ 5923 CHAR_DOUBLE_QUOTE: '"', /* " */ 5924 CHAR_EQUAL: '=', /* = */ 5925 CHAR_EXCLAMATION_MARK: '!', /* ! */ 5926 CHAR_FORM_FEED: '\f', /* \f */ 5927 CHAR_FORWARD_SLASH: '/', /* / */ 5928 CHAR_HASH: '#', /* # */ 5929 CHAR_HYPHEN_MINUS: '-', /* - */ 5930 CHAR_LEFT_ANGLE_BRACKET: '<', /* < */ 5931 CHAR_LEFT_CURLY_BRACE: '{', /* { */ 5932 CHAR_LEFT_SQUARE_BRACKET: '[', /* [ */ 5933 CHAR_LINE_FEED: '\n', /* \n */ 5934 CHAR_NO_BREAK_SPACE: '\u00A0', /* \u00A0 */ 5935 CHAR_PERCENT: '%', /* % */ 5936 CHAR_PLUS: '+', /* + */ 5937 CHAR_QUESTION_MARK: '?', /* ? */ 5938 CHAR_RIGHT_ANGLE_BRACKET: '>', /* > */ 5939 CHAR_RIGHT_CURLY_BRACE: '}', /* } */ 5940 CHAR_RIGHT_SQUARE_BRACKET: ']', /* ] */ 5941 CHAR_SEMICOLON: ';', /* ; */ 5942 CHAR_SINGLE_QUOTE: '\'', /* ' */ 5943 CHAR_SPACE: ' ', /* */ 5944 CHAR_TAB: '\t', /* \t */ 5945 CHAR_UNDERSCORE: '_', /* _ */ 5946 CHAR_VERTICAL_LINE: '|', /* | */ 5947 CHAR_ZERO_WIDTH_NOBREAK_SPACE: '\uFEFF' /* \uFEFF */ 5948 }; 5949 return constants$1; 5950 } 5951 5952 var parse_1; 5953 var hasRequiredParse; 5954 5955 function requireParse () { 5956 if (hasRequiredParse) return parse_1; 5957 hasRequiredParse = 1; 5958 5959 const stringify = /*@__PURE__*/ requireStringify(); 5960 5961 /** 5962 * Constants 5963 */ 5964 5965 const { 5966 MAX_LENGTH, 5967 CHAR_BACKSLASH, /* \ */ 5968 CHAR_BACKTICK, /* ` */ 5969 CHAR_COMMA, /* , */ 5970 CHAR_DOT, /* . */ 5971 CHAR_LEFT_PARENTHESES, /* ( */ 5972 CHAR_RIGHT_PARENTHESES, /* ) */ 5973 CHAR_LEFT_CURLY_BRACE, /* { */ 5974 CHAR_RIGHT_CURLY_BRACE, /* } */ 5975 CHAR_LEFT_SQUARE_BRACKET, /* [ */ 5976 CHAR_RIGHT_SQUARE_BRACKET, /* ] */ 5977 CHAR_DOUBLE_QUOTE, /* " */ 5978 CHAR_SINGLE_QUOTE, /* ' */ 5979 CHAR_NO_BREAK_SPACE, 5980 CHAR_ZERO_WIDTH_NOBREAK_SPACE 5981 } = /*@__PURE__*/ requireConstants$1(); 5982 5983 /** 5984 * parse 5985 */ 5986 5987 const parse = (input, options = {}) => { 5988 if (typeof input !== 'string') { 5989 throw new TypeError('Expected a string'); 5990 } 5991 5992 const opts = options || {}; 5993 const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; 5994 if (input.length > max) { 5995 throw new SyntaxError(`Input length (${input.length}), exceeds max characters (${max})`); 5996 } 5997 5998 const ast = { type: 'root', input, nodes: [] }; 5999 const stack = [ast]; 6000 let block = ast; 6001 let prev = ast; 6002 let brackets = 0; 6003 const length = input.length; 6004 let index = 0; 6005 let depth = 0; 6006 let value; 6007 6008 /** 6009 * Helpers 6010 */ 6011 6012 const advance = () => input[index++]; 6013 const push = node => { 6014 if (node.type === 'text' && prev.type === 'dot') { 6015 prev.type = 'text'; 6016 } 6017 6018 if (prev && prev.type === 'text' && node.type === 'text') { 6019 prev.value += node.value; 6020 return; 6021 } 6022 6023 block.nodes.push(node); 6024 node.parent = block; 6025 node.prev = prev; 6026 prev = node; 6027 return node; 6028 }; 6029 6030 push({ type: 'bos' }); 6031 6032 while (index < length) { 6033 block = stack[stack.length - 1]; 6034 value = advance(); 6035 6036 /** 6037 * Invalid chars 6038 */ 6039 6040 if (value === CHAR_ZERO_WIDTH_NOBREAK_SPACE || value === CHAR_NO_BREAK_SPACE) { 6041 continue; 6042 } 6043 6044 /** 6045 * Escaped chars 6046 */ 6047 6048 if (value === CHAR_BACKSLASH) { 6049 push({ type: 'text', value: (options.keepEscaping ? value : '') + advance() }); 6050 continue; 6051 } 6052 6053 /** 6054 * Right square bracket (literal): ']' 6055 */ 6056 6057 if (value === CHAR_RIGHT_SQUARE_BRACKET) { 6058 push({ type: 'text', value: '\\' + value }); 6059 continue; 6060 } 6061 6062 /** 6063 * Left square bracket: '[' 6064 */ 6065 6066 if (value === CHAR_LEFT_SQUARE_BRACKET) { 6067 brackets++; 6068 6069 let next; 6070 6071 while (index < length && (next = advance())) { 6072 value += next; 6073 6074 if (next === CHAR_LEFT_SQUARE_BRACKET) { 6075 brackets++; 6076 continue; 6077 } 6078 6079 if (next === CHAR_BACKSLASH) { 6080 value += advance(); 6081 continue; 6082 } 6083 6084 if (next === CHAR_RIGHT_SQUARE_BRACKET) { 6085 brackets--; 6086 6087 if (brackets === 0) { 6088 break; 6089 } 6090 } 6091 } 6092 6093 push({ type: 'text', value }); 6094 continue; 6095 } 6096 6097 /** 6098 * Parentheses 6099 */ 6100 6101 if (value === CHAR_LEFT_PARENTHESES) { 6102 block = push({ type: 'paren', nodes: [] }); 6103 stack.push(block); 6104 push({ type: 'text', value }); 6105 continue; 6106 } 6107 6108 if (value === CHAR_RIGHT_PARENTHESES) { 6109 if (block.type !== 'paren') { 6110 push({ type: 'text', value }); 6111 continue; 6112 } 6113 block = stack.pop(); 6114 push({ type: 'text', value }); 6115 block = stack[stack.length - 1]; 6116 continue; 6117 } 6118 6119 /** 6120 * Quotes: '|"|` 6121 */ 6122 6123 if (value === CHAR_DOUBLE_QUOTE || value === CHAR_SINGLE_QUOTE || value === CHAR_BACKTICK) { 6124 const open = value; 6125 let next; 6126 6127 if (options.keepQuotes !== true) { 6128 value = ''; 6129 } 6130 6131 while (index < length && (next = advance())) { 6132 if (next === CHAR_BACKSLASH) { 6133 value += next + advance(); 6134 continue; 6135 } 6136 6137 if (next === open) { 6138 if (options.keepQuotes === true) value += next; 6139 break; 6140 } 6141 6142 value += next; 6143 } 6144 6145 push({ type: 'text', value }); 6146 continue; 6147 } 6148 6149 /** 6150 * Left curly brace: '{' 6151 */ 6152 6153 if (value === CHAR_LEFT_CURLY_BRACE) { 6154 depth++; 6155 6156 const dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true; 6157 const brace = { 6158 type: 'brace', 6159 open: true, 6160 close: false, 6161 dollar, 6162 depth, 6163 commas: 0, 6164 ranges: 0, 6165 nodes: [] 6166 }; 6167 6168 block = push(brace); 6169 stack.push(block); 6170 push({ type: 'open', value }); 6171 continue; 6172 } 6173 6174 /** 6175 * Right curly brace: '}' 6176 */ 6177 6178 if (value === CHAR_RIGHT_CURLY_BRACE) { 6179 if (block.type !== 'brace') { 6180 push({ type: 'text', value }); 6181 continue; 6182 } 6183 6184 const type = 'close'; 6185 block = stack.pop(); 6186 block.close = true; 6187 6188 push({ type, value }); 6189 depth--; 6190 6191 block = stack[stack.length - 1]; 6192 continue; 6193 } 6194 6195 /** 6196 * Comma: ',' 6197 */ 6198 6199 if (value === CHAR_COMMA && depth > 0) { 6200 if (block.ranges > 0) { 6201 block.ranges = 0; 6202 const open = block.nodes.shift(); 6203 block.nodes = [open, { type: 'text', value: stringify(block) }]; 6204 } 6205 6206 push({ type: 'comma', value }); 6207 block.commas++; 6208 continue; 6209 } 6210 6211 /** 6212 * Dot: '.' 6213 */ 6214 6215 if (value === CHAR_DOT && depth > 0 && block.commas === 0) { 6216 const siblings = block.nodes; 6217 6218 if (depth === 0 || siblings.length === 0) { 6219 push({ type: 'text', value }); 6220 continue; 6221 } 6222 6223 if (prev.type === 'dot') { 6224 block.range = []; 6225 prev.value += value; 6226 prev.type = 'range'; 6227 6228 if (block.nodes.length !== 3 && block.nodes.length !== 5) { 6229 block.invalid = true; 6230 block.ranges = 0; 6231 prev.type = 'text'; 6232 continue; 6233 } 6234 6235 block.ranges++; 6236 block.args = []; 6237 continue; 6238 } 6239 6240 if (prev.type === 'range') { 6241 siblings.pop(); 6242 6243 const before = siblings[siblings.length - 1]; 6244 before.value += prev.value + value; 6245 prev = before; 6246 block.ranges--; 6247 continue; 6248 } 6249 6250 push({ type: 'dot', value }); 6251 continue; 6252 } 6253 6254 /** 6255 * Text 6256 */ 6257 6258 push({ type: 'text', value }); 6259 } 6260 6261 // Mark imbalanced braces and brackets as invalid 6262 do { 6263 block = stack.pop(); 6264 6265 if (block.type !== 'root') { 6266 block.nodes.forEach(node => { 6267 if (!node.nodes) { 6268 if (node.type === 'open') node.isOpen = true; 6269 if (node.type === 'close') node.isClose = true; 6270 if (!node.nodes) node.type = 'text'; 6271 node.invalid = true; 6272 } 6273 }); 6274 6275 // get the location of the block on parent.nodes (block's siblings) 6276 const parent = stack[stack.length - 1]; 6277 const index = parent.nodes.indexOf(block); 6278 // replace the (invalid) block with it's nodes 6279 parent.nodes.splice(index, 1, ...block.nodes); 6280 } 6281 } while (stack.length > 0); 6282 6283 push({ type: 'eos' }); 6284 return ast; 6285 }; 6286 6287 parse_1 = parse; 6288 return parse_1; 6289 } 6290 6291 var braces_1; 6292 var hasRequiredBraces; 6293 6294 function requireBraces () { 6295 if (hasRequiredBraces) return braces_1; 6296 hasRequiredBraces = 1; 6297 6298 const stringify = /*@__PURE__*/ requireStringify(); 6299 const compile = /*@__PURE__*/ requireCompile(); 6300 const expand = /*@__PURE__*/ requireExpand(); 6301 const parse = /*@__PURE__*/ requireParse(); 6302 6303 /** 6304 * Expand the given pattern or create a regex-compatible string. 6305 * 6306 * ```js 6307 * const braces = require('braces'); 6308 * console.log(braces('{a,b,c}', { compile: true })); //=> ['(a|b|c)'] 6309 * console.log(braces('{a,b,c}')); //=> ['a', 'b', 'c'] 6310 * ``` 6311 * @param {String} `str` 6312 * @param {Object} `options` 6313 * @return {String} 6314 * @api public 6315 */ 6316 6317 const braces = (input, options = {}) => { 6318 let output = []; 6319 6320 if (Array.isArray(input)) { 6321 for (const pattern of input) { 6322 const result = braces.create(pattern, options); 6323 if (Array.isArray(result)) { 6324 output.push(...result); 6325 } else { 6326 output.push(result); 6327 } 6328 } 6329 } else { 6330 output = [].concat(braces.create(input, options)); 6331 } 6332 6333 if (options && options.expand === true && options.nodupes === true) { 6334 output = [...new Set(output)]; 6335 } 6336 return output; 6337 }; 6338 6339 /** 6340 * Parse the given `str` with the given `options`. 6341 * 6342 * ```js 6343 * // braces.parse(pattern, [, options]); 6344 * const ast = braces.parse('a/{b,c}/d'); 6345 * console.log(ast); 6346 * ``` 6347 * @param {String} pattern Brace pattern to parse 6348 * @param {Object} options 6349 * @return {Object} Returns an AST 6350 * @api public 6351 */ 6352 6353 braces.parse = (input, options = {}) => parse(input, options); 6354 6355 /** 6356 * Creates a braces string from an AST, or an AST node. 6357 * 6358 * ```js 6359 * const braces = require('braces'); 6360 * let ast = braces.parse('foo/{a,b}/bar'); 6361 * console.log(stringify(ast.nodes[2])); //=> '{a,b}' 6362 * ``` 6363 * @param {String} `input` Brace pattern or AST. 6364 * @param {Object} `options` 6365 * @return {Array} Returns an array of expanded values. 6366 * @api public 6367 */ 6368 6369 braces.stringify = (input, options = {}) => { 6370 if (typeof input === 'string') { 6371 return stringify(braces.parse(input, options), options); 6372 } 6373 return stringify(input, options); 6374 }; 6375 6376 /** 6377 * Compiles a brace pattern into a regex-compatible, optimized string. 6378 * This method is called by the main [braces](#braces) function by default. 6379 * 6380 * ```js 6381 * const braces = require('braces'); 6382 * console.log(braces.compile('a/{b,c}/d')); 6383 * //=> ['a/(b|c)/d'] 6384 * ``` 6385 * @param {String} `input` Brace pattern or AST. 6386 * @param {Object} `options` 6387 * @return {Array} Returns an array of expanded values. 6388 * @api public 6389 */ 6390 6391 braces.compile = (input, options = {}) => { 6392 if (typeof input === 'string') { 6393 input = braces.parse(input, options); 6394 } 6395 return compile(input, options); 6396 }; 6397 6398 /** 6399 * Expands a brace pattern into an array. This method is called by the 6400 * main [braces](#braces) function when `options.expand` is true. Before 6401 * using this method it's recommended that you read the [performance notes](#performance)) 6402 * and advantages of using [.compile](#compile) instead. 6403 * 6404 * ```js 6405 * const braces = require('braces'); 6406 * console.log(braces.expand('a/{b,c}/d')); 6407 * //=> ['a/b/d', 'a/c/d']; 6408 * ``` 6409 * @param {String} `pattern` Brace pattern 6410 * @param {Object} `options` 6411 * @return {Array} Returns an array of expanded values. 6412 * @api public 6413 */ 6414 6415 braces.expand = (input, options = {}) => { 6416 if (typeof input === 'string') { 6417 input = braces.parse(input, options); 6418 } 6419 6420 let result = expand(input, options); 6421 6422 // filter out empty strings if specified 6423 if (options.noempty === true) { 6424 result = result.filter(Boolean); 6425 } 6426 6427 // filter out duplicates if specified 6428 if (options.nodupes === true) { 6429 result = [...new Set(result)]; 6430 } 6431 6432 return result; 6433 }; 6434 6435 /** 6436 * Processes a brace pattern and returns either an expanded array 6437 * (if `options.expand` is true), a highly optimized regex-compatible string. 6438 * This method is called by the main [braces](#braces) function. 6439 * 6440 * ```js 6441 * const braces = require('braces'); 6442 * console.log(braces.create('user-{200..300}/project-{a,b,c}-{1..10}')) 6443 * //=> 'user-(20[0-9]|2[1-9][0-9]|300)/project-(a|b|c)-([1-9]|10)' 6444 * ``` 6445 * @param {String} `pattern` Brace pattern 6446 * @param {Object} `options` 6447 * @return {Array} Returns an array of expanded values. 6448 * @api public 6449 */ 6450 6451 braces.create = (input, options = {}) => { 6452 if (input === '' || input.length < 3) { 6453 return [input]; 6454 } 6455 6456 return options.expand !== true 6457 ? braces.compile(input, options) 6458 : braces.expand(input, options); 6459 }; 6460 6461 /** 6462 * Expose "braces" 6463 */ 6464 6465 braces_1 = braces; 6466 return braces_1; 6467 } 2104 6468 2105 6469 const require$$0 = [ … … 2367 6731 ]; 2368 6732 2369 var binaryExtensions$1 = require$$0; 2370 2371 const path = require$$0$2; 2372 const binaryExtensions = binaryExtensions$1; 2373 2374 const extensions = new Set(binaryExtensions); 2375 2376 var isBinaryPath$1 = filePath => extensions.has(path.extname(filePath).slice(1).toLowerCase()); 6733 var binaryExtensions; 6734 var hasRequiredBinaryExtensions; 6735 6736 function requireBinaryExtensions () { 6737 if (hasRequiredBinaryExtensions) return binaryExtensions; 6738 hasRequiredBinaryExtensions = 1; 6739 binaryExtensions = require$$0; 6740 return binaryExtensions; 6741 } 6742 6743 var isBinaryPath; 6744 var hasRequiredIsBinaryPath; 6745 6746 function requireIsBinaryPath () { 6747 if (hasRequiredIsBinaryPath) return isBinaryPath; 6748 hasRequiredIsBinaryPath = 1; 6749 const path = require$$0$1; 6750 const binaryExtensions = /*@__PURE__*/ requireBinaryExtensions(); 6751 6752 const extensions = new Set(binaryExtensions); 6753 6754 isBinaryPath = filePath => extensions.has(path.extname(filePath).slice(1).toLowerCase()); 6755 return isBinaryPath; 6756 } 2377 6757 2378 6758 var constants = {}; 2379 6759 2380 (function (exports) { 2381 2382 const {sep} = require$$0$2; 2383 const {platform} = process; 2384 const os = require$$2$1; 2385 2386 exports.EV_ALL = 'all'; 2387 exports.EV_READY = 'ready'; 2388 exports.EV_ADD = 'add'; 2389 exports.EV_CHANGE = 'change'; 2390 exports.EV_ADD_DIR = 'addDir'; 2391 exports.EV_UNLINK = 'unlink'; 2392 exports.EV_UNLINK_DIR = 'unlinkDir'; 2393 exports.EV_RAW = 'raw'; 2394 exports.EV_ERROR = 'error'; 2395 2396 exports.STR_DATA = 'data'; 2397 exports.STR_END = 'end'; 2398 exports.STR_CLOSE = 'close'; 2399 2400 exports.FSEVENT_CREATED = 'created'; 2401 exports.FSEVENT_MODIFIED = 'modified'; 2402 exports.FSEVENT_DELETED = 'deleted'; 2403 exports.FSEVENT_MOVED = 'moved'; 2404 exports.FSEVENT_CLONED = 'cloned'; 2405 exports.FSEVENT_UNKNOWN = 'unknown'; 2406 exports.FSEVENT_FLAG_MUST_SCAN_SUBDIRS = 1; 2407 exports.FSEVENT_TYPE_FILE = 'file'; 2408 exports.FSEVENT_TYPE_DIRECTORY = 'directory'; 2409 exports.FSEVENT_TYPE_SYMLINK = 'symlink'; 2410 2411 exports.KEY_LISTENERS = 'listeners'; 2412 exports.KEY_ERR = 'errHandlers'; 2413 exports.KEY_RAW = 'rawEmitters'; 2414 exports.HANDLER_KEYS = [exports.KEY_LISTENERS, exports.KEY_ERR, exports.KEY_RAW]; 2415 2416 exports.DOT_SLASH = `.${sep}`; 2417 2418 exports.BACK_SLASH_RE = /\\/g; 2419 exports.DOUBLE_SLASH_RE = /\/\//; 2420 exports.SLASH_OR_BACK_SLASH_RE = /[/\\]/; 2421 exports.DOT_RE = /\..*\.(sw[px])$|~$|\.subl.*\.tmp/; 2422 exports.REPLACER_RE = /^\.[/\\]/; 2423 2424 exports.SLASH = '/'; 2425 exports.SLASH_SLASH = '//'; 2426 exports.BRACE_START = '{'; 2427 exports.BANG = '!'; 2428 exports.ONE_DOT = '.'; 2429 exports.TWO_DOTS = '..'; 2430 exports.STAR = '*'; 2431 exports.GLOBSTAR = '**'; 2432 exports.ROOT_GLOBSTAR = '/**/*'; 2433 exports.SLASH_GLOBSTAR = '/**'; 2434 exports.DIR_SUFFIX = 'Dir'; 2435 exports.ANYMATCH_OPTS = {dot: true}; 2436 exports.STRING_TYPE = 'string'; 2437 exports.FUNCTION_TYPE = 'function'; 2438 exports.EMPTY_STR = ''; 2439 exports.EMPTY_FN = () => {}; 2440 exports.IDENTITY_FN = val => val; 2441 2442 exports.isWindows = platform === 'win32'; 2443 exports.isMacos = platform === 'darwin'; 2444 exports.isLinux = platform === 'linux'; 2445 exports.isIBMi = os.type() === 'OS400'; 2446 } (constants)); 2447 2448 const fs$2 = require$$0$1; 2449 const sysPath$2 = require$$0$2; 2450 const { promisify: promisify$2 } = require$$2; 2451 const isBinaryPath = isBinaryPath$1; 2452 const { 2453 isWindows: isWindows$1, 2454 isLinux, 2455 EMPTY_FN: EMPTY_FN$2, 2456 EMPTY_STR: EMPTY_STR$1, 2457 KEY_LISTENERS, 2458 KEY_ERR, 2459 KEY_RAW, 2460 HANDLER_KEYS, 2461 EV_CHANGE: EV_CHANGE$2, 2462 EV_ADD: EV_ADD$2, 2463 EV_ADD_DIR: EV_ADD_DIR$2, 2464 EV_ERROR: EV_ERROR$2, 2465 STR_DATA: STR_DATA$1, 2466 STR_END: STR_END$2, 2467 BRACE_START: BRACE_START$1, 2468 STAR 2469 } = constants; 2470 2471 const THROTTLE_MODE_WATCH = 'watch'; 2472 2473 const open = promisify$2(fs$2.open); 2474 const stat$2 = promisify$2(fs$2.stat); 2475 const lstat$1 = promisify$2(fs$2.lstat); 2476 const close = promisify$2(fs$2.close); 2477 const fsrealpath = promisify$2(fs$2.realpath); 2478 2479 const statMethods$1 = { lstat: lstat$1, stat: stat$2 }; 2480 2481 // TODO: emit errors properly. Example: EMFILE on Macos. 2482 const foreach = (val, fn) => { 2483 if (val instanceof Set) { 2484 val.forEach(fn); 2485 } else { 2486 fn(val); 2487 } 2488 }; 2489 2490 const addAndConvert = (main, prop, item) => { 2491 let container = main[prop]; 2492 if (!(container instanceof Set)) { 2493 main[prop] = container = new Set([container]); 2494 } 2495 container.add(item); 2496 }; 2497 2498 const clearItem = cont => key => { 2499 const set = cont[key]; 2500 if (set instanceof Set) { 2501 set.clear(); 2502 } else { 2503 delete cont[key]; 2504 } 2505 }; 2506 2507 const delFromSet = (main, prop, item) => { 2508 const container = main[prop]; 2509 if (container instanceof Set) { 2510 container.delete(item); 2511 } else if (container === item) { 2512 delete main[prop]; 2513 } 2514 }; 2515 2516 const isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val; 2517 2518 /** 2519 * @typedef {String} Path 2520 */ 2521 2522 // fs_watch helpers 2523 2524 // object to hold per-process fs_watch instances 2525 // (may be shared across chokidar FSWatcher instances) 2526 2527 /** 2528 * @typedef {Object} FsWatchContainer 2529 * @property {Set} listeners 2530 * @property {Set} errHandlers 2531 * @property {Set} rawEmitters 2532 * @property {fs.FSWatcher=} watcher 2533 * @property {Boolean=} watcherUnusable 2534 */ 2535 2536 /** 2537 * @type {Map<String,FsWatchContainer>} 2538 */ 2539 const FsWatchInstances = new Map(); 2540 2541 /** 2542 * Instantiates the fs_watch interface 2543 * @param {String} path to be watched 2544 * @param {Object} options to be passed to fs_watch 2545 * @param {Function} listener main event handler 2546 * @param {Function} errHandler emits info about errors 2547 * @param {Function} emitRaw emits raw event data 2548 * @returns {fs.FSWatcher} new fsevents instance 2549 */ 2550 function createFsWatchInstance(path, options, listener, errHandler, emitRaw) { 2551 const handleEvent = (rawEvent, evPath) => { 2552 listener(path); 2553 emitRaw(rawEvent, evPath, {watchedPath: path}); 2554 2555 // emit based on events occurring for files from a directory's watcher in 2556 // case the file's watcher misses it (and rely on throttling to de-dupe) 2557 if (evPath && path !== evPath) { 2558 fsWatchBroadcast( 2559 sysPath$2.resolve(path, evPath), KEY_LISTENERS, sysPath$2.join(path, evPath) 2560 ); 2561 } 2562 }; 2563 try { 2564 return fs$2.watch(path, options, handleEvent); 2565 } catch (error) { 2566 errHandler(error); 2567 } 6760 var hasRequiredConstants; 6761 6762 function requireConstants () { 6763 if (hasRequiredConstants) return constants; 6764 hasRequiredConstants = 1; 6765 (function (exports) { 6766 6767 const {sep} = require$$0$1; 6768 const {platform} = process; 6769 const os = require$$2$1; 6770 6771 exports.EV_ALL = 'all'; 6772 exports.EV_READY = 'ready'; 6773 exports.EV_ADD = 'add'; 6774 exports.EV_CHANGE = 'change'; 6775 exports.EV_ADD_DIR = 'addDir'; 6776 exports.EV_UNLINK = 'unlink'; 6777 exports.EV_UNLINK_DIR = 'unlinkDir'; 6778 exports.EV_RAW = 'raw'; 6779 exports.EV_ERROR = 'error'; 6780 6781 exports.STR_DATA = 'data'; 6782 exports.STR_END = 'end'; 6783 exports.STR_CLOSE = 'close'; 6784 6785 exports.FSEVENT_CREATED = 'created'; 6786 exports.FSEVENT_MODIFIED = 'modified'; 6787 exports.FSEVENT_DELETED = 'deleted'; 6788 exports.FSEVENT_MOVED = 'moved'; 6789 exports.FSEVENT_CLONED = 'cloned'; 6790 exports.FSEVENT_UNKNOWN = 'unknown'; 6791 exports.FSEVENT_FLAG_MUST_SCAN_SUBDIRS = 1; 6792 exports.FSEVENT_TYPE_FILE = 'file'; 6793 exports.FSEVENT_TYPE_DIRECTORY = 'directory'; 6794 exports.FSEVENT_TYPE_SYMLINK = 'symlink'; 6795 6796 exports.KEY_LISTENERS = 'listeners'; 6797 exports.KEY_ERR = 'errHandlers'; 6798 exports.KEY_RAW = 'rawEmitters'; 6799 exports.HANDLER_KEYS = [exports.KEY_LISTENERS, exports.KEY_ERR, exports.KEY_RAW]; 6800 6801 exports.DOT_SLASH = `.${sep}`; 6802 6803 exports.BACK_SLASH_RE = /\\/g; 6804 exports.DOUBLE_SLASH_RE = /\/\//; 6805 exports.SLASH_OR_BACK_SLASH_RE = /[/\\]/; 6806 exports.DOT_RE = /\..*\.(sw[px])$|~$|\.subl.*\.tmp/; 6807 exports.REPLACER_RE = /^\.[/\\]/; 6808 6809 exports.SLASH = '/'; 6810 exports.SLASH_SLASH = '//'; 6811 exports.BRACE_START = '{'; 6812 exports.BANG = '!'; 6813 exports.ONE_DOT = '.'; 6814 exports.TWO_DOTS = '..'; 6815 exports.STAR = '*'; 6816 exports.GLOBSTAR = '**'; 6817 exports.ROOT_GLOBSTAR = '/**/*'; 6818 exports.SLASH_GLOBSTAR = '/**'; 6819 exports.DIR_SUFFIX = 'Dir'; 6820 exports.ANYMATCH_OPTS = {dot: true}; 6821 exports.STRING_TYPE = 'string'; 6822 exports.FUNCTION_TYPE = 'function'; 6823 exports.EMPTY_STR = ''; 6824 exports.EMPTY_FN = () => {}; 6825 exports.IDENTITY_FN = val => val; 6826 6827 exports.isWindows = platform === 'win32'; 6828 exports.isMacos = platform === 'darwin'; 6829 exports.isLinux = platform === 'linux'; 6830 exports.isIBMi = os.type() === 'OS400'; 6831 } (constants)); 6832 return constants; 2568 6833 } 2569 6834 2570 /** 2571 * Helper for passing fs_watch event data to a collection of listeners 2572 * @param {Path} fullPath absolute path bound to fs_watch instance 2573 * @param {String} type listener type 2574 * @param {*=} val1 arguments to be passed to listeners 2575 * @param {*=} val2 2576 * @param {*=} val3 2577 */ 2578 const fsWatchBroadcast = (fullPath, type, val1, val2, val3) => { 2579 const cont = FsWatchInstances.get(fullPath); 2580 if (!cont) return; 2581 foreach(cont[type], (listener) => { 2582 listener(val1, val2, val3); 2583 }); 2584 }; 2585 2586 /** 2587 * Instantiates the fs_watch interface or binds listeners 2588 * to an existing one covering the same file system entry 2589 * @param {String} path 2590 * @param {String} fullPath absolute path 2591 * @param {Object} options to be passed to fs_watch 2592 * @param {Object} handlers container for event listener functions 2593 */ 2594 const setFsWatchListener = (path, fullPath, options, handlers) => { 2595 const {listener, errHandler, rawEmitter} = handlers; 2596 let cont = FsWatchInstances.get(fullPath); 2597 2598 /** @type {fs.FSWatcher=} */ 2599 let watcher; 2600 if (!options.persistent) { 2601 watcher = createFsWatchInstance( 2602 path, options, listener, errHandler, rawEmitter 2603 ); 2604 return watcher.close.bind(watcher); 2605 } 2606 if (cont) { 2607 addAndConvert(cont, KEY_LISTENERS, listener); 2608 addAndConvert(cont, KEY_ERR, errHandler); 2609 addAndConvert(cont, KEY_RAW, rawEmitter); 2610 } else { 2611 watcher = createFsWatchInstance( 2612 path, 2613 options, 2614 fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), 2615 errHandler, // no need to use broadcast here 2616 fsWatchBroadcast.bind(null, fullPath, KEY_RAW) 2617 ); 2618 if (!watcher) return; 2619 watcher.on(EV_ERROR$2, async (error) => { 2620 const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR); 2621 cont.watcherUnusable = true; // documented since Node 10.4.1 2622 // Workaround for https://github.com/joyent/node/issues/4337 2623 if (isWindows$1 && error.code === 'EPERM') { 2624 try { 2625 const fd = await open(path, 'r'); 2626 await close(fd); 2627 broadcastErr(error); 2628 } catch (err) {} 2629 } else { 2630 broadcastErr(error); 2631 } 2632 }); 2633 cont = { 2634 listeners: listener, 2635 errHandlers: errHandler, 2636 rawEmitters: rawEmitter, 2637 watcher 2638 }; 2639 FsWatchInstances.set(fullPath, cont); 2640 } 2641 // const index = cont.listeners.indexOf(listener); 2642 2643 // removes this instance's listeners and closes the underlying fs_watch 2644 // instance if there are no more listeners left 2645 return () => { 2646 delFromSet(cont, KEY_LISTENERS, listener); 2647 delFromSet(cont, KEY_ERR, errHandler); 2648 delFromSet(cont, KEY_RAW, rawEmitter); 2649 if (isEmptySet(cont.listeners)) { 2650 // Check to protect against issue gh-730. 2651 // if (cont.watcherUnusable) { 2652 cont.watcher.close(); 2653 // } 2654 FsWatchInstances.delete(fullPath); 2655 HANDLER_KEYS.forEach(clearItem(cont)); 2656 cont.watcher = undefined; 2657 Object.freeze(cont); 2658 } 2659 }; 2660 }; 2661 2662 // fs_watchFile helpers 2663 2664 // object to hold per-process fs_watchFile instances 2665 // (may be shared across chokidar FSWatcher instances) 2666 const FsWatchFileInstances = new Map(); 2667 2668 /** 2669 * Instantiates the fs_watchFile interface or binds listeners 2670 * to an existing one covering the same file system entry 2671 * @param {String} path to be watched 2672 * @param {String} fullPath absolute path 2673 * @param {Object} options options to be passed to fs_watchFile 2674 * @param {Object} handlers container for event listener functions 2675 * @returns {Function} closer 2676 */ 2677 const setFsWatchFileListener = (path, fullPath, options, handlers) => { 2678 const {listener, rawEmitter} = handlers; 2679 let cont = FsWatchFileInstances.get(fullPath); 2680 2681 const copts = cont && cont.options; 2682 if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) { 2683 fs$2.unwatchFile(fullPath); 2684 cont = undefined; 2685 } 2686 2687 /* eslint-enable no-unused-vars, prefer-destructuring */ 2688 2689 if (cont) { 2690 addAndConvert(cont, KEY_LISTENERS, listener); 2691 addAndConvert(cont, KEY_RAW, rawEmitter); 2692 } else { 2693 // TODO 2694 // listeners.add(listener); 2695 // rawEmitters.add(rawEmitter); 2696 cont = { 2697 listeners: listener, 2698 rawEmitters: rawEmitter, 2699 options, 2700 watcher: fs$2.watchFile(fullPath, options, (curr, prev) => { 2701 foreach(cont.rawEmitters, (rawEmitter) => { 2702 rawEmitter(EV_CHANGE$2, fullPath, {curr, prev}); 2703 }); 2704 const currmtime = curr.mtimeMs; 2705 if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) { 2706 foreach(cont.listeners, (listener) => listener(path, curr)); 2707 } 2708 }) 2709 }; 2710 FsWatchFileInstances.set(fullPath, cont); 2711 } 2712 // const index = cont.listeners.indexOf(listener); 2713 2714 // Removes this instance's listeners and closes the underlying fs_watchFile 2715 // instance if there are no more listeners left. 2716 return () => { 2717 delFromSet(cont, KEY_LISTENERS, listener); 2718 delFromSet(cont, KEY_RAW, rawEmitter); 2719 if (isEmptySet(cont.listeners)) { 2720 FsWatchFileInstances.delete(fullPath); 2721 fs$2.unwatchFile(fullPath); 2722 cont.options = cont.watcher = undefined; 2723 Object.freeze(cont); 2724 } 2725 }; 2726 }; 2727 2728 /** 2729 * @mixin 2730 */ 2731 let NodeFsHandler$1 = class NodeFsHandler { 2732 2733 /** 2734 * @param {import("../index").FSWatcher} fsW 2735 */ 2736 constructor(fsW) { 2737 this.fsw = fsW; 2738 this._boundHandleError = (error) => fsW._handleError(error); 6835 var nodefsHandler; 6836 var hasRequiredNodefsHandler; 6837 6838 function requireNodefsHandler () { 6839 if (hasRequiredNodefsHandler) return nodefsHandler; 6840 hasRequiredNodefsHandler = 1; 6841 6842 const fs = require$$0$2; 6843 const sysPath = require$$0$1; 6844 const { promisify } = require$$2; 6845 const isBinaryPath = /*@__PURE__*/ requireIsBinaryPath(); 6846 const { 6847 isWindows, 6848 isLinux, 6849 EMPTY_FN, 6850 EMPTY_STR, 6851 KEY_LISTENERS, 6852 KEY_ERR, 6853 KEY_RAW, 6854 HANDLER_KEYS, 6855 EV_CHANGE, 6856 EV_ADD, 6857 EV_ADD_DIR, 6858 EV_ERROR, 6859 STR_DATA, 6860 STR_END, 6861 BRACE_START, 6862 STAR 6863 } = /*@__PURE__*/ requireConstants(); 6864 6865 const THROTTLE_MODE_WATCH = 'watch'; 6866 6867 const open = promisify(fs.open); 6868 const stat = promisify(fs.stat); 6869 const lstat = promisify(fs.lstat); 6870 const close = promisify(fs.close); 6871 const fsrealpath = promisify(fs.realpath); 6872 6873 const statMethods = { lstat, stat }; 6874 6875 // TODO: emit errors properly. Example: EMFILE on Macos. 6876 const foreach = (val, fn) => { 6877 if (val instanceof Set) { 6878 val.forEach(fn); 6879 } else { 6880 fn(val); 6881 } 6882 }; 6883 6884 const addAndConvert = (main, prop, item) => { 6885 let container = main[prop]; 6886 if (!(container instanceof Set)) { 6887 main[prop] = container = new Set([container]); 6888 } 6889 container.add(item); 6890 }; 6891 6892 const clearItem = cont => key => { 6893 const set = cont[key]; 6894 if (set instanceof Set) { 6895 set.clear(); 6896 } else { 6897 delete cont[key]; 6898 } 6899 }; 6900 6901 const delFromSet = (main, prop, item) => { 6902 const container = main[prop]; 6903 if (container instanceof Set) { 6904 container.delete(item); 6905 } else if (container === item) { 6906 delete main[prop]; 6907 } 6908 }; 6909 6910 const isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val; 6911 6912 /** 6913 * @typedef {String} Path 6914 */ 6915 6916 // fs_watch helpers 6917 6918 // object to hold per-process fs_watch instances 6919 // (may be shared across chokidar FSWatcher instances) 6920 6921 /** 6922 * @typedef {Object} FsWatchContainer 6923 * @property {Set} listeners 6924 * @property {Set} errHandlers 6925 * @property {Set} rawEmitters 6926 * @property {fs.FSWatcher=} watcher 6927 * @property {Boolean=} watcherUnusable 6928 */ 6929 6930 /** 6931 * @type {Map<String,FsWatchContainer>} 6932 */ 6933 const FsWatchInstances = new Map(); 6934 6935 /** 6936 * Instantiates the fs_watch interface 6937 * @param {String} path to be watched 6938 * @param {Object} options to be passed to fs_watch 6939 * @param {Function} listener main event handler 6940 * @param {Function} errHandler emits info about errors 6941 * @param {Function} emitRaw emits raw event data 6942 * @returns {fs.FSWatcher} new fsevents instance 6943 */ 6944 function createFsWatchInstance(path, options, listener, errHandler, emitRaw) { 6945 const handleEvent = (rawEvent, evPath) => { 6946 listener(path); 6947 emitRaw(rawEvent, evPath, {watchedPath: path}); 6948 6949 // emit based on events occurring for files from a directory's watcher in 6950 // case the file's watcher misses it (and rely on throttling to de-dupe) 6951 if (evPath && path !== evPath) { 6952 fsWatchBroadcast( 6953 sysPath.resolve(path, evPath), KEY_LISTENERS, sysPath.join(path, evPath) 6954 ); 6955 } 6956 }; 6957 try { 6958 return fs.watch(path, options, handleEvent); 6959 } catch (error) { 6960 errHandler(error); 6961 } 6962 } 6963 6964 /** 6965 * Helper for passing fs_watch event data to a collection of listeners 6966 * @param {Path} fullPath absolute path bound to fs_watch instance 6967 * @param {String} type listener type 6968 * @param {*=} val1 arguments to be passed to listeners 6969 * @param {*=} val2 6970 * @param {*=} val3 6971 */ 6972 const fsWatchBroadcast = (fullPath, type, val1, val2, val3) => { 6973 const cont = FsWatchInstances.get(fullPath); 6974 if (!cont) return; 6975 foreach(cont[type], (listener) => { 6976 listener(val1, val2, val3); 6977 }); 6978 }; 6979 6980 /** 6981 * Instantiates the fs_watch interface or binds listeners 6982 * to an existing one covering the same file system entry 6983 * @param {String} path 6984 * @param {String} fullPath absolute path 6985 * @param {Object} options to be passed to fs_watch 6986 * @param {Object} handlers container for event listener functions 6987 */ 6988 const setFsWatchListener = (path, fullPath, options, handlers) => { 6989 const {listener, errHandler, rawEmitter} = handlers; 6990 let cont = FsWatchInstances.get(fullPath); 6991 6992 /** @type {fs.FSWatcher=} */ 6993 let watcher; 6994 if (!options.persistent) { 6995 watcher = createFsWatchInstance( 6996 path, options, listener, errHandler, rawEmitter 6997 ); 6998 return watcher.close.bind(watcher); 6999 } 7000 if (cont) { 7001 addAndConvert(cont, KEY_LISTENERS, listener); 7002 addAndConvert(cont, KEY_ERR, errHandler); 7003 addAndConvert(cont, KEY_RAW, rawEmitter); 7004 } else { 7005 watcher = createFsWatchInstance( 7006 path, 7007 options, 7008 fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), 7009 errHandler, // no need to use broadcast here 7010 fsWatchBroadcast.bind(null, fullPath, KEY_RAW) 7011 ); 7012 if (!watcher) return; 7013 watcher.on(EV_ERROR, async (error) => { 7014 const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR); 7015 cont.watcherUnusable = true; // documented since Node 10.4.1 7016 // Workaround for https://github.com/joyent/node/issues/4337 7017 if (isWindows && error.code === 'EPERM') { 7018 try { 7019 const fd = await open(path, 'r'); 7020 await close(fd); 7021 broadcastErr(error); 7022 } catch (err) {} 7023 } else { 7024 broadcastErr(error); 7025 } 7026 }); 7027 cont = { 7028 listeners: listener, 7029 errHandlers: errHandler, 7030 rawEmitters: rawEmitter, 7031 watcher 7032 }; 7033 FsWatchInstances.set(fullPath, cont); 7034 } 7035 // const index = cont.listeners.indexOf(listener); 7036 7037 // removes this instance's listeners and closes the underlying fs_watch 7038 // instance if there are no more listeners left 7039 return () => { 7040 delFromSet(cont, KEY_LISTENERS, listener); 7041 delFromSet(cont, KEY_ERR, errHandler); 7042 delFromSet(cont, KEY_RAW, rawEmitter); 7043 if (isEmptySet(cont.listeners)) { 7044 // Check to protect against issue gh-730. 7045 // if (cont.watcherUnusable) { 7046 cont.watcher.close(); 7047 // } 7048 FsWatchInstances.delete(fullPath); 7049 HANDLER_KEYS.forEach(clearItem(cont)); 7050 cont.watcher = undefined; 7051 Object.freeze(cont); 7052 } 7053 }; 7054 }; 7055 7056 // fs_watchFile helpers 7057 7058 // object to hold per-process fs_watchFile instances 7059 // (may be shared across chokidar FSWatcher instances) 7060 const FsWatchFileInstances = new Map(); 7061 7062 /** 7063 * Instantiates the fs_watchFile interface or binds listeners 7064 * to an existing one covering the same file system entry 7065 * @param {String} path to be watched 7066 * @param {String} fullPath absolute path 7067 * @param {Object} options options to be passed to fs_watchFile 7068 * @param {Object} handlers container for event listener functions 7069 * @returns {Function} closer 7070 */ 7071 const setFsWatchFileListener = (path, fullPath, options, handlers) => { 7072 const {listener, rawEmitter} = handlers; 7073 let cont = FsWatchFileInstances.get(fullPath); 7074 7075 const copts = cont && cont.options; 7076 if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) { 7077 fs.unwatchFile(fullPath); 7078 cont = undefined; 7079 } 7080 7081 /* eslint-enable no-unused-vars, prefer-destructuring */ 7082 7083 if (cont) { 7084 addAndConvert(cont, KEY_LISTENERS, listener); 7085 addAndConvert(cont, KEY_RAW, rawEmitter); 7086 } else { 7087 // TODO 7088 // listeners.add(listener); 7089 // rawEmitters.add(rawEmitter); 7090 cont = { 7091 listeners: listener, 7092 rawEmitters: rawEmitter, 7093 options, 7094 watcher: fs.watchFile(fullPath, options, (curr, prev) => { 7095 foreach(cont.rawEmitters, (rawEmitter) => { 7096 rawEmitter(EV_CHANGE, fullPath, {curr, prev}); 7097 }); 7098 const currmtime = curr.mtimeMs; 7099 if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) { 7100 foreach(cont.listeners, (listener) => listener(path, curr)); 7101 } 7102 }) 7103 }; 7104 FsWatchFileInstances.set(fullPath, cont); 7105 } 7106 // const index = cont.listeners.indexOf(listener); 7107 7108 // Removes this instance's listeners and closes the underlying fs_watchFile 7109 // instance if there are no more listeners left. 7110 return () => { 7111 delFromSet(cont, KEY_LISTENERS, listener); 7112 delFromSet(cont, KEY_RAW, rawEmitter); 7113 if (isEmptySet(cont.listeners)) { 7114 FsWatchFileInstances.delete(fullPath); 7115 fs.unwatchFile(fullPath); 7116 cont.options = cont.watcher = undefined; 7117 Object.freeze(cont); 7118 } 7119 }; 7120 }; 7121 7122 /** 7123 * @mixin 7124 */ 7125 class NodeFsHandler { 7126 7127 /** 7128 * @param {import("../index").FSWatcher} fsW 7129 */ 7130 constructor(fsW) { 7131 this.fsw = fsW; 7132 this._boundHandleError = (error) => fsW._handleError(error); 7133 } 7134 7135 /** 7136 * Watch file for changes with fs_watchFile or fs_watch. 7137 * @param {String} path to file or dir 7138 * @param {Function} listener on fs change 7139 * @returns {Function} closer for the watcher instance 7140 */ 7141 _watchWithNodeFs(path, listener) { 7142 const opts = this.fsw.options; 7143 const directory = sysPath.dirname(path); 7144 const basename = sysPath.basename(path); 7145 const parent = this.fsw._getWatchedDir(directory); 7146 parent.add(basename); 7147 const absolutePath = sysPath.resolve(path); 7148 const options = {persistent: opts.persistent}; 7149 if (!listener) listener = EMPTY_FN; 7150 7151 let closer; 7152 if (opts.usePolling) { 7153 options.interval = opts.enableBinaryInterval && isBinaryPath(basename) ? 7154 opts.binaryInterval : opts.interval; 7155 closer = setFsWatchFileListener(path, absolutePath, options, { 7156 listener, 7157 rawEmitter: this.fsw._emitRaw 7158 }); 7159 } else { 7160 closer = setFsWatchListener(path, absolutePath, options, { 7161 listener, 7162 errHandler: this._boundHandleError, 7163 rawEmitter: this.fsw._emitRaw 7164 }); 7165 } 7166 return closer; 7167 } 7168 7169 /** 7170 * Watch a file and emit add event if warranted. 7171 * @param {Path} file Path 7172 * @param {fs.Stats} stats result of fs_stat 7173 * @param {Boolean} initialAdd was the file added at watch instantiation? 7174 * @returns {Function} closer for the watcher instance 7175 */ 7176 _handleFile(file, stats, initialAdd) { 7177 if (this.fsw.closed) { 7178 return; 7179 } 7180 const dirname = sysPath.dirname(file); 7181 const basename = sysPath.basename(file); 7182 const parent = this.fsw._getWatchedDir(dirname); 7183 // stats is always present 7184 let prevStats = stats; 7185 7186 // if the file is already being watched, do nothing 7187 if (parent.has(basename)) return; 7188 7189 const listener = async (path, newStats) => { 7190 if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5)) return; 7191 if (!newStats || newStats.mtimeMs === 0) { 7192 try { 7193 const newStats = await stat(file); 7194 if (this.fsw.closed) return; 7195 // Check that change event was not fired because of changed only accessTime. 7196 const at = newStats.atimeMs; 7197 const mt = newStats.mtimeMs; 7198 if (!at || at <= mt || mt !== prevStats.mtimeMs) { 7199 this.fsw._emit(EV_CHANGE, file, newStats); 7200 } 7201 if (isLinux && prevStats.ino !== newStats.ino) { 7202 this.fsw._closeFile(path); 7203 prevStats = newStats; 7204 this.fsw._addPathCloser(path, this._watchWithNodeFs(file, listener)); 7205 } else { 7206 prevStats = newStats; 7207 } 7208 } catch (error) { 7209 // Fix issues where mtime is null but file is still present 7210 this.fsw._remove(dirname, basename); 7211 } 7212 // add is about to be emitted if file not already tracked in parent 7213 } else if (parent.has(basename)) { 7214 // Check that change event was not fired because of changed only accessTime. 7215 const at = newStats.atimeMs; 7216 const mt = newStats.mtimeMs; 7217 if (!at || at <= mt || mt !== prevStats.mtimeMs) { 7218 this.fsw._emit(EV_CHANGE, file, newStats); 7219 } 7220 prevStats = newStats; 7221 } 7222 }; 7223 // kick off the watcher 7224 const closer = this._watchWithNodeFs(file, listener); 7225 7226 // emit an add event if we're supposed to 7227 if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file)) { 7228 if (!this.fsw._throttle(EV_ADD, file, 0)) return; 7229 this.fsw._emit(EV_ADD, file, stats); 7230 } 7231 7232 return closer; 7233 } 7234 7235 /** 7236 * Handle symlinks encountered while reading a dir. 7237 * @param {Object} entry returned by readdirp 7238 * @param {String} directory path of dir being read 7239 * @param {String} path of this item 7240 * @param {String} item basename of this item 7241 * @returns {Promise<Boolean>} true if no more processing is needed for this entry. 7242 */ 7243 async _handleSymlink(entry, directory, path, item) { 7244 if (this.fsw.closed) { 7245 return; 7246 } 7247 const full = entry.fullPath; 7248 const dir = this.fsw._getWatchedDir(directory); 7249 7250 if (!this.fsw.options.followSymlinks) { 7251 // watch symlink directly (don't follow) and detect changes 7252 this.fsw._incrReadyCount(); 7253 7254 let linkPath; 7255 try { 7256 linkPath = await fsrealpath(path); 7257 } catch (e) { 7258 this.fsw._emitReady(); 7259 return true; 7260 } 7261 7262 if (this.fsw.closed) return; 7263 if (dir.has(item)) { 7264 if (this.fsw._symlinkPaths.get(full) !== linkPath) { 7265 this.fsw._symlinkPaths.set(full, linkPath); 7266 this.fsw._emit(EV_CHANGE, path, entry.stats); 7267 } 7268 } else { 7269 dir.add(item); 7270 this.fsw._symlinkPaths.set(full, linkPath); 7271 this.fsw._emit(EV_ADD, path, entry.stats); 7272 } 7273 this.fsw._emitReady(); 7274 return true; 7275 } 7276 7277 // don't follow the same symlink more than once 7278 if (this.fsw._symlinkPaths.has(full)) { 7279 return true; 7280 } 7281 7282 this.fsw._symlinkPaths.set(full, true); 7283 } 7284 7285 _handleRead(directory, initialAdd, wh, target, dir, depth, throttler) { 7286 // Normalize the directory name on Windows 7287 directory = sysPath.join(directory, EMPTY_STR); 7288 7289 if (!wh.hasGlob) { 7290 throttler = this.fsw._throttle('readdir', directory, 1000); 7291 if (!throttler) return; 7292 } 7293 7294 const previous = this.fsw._getWatchedDir(wh.path); 7295 const current = new Set(); 7296 7297 let stream = this.fsw._readdirp(directory, { 7298 fileFilter: entry => wh.filterPath(entry), 7299 directoryFilter: entry => wh.filterDir(entry), 7300 depth: 0 7301 }).on(STR_DATA, async (entry) => { 7302 if (this.fsw.closed) { 7303 stream = undefined; 7304 return; 7305 } 7306 const item = entry.path; 7307 let path = sysPath.join(directory, item); 7308 current.add(item); 7309 7310 if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path, item)) { 7311 return; 7312 } 7313 7314 if (this.fsw.closed) { 7315 stream = undefined; 7316 return; 7317 } 7318 // Files that present in current directory snapshot 7319 // but absent in previous are added to watch list and 7320 // emit `add` event. 7321 if (item === target || !target && !previous.has(item)) { 7322 this.fsw._incrReadyCount(); 7323 7324 // ensure relativeness of path is preserved in case of watcher reuse 7325 path = sysPath.join(dir, sysPath.relative(dir, path)); 7326 7327 this._addToNodeFs(path, initialAdd, wh, depth + 1); 7328 } 7329 }).on(EV_ERROR, this._boundHandleError); 7330 7331 return new Promise(resolve => 7332 stream.once(STR_END, () => { 7333 if (this.fsw.closed) { 7334 stream = undefined; 7335 return; 7336 } 7337 const wasThrottled = throttler ? throttler.clear() : false; 7338 7339 resolve(); 7340 7341 // Files that absent in current directory snapshot 7342 // but present in previous emit `remove` event 7343 // and are removed from @watched[directory]. 7344 previous.getChildren().filter((item) => { 7345 return item !== directory && 7346 !current.has(item) && 7347 // in case of intersecting globs; 7348 // a path may have been filtered out of this readdir, but 7349 // shouldn't be removed because it matches a different glob 7350 (!wh.hasGlob || wh.filterPath({ 7351 fullPath: sysPath.resolve(directory, item) 7352 })); 7353 }).forEach((item) => { 7354 this.fsw._remove(directory, item); 7355 }); 7356 7357 stream = undefined; 7358 7359 // one more time for any missed in case changes came in extremely quickly 7360 if (wasThrottled) this._handleRead(directory, false, wh, target, dir, depth, throttler); 7361 }) 7362 ); 7363 } 7364 7365 /** 7366 * Read directory to add / remove files from `@watched` list and re-read it on change. 7367 * @param {String} dir fs path 7368 * @param {fs.Stats} stats 7369 * @param {Boolean} initialAdd 7370 * @param {Number} depth relative to user-supplied path 7371 * @param {String} target child path targeted for watch 7372 * @param {Object} wh Common watch helpers for this path 7373 * @param {String} realpath 7374 * @returns {Promise<Function>} closer for the watcher instance. 7375 */ 7376 async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath) { 7377 const parentDir = this.fsw._getWatchedDir(sysPath.dirname(dir)); 7378 const tracked = parentDir.has(sysPath.basename(dir)); 7379 if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) { 7380 if (!wh.hasGlob || wh.globFilter(dir)) this.fsw._emit(EV_ADD_DIR, dir, stats); 7381 } 7382 7383 // ensure dir is tracked (harmless if redundant) 7384 parentDir.add(sysPath.basename(dir)); 7385 this.fsw._getWatchedDir(dir); 7386 let throttler; 7387 let closer; 7388 7389 const oDepth = this.fsw.options.depth; 7390 if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath)) { 7391 if (!target) { 7392 await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler); 7393 if (this.fsw.closed) return; 7394 } 7395 7396 closer = this._watchWithNodeFs(dir, (dirPath, stats) => { 7397 // if current directory is removed, do nothing 7398 if (stats && stats.mtimeMs === 0) return; 7399 7400 this._handleRead(dirPath, false, wh, target, dir, depth, throttler); 7401 }); 7402 } 7403 return closer; 7404 } 7405 7406 /** 7407 * Handle added file, directory, or glob pattern. 7408 * Delegates call to _handleFile / _handleDir after checks. 7409 * @param {String} path to file or ir 7410 * @param {Boolean} initialAdd was the file added at watch instantiation? 7411 * @param {Object} priorWh depth relative to user-supplied path 7412 * @param {Number} depth Child path actually targeted for watch 7413 * @param {String=} target Child path actually targeted for watch 7414 * @returns {Promise} 7415 */ 7416 async _addToNodeFs(path, initialAdd, priorWh, depth, target) { 7417 const ready = this.fsw._emitReady; 7418 if (this.fsw._isIgnored(path) || this.fsw.closed) { 7419 ready(); 7420 return false; 7421 } 7422 7423 const wh = this.fsw._getWatchHelpers(path, depth); 7424 if (!wh.hasGlob && priorWh) { 7425 wh.hasGlob = priorWh.hasGlob; 7426 wh.globFilter = priorWh.globFilter; 7427 wh.filterPath = entry => priorWh.filterPath(entry); 7428 wh.filterDir = entry => priorWh.filterDir(entry); 7429 } 7430 7431 // evaluate what is at the path we're being asked to watch 7432 try { 7433 const stats = await statMethods[wh.statMethod](wh.watchPath); 7434 if (this.fsw.closed) return; 7435 if (this.fsw._isIgnored(wh.watchPath, stats)) { 7436 ready(); 7437 return false; 7438 } 7439 7440 const follow = this.fsw.options.followSymlinks && !path.includes(STAR) && !path.includes(BRACE_START); 7441 let closer; 7442 if (stats.isDirectory()) { 7443 const absPath = sysPath.resolve(path); 7444 const targetPath = follow ? await fsrealpath(path) : path; 7445 if (this.fsw.closed) return; 7446 closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath); 7447 if (this.fsw.closed) return; 7448 // preserve this symlink's target path 7449 if (absPath !== targetPath && targetPath !== undefined) { 7450 this.fsw._symlinkPaths.set(absPath, targetPath); 7451 } 7452 } else if (stats.isSymbolicLink()) { 7453 const targetPath = follow ? await fsrealpath(path) : path; 7454 if (this.fsw.closed) return; 7455 const parent = sysPath.dirname(wh.watchPath); 7456 this.fsw._getWatchedDir(parent).add(wh.watchPath); 7457 this.fsw._emit(EV_ADD, wh.watchPath, stats); 7458 closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath); 7459 if (this.fsw.closed) return; 7460 7461 // preserve this symlink's target path 7462 if (targetPath !== undefined) { 7463 this.fsw._symlinkPaths.set(sysPath.resolve(path), targetPath); 7464 } 7465 } else { 7466 closer = this._handleFile(wh.watchPath, stats, initialAdd); 7467 } 7468 ready(); 7469 7470 this.fsw._addPathCloser(path, closer); 7471 return false; 7472 7473 } catch (error) { 7474 if (this.fsw._handleError(error)) { 7475 ready(); 7476 return path; 7477 } 7478 } 7479 } 7480 7481 } 7482 7483 nodefsHandler = NodeFsHandler; 7484 return nodefsHandler; 2739 7485 } 2740 7486 2741 /** 2742 * Watch file for changes with fs_watchFile or fs_watch. 2743 * @param {String} path to file or dir 2744 * @param {Function} listener on fs change 2745 * @returns {Function} closer for the watcher instance 2746 */ 2747 _watchWithNodeFs(path, listener) { 2748 const opts = this.fsw.options; 2749 const directory = sysPath$2.dirname(path); 2750 const basename = sysPath$2.basename(path); 2751 const parent = this.fsw._getWatchedDir(directory); 2752 parent.add(basename); 2753 const absolutePath = sysPath$2.resolve(path); 2754 const options = {persistent: opts.persistent}; 2755 if (!listener) listener = EMPTY_FN$2; 2756 2757 let closer; 2758 if (opts.usePolling) { 2759 options.interval = opts.enableBinaryInterval && isBinaryPath(basename) ? 2760 opts.binaryInterval : opts.interval; 2761 closer = setFsWatchFileListener(path, absolutePath, options, { 2762 listener, 2763 rawEmitter: this.fsw._emitRaw 2764 }); 2765 } else { 2766 closer = setFsWatchListener(path, absolutePath, options, { 2767 listener, 2768 errHandler: this._boundHandleError, 2769 rawEmitter: this.fsw._emitRaw 2770 }); 2771 } 2772 return closer; 7487 var fseventsHandler = {exports: {}}; 7488 7489 const require$$3 = /*@__PURE__*/getAugmentedNamespace(fseventsImporter); 7490 7491 var hasRequiredFseventsHandler; 7492 7493 function requireFseventsHandler () { 7494 if (hasRequiredFseventsHandler) return fseventsHandler.exports; 7495 hasRequiredFseventsHandler = 1; 7496 7497 const fs = require$$0$2; 7498 const sysPath = require$$0$1; 7499 const { promisify } = require$$2; 7500 7501 let fsevents; 7502 try { 7503 fsevents = require$$3.getFsEvents(); 7504 } catch (error) { 7505 if (process.env.CHOKIDAR_PRINT_FSEVENTS_REQUIRE_ERROR) console.error(error); 7506 } 7507 7508 if (fsevents) { 7509 // TODO: real check 7510 const mtch = process.version.match(/v(\d+)\.(\d+)/); 7511 if (mtch && mtch[1] && mtch[2]) { 7512 const maj = Number.parseInt(mtch[1], 10); 7513 const min = Number.parseInt(mtch[2], 10); 7514 if (maj === 8 && min < 16) { 7515 fsevents = undefined; 7516 } 7517 } 7518 } 7519 7520 const { 7521 EV_ADD, 7522 EV_CHANGE, 7523 EV_ADD_DIR, 7524 EV_UNLINK, 7525 EV_ERROR, 7526 STR_DATA, 7527 STR_END, 7528 FSEVENT_CREATED, 7529 FSEVENT_MODIFIED, 7530 FSEVENT_DELETED, 7531 FSEVENT_MOVED, 7532 // FSEVENT_CLONED, 7533 FSEVENT_UNKNOWN, 7534 FSEVENT_FLAG_MUST_SCAN_SUBDIRS, 7535 FSEVENT_TYPE_FILE, 7536 FSEVENT_TYPE_DIRECTORY, 7537 FSEVENT_TYPE_SYMLINK, 7538 7539 ROOT_GLOBSTAR, 7540 DIR_SUFFIX, 7541 DOT_SLASH, 7542 FUNCTION_TYPE, 7543 EMPTY_FN, 7544 IDENTITY_FN 7545 } = /*@__PURE__*/ requireConstants(); 7546 7547 const Depth = (value) => isNaN(value) ? {} : {depth: value}; 7548 7549 const stat = promisify(fs.stat); 7550 const lstat = promisify(fs.lstat); 7551 const realpath = promisify(fs.realpath); 7552 7553 const statMethods = { stat, lstat }; 7554 7555 /** 7556 * @typedef {String} Path 7557 */ 7558 7559 /** 7560 * @typedef {Object} FsEventsWatchContainer 7561 * @property {Set<Function>} listeners 7562 * @property {Function} rawEmitter 7563 * @property {{stop: Function}} watcher 7564 */ 7565 7566 // fsevents instance helper functions 7567 /** 7568 * Object to hold per-process fsevents instances (may be shared across chokidar FSWatcher instances) 7569 * @type {Map<Path,FsEventsWatchContainer>} 7570 */ 7571 const FSEventsWatchers = new Map(); 7572 7573 // Threshold of duplicate path prefixes at which to start 7574 // consolidating going forward 7575 const consolidateThreshhold = 10; 7576 7577 const wrongEventFlags = new Set([ 7578 69888, 70400, 71424, 72704, 73472, 131328, 131840, 262912 7579 ]); 7580 7581 /** 7582 * Instantiates the fsevents interface 7583 * @param {Path} path path to be watched 7584 * @param {Function} callback called when fsevents is bound and ready 7585 * @returns {{stop: Function}} new fsevents instance 7586 */ 7587 const createFSEventsInstance = (path, callback) => { 7588 const stop = fsevents.watch(path, callback); 7589 return {stop}; 7590 }; 7591 7592 /** 7593 * Instantiates the fsevents interface or binds listeners to an existing one covering 7594 * the same file tree. 7595 * @param {Path} path - to be watched 7596 * @param {Path} realPath - real path for symlinks 7597 * @param {Function} listener - called when fsevents emits events 7598 * @param {Function} rawEmitter - passes data to listeners of the 'raw' event 7599 * @returns {Function} closer 7600 */ 7601 function setFSEventsListener(path, realPath, listener, rawEmitter) { 7602 let watchPath = sysPath.extname(realPath) ? sysPath.dirname(realPath) : realPath; 7603 7604 const parentPath = sysPath.dirname(watchPath); 7605 let cont = FSEventsWatchers.get(watchPath); 7606 7607 // If we've accumulated a substantial number of paths that 7608 // could have been consolidated by watching one directory 7609 // above the current one, create a watcher on the parent 7610 // path instead, so that we do consolidate going forward. 7611 if (couldConsolidate(parentPath)) { 7612 watchPath = parentPath; 7613 } 7614 7615 const resolvedPath = sysPath.resolve(path); 7616 const hasSymlink = resolvedPath !== realPath; 7617 7618 const filteredListener = (fullPath, flags, info) => { 7619 if (hasSymlink) fullPath = fullPath.replace(realPath, resolvedPath); 7620 if ( 7621 fullPath === resolvedPath || 7622 !fullPath.indexOf(resolvedPath + sysPath.sep) 7623 ) listener(fullPath, flags, info); 7624 }; 7625 7626 // check if there is already a watcher on a parent path 7627 // modifies `watchPath` to the parent path when it finds a match 7628 let watchedParent = false; 7629 for (const watchedPath of FSEventsWatchers.keys()) { 7630 if (realPath.indexOf(sysPath.resolve(watchedPath) + sysPath.sep) === 0) { 7631 watchPath = watchedPath; 7632 cont = FSEventsWatchers.get(watchPath); 7633 watchedParent = true; 7634 break; 7635 } 7636 } 7637 7638 if (cont || watchedParent) { 7639 cont.listeners.add(filteredListener); 7640 } else { 7641 cont = { 7642 listeners: new Set([filteredListener]), 7643 rawEmitter, 7644 watcher: createFSEventsInstance(watchPath, (fullPath, flags) => { 7645 if (!cont.listeners.size) return; 7646 if (flags & FSEVENT_FLAG_MUST_SCAN_SUBDIRS) return; 7647 const info = fsevents.getInfo(fullPath, flags); 7648 cont.listeners.forEach(list => { 7649 list(fullPath, flags, info); 7650 }); 7651 7652 cont.rawEmitter(info.event, fullPath, info); 7653 }) 7654 }; 7655 FSEventsWatchers.set(watchPath, cont); 7656 } 7657 7658 // removes this instance's listeners and closes the underlying fsevents 7659 // instance if there are no more listeners left 7660 return () => { 7661 const lst = cont.listeners; 7662 7663 lst.delete(filteredListener); 7664 if (!lst.size) { 7665 FSEventsWatchers.delete(watchPath); 7666 if (cont.watcher) return cont.watcher.stop().then(() => { 7667 cont.rawEmitter = cont.watcher = undefined; 7668 Object.freeze(cont); 7669 }); 7670 } 7671 }; 7672 } 7673 7674 // Decide whether or not we should start a new higher-level 7675 // parent watcher 7676 const couldConsolidate = (path) => { 7677 let count = 0; 7678 for (const watchPath of FSEventsWatchers.keys()) { 7679 if (watchPath.indexOf(path) === 0) { 7680 count++; 7681 if (count >= consolidateThreshhold) { 7682 return true; 7683 } 7684 } 7685 } 7686 7687 return false; 7688 }; 7689 7690 // returns boolean indicating whether fsevents can be used 7691 const canUse = () => fsevents && FSEventsWatchers.size < 128; 7692 7693 // determines subdirectory traversal levels from root to path 7694 const calcDepth = (path, root) => { 7695 let i = 0; 7696 while (!path.indexOf(root) && (path = sysPath.dirname(path)) !== root) i++; 7697 return i; 7698 }; 7699 7700 // returns boolean indicating whether the fsevents' event info has the same type 7701 // as the one returned by fs.stat 7702 const sameTypes = (info, stats) => ( 7703 info.type === FSEVENT_TYPE_DIRECTORY && stats.isDirectory() || 7704 info.type === FSEVENT_TYPE_SYMLINK && stats.isSymbolicLink() || 7705 info.type === FSEVENT_TYPE_FILE && stats.isFile() 7706 ); 7707 7708 /** 7709 * @mixin 7710 */ 7711 class FsEventsHandler { 7712 7713 /** 7714 * @param {import('../index').FSWatcher} fsw 7715 */ 7716 constructor(fsw) { 7717 this.fsw = fsw; 7718 } 7719 checkIgnored(path, stats) { 7720 const ipaths = this.fsw._ignoredPaths; 7721 if (this.fsw._isIgnored(path, stats)) { 7722 ipaths.add(path); 7723 if (stats && stats.isDirectory()) { 7724 ipaths.add(path + ROOT_GLOBSTAR); 7725 } 7726 return true; 7727 } 7728 7729 ipaths.delete(path); 7730 ipaths.delete(path + ROOT_GLOBSTAR); 7731 } 7732 7733 addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts) { 7734 const event = watchedDir.has(item) ? EV_CHANGE : EV_ADD; 7735 this.handleEvent(event, path, fullPath, realPath, parent, watchedDir, item, info, opts); 7736 } 7737 7738 async checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts) { 7739 try { 7740 const stats = await stat(path); 7741 if (this.fsw.closed) return; 7742 if (sameTypes(info, stats)) { 7743 this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts); 7744 } else { 7745 this.handleEvent(EV_UNLINK, path, fullPath, realPath, parent, watchedDir, item, info, opts); 7746 } 7747 } catch (error) { 7748 if (error.code === 'EACCES') { 7749 this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts); 7750 } else { 7751 this.handleEvent(EV_UNLINK, path, fullPath, realPath, parent, watchedDir, item, info, opts); 7752 } 7753 } 7754 } 7755 7756 handleEvent(event, path, fullPath, realPath, parent, watchedDir, item, info, opts) { 7757 if (this.fsw.closed || this.checkIgnored(path)) return; 7758 7759 if (event === EV_UNLINK) { 7760 const isDirectory = info.type === FSEVENT_TYPE_DIRECTORY; 7761 // suppress unlink events on never before seen files 7762 if (isDirectory || watchedDir.has(item)) { 7763 this.fsw._remove(parent, item, isDirectory); 7764 } 7765 } else { 7766 if (event === EV_ADD) { 7767 // track new directories 7768 if (info.type === FSEVENT_TYPE_DIRECTORY) this.fsw._getWatchedDir(path); 7769 7770 if (info.type === FSEVENT_TYPE_SYMLINK && opts.followSymlinks) { 7771 // push symlinks back to the top of the stack to get handled 7772 const curDepth = opts.depth === undefined ? 7773 undefined : calcDepth(fullPath, realPath) + 1; 7774 return this._addToFsEvents(path, false, true, curDepth); 7775 } 7776 7777 // track new paths 7778 // (other than symlinks being followed, which will be tracked soon) 7779 this.fsw._getWatchedDir(parent).add(item); 7780 } 7781 /** 7782 * @type {'add'|'addDir'|'unlink'|'unlinkDir'} 7783 */ 7784 const eventName = info.type === FSEVENT_TYPE_DIRECTORY ? event + DIR_SUFFIX : event; 7785 this.fsw._emit(eventName, path); 7786 if (eventName === EV_ADD_DIR) this._addToFsEvents(path, false, true); 7787 } 7788 } 7789 7790 /** 7791 * Handle symlinks encountered during directory scan 7792 * @param {String} watchPath - file/dir path to be watched with fsevents 7793 * @param {String} realPath - real path (in case of symlinks) 7794 * @param {Function} transform - path transformer 7795 * @param {Function} globFilter - path filter in case a glob pattern was provided 7796 * @returns {Function} closer for the watcher instance 7797 */ 7798 _watchWithFsEvents(watchPath, realPath, transform, globFilter) { 7799 if (this.fsw.closed || this.fsw._isIgnored(watchPath)) return; 7800 const opts = this.fsw.options; 7801 const watchCallback = async (fullPath, flags, info) => { 7802 if (this.fsw.closed) return; 7803 if ( 7804 opts.depth !== undefined && 7805 calcDepth(fullPath, realPath) > opts.depth 7806 ) return; 7807 const path = transform(sysPath.join( 7808 watchPath, sysPath.relative(watchPath, fullPath) 7809 )); 7810 if (globFilter && !globFilter(path)) return; 7811 // ensure directories are tracked 7812 const parent = sysPath.dirname(path); 7813 const item = sysPath.basename(path); 7814 const watchedDir = this.fsw._getWatchedDir( 7815 info.type === FSEVENT_TYPE_DIRECTORY ? path : parent 7816 ); 7817 7818 // correct for wrong events emitted 7819 if (wrongEventFlags.has(flags) || info.event === FSEVENT_UNKNOWN) { 7820 if (typeof opts.ignored === FUNCTION_TYPE) { 7821 let stats; 7822 try { 7823 stats = await stat(path); 7824 } catch (error) {} 7825 if (this.fsw.closed) return; 7826 if (this.checkIgnored(path, stats)) return; 7827 if (sameTypes(info, stats)) { 7828 this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts); 7829 } else { 7830 this.handleEvent(EV_UNLINK, path, fullPath, realPath, parent, watchedDir, item, info, opts); 7831 } 7832 } else { 7833 this.checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts); 7834 } 7835 } else { 7836 switch (info.event) { 7837 case FSEVENT_CREATED: 7838 case FSEVENT_MODIFIED: 7839 return this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts); 7840 case FSEVENT_DELETED: 7841 case FSEVENT_MOVED: 7842 return this.checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts); 7843 } 7844 } 7845 }; 7846 7847 const closer = setFSEventsListener( 7848 watchPath, 7849 realPath, 7850 watchCallback, 7851 this.fsw._emitRaw 7852 ); 7853 7854 this.fsw._emitReady(); 7855 return closer; 7856 } 7857 7858 /** 7859 * Handle symlinks encountered during directory scan 7860 * @param {String} linkPath path to symlink 7861 * @param {String} fullPath absolute path to the symlink 7862 * @param {Function} transform pre-existing path transformer 7863 * @param {Number} curDepth level of subdirectories traversed to where symlink is 7864 * @returns {Promise<void>} 7865 */ 7866 async _handleFsEventsSymlink(linkPath, fullPath, transform, curDepth) { 7867 // don't follow the same symlink more than once 7868 if (this.fsw.closed || this.fsw._symlinkPaths.has(fullPath)) return; 7869 7870 this.fsw._symlinkPaths.set(fullPath, true); 7871 this.fsw._incrReadyCount(); 7872 7873 try { 7874 const linkTarget = await realpath(linkPath); 7875 if (this.fsw.closed) return; 7876 if (this.fsw._isIgnored(linkTarget)) { 7877 return this.fsw._emitReady(); 7878 } 7879 7880 this.fsw._incrReadyCount(); 7881 7882 // add the linkTarget for watching with a wrapper for transform 7883 // that causes emitted paths to incorporate the link's path 7884 this._addToFsEvents(linkTarget || linkPath, (path) => { 7885 let aliasedPath = linkPath; 7886 if (linkTarget && linkTarget !== DOT_SLASH) { 7887 aliasedPath = path.replace(linkTarget, linkPath); 7888 } else if (path !== DOT_SLASH) { 7889 aliasedPath = sysPath.join(linkPath, path); 7890 } 7891 return transform(aliasedPath); 7892 }, false, curDepth); 7893 } catch(error) { 7894 if (this.fsw._handleError(error)) { 7895 return this.fsw._emitReady(); 7896 } 7897 } 7898 } 7899 7900 /** 7901 * 7902 * @param {Path} newPath 7903 * @param {fs.Stats} stats 7904 */ 7905 emitAdd(newPath, stats, processPath, opts, forceAdd) { 7906 const pp = processPath(newPath); 7907 const isDir = stats.isDirectory(); 7908 const dirObj = this.fsw._getWatchedDir(sysPath.dirname(pp)); 7909 const base = sysPath.basename(pp); 7910 7911 // ensure empty dirs get tracked 7912 if (isDir) this.fsw._getWatchedDir(pp); 7913 if (dirObj.has(base)) return; 7914 dirObj.add(base); 7915 7916 if (!opts.ignoreInitial || forceAdd === true) { 7917 this.fsw._emit(isDir ? EV_ADD_DIR : EV_ADD, pp, stats); 7918 } 7919 } 7920 7921 initWatch(realPath, path, wh, processPath) { 7922 if (this.fsw.closed) return; 7923 const closer = this._watchWithFsEvents( 7924 wh.watchPath, 7925 sysPath.resolve(realPath || wh.watchPath), 7926 processPath, 7927 wh.globFilter 7928 ); 7929 this.fsw._addPathCloser(path, closer); 7930 } 7931 7932 /** 7933 * Handle added path with fsevents 7934 * @param {String} path file/dir path or glob pattern 7935 * @param {Function|Boolean=} transform converts working path to what the user expects 7936 * @param {Boolean=} forceAdd ensure add is emitted 7937 * @param {Number=} priorDepth Level of subdirectories already traversed. 7938 * @returns {Promise<void>} 7939 */ 7940 async _addToFsEvents(path, transform, forceAdd, priorDepth) { 7941 if (this.fsw.closed) { 7942 return; 7943 } 7944 const opts = this.fsw.options; 7945 const processPath = typeof transform === FUNCTION_TYPE ? transform : IDENTITY_FN; 7946 7947 const wh = this.fsw._getWatchHelpers(path); 7948 7949 // evaluate what is at the path we're being asked to watch 7950 try { 7951 const stats = await statMethods[wh.statMethod](wh.watchPath); 7952 if (this.fsw.closed) return; 7953 if (this.fsw._isIgnored(wh.watchPath, stats)) { 7954 throw null; 7955 } 7956 if (stats.isDirectory()) { 7957 // emit addDir unless this is a glob parent 7958 if (!wh.globFilter) this.emitAdd(processPath(path), stats, processPath, opts, forceAdd); 7959 7960 // don't recurse further if it would exceed depth setting 7961 if (priorDepth && priorDepth > opts.depth) return; 7962 7963 // scan the contents of the dir 7964 this.fsw._readdirp(wh.watchPath, { 7965 fileFilter: entry => wh.filterPath(entry), 7966 directoryFilter: entry => wh.filterDir(entry), 7967 ...Depth(opts.depth - (priorDepth || 0)) 7968 }).on(STR_DATA, (entry) => { 7969 // need to check filterPath on dirs b/c filterDir is less restrictive 7970 if (this.fsw.closed) { 7971 return; 7972 } 7973 if (entry.stats.isDirectory() && !wh.filterPath(entry)) return; 7974 7975 const joinedPath = sysPath.join(wh.watchPath, entry.path); 7976 const {fullPath} = entry; 7977 7978 if (wh.followSymlinks && entry.stats.isSymbolicLink()) { 7979 // preserve the current depth here since it can't be derived from 7980 // real paths past the symlink 7981 const curDepth = opts.depth === undefined ? 7982 undefined : calcDepth(joinedPath, sysPath.resolve(wh.watchPath)) + 1; 7983 7984 this._handleFsEventsSymlink(joinedPath, fullPath, processPath, curDepth); 7985 } else { 7986 this.emitAdd(joinedPath, entry.stats, processPath, opts, forceAdd); 7987 } 7988 }).on(EV_ERROR, EMPTY_FN).on(STR_END, () => { 7989 this.fsw._emitReady(); 7990 }); 7991 } else { 7992 this.emitAdd(wh.watchPath, stats, processPath, opts, forceAdd); 7993 this.fsw._emitReady(); 7994 } 7995 } catch (error) { 7996 if (!error || this.fsw._handleError(error)) { 7997 // TODO: Strange thing: "should not choke on an ignored watch path" will be failed without 2 ready calls -__- 7998 this.fsw._emitReady(); 7999 this.fsw._emitReady(); 8000 } 8001 } 8002 8003 if (opts.persistent && forceAdd !== true) { 8004 if (typeof transform === FUNCTION_TYPE) { 8005 // realpath has already been resolved 8006 this.initWatch(undefined, path, wh, processPath); 8007 } else { 8008 let realPath; 8009 try { 8010 realPath = await realpath(wh.watchPath); 8011 } catch (e) {} 8012 this.initWatch(realPath, path, wh, processPath); 8013 } 8014 } 8015 } 8016 8017 } 8018 8019 fseventsHandler.exports = FsEventsHandler; 8020 fseventsHandler.exports.canUse = canUse; 8021 return fseventsHandler.exports; 2773 8022 } 2774 8023 2775 /** 2776 * Watch a file and emit add event if warranted. 2777 * @param {Path} file Path 2778 * @param {fs.Stats} stats result of fs_stat 2779 * @param {Boolean} initialAdd was the file added at watch instantiation? 2780 * @returns {Function} closer for the watcher instance 2781 */ 2782 _handleFile(file, stats, initialAdd) { 2783 if (this.fsw.closed) { 2784 return; 2785 } 2786 const dirname = sysPath$2.dirname(file); 2787 const basename = sysPath$2.basename(file); 2788 const parent = this.fsw._getWatchedDir(dirname); 2789 // stats is always present 2790 let prevStats = stats; 2791 2792 // if the file is already being watched, do nothing 2793 if (parent.has(basename)) return; 2794 2795 const listener = async (path, newStats) => { 2796 if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5)) return; 2797 if (!newStats || newStats.mtimeMs === 0) { 2798 try { 2799 const newStats = await stat$2(file); 2800 if (this.fsw.closed) return; 2801 // Check that change event was not fired because of changed only accessTime. 2802 const at = newStats.atimeMs; 2803 const mt = newStats.mtimeMs; 2804 if (!at || at <= mt || mt !== prevStats.mtimeMs) { 2805 this.fsw._emit(EV_CHANGE$2, file, newStats); 2806 } 2807 if (isLinux && prevStats.ino !== newStats.ino) { 2808 this.fsw._closeFile(path); 2809 prevStats = newStats; 2810 this.fsw._addPathCloser(path, this._watchWithNodeFs(file, listener)); 2811 } else { 2812 prevStats = newStats; 2813 } 2814 } catch (error) { 2815 // Fix issues where mtime is null but file is still present 2816 this.fsw._remove(dirname, basename); 2817 } 2818 // add is about to be emitted if file not already tracked in parent 2819 } else if (parent.has(basename)) { 2820 // Check that change event was not fired because of changed only accessTime. 2821 const at = newStats.atimeMs; 2822 const mt = newStats.mtimeMs; 2823 if (!at || at <= mt || mt !== prevStats.mtimeMs) { 2824 this.fsw._emit(EV_CHANGE$2, file, newStats); 2825 } 2826 prevStats = newStats; 2827 } 2828 }; 2829 // kick off the watcher 2830 const closer = this._watchWithNodeFs(file, listener); 2831 2832 // emit an add event if we're supposed to 2833 if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file)) { 2834 if (!this.fsw._throttle(EV_ADD$2, file, 0)) return; 2835 this.fsw._emit(EV_ADD$2, file, stats); 2836 } 2837 2838 return closer; 8024 var hasRequiredChokidar; 8025 8026 function requireChokidar () { 8027 if (hasRequiredChokidar) return chokidar$1; 8028 hasRequiredChokidar = 1; 8029 8030 const { EventEmitter } = require$$0$3; 8031 const fs = require$$0$2; 8032 const sysPath = require$$0$1; 8033 const { promisify } = require$$2; 8034 const readdirp = /*@__PURE__*/ requireReaddirp(); 8035 const anymatch = /*@__PURE__*/ requireAnymatch().default; 8036 const globParent = /*@__PURE__*/ requireGlobParent(); 8037 const isGlob = /*@__PURE__*/ requireIsGlob(); 8038 const braces = /*@__PURE__*/ requireBraces(); 8039 const normalizePath = /*@__PURE__*/ requireNormalizePath(); 8040 8041 const NodeFsHandler = /*@__PURE__*/ requireNodefsHandler(); 8042 const FsEventsHandler = /*@__PURE__*/ requireFseventsHandler(); 8043 const { 8044 EV_ALL, 8045 EV_READY, 8046 EV_ADD, 8047 EV_CHANGE, 8048 EV_UNLINK, 8049 EV_ADD_DIR, 8050 EV_UNLINK_DIR, 8051 EV_RAW, 8052 EV_ERROR, 8053 8054 STR_CLOSE, 8055 STR_END, 8056 8057 BACK_SLASH_RE, 8058 DOUBLE_SLASH_RE, 8059 SLASH_OR_BACK_SLASH_RE, 8060 DOT_RE, 8061 REPLACER_RE, 8062 8063 SLASH, 8064 SLASH_SLASH, 8065 BRACE_START, 8066 BANG, 8067 ONE_DOT, 8068 TWO_DOTS, 8069 GLOBSTAR, 8070 SLASH_GLOBSTAR, 8071 ANYMATCH_OPTS, 8072 STRING_TYPE, 8073 FUNCTION_TYPE, 8074 EMPTY_STR, 8075 EMPTY_FN, 8076 8077 isWindows, 8078 isMacos, 8079 isIBMi 8080 } = /*@__PURE__*/ requireConstants(); 8081 8082 const stat = promisify(fs.stat); 8083 const readdir = promisify(fs.readdir); 8084 8085 /** 8086 * @typedef {String} Path 8087 * @typedef {'all'|'add'|'addDir'|'change'|'unlink'|'unlinkDir'|'raw'|'error'|'ready'} EventName 8088 * @typedef {'readdir'|'watch'|'add'|'remove'|'change'} ThrottleType 8089 */ 8090 8091 /** 8092 * 8093 * @typedef {Object} WatchHelpers 8094 * @property {Boolean} followSymlinks 8095 * @property {'stat'|'lstat'} statMethod 8096 * @property {Path} path 8097 * @property {Path} watchPath 8098 * @property {Function} entryPath 8099 * @property {Boolean} hasGlob 8100 * @property {Object} globFilter 8101 * @property {Function} filterPath 8102 * @property {Function} filterDir 8103 */ 8104 8105 const arrify = (value = []) => Array.isArray(value) ? value : [value]; 8106 const flatten = (list, result = []) => { 8107 list.forEach(item => { 8108 if (Array.isArray(item)) { 8109 flatten(item, result); 8110 } else { 8111 result.push(item); 8112 } 8113 }); 8114 return result; 8115 }; 8116 8117 const unifyPaths = (paths_) => { 8118 /** 8119 * @type {Array<String>} 8120 */ 8121 const paths = flatten(arrify(paths_)); 8122 if (!paths.every(p => typeof p === STRING_TYPE)) { 8123 throw new TypeError(`Non-string provided as watch path: ${paths}`); 8124 } 8125 return paths.map(normalizePathToUnix); 8126 }; 8127 8128 // If SLASH_SLASH occurs at the beginning of path, it is not replaced 8129 // because "//StoragePC/DrivePool/Movies" is a valid network path 8130 const toUnix = (string) => { 8131 let str = string.replace(BACK_SLASH_RE, SLASH); 8132 let prepend = false; 8133 if (str.startsWith(SLASH_SLASH)) { 8134 prepend = true; 8135 } 8136 while (str.match(DOUBLE_SLASH_RE)) { 8137 str = str.replace(DOUBLE_SLASH_RE, SLASH); 8138 } 8139 if (prepend) { 8140 str = SLASH + str; 8141 } 8142 return str; 8143 }; 8144 8145 // Our version of upath.normalize 8146 // TODO: this is not equal to path-normalize module - investigate why 8147 const normalizePathToUnix = (path) => toUnix(sysPath.normalize(toUnix(path))); 8148 8149 const normalizeIgnored = (cwd = EMPTY_STR) => (path) => { 8150 if (typeof path !== STRING_TYPE) return path; 8151 return normalizePathToUnix(sysPath.isAbsolute(path) ? path : sysPath.join(cwd, path)); 8152 }; 8153 8154 const getAbsolutePath = (path, cwd) => { 8155 if (sysPath.isAbsolute(path)) { 8156 return path; 8157 } 8158 if (path.startsWith(BANG)) { 8159 return BANG + sysPath.join(cwd, path.slice(1)); 8160 } 8161 return sysPath.join(cwd, path); 8162 }; 8163 8164 const undef = (opts, key) => opts[key] === undefined; 8165 8166 /** 8167 * Directory entry. 8168 * @property {Path} path 8169 * @property {Set<Path>} items 8170 */ 8171 class DirEntry { 8172 /** 8173 * @param {Path} dir 8174 * @param {Function} removeWatcher 8175 */ 8176 constructor(dir, removeWatcher) { 8177 this.path = dir; 8178 this._removeWatcher = removeWatcher; 8179 /** @type {Set<Path>} */ 8180 this.items = new Set(); 8181 } 8182 8183 add(item) { 8184 const {items} = this; 8185 if (!items) return; 8186 if (item !== ONE_DOT && item !== TWO_DOTS) items.add(item); 8187 } 8188 8189 async remove(item) { 8190 const {items} = this; 8191 if (!items) return; 8192 items.delete(item); 8193 if (items.size > 0) return; 8194 8195 const dir = this.path; 8196 try { 8197 await readdir(dir); 8198 } catch (err) { 8199 if (this._removeWatcher) { 8200 this._removeWatcher(sysPath.dirname(dir), sysPath.basename(dir)); 8201 } 8202 } 8203 } 8204 8205 has(item) { 8206 const {items} = this; 8207 if (!items) return; 8208 return items.has(item); 8209 } 8210 8211 /** 8212 * @returns {Array<String>} 8213 */ 8214 getChildren() { 8215 const {items} = this; 8216 if (!items) return; 8217 return [...items.values()]; 8218 } 8219 8220 dispose() { 8221 this.items.clear(); 8222 delete this.path; 8223 delete this._removeWatcher; 8224 delete this.items; 8225 Object.freeze(this); 8226 } 8227 } 8228 8229 const STAT_METHOD_F = 'stat'; 8230 const STAT_METHOD_L = 'lstat'; 8231 class WatchHelper { 8232 constructor(path, watchPath, follow, fsw) { 8233 this.fsw = fsw; 8234 this.path = path = path.replace(REPLACER_RE, EMPTY_STR); 8235 this.watchPath = watchPath; 8236 this.fullWatchPath = sysPath.resolve(watchPath); 8237 this.hasGlob = watchPath !== path; 8238 /** @type {object|boolean} */ 8239 if (path === EMPTY_STR) this.hasGlob = false; 8240 this.globSymlink = this.hasGlob && follow ? undefined : false; 8241 this.globFilter = this.hasGlob ? anymatch(path, undefined, ANYMATCH_OPTS) : false; 8242 this.dirParts = this.getDirParts(path); 8243 this.dirParts.forEach((parts) => { 8244 if (parts.length > 1) parts.pop(); 8245 }); 8246 this.followSymlinks = follow; 8247 this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L; 8248 } 8249 8250 checkGlobSymlink(entry) { 8251 // only need to resolve once 8252 // first entry should always have entry.parentDir === EMPTY_STR 8253 if (this.globSymlink === undefined) { 8254 this.globSymlink = entry.fullParentDir === this.fullWatchPath ? 8255 false : {realPath: entry.fullParentDir, linkPath: this.fullWatchPath}; 8256 } 8257 8258 if (this.globSymlink) { 8259 return entry.fullPath.replace(this.globSymlink.realPath, this.globSymlink.linkPath); 8260 } 8261 8262 return entry.fullPath; 8263 } 8264 8265 entryPath(entry) { 8266 return sysPath.join(this.watchPath, 8267 sysPath.relative(this.watchPath, this.checkGlobSymlink(entry)) 8268 ); 8269 } 8270 8271 filterPath(entry) { 8272 const {stats} = entry; 8273 if (stats && stats.isSymbolicLink()) return this.filterDir(entry); 8274 const resolvedPath = this.entryPath(entry); 8275 const matchesGlob = this.hasGlob && typeof this.globFilter === FUNCTION_TYPE ? 8276 this.globFilter(resolvedPath) : true; 8277 return matchesGlob && 8278 this.fsw._isntIgnored(resolvedPath, stats) && 8279 this.fsw._hasReadPermissions(stats); 8280 } 8281 8282 getDirParts(path) { 8283 if (!this.hasGlob) return []; 8284 const parts = []; 8285 const expandedPath = path.includes(BRACE_START) ? braces.expand(path) : [path]; 8286 expandedPath.forEach((path) => { 8287 parts.push(sysPath.relative(this.watchPath, path).split(SLASH_OR_BACK_SLASH_RE)); 8288 }); 8289 return parts; 8290 } 8291 8292 filterDir(entry) { 8293 if (this.hasGlob) { 8294 const entryParts = this.getDirParts(this.checkGlobSymlink(entry)); 8295 let globstar = false; 8296 this.unmatchedGlob = !this.dirParts.some((parts) => { 8297 return parts.every((part, i) => { 8298 if (part === GLOBSTAR) globstar = true; 8299 return globstar || !entryParts[0][i] || anymatch(part, entryParts[0][i], ANYMATCH_OPTS); 8300 }); 8301 }); 8302 } 8303 return !this.unmatchedGlob && this.fsw._isntIgnored(this.entryPath(entry), entry.stats); 8304 } 8305 } 8306 8307 /** 8308 * Watches files & directories for changes. Emitted events: 8309 * `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `all`, `error` 8310 * 8311 * new FSWatcher() 8312 * .add(directories) 8313 * .on('add', path => log('File', path, 'was added')) 8314 */ 8315 class FSWatcher extends EventEmitter { 8316 // Not indenting methods for history sake; for now. 8317 constructor(_opts) { 8318 super(); 8319 8320 const opts = {}; 8321 if (_opts) Object.assign(opts, _opts); // for frozen objects 8322 8323 /** @type {Map<String, DirEntry>} */ 8324 this._watched = new Map(); 8325 /** @type {Map<String, Array>} */ 8326 this._closers = new Map(); 8327 /** @type {Set<String>} */ 8328 this._ignoredPaths = new Set(); 8329 8330 /** @type {Map<ThrottleType, Map>} */ 8331 this._throttled = new Map(); 8332 8333 /** @type {Map<Path, String|Boolean>} */ 8334 this._symlinkPaths = new Map(); 8335 8336 this._streams = new Set(); 8337 this.closed = false; 8338 8339 // Set up default options. 8340 if (undef(opts, 'persistent')) opts.persistent = true; 8341 if (undef(opts, 'ignoreInitial')) opts.ignoreInitial = false; 8342 if (undef(opts, 'ignorePermissionErrors')) opts.ignorePermissionErrors = false; 8343 if (undef(opts, 'interval')) opts.interval = 100; 8344 if (undef(opts, 'binaryInterval')) opts.binaryInterval = 300; 8345 if (undef(opts, 'disableGlobbing')) opts.disableGlobbing = false; 8346 opts.enableBinaryInterval = opts.binaryInterval !== opts.interval; 8347 8348 // Enable fsevents on OS X when polling isn't explicitly enabled. 8349 if (undef(opts, 'useFsEvents')) opts.useFsEvents = !opts.usePolling; 8350 8351 // If we can't use fsevents, ensure the options reflect it's disabled. 8352 const canUseFsEvents = FsEventsHandler.canUse(); 8353 if (!canUseFsEvents) opts.useFsEvents = false; 8354 8355 // Use polling on Mac if not using fsevents. 8356 // Other platforms use non-polling fs_watch. 8357 if (undef(opts, 'usePolling') && !opts.useFsEvents) { 8358 opts.usePolling = isMacos; 8359 } 8360 8361 // Always default to polling on IBM i because fs.watch() is not available on IBM i. 8362 if(isIBMi) { 8363 opts.usePolling = true; 8364 } 8365 8366 // Global override (useful for end-developers that need to force polling for all 8367 // instances of chokidar, regardless of usage/dependency depth) 8368 const envPoll = process.env.CHOKIDAR_USEPOLLING; 8369 if (envPoll !== undefined) { 8370 const envLower = envPoll.toLowerCase(); 8371 8372 if (envLower === 'false' || envLower === '0') { 8373 opts.usePolling = false; 8374 } else if (envLower === 'true' || envLower === '1') { 8375 opts.usePolling = true; 8376 } else { 8377 opts.usePolling = !!envLower; 8378 } 8379 } 8380 const envInterval = process.env.CHOKIDAR_INTERVAL; 8381 if (envInterval) { 8382 opts.interval = Number.parseInt(envInterval, 10); 8383 } 8384 8385 // Editor atomic write normalization enabled by default with fs.watch 8386 if (undef(opts, 'atomic')) opts.atomic = !opts.usePolling && !opts.useFsEvents; 8387 if (opts.atomic) this._pendingUnlinks = new Map(); 8388 8389 if (undef(opts, 'followSymlinks')) opts.followSymlinks = true; 8390 8391 if (undef(opts, 'awaitWriteFinish')) opts.awaitWriteFinish = false; 8392 if (opts.awaitWriteFinish === true) opts.awaitWriteFinish = {}; 8393 const awf = opts.awaitWriteFinish; 8394 if (awf) { 8395 if (!awf.stabilityThreshold) awf.stabilityThreshold = 2000; 8396 if (!awf.pollInterval) awf.pollInterval = 100; 8397 this._pendingWrites = new Map(); 8398 } 8399 if (opts.ignored) opts.ignored = arrify(opts.ignored); 8400 8401 let readyCalls = 0; 8402 this._emitReady = () => { 8403 readyCalls++; 8404 if (readyCalls >= this._readyCount) { 8405 this._emitReady = EMPTY_FN; 8406 this._readyEmitted = true; 8407 // use process.nextTick to allow time for listener to be bound 8408 process.nextTick(() => this.emit(EV_READY)); 8409 } 8410 }; 8411 this._emitRaw = (...args) => this.emit(EV_RAW, ...args); 8412 this._readyEmitted = false; 8413 this.options = opts; 8414 8415 // Initialize with proper watcher. 8416 if (opts.useFsEvents) { 8417 this._fsEventsHandler = new FsEventsHandler(this); 8418 } else { 8419 this._nodeFsHandler = new NodeFsHandler(this); 8420 } 8421 8422 // You’re frozen when your heart’s not open. 8423 Object.freeze(opts); 8424 } 8425 8426 // Public methods 8427 8428 /** 8429 * Adds paths to be watched on an existing FSWatcher instance 8430 * @param {Path|Array<Path>} paths_ 8431 * @param {String=} _origAdd private; for handling non-existent paths to be watched 8432 * @param {Boolean=} _internal private; indicates a non-user add 8433 * @returns {FSWatcher} for chaining 8434 */ 8435 add(paths_, _origAdd, _internal) { 8436 const {cwd, disableGlobbing} = this.options; 8437 this.closed = false; 8438 let paths = unifyPaths(paths_); 8439 if (cwd) { 8440 paths = paths.map((path) => { 8441 const absPath = getAbsolutePath(path, cwd); 8442 8443 // Check `path` instead of `absPath` because the cwd portion can't be a glob 8444 if (disableGlobbing || !isGlob(path)) { 8445 return absPath; 8446 } 8447 return normalizePath(absPath); 8448 }); 8449 } 8450 8451 // set aside negated glob strings 8452 paths = paths.filter((path) => { 8453 if (path.startsWith(BANG)) { 8454 this._ignoredPaths.add(path.slice(1)); 8455 return false; 8456 } 8457 8458 // if a path is being added that was previously ignored, stop ignoring it 8459 this._ignoredPaths.delete(path); 8460 this._ignoredPaths.delete(path + SLASH_GLOBSTAR); 8461 8462 // reset the cached userIgnored anymatch fn 8463 // to make ignoredPaths changes effective 8464 this._userIgnored = undefined; 8465 8466 return true; 8467 }); 8468 8469 if (this.options.useFsEvents && this._fsEventsHandler) { 8470 if (!this._readyCount) this._readyCount = paths.length; 8471 if (this.options.persistent) this._readyCount += paths.length; 8472 paths.forEach((path) => this._fsEventsHandler._addToFsEvents(path)); 8473 } else { 8474 if (!this._readyCount) this._readyCount = 0; 8475 this._readyCount += paths.length; 8476 Promise.all( 8477 paths.map(async path => { 8478 const res = await this._nodeFsHandler._addToNodeFs(path, !_internal, 0, 0, _origAdd); 8479 if (res) this._emitReady(); 8480 return res; 8481 }) 8482 ).then(results => { 8483 if (this.closed) return; 8484 results.filter(item => item).forEach(item => { 8485 this.add(sysPath.dirname(item), sysPath.basename(_origAdd || item)); 8486 }); 8487 }); 8488 } 8489 8490 return this; 8491 } 8492 8493 /** 8494 * Close watchers or start ignoring events from specified paths. 8495 * @param {Path|Array<Path>} paths_ - string or array of strings, file/directory paths and/or globs 8496 * @returns {FSWatcher} for chaining 8497 */ 8498 unwatch(paths_) { 8499 if (this.closed) return this; 8500 const paths = unifyPaths(paths_); 8501 const {cwd} = this.options; 8502 8503 paths.forEach((path) => { 8504 // convert to absolute path unless relative path already matches 8505 if (!sysPath.isAbsolute(path) && !this._closers.has(path)) { 8506 if (cwd) path = sysPath.join(cwd, path); 8507 path = sysPath.resolve(path); 8508 } 8509 8510 this._closePath(path); 8511 8512 this._ignoredPaths.add(path); 8513 if (this._watched.has(path)) { 8514 this._ignoredPaths.add(path + SLASH_GLOBSTAR); 8515 } 8516 8517 // reset the cached userIgnored anymatch fn 8518 // to make ignoredPaths changes effective 8519 this._userIgnored = undefined; 8520 }); 8521 8522 return this; 8523 } 8524 8525 /** 8526 * Close watchers and remove all listeners from watched paths. 8527 * @returns {Promise<void>}. 8528 */ 8529 close() { 8530 if (this.closed) return this._closePromise; 8531 this.closed = true; 8532 8533 // Memory management. 8534 this.removeAllListeners(); 8535 const closers = []; 8536 this._closers.forEach(closerList => closerList.forEach(closer => { 8537 const promise = closer(); 8538 if (promise instanceof Promise) closers.push(promise); 8539 })); 8540 this._streams.forEach(stream => stream.destroy()); 8541 this._userIgnored = undefined; 8542 this._readyCount = 0; 8543 this._readyEmitted = false; 8544 this._watched.forEach(dirent => dirent.dispose()); 8545 ['closers', 'watched', 'streams', 'symlinkPaths', 'throttled'].forEach(key => { 8546 this[`_${key}`].clear(); 8547 }); 8548 8549 this._closePromise = closers.length ? Promise.all(closers).then(() => undefined) : Promise.resolve(); 8550 return this._closePromise; 8551 } 8552 8553 /** 8554 * Expose list of watched paths 8555 * @returns {Object} for chaining 8556 */ 8557 getWatched() { 8558 const watchList = {}; 8559 this._watched.forEach((entry, dir) => { 8560 const key = this.options.cwd ? sysPath.relative(this.options.cwd, dir) : dir; 8561 watchList[key || ONE_DOT] = entry.getChildren().sort(); 8562 }); 8563 return watchList; 8564 } 8565 8566 emitWithAll(event, args) { 8567 this.emit(...args); 8568 if (event !== EV_ERROR) this.emit(EV_ALL, ...args); 8569 } 8570 8571 // Common helpers 8572 // -------------- 8573 8574 /** 8575 * Normalize and emit events. 8576 * Calling _emit DOES NOT MEAN emit() would be called! 8577 * @param {EventName} event Type of event 8578 * @param {Path} path File or directory path 8579 * @param {*=} val1 arguments to be passed with event 8580 * @param {*=} val2 8581 * @param {*=} val3 8582 * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag 8583 */ 8584 async _emit(event, path, val1, val2, val3) { 8585 if (this.closed) return; 8586 8587 const opts = this.options; 8588 if (isWindows) path = sysPath.normalize(path); 8589 if (opts.cwd) path = sysPath.relative(opts.cwd, path); 8590 /** @type Array<any> */ 8591 const args = [event, path]; 8592 if (val3 !== undefined) args.push(val1, val2, val3); 8593 else if (val2 !== undefined) args.push(val1, val2); 8594 else if (val1 !== undefined) args.push(val1); 8595 8596 const awf = opts.awaitWriteFinish; 8597 let pw; 8598 if (awf && (pw = this._pendingWrites.get(path))) { 8599 pw.lastChange = new Date(); 8600 return this; 8601 } 8602 8603 if (opts.atomic) { 8604 if (event === EV_UNLINK) { 8605 this._pendingUnlinks.set(path, args); 8606 setTimeout(() => { 8607 this._pendingUnlinks.forEach((entry, path) => { 8608 this.emit(...entry); 8609 this.emit(EV_ALL, ...entry); 8610 this._pendingUnlinks.delete(path); 8611 }); 8612 }, typeof opts.atomic === 'number' ? opts.atomic : 100); 8613 return this; 8614 } 8615 if (event === EV_ADD && this._pendingUnlinks.has(path)) { 8616 event = args[0] = EV_CHANGE; 8617 this._pendingUnlinks.delete(path); 8618 } 8619 } 8620 8621 if (awf && (event === EV_ADD || event === EV_CHANGE) && this._readyEmitted) { 8622 const awfEmit = (err, stats) => { 8623 if (err) { 8624 event = args[0] = EV_ERROR; 8625 args[1] = err; 8626 this.emitWithAll(event, args); 8627 } else if (stats) { 8628 // if stats doesn't exist the file must have been deleted 8629 if (args.length > 2) { 8630 args[2] = stats; 8631 } else { 8632 args.push(stats); 8633 } 8634 this.emitWithAll(event, args); 8635 } 8636 }; 8637 8638 this._awaitWriteFinish(path, awf.stabilityThreshold, event, awfEmit); 8639 return this; 8640 } 8641 8642 if (event === EV_CHANGE) { 8643 const isThrottled = !this._throttle(EV_CHANGE, path, 50); 8644 if (isThrottled) return this; 8645 } 8646 8647 if (opts.alwaysStat && val1 === undefined && 8648 (event === EV_ADD || event === EV_ADD_DIR || event === EV_CHANGE) 8649 ) { 8650 const fullPath = opts.cwd ? sysPath.join(opts.cwd, path) : path; 8651 let stats; 8652 try { 8653 stats = await stat(fullPath); 8654 } catch (err) {} 8655 // Suppress event when fs_stat fails, to avoid sending undefined 'stat' 8656 if (!stats || this.closed) return; 8657 args.push(stats); 8658 } 8659 this.emitWithAll(event, args); 8660 8661 return this; 8662 } 8663 8664 /** 8665 * Common handler for errors 8666 * @param {Error} error 8667 * @returns {Error|Boolean} The error if defined, otherwise the value of the FSWatcher instance's `closed` flag 8668 */ 8669 _handleError(error) { 8670 const code = error && error.code; 8671 if (error && code !== 'ENOENT' && code !== 'ENOTDIR' && 8672 (!this.options.ignorePermissionErrors || (code !== 'EPERM' && code !== 'EACCES')) 8673 ) { 8674 this.emit(EV_ERROR, error); 8675 } 8676 return error || this.closed; 8677 } 8678 8679 /** 8680 * Helper utility for throttling 8681 * @param {ThrottleType} actionType type being throttled 8682 * @param {Path} path being acted upon 8683 * @param {Number} timeout duration of time to suppress duplicate actions 8684 * @returns {Object|false} tracking object or false if action should be suppressed 8685 */ 8686 _throttle(actionType, path, timeout) { 8687 if (!this._throttled.has(actionType)) { 8688 this._throttled.set(actionType, new Map()); 8689 } 8690 8691 /** @type {Map<Path, Object>} */ 8692 const action = this._throttled.get(actionType); 8693 /** @type {Object} */ 8694 const actionPath = action.get(path); 8695 8696 if (actionPath) { 8697 actionPath.count++; 8698 return false; 8699 } 8700 8701 let timeoutObject; 8702 const clear = () => { 8703 const item = action.get(path); 8704 const count = item ? item.count : 0; 8705 action.delete(path); 8706 clearTimeout(timeoutObject); 8707 if (item) clearTimeout(item.timeoutObject); 8708 return count; 8709 }; 8710 timeoutObject = setTimeout(clear, timeout); 8711 const thr = {timeoutObject, clear, count: 0}; 8712 action.set(path, thr); 8713 return thr; 8714 } 8715 8716 _incrReadyCount() { 8717 return this._readyCount++; 8718 } 8719 8720 /** 8721 * Awaits write operation to finish. 8722 * Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback. 8723 * @param {Path} path being acted upon 8724 * @param {Number} threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished 8725 * @param {EventName} event 8726 * @param {Function} awfEmit Callback to be called when ready for event to be emitted. 8727 */ 8728 _awaitWriteFinish(path, threshold, event, awfEmit) { 8729 let timeoutHandler; 8730 8731 let fullPath = path; 8732 if (this.options.cwd && !sysPath.isAbsolute(path)) { 8733 fullPath = sysPath.join(this.options.cwd, path); 8734 } 8735 8736 const now = new Date(); 8737 8738 const awaitWriteFinish = (prevStat) => { 8739 fs.stat(fullPath, (err, curStat) => { 8740 if (err || !this._pendingWrites.has(path)) { 8741 if (err && err.code !== 'ENOENT') awfEmit(err); 8742 return; 8743 } 8744 8745 const now = Number(new Date()); 8746 8747 if (prevStat && curStat.size !== prevStat.size) { 8748 this._pendingWrites.get(path).lastChange = now; 8749 } 8750 const pw = this._pendingWrites.get(path); 8751 const df = now - pw.lastChange; 8752 8753 if (df >= threshold) { 8754 this._pendingWrites.delete(path); 8755 awfEmit(undefined, curStat); 8756 } else { 8757 timeoutHandler = setTimeout( 8758 awaitWriteFinish, 8759 this.options.awaitWriteFinish.pollInterval, 8760 curStat 8761 ); 8762 } 8763 }); 8764 }; 8765 8766 if (!this._pendingWrites.has(path)) { 8767 this._pendingWrites.set(path, { 8768 lastChange: now, 8769 cancelWait: () => { 8770 this._pendingWrites.delete(path); 8771 clearTimeout(timeoutHandler); 8772 return event; 8773 } 8774 }); 8775 timeoutHandler = setTimeout( 8776 awaitWriteFinish, 8777 this.options.awaitWriteFinish.pollInterval 8778 ); 8779 } 8780 } 8781 8782 _getGlobIgnored() { 8783 return [...this._ignoredPaths.values()]; 8784 } 8785 8786 /** 8787 * Determines whether user has asked to ignore this path. 8788 * @param {Path} path filepath or dir 8789 * @param {fs.Stats=} stats result of fs.stat 8790 * @returns {Boolean} 8791 */ 8792 _isIgnored(path, stats) { 8793 if (this.options.atomic && DOT_RE.test(path)) return true; 8794 if (!this._userIgnored) { 8795 const {cwd} = this.options; 8796 const ign = this.options.ignored; 8797 8798 const ignored = ign && ign.map(normalizeIgnored(cwd)); 8799 const paths = arrify(ignored) 8800 .filter((path) => typeof path === STRING_TYPE && !isGlob(path)) 8801 .map((path) => path + SLASH_GLOBSTAR); 8802 const list = this._getGlobIgnored().map(normalizeIgnored(cwd)).concat(ignored, paths); 8803 this._userIgnored = anymatch(list, undefined, ANYMATCH_OPTS); 8804 } 8805 8806 return this._userIgnored([path, stats]); 8807 } 8808 8809 _isntIgnored(path, stat) { 8810 return !this._isIgnored(path, stat); 8811 } 8812 8813 /** 8814 * Provides a set of common helpers and properties relating to symlink and glob handling. 8815 * @param {Path} path file, directory, or glob pattern being watched 8816 * @param {Number=} depth at any depth > 0, this isn't a glob 8817 * @returns {WatchHelper} object containing helpers for this path 8818 */ 8819 _getWatchHelpers(path, depth) { 8820 const watchPath = depth || this.options.disableGlobbing || !isGlob(path) ? path : globParent(path); 8821 const follow = this.options.followSymlinks; 8822 8823 return new WatchHelper(path, watchPath, follow, this); 8824 } 8825 8826 // Directory helpers 8827 // ----------------- 8828 8829 /** 8830 * Provides directory tracking objects 8831 * @param {String} directory path of the directory 8832 * @returns {DirEntry} the directory's tracking object 8833 */ 8834 _getWatchedDir(directory) { 8835 if (!this._boundRemove) this._boundRemove = this._remove.bind(this); 8836 const dir = sysPath.resolve(directory); 8837 if (!this._watched.has(dir)) this._watched.set(dir, new DirEntry(dir, this._boundRemove)); 8838 return this._watched.get(dir); 8839 } 8840 8841 // File helpers 8842 // ------------ 8843 8844 /** 8845 * Check for read permissions. 8846 * Based on this answer on SO: https://stackoverflow.com/a/11781404/1358405 8847 * @param {fs.Stats} stats - object, result of fs_stat 8848 * @returns {Boolean} indicates whether the file can be read 8849 */ 8850 _hasReadPermissions(stats) { 8851 if (this.options.ignorePermissionErrors) return true; 8852 8853 // stats.mode may be bigint 8854 const md = stats && Number.parseInt(stats.mode, 10); 8855 const st = md & 0o777; 8856 const it = Number.parseInt(st.toString(8)[0], 10); 8857 return Boolean(4 & it); 8858 } 8859 8860 /** 8861 * Handles emitting unlink events for 8862 * files and directories, and via recursion, for 8863 * files and directories within directories that are unlinked 8864 * @param {String} directory within which the following item is located 8865 * @param {String} item base path of item/directory 8866 * @returns {void} 8867 */ 8868 _remove(directory, item, isDirectory) { 8869 // if what is being deleted is a directory, get that directory's paths 8870 // for recursive deleting and cleaning of watched object 8871 // if it is not a directory, nestedDirectoryChildren will be empty array 8872 const path = sysPath.join(directory, item); 8873 const fullPath = sysPath.resolve(path); 8874 isDirectory = isDirectory != null 8875 ? isDirectory 8876 : this._watched.has(path) || this._watched.has(fullPath); 8877 8878 // prevent duplicate handling in case of arriving here nearly simultaneously 8879 // via multiple paths (such as _handleFile and _handleDir) 8880 if (!this._throttle('remove', path, 100)) return; 8881 8882 // if the only watched file is removed, watch for its return 8883 if (!isDirectory && !this.options.useFsEvents && this._watched.size === 1) { 8884 this.add(directory, item, true); 8885 } 8886 8887 // This will create a new entry in the watched object in either case 8888 // so we got to do the directory check beforehand 8889 const wp = this._getWatchedDir(path); 8890 const nestedDirectoryChildren = wp.getChildren(); 8891 8892 // Recursively remove children directories / files. 8893 nestedDirectoryChildren.forEach(nested => this._remove(path, nested)); 8894 8895 // Check if item was on the watched list and remove it 8896 const parent = this._getWatchedDir(directory); 8897 const wasTracked = parent.has(item); 8898 parent.remove(item); 8899 8900 // Fixes issue #1042 -> Relative paths were detected and added as symlinks 8901 // (https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L612), 8902 // but never removed from the map in case the path was deleted. 8903 // This leads to an incorrect state if the path was recreated: 8904 // https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L553 8905 if (this._symlinkPaths.has(fullPath)) { 8906 this._symlinkPaths.delete(fullPath); 8907 } 8908 8909 // If we wait for this file to be fully written, cancel the wait. 8910 let relPath = path; 8911 if (this.options.cwd) relPath = sysPath.relative(this.options.cwd, path); 8912 if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) { 8913 const event = this._pendingWrites.get(relPath).cancelWait(); 8914 if (event === EV_ADD) return; 8915 } 8916 8917 // The Entry will either be a directory that just got removed 8918 // or a bogus entry to a file, in either case we have to remove it 8919 this._watched.delete(path); 8920 this._watched.delete(fullPath); 8921 const eventName = isDirectory ? EV_UNLINK_DIR : EV_UNLINK; 8922 if (wasTracked && !this._isIgnored(path)) this._emit(eventName, path); 8923 8924 // Avoid conflicts if we later create another file with the same name 8925 if (!this.options.useFsEvents) { 8926 this._closePath(path); 8927 } 8928 } 8929 8930 /** 8931 * Closes all watchers for a path 8932 * @param {Path} path 8933 */ 8934 _closePath(path) { 8935 this._closeFile(path); 8936 const dir = sysPath.dirname(path); 8937 this._getWatchedDir(dir).remove(sysPath.basename(path)); 8938 } 8939 8940 /** 8941 * Closes only file-specific watchers 8942 * @param {Path} path 8943 */ 8944 _closeFile(path) { 8945 const closers = this._closers.get(path); 8946 if (!closers) return; 8947 closers.forEach(closer => closer()); 8948 this._closers.delete(path); 8949 } 8950 8951 /** 8952 * 8953 * @param {Path} path 8954 * @param {Function} closer 8955 */ 8956 _addPathCloser(path, closer) { 8957 if (!closer) return; 8958 let list = this._closers.get(path); 8959 if (!list) { 8960 list = []; 8961 this._closers.set(path, list); 8962 } 8963 list.push(closer); 8964 } 8965 8966 _readdirp(root, opts) { 8967 if (this.closed) return; 8968 const options = {type: EV_ALL, alwaysStat: true, lstat: true, ...opts}; 8969 let stream = readdirp(root, options); 8970 this._streams.add(stream); 8971 stream.once(STR_CLOSE, () => { 8972 stream = undefined; 8973 }); 8974 stream.once(STR_END, () => { 8975 if (stream) { 8976 this._streams.delete(stream); 8977 stream = undefined; 8978 } 8979 }); 8980 return stream; 8981 } 8982 8983 } 8984 8985 // Export FSWatcher class 8986 chokidar$1.FSWatcher = FSWatcher; 8987 8988 /** 8989 * Instantiates watcher with paths to be tracked. 8990 * @param {String|Array<String>} paths file/directory paths and/or globs 8991 * @param {Object=} options chokidar opts 8992 * @returns an instance of FSWatcher for chaining. 8993 */ 8994 const watch = (paths, options) => { 8995 const watcher = new FSWatcher(options); 8996 watcher.add(paths); 8997 return watcher; 8998 }; 8999 9000 chokidar$1.watch = watch; 9001 return chokidar$1; 2839 9002 } 2840 9003 2841 /** 2842 * Handle symlinks encountered while reading a dir. 2843 * @param {Object} entry returned by readdirp 2844 * @param {String} directory path of dir being read 2845 * @param {String} path of this item 2846 * @param {String} item basename of this item 2847 * @returns {Promise<Boolean>} true if no more processing is needed for this entry. 2848 */ 2849 async _handleSymlink(entry, directory, path, item) { 2850 if (this.fsw.closed) { 2851 return; 2852 } 2853 const full = entry.fullPath; 2854 const dir = this.fsw._getWatchedDir(directory); 2855 2856 if (!this.fsw.options.followSymlinks) { 2857 // watch symlink directly (don't follow) and detect changes 2858 this.fsw._incrReadyCount(); 2859 2860 let linkPath; 2861 try { 2862 linkPath = await fsrealpath(path); 2863 } catch (e) { 2864 this.fsw._emitReady(); 2865 return true; 2866 } 2867 2868 if (this.fsw.closed) return; 2869 if (dir.has(item)) { 2870 if (this.fsw._symlinkPaths.get(full) !== linkPath) { 2871 this.fsw._symlinkPaths.set(full, linkPath); 2872 this.fsw._emit(EV_CHANGE$2, path, entry.stats); 2873 } 2874 } else { 2875 dir.add(item); 2876 this.fsw._symlinkPaths.set(full, linkPath); 2877 this.fsw._emit(EV_ADD$2, path, entry.stats); 2878 } 2879 this.fsw._emitReady(); 2880 return true; 2881 } 2882 2883 // don't follow the same symlink more than once 2884 if (this.fsw._symlinkPaths.has(full)) { 2885 return true; 2886 } 2887 2888 this.fsw._symlinkPaths.set(full, true); 2889 } 2890 2891 _handleRead(directory, initialAdd, wh, target, dir, depth, throttler) { 2892 // Normalize the directory name on Windows 2893 directory = sysPath$2.join(directory, EMPTY_STR$1); 2894 2895 if (!wh.hasGlob) { 2896 throttler = this.fsw._throttle('readdir', directory, 1000); 2897 if (!throttler) return; 2898 } 2899 2900 const previous = this.fsw._getWatchedDir(wh.path); 2901 const current = new Set(); 2902 2903 let stream = this.fsw._readdirp(directory, { 2904 fileFilter: entry => wh.filterPath(entry), 2905 directoryFilter: entry => wh.filterDir(entry), 2906 depth: 0 2907 }).on(STR_DATA$1, async (entry) => { 2908 if (this.fsw.closed) { 2909 stream = undefined; 2910 return; 2911 } 2912 const item = entry.path; 2913 let path = sysPath$2.join(directory, item); 2914 current.add(item); 2915 2916 if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path, item)) { 2917 return; 2918 } 2919 2920 if (this.fsw.closed) { 2921 stream = undefined; 2922 return; 2923 } 2924 // Files that present in current directory snapshot 2925 // but absent in previous are added to watch list and 2926 // emit `add` event. 2927 if (item === target || !target && !previous.has(item)) { 2928 this.fsw._incrReadyCount(); 2929 2930 // ensure relativeness of path is preserved in case of watcher reuse 2931 path = sysPath$2.join(dir, sysPath$2.relative(dir, path)); 2932 2933 this._addToNodeFs(path, initialAdd, wh, depth + 1); 2934 } 2935 }).on(EV_ERROR$2, this._boundHandleError); 2936 2937 return new Promise(resolve => 2938 stream.once(STR_END$2, () => { 2939 if (this.fsw.closed) { 2940 stream = undefined; 2941 return; 2942 } 2943 const wasThrottled = throttler ? throttler.clear() : false; 2944 2945 resolve(); 2946 2947 // Files that absent in current directory snapshot 2948 // but present in previous emit `remove` event 2949 // and are removed from @watched[directory]. 2950 previous.getChildren().filter((item) => { 2951 return item !== directory && 2952 !current.has(item) && 2953 // in case of intersecting globs; 2954 // a path may have been filtered out of this readdir, but 2955 // shouldn't be removed because it matches a different glob 2956 (!wh.hasGlob || wh.filterPath({ 2957 fullPath: sysPath$2.resolve(directory, item) 2958 })); 2959 }).forEach((item) => { 2960 this.fsw._remove(directory, item); 2961 }); 2962 2963 stream = undefined; 2964 2965 // one more time for any missed in case changes came in extremely quickly 2966 if (wasThrottled) this._handleRead(directory, false, wh, target, dir, depth, throttler); 2967 }) 2968 ); 2969 } 2970 2971 /** 2972 * Read directory to add / remove files from `@watched` list and re-read it on change. 2973 * @param {String} dir fs path 2974 * @param {fs.Stats} stats 2975 * @param {Boolean} initialAdd 2976 * @param {Number} depth relative to user-supplied path 2977 * @param {String} target child path targeted for watch 2978 * @param {Object} wh Common watch helpers for this path 2979 * @param {String} realpath 2980 * @returns {Promise<Function>} closer for the watcher instance. 2981 */ 2982 async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath) { 2983 const parentDir = this.fsw._getWatchedDir(sysPath$2.dirname(dir)); 2984 const tracked = parentDir.has(sysPath$2.basename(dir)); 2985 if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) { 2986 if (!wh.hasGlob || wh.globFilter(dir)) this.fsw._emit(EV_ADD_DIR$2, dir, stats); 2987 } 2988 2989 // ensure dir is tracked (harmless if redundant) 2990 parentDir.add(sysPath$2.basename(dir)); 2991 this.fsw._getWatchedDir(dir); 2992 let throttler; 2993 let closer; 2994 2995 const oDepth = this.fsw.options.depth; 2996 if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath)) { 2997 if (!target) { 2998 await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler); 2999 if (this.fsw.closed) return; 3000 } 3001 3002 closer = this._watchWithNodeFs(dir, (dirPath, stats) => { 3003 // if current directory is removed, do nothing 3004 if (stats && stats.mtimeMs === 0) return; 3005 3006 this._handleRead(dirPath, false, wh, target, dir, depth, throttler); 3007 }); 3008 } 3009 return closer; 3010 } 3011 3012 /** 3013 * Handle added file, directory, or glob pattern. 3014 * Delegates call to _handleFile / _handleDir after checks. 3015 * @param {String} path to file or ir 3016 * @param {Boolean} initialAdd was the file added at watch instantiation? 3017 * @param {Object} priorWh depth relative to user-supplied path 3018 * @param {Number} depth Child path actually targeted for watch 3019 * @param {String=} target Child path actually targeted for watch 3020 * @returns {Promise} 3021 */ 3022 async _addToNodeFs(path, initialAdd, priorWh, depth, target) { 3023 const ready = this.fsw._emitReady; 3024 if (this.fsw._isIgnored(path) || this.fsw.closed) { 3025 ready(); 3026 return false; 3027 } 3028 3029 const wh = this.fsw._getWatchHelpers(path, depth); 3030 if (!wh.hasGlob && priorWh) { 3031 wh.hasGlob = priorWh.hasGlob; 3032 wh.globFilter = priorWh.globFilter; 3033 wh.filterPath = entry => priorWh.filterPath(entry); 3034 wh.filterDir = entry => priorWh.filterDir(entry); 3035 } 3036 3037 // evaluate what is at the path we're being asked to watch 3038 try { 3039 const stats = await statMethods$1[wh.statMethod](wh.watchPath); 3040 if (this.fsw.closed) return; 3041 if (this.fsw._isIgnored(wh.watchPath, stats)) { 3042 ready(); 3043 return false; 3044 } 3045 3046 const follow = this.fsw.options.followSymlinks && !path.includes(STAR) && !path.includes(BRACE_START$1); 3047 let closer; 3048 if (stats.isDirectory()) { 3049 const absPath = sysPath$2.resolve(path); 3050 const targetPath = follow ? await fsrealpath(path) : path; 3051 if (this.fsw.closed) return; 3052 closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath); 3053 if (this.fsw.closed) return; 3054 // preserve this symlink's target path 3055 if (absPath !== targetPath && targetPath !== undefined) { 3056 this.fsw._symlinkPaths.set(absPath, targetPath); 3057 } 3058 } else if (stats.isSymbolicLink()) { 3059 const targetPath = follow ? await fsrealpath(path) : path; 3060 if (this.fsw.closed) return; 3061 const parent = sysPath$2.dirname(wh.watchPath); 3062 this.fsw._getWatchedDir(parent).add(wh.watchPath); 3063 this.fsw._emit(EV_ADD$2, wh.watchPath, stats); 3064 closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath); 3065 if (this.fsw.closed) return; 3066 3067 // preserve this symlink's target path 3068 if (targetPath !== undefined) { 3069 this.fsw._symlinkPaths.set(sysPath$2.resolve(path), targetPath); 3070 } 3071 } else { 3072 closer = this._handleFile(wh.watchPath, stats, initialAdd); 3073 } 3074 ready(); 3075 3076 this.fsw._addPathCloser(path, closer); 3077 return false; 3078 3079 } catch (error) { 3080 if (this.fsw._handleError(error)) { 3081 ready(); 3082 return path; 3083 } 3084 } 3085 } 3086 3087 }; 3088 3089 var nodefsHandler = NodeFsHandler$1; 3090 3091 var fseventsHandler = {exports: {}}; 3092 3093 const require$$3 = /*@__PURE__*/getAugmentedNamespace(fseventsImporter); 3094 3095 const fs$1 = require$$0$1; 3096 const sysPath$1 = require$$0$2; 3097 const { promisify: promisify$1 } = require$$2; 3098 3099 let fsevents; 3100 try { 3101 fsevents = require$$3.getFsEvents(); 3102 } catch (error) { 3103 if (process.env.CHOKIDAR_PRINT_FSEVENTS_REQUIRE_ERROR) console.error(error); 3104 } 3105 3106 if (fsevents) { 3107 // TODO: real check 3108 const mtch = process.version.match(/v(\d+)\.(\d+)/); 3109 if (mtch && mtch[1] && mtch[2]) { 3110 const maj = Number.parseInt(mtch[1], 10); 3111 const min = Number.parseInt(mtch[2], 10); 3112 if (maj === 8 && min < 16) { 3113 fsevents = undefined; 3114 } 3115 } 3116 } 3117 3118 const { 3119 EV_ADD: EV_ADD$1, 3120 EV_CHANGE: EV_CHANGE$1, 3121 EV_ADD_DIR: EV_ADD_DIR$1, 3122 EV_UNLINK: EV_UNLINK$1, 3123 EV_ERROR: EV_ERROR$1, 3124 STR_DATA, 3125 STR_END: STR_END$1, 3126 FSEVENT_CREATED, 3127 FSEVENT_MODIFIED, 3128 FSEVENT_DELETED, 3129 FSEVENT_MOVED, 3130 // FSEVENT_CLONED, 3131 FSEVENT_UNKNOWN, 3132 FSEVENT_FLAG_MUST_SCAN_SUBDIRS, 3133 FSEVENT_TYPE_FILE, 3134 FSEVENT_TYPE_DIRECTORY, 3135 FSEVENT_TYPE_SYMLINK, 3136 3137 ROOT_GLOBSTAR, 3138 DIR_SUFFIX, 3139 DOT_SLASH, 3140 FUNCTION_TYPE: FUNCTION_TYPE$1, 3141 EMPTY_FN: EMPTY_FN$1, 3142 IDENTITY_FN 3143 } = constants; 3144 3145 const Depth = (value) => isNaN(value) ? {} : {depth: value}; 3146 3147 const stat$1 = promisify$1(fs$1.stat); 3148 const lstat = promisify$1(fs$1.lstat); 3149 const realpath = promisify$1(fs$1.realpath); 3150 3151 const statMethods = { stat: stat$1, lstat }; 3152 3153 /** 3154 * @typedef {String} Path 3155 */ 3156 3157 /** 3158 * @typedef {Object} FsEventsWatchContainer 3159 * @property {Set<Function>} listeners 3160 * @property {Function} rawEmitter 3161 * @property {{stop: Function}} watcher 3162 */ 3163 3164 // fsevents instance helper functions 3165 /** 3166 * Object to hold per-process fsevents instances (may be shared across chokidar FSWatcher instances) 3167 * @type {Map<Path,FsEventsWatchContainer>} 3168 */ 3169 const FSEventsWatchers = new Map(); 3170 3171 // Threshold of duplicate path prefixes at which to start 3172 // consolidating going forward 3173 const consolidateThreshhold = 10; 3174 3175 const wrongEventFlags = new Set([ 3176 69888, 70400, 71424, 72704, 73472, 131328, 131840, 262912 3177 ]); 3178 3179 /** 3180 * Instantiates the fsevents interface 3181 * @param {Path} path path to be watched 3182 * @param {Function} callback called when fsevents is bound and ready 3183 * @returns {{stop: Function}} new fsevents instance 3184 */ 3185 const createFSEventsInstance = (path, callback) => { 3186 const stop = fsevents.watch(path, callback); 3187 return {stop}; 3188 }; 3189 3190 /** 3191 * Instantiates the fsevents interface or binds listeners to an existing one covering 3192 * the same file tree. 3193 * @param {Path} path - to be watched 3194 * @param {Path} realPath - real path for symlinks 3195 * @param {Function} listener - called when fsevents emits events 3196 * @param {Function} rawEmitter - passes data to listeners of the 'raw' event 3197 * @returns {Function} closer 3198 */ 3199 function setFSEventsListener(path, realPath, listener, rawEmitter) { 3200 let watchPath = sysPath$1.extname(realPath) ? sysPath$1.dirname(realPath) : realPath; 3201 3202 const parentPath = sysPath$1.dirname(watchPath); 3203 let cont = FSEventsWatchers.get(watchPath); 3204 3205 // If we've accumulated a substantial number of paths that 3206 // could have been consolidated by watching one directory 3207 // above the current one, create a watcher on the parent 3208 // path instead, so that we do consolidate going forward. 3209 if (couldConsolidate(parentPath)) { 3210 watchPath = parentPath; 3211 } 3212 3213 const resolvedPath = sysPath$1.resolve(path); 3214 const hasSymlink = resolvedPath !== realPath; 3215 3216 const filteredListener = (fullPath, flags, info) => { 3217 if (hasSymlink) fullPath = fullPath.replace(realPath, resolvedPath); 3218 if ( 3219 fullPath === resolvedPath || 3220 !fullPath.indexOf(resolvedPath + sysPath$1.sep) 3221 ) listener(fullPath, flags, info); 3222 }; 3223 3224 // check if there is already a watcher on a parent path 3225 // modifies `watchPath` to the parent path when it finds a match 3226 let watchedParent = false; 3227 for (const watchedPath of FSEventsWatchers.keys()) { 3228 if (realPath.indexOf(sysPath$1.resolve(watchedPath) + sysPath$1.sep) === 0) { 3229 watchPath = watchedPath; 3230 cont = FSEventsWatchers.get(watchPath); 3231 watchedParent = true; 3232 break; 3233 } 3234 } 3235 3236 if (cont || watchedParent) { 3237 cont.listeners.add(filteredListener); 3238 } else { 3239 cont = { 3240 listeners: new Set([filteredListener]), 3241 rawEmitter, 3242 watcher: createFSEventsInstance(watchPath, (fullPath, flags) => { 3243 if (!cont.listeners.size) return; 3244 if (flags & FSEVENT_FLAG_MUST_SCAN_SUBDIRS) return; 3245 const info = fsevents.getInfo(fullPath, flags); 3246 cont.listeners.forEach(list => { 3247 list(fullPath, flags, info); 3248 }); 3249 3250 cont.rawEmitter(info.event, fullPath, info); 3251 }) 3252 }; 3253 FSEventsWatchers.set(watchPath, cont); 3254 } 3255 3256 // removes this instance's listeners and closes the underlying fsevents 3257 // instance if there are no more listeners left 3258 return () => { 3259 const lst = cont.listeners; 3260 3261 lst.delete(filteredListener); 3262 if (!lst.size) { 3263 FSEventsWatchers.delete(watchPath); 3264 if (cont.watcher) return cont.watcher.stop().then(() => { 3265 cont.rawEmitter = cont.watcher = undefined; 3266 Object.freeze(cont); 3267 }); 3268 } 3269 }; 3270 } 3271 3272 // Decide whether or not we should start a new higher-level 3273 // parent watcher 3274 const couldConsolidate = (path) => { 3275 let count = 0; 3276 for (const watchPath of FSEventsWatchers.keys()) { 3277 if (watchPath.indexOf(path) === 0) { 3278 count++; 3279 if (count >= consolidateThreshhold) { 3280 return true; 3281 } 3282 } 3283 } 3284 3285 return false; 3286 }; 3287 3288 // returns boolean indicating whether fsevents can be used 3289 const canUse = () => fsevents && FSEventsWatchers.size < 128; 3290 3291 // determines subdirectory traversal levels from root to path 3292 const calcDepth = (path, root) => { 3293 let i = 0; 3294 while (!path.indexOf(root) && (path = sysPath$1.dirname(path)) !== root) i++; 3295 return i; 3296 }; 3297 3298 // returns boolean indicating whether the fsevents' event info has the same type 3299 // as the one returned by fs.stat 3300 const sameTypes = (info, stats) => ( 3301 info.type === FSEVENT_TYPE_DIRECTORY && stats.isDirectory() || 3302 info.type === FSEVENT_TYPE_SYMLINK && stats.isSymbolicLink() || 3303 info.type === FSEVENT_TYPE_FILE && stats.isFile() 3304 ); 3305 3306 /** 3307 * @mixin 3308 */ 3309 let FsEventsHandler$1 = class FsEventsHandler { 3310 3311 /** 3312 * @param {import('../index').FSWatcher} fsw 3313 */ 3314 constructor(fsw) { 3315 this.fsw = fsw; 3316 } 3317 checkIgnored(path, stats) { 3318 const ipaths = this.fsw._ignoredPaths; 3319 if (this.fsw._isIgnored(path, stats)) { 3320 ipaths.add(path); 3321 if (stats && stats.isDirectory()) { 3322 ipaths.add(path + ROOT_GLOBSTAR); 3323 } 3324 return true; 3325 } 3326 3327 ipaths.delete(path); 3328 ipaths.delete(path + ROOT_GLOBSTAR); 3329 } 3330 3331 addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts) { 3332 const event = watchedDir.has(item) ? EV_CHANGE$1 : EV_ADD$1; 3333 this.handleEvent(event, path, fullPath, realPath, parent, watchedDir, item, info, opts); 3334 } 3335 3336 async checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts) { 3337 try { 3338 const stats = await stat$1(path); 3339 if (this.fsw.closed) return; 3340 if (sameTypes(info, stats)) { 3341 this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts); 3342 } else { 3343 this.handleEvent(EV_UNLINK$1, path, fullPath, realPath, parent, watchedDir, item, info, opts); 3344 } 3345 } catch (error) { 3346 if (error.code === 'EACCES') { 3347 this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts); 3348 } else { 3349 this.handleEvent(EV_UNLINK$1, path, fullPath, realPath, parent, watchedDir, item, info, opts); 3350 } 3351 } 3352 } 3353 3354 handleEvent(event, path, fullPath, realPath, parent, watchedDir, item, info, opts) { 3355 if (this.fsw.closed || this.checkIgnored(path)) return; 3356 3357 if (event === EV_UNLINK$1) { 3358 const isDirectory = info.type === FSEVENT_TYPE_DIRECTORY; 3359 // suppress unlink events on never before seen files 3360 if (isDirectory || watchedDir.has(item)) { 3361 this.fsw._remove(parent, item, isDirectory); 3362 } 3363 } else { 3364 if (event === EV_ADD$1) { 3365 // track new directories 3366 if (info.type === FSEVENT_TYPE_DIRECTORY) this.fsw._getWatchedDir(path); 3367 3368 if (info.type === FSEVENT_TYPE_SYMLINK && opts.followSymlinks) { 3369 // push symlinks back to the top of the stack to get handled 3370 const curDepth = opts.depth === undefined ? 3371 undefined : calcDepth(fullPath, realPath) + 1; 3372 return this._addToFsEvents(path, false, true, curDepth); 3373 } 3374 3375 // track new paths 3376 // (other than symlinks being followed, which will be tracked soon) 3377 this.fsw._getWatchedDir(parent).add(item); 3378 } 3379 /** 3380 * @type {'add'|'addDir'|'unlink'|'unlinkDir'} 3381 */ 3382 const eventName = info.type === FSEVENT_TYPE_DIRECTORY ? event + DIR_SUFFIX : event; 3383 this.fsw._emit(eventName, path); 3384 if (eventName === EV_ADD_DIR$1) this._addToFsEvents(path, false, true); 3385 } 3386 } 3387 3388 /** 3389 * Handle symlinks encountered during directory scan 3390 * @param {String} watchPath - file/dir path to be watched with fsevents 3391 * @param {String} realPath - real path (in case of symlinks) 3392 * @param {Function} transform - path transformer 3393 * @param {Function} globFilter - path filter in case a glob pattern was provided 3394 * @returns {Function} closer for the watcher instance 3395 */ 3396 _watchWithFsEvents(watchPath, realPath, transform, globFilter) { 3397 if (this.fsw.closed || this.fsw._isIgnored(watchPath)) return; 3398 const opts = this.fsw.options; 3399 const watchCallback = async (fullPath, flags, info) => { 3400 if (this.fsw.closed) return; 3401 if ( 3402 opts.depth !== undefined && 3403 calcDepth(fullPath, realPath) > opts.depth 3404 ) return; 3405 const path = transform(sysPath$1.join( 3406 watchPath, sysPath$1.relative(watchPath, fullPath) 3407 )); 3408 if (globFilter && !globFilter(path)) return; 3409 // ensure directories are tracked 3410 const parent = sysPath$1.dirname(path); 3411 const item = sysPath$1.basename(path); 3412 const watchedDir = this.fsw._getWatchedDir( 3413 info.type === FSEVENT_TYPE_DIRECTORY ? path : parent 3414 ); 3415 3416 // correct for wrong events emitted 3417 if (wrongEventFlags.has(flags) || info.event === FSEVENT_UNKNOWN) { 3418 if (typeof opts.ignored === FUNCTION_TYPE$1) { 3419 let stats; 3420 try { 3421 stats = await stat$1(path); 3422 } catch (error) {} 3423 if (this.fsw.closed) return; 3424 if (this.checkIgnored(path, stats)) return; 3425 if (sameTypes(info, stats)) { 3426 this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts); 3427 } else { 3428 this.handleEvent(EV_UNLINK$1, path, fullPath, realPath, parent, watchedDir, item, info, opts); 3429 } 3430 } else { 3431 this.checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts); 3432 } 3433 } else { 3434 switch (info.event) { 3435 case FSEVENT_CREATED: 3436 case FSEVENT_MODIFIED: 3437 return this.addOrChange(path, fullPath, realPath, parent, watchedDir, item, info, opts); 3438 case FSEVENT_DELETED: 3439 case FSEVENT_MOVED: 3440 return this.checkExists(path, fullPath, realPath, parent, watchedDir, item, info, opts); 3441 } 3442 } 3443 }; 3444 3445 const closer = setFSEventsListener( 3446 watchPath, 3447 realPath, 3448 watchCallback, 3449 this.fsw._emitRaw 3450 ); 3451 3452 this.fsw._emitReady(); 3453 return closer; 3454 } 3455 3456 /** 3457 * Handle symlinks encountered during directory scan 3458 * @param {String} linkPath path to symlink 3459 * @param {String} fullPath absolute path to the symlink 3460 * @param {Function} transform pre-existing path transformer 3461 * @param {Number} curDepth level of subdirectories traversed to where symlink is 3462 * @returns {Promise<void>} 3463 */ 3464 async _handleFsEventsSymlink(linkPath, fullPath, transform, curDepth) { 3465 // don't follow the same symlink more than once 3466 if (this.fsw.closed || this.fsw._symlinkPaths.has(fullPath)) return; 3467 3468 this.fsw._symlinkPaths.set(fullPath, true); 3469 this.fsw._incrReadyCount(); 3470 3471 try { 3472 const linkTarget = await realpath(linkPath); 3473 if (this.fsw.closed) return; 3474 if (this.fsw._isIgnored(linkTarget)) { 3475 return this.fsw._emitReady(); 3476 } 3477 3478 this.fsw._incrReadyCount(); 3479 3480 // add the linkTarget for watching with a wrapper for transform 3481 // that causes emitted paths to incorporate the link's path 3482 this._addToFsEvents(linkTarget || linkPath, (path) => { 3483 let aliasedPath = linkPath; 3484 if (linkTarget && linkTarget !== DOT_SLASH) { 3485 aliasedPath = path.replace(linkTarget, linkPath); 3486 } else if (path !== DOT_SLASH) { 3487 aliasedPath = sysPath$1.join(linkPath, path); 3488 } 3489 return transform(aliasedPath); 3490 }, false, curDepth); 3491 } catch(error) { 3492 if (this.fsw._handleError(error)) { 3493 return this.fsw._emitReady(); 3494 } 3495 } 3496 } 3497 3498 /** 3499 * 3500 * @param {Path} newPath 3501 * @param {fs.Stats} stats 3502 */ 3503 emitAdd(newPath, stats, processPath, opts, forceAdd) { 3504 const pp = processPath(newPath); 3505 const isDir = stats.isDirectory(); 3506 const dirObj = this.fsw._getWatchedDir(sysPath$1.dirname(pp)); 3507 const base = sysPath$1.basename(pp); 3508 3509 // ensure empty dirs get tracked 3510 if (isDir) this.fsw._getWatchedDir(pp); 3511 if (dirObj.has(base)) return; 3512 dirObj.add(base); 3513 3514 if (!opts.ignoreInitial || forceAdd === true) { 3515 this.fsw._emit(isDir ? EV_ADD_DIR$1 : EV_ADD$1, pp, stats); 3516 } 3517 } 3518 3519 initWatch(realPath, path, wh, processPath) { 3520 if (this.fsw.closed) return; 3521 const closer = this._watchWithFsEvents( 3522 wh.watchPath, 3523 sysPath$1.resolve(realPath || wh.watchPath), 3524 processPath, 3525 wh.globFilter 3526 ); 3527 this.fsw._addPathCloser(path, closer); 3528 } 3529 3530 /** 3531 * Handle added path with fsevents 3532 * @param {String} path file/dir path or glob pattern 3533 * @param {Function|Boolean=} transform converts working path to what the user expects 3534 * @param {Boolean=} forceAdd ensure add is emitted 3535 * @param {Number=} priorDepth Level of subdirectories already traversed. 3536 * @returns {Promise<void>} 3537 */ 3538 async _addToFsEvents(path, transform, forceAdd, priorDepth) { 3539 if (this.fsw.closed) { 3540 return; 3541 } 3542 const opts = this.fsw.options; 3543 const processPath = typeof transform === FUNCTION_TYPE$1 ? transform : IDENTITY_FN; 3544 3545 const wh = this.fsw._getWatchHelpers(path); 3546 3547 // evaluate what is at the path we're being asked to watch 3548 try { 3549 const stats = await statMethods[wh.statMethod](wh.watchPath); 3550 if (this.fsw.closed) return; 3551 if (this.fsw._isIgnored(wh.watchPath, stats)) { 3552 throw null; 3553 } 3554 if (stats.isDirectory()) { 3555 // emit addDir unless this is a glob parent 3556 if (!wh.globFilter) this.emitAdd(processPath(path), stats, processPath, opts, forceAdd); 3557 3558 // don't recurse further if it would exceed depth setting 3559 if (priorDepth && priorDepth > opts.depth) return; 3560 3561 // scan the contents of the dir 3562 this.fsw._readdirp(wh.watchPath, { 3563 fileFilter: entry => wh.filterPath(entry), 3564 directoryFilter: entry => wh.filterDir(entry), 3565 ...Depth(opts.depth - (priorDepth || 0)) 3566 }).on(STR_DATA, (entry) => { 3567 // need to check filterPath on dirs b/c filterDir is less restrictive 3568 if (this.fsw.closed) { 3569 return; 3570 } 3571 if (entry.stats.isDirectory() && !wh.filterPath(entry)) return; 3572 3573 const joinedPath = sysPath$1.join(wh.watchPath, entry.path); 3574 const {fullPath} = entry; 3575 3576 if (wh.followSymlinks && entry.stats.isSymbolicLink()) { 3577 // preserve the current depth here since it can't be derived from 3578 // real paths past the symlink 3579 const curDepth = opts.depth === undefined ? 3580 undefined : calcDepth(joinedPath, sysPath$1.resolve(wh.watchPath)) + 1; 3581 3582 this._handleFsEventsSymlink(joinedPath, fullPath, processPath, curDepth); 3583 } else { 3584 this.emitAdd(joinedPath, entry.stats, processPath, opts, forceAdd); 3585 } 3586 }).on(EV_ERROR$1, EMPTY_FN$1).on(STR_END$1, () => { 3587 this.fsw._emitReady(); 3588 }); 3589 } else { 3590 this.emitAdd(wh.watchPath, stats, processPath, opts, forceAdd); 3591 this.fsw._emitReady(); 3592 } 3593 } catch (error) { 3594 if (!error || this.fsw._handleError(error)) { 3595 // TODO: Strange thing: "should not choke on an ignored watch path" will be failed without 2 ready calls -__- 3596 this.fsw._emitReady(); 3597 this.fsw._emitReady(); 3598 } 3599 } 3600 3601 if (opts.persistent && forceAdd !== true) { 3602 if (typeof transform === FUNCTION_TYPE$1) { 3603 // realpath has already been resolved 3604 this.initWatch(undefined, path, wh, processPath); 3605 } else { 3606 let realPath; 3607 try { 3608 realPath = await realpath(wh.watchPath); 3609 } catch (e) {} 3610 this.initWatch(realPath, path, wh, processPath); 3611 } 3612 } 3613 } 3614 3615 }; 3616 3617 fseventsHandler.exports = FsEventsHandler$1; 3618 fseventsHandler.exports.canUse = canUse; 3619 3620 var fseventsHandlerExports = fseventsHandler.exports; 3621 3622 const { EventEmitter } = require$$0$3; 3623 const fs = require$$0$1; 3624 const sysPath = require$$0$2; 3625 const { promisify } = require$$2; 3626 const readdirp = readdirp_1; 3627 const anymatch = anymatchExports.default; 3628 const globParent = globParent$1; 3629 const isGlob = isGlob$2; 3630 const braces = braces_1; 3631 const normalizePath = normalizePath$2; 3632 3633 const NodeFsHandler = nodefsHandler; 3634 const FsEventsHandler = fseventsHandlerExports; 3635 const { 3636 EV_ALL, 3637 EV_READY, 3638 EV_ADD, 3639 EV_CHANGE, 3640 EV_UNLINK, 3641 EV_ADD_DIR, 3642 EV_UNLINK_DIR, 3643 EV_RAW, 3644 EV_ERROR, 3645 3646 STR_CLOSE, 3647 STR_END, 3648 3649 BACK_SLASH_RE, 3650 DOUBLE_SLASH_RE, 3651 SLASH_OR_BACK_SLASH_RE, 3652 DOT_RE, 3653 REPLACER_RE, 3654 3655 SLASH, 3656 SLASH_SLASH, 3657 BRACE_START, 3658 BANG, 3659 ONE_DOT, 3660 TWO_DOTS, 3661 GLOBSTAR, 3662 SLASH_GLOBSTAR, 3663 ANYMATCH_OPTS, 3664 STRING_TYPE, 3665 FUNCTION_TYPE, 3666 EMPTY_STR, 3667 EMPTY_FN, 3668 3669 isWindows, 3670 isMacos, 3671 isIBMi 3672 } = constants; 3673 3674 const stat = promisify(fs.stat); 3675 const readdir = promisify(fs.readdir); 3676 3677 /** 3678 * @typedef {String} Path 3679 * @typedef {'all'|'add'|'addDir'|'change'|'unlink'|'unlinkDir'|'raw'|'error'|'ready'} EventName 3680 * @typedef {'readdir'|'watch'|'add'|'remove'|'change'} ThrottleType 3681 */ 3682 3683 /** 3684 * 3685 * @typedef {Object} WatchHelpers 3686 * @property {Boolean} followSymlinks 3687 * @property {'stat'|'lstat'} statMethod 3688 * @property {Path} path 3689 * @property {Path} watchPath 3690 * @property {Function} entryPath 3691 * @property {Boolean} hasGlob 3692 * @property {Object} globFilter 3693 * @property {Function} filterPath 3694 * @property {Function} filterDir 3695 */ 3696 3697 const arrify = (value = []) => Array.isArray(value) ? value : [value]; 3698 const flatten = (list, result = []) => { 3699 list.forEach(item => { 3700 if (Array.isArray(item)) { 3701 flatten(item, result); 3702 } else { 3703 result.push(item); 3704 } 3705 }); 3706 return result; 3707 }; 3708 3709 const unifyPaths = (paths_) => { 3710 /** 3711 * @type {Array<String>} 3712 */ 3713 const paths = flatten(arrify(paths_)); 3714 if (!paths.every(p => typeof p === STRING_TYPE)) { 3715 throw new TypeError(`Non-string provided as watch path: ${paths}`); 3716 } 3717 return paths.map(normalizePathToUnix); 3718 }; 3719 3720 // If SLASH_SLASH occurs at the beginning of path, it is not replaced 3721 // because "//StoragePC/DrivePool/Movies" is a valid network path 3722 const toUnix = (string) => { 3723 let str = string.replace(BACK_SLASH_RE, SLASH); 3724 let prepend = false; 3725 if (str.startsWith(SLASH_SLASH)) { 3726 prepend = true; 3727 } 3728 while (str.match(DOUBLE_SLASH_RE)) { 3729 str = str.replace(DOUBLE_SLASH_RE, SLASH); 3730 } 3731 if (prepend) { 3732 str = SLASH + str; 3733 } 3734 return str; 3735 }; 3736 3737 // Our version of upath.normalize 3738 // TODO: this is not equal to path-normalize module - investigate why 3739 const normalizePathToUnix = (path) => toUnix(sysPath.normalize(toUnix(path))); 3740 3741 const normalizeIgnored = (cwd = EMPTY_STR) => (path) => { 3742 if (typeof path !== STRING_TYPE) return path; 3743 return normalizePathToUnix(sysPath.isAbsolute(path) ? path : sysPath.join(cwd, path)); 3744 }; 3745 3746 const getAbsolutePath = (path, cwd) => { 3747 if (sysPath.isAbsolute(path)) { 3748 return path; 3749 } 3750 if (path.startsWith(BANG)) { 3751 return BANG + sysPath.join(cwd, path.slice(1)); 3752 } 3753 return sysPath.join(cwd, path); 3754 }; 3755 3756 const undef = (opts, key) => opts[key] === undefined; 3757 3758 /** 3759 * Directory entry. 3760 * @property {Path} path 3761 * @property {Set<Path>} items 3762 */ 3763 class DirEntry { 3764 /** 3765 * @param {Path} dir 3766 * @param {Function} removeWatcher 3767 */ 3768 constructor(dir, removeWatcher) { 3769 this.path = dir; 3770 this._removeWatcher = removeWatcher; 3771 /** @type {Set<Path>} */ 3772 this.items = new Set(); 3773 } 3774 3775 add(item) { 3776 const {items} = this; 3777 if (!items) return; 3778 if (item !== ONE_DOT && item !== TWO_DOTS) items.add(item); 3779 } 3780 3781 async remove(item) { 3782 const {items} = this; 3783 if (!items) return; 3784 items.delete(item); 3785 if (items.size > 0) return; 3786 3787 const dir = this.path; 3788 try { 3789 await readdir(dir); 3790 } catch (err) { 3791 if (this._removeWatcher) { 3792 this._removeWatcher(sysPath.dirname(dir), sysPath.basename(dir)); 3793 } 3794 } 3795 } 3796 3797 has(item) { 3798 const {items} = this; 3799 if (!items) return; 3800 return items.has(item); 3801 } 3802 3803 /** 3804 * @returns {Array<String>} 3805 */ 3806 getChildren() { 3807 const {items} = this; 3808 if (!items) return; 3809 return [...items.values()]; 3810 } 3811 3812 dispose() { 3813 this.items.clear(); 3814 delete this.path; 3815 delete this._removeWatcher; 3816 delete this.items; 3817 Object.freeze(this); 3818 } 3819 } 3820 3821 const STAT_METHOD_F = 'stat'; 3822 const STAT_METHOD_L = 'lstat'; 3823 class WatchHelper { 3824 constructor(path, watchPath, follow, fsw) { 3825 this.fsw = fsw; 3826 this.path = path = path.replace(REPLACER_RE, EMPTY_STR); 3827 this.watchPath = watchPath; 3828 this.fullWatchPath = sysPath.resolve(watchPath); 3829 this.hasGlob = watchPath !== path; 3830 /** @type {object|boolean} */ 3831 if (path === EMPTY_STR) this.hasGlob = false; 3832 this.globSymlink = this.hasGlob && follow ? undefined : false; 3833 this.globFilter = this.hasGlob ? anymatch(path, undefined, ANYMATCH_OPTS) : false; 3834 this.dirParts = this.getDirParts(path); 3835 this.dirParts.forEach((parts) => { 3836 if (parts.length > 1) parts.pop(); 3837 }); 3838 this.followSymlinks = follow; 3839 this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L; 3840 } 3841 3842 checkGlobSymlink(entry) { 3843 // only need to resolve once 3844 // first entry should always have entry.parentDir === EMPTY_STR 3845 if (this.globSymlink === undefined) { 3846 this.globSymlink = entry.fullParentDir === this.fullWatchPath ? 3847 false : {realPath: entry.fullParentDir, linkPath: this.fullWatchPath}; 3848 } 3849 3850 if (this.globSymlink) { 3851 return entry.fullPath.replace(this.globSymlink.realPath, this.globSymlink.linkPath); 3852 } 3853 3854 return entry.fullPath; 3855 } 3856 3857 entryPath(entry) { 3858 return sysPath.join(this.watchPath, 3859 sysPath.relative(this.watchPath, this.checkGlobSymlink(entry)) 3860 ); 3861 } 3862 3863 filterPath(entry) { 3864 const {stats} = entry; 3865 if (stats && stats.isSymbolicLink()) return this.filterDir(entry); 3866 const resolvedPath = this.entryPath(entry); 3867 const matchesGlob = this.hasGlob && typeof this.globFilter === FUNCTION_TYPE ? 3868 this.globFilter(resolvedPath) : true; 3869 return matchesGlob && 3870 this.fsw._isntIgnored(resolvedPath, stats) && 3871 this.fsw._hasReadPermissions(stats); 3872 } 3873 3874 getDirParts(path) { 3875 if (!this.hasGlob) return []; 3876 const parts = []; 3877 const expandedPath = path.includes(BRACE_START) ? braces.expand(path) : [path]; 3878 expandedPath.forEach((path) => { 3879 parts.push(sysPath.relative(this.watchPath, path).split(SLASH_OR_BACK_SLASH_RE)); 3880 }); 3881 return parts; 3882 } 3883 3884 filterDir(entry) { 3885 if (this.hasGlob) { 3886 const entryParts = this.getDirParts(this.checkGlobSymlink(entry)); 3887 let globstar = false; 3888 this.unmatchedGlob = !this.dirParts.some((parts) => { 3889 return parts.every((part, i) => { 3890 if (part === GLOBSTAR) globstar = true; 3891 return globstar || !entryParts[0][i] || anymatch(part, entryParts[0][i], ANYMATCH_OPTS); 3892 }); 3893 }); 3894 } 3895 return !this.unmatchedGlob && this.fsw._isntIgnored(this.entryPath(entry), entry.stats); 3896 } 3897 } 3898 3899 /** 3900 * Watches files & directories for changes. Emitted events: 3901 * `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `all`, `error` 3902 * 3903 * new FSWatcher() 3904 * .add(directories) 3905 * .on('add', path => log('File', path, 'was added')) 3906 */ 3907 class FSWatcher extends EventEmitter { 3908 // Not indenting methods for history sake; for now. 3909 constructor(_opts) { 3910 super(); 3911 3912 const opts = {}; 3913 if (_opts) Object.assign(opts, _opts); // for frozen objects 3914 3915 /** @type {Map<String, DirEntry>} */ 3916 this._watched = new Map(); 3917 /** @type {Map<String, Array>} */ 3918 this._closers = new Map(); 3919 /** @type {Set<String>} */ 3920 this._ignoredPaths = new Set(); 3921 3922 /** @type {Map<ThrottleType, Map>} */ 3923 this._throttled = new Map(); 3924 3925 /** @type {Map<Path, String|Boolean>} */ 3926 this._symlinkPaths = new Map(); 3927 3928 this._streams = new Set(); 3929 this.closed = false; 3930 3931 // Set up default options. 3932 if (undef(opts, 'persistent')) opts.persistent = true; 3933 if (undef(opts, 'ignoreInitial')) opts.ignoreInitial = false; 3934 if (undef(opts, 'ignorePermissionErrors')) opts.ignorePermissionErrors = false; 3935 if (undef(opts, 'interval')) opts.interval = 100; 3936 if (undef(opts, 'binaryInterval')) opts.binaryInterval = 300; 3937 if (undef(opts, 'disableGlobbing')) opts.disableGlobbing = false; 3938 opts.enableBinaryInterval = opts.binaryInterval !== opts.interval; 3939 3940 // Enable fsevents on OS X when polling isn't explicitly enabled. 3941 if (undef(opts, 'useFsEvents')) opts.useFsEvents = !opts.usePolling; 3942 3943 // If we can't use fsevents, ensure the options reflect it's disabled. 3944 const canUseFsEvents = FsEventsHandler.canUse(); 3945 if (!canUseFsEvents) opts.useFsEvents = false; 3946 3947 // Use polling on Mac if not using fsevents. 3948 // Other platforms use non-polling fs_watch. 3949 if (undef(opts, 'usePolling') && !opts.useFsEvents) { 3950 opts.usePolling = isMacos; 3951 } 3952 3953 // Always default to polling on IBM i because fs.watch() is not available on IBM i. 3954 if(isIBMi) { 3955 opts.usePolling = true; 3956 } 3957 3958 // Global override (useful for end-developers that need to force polling for all 3959 // instances of chokidar, regardless of usage/dependency depth) 3960 const envPoll = process.env.CHOKIDAR_USEPOLLING; 3961 if (envPoll !== undefined) { 3962 const envLower = envPoll.toLowerCase(); 3963 3964 if (envLower === 'false' || envLower === '0') { 3965 opts.usePolling = false; 3966 } else if (envLower === 'true' || envLower === '1') { 3967 opts.usePolling = true; 3968 } else { 3969 opts.usePolling = !!envLower; 3970 } 3971 } 3972 const envInterval = process.env.CHOKIDAR_INTERVAL; 3973 if (envInterval) { 3974 opts.interval = Number.parseInt(envInterval, 10); 3975 } 3976 3977 // Editor atomic write normalization enabled by default with fs.watch 3978 if (undef(opts, 'atomic')) opts.atomic = !opts.usePolling && !opts.useFsEvents; 3979 if (opts.atomic) this._pendingUnlinks = new Map(); 3980 3981 if (undef(opts, 'followSymlinks')) opts.followSymlinks = true; 3982 3983 if (undef(opts, 'awaitWriteFinish')) opts.awaitWriteFinish = false; 3984 if (opts.awaitWriteFinish === true) opts.awaitWriteFinish = {}; 3985 const awf = opts.awaitWriteFinish; 3986 if (awf) { 3987 if (!awf.stabilityThreshold) awf.stabilityThreshold = 2000; 3988 if (!awf.pollInterval) awf.pollInterval = 100; 3989 this._pendingWrites = new Map(); 3990 } 3991 if (opts.ignored) opts.ignored = arrify(opts.ignored); 3992 3993 let readyCalls = 0; 3994 this._emitReady = () => { 3995 readyCalls++; 3996 if (readyCalls >= this._readyCount) { 3997 this._emitReady = EMPTY_FN; 3998 this._readyEmitted = true; 3999 // use process.nextTick to allow time for listener to be bound 4000 process.nextTick(() => this.emit(EV_READY)); 4001 } 4002 }; 4003 this._emitRaw = (...args) => this.emit(EV_RAW, ...args); 4004 this._readyEmitted = false; 4005 this.options = opts; 4006 4007 // Initialize with proper watcher. 4008 if (opts.useFsEvents) { 4009 this._fsEventsHandler = new FsEventsHandler(this); 4010 } else { 4011 this._nodeFsHandler = new NodeFsHandler(this); 4012 } 4013 4014 // You’re frozen when your heart’s not open. 4015 Object.freeze(opts); 4016 } 4017 4018 // Public methods 4019 4020 /** 4021 * Adds paths to be watched on an existing FSWatcher instance 4022 * @param {Path|Array<Path>} paths_ 4023 * @param {String=} _origAdd private; for handling non-existent paths to be watched 4024 * @param {Boolean=} _internal private; indicates a non-user add 4025 * @returns {FSWatcher} for chaining 4026 */ 4027 add(paths_, _origAdd, _internal) { 4028 const {cwd, disableGlobbing} = this.options; 4029 this.closed = false; 4030 let paths = unifyPaths(paths_); 4031 if (cwd) { 4032 paths = paths.map((path) => { 4033 const absPath = getAbsolutePath(path, cwd); 4034 4035 // Check `path` instead of `absPath` because the cwd portion can't be a glob 4036 if (disableGlobbing || !isGlob(path)) { 4037 return absPath; 4038 } 4039 return normalizePath(absPath); 4040 }); 4041 } 4042 4043 // set aside negated glob strings 4044 paths = paths.filter((path) => { 4045 if (path.startsWith(BANG)) { 4046 this._ignoredPaths.add(path.slice(1)); 4047 return false; 4048 } 4049 4050 // if a path is being added that was previously ignored, stop ignoring it 4051 this._ignoredPaths.delete(path); 4052 this._ignoredPaths.delete(path + SLASH_GLOBSTAR); 4053 4054 // reset the cached userIgnored anymatch fn 4055 // to make ignoredPaths changes effective 4056 this._userIgnored = undefined; 4057 4058 return true; 4059 }); 4060 4061 if (this.options.useFsEvents && this._fsEventsHandler) { 4062 if (!this._readyCount) this._readyCount = paths.length; 4063 if (this.options.persistent) this._readyCount += paths.length; 4064 paths.forEach((path) => this._fsEventsHandler._addToFsEvents(path)); 4065 } else { 4066 if (!this._readyCount) this._readyCount = 0; 4067 this._readyCount += paths.length; 4068 Promise.all( 4069 paths.map(async path => { 4070 const res = await this._nodeFsHandler._addToNodeFs(path, !_internal, 0, 0, _origAdd); 4071 if (res) this._emitReady(); 4072 return res; 4073 }) 4074 ).then(results => { 4075 if (this.closed) return; 4076 results.filter(item => item).forEach(item => { 4077 this.add(sysPath.dirname(item), sysPath.basename(_origAdd || item)); 4078 }); 4079 }); 4080 } 4081 4082 return this; 4083 } 4084 4085 /** 4086 * Close watchers or start ignoring events from specified paths. 4087 * @param {Path|Array<Path>} paths_ - string or array of strings, file/directory paths and/or globs 4088 * @returns {FSWatcher} for chaining 4089 */ 4090 unwatch(paths_) { 4091 if (this.closed) return this; 4092 const paths = unifyPaths(paths_); 4093 const {cwd} = this.options; 4094 4095 paths.forEach((path) => { 4096 // convert to absolute path unless relative path already matches 4097 if (!sysPath.isAbsolute(path) && !this._closers.has(path)) { 4098 if (cwd) path = sysPath.join(cwd, path); 4099 path = sysPath.resolve(path); 4100 } 4101 4102 this._closePath(path); 4103 4104 this._ignoredPaths.add(path); 4105 if (this._watched.has(path)) { 4106 this._ignoredPaths.add(path + SLASH_GLOBSTAR); 4107 } 4108 4109 // reset the cached userIgnored anymatch fn 4110 // to make ignoredPaths changes effective 4111 this._userIgnored = undefined; 4112 }); 4113 4114 return this; 4115 } 4116 4117 /** 4118 * Close watchers and remove all listeners from watched paths. 4119 * @returns {Promise<void>}. 4120 */ 4121 close() { 4122 if (this.closed) return this._closePromise; 4123 this.closed = true; 4124 4125 // Memory management. 4126 this.removeAllListeners(); 4127 const closers = []; 4128 this._closers.forEach(closerList => closerList.forEach(closer => { 4129 const promise = closer(); 4130 if (promise instanceof Promise) closers.push(promise); 4131 })); 4132 this._streams.forEach(stream => stream.destroy()); 4133 this._userIgnored = undefined; 4134 this._readyCount = 0; 4135 this._readyEmitted = false; 4136 this._watched.forEach(dirent => dirent.dispose()); 4137 ['closers', 'watched', 'streams', 'symlinkPaths', 'throttled'].forEach(key => { 4138 this[`_${key}`].clear(); 4139 }); 4140 4141 this._closePromise = closers.length ? Promise.all(closers).then(() => undefined) : Promise.resolve(); 4142 return this._closePromise; 4143 } 4144 4145 /** 4146 * Expose list of watched paths 4147 * @returns {Object} for chaining 4148 */ 4149 getWatched() { 4150 const watchList = {}; 4151 this._watched.forEach((entry, dir) => { 4152 const key = this.options.cwd ? sysPath.relative(this.options.cwd, dir) : dir; 4153 watchList[key || ONE_DOT] = entry.getChildren().sort(); 4154 }); 4155 return watchList; 4156 } 4157 4158 emitWithAll(event, args) { 4159 this.emit(...args); 4160 if (event !== EV_ERROR) this.emit(EV_ALL, ...args); 4161 } 4162 4163 // Common helpers 4164 // -------------- 4165 4166 /** 4167 * Normalize and emit events. 4168 * Calling _emit DOES NOT MEAN emit() would be called! 4169 * @param {EventName} event Type of event 4170 * @param {Path} path File or directory path 4171 * @param {*=} val1 arguments to be passed with event 4172 * @param {*=} val2 4173 * @param {*=} val3 4174 * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag 4175 */ 4176 async _emit(event, path, val1, val2, val3) { 4177 if (this.closed) return; 4178 4179 const opts = this.options; 4180 if (isWindows) path = sysPath.normalize(path); 4181 if (opts.cwd) path = sysPath.relative(opts.cwd, path); 4182 /** @type Array<any> */ 4183 const args = [event, path]; 4184 if (val3 !== undefined) args.push(val1, val2, val3); 4185 else if (val2 !== undefined) args.push(val1, val2); 4186 else if (val1 !== undefined) args.push(val1); 4187 4188 const awf = opts.awaitWriteFinish; 4189 let pw; 4190 if (awf && (pw = this._pendingWrites.get(path))) { 4191 pw.lastChange = new Date(); 4192 return this; 4193 } 4194 4195 if (opts.atomic) { 4196 if (event === EV_UNLINK) { 4197 this._pendingUnlinks.set(path, args); 4198 setTimeout(() => { 4199 this._pendingUnlinks.forEach((entry, path) => { 4200 this.emit(...entry); 4201 this.emit(EV_ALL, ...entry); 4202 this._pendingUnlinks.delete(path); 4203 }); 4204 }, typeof opts.atomic === 'number' ? opts.atomic : 100); 4205 return this; 4206 } 4207 if (event === EV_ADD && this._pendingUnlinks.has(path)) { 4208 event = args[0] = EV_CHANGE; 4209 this._pendingUnlinks.delete(path); 4210 } 4211 } 4212 4213 if (awf && (event === EV_ADD || event === EV_CHANGE) && this._readyEmitted) { 4214 const awfEmit = (err, stats) => { 4215 if (err) { 4216 event = args[0] = EV_ERROR; 4217 args[1] = err; 4218 this.emitWithAll(event, args); 4219 } else if (stats) { 4220 // if stats doesn't exist the file must have been deleted 4221 if (args.length > 2) { 4222 args[2] = stats; 4223 } else { 4224 args.push(stats); 4225 } 4226 this.emitWithAll(event, args); 4227 } 4228 }; 4229 4230 this._awaitWriteFinish(path, awf.stabilityThreshold, event, awfEmit); 4231 return this; 4232 } 4233 4234 if (event === EV_CHANGE) { 4235 const isThrottled = !this._throttle(EV_CHANGE, path, 50); 4236 if (isThrottled) return this; 4237 } 4238 4239 if (opts.alwaysStat && val1 === undefined && 4240 (event === EV_ADD || event === EV_ADD_DIR || event === EV_CHANGE) 4241 ) { 4242 const fullPath = opts.cwd ? sysPath.join(opts.cwd, path) : path; 4243 let stats; 4244 try { 4245 stats = await stat(fullPath); 4246 } catch (err) {} 4247 // Suppress event when fs_stat fails, to avoid sending undefined 'stat' 4248 if (!stats || this.closed) return; 4249 args.push(stats); 4250 } 4251 this.emitWithAll(event, args); 4252 4253 return this; 4254 } 4255 4256 /** 4257 * Common handler for errors 4258 * @param {Error} error 4259 * @returns {Error|Boolean} The error if defined, otherwise the value of the FSWatcher instance's `closed` flag 4260 */ 4261 _handleError(error) { 4262 const code = error && error.code; 4263 if (error && code !== 'ENOENT' && code !== 'ENOTDIR' && 4264 (!this.options.ignorePermissionErrors || (code !== 'EPERM' && code !== 'EACCES')) 4265 ) { 4266 this.emit(EV_ERROR, error); 4267 } 4268 return error || this.closed; 4269 } 4270 4271 /** 4272 * Helper utility for throttling 4273 * @param {ThrottleType} actionType type being throttled 4274 * @param {Path} path being acted upon 4275 * @param {Number} timeout duration of time to suppress duplicate actions 4276 * @returns {Object|false} tracking object or false if action should be suppressed 4277 */ 4278 _throttle(actionType, path, timeout) { 4279 if (!this._throttled.has(actionType)) { 4280 this._throttled.set(actionType, new Map()); 4281 } 4282 4283 /** @type {Map<Path, Object>} */ 4284 const action = this._throttled.get(actionType); 4285 /** @type {Object} */ 4286 const actionPath = action.get(path); 4287 4288 if (actionPath) { 4289 actionPath.count++; 4290 return false; 4291 } 4292 4293 let timeoutObject; 4294 const clear = () => { 4295 const item = action.get(path); 4296 const count = item ? item.count : 0; 4297 action.delete(path); 4298 clearTimeout(timeoutObject); 4299 if (item) clearTimeout(item.timeoutObject); 4300 return count; 4301 }; 4302 timeoutObject = setTimeout(clear, timeout); 4303 const thr = {timeoutObject, clear, count: 0}; 4304 action.set(path, thr); 4305 return thr; 4306 } 4307 4308 _incrReadyCount() { 4309 return this._readyCount++; 4310 } 4311 4312 /** 4313 * Awaits write operation to finish. 4314 * Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback. 4315 * @param {Path} path being acted upon 4316 * @param {Number} threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished 4317 * @param {EventName} event 4318 * @param {Function} awfEmit Callback to be called when ready for event to be emitted. 4319 */ 4320 _awaitWriteFinish(path, threshold, event, awfEmit) { 4321 let timeoutHandler; 4322 4323 let fullPath = path; 4324 if (this.options.cwd && !sysPath.isAbsolute(path)) { 4325 fullPath = sysPath.join(this.options.cwd, path); 4326 } 4327 4328 const now = new Date(); 4329 4330 const awaitWriteFinish = (prevStat) => { 4331 fs.stat(fullPath, (err, curStat) => { 4332 if (err || !this._pendingWrites.has(path)) { 4333 if (err && err.code !== 'ENOENT') awfEmit(err); 4334 return; 4335 } 4336 4337 const now = Number(new Date()); 4338 4339 if (prevStat && curStat.size !== prevStat.size) { 4340 this._pendingWrites.get(path).lastChange = now; 4341 } 4342 const pw = this._pendingWrites.get(path); 4343 const df = now - pw.lastChange; 4344 4345 if (df >= threshold) { 4346 this._pendingWrites.delete(path); 4347 awfEmit(undefined, curStat); 4348 } else { 4349 timeoutHandler = setTimeout( 4350 awaitWriteFinish, 4351 this.options.awaitWriteFinish.pollInterval, 4352 curStat 4353 ); 4354 } 4355 }); 4356 }; 4357 4358 if (!this._pendingWrites.has(path)) { 4359 this._pendingWrites.set(path, { 4360 lastChange: now, 4361 cancelWait: () => { 4362 this._pendingWrites.delete(path); 4363 clearTimeout(timeoutHandler); 4364 return event; 4365 } 4366 }); 4367 timeoutHandler = setTimeout( 4368 awaitWriteFinish, 4369 this.options.awaitWriteFinish.pollInterval 4370 ); 4371 } 4372 } 4373 4374 _getGlobIgnored() { 4375 return [...this._ignoredPaths.values()]; 4376 } 4377 4378 /** 4379 * Determines whether user has asked to ignore this path. 4380 * @param {Path} path filepath or dir 4381 * @param {fs.Stats=} stats result of fs.stat 4382 * @returns {Boolean} 4383 */ 4384 _isIgnored(path, stats) { 4385 if (this.options.atomic && DOT_RE.test(path)) return true; 4386 if (!this._userIgnored) { 4387 const {cwd} = this.options; 4388 const ign = this.options.ignored; 4389 4390 const ignored = ign && ign.map(normalizeIgnored(cwd)); 4391 const paths = arrify(ignored) 4392 .filter((path) => typeof path === STRING_TYPE && !isGlob(path)) 4393 .map((path) => path + SLASH_GLOBSTAR); 4394 const list = this._getGlobIgnored().map(normalizeIgnored(cwd)).concat(ignored, paths); 4395 this._userIgnored = anymatch(list, undefined, ANYMATCH_OPTS); 4396 } 4397 4398 return this._userIgnored([path, stats]); 4399 } 4400 4401 _isntIgnored(path, stat) { 4402 return !this._isIgnored(path, stat); 4403 } 4404 4405 /** 4406 * Provides a set of common helpers and properties relating to symlink and glob handling. 4407 * @param {Path} path file, directory, or glob pattern being watched 4408 * @param {Number=} depth at any depth > 0, this isn't a glob 4409 * @returns {WatchHelper} object containing helpers for this path 4410 */ 4411 _getWatchHelpers(path, depth) { 4412 const watchPath = depth || this.options.disableGlobbing || !isGlob(path) ? path : globParent(path); 4413 const follow = this.options.followSymlinks; 4414 4415 return new WatchHelper(path, watchPath, follow, this); 4416 } 4417 4418 // Directory helpers 4419 // ----------------- 4420 4421 /** 4422 * Provides directory tracking objects 4423 * @param {String} directory path of the directory 4424 * @returns {DirEntry} the directory's tracking object 4425 */ 4426 _getWatchedDir(directory) { 4427 if (!this._boundRemove) this._boundRemove = this._remove.bind(this); 4428 const dir = sysPath.resolve(directory); 4429 if (!this._watched.has(dir)) this._watched.set(dir, new DirEntry(dir, this._boundRemove)); 4430 return this._watched.get(dir); 4431 } 4432 4433 // File helpers 4434 // ------------ 4435 4436 /** 4437 * Check for read permissions. 4438 * Based on this answer on SO: https://stackoverflow.com/a/11781404/1358405 4439 * @param {fs.Stats} stats - object, result of fs_stat 4440 * @returns {Boolean} indicates whether the file can be read 4441 */ 4442 _hasReadPermissions(stats) { 4443 if (this.options.ignorePermissionErrors) return true; 4444 4445 // stats.mode may be bigint 4446 const md = stats && Number.parseInt(stats.mode, 10); 4447 const st = md & 0o777; 4448 const it = Number.parseInt(st.toString(8)[0], 10); 4449 return Boolean(4 & it); 4450 } 4451 4452 /** 4453 * Handles emitting unlink events for 4454 * files and directories, and via recursion, for 4455 * files and directories within directories that are unlinked 4456 * @param {String} directory within which the following item is located 4457 * @param {String} item base path of item/directory 4458 * @returns {void} 4459 */ 4460 _remove(directory, item, isDirectory) { 4461 // if what is being deleted is a directory, get that directory's paths 4462 // for recursive deleting and cleaning of watched object 4463 // if it is not a directory, nestedDirectoryChildren will be empty array 4464 const path = sysPath.join(directory, item); 4465 const fullPath = sysPath.resolve(path); 4466 isDirectory = isDirectory != null 4467 ? isDirectory 4468 : this._watched.has(path) || this._watched.has(fullPath); 4469 4470 // prevent duplicate handling in case of arriving here nearly simultaneously 4471 // via multiple paths (such as _handleFile and _handleDir) 4472 if (!this._throttle('remove', path, 100)) return; 4473 4474 // if the only watched file is removed, watch for its return 4475 if (!isDirectory && !this.options.useFsEvents && this._watched.size === 1) { 4476 this.add(directory, item, true); 4477 } 4478 4479 // This will create a new entry in the watched object in either case 4480 // so we got to do the directory check beforehand 4481 const wp = this._getWatchedDir(path); 4482 const nestedDirectoryChildren = wp.getChildren(); 4483 4484 // Recursively remove children directories / files. 4485 nestedDirectoryChildren.forEach(nested => this._remove(path, nested)); 4486 4487 // Check if item was on the watched list and remove it 4488 const parent = this._getWatchedDir(directory); 4489 const wasTracked = parent.has(item); 4490 parent.remove(item); 4491 4492 // Fixes issue #1042 -> Relative paths were detected and added as symlinks 4493 // (https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L612), 4494 // but never removed from the map in case the path was deleted. 4495 // This leads to an incorrect state if the path was recreated: 4496 // https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L553 4497 if (this._symlinkPaths.has(fullPath)) { 4498 this._symlinkPaths.delete(fullPath); 4499 } 4500 4501 // If we wait for this file to be fully written, cancel the wait. 4502 let relPath = path; 4503 if (this.options.cwd) relPath = sysPath.relative(this.options.cwd, path); 4504 if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) { 4505 const event = this._pendingWrites.get(relPath).cancelWait(); 4506 if (event === EV_ADD) return; 4507 } 4508 4509 // The Entry will either be a directory that just got removed 4510 // or a bogus entry to a file, in either case we have to remove it 4511 this._watched.delete(path); 4512 this._watched.delete(fullPath); 4513 const eventName = isDirectory ? EV_UNLINK_DIR : EV_UNLINK; 4514 if (wasTracked && !this._isIgnored(path)) this._emit(eventName, path); 4515 4516 // Avoid conflicts if we later create another file with the same name 4517 if (!this.options.useFsEvents) { 4518 this._closePath(path); 4519 } 4520 } 4521 4522 /** 4523 * Closes all watchers for a path 4524 * @param {Path} path 4525 */ 4526 _closePath(path) { 4527 this._closeFile(path); 4528 const dir = sysPath.dirname(path); 4529 this._getWatchedDir(dir).remove(sysPath.basename(path)); 4530 } 4531 4532 /** 4533 * Closes only file-specific watchers 4534 * @param {Path} path 4535 */ 4536 _closeFile(path) { 4537 const closers = this._closers.get(path); 4538 if (!closers) return; 4539 closers.forEach(closer => closer()); 4540 this._closers.delete(path); 4541 } 4542 4543 /** 4544 * 4545 * @param {Path} path 4546 * @param {Function} closer 4547 */ 4548 _addPathCloser(path, closer) { 4549 if (!closer) return; 4550 let list = this._closers.get(path); 4551 if (!list) { 4552 list = []; 4553 this._closers.set(path, list); 4554 } 4555 list.push(closer); 4556 } 4557 4558 _readdirp(root, opts) { 4559 if (this.closed) return; 4560 const options = {type: EV_ALL, alwaysStat: true, lstat: true, ...opts}; 4561 let stream = readdirp(root, options); 4562 this._streams.add(stream); 4563 stream.once(STR_CLOSE, () => { 4564 stream = undefined; 4565 }); 4566 stream.once(STR_END, () => { 4567 if (stream) { 4568 this._streams.delete(stream); 4569 stream = undefined; 4570 } 4571 }); 4572 return stream; 4573 } 4574 4575 } 4576 4577 // Export FSWatcher class 4578 chokidar.FSWatcher = FSWatcher; 4579 4580 /** 4581 * Instantiates watcher with paths to be tracked. 4582 * @param {String|Array<String>} paths file/directory paths and/or globs 4583 * @param {Object=} options chokidar opts 4584 * @returns an instance of FSWatcher for chaining. 4585 */ 4586 const watch = (paths, options) => { 4587 const watcher = new FSWatcher(options); 4588 watcher.add(paths); 4589 return watcher; 4590 }; 4591 4592 chokidar.watch = watch; 9004 var chokidarExports = /*@__PURE__*/ requireChokidar(); 9005 const chokidar = /*@__PURE__*/getDefaultExportFromCjs(chokidarExports); 4593 9006 4594 9007 class FileWatcher { … … 4626 9039 const task = this.task; 4627 9040 const isLinux = platform() === 'linux'; 9041 const isFreeBSD = platform() === 'freebsd'; 4628 9042 const isTransformDependency = transformWatcherId !== null; 4629 9043 const handleChange = (id, event) => { 4630 9044 const changedId = transformWatcherId || id; 4631 if (isLinux ) {9045 if (isLinux || isFreeBSD) { 4632 9046 // unwatching and watching fixes an issue with chokidar where on certain systems, 4633 9047 // a file that was unlinked and immediately recreated would create a change event … … 4768 9182 this.outputFiles = this.outputs.map(output => { 4769 9183 if (output.file || output.dir) 4770 return path $1.resolve(output.file || output.dir);9184 return path.resolve(output.file || output.dir); 4771 9185 return undefined; 4772 9186 });
Note:
See TracChangeset
for help on using the changeset viewer.