wildcard-match
Version:
A tiny and extremely fast library for compiling and matching basic glob patterns
1 lines • 12 kB
Source Map (JSON)
{"version":3,"file":"index.es.mjs","sources":["../src/transform.ts","../src/index.ts"],"sourcesContent":["/**\n * Escapes a character if it has a special meaning in regular expressions\n * and returns the character as is if it doesn't\n */\nfunction escapeRegExpChar(char: string) {\n if (\n char === '-' ||\n char === '^' ||\n char === '$' ||\n char === '+' ||\n char === '.' ||\n char === '(' ||\n char === ')' ||\n char === '|' ||\n char === '[' ||\n char === ']' ||\n char === '{' ||\n char === '}' ||\n char === '*' ||\n char === '?' ||\n char === '\\\\'\n ) {\n return `\\\\${char}`\n } else {\n return char\n }\n}\n\n/**\n * Escapes all characters in a given string that have a special meaning in regular expressions\n */\nfunction escapeRegExpString(str: string) {\n let result = ''\n for (let i = 0; i < str.length; i++) {\n result += escapeRegExpChar(str[i])\n }\n return result\n}\n\n/**\n * Transforms one or more glob patterns into a RegExp pattern\n */\nfunction transform(\n pattern: string | string[],\n separator: string | boolean = true\n): string {\n if (Array.isArray(pattern)) {\n let regExpPatterns = pattern.map((p) => `^${transform(p, separator)}$`)\n return `(?:${regExpPatterns.join('|')})`\n }\n\n let separatorSplitter = ''\n let separatorMatcher = ''\n let wildcard = '.'\n\n if (separator === true) {\n // In this case forward slashes in patterns match both forward and backslashes in samples:\n //\n // `foo/bar` will match `foo/bar`\n // will match `foo\\bar`\n //\n separatorSplitter = '/'\n separatorMatcher = '[/\\\\\\\\]'\n wildcard = '[^/\\\\\\\\]'\n } else if (separator) {\n separatorSplitter = separator\n separatorMatcher = escapeRegExpString(separatorSplitter)\n\n if (separatorMatcher.length > 1) {\n separatorMatcher = `(?:${separatorMatcher})`\n wildcard = `((?!${separatorMatcher}).)`\n } else {\n wildcard = `[^${separatorMatcher}]`\n }\n }\n\n // When a separator is explicitly specified in a pattern,\n // it MUST match ONE OR MORE separators in a sample:\n //\n // `foo/bar/` will match `foo//bar///`\n // won't match `foo/bar`\n //\n // When a pattern doesn't have a trailing separator,\n // a sample can still optionally have them:\n //\n // `foo/bar` will match `foo/bar//`\n //\n // So we use different quantifiers depending on the index of a segment.\n let requiredSeparator = separator ? `${separatorMatcher}+?` : ''\n let optionalSeparator = separator ? `${separatorMatcher}*?` : ''\n\n let segments = separator ? pattern.split(separatorSplitter) : [pattern]\n let result = ''\n\n for (let s = 0; s < segments.length; s++) {\n let segment = segments[s]\n let nextSegment = segments[s + 1]\n let currentSeparator = ''\n\n if (!segment && s > 0) {\n continue\n }\n\n if (separator) {\n if (s === segments.length - 1) {\n currentSeparator = optionalSeparator\n } else if (nextSegment !== '**') {\n currentSeparator = requiredSeparator\n } else {\n currentSeparator = ''\n }\n }\n\n if (separator && segment === '**') {\n if (currentSeparator) {\n result +=\n s === 0\n ? ''\n : s === segments.length - 1\n ? `(?:${requiredSeparator}|$)`\n : requiredSeparator\n result += `(?:${wildcard}*?${currentSeparator})*?`\n }\n continue\n }\n\n for (let c = 0; c < segment.length; c++) {\n let char = segment[c]\n\n if (char === '\\\\') {\n if (c < segment.length - 1) {\n result += escapeRegExpChar(segment[c + 1])\n c++\n }\n } else if (char === '?') {\n result += wildcard\n } else if (char === '*') {\n result += `${wildcard}*?`\n } else {\n result += escapeRegExpChar(char)\n }\n }\n\n result += currentSeparator\n }\n\n return result\n}\n\nexport default transform\n","import transform from './transform'\n\ninterface WildcardMatchOptions {\n /** Separator to be used to split patterns and samples into segments */\n separator?: string | boolean\n\n /** Flags to pass to the RegExp */\n flags?: string\n}\n\n// This overrides the function's signature because for the end user\n// the function is always bound to a RegExp\ninterface isMatch {\n /**\n * Tests if a sample string matches the pattern(s)\n *\n * ```js\n * isMatch('foo') //=> true\n * ```\n */\n (sample: string): boolean\n\n /** Compiled regular expression */\n regexp: RegExp\n\n /** Original pattern or array of patterns that was used to compile the RegExp */\n pattern: string | string[]\n\n /** Options that were used to compile the RegExp */\n options: WildcardMatchOptions\n}\n\nfunction isMatch(regexp: RegExp, sample: string) {\n if (typeof sample !== 'string') {\n throw new TypeError(`Sample must be a string, but ${typeof sample} given`)\n }\n\n return regexp.test(sample)\n}\n\n/**\n * Compiles one or more glob patterns into a RegExp and returns an isMatch function.\n * The isMatch function takes a sample string as its only argument and returns `true`\n * if the string matches the pattern(s).\n *\n * ```js\n * wildcardMatch('src/*.js')('src/index.js') //=> true\n * ```\n *\n * ```js\n * const isMatch = wildcardMatch('*.example.com', '.')\n * isMatch('foo.example.com') //=> true\n * isMatch('foo.bar.com') //=> false\n * ```\n */\nfunction wildcardMatch(\n pattern: string | string[],\n options?: string | boolean | WildcardMatchOptions\n) {\n if (typeof pattern !== 'string' && !Array.isArray(pattern)) {\n throw new TypeError(\n `The first argument must be a single pattern string or an array of patterns, but ${typeof pattern} given`\n )\n }\n\n if (typeof options === 'string' || typeof options === 'boolean') {\n options = { separator: options }\n }\n\n if (\n arguments.length === 2 &&\n !(\n typeof options === 'undefined' ||\n (typeof options === 'object' && options !== null && !Array.isArray(options))\n )\n ) {\n throw new TypeError(\n `The second argument must be an options object or a string/boolean separator, but ${typeof options} given`\n )\n }\n\n options = options || {}\n\n if (options.separator === '\\\\') {\n throw new Error(\n '\\\\ is not a valid separator because it is used for escaping. Try setting the separator to `true` instead'\n )\n }\n\n let regexpPattern = transform(pattern, options.separator)\n let regexp = new RegExp(`^${regexpPattern}$`, options.flags)\n\n let fn = isMatch.bind(null, regexp) as isMatch\n fn.options = options\n fn.pattern = pattern\n fn.regexp = regexp\n return fn\n}\n\nexport default wildcardMatch\n"],"names":[],"mappings":"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"}