diff --git a/.eslintrc.json b/.eslintrc.json index ba84ad6..b23abd6 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -2,36 +2,106 @@ "extends": [ "eslint:recommended" ], - "env": { "es6": true, "node": true }, - "parserOptions": { - "ecmaVersion": 2018 + "ecmaVersion": 2018, + "sourceType": "module" }, - "rules": { "accessor-pairs": 2, - "arrow-parens": [2, "as-needed"], - "arrow-spacing": [2, { "before": true, "after": true }], - "block-spacing": [2, "always"], - "brace-style": [2, "1tbs", { "allowSingleLine": true }], - "comma-dangle": [2, "never"], - "comma-spacing": [2, { "before": false, "after": true }], - "comma-style": [2, "last"], + "arrow-parens": [ + 2, + "as-needed" + ], + "arrow-spacing": [ + 2, + { + "before": true, + "after": true + } + ], + "block-spacing": [ + 2, + "always" + ], + "brace-style": [ + 2, + "1tbs", + { + "allowSingleLine": true + } + ], + "comma-dangle": [ + 2, + "never" + ], + "comma-spacing": [ + 2, + { + "before": false, + "after": true + } + ], + "comma-style": [ + 2, + "last" + ], "constructor-super": 2, - "curly": [2, "multi-line"], - "dot-location": [2, "property"], + "curly": [ + 2, + "multi-line" + ], + "dot-location": [ + 2, + "property" + ], "eol-last": 2, - "eqeqeq": [2, "allow-null"], - "generator-star-spacing": [2, { "before": true, "after": true }], - "handle-callback-err": [2, "^(err|error)$"], - "indent": [2, 2, { "SwitchCase": 1 }], - "key-spacing": [2, { "beforeColon": false, "afterColon": true }], - "keyword-spacing": [2, { "before": true, "after": true }], - "new-cap": [2, { "newIsCap": true, "capIsNew": false }], + "eqeqeq": [ + 2, + "allow-null" + ], + "generator-star-spacing": [ + 2, + { + "before": true, + "after": true + } + ], + "handle-callback-err": [ + 2, + "^(err|error)$" + ], + "indent": [ + 2, + 2, + { + "SwitchCase": 1 + } + ], + "key-spacing": [ + 2, + { + "beforeColon": false, + "afterColon": true + } + ], + "keyword-spacing": [ + 2, + { + "before": true, + "after": true + } + ], + "new-cap": [ + 2, + { + "newIsCap": true, + "capIsNew": false + } + ], "new-parens": 2, "no-array-constructor": 2, "no-caller": 2, @@ -51,13 +121,19 @@ "no-extend-native": 2, "no-extra-bind": 2, "no-extra-boolean-cast": 2, - "no-extra-parens": [2, "functions"], + "no-extra-parens": [ + 2, + "functions" + ], "no-fallthrough": 2, "no-floating-decimal": 2, "no-func-assign": 2, "no-implied-eval": 2, "no-implicit-coercion": 2, - "no-inner-declarations": [2, "functions"], + "no-inner-declarations": [ + 2, + "functions" + ], "no-invalid-regexp": 2, "no-irregular-whitespace": 2, "no-iterator": 2, @@ -68,7 +144,12 @@ "no-mixed-spaces-and-tabs": 2, "no-multi-spaces": 0, "no-multi-str": 2, - "no-multiple-empty-lines": [2, { "max": 1 }], + "no-multiple-empty-lines": [ + 2, + { + "max": 1 + } + ], "no-native-reassign": 2, "no-negated-in-lhs": 2, "no-new": 2, @@ -94,31 +175,123 @@ "no-undef": 2, "no-undef-init": 2, "no-unexpected-multiline": 2, - "no-unneeded-ternary": [2, { "defaultAssignment": false }], + "no-unneeded-ternary": [ + 2, + { + "defaultAssignment": false + } + ], "no-unreachable": 2, "no-unused-expressions": 2, - "no-unused-vars": [2, { "vars": "all", "args": "none" }], + "no-unused-vars": [ + 2, + { + "vars": "all", + "args": "none" + } + ], "no-useless-call": 2, "no-with": 2, - "object-curly-spacing": ["error", "always", { "objectsInObjects": true }], - "one-var": [2, { "initialized": "never" }], - "operator-linebreak": [0, "after", { "overrides": { "?": "before", ":": "before" } }], - "padded-blocks": [0, "never"], - "prefer-const": [2, { "destructuring": "all", "ignoreReadBeforeAssign": false }], - "quotes": [2, "single", "avoid-escape"], + "object-curly-spacing": [ + "error", + "always", + { + "objectsInObjects": true + } + ], + "one-var": [ + 2, + { + "initialized": "never" + } + ], + "operator-linebreak": [ + 0, + "after", + { + "overrides": { + "?": "before", + ":": "before" + } + } + ], + "padded-blocks": [ + 0, + "never" + ], + "prefer-const": [ + 2, + { + "destructuring": "all", + "ignoreReadBeforeAssign": false + } + ], + "quotes": [ + 2, + "single", + "avoid-escape" + ], "radix": 2, - "semi": [2, "always"], - "semi-spacing": [2, { "before": false, "after": true }], - "space-before-blocks": [2, "always"], - "space-before-function-paren": [2, { "anonymous": "never", "named": "never", "asyncArrow": "always" }], - "space-in-parens": [2, "never"], + "semi": [ + 2, + "always" + ], + "semi-spacing": [ + 2, + { + "before": false, + "after": true + } + ], + "space-before-blocks": [ + 2, + "always" + ], + "space-before-function-paren": [ + 2, + { + "anonymous": "never", + "named": "never", + "asyncArrow": "always" + } + ], + "space-in-parens": [ + 2, + "never" + ], "space-infix-ops": 2, - "space-unary-ops": [2, { "words": true, "nonwords": false }], - "spaced-comment": [0, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!", ","] }], + "space-unary-ops": [ + 2, + { + "words": true, + "nonwords": false + } + ], + "spaced-comment": [ + 0, + "always", + { + "markers": [ + "global", + "globals", + "eslint", + "eslint-disable", + "*package", + "!", + "," + ] + } + ], "strict": 2, "use-isnan": 2, "valid-typeof": 2, - "wrap-iife": [2, "any"], - "yoda": [2, "never"] + "wrap-iife": [ + 2, + "any" + ], + "yoda": [ + 2, + "never" + ] } -} +} \ No newline at end of file diff --git a/bench/first-match-minimatch.js b/bench/first-match-minimatch.js index 1a8c617..d3fd972 100644 --- a/bench/first-match-minimatch.js +++ b/bench/first-match-minimatch.js @@ -1,4 +1,3 @@ -'use strict'; const mm = require('minimatch'); diff --git a/bench/first-match-picomatch.js b/bench/first-match-picomatch.js index b803927..ea56372 100644 --- a/bench/first-match-picomatch.js +++ b/bench/first-match-picomatch.js @@ -1,6 +1,5 @@ -'use strict'; -const pm = require('..'); +const pm = require('../lib'); console.time('picomatch'); console.log(pm.makeRe('**/*').test('foo/bar/baz/qux.js')); diff --git a/bench/glob-parent.js b/bench/glob-parent.js index 2790415..d219bc9 100644 --- a/bench/glob-parent.js +++ b/bench/glob-parent.js @@ -1,4 +1,3 @@ -'use strict'; const { Suite } = require('benchmark'); const { red } = require('ansi-colors'); diff --git a/bench/index.js b/bench/index.js index cf12e43..a73c43d 100644 --- a/bench/index.js +++ b/bench/index.js @@ -1,10 +1,9 @@ -'use strict'; const { Suite } = require('benchmark'); const { red } = require('ansi-colors'); const minimist = require('minimist'); const mm = require('minimatch'); -const pm = require('..'); +const pm = require('../dist/index.cjs'); const argv = minimist(process.argv.slice(2)); diff --git a/bench/load-time.js b/bench/load-time.js index b5e5c3a..22b2ac4 100644 --- a/bench/load-time.js +++ b/bench/load-time.js @@ -1,8 +1,7 @@ -'use strict'; console.log('# Load time'); console.time('picomatch'); -exports.pm = require('..'); +exports.pm = require('../lib'); console.timeEnd('picomatch'); console.time('minimatch'); exports.mm = require('minimatch'); diff --git a/dist/index.cjs b/dist/index.cjs new file mode 100644 index 0000000..ff1ef84 --- /dev/null +++ b/dist/index.cjs @@ -0,0 +1,1510 @@ +var __create = Object.create; +var __defProp = Object.defineProperty; +var __getOwnPropDesc = Object.getOwnPropertyDescriptor; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __getProtoOf = Object.getPrototypeOf; +var __hasOwnProp = Object.prototype.hasOwnProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; +var __copyProps = (to, from, except, desc) => { + if (from && typeof from === "object" || typeof from === "function") { + for (let key of __getOwnPropNames(from)) + if (!__hasOwnProp.call(to, key) && key !== except) + __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); + } + return to; +}; +var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod)); +var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); + +// lib/index.js +var lib_exports = {}; +__export(lib_exports, { + default: () => lib_default, + utils: () => utils_exports +}); +module.exports = __toCommonJS(lib_exports); + +// lib/picomatch.js +var import_path3 = __toESM(require("path"), 1); + +// lib/utils.js +var utils_exports = {}; +__export(utils_exports, { + escapeLast: () => escapeLast, + escapeRegex: () => escapeRegex, + hasRegexChars: () => hasRegexChars, + isObject: () => isObject, + isRegexChar: () => isRegexChar, + isWindows: () => isWindows, + removeBackslashes: () => removeBackslashes, + removePrefix: () => removePrefix, + supportsLookbehinds: () => supportsLookbehinds, + toPosixSlashes: () => toPosixSlashes, + wrapOutput: () => wrapOutput +}); +var import_path2 = __toESM(require("path"), 1); + +// lib/constants.js +var constants_exports = {}; +__export(constants_exports, { + CHAR_0: () => CHAR_0, + CHAR_9: () => CHAR_9, + CHAR_AMPERSAND: () => CHAR_AMPERSAND, + CHAR_ASTERISK: () => CHAR_ASTERISK, + CHAR_AT: () => CHAR_AT, + CHAR_BACKWARD_SLASH: () => CHAR_BACKWARD_SLASH, + CHAR_CARRIAGE_RETURN: () => CHAR_CARRIAGE_RETURN, + CHAR_CIRCUMFLEX_ACCENT: () => CHAR_CIRCUMFLEX_ACCENT, + CHAR_COLON: () => CHAR_COLON, + CHAR_COMMA: () => CHAR_COMMA, + CHAR_DOT: () => CHAR_DOT, + CHAR_DOUBLE_QUOTE: () => CHAR_DOUBLE_QUOTE, + CHAR_EQUAL: () => CHAR_EQUAL, + CHAR_EXCLAMATION_MARK: () => CHAR_EXCLAMATION_MARK, + CHAR_FORM_FEED: () => CHAR_FORM_FEED, + CHAR_FORWARD_SLASH: () => CHAR_FORWARD_SLASH, + CHAR_GRAVE_ACCENT: () => CHAR_GRAVE_ACCENT, + CHAR_HASH: () => CHAR_HASH, + CHAR_HYPHEN_MINUS: () => CHAR_HYPHEN_MINUS, + CHAR_LEFT_ANGLE_BRACKET: () => CHAR_LEFT_ANGLE_BRACKET, + CHAR_LEFT_CURLY_BRACE: () => CHAR_LEFT_CURLY_BRACE, + CHAR_LEFT_PARENTHESES: () => CHAR_LEFT_PARENTHESES, + CHAR_LEFT_SQUARE_BRACKET: () => CHAR_LEFT_SQUARE_BRACKET, + CHAR_LINE_FEED: () => CHAR_LINE_FEED, + CHAR_LOWERCASE_A: () => CHAR_LOWERCASE_A, + CHAR_LOWERCASE_Z: () => CHAR_LOWERCASE_Z, + CHAR_NO_BREAK_SPACE: () => CHAR_NO_BREAK_SPACE, + CHAR_PERCENT: () => CHAR_PERCENT, + CHAR_PLUS: () => CHAR_PLUS, + CHAR_QUESTION_MARK: () => CHAR_QUESTION_MARK, + CHAR_RIGHT_ANGLE_BRACKET: () => CHAR_RIGHT_ANGLE_BRACKET, + CHAR_RIGHT_CURLY_BRACE: () => CHAR_RIGHT_CURLY_BRACE, + CHAR_RIGHT_PARENTHESES: () => CHAR_RIGHT_PARENTHESES, + CHAR_RIGHT_SQUARE_BRACKET: () => CHAR_RIGHT_SQUARE_BRACKET, + CHAR_SEMICOLON: () => CHAR_SEMICOLON, + CHAR_SINGLE_QUOTE: () => CHAR_SINGLE_QUOTE, + CHAR_SPACE: () => CHAR_SPACE, + CHAR_TAB: () => CHAR_TAB, + CHAR_UNDERSCORE: () => CHAR_UNDERSCORE, + CHAR_UPPERCASE_A: () => CHAR_UPPERCASE_A, + CHAR_UPPERCASE_Z: () => CHAR_UPPERCASE_Z, + CHAR_VERTICAL_LINE: () => CHAR_VERTICAL_LINE, + CHAR_ZERO_WIDTH_NOBREAK_SPACE: () => CHAR_ZERO_WIDTH_NOBREAK_SPACE, + DOTS_SLASH: () => DOTS_SLASH, + DOT_LITERAL: () => DOT_LITERAL, + END_ANCHOR: () => END_ANCHOR, + MAX_LENGTH: () => MAX_LENGTH, + NO_DOT: () => NO_DOT, + NO_DOTS: () => NO_DOTS, + NO_DOTS_SLASH: () => NO_DOTS_SLASH, + NO_DOT_SLASH: () => NO_DOT_SLASH, + ONE_CHAR: () => ONE_CHAR, + PLUS_LITERAL: () => PLUS_LITERAL, + POSIX_CHARS: () => POSIX_CHARS, + POSIX_REGEX_SOURCE: () => POSIX_REGEX_SOURCE, + QMARK: () => QMARK, + QMARK_LITERAL: () => QMARK_LITERAL, + QMARK_NO_DOT: () => QMARK_NO_DOT, + REGEX_BACKSLASH: () => REGEX_BACKSLASH, + REGEX_NON_SPECIAL_CHARS: () => REGEX_NON_SPECIAL_CHARS, + REGEX_REMOVE_BACKSLASH: () => REGEX_REMOVE_BACKSLASH, + REGEX_SPECIAL_CHARS: () => REGEX_SPECIAL_CHARS, + REGEX_SPECIAL_CHARS_BACKREF: () => REGEX_SPECIAL_CHARS_BACKREF, + REGEX_SPECIAL_CHARS_GLOBAL: () => REGEX_SPECIAL_CHARS_GLOBAL, + REPLACEMENTS: () => REPLACEMENTS, + SEP: () => SEP, + SLASH_LITERAL: () => SLASH_LITERAL, + STAR: () => STAR, + START_ANCHOR: () => START_ANCHOR, + WINDOWS_CHARS: () => WINDOWS_CHARS, + WIN_NO_SLASH: () => WIN_NO_SLASH, + WIN_SLASH: () => WIN_SLASH, + extglobChars: () => extglobChars, + globChars: () => globChars +}); +var import_path = __toESM(require("path"), 1); +var WIN_SLASH = "\\\\/"; +var WIN_NO_SLASH = `[^${WIN_SLASH}]`; +var DOT_LITERAL = "\\."; +var PLUS_LITERAL = "\\+"; +var QMARK_LITERAL = "\\?"; +var SLASH_LITERAL = "\\/"; +var ONE_CHAR = "(?=.)"; +var QMARK = "[^/]"; +var END_ANCHOR = `(?:${SLASH_LITERAL}|$)`; +var START_ANCHOR = `(?:^|${SLASH_LITERAL})`; +var DOTS_SLASH = `${DOT_LITERAL}{1,2}${END_ANCHOR}`; +var NO_DOT = `(?!${DOT_LITERAL})`; +var NO_DOTS = `(?!${START_ANCHOR}${DOTS_SLASH})`; +var NO_DOT_SLASH = `(?!${DOT_LITERAL}{0,1}${END_ANCHOR})`; +var NO_DOTS_SLASH = `(?!${DOTS_SLASH})`; +var QMARK_NO_DOT = `[^.${SLASH_LITERAL}]`; +var STAR = `${QMARK}*?`; +var POSIX_CHARS = { + DOT_LITERAL, + PLUS_LITERAL, + QMARK_LITERAL, + SLASH_LITERAL, + ONE_CHAR, + QMARK, + END_ANCHOR, + DOTS_SLASH, + NO_DOT, + NO_DOTS, + NO_DOT_SLASH, + NO_DOTS_SLASH, + QMARK_NO_DOT, + STAR, + START_ANCHOR +}; +var WINDOWS_CHARS = { + ...POSIX_CHARS, + SLASH_LITERAL: `[${WIN_SLASH}]`, + QMARK: WIN_NO_SLASH, + STAR: `${WIN_NO_SLASH}*?`, + DOTS_SLASH: `${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$)`, + NO_DOT: `(?!${DOT_LITERAL})`, + NO_DOTS: `(?!(?:^|[${WIN_SLASH}])${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`, + NO_DOT_SLASH: `(?!${DOT_LITERAL}{0,1}(?:[${WIN_SLASH}]|$))`, + NO_DOTS_SLASH: `(?!${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`, + QMARK_NO_DOT: `[^.${WIN_SLASH}]`, + START_ANCHOR: `(?:^|[${WIN_SLASH}])`, + END_ANCHOR: `(?:[${WIN_SLASH}]|$)` +}; +var POSIX_REGEX_SOURCE = { + alnum: "a-zA-Z0-9", + alpha: "a-zA-Z", + ascii: "\\x00-\\x7F", + blank: " \\t", + cntrl: "\\x00-\\x1F\\x7F", + digit: "0-9", + graph: "\\x21-\\x7E", + lower: "a-z", + print: "\\x20-\\x7E ", + punct: "\\-!\"#$%&'()\\*+,./:;<=>?@[\\]^_`{|}~", + space: " \\t\\r\\n\\v\\f", + upper: "A-Z", + word: "A-Za-z0-9_", + xdigit: "A-Fa-f0-9" +}; +var MAX_LENGTH = 1024 * 64; +var REGEX_BACKSLASH = /\\(?![*+?^${}(|)[\]])/g; +var REGEX_NON_SPECIAL_CHARS = /^[^@![\].,$*+?^{}()|\\/]+/; +var REGEX_SPECIAL_CHARS = /[-*+?.^${}(|)[\]]/; +var REGEX_SPECIAL_CHARS_BACKREF = /(\\?)((\W)(\3*))/g; +var REGEX_SPECIAL_CHARS_GLOBAL = /([-*+?.^${}(|)[\]])/g; +var REGEX_REMOVE_BACKSLASH = /(?:\[.*?[^\\]\]|\\(?=.))/g; +var REPLACEMENTS = { + "***": "*", + "**/**": "**", + "**/**/**": "**" +}; +var CHAR_0 = 48; +var CHAR_9 = 57; +var CHAR_UPPERCASE_A = 65; +var CHAR_LOWERCASE_A = 97; +var CHAR_UPPERCASE_Z = 90; +var CHAR_LOWERCASE_Z = 122; +var CHAR_LEFT_PARENTHESES = 40; +var CHAR_RIGHT_PARENTHESES = 41; +var CHAR_ASTERISK = 42; +var CHAR_AMPERSAND = 38; +var CHAR_AT = 64; +var CHAR_BACKWARD_SLASH = 92; +var CHAR_CARRIAGE_RETURN = 13; +var CHAR_CIRCUMFLEX_ACCENT = 94; +var CHAR_COLON = 58; +var CHAR_COMMA = 44; +var CHAR_DOT = 46; +var CHAR_DOUBLE_QUOTE = 34; +var CHAR_EQUAL = 61; +var CHAR_EXCLAMATION_MARK = 33; +var CHAR_FORM_FEED = 12; +var CHAR_FORWARD_SLASH = 47; +var CHAR_GRAVE_ACCENT = 96; +var CHAR_HASH = 35; +var CHAR_HYPHEN_MINUS = 45; +var CHAR_LEFT_ANGLE_BRACKET = 60; +var CHAR_LEFT_CURLY_BRACE = 123; +var CHAR_LEFT_SQUARE_BRACKET = 91; +var CHAR_LINE_FEED = 10; +var CHAR_NO_BREAK_SPACE = 160; +var CHAR_PERCENT = 37; +var CHAR_PLUS = 43; +var CHAR_QUESTION_MARK = 63; +var CHAR_RIGHT_ANGLE_BRACKET = 62; +var CHAR_RIGHT_CURLY_BRACE = 125; +var CHAR_RIGHT_SQUARE_BRACKET = 93; +var CHAR_SEMICOLON = 59; +var CHAR_SINGLE_QUOTE = 39; +var CHAR_SPACE = 32; +var CHAR_TAB = 9; +var CHAR_UNDERSCORE = 95; +var CHAR_VERTICAL_LINE = 124; +var CHAR_ZERO_WIDTH_NOBREAK_SPACE = 65279; +var SEP = import_path.default.sep; +var extglobChars = (chars) => { + return { + "!": { type: "negate", open: "(?:(?!(?:", close: `))${chars.STAR})` }, + "?": { type: "qmark", open: "(?:", close: ")?" }, + "+": { type: "plus", open: "(?:", close: ")+" }, + "*": { type: "star", open: "(?:", close: ")*" }, + "@": { type: "at", open: "(?:", close: ")" } + }; +}; +var globChars = (win322) => { + return win322 === true ? WINDOWS_CHARS : POSIX_CHARS; +}; + +// lib/utils.js +var win32 = process.platform === "win32"; +var isObject = (val) => val !== null && typeof val === "object" && !Array.isArray(val); +var hasRegexChars = (str) => REGEX_SPECIAL_CHARS.test(str); +var isRegexChar = (str) => str.length === 1 && hasRegexChars(str); +var escapeRegex = (str) => str.replace(REGEX_SPECIAL_CHARS_GLOBAL, "\\$1"); +var toPosixSlashes = (str) => str.replace(REGEX_BACKSLASH, "/"); +var removeBackslashes = (str) => { + return str.replace(REGEX_REMOVE_BACKSLASH, (match) => { + return match === "\\" ? "" : match; + }); +}; +var supportsLookbehinds = () => { + const segs = process.version.slice(1).split(".").map(Number); + if (segs.length === 3 && segs[0] >= 9 || segs[0] === 8 && segs[1] >= 10) { + return true; + } + return false; +}; +var isWindows = (options) => { + if (options && typeof options.windows === "boolean") { + return options.windows; + } + return win32 === true || import_path2.default.sep === "\\"; +}; +var escapeLast = (input, char, lastIdx) => { + const idx = input.lastIndexOf(char, lastIdx); + if (idx === -1) + return input; + return input[idx - 1] === "\\" ? escapeLast(input, char, idx - 1) : input.slice(0, idx) + "\\" + input.slice(idx); +}; +var removePrefix = (input, state = {}) => { + let output = input; + if (output.startsWith("./")) { + output = output.slice(2); + state.prefix = "./"; + } + return output; +}; +var wrapOutput = (input, state = {}, options = {}) => { + const prepend = options.contains ? "" : "^"; + const append = options.contains ? "" : "$"; + let output = `${prepend}(?:${input})${append}`; + if (state.negated === true) { + output = `(?:^(?!${output}).*$)`; + } + return output; +}; + +// lib/scan.js +var isPathSeparator = (code) => { + return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; +}; +var depth = (token) => { + if (token.isPrefix !== true) { + token.depth = token.isGlobstar ? Infinity : 1; + } +}; +var scan = (input, options) => { + const opts = options || {}; + const length = input.length - 1; + const scanToEnd = opts.parts === true || opts.scanToEnd === true; + const slashes = []; + const tokens = []; + const parts = []; + let str = input; + let index = -1; + let start = 0; + let lastIndex = 0; + let isBrace = false; + let isBracket = false; + let isGlob = false; + let isExtglob = false; + let isGlobstar = false; + let braceEscaped = false; + let backslashes = false; + let negated = false; + let negatedExtglob = false; + let finished = false; + let braces = 0; + let prev; + let code; + let token = { value: "", depth: 0, isGlob: false }; + const eos = () => index >= length; + const peek = () => str.charCodeAt(index + 1); + const advance = () => { + prev = code; + return str.charCodeAt(++index); + }; + while (index < length) { + code = advance(); + let next; + if (code === CHAR_BACKWARD_SLASH) { + backslashes = token.backslashes = true; + code = advance(); + if (code === CHAR_LEFT_CURLY_BRACE) { + braceEscaped = true; + } + continue; + } + if (braceEscaped === true || code === CHAR_LEFT_CURLY_BRACE) { + braces++; + while (eos() !== true && (code = advance())) { + if (code === CHAR_BACKWARD_SLASH) { + backslashes = token.backslashes = true; + advance(); + continue; + } + if (code === CHAR_LEFT_CURLY_BRACE) { + braces++; + continue; + } + if (braceEscaped !== true && code === CHAR_DOT && (code = advance()) === CHAR_DOT) { + isBrace = token.isBrace = true; + isGlob = token.isGlob = true; + finished = true; + if (scanToEnd === true) { + continue; + } + break; + } + if (braceEscaped !== true && code === CHAR_COMMA) { + isBrace = token.isBrace = true; + isGlob = token.isGlob = true; + finished = true; + if (scanToEnd === true) { + continue; + } + break; + } + if (code === CHAR_RIGHT_CURLY_BRACE) { + braces--; + if (braces === 0) { + braceEscaped = false; + isBrace = token.isBrace = true; + finished = true; + break; + } + } + } + if (scanToEnd === true) { + continue; + } + break; + } + if (code === CHAR_FORWARD_SLASH) { + slashes.push(index); + tokens.push(token); + token = { value: "", depth: 0, isGlob: false }; + if (finished === true) + continue; + if (prev === CHAR_DOT && index === start + 1) { + start += 2; + continue; + } + lastIndex = index + 1; + continue; + } + if (opts.noext !== true) { + const isExtglobChar = code === CHAR_PLUS || code === CHAR_AT || code === CHAR_ASTERISK || code === CHAR_QUESTION_MARK || code === CHAR_EXCLAMATION_MARK; + if (isExtglobChar === true && peek() === CHAR_LEFT_PARENTHESES) { + isGlob = token.isGlob = true; + isExtglob = token.isExtglob = true; + finished = true; + if (code === CHAR_EXCLAMATION_MARK && index === start) { + negatedExtglob = true; + } + if (scanToEnd === true) { + while (eos() !== true && (code = advance())) { + if (code === CHAR_BACKWARD_SLASH) { + backslashes = token.backslashes = true; + code = advance(); + continue; + } + if (code === CHAR_RIGHT_PARENTHESES) { + isGlob = token.isGlob = true; + finished = true; + break; + } + } + continue; + } + break; + } + } + if (code === CHAR_ASTERISK) { + if (prev === CHAR_ASTERISK) + isGlobstar = token.isGlobstar = true; + isGlob = token.isGlob = true; + finished = true; + if (scanToEnd === true) { + continue; + } + break; + } + if (code === CHAR_QUESTION_MARK) { + isGlob = token.isGlob = true; + finished = true; + if (scanToEnd === true) { + continue; + } + break; + } + if (code === CHAR_LEFT_SQUARE_BRACKET) { + while (eos() !== true && (next = advance())) { + if (next === CHAR_BACKWARD_SLASH) { + backslashes = token.backslashes = true; + advance(); + continue; + } + if (next === CHAR_RIGHT_SQUARE_BRACKET) { + isBracket = token.isBracket = true; + isGlob = token.isGlob = true; + finished = true; + break; + } + } + if (scanToEnd === true) { + continue; + } + break; + } + if (opts.nonegate !== true && code === CHAR_EXCLAMATION_MARK && index === start) { + negated = token.negated = true; + start++; + continue; + } + if (opts.noparen !== true && code === CHAR_LEFT_PARENTHESES) { + isGlob = token.isGlob = true; + if (scanToEnd === true) { + while (eos() !== true && (code = advance())) { + if (code === CHAR_LEFT_PARENTHESES) { + backslashes = token.backslashes = true; + code = advance(); + continue; + } + if (code === CHAR_RIGHT_PARENTHESES) { + finished = true; + break; + } + } + continue; + } + break; + } + if (isGlob === true) { + finished = true; + if (scanToEnd === true) { + continue; + } + break; + } + } + if (opts.noext === true) { + isExtglob = false; + isGlob = false; + } + let base = str; + let prefix = ""; + let glob = ""; + if (start > 0) { + prefix = str.slice(0, start); + str = str.slice(start); + lastIndex -= start; + } + if (base && isGlob === true && lastIndex > 0) { + base = str.slice(0, lastIndex); + glob = str.slice(lastIndex); + } else if (isGlob === true) { + base = ""; + glob = str; + } else { + base = str; + } + if (base && base !== "" && base !== "/" && base !== str) { + if (isPathSeparator(base.charCodeAt(base.length - 1))) { + base = base.slice(0, -1); + } + } + if (opts.unescape === true) { + if (glob) + glob = removeBackslashes(glob); + if (base && backslashes === true) { + base = removeBackslashes(base); + } + } + const state = { + prefix, + input, + start, + base, + glob, + isBrace, + isBracket, + isGlob, + isExtglob, + isGlobstar, + negated, + negatedExtglob + }; + if (opts.tokens === true) { + state.maxDepth = 0; + if (!isPathSeparator(code)) { + tokens.push(token); + } + state.tokens = tokens; + } + if (opts.parts === true || opts.tokens === true) { + let prevIndex; + for (let idx = 0; idx < slashes.length; idx++) { + const n = prevIndex ? prevIndex + 1 : start; + const i = slashes[idx]; + const value = input.slice(n, i); + if (opts.tokens) { + if (idx === 0 && start !== 0) { + tokens[idx].isPrefix = true; + tokens[idx].value = prefix; + } else { + tokens[idx].value = value; + } + depth(tokens[idx]); + state.maxDepth += tokens[idx].depth; + } + if (idx !== 0 || value !== "") { + parts.push(value); + } + prevIndex = i; + } + if (prevIndex && prevIndex + 1 < input.length) { + const value = input.slice(prevIndex + 1); + parts.push(value); + if (opts.tokens) { + tokens[tokens.length - 1].value = value; + depth(tokens[tokens.length - 1]); + state.maxDepth += tokens[tokens.length - 1].depth; + } + } + state.slashes = slashes; + state.parts = parts; + } + return state; +}; + +// lib/parse.js +var expandRange = (args, options) => { + if (typeof options.expandRange === "function") { + return options.expandRange(...args, options); + } + args.sort(); + const value = `[${args.join("-")}]`; + try { + new RegExp(value); + } catch (ex) { + return args.map((v) => escapeRegex(v)).join(".."); + } + return value; +}; +var syntaxError = (type, char) => { + return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`; +}; +var parse = (input, options) => { + if (typeof input !== "string") { + throw new TypeError("Expected a string"); + } + input = REPLACEMENTS[input] || input; + const opts = { ...options }; + const max = typeof opts.maxLength === "number" ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; + let len = input.length; + if (len > max) { + throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); + } + const bos = { type: "bos", value: "", output: opts.prepend || "" }; + const tokens = [bos]; + const capture = opts.capture ? "" : "?:"; + const win322 = isWindows(options); + const PLATFORM_CHARS = globChars(win322); + const EXTGLOB_CHARS = extglobChars(PLATFORM_CHARS); + const { + DOT_LITERAL: DOT_LITERAL2, + PLUS_LITERAL: PLUS_LITERAL2, + SLASH_LITERAL: SLASH_LITERAL2, + ONE_CHAR: ONE_CHAR2, + DOTS_SLASH: DOTS_SLASH2, + NO_DOT: NO_DOT2, + NO_DOT_SLASH: NO_DOT_SLASH2, + NO_DOTS_SLASH: NO_DOTS_SLASH2, + QMARK: QMARK2, + QMARK_NO_DOT: QMARK_NO_DOT2, + STAR: STAR2, + START_ANCHOR: START_ANCHOR2 + } = PLATFORM_CHARS; + const globstar = (opts2) => { + return `(${capture}(?:(?!${START_ANCHOR2}${opts2.dot ? DOTS_SLASH2 : DOT_LITERAL2}).)*?)`; + }; + const nodot = opts.dot ? "" : NO_DOT2; + const qmarkNoDot = opts.dot ? QMARK2 : QMARK_NO_DOT2; + let star = opts.bash === true ? globstar(opts) : STAR2; + if (opts.capture) { + star = `(${star})`; + } + if (typeof opts.noext === "boolean") { + opts.noextglob = opts.noext; + } + const state = { + input, + index: -1, + start: 0, + dot: opts.dot === true, + consumed: "", + output: "", + prefix: "", + backtrack: false, + negated: false, + brackets: 0, + braces: 0, + parens: 0, + quotes: 0, + globstar: false, + tokens + }; + input = removePrefix(input, state); + len = input.length; + const extglobs = []; + const braces = []; + const stack = []; + let prev = bos; + let value; + const eos = () => state.index === len - 1; + const peek = state.peek = (n = 1) => input[state.index + n]; + const advance = state.advance = () => input[++state.index] || ""; + const remaining = () => input.slice(state.index + 1); + const consume = (value2 = "", num = 0) => { + state.consumed += value2; + state.index += num; + }; + const append = (token) => { + state.output += token.output != null ? token.output : token.value; + consume(token.value); + }; + const negate = () => { + let count = 1; + while (peek() === "!" && (peek(2) !== "(" || peek(3) === "?")) { + advance(); + state.start++; + count++; + } + if (count % 2 === 0) { + return false; + } + state.negated = true; + state.start++; + return true; + }; + const increment = (type) => { + state[type]++; + stack.push(type); + }; + const decrement = (type) => { + state[type]--; + stack.pop(); + }; + const push = (tok) => { + if (prev.type === "globstar") { + const isBrace = state.braces > 0 && (tok.type === "comma" || tok.type === "brace"); + const isExtglob = tok.extglob === true || extglobs.length && (tok.type === "pipe" || tok.type === "paren"); + if (tok.type !== "slash" && tok.type !== "paren" && !isBrace && !isExtglob) { + state.output = state.output.slice(0, -prev.output.length); + prev.type = "star"; + prev.value = "*"; + prev.output = star; + state.output += prev.output; + } + } + if (extglobs.length && tok.type !== "paren") { + extglobs[extglobs.length - 1].inner += tok.value; + } + if (tok.value || tok.output) + append(tok); + if (prev && prev.type === "text" && tok.type === "text") { + prev.value += tok.value; + prev.output = (prev.output || "") + tok.value; + return; + } + tok.prev = prev; + tokens.push(tok); + prev = tok; + }; + const extglobOpen = (type, value2) => { + const token = { ...EXTGLOB_CHARS[value2], conditions: 1, inner: "" }; + token.prev = prev; + token.parens = state.parens; + token.output = state.output; + const output = (opts.capture ? "(" : "") + token.open; + increment("parens"); + push({ type, value: value2, output: state.output ? "" : ONE_CHAR2 }); + push({ type: "paren", extglob: true, value: advance(), output }); + extglobs.push(token); + }; + const extglobClose = (token) => { + let output = token.close + (opts.capture ? ")" : ""); + let rest; + if (token.type === "negate") { + let extglobStar = star; + if (token.inner && token.inner.length > 1 && token.inner.includes("/")) { + extglobStar = globstar(opts); + } + if (extglobStar !== star || eos() || /^\)+$/.test(remaining())) { + output = token.close = `)$))${extglobStar}`; + } + if (token.inner.includes("*") && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) { + const expression = parse(rest, { ...options, fastpaths: false }).output; + output = token.close = `)${expression})${extglobStar})`; + } + if (token.prev.type === "bos") { + state.negatedExtglob = true; + } + } + push({ type: "paren", extglob: true, value, output }); + decrement("parens"); + }; + if (opts.fastpaths !== false && !/(^[*!]|[/()[\]{}"])/.test(input)) { + let backslashes = false; + let output = input.replace(REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index) => { + if (first === "\\") { + backslashes = true; + return m; + } + if (first === "?") { + if (esc) { + return esc + first + (rest ? QMARK2.repeat(rest.length) : ""); + } + if (index === 0) { + return qmarkNoDot + (rest ? QMARK2.repeat(rest.length) : ""); + } + return QMARK2.repeat(chars.length); + } + if (first === ".") { + return DOT_LITERAL2.repeat(chars.length); + } + if (first === "*") { + if (esc) { + return esc + first + (rest ? star : ""); + } + return star; + } + return esc ? m : `\\${m}`; + }); + if (backslashes === true) { + if (opts.unescape === true) { + output = output.replace(/\\/g, ""); + } else { + output = output.replace(/\\+/g, (m) => { + return m.length % 2 === 0 ? "\\\\" : m ? "\\" : ""; + }); + } + } + if (output === input && opts.contains === true) { + state.output = input; + return state; + } + state.output = wrapOutput(output, state, options); + return state; + } + while (!eos()) { + value = advance(); + if (value === "\0") { + continue; + } + if (value === "\\") { + const next = peek(); + if (next === "/" && opts.bash !== true) { + continue; + } + if (next === "." || next === ";") { + continue; + } + if (!next) { + value += "\\"; + push({ type: "text", value }); + continue; + } + const match = /^\\+/.exec(remaining()); + let slashes = 0; + if (match && match[0].length > 2) { + slashes = match[0].length; + state.index += slashes; + if (slashes % 2 !== 0) { + value += "\\"; + } + } + if (opts.unescape === true) { + value = advance(); + } else { + value += advance(); + } + if (state.brackets === 0) { + push({ type: "text", value }); + continue; + } + } + if (state.brackets > 0 && (value !== "]" || prev.value === "[" || prev.value === "[^")) { + if (opts.posix !== false && value === ":") { + const inner = prev.value.slice(1); + if (inner.includes("[")) { + prev.posix = true; + if (inner.includes(":")) { + const idx = prev.value.lastIndexOf("["); + const pre = prev.value.slice(0, idx); + const rest2 = prev.value.slice(idx + 2); + const posix = POSIX_REGEX_SOURCE[rest2]; + if (posix) { + prev.value = pre + posix; + state.backtrack = true; + advance(); + if (!bos.output && tokens.indexOf(prev) === 1) { + bos.output = ONE_CHAR2; + } + continue; + } + } + } + } + if (value === "[" && peek() !== ":" || value === "-" && peek() === "]") { + value = `\\${value}`; + } + if (value === "]" && (prev.value === "[" || prev.value === "[^")) { + value = `\\${value}`; + } + if (opts.posix === true && value === "!" && prev.value === "[") { + value = "^"; + } + prev.value += value; + append({ value }); + continue; + } + if (state.quotes === 1 && value !== '"') { + value = escapeRegex(value); + prev.value += value; + append({ value }); + continue; + } + if (value === '"') { + state.quotes = state.quotes === 1 ? 0 : 1; + if (opts.keepQuotes === true) { + push({ type: "text", value }); + } + continue; + } + if (value === "(") { + increment("parens"); + push({ type: "paren", value }); + continue; + } + if (value === ")") { + if (state.parens === 0 && opts.strictBrackets === true) { + throw new SyntaxError(syntaxError("opening", "(")); + } + const extglob = extglobs[extglobs.length - 1]; + if (extglob && state.parens === extglob.parens + 1) { + extglobClose(extglobs.pop()); + continue; + } + push({ type: "paren", value, output: state.parens ? ")" : "\\)" }); + decrement("parens"); + continue; + } + if (value === "[") { + if (opts.nobracket === true || !remaining().includes("]")) { + if (opts.nobracket !== true && opts.strictBrackets === true) { + throw new SyntaxError(syntaxError("closing", "]")); + } + value = `\\${value}`; + } else { + increment("brackets"); + } + push({ type: "bracket", value }); + continue; + } + if (value === "]") { + if (opts.nobracket === true || prev && prev.type === "bracket" && prev.value.length === 1) { + push({ type: "text", value, output: `\\${value}` }); + continue; + } + if (state.brackets === 0) { + if (opts.strictBrackets === true) { + throw new SyntaxError(syntaxError("opening", "[")); + } + push({ type: "text", value, output: `\\${value}` }); + continue; + } + decrement("brackets"); + const prevValue = prev.value.slice(1); + if (prev.posix !== true && prevValue[0] === "^" && !prevValue.includes("/")) { + value = `/${value}`; + } + prev.value += value; + append({ value }); + if (opts.literalBrackets === false || hasRegexChars(prevValue)) { + continue; + } + const escaped = escapeRegex(prev.value); + state.output = state.output.slice(0, -prev.value.length); + if (opts.literalBrackets === true) { + state.output += escaped; + prev.value = escaped; + continue; + } + prev.value = `(${capture}${escaped}|${prev.value})`; + state.output += prev.value; + continue; + } + if (value === "{" && opts.nobrace !== true) { + increment("braces"); + const open = { + type: "brace", + value, + output: "(", + outputIndex: state.output.length, + tokensIndex: state.tokens.length + }; + braces.push(open); + push(open); + continue; + } + if (value === "}") { + const brace = braces[braces.length - 1]; + if (opts.nobrace === true || !brace) { + push({ type: "text", value, output: value }); + continue; + } + let output = ")"; + if (brace.dots === true) { + const arr = tokens.slice(); + const range = []; + for (let i = arr.length - 1; i >= 0; i--) { + tokens.pop(); + if (arr[i].type === "brace") { + break; + } + if (arr[i].type !== "dots") { + range.unshift(arr[i].value); + } + } + output = expandRange(range, opts); + state.backtrack = true; + } + if (brace.comma !== true && brace.dots !== true) { + const out = state.output.slice(0, brace.outputIndex); + const toks = state.tokens.slice(brace.tokensIndex); + brace.value = brace.output = "\\{"; + value = output = "\\}"; + state.output = out; + for (const t of toks) { + state.output += t.output || t.value; + } + } + push({ type: "brace", value, output }); + decrement("braces"); + braces.pop(); + continue; + } + if (value === "|") { + if (extglobs.length > 0) { + extglobs[extglobs.length - 1].conditions++; + } + push({ type: "text", value }); + continue; + } + if (value === ",") { + let output = value; + const brace = braces[braces.length - 1]; + if (brace && stack[stack.length - 1] === "braces") { + brace.comma = true; + output = "|"; + } + push({ type: "comma", value, output }); + continue; + } + if (value === "/") { + if (prev.type === "dot" && state.index === state.start + 1) { + state.start = state.index + 1; + state.consumed = ""; + state.output = ""; + tokens.pop(); + prev = bos; + continue; + } + push({ type: "slash", value, output: SLASH_LITERAL2 }); + continue; + } + if (value === ".") { + if (state.braces > 0 && prev.type === "dot") { + if (prev.value === ".") + prev.output = DOT_LITERAL2; + const brace = braces[braces.length - 1]; + prev.type = "dots"; + prev.output += value; + prev.value += value; + brace.dots = true; + continue; + } + if (state.braces + state.parens === 0 && prev.type !== "bos" && prev.type !== "slash") { + push({ type: "text", value, output: DOT_LITERAL2 }); + continue; + } + push({ type: "dot", value, output: DOT_LITERAL2 }); + continue; + } + if (value === "?") { + const isGroup = prev && prev.value === "("; + if (!isGroup && opts.noextglob !== true && peek() === "(" && peek(2) !== "?") { + extglobOpen("qmark", value); + continue; + } + if (prev && prev.type === "paren") { + const next = peek(); + let output = value; + if (next === "<" && !supportsLookbehinds()) { + throw new Error("Node.js v10 or higher is required for regex lookbehinds"); + } + if (prev.value === "(" && !/[!=<:]/.test(next) || next === "<" && !/<([!=]|\w+>)/.test(remaining())) { + output = `\\${value}`; + } + push({ type: "text", value, output }); + continue; + } + if (opts.dot !== true && (prev.type === "slash" || prev.type === "bos")) { + push({ type: "qmark", value, output: QMARK_NO_DOT2 }); + continue; + } + push({ type: "qmark", value, output: QMARK2 }); + continue; + } + if (value === "!") { + if (opts.noextglob !== true && peek() === "(") { + if (peek(2) !== "?" || !/[!=<:]/.test(peek(3))) { + extglobOpen("negate", value); + continue; + } + } + if (opts.nonegate !== true && state.index === 0) { + negate(); + continue; + } + } + if (value === "+") { + if (opts.noextglob !== true && peek() === "(" && peek(2) !== "?") { + extglobOpen("plus", value); + continue; + } + if (prev && prev.value === "(" || opts.regex === false) { + push({ type: "plus", value, output: PLUS_LITERAL2 }); + continue; + } + if (prev && (prev.type === "bracket" || prev.type === "paren" || prev.type === "brace") || state.parens > 0) { + push({ type: "plus", value }); + continue; + } + push({ type: "plus", value: PLUS_LITERAL2 }); + continue; + } + if (value === "@") { + if (opts.noextglob !== true && peek() === "(" && peek(2) !== "?") { + push({ type: "at", extglob: true, value, output: "" }); + continue; + } + push({ type: "text", value }); + continue; + } + if (value !== "*") { + if (value === "$" || value === "^") { + value = `\\${value}`; + } + const match = REGEX_NON_SPECIAL_CHARS.exec(remaining()); + if (match) { + value += match[0]; + state.index += match[0].length; + } + push({ type: "text", value }); + continue; + } + if (prev && (prev.type === "globstar" || prev.star === true)) { + prev.type = "star"; + prev.star = true; + prev.value += value; + prev.output = star; + state.backtrack = true; + state.globstar = true; + consume(value); + continue; + } + let rest = remaining(); + if (opts.noextglob !== true && /^\([^?]/.test(rest)) { + extglobOpen("star", value); + continue; + } + if (prev.type === "star") { + if (opts.noglobstar === true) { + consume(value); + continue; + } + const prior = prev.prev; + const before = prior.prev; + const isStart = prior.type === "slash" || prior.type === "bos"; + const afterStar = before && (before.type === "star" || before.type === "globstar"); + if (opts.bash === true && (!isStart || rest[0] && rest[0] !== "/")) { + push({ type: "star", value, output: "" }); + continue; + } + const isBrace = state.braces > 0 && (prior.type === "comma" || prior.type === "brace"); + const isExtglob = extglobs.length && (prior.type === "pipe" || prior.type === "paren"); + if (!isStart && prior.type !== "paren" && !isBrace && !isExtglob) { + push({ type: "star", value, output: "" }); + continue; + } + while (rest.slice(0, 3) === "/**") { + const after = input[state.index + 4]; + if (after && after !== "/") { + break; + } + rest = rest.slice(3); + consume("/**", 3); + } + if (prior.type === "bos" && eos()) { + prev.type = "globstar"; + prev.value += value; + prev.output = globstar(opts); + state.output = prev.output; + state.globstar = true; + consume(value); + continue; + } + if (prior.type === "slash" && prior.prev.type !== "bos" && !afterStar && eos()) { + state.output = state.output.slice(0, -(prior.output + prev.output).length); + prior.output = `(?:${prior.output}`; + prev.type = "globstar"; + prev.output = globstar(opts) + (opts.strictSlashes ? ")" : "|$)"); + prev.value += value; + state.globstar = true; + state.output += prior.output + prev.output; + consume(value); + continue; + } + if (prior.type === "slash" && prior.prev.type !== "bos" && rest[0] === "/") { + const end = rest[1] !== void 0 ? "|$" : ""; + state.output = state.output.slice(0, -(prior.output + prev.output).length); + prior.output = `(?:${prior.output}`; + prev.type = "globstar"; + prev.output = `${globstar(opts)}${SLASH_LITERAL2}|${SLASH_LITERAL2}${end})`; + prev.value += value; + state.output += prior.output + prev.output; + state.globstar = true; + consume(value + advance()); + push({ type: "slash", value: "/", output: "" }); + continue; + } + if (prior.type === "bos" && rest[0] === "/") { + prev.type = "globstar"; + prev.value += value; + prev.output = `(?:^|${SLASH_LITERAL2}|${globstar(opts)}${SLASH_LITERAL2})`; + state.output = prev.output; + state.globstar = true; + consume(value + advance()); + push({ type: "slash", value: "/", output: "" }); + continue; + } + state.output = state.output.slice(0, -prev.output.length); + prev.type = "globstar"; + prev.output = globstar(opts); + prev.value += value; + state.output += prev.output; + state.globstar = true; + consume(value); + continue; + } + const token = { type: "star", value, output: star }; + if (opts.bash === true) { + token.output = ".*?"; + if (prev.type === "bos" || prev.type === "slash") { + token.output = nodot + token.output; + } + push(token); + continue; + } + if (prev && (prev.type === "bracket" || prev.type === "paren") && opts.regex === true) { + token.output = value; + push(token); + continue; + } + if (state.index === state.start || prev.type === "slash" || prev.type === "dot") { + if (prev.type === "dot") { + state.output += NO_DOT_SLASH2; + prev.output += NO_DOT_SLASH2; + } else if (opts.dot === true) { + state.output += NO_DOTS_SLASH2; + prev.output += NO_DOTS_SLASH2; + } else { + state.output += nodot; + prev.output += nodot; + } + if (peek() !== "*") { + state.output += ONE_CHAR2; + prev.output += ONE_CHAR2; + } + } + push(token); + } + while (state.brackets > 0) { + if (opts.strictBrackets === true) + throw new SyntaxError(syntaxError("closing", "]")); + state.output = escapeLast(state.output, "["); + decrement("brackets"); + } + while (state.parens > 0) { + if (opts.strictBrackets === true) + throw new SyntaxError(syntaxError("closing", ")")); + state.output = escapeLast(state.output, "("); + decrement("parens"); + } + while (state.braces > 0) { + if (opts.strictBrackets === true) + throw new SyntaxError(syntaxError("closing", "}")); + state.output = escapeLast(state.output, "{"); + decrement("braces"); + } + if (opts.strictSlashes !== true && (prev.type === "star" || prev.type === "bracket")) { + push({ type: "maybe_slash", value: "", output: `${SLASH_LITERAL2}?` }); + } + if (state.backtrack === true) { + state.output = ""; + for (const token of state.tokens) { + state.output += token.output != null ? token.output : token.value; + if (token.suffix) { + state.output += token.suffix; + } + } + } + return state; +}; +parse.fastpaths = (input, options) => { + const opts = { ...options }; + const max = typeof opts.maxLength === "number" ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; + const len = input.length; + if (len > max) { + throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); + } + input = REPLACEMENTS[input] || input; + const win322 = isWindows(options); + const { + DOT_LITERAL: DOT_LITERAL2, + SLASH_LITERAL: SLASH_LITERAL2, + ONE_CHAR: ONE_CHAR2, + DOTS_SLASH: DOTS_SLASH2, + NO_DOT: NO_DOT2, + NO_DOTS: NO_DOTS2, + NO_DOTS_SLASH: NO_DOTS_SLASH2, + STAR: STAR2, + START_ANCHOR: START_ANCHOR2 + } = globChars(win322); + const nodot = opts.dot ? NO_DOTS2 : NO_DOT2; + const slashDot = opts.dot ? NO_DOTS_SLASH2 : NO_DOT2; + const capture = opts.capture ? "" : "?:"; + const state = { negated: false, prefix: "" }; + let star = opts.bash === true ? ".*?" : STAR2; + if (opts.capture) { + star = `(${star})`; + } + const globstar = (opts2) => { + if (opts2.noglobstar === true) + return star; + return `(${capture}(?:(?!${START_ANCHOR2}${opts2.dot ? DOTS_SLASH2 : DOT_LITERAL2}).)*?)`; + }; + const create = (str) => { + switch (str) { + case "*": + return `${nodot}${ONE_CHAR2}${star}`; + case ".*": + return `${DOT_LITERAL2}${ONE_CHAR2}${star}`; + case "*.*": + return `${nodot}${star}${DOT_LITERAL2}${ONE_CHAR2}${star}`; + case "*/*": + return `${nodot}${star}${SLASH_LITERAL2}${ONE_CHAR2}${slashDot}${star}`; + case "**": + return nodot + globstar(opts); + case "**/*": + return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL2})?${slashDot}${ONE_CHAR2}${star}`; + case "**/*.*": + return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL2})?${slashDot}${star}${DOT_LITERAL2}${ONE_CHAR2}${star}`; + case "**/.*": + return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL2})?${DOT_LITERAL2}${ONE_CHAR2}${star}`; + default: { + const match = /^(.*?)\.(\w+)$/.exec(str); + if (!match) + return; + const source2 = create(match[1]); + if (!source2) + return; + return source2 + DOT_LITERAL2 + match[2]; + } + } + }; + const output = removePrefix(input, state); + let source = create(output); + if (source && opts.strictSlashes !== true) { + source += `${SLASH_LITERAL2}?`; + } + return source; +}; + +// lib/picomatch.js +var isObject2 = (val) => val && typeof val === "object" && !Array.isArray(val); +var picomatch = (glob, options, returnState = false) => { + if (Array.isArray(glob)) { + const fns = glob.map((input) => picomatch(input, options, returnState)); + const arrayMatcher = (str) => { + for (const isMatch of fns) { + const state2 = isMatch(str); + if (state2) + return state2; + } + return false; + }; + return arrayMatcher; + } + const isState = isObject2(glob) && glob.tokens && glob.input; + if (glob === "" || typeof glob !== "string" && !isState) { + throw new TypeError("Expected pattern to be a non-empty string"); + } + const opts = options || {}; + const posix = isWindows(options); + const regex = isState ? picomatch.compileRe(glob, options) : picomatch.makeRe(glob, options, false, true); + const state = regex.state; + delete regex.state; + let isIgnored = () => false; + if (opts.ignore) { + const ignoreOpts = { ...options, ignore: null, onMatch: null, onResult: null }; + isIgnored = picomatch(opts.ignore, ignoreOpts, returnState); + } + const matcher = (input, returnObject = false) => { + const { isMatch, match, output } = picomatch.test(input, regex, options, { glob, posix }); + const result = { glob, state, regex, posix, input, output, match, isMatch }; + if (typeof opts.onResult === "function") { + opts.onResult(result); + } + if (isMatch === false) { + result.isMatch = false; + return returnObject ? result : false; + } + if (isIgnored(input)) { + if (typeof opts.onIgnore === "function") { + opts.onIgnore(result); + } + result.isMatch = false; + return returnObject ? result : false; + } + if (typeof opts.onMatch === "function") { + opts.onMatch(result); + } + return returnObject ? result : true; + }; + if (returnState) { + matcher.state = state; + } + return matcher; +}; +picomatch.test = (input, regex, options, { glob, posix } = {}) => { + if (typeof input !== "string") { + throw new TypeError("Expected input to be a string"); + } + if (input === "") { + return { isMatch: false, output: "" }; + } + const opts = options || {}; + const format = opts.format || (posix ? toPosixSlashes : null); + let match = input === glob; + let output = match && format ? format(input) : input; + if (match === false) { + output = format ? format(input) : input; + match = output === glob; + } + if (match === false || opts.capture === true) { + if (opts.matchBase === true || opts.basename === true) { + match = picomatch.matchBase(input, regex, options, posix); + } else { + match = regex.exec(output); + } + } + return { isMatch: Boolean(match), match, output }; +}; +picomatch.matchBase = (input, glob, options, posix = isWindows(options)) => { + const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options); + return regex.test(import_path3.default.basename(input)); +}; +picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str); +picomatch.parse = (pattern, options) => { + if (Array.isArray(pattern)) + return pattern.map((p) => picomatch.parse(p, options)); + return parse(pattern, { ...options, fastpaths: false }); +}; +picomatch.scan = (input, options) => scan(input, options); +picomatch.compileRe = (state, options, returnOutput = false, returnState = false) => { + if (returnOutput === true) { + return state.output; + } + const opts = options || {}; + const prepend = opts.contains ? "" : "^"; + const append = opts.contains ? "" : "$"; + let source = `${prepend}(?:${state.output})${append}`; + if (state && state.negated === true) { + source = `^(?!${source}).*$`; + } + const regex = picomatch.toRegex(source, options); + if (returnState === true) { + regex.state = state; + } + return regex; +}; +picomatch.makeRe = (input, options = {}, returnOutput = false, returnState = false) => { + if (!input || typeof input !== "string") { + throw new TypeError("Expected a non-empty string"); + } + let parsed = { negated: false, fastpaths: true }; + if (options.fastpaths !== false && (input[0] === "." || input[0] === "*")) { + parsed.output = parse.fastpaths(input, options); + } + if (!parsed.output) { + parsed = parse(input, options); + } + return picomatch.compileRe(parsed, options, returnOutput, returnState); +}; +picomatch.toRegex = (source, options) => { + try { + const opts = options || {}; + return new RegExp(source, opts.flags || (opts.nocase ? "i" : "")); + } catch (err) { + if (options && options.debug === true) + throw err; + return /$^/; + } +}; +picomatch.constants = constants_exports; +var picomatch_default = picomatch; + +// lib/index.js +var lib_default = picomatch_default; +// Annotate the CommonJS export names for ESM import in node: +0 && (module.exports = { + utils +}); diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..77b3554 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,1487 @@ +var __defProp = Object.defineProperty; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; + +// lib/picomatch.js +import path3 from "path"; + +// lib/utils.js +var utils_exports = {}; +__export(utils_exports, { + escapeLast: () => escapeLast, + escapeRegex: () => escapeRegex, + hasRegexChars: () => hasRegexChars, + isObject: () => isObject, + isRegexChar: () => isRegexChar, + isWindows: () => isWindows, + removeBackslashes: () => removeBackslashes, + removePrefix: () => removePrefix, + supportsLookbehinds: () => supportsLookbehinds, + toPosixSlashes: () => toPosixSlashes, + wrapOutput: () => wrapOutput +}); +import path2 from "path"; + +// lib/constants.js +var constants_exports = {}; +__export(constants_exports, { + CHAR_0: () => CHAR_0, + CHAR_9: () => CHAR_9, + CHAR_AMPERSAND: () => CHAR_AMPERSAND, + CHAR_ASTERISK: () => CHAR_ASTERISK, + CHAR_AT: () => CHAR_AT, + CHAR_BACKWARD_SLASH: () => CHAR_BACKWARD_SLASH, + CHAR_CARRIAGE_RETURN: () => CHAR_CARRIAGE_RETURN, + CHAR_CIRCUMFLEX_ACCENT: () => CHAR_CIRCUMFLEX_ACCENT, + CHAR_COLON: () => CHAR_COLON, + CHAR_COMMA: () => CHAR_COMMA, + CHAR_DOT: () => CHAR_DOT, + CHAR_DOUBLE_QUOTE: () => CHAR_DOUBLE_QUOTE, + CHAR_EQUAL: () => CHAR_EQUAL, + CHAR_EXCLAMATION_MARK: () => CHAR_EXCLAMATION_MARK, + CHAR_FORM_FEED: () => CHAR_FORM_FEED, + CHAR_FORWARD_SLASH: () => CHAR_FORWARD_SLASH, + CHAR_GRAVE_ACCENT: () => CHAR_GRAVE_ACCENT, + CHAR_HASH: () => CHAR_HASH, + CHAR_HYPHEN_MINUS: () => CHAR_HYPHEN_MINUS, + CHAR_LEFT_ANGLE_BRACKET: () => CHAR_LEFT_ANGLE_BRACKET, + CHAR_LEFT_CURLY_BRACE: () => CHAR_LEFT_CURLY_BRACE, + CHAR_LEFT_PARENTHESES: () => CHAR_LEFT_PARENTHESES, + CHAR_LEFT_SQUARE_BRACKET: () => CHAR_LEFT_SQUARE_BRACKET, + CHAR_LINE_FEED: () => CHAR_LINE_FEED, + CHAR_LOWERCASE_A: () => CHAR_LOWERCASE_A, + CHAR_LOWERCASE_Z: () => CHAR_LOWERCASE_Z, + CHAR_NO_BREAK_SPACE: () => CHAR_NO_BREAK_SPACE, + CHAR_PERCENT: () => CHAR_PERCENT, + CHAR_PLUS: () => CHAR_PLUS, + CHAR_QUESTION_MARK: () => CHAR_QUESTION_MARK, + CHAR_RIGHT_ANGLE_BRACKET: () => CHAR_RIGHT_ANGLE_BRACKET, + CHAR_RIGHT_CURLY_BRACE: () => CHAR_RIGHT_CURLY_BRACE, + CHAR_RIGHT_PARENTHESES: () => CHAR_RIGHT_PARENTHESES, + CHAR_RIGHT_SQUARE_BRACKET: () => CHAR_RIGHT_SQUARE_BRACKET, + CHAR_SEMICOLON: () => CHAR_SEMICOLON, + CHAR_SINGLE_QUOTE: () => CHAR_SINGLE_QUOTE, + CHAR_SPACE: () => CHAR_SPACE, + CHAR_TAB: () => CHAR_TAB, + CHAR_UNDERSCORE: () => CHAR_UNDERSCORE, + CHAR_UPPERCASE_A: () => CHAR_UPPERCASE_A, + CHAR_UPPERCASE_Z: () => CHAR_UPPERCASE_Z, + CHAR_VERTICAL_LINE: () => CHAR_VERTICAL_LINE, + CHAR_ZERO_WIDTH_NOBREAK_SPACE: () => CHAR_ZERO_WIDTH_NOBREAK_SPACE, + DOTS_SLASH: () => DOTS_SLASH, + DOT_LITERAL: () => DOT_LITERAL, + END_ANCHOR: () => END_ANCHOR, + MAX_LENGTH: () => MAX_LENGTH, + NO_DOT: () => NO_DOT, + NO_DOTS: () => NO_DOTS, + NO_DOTS_SLASH: () => NO_DOTS_SLASH, + NO_DOT_SLASH: () => NO_DOT_SLASH, + ONE_CHAR: () => ONE_CHAR, + PLUS_LITERAL: () => PLUS_LITERAL, + POSIX_CHARS: () => POSIX_CHARS, + POSIX_REGEX_SOURCE: () => POSIX_REGEX_SOURCE, + QMARK: () => QMARK, + QMARK_LITERAL: () => QMARK_LITERAL, + QMARK_NO_DOT: () => QMARK_NO_DOT, + REGEX_BACKSLASH: () => REGEX_BACKSLASH, + REGEX_NON_SPECIAL_CHARS: () => REGEX_NON_SPECIAL_CHARS, + REGEX_REMOVE_BACKSLASH: () => REGEX_REMOVE_BACKSLASH, + REGEX_SPECIAL_CHARS: () => REGEX_SPECIAL_CHARS, + REGEX_SPECIAL_CHARS_BACKREF: () => REGEX_SPECIAL_CHARS_BACKREF, + REGEX_SPECIAL_CHARS_GLOBAL: () => REGEX_SPECIAL_CHARS_GLOBAL, + REPLACEMENTS: () => REPLACEMENTS, + SEP: () => SEP, + SLASH_LITERAL: () => SLASH_LITERAL, + STAR: () => STAR, + START_ANCHOR: () => START_ANCHOR, + WINDOWS_CHARS: () => WINDOWS_CHARS, + WIN_NO_SLASH: () => WIN_NO_SLASH, + WIN_SLASH: () => WIN_SLASH, + extglobChars: () => extglobChars, + globChars: () => globChars +}); +import path from "path"; +var WIN_SLASH = "\\\\/"; +var WIN_NO_SLASH = `[^${WIN_SLASH}]`; +var DOT_LITERAL = "\\."; +var PLUS_LITERAL = "\\+"; +var QMARK_LITERAL = "\\?"; +var SLASH_LITERAL = "\\/"; +var ONE_CHAR = "(?=.)"; +var QMARK = "[^/]"; +var END_ANCHOR = `(?:${SLASH_LITERAL}|$)`; +var START_ANCHOR = `(?:^|${SLASH_LITERAL})`; +var DOTS_SLASH = `${DOT_LITERAL}{1,2}${END_ANCHOR}`; +var NO_DOT = `(?!${DOT_LITERAL})`; +var NO_DOTS = `(?!${START_ANCHOR}${DOTS_SLASH})`; +var NO_DOT_SLASH = `(?!${DOT_LITERAL}{0,1}${END_ANCHOR})`; +var NO_DOTS_SLASH = `(?!${DOTS_SLASH})`; +var QMARK_NO_DOT = `[^.${SLASH_LITERAL}]`; +var STAR = `${QMARK}*?`; +var POSIX_CHARS = { + DOT_LITERAL, + PLUS_LITERAL, + QMARK_LITERAL, + SLASH_LITERAL, + ONE_CHAR, + QMARK, + END_ANCHOR, + DOTS_SLASH, + NO_DOT, + NO_DOTS, + NO_DOT_SLASH, + NO_DOTS_SLASH, + QMARK_NO_DOT, + STAR, + START_ANCHOR +}; +var WINDOWS_CHARS = { + ...POSIX_CHARS, + SLASH_LITERAL: `[${WIN_SLASH}]`, + QMARK: WIN_NO_SLASH, + STAR: `${WIN_NO_SLASH}*?`, + DOTS_SLASH: `${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$)`, + NO_DOT: `(?!${DOT_LITERAL})`, + NO_DOTS: `(?!(?:^|[${WIN_SLASH}])${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`, + NO_DOT_SLASH: `(?!${DOT_LITERAL}{0,1}(?:[${WIN_SLASH}]|$))`, + NO_DOTS_SLASH: `(?!${DOT_LITERAL}{1,2}(?:[${WIN_SLASH}]|$))`, + QMARK_NO_DOT: `[^.${WIN_SLASH}]`, + START_ANCHOR: `(?:^|[${WIN_SLASH}])`, + END_ANCHOR: `(?:[${WIN_SLASH}]|$)` +}; +var POSIX_REGEX_SOURCE = { + alnum: "a-zA-Z0-9", + alpha: "a-zA-Z", + ascii: "\\x00-\\x7F", + blank: " \\t", + cntrl: "\\x00-\\x1F\\x7F", + digit: "0-9", + graph: "\\x21-\\x7E", + lower: "a-z", + print: "\\x20-\\x7E ", + punct: "\\-!\"#$%&'()\\*+,./:;<=>?@[\\]^_`{|}~", + space: " \\t\\r\\n\\v\\f", + upper: "A-Z", + word: "A-Za-z0-9_", + xdigit: "A-Fa-f0-9" +}; +var MAX_LENGTH = 1024 * 64; +var REGEX_BACKSLASH = /\\(?![*+?^${}(|)[\]])/g; +var REGEX_NON_SPECIAL_CHARS = /^[^@![\].,$*+?^{}()|\\/]+/; +var REGEX_SPECIAL_CHARS = /[-*+?.^${}(|)[\]]/; +var REGEX_SPECIAL_CHARS_BACKREF = /(\\?)((\W)(\3*))/g; +var REGEX_SPECIAL_CHARS_GLOBAL = /([-*+?.^${}(|)[\]])/g; +var REGEX_REMOVE_BACKSLASH = /(?:\[.*?[^\\]\]|\\(?=.))/g; +var REPLACEMENTS = { + "***": "*", + "**/**": "**", + "**/**/**": "**" +}; +var CHAR_0 = 48; +var CHAR_9 = 57; +var CHAR_UPPERCASE_A = 65; +var CHAR_LOWERCASE_A = 97; +var CHAR_UPPERCASE_Z = 90; +var CHAR_LOWERCASE_Z = 122; +var CHAR_LEFT_PARENTHESES = 40; +var CHAR_RIGHT_PARENTHESES = 41; +var CHAR_ASTERISK = 42; +var CHAR_AMPERSAND = 38; +var CHAR_AT = 64; +var CHAR_BACKWARD_SLASH = 92; +var CHAR_CARRIAGE_RETURN = 13; +var CHAR_CIRCUMFLEX_ACCENT = 94; +var CHAR_COLON = 58; +var CHAR_COMMA = 44; +var CHAR_DOT = 46; +var CHAR_DOUBLE_QUOTE = 34; +var CHAR_EQUAL = 61; +var CHAR_EXCLAMATION_MARK = 33; +var CHAR_FORM_FEED = 12; +var CHAR_FORWARD_SLASH = 47; +var CHAR_GRAVE_ACCENT = 96; +var CHAR_HASH = 35; +var CHAR_HYPHEN_MINUS = 45; +var CHAR_LEFT_ANGLE_BRACKET = 60; +var CHAR_LEFT_CURLY_BRACE = 123; +var CHAR_LEFT_SQUARE_BRACKET = 91; +var CHAR_LINE_FEED = 10; +var CHAR_NO_BREAK_SPACE = 160; +var CHAR_PERCENT = 37; +var CHAR_PLUS = 43; +var CHAR_QUESTION_MARK = 63; +var CHAR_RIGHT_ANGLE_BRACKET = 62; +var CHAR_RIGHT_CURLY_BRACE = 125; +var CHAR_RIGHT_SQUARE_BRACKET = 93; +var CHAR_SEMICOLON = 59; +var CHAR_SINGLE_QUOTE = 39; +var CHAR_SPACE = 32; +var CHAR_TAB = 9; +var CHAR_UNDERSCORE = 95; +var CHAR_VERTICAL_LINE = 124; +var CHAR_ZERO_WIDTH_NOBREAK_SPACE = 65279; +var SEP = path.sep; +var extglobChars = (chars) => { + return { + "!": { type: "negate", open: "(?:(?!(?:", close: `))${chars.STAR})` }, + "?": { type: "qmark", open: "(?:", close: ")?" }, + "+": { type: "plus", open: "(?:", close: ")+" }, + "*": { type: "star", open: "(?:", close: ")*" }, + "@": { type: "at", open: "(?:", close: ")" } + }; +}; +var globChars = (win322) => { + return win322 === true ? WINDOWS_CHARS : POSIX_CHARS; +}; + +// lib/utils.js +var win32 = process.platform === "win32"; +var isObject = (val) => val !== null && typeof val === "object" && !Array.isArray(val); +var hasRegexChars = (str) => REGEX_SPECIAL_CHARS.test(str); +var isRegexChar = (str) => str.length === 1 && hasRegexChars(str); +var escapeRegex = (str) => str.replace(REGEX_SPECIAL_CHARS_GLOBAL, "\\$1"); +var toPosixSlashes = (str) => str.replace(REGEX_BACKSLASH, "/"); +var removeBackslashes = (str) => { + return str.replace(REGEX_REMOVE_BACKSLASH, (match) => { + return match === "\\" ? "" : match; + }); +}; +var supportsLookbehinds = () => { + const segs = process.version.slice(1).split(".").map(Number); + if (segs.length === 3 && segs[0] >= 9 || segs[0] === 8 && segs[1] >= 10) { + return true; + } + return false; +}; +var isWindows = (options) => { + if (options && typeof options.windows === "boolean") { + return options.windows; + } + return win32 === true || path2.sep === "\\"; +}; +var escapeLast = (input, char, lastIdx) => { + const idx = input.lastIndexOf(char, lastIdx); + if (idx === -1) + return input; + return input[idx - 1] === "\\" ? escapeLast(input, char, idx - 1) : input.slice(0, idx) + "\\" + input.slice(idx); +}; +var removePrefix = (input, state = {}) => { + let output = input; + if (output.startsWith("./")) { + output = output.slice(2); + state.prefix = "./"; + } + return output; +}; +var wrapOutput = (input, state = {}, options = {}) => { + const prepend = options.contains ? "" : "^"; + const append = options.contains ? "" : "$"; + let output = `${prepend}(?:${input})${append}`; + if (state.negated === true) { + output = `(?:^(?!${output}).*$)`; + } + return output; +}; + +// lib/scan.js +var isPathSeparator = (code) => { + return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; +}; +var depth = (token) => { + if (token.isPrefix !== true) { + token.depth = token.isGlobstar ? Infinity : 1; + } +}; +var scan = (input, options) => { + const opts = options || {}; + const length = input.length - 1; + const scanToEnd = opts.parts === true || opts.scanToEnd === true; + const slashes = []; + const tokens = []; + const parts = []; + let str = input; + let index = -1; + let start = 0; + let lastIndex = 0; + let isBrace = false; + let isBracket = false; + let isGlob = false; + let isExtglob = false; + let isGlobstar = false; + let braceEscaped = false; + let backslashes = false; + let negated = false; + let negatedExtglob = false; + let finished = false; + let braces = 0; + let prev; + let code; + let token = { value: "", depth: 0, isGlob: false }; + const eos = () => index >= length; + const peek = () => str.charCodeAt(index + 1); + const advance = () => { + prev = code; + return str.charCodeAt(++index); + }; + while (index < length) { + code = advance(); + let next; + if (code === CHAR_BACKWARD_SLASH) { + backslashes = token.backslashes = true; + code = advance(); + if (code === CHAR_LEFT_CURLY_BRACE) { + braceEscaped = true; + } + continue; + } + if (braceEscaped === true || code === CHAR_LEFT_CURLY_BRACE) { + braces++; + while (eos() !== true && (code = advance())) { + if (code === CHAR_BACKWARD_SLASH) { + backslashes = token.backslashes = true; + advance(); + continue; + } + if (code === CHAR_LEFT_CURLY_BRACE) { + braces++; + continue; + } + if (braceEscaped !== true && code === CHAR_DOT && (code = advance()) === CHAR_DOT) { + isBrace = token.isBrace = true; + isGlob = token.isGlob = true; + finished = true; + if (scanToEnd === true) { + continue; + } + break; + } + if (braceEscaped !== true && code === CHAR_COMMA) { + isBrace = token.isBrace = true; + isGlob = token.isGlob = true; + finished = true; + if (scanToEnd === true) { + continue; + } + break; + } + if (code === CHAR_RIGHT_CURLY_BRACE) { + braces--; + if (braces === 0) { + braceEscaped = false; + isBrace = token.isBrace = true; + finished = true; + break; + } + } + } + if (scanToEnd === true) { + continue; + } + break; + } + if (code === CHAR_FORWARD_SLASH) { + slashes.push(index); + tokens.push(token); + token = { value: "", depth: 0, isGlob: false }; + if (finished === true) + continue; + if (prev === CHAR_DOT && index === start + 1) { + start += 2; + continue; + } + lastIndex = index + 1; + continue; + } + if (opts.noext !== true) { + const isExtglobChar = code === CHAR_PLUS || code === CHAR_AT || code === CHAR_ASTERISK || code === CHAR_QUESTION_MARK || code === CHAR_EXCLAMATION_MARK; + if (isExtglobChar === true && peek() === CHAR_LEFT_PARENTHESES) { + isGlob = token.isGlob = true; + isExtglob = token.isExtglob = true; + finished = true; + if (code === CHAR_EXCLAMATION_MARK && index === start) { + negatedExtglob = true; + } + if (scanToEnd === true) { + while (eos() !== true && (code = advance())) { + if (code === CHAR_BACKWARD_SLASH) { + backslashes = token.backslashes = true; + code = advance(); + continue; + } + if (code === CHAR_RIGHT_PARENTHESES) { + isGlob = token.isGlob = true; + finished = true; + break; + } + } + continue; + } + break; + } + } + if (code === CHAR_ASTERISK) { + if (prev === CHAR_ASTERISK) + isGlobstar = token.isGlobstar = true; + isGlob = token.isGlob = true; + finished = true; + if (scanToEnd === true) { + continue; + } + break; + } + if (code === CHAR_QUESTION_MARK) { + isGlob = token.isGlob = true; + finished = true; + if (scanToEnd === true) { + continue; + } + break; + } + if (code === CHAR_LEFT_SQUARE_BRACKET) { + while (eos() !== true && (next = advance())) { + if (next === CHAR_BACKWARD_SLASH) { + backslashes = token.backslashes = true; + advance(); + continue; + } + if (next === CHAR_RIGHT_SQUARE_BRACKET) { + isBracket = token.isBracket = true; + isGlob = token.isGlob = true; + finished = true; + break; + } + } + if (scanToEnd === true) { + continue; + } + break; + } + if (opts.nonegate !== true && code === CHAR_EXCLAMATION_MARK && index === start) { + negated = token.negated = true; + start++; + continue; + } + if (opts.noparen !== true && code === CHAR_LEFT_PARENTHESES) { + isGlob = token.isGlob = true; + if (scanToEnd === true) { + while (eos() !== true && (code = advance())) { + if (code === CHAR_LEFT_PARENTHESES) { + backslashes = token.backslashes = true; + code = advance(); + continue; + } + if (code === CHAR_RIGHT_PARENTHESES) { + finished = true; + break; + } + } + continue; + } + break; + } + if (isGlob === true) { + finished = true; + if (scanToEnd === true) { + continue; + } + break; + } + } + if (opts.noext === true) { + isExtglob = false; + isGlob = false; + } + let base = str; + let prefix = ""; + let glob = ""; + if (start > 0) { + prefix = str.slice(0, start); + str = str.slice(start); + lastIndex -= start; + } + if (base && isGlob === true && lastIndex > 0) { + base = str.slice(0, lastIndex); + glob = str.slice(lastIndex); + } else if (isGlob === true) { + base = ""; + glob = str; + } else { + base = str; + } + if (base && base !== "" && base !== "/" && base !== str) { + if (isPathSeparator(base.charCodeAt(base.length - 1))) { + base = base.slice(0, -1); + } + } + if (opts.unescape === true) { + if (glob) + glob = removeBackslashes(glob); + if (base && backslashes === true) { + base = removeBackslashes(base); + } + } + const state = { + prefix, + input, + start, + base, + glob, + isBrace, + isBracket, + isGlob, + isExtglob, + isGlobstar, + negated, + negatedExtglob + }; + if (opts.tokens === true) { + state.maxDepth = 0; + if (!isPathSeparator(code)) { + tokens.push(token); + } + state.tokens = tokens; + } + if (opts.parts === true || opts.tokens === true) { + let prevIndex; + for (let idx = 0; idx < slashes.length; idx++) { + const n = prevIndex ? prevIndex + 1 : start; + const i = slashes[idx]; + const value = input.slice(n, i); + if (opts.tokens) { + if (idx === 0 && start !== 0) { + tokens[idx].isPrefix = true; + tokens[idx].value = prefix; + } else { + tokens[idx].value = value; + } + depth(tokens[idx]); + state.maxDepth += tokens[idx].depth; + } + if (idx !== 0 || value !== "") { + parts.push(value); + } + prevIndex = i; + } + if (prevIndex && prevIndex + 1 < input.length) { + const value = input.slice(prevIndex + 1); + parts.push(value); + if (opts.tokens) { + tokens[tokens.length - 1].value = value; + depth(tokens[tokens.length - 1]); + state.maxDepth += tokens[tokens.length - 1].depth; + } + } + state.slashes = slashes; + state.parts = parts; + } + return state; +}; + +// lib/parse.js +var expandRange = (args, options) => { + if (typeof options.expandRange === "function") { + return options.expandRange(...args, options); + } + args.sort(); + const value = `[${args.join("-")}]`; + try { + new RegExp(value); + } catch (ex) { + return args.map((v) => escapeRegex(v)).join(".."); + } + return value; +}; +var syntaxError = (type, char) => { + return `Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`; +}; +var parse = (input, options) => { + if (typeof input !== "string") { + throw new TypeError("Expected a string"); + } + input = REPLACEMENTS[input] || input; + const opts = { ...options }; + const max = typeof opts.maxLength === "number" ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; + let len = input.length; + if (len > max) { + throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); + } + const bos = { type: "bos", value: "", output: opts.prepend || "" }; + const tokens = [bos]; + const capture = opts.capture ? "" : "?:"; + const win322 = isWindows(options); + const PLATFORM_CHARS = globChars(win322); + const EXTGLOB_CHARS = extglobChars(PLATFORM_CHARS); + const { + DOT_LITERAL: DOT_LITERAL2, + PLUS_LITERAL: PLUS_LITERAL2, + SLASH_LITERAL: SLASH_LITERAL2, + ONE_CHAR: ONE_CHAR2, + DOTS_SLASH: DOTS_SLASH2, + NO_DOT: NO_DOT2, + NO_DOT_SLASH: NO_DOT_SLASH2, + NO_DOTS_SLASH: NO_DOTS_SLASH2, + QMARK: QMARK2, + QMARK_NO_DOT: QMARK_NO_DOT2, + STAR: STAR2, + START_ANCHOR: START_ANCHOR2 + } = PLATFORM_CHARS; + const globstar = (opts2) => { + return `(${capture}(?:(?!${START_ANCHOR2}${opts2.dot ? DOTS_SLASH2 : DOT_LITERAL2}).)*?)`; + }; + const nodot = opts.dot ? "" : NO_DOT2; + const qmarkNoDot = opts.dot ? QMARK2 : QMARK_NO_DOT2; + let star = opts.bash === true ? globstar(opts) : STAR2; + if (opts.capture) { + star = `(${star})`; + } + if (typeof opts.noext === "boolean") { + opts.noextglob = opts.noext; + } + const state = { + input, + index: -1, + start: 0, + dot: opts.dot === true, + consumed: "", + output: "", + prefix: "", + backtrack: false, + negated: false, + brackets: 0, + braces: 0, + parens: 0, + quotes: 0, + globstar: false, + tokens + }; + input = removePrefix(input, state); + len = input.length; + const extglobs = []; + const braces = []; + const stack = []; + let prev = bos; + let value; + const eos = () => state.index === len - 1; + const peek = state.peek = (n = 1) => input[state.index + n]; + const advance = state.advance = () => input[++state.index] || ""; + const remaining = () => input.slice(state.index + 1); + const consume = (value2 = "", num = 0) => { + state.consumed += value2; + state.index += num; + }; + const append = (token) => { + state.output += token.output != null ? token.output : token.value; + consume(token.value); + }; + const negate = () => { + let count = 1; + while (peek() === "!" && (peek(2) !== "(" || peek(3) === "?")) { + advance(); + state.start++; + count++; + } + if (count % 2 === 0) { + return false; + } + state.negated = true; + state.start++; + return true; + }; + const increment = (type) => { + state[type]++; + stack.push(type); + }; + const decrement = (type) => { + state[type]--; + stack.pop(); + }; + const push = (tok) => { + if (prev.type === "globstar") { + const isBrace = state.braces > 0 && (tok.type === "comma" || tok.type === "brace"); + const isExtglob = tok.extglob === true || extglobs.length && (tok.type === "pipe" || tok.type === "paren"); + if (tok.type !== "slash" && tok.type !== "paren" && !isBrace && !isExtglob) { + state.output = state.output.slice(0, -prev.output.length); + prev.type = "star"; + prev.value = "*"; + prev.output = star; + state.output += prev.output; + } + } + if (extglobs.length && tok.type !== "paren") { + extglobs[extglobs.length - 1].inner += tok.value; + } + if (tok.value || tok.output) + append(tok); + if (prev && prev.type === "text" && tok.type === "text") { + prev.value += tok.value; + prev.output = (prev.output || "") + tok.value; + return; + } + tok.prev = prev; + tokens.push(tok); + prev = tok; + }; + const extglobOpen = (type, value2) => { + const token = { ...EXTGLOB_CHARS[value2], conditions: 1, inner: "" }; + token.prev = prev; + token.parens = state.parens; + token.output = state.output; + const output = (opts.capture ? "(" : "") + token.open; + increment("parens"); + push({ type, value: value2, output: state.output ? "" : ONE_CHAR2 }); + push({ type: "paren", extglob: true, value: advance(), output }); + extglobs.push(token); + }; + const extglobClose = (token) => { + let output = token.close + (opts.capture ? ")" : ""); + let rest; + if (token.type === "negate") { + let extglobStar = star; + if (token.inner && token.inner.length > 1 && token.inner.includes("/")) { + extglobStar = globstar(opts); + } + if (extglobStar !== star || eos() || /^\)+$/.test(remaining())) { + output = token.close = `)$))${extglobStar}`; + } + if (token.inner.includes("*") && (rest = remaining()) && /^\.[^\\/.]+$/.test(rest)) { + const expression = parse(rest, { ...options, fastpaths: false }).output; + output = token.close = `)${expression})${extglobStar})`; + } + if (token.prev.type === "bos") { + state.negatedExtglob = true; + } + } + push({ type: "paren", extglob: true, value, output }); + decrement("parens"); + }; + if (opts.fastpaths !== false && !/(^[*!]|[/()[\]{}"])/.test(input)) { + let backslashes = false; + let output = input.replace(REGEX_SPECIAL_CHARS_BACKREF, (m, esc, chars, first, rest, index) => { + if (first === "\\") { + backslashes = true; + return m; + } + if (first === "?") { + if (esc) { + return esc + first + (rest ? QMARK2.repeat(rest.length) : ""); + } + if (index === 0) { + return qmarkNoDot + (rest ? QMARK2.repeat(rest.length) : ""); + } + return QMARK2.repeat(chars.length); + } + if (first === ".") { + return DOT_LITERAL2.repeat(chars.length); + } + if (first === "*") { + if (esc) { + return esc + first + (rest ? star : ""); + } + return star; + } + return esc ? m : `\\${m}`; + }); + if (backslashes === true) { + if (opts.unescape === true) { + output = output.replace(/\\/g, ""); + } else { + output = output.replace(/\\+/g, (m) => { + return m.length % 2 === 0 ? "\\\\" : m ? "\\" : ""; + }); + } + } + if (output === input && opts.contains === true) { + state.output = input; + return state; + } + state.output = wrapOutput(output, state, options); + return state; + } + while (!eos()) { + value = advance(); + if (value === "\0") { + continue; + } + if (value === "\\") { + const next = peek(); + if (next === "/" && opts.bash !== true) { + continue; + } + if (next === "." || next === ";") { + continue; + } + if (!next) { + value += "\\"; + push({ type: "text", value }); + continue; + } + const match = /^\\+/.exec(remaining()); + let slashes = 0; + if (match && match[0].length > 2) { + slashes = match[0].length; + state.index += slashes; + if (slashes % 2 !== 0) { + value += "\\"; + } + } + if (opts.unescape === true) { + value = advance(); + } else { + value += advance(); + } + if (state.brackets === 0) { + push({ type: "text", value }); + continue; + } + } + if (state.brackets > 0 && (value !== "]" || prev.value === "[" || prev.value === "[^")) { + if (opts.posix !== false && value === ":") { + const inner = prev.value.slice(1); + if (inner.includes("[")) { + prev.posix = true; + if (inner.includes(":")) { + const idx = prev.value.lastIndexOf("["); + const pre = prev.value.slice(0, idx); + const rest2 = prev.value.slice(idx + 2); + const posix = POSIX_REGEX_SOURCE[rest2]; + if (posix) { + prev.value = pre + posix; + state.backtrack = true; + advance(); + if (!bos.output && tokens.indexOf(prev) === 1) { + bos.output = ONE_CHAR2; + } + continue; + } + } + } + } + if (value === "[" && peek() !== ":" || value === "-" && peek() === "]") { + value = `\\${value}`; + } + if (value === "]" && (prev.value === "[" || prev.value === "[^")) { + value = `\\${value}`; + } + if (opts.posix === true && value === "!" && prev.value === "[") { + value = "^"; + } + prev.value += value; + append({ value }); + continue; + } + if (state.quotes === 1 && value !== '"') { + value = escapeRegex(value); + prev.value += value; + append({ value }); + continue; + } + if (value === '"') { + state.quotes = state.quotes === 1 ? 0 : 1; + if (opts.keepQuotes === true) { + push({ type: "text", value }); + } + continue; + } + if (value === "(") { + increment("parens"); + push({ type: "paren", value }); + continue; + } + if (value === ")") { + if (state.parens === 0 && opts.strictBrackets === true) { + throw new SyntaxError(syntaxError("opening", "(")); + } + const extglob = extglobs[extglobs.length - 1]; + if (extglob && state.parens === extglob.parens + 1) { + extglobClose(extglobs.pop()); + continue; + } + push({ type: "paren", value, output: state.parens ? ")" : "\\)" }); + decrement("parens"); + continue; + } + if (value === "[") { + if (opts.nobracket === true || !remaining().includes("]")) { + if (opts.nobracket !== true && opts.strictBrackets === true) { + throw new SyntaxError(syntaxError("closing", "]")); + } + value = `\\${value}`; + } else { + increment("brackets"); + } + push({ type: "bracket", value }); + continue; + } + if (value === "]") { + if (opts.nobracket === true || prev && prev.type === "bracket" && prev.value.length === 1) { + push({ type: "text", value, output: `\\${value}` }); + continue; + } + if (state.brackets === 0) { + if (opts.strictBrackets === true) { + throw new SyntaxError(syntaxError("opening", "[")); + } + push({ type: "text", value, output: `\\${value}` }); + continue; + } + decrement("brackets"); + const prevValue = prev.value.slice(1); + if (prev.posix !== true && prevValue[0] === "^" && !prevValue.includes("/")) { + value = `/${value}`; + } + prev.value += value; + append({ value }); + if (opts.literalBrackets === false || hasRegexChars(prevValue)) { + continue; + } + const escaped = escapeRegex(prev.value); + state.output = state.output.slice(0, -prev.value.length); + if (opts.literalBrackets === true) { + state.output += escaped; + prev.value = escaped; + continue; + } + prev.value = `(${capture}${escaped}|${prev.value})`; + state.output += prev.value; + continue; + } + if (value === "{" && opts.nobrace !== true) { + increment("braces"); + const open = { + type: "brace", + value, + output: "(", + outputIndex: state.output.length, + tokensIndex: state.tokens.length + }; + braces.push(open); + push(open); + continue; + } + if (value === "}") { + const brace = braces[braces.length - 1]; + if (opts.nobrace === true || !brace) { + push({ type: "text", value, output: value }); + continue; + } + let output = ")"; + if (brace.dots === true) { + const arr = tokens.slice(); + const range = []; + for (let i = arr.length - 1; i >= 0; i--) { + tokens.pop(); + if (arr[i].type === "brace") { + break; + } + if (arr[i].type !== "dots") { + range.unshift(arr[i].value); + } + } + output = expandRange(range, opts); + state.backtrack = true; + } + if (brace.comma !== true && brace.dots !== true) { + const out = state.output.slice(0, brace.outputIndex); + const toks = state.tokens.slice(brace.tokensIndex); + brace.value = brace.output = "\\{"; + value = output = "\\}"; + state.output = out; + for (const t of toks) { + state.output += t.output || t.value; + } + } + push({ type: "brace", value, output }); + decrement("braces"); + braces.pop(); + continue; + } + if (value === "|") { + if (extglobs.length > 0) { + extglobs[extglobs.length - 1].conditions++; + } + push({ type: "text", value }); + continue; + } + if (value === ",") { + let output = value; + const brace = braces[braces.length - 1]; + if (brace && stack[stack.length - 1] === "braces") { + brace.comma = true; + output = "|"; + } + push({ type: "comma", value, output }); + continue; + } + if (value === "/") { + if (prev.type === "dot" && state.index === state.start + 1) { + state.start = state.index + 1; + state.consumed = ""; + state.output = ""; + tokens.pop(); + prev = bos; + continue; + } + push({ type: "slash", value, output: SLASH_LITERAL2 }); + continue; + } + if (value === ".") { + if (state.braces > 0 && prev.type === "dot") { + if (prev.value === ".") + prev.output = DOT_LITERAL2; + const brace = braces[braces.length - 1]; + prev.type = "dots"; + prev.output += value; + prev.value += value; + brace.dots = true; + continue; + } + if (state.braces + state.parens === 0 && prev.type !== "bos" && prev.type !== "slash") { + push({ type: "text", value, output: DOT_LITERAL2 }); + continue; + } + push({ type: "dot", value, output: DOT_LITERAL2 }); + continue; + } + if (value === "?") { + const isGroup = prev && prev.value === "("; + if (!isGroup && opts.noextglob !== true && peek() === "(" && peek(2) !== "?") { + extglobOpen("qmark", value); + continue; + } + if (prev && prev.type === "paren") { + const next = peek(); + let output = value; + if (next === "<" && !supportsLookbehinds()) { + throw new Error("Node.js v10 or higher is required for regex lookbehinds"); + } + if (prev.value === "(" && !/[!=<:]/.test(next) || next === "<" && !/<([!=]|\w+>)/.test(remaining())) { + output = `\\${value}`; + } + push({ type: "text", value, output }); + continue; + } + if (opts.dot !== true && (prev.type === "slash" || prev.type === "bos")) { + push({ type: "qmark", value, output: QMARK_NO_DOT2 }); + continue; + } + push({ type: "qmark", value, output: QMARK2 }); + continue; + } + if (value === "!") { + if (opts.noextglob !== true && peek() === "(") { + if (peek(2) !== "?" || !/[!=<:]/.test(peek(3))) { + extglobOpen("negate", value); + continue; + } + } + if (opts.nonegate !== true && state.index === 0) { + negate(); + continue; + } + } + if (value === "+") { + if (opts.noextglob !== true && peek() === "(" && peek(2) !== "?") { + extglobOpen("plus", value); + continue; + } + if (prev && prev.value === "(" || opts.regex === false) { + push({ type: "plus", value, output: PLUS_LITERAL2 }); + continue; + } + if (prev && (prev.type === "bracket" || prev.type === "paren" || prev.type === "brace") || state.parens > 0) { + push({ type: "plus", value }); + continue; + } + push({ type: "plus", value: PLUS_LITERAL2 }); + continue; + } + if (value === "@") { + if (opts.noextglob !== true && peek() === "(" && peek(2) !== "?") { + push({ type: "at", extglob: true, value, output: "" }); + continue; + } + push({ type: "text", value }); + continue; + } + if (value !== "*") { + if (value === "$" || value === "^") { + value = `\\${value}`; + } + const match = REGEX_NON_SPECIAL_CHARS.exec(remaining()); + if (match) { + value += match[0]; + state.index += match[0].length; + } + push({ type: "text", value }); + continue; + } + if (prev && (prev.type === "globstar" || prev.star === true)) { + prev.type = "star"; + prev.star = true; + prev.value += value; + prev.output = star; + state.backtrack = true; + state.globstar = true; + consume(value); + continue; + } + let rest = remaining(); + if (opts.noextglob !== true && /^\([^?]/.test(rest)) { + extglobOpen("star", value); + continue; + } + if (prev.type === "star") { + if (opts.noglobstar === true) { + consume(value); + continue; + } + const prior = prev.prev; + const before = prior.prev; + const isStart = prior.type === "slash" || prior.type === "bos"; + const afterStar = before && (before.type === "star" || before.type === "globstar"); + if (opts.bash === true && (!isStart || rest[0] && rest[0] !== "/")) { + push({ type: "star", value, output: "" }); + continue; + } + const isBrace = state.braces > 0 && (prior.type === "comma" || prior.type === "brace"); + const isExtglob = extglobs.length && (prior.type === "pipe" || prior.type === "paren"); + if (!isStart && prior.type !== "paren" && !isBrace && !isExtglob) { + push({ type: "star", value, output: "" }); + continue; + } + while (rest.slice(0, 3) === "/**") { + const after = input[state.index + 4]; + if (after && after !== "/") { + break; + } + rest = rest.slice(3); + consume("/**", 3); + } + if (prior.type === "bos" && eos()) { + prev.type = "globstar"; + prev.value += value; + prev.output = globstar(opts); + state.output = prev.output; + state.globstar = true; + consume(value); + continue; + } + if (prior.type === "slash" && prior.prev.type !== "bos" && !afterStar && eos()) { + state.output = state.output.slice(0, -(prior.output + prev.output).length); + prior.output = `(?:${prior.output}`; + prev.type = "globstar"; + prev.output = globstar(opts) + (opts.strictSlashes ? ")" : "|$)"); + prev.value += value; + state.globstar = true; + state.output += prior.output + prev.output; + consume(value); + continue; + } + if (prior.type === "slash" && prior.prev.type !== "bos" && rest[0] === "/") { + const end = rest[1] !== void 0 ? "|$" : ""; + state.output = state.output.slice(0, -(prior.output + prev.output).length); + prior.output = `(?:${prior.output}`; + prev.type = "globstar"; + prev.output = `${globstar(opts)}${SLASH_LITERAL2}|${SLASH_LITERAL2}${end})`; + prev.value += value; + state.output += prior.output + prev.output; + state.globstar = true; + consume(value + advance()); + push({ type: "slash", value: "/", output: "" }); + continue; + } + if (prior.type === "bos" && rest[0] === "/") { + prev.type = "globstar"; + prev.value += value; + prev.output = `(?:^|${SLASH_LITERAL2}|${globstar(opts)}${SLASH_LITERAL2})`; + state.output = prev.output; + state.globstar = true; + consume(value + advance()); + push({ type: "slash", value: "/", output: "" }); + continue; + } + state.output = state.output.slice(0, -prev.output.length); + prev.type = "globstar"; + prev.output = globstar(opts); + prev.value += value; + state.output += prev.output; + state.globstar = true; + consume(value); + continue; + } + const token = { type: "star", value, output: star }; + if (opts.bash === true) { + token.output = ".*?"; + if (prev.type === "bos" || prev.type === "slash") { + token.output = nodot + token.output; + } + push(token); + continue; + } + if (prev && (prev.type === "bracket" || prev.type === "paren") && opts.regex === true) { + token.output = value; + push(token); + continue; + } + if (state.index === state.start || prev.type === "slash" || prev.type === "dot") { + if (prev.type === "dot") { + state.output += NO_DOT_SLASH2; + prev.output += NO_DOT_SLASH2; + } else if (opts.dot === true) { + state.output += NO_DOTS_SLASH2; + prev.output += NO_DOTS_SLASH2; + } else { + state.output += nodot; + prev.output += nodot; + } + if (peek() !== "*") { + state.output += ONE_CHAR2; + prev.output += ONE_CHAR2; + } + } + push(token); + } + while (state.brackets > 0) { + if (opts.strictBrackets === true) + throw new SyntaxError(syntaxError("closing", "]")); + state.output = escapeLast(state.output, "["); + decrement("brackets"); + } + while (state.parens > 0) { + if (opts.strictBrackets === true) + throw new SyntaxError(syntaxError("closing", ")")); + state.output = escapeLast(state.output, "("); + decrement("parens"); + } + while (state.braces > 0) { + if (opts.strictBrackets === true) + throw new SyntaxError(syntaxError("closing", "}")); + state.output = escapeLast(state.output, "{"); + decrement("braces"); + } + if (opts.strictSlashes !== true && (prev.type === "star" || prev.type === "bracket")) { + push({ type: "maybe_slash", value: "", output: `${SLASH_LITERAL2}?` }); + } + if (state.backtrack === true) { + state.output = ""; + for (const token of state.tokens) { + state.output += token.output != null ? token.output : token.value; + if (token.suffix) { + state.output += token.suffix; + } + } + } + return state; +}; +parse.fastpaths = (input, options) => { + const opts = { ...options }; + const max = typeof opts.maxLength === "number" ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH; + const len = input.length; + if (len > max) { + throw new SyntaxError(`Input length: ${len}, exceeds maximum allowed length: ${max}`); + } + input = REPLACEMENTS[input] || input; + const win322 = isWindows(options); + const { + DOT_LITERAL: DOT_LITERAL2, + SLASH_LITERAL: SLASH_LITERAL2, + ONE_CHAR: ONE_CHAR2, + DOTS_SLASH: DOTS_SLASH2, + NO_DOT: NO_DOT2, + NO_DOTS: NO_DOTS2, + NO_DOTS_SLASH: NO_DOTS_SLASH2, + STAR: STAR2, + START_ANCHOR: START_ANCHOR2 + } = globChars(win322); + const nodot = opts.dot ? NO_DOTS2 : NO_DOT2; + const slashDot = opts.dot ? NO_DOTS_SLASH2 : NO_DOT2; + const capture = opts.capture ? "" : "?:"; + const state = { negated: false, prefix: "" }; + let star = opts.bash === true ? ".*?" : STAR2; + if (opts.capture) { + star = `(${star})`; + } + const globstar = (opts2) => { + if (opts2.noglobstar === true) + return star; + return `(${capture}(?:(?!${START_ANCHOR2}${opts2.dot ? DOTS_SLASH2 : DOT_LITERAL2}).)*?)`; + }; + const create = (str) => { + switch (str) { + case "*": + return `${nodot}${ONE_CHAR2}${star}`; + case ".*": + return `${DOT_LITERAL2}${ONE_CHAR2}${star}`; + case "*.*": + return `${nodot}${star}${DOT_LITERAL2}${ONE_CHAR2}${star}`; + case "*/*": + return `${nodot}${star}${SLASH_LITERAL2}${ONE_CHAR2}${slashDot}${star}`; + case "**": + return nodot + globstar(opts); + case "**/*": + return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL2})?${slashDot}${ONE_CHAR2}${star}`; + case "**/*.*": + return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL2})?${slashDot}${star}${DOT_LITERAL2}${ONE_CHAR2}${star}`; + case "**/.*": + return `(?:${nodot}${globstar(opts)}${SLASH_LITERAL2})?${DOT_LITERAL2}${ONE_CHAR2}${star}`; + default: { + const match = /^(.*?)\.(\w+)$/.exec(str); + if (!match) + return; + const source2 = create(match[1]); + if (!source2) + return; + return source2 + DOT_LITERAL2 + match[2]; + } + } + }; + const output = removePrefix(input, state); + let source = create(output); + if (source && opts.strictSlashes !== true) { + source += `${SLASH_LITERAL2}?`; + } + return source; +}; + +// lib/picomatch.js +var isObject2 = (val) => val && typeof val === "object" && !Array.isArray(val); +var picomatch = (glob, options, returnState = false) => { + if (Array.isArray(glob)) { + const fns = glob.map((input) => picomatch(input, options, returnState)); + const arrayMatcher = (str) => { + for (const isMatch of fns) { + const state2 = isMatch(str); + if (state2) + return state2; + } + return false; + }; + return arrayMatcher; + } + const isState = isObject2(glob) && glob.tokens && glob.input; + if (glob === "" || typeof glob !== "string" && !isState) { + throw new TypeError("Expected pattern to be a non-empty string"); + } + const opts = options || {}; + const posix = isWindows(options); + const regex = isState ? picomatch.compileRe(glob, options) : picomatch.makeRe(glob, options, false, true); + const state = regex.state; + delete regex.state; + let isIgnored = () => false; + if (opts.ignore) { + const ignoreOpts = { ...options, ignore: null, onMatch: null, onResult: null }; + isIgnored = picomatch(opts.ignore, ignoreOpts, returnState); + } + const matcher = (input, returnObject = false) => { + const { isMatch, match, output } = picomatch.test(input, regex, options, { glob, posix }); + const result = { glob, state, regex, posix, input, output, match, isMatch }; + if (typeof opts.onResult === "function") { + opts.onResult(result); + } + if (isMatch === false) { + result.isMatch = false; + return returnObject ? result : false; + } + if (isIgnored(input)) { + if (typeof opts.onIgnore === "function") { + opts.onIgnore(result); + } + result.isMatch = false; + return returnObject ? result : false; + } + if (typeof opts.onMatch === "function") { + opts.onMatch(result); + } + return returnObject ? result : true; + }; + if (returnState) { + matcher.state = state; + } + return matcher; +}; +picomatch.test = (input, regex, options, { glob, posix } = {}) => { + if (typeof input !== "string") { + throw new TypeError("Expected input to be a string"); + } + if (input === "") { + return { isMatch: false, output: "" }; + } + const opts = options || {}; + const format = opts.format || (posix ? toPosixSlashes : null); + let match = input === glob; + let output = match && format ? format(input) : input; + if (match === false) { + output = format ? format(input) : input; + match = output === glob; + } + if (match === false || opts.capture === true) { + if (opts.matchBase === true || opts.basename === true) { + match = picomatch.matchBase(input, regex, options, posix); + } else { + match = regex.exec(output); + } + } + return { isMatch: Boolean(match), match, output }; +}; +picomatch.matchBase = (input, glob, options, posix = isWindows(options)) => { + const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options); + return regex.test(path3.basename(input)); +}; +picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str); +picomatch.parse = (pattern, options) => { + if (Array.isArray(pattern)) + return pattern.map((p) => picomatch.parse(p, options)); + return parse(pattern, { ...options, fastpaths: false }); +}; +picomatch.scan = (input, options) => scan(input, options); +picomatch.compileRe = (state, options, returnOutput = false, returnState = false) => { + if (returnOutput === true) { + return state.output; + } + const opts = options || {}; + const prepend = opts.contains ? "" : "^"; + const append = opts.contains ? "" : "$"; + let source = `${prepend}(?:${state.output})${append}`; + if (state && state.negated === true) { + source = `^(?!${source}).*$`; + } + const regex = picomatch.toRegex(source, options); + if (returnState === true) { + regex.state = state; + } + return regex; +}; +picomatch.makeRe = (input, options = {}, returnOutput = false, returnState = false) => { + if (!input || typeof input !== "string") { + throw new TypeError("Expected a non-empty string"); + } + let parsed = { negated: false, fastpaths: true }; + if (options.fastpaths !== false && (input[0] === "." || input[0] === "*")) { + parsed.output = parse.fastpaths(input, options); + } + if (!parsed.output) { + parsed = parse(input, options); + } + return picomatch.compileRe(parsed, options, returnOutput, returnState); +}; +picomatch.toRegex = (source, options) => { + try { + const opts = options || {}; + return new RegExp(source, opts.flags || (opts.nocase ? "i" : "")); + } catch (err) { + if (options && options.debug === true) + throw err; + return /$^/; + } +}; +picomatch.constants = constants_exports; +var picomatch_default = picomatch; + +// lib/index.js +var lib_default = picomatch_default; +export { + lib_default as default, + utils_exports as utils +}; diff --git a/examples/extglob-negated.js b/examples/extglob-negated.js index 78c7c5a..7029e9f 100644 --- a/examples/extglob-negated.js +++ b/examples/extglob-negated.js @@ -1,6 +1,5 @@ -'use strict'; -const picomatch = require('..'); +import picomatch from '../lib'; const fixtures = [ ['/file.d.ts', false], diff --git a/examples/extglob.js b/examples/extglob.js index d5abdbc..583cb8c 100644 --- a/examples/extglob.js +++ b/examples/extglob.js @@ -1,6 +1,5 @@ -'use strict'; -const pm = require('..'); +const pm = require('../lib'); console.log(pm.makeRe('(a|b|c)')); console.log(pm.makeRe('!(a|b|c)')); diff --git a/examples/makeRe.js b/examples/makeRe.js index 46a36d1..ee3a596 100644 --- a/examples/makeRe.js +++ b/examples/makeRe.js @@ -1,6 +1,5 @@ -'use strict'; -const pm = require('..'); +const pm = require('../lib'); console.log(pm.makeRe('*')); // /^(?:(?!\.)(?=.)[^\\\/]*?\/?)$/ diff --git a/examples/match.js b/examples/match.js index aca9f94..df372d7 100644 --- a/examples/match.js +++ b/examples/match.js @@ -1,8 +1,7 @@ -'use strict'; -const path = require('path'); -// const assert = require('assert'); -const pm = require('..'); +import path from "path"; +// import assert from "assert"; +const pm = require('../lib'); /** * Example function for matching an array of strings diff --git a/examples/option-expandRange.js b/examples/option-expandRange.js index 8f72236..d999347 100644 --- a/examples/option-expandRange.js +++ b/examples/option-expandRange.js @@ -1,7 +1,6 @@ -'use strict'; const fill = require('fill-range'); -const pm = require('..'); +const pm = require('../lib'); const regex = pm.makeRe('foo/{01..25}/bar', { expandRange(a, b) { return `(${fill(a, b, { toRegex: true })})`; diff --git a/examples/option-ignore.js b/examples/option-ignore.js index 8401ec0..92ba0b0 100644 --- a/examples/option-ignore.js +++ b/examples/option-ignore.js @@ -1,6 +1,5 @@ -'use strict'; -const pm = require('..'); +const pm = require('../lib'); const isMatch = pm.matcher('*', { ignore: 'f*' }); console.log(isMatch('foo')); //=> false diff --git a/examples/option-onIgnore.js b/examples/option-onIgnore.js index 6d19a0c..27d9d86 100644 --- a/examples/option-onIgnore.js +++ b/examples/option-onIgnore.js @@ -1,6 +1,5 @@ -'use strict'; -const pm = require('..'); +const pm = require('../lib'); const onIgnore = ({ glob, regex, input, output }) => { console.log({ glob, regex, input, output }); diff --git a/examples/option-onMatch.js b/examples/option-onMatch.js index 3ceb2a8..387e752 100644 --- a/examples/option-onMatch.js +++ b/examples/option-onMatch.js @@ -1,6 +1,5 @@ -'use strict'; -const pm = require('..'); +const pm = require('../lib'); const onMatch = ({ glob, regex, input, output }) => { console.log({ input, output }); diff --git a/examples/option-onResult.js b/examples/option-onResult.js index 2c5aa45..bff93dd 100644 --- a/examples/option-onResult.js +++ b/examples/option-onResult.js @@ -1,6 +1,5 @@ -'use strict'; -const pm = require('..'); +const pm = require('../lib'); const onResult = ({ glob, regex, input, output }) => { console.log({ input, output }); diff --git a/examples/regex-quantifier.js b/examples/regex-quantifier.js index 38306b7..5dc1893 100644 --- a/examples/regex-quantifier.js +++ b/examples/regex-quantifier.js @@ -1,6 +1,5 @@ -'use strict'; -const pico = require('..'); +const pico = require('../lib'); /** * See: https://github.com/gulpjs/glob-parent/issues/39#issuecomment-794075641 diff --git a/examples/scan.js b/examples/scan.js index 962422d..12c251a 100644 --- a/examples/scan.js +++ b/examples/scan.js @@ -1,6 +1,5 @@ -'use strict'; -const pm = require('..'); +const pm = require('../lib'); console.log(pm.scan('foo/bar/*/*/*.js')); console.log(pm.scan('foo/(*|**a).js')); diff --git a/examples/test.js b/examples/test.js index b077773..c3d5ba7 100644 --- a/examples/test.js +++ b/examples/test.js @@ -1,6 +1,5 @@ -'use strict'; -const pm = require('..'); +const pm = require('../lib'); console.log(pm.test('foo/bar', /^(?:([^/]*?)\/([^/]*?))$/)); // { isMatch: true, match: [ 'foo/', 'foo', 'bar' ], output: 'foo/bar' } diff --git a/examples/windows.js b/examples/windows.js index 1f4d705..8da29d2 100644 --- a/examples/windows.js +++ b/examples/windows.js @@ -1,7 +1,6 @@ -'use strict'; -const path = require('path'); -const pm = require('..'); +import path from "path"; +const pm = require('../lib'); const { sep } = path; console.log(); diff --git a/index.js b/index.js deleted file mode 100644 index d2f2bc5..0000000 --- a/index.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict'; - -module.exports = require('./lib/picomatch'); diff --git a/lib/constants.js b/lib/constants.js index a62ef38..159a43b 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -1,30 +1,29 @@ -'use strict'; -const path = require('path'); -const WIN_SLASH = '\\\\/'; -const WIN_NO_SLASH = `[^${WIN_SLASH}]`; +import path from 'path'; +export const WIN_SLASH = '\\\\/'; +export const WIN_NO_SLASH = `[^${WIN_SLASH}]`; /** * Posix glob regex */ -const DOT_LITERAL = '\\.'; -const PLUS_LITERAL = '\\+'; -const QMARK_LITERAL = '\\?'; -const SLASH_LITERAL = '\\/'; -const ONE_CHAR = '(?=.)'; -const QMARK = '[^/]'; -const END_ANCHOR = `(?:${SLASH_LITERAL}|$)`; -const START_ANCHOR = `(?:^|${SLASH_LITERAL})`; -const DOTS_SLASH = `${DOT_LITERAL}{1,2}${END_ANCHOR}`; -const NO_DOT = `(?!${DOT_LITERAL})`; -const NO_DOTS = `(?!${START_ANCHOR}${DOTS_SLASH})`; -const NO_DOT_SLASH = `(?!${DOT_LITERAL}{0,1}${END_ANCHOR})`; -const NO_DOTS_SLASH = `(?!${DOTS_SLASH})`; -const QMARK_NO_DOT = `[^.${SLASH_LITERAL}]`; -const STAR = `${QMARK}*?`; - -const POSIX_CHARS = { +export const DOT_LITERAL = '\\.'; +export const PLUS_LITERAL = '\\+'; +export const QMARK_LITERAL = '\\?'; +export const SLASH_LITERAL = '\\/'; +export const ONE_CHAR = '(?=.)'; +export const QMARK = '[^/]'; +export const END_ANCHOR = `(?:${SLASH_LITERAL}|$)`; +export const START_ANCHOR = `(?:^|${SLASH_LITERAL})`; +export const DOTS_SLASH = `${DOT_LITERAL}{1,2}${END_ANCHOR}`; +export const NO_DOT = `(?!${DOT_LITERAL})`; +export const NO_DOTS = `(?!${START_ANCHOR}${DOTS_SLASH})`; +export const NO_DOT_SLASH = `(?!${DOT_LITERAL}{0,1}${END_ANCHOR})`; +export const NO_DOTS_SLASH = `(?!${DOTS_SLASH})`; +export const QMARK_NO_DOT = `[^.${SLASH_LITERAL}]`; +export const STAR = `${QMARK}*?`; + +export const POSIX_CHARS = { DOT_LITERAL, PLUS_LITERAL, QMARK_LITERAL, @@ -46,7 +45,7 @@ const POSIX_CHARS = { * Windows glob regex */ -const WINDOWS_CHARS = { +export const WINDOWS_CHARS = { ...POSIX_CHARS, SLASH_LITERAL: `[${WIN_SLASH}]`, @@ -66,7 +65,7 @@ const WINDOWS_CHARS = { * POSIX Bracket Regex */ -const POSIX_REGEX_SOURCE = { +export const POSIX_REGEX_SOURCE = { alnum: 'a-zA-Z0-9', alpha: 'a-zA-Z', ascii: '\\x00-\\x7F', @@ -83,97 +82,91 @@ const POSIX_REGEX_SOURCE = { xdigit: 'A-Fa-f0-9' }; -module.exports = { - MAX_LENGTH: 1024 * 64, - POSIX_REGEX_SOURCE, - - // regular expressions - REGEX_BACKSLASH: /\\(?![*+?^${}(|)[\]])/g, - REGEX_NON_SPECIAL_CHARS: /^[^@![\].,$*+?^{}()|\\/]+/, - REGEX_SPECIAL_CHARS: /[-*+?.^${}(|)[\]]/, - REGEX_SPECIAL_CHARS_BACKREF: /(\\?)((\W)(\3*))/g, - REGEX_SPECIAL_CHARS_GLOBAL: /([-*+?.^${}(|)[\]])/g, - REGEX_REMOVE_BACKSLASH: /(?:\[.*?[^\\]\]|\\(?=.))/g, - - // Replace globs with equivalent patterns to reduce parsing time. - REPLACEMENTS: { - '***': '*', - '**/**': '**', - '**/**/**': '**' - }, - - // Digits - CHAR_0: 48, /* 0 */ - CHAR_9: 57, /* 9 */ - - // Alphabet chars. - CHAR_UPPERCASE_A: 65, /* A */ - CHAR_LOWERCASE_A: 97, /* a */ - CHAR_UPPERCASE_Z: 90, /* Z */ - CHAR_LOWERCASE_Z: 122, /* z */ - - CHAR_LEFT_PARENTHESES: 40, /* ( */ - CHAR_RIGHT_PARENTHESES: 41, /* ) */ - - CHAR_ASTERISK: 42, /* * */ - - // Non-alphabetic chars. - CHAR_AMPERSAND: 38, /* & */ - CHAR_AT: 64, /* @ */ - CHAR_BACKWARD_SLASH: 92, /* \ */ - CHAR_CARRIAGE_RETURN: 13, /* \r */ - CHAR_CIRCUMFLEX_ACCENT: 94, /* ^ */ - CHAR_COLON: 58, /* : */ - CHAR_COMMA: 44, /* , */ - CHAR_DOT: 46, /* . */ - CHAR_DOUBLE_QUOTE: 34, /* " */ - CHAR_EQUAL: 61, /* = */ - CHAR_EXCLAMATION_MARK: 33, /* ! */ - CHAR_FORM_FEED: 12, /* \f */ - CHAR_FORWARD_SLASH: 47, /* / */ - CHAR_GRAVE_ACCENT: 96, /* ` */ - CHAR_HASH: 35, /* # */ - CHAR_HYPHEN_MINUS: 45, /* - */ - CHAR_LEFT_ANGLE_BRACKET: 60, /* < */ - CHAR_LEFT_CURLY_BRACE: 123, /* { */ - CHAR_LEFT_SQUARE_BRACKET: 91, /* [ */ - CHAR_LINE_FEED: 10, /* \n */ - CHAR_NO_BREAK_SPACE: 160, /* \u00A0 */ - CHAR_PERCENT: 37, /* % */ - CHAR_PLUS: 43, /* + */ - CHAR_QUESTION_MARK: 63, /* ? */ - CHAR_RIGHT_ANGLE_BRACKET: 62, /* > */ - CHAR_RIGHT_CURLY_BRACE: 125, /* } */ - CHAR_RIGHT_SQUARE_BRACKET: 93, /* ] */ - CHAR_SEMICOLON: 59, /* ; */ - CHAR_SINGLE_QUOTE: 39, /* ' */ - CHAR_SPACE: 32, /* */ - CHAR_TAB: 9, /* \t */ - CHAR_UNDERSCORE: 95, /* _ */ - CHAR_VERTICAL_LINE: 124, /* | */ - CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279, /* \uFEFF */ - - SEP: path.sep, - - /** - * Create EXTGLOB_CHARS - */ +export const MAX_LENGTH = 1024 * 64; + +// regular expressions +export const REGEX_BACKSLASH = /\\(?![*+?^${}(|)[\]])/g; +export const REGEX_NON_SPECIAL_CHARS = /^[^@![\].,$*+?^{}()|\\/]+/; +export const REGEX_SPECIAL_CHARS = /[-*+?.^${}(|)[\]]/; +export const REGEX_SPECIAL_CHARS_BACKREF = /(\\?)((\W)(\3*))/g; +export const REGEX_SPECIAL_CHARS_GLOBAL = /([-*+?.^${}(|)[\]])/g; +export const REGEX_REMOVE_BACKSLASH = /(?:\[.*?[^\\]\]|\\(?=.))/g; + +// Replace globs with equivalent patterns to reduce parsing time. +export const REPLACEMENTS = { + '***': '*', + '**/**': '**', + '**/**/**': '**' +}; - extglobChars(chars) { - return { - '!': { type: 'negate', open: '(?:(?!(?:', close: `))${chars.STAR})` }, - '?': { type: 'qmark', open: '(?:', close: ')?' }, - '+': { type: 'plus', open: '(?:', close: ')+' }, - '*': { type: 'star', open: '(?:', close: ')*' }, - '@': { type: 'at', open: '(?:', close: ')' } - }; - }, - - /** - * Create GLOB_CHARS +// Digits +export const CHAR_0 = 48; /* 0 */ +export const CHAR_9 = 57; /* 9 */ + +// Alphabet chars. +export const CHAR_UPPERCASE_A = 65; /* A */ +export const CHAR_LOWERCASE_A = 97; /* a */ +export const CHAR_UPPERCASE_Z = 90; /* Z */ +export const CHAR_LOWERCASE_Z = 122; /* z */ + +export const CHAR_LEFT_PARENTHESES = 40; /* ( */ +export const CHAR_RIGHT_PARENTHESES = 41; /* ) */ +export const CHAR_ASTERISK = 42; /* * */ + +// Non-alphabetic chars. +export const CHAR_AMPERSAND = 38; /* & */ +export const CHAR_AT = 64; /* @ */ +export const CHAR_BACKWARD_SLASH = 92; /* \ */ +export const CHAR_CARRIAGE_RETURN = 13; /* \r */ +export const CHAR_CIRCUMFLEX_ACCENT = 94; /* ^ */ +export const CHAR_COLON = 58; /* = */ +export const CHAR_COMMA = 44; /* ; */ +export const CHAR_DOT = 46; /* . */ +export const CHAR_DOUBLE_QUOTE = 34; /* " */ +export const CHAR_EQUAL = 61; /* = */ +export const CHAR_EXCLAMATION_MARK = 33; /* ! */ +export const CHAR_FORM_FEED = 12; /* \f */ +export const CHAR_FORWARD_SLASH = 47; /* / */ +export const CHAR_GRAVE_ACCENT = 96; /* ` */ +export const CHAR_HASH = 35; /* # */ +export const CHAR_HYPHEN_MINUS = 45; /* - */ +export const CHAR_LEFT_ANGLE_BRACKET = 60; /* < */ +export const CHAR_LEFT_CURLY_BRACE = 123; /* { */ +export const CHAR_LEFT_SQUARE_BRACKET = 91; /* [ */ +export const CHAR_LINE_FEED = 10; /* \n */ +export const CHAR_NO_BREAK_SPACE = 160; /* \u00A0 */ +export const CHAR_PERCENT = 37; /* % */ +export const CHAR_PLUS = 43; /* + */ +export const CHAR_QUESTION_MARK = 63; /* ? */ +export const CHAR_RIGHT_ANGLE_BRACKET = 62; /* > */ +export const CHAR_RIGHT_CURLY_BRACE = 125; /* } */ +export const CHAR_RIGHT_SQUARE_BRACKET = 93; /* ] */ +export const CHAR_SEMICOLON = 59; /* ; */ +export const CHAR_SINGLE_QUOTE = 39; /* ' */ +export const CHAR_SPACE = 32; /* */ +export const CHAR_TAB = 9; /* \t */ +export const CHAR_UNDERSCORE = 95; /* _ */ +export const CHAR_VERTICAL_LINE = 124; /* | */ +export const CHAR_ZERO_WIDTH_NOBREAK_SPACE = 65279; /* \uFEFF */ + +export const SEP = path.sep; + +/** + * Create EXTGLOB_CHARS */ +export const extglobChars = chars => { + return { + '!': { type: 'negate', open: '(?:(?!(?:', close: `))${chars.STAR})` }, + '?': { type: 'qmark', open: '(?:', close: ')?' }, + '+': { type: 'plus', open: '(?:', close: ')+' }, + '*': { type: 'star', open: '(?:', close: ')*' }, + '@': { type: 'at', open: '(?:', close: ')' } + }; +}; - globChars(win32) { - return win32 === true ? WINDOWS_CHARS : POSIX_CHARS; - } +/** + * Create GLOB_CHARS + */ +export const globChars = win32 => { + return win32 === true ? WINDOWS_CHARS : POSIX_CHARS; }; diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..da15c7a --- /dev/null +++ b/lib/index.js @@ -0,0 +1,5 @@ +import { default as picomatch } from './picomatch.js'; +import * as utils from './utils.js'; + +export { utils }; +export default picomatch; diff --git a/lib/parse.js b/lib/parse.js index 58269d0..58d2c9e 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -1,19 +1,15 @@ -'use strict'; -const constants = require('./constants'); -const utils = require('./utils'); +import * as utils from './utils.js'; -/** - * Constants - */ - -const { +import { MAX_LENGTH, POSIX_REGEX_SOURCE, REGEX_NON_SPECIAL_CHARS, REGEX_SPECIAL_CHARS_BACKREF, - REPLACEMENTS -} = constants; + REPLACEMENTS, + globChars, + extglobChars +} from './constants.js'; /** * Helpers @@ -52,7 +48,7 @@ const syntaxError = (type, char) => { * @return {Object} */ -const parse = (input, options) => { +export const parse = (input, options) => { if (typeof input !== 'string') { throw new TypeError('Expected a string'); } @@ -74,8 +70,8 @@ const parse = (input, options) => { const win32 = utils.isWindows(options); // create constants based on platform, for windows or posix - const PLATFORM_CHARS = constants.globChars(win32); - const EXTGLOB_CHARS = constants.extglobChars(PLATFORM_CHARS); + const PLATFORM_CHARS = globChars(win32); + const EXTGLOB_CHARS = extglobChars(PLATFORM_CHARS); const { DOT_LITERAL, @@ -1023,7 +1019,7 @@ parse.fastpaths = (input, options) => { NO_DOTS_SLASH, STAR, START_ANCHOR - } = constants.globChars(win32); + } = globChars(win32); const nodot = opts.dot ? NO_DOTS : NO_DOT; const slashDot = opts.dot ? NO_DOTS_SLASH : NO_DOT; @@ -1087,5 +1083,3 @@ parse.fastpaths = (input, options) => { return source; }; - -module.exports = parse; diff --git a/lib/picomatch.js b/lib/picomatch.js index 782d809..5934126 100644 --- a/lib/picomatch.js +++ b/lib/picomatch.js @@ -1,10 +1,9 @@ -'use strict'; +import path from 'path'; +import { scan } from './scan.js'; +import { parse } from './parse.js'; +import * as utils from './utils.js'; +import * as constants from './constants.js'; -const path = require('path'); -const scan = require('./scan'); -const parse = require('./parse'); -const utils = require('./utils'); -const constants = require('./constants'); const isObject = val => val && typeof val === 'object' && !Array.isArray(val); /** @@ -28,7 +27,6 @@ const isObject = val => val && typeof val === 'object' && !Array.isArray(val); * @return {Function=} Returns a matcher function. * @api public */ - const picomatch = (glob, options, returnState = false) => { if (Array.isArray(glob)) { const fns = glob.map(input => picomatch(input, options, returnState)); @@ -113,7 +111,6 @@ const picomatch = (glob, options, returnState = false) => { * @return {Object} Returns an object with matching info. * @api public */ - picomatch.test = (input, regex, options, { glob, posix } = {}) => { if (typeof input !== 'string') { throw new TypeError('Expected input to be a string'); @@ -157,7 +154,6 @@ picomatch.test = (input, regex, options, { glob, posix } = {}) => { * @return {Boolean} * @api public */ - picomatch.matchBase = (input, glob, options, posix = utils.isWindows(options)) => { const regex = glob instanceof RegExp ? glob : picomatch.makeRe(glob, options); return regex.test(path.basename(input)); @@ -179,7 +175,6 @@ picomatch.matchBase = (input, glob, options, posix = utils.isWindows(options)) = * @return {Boolean} Returns true if any patterns match `str` * @api public */ - picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str); /** @@ -195,7 +190,6 @@ picomatch.isMatch = (str, patterns, options) => picomatch(patterns, options)(str * @return {Object} Returns an object with useful properties and output to be used as a regex source string. * @api public */ - picomatch.parse = (pattern, options) => { if (Array.isArray(pattern)) return pattern.map(p => picomatch.parse(p, options)); return parse(pattern, { ...options, fastpaths: false }); @@ -227,7 +221,6 @@ picomatch.parse = (pattern, options) => { * @return {Object} Returns an object with * @api public */ - picomatch.scan = (input, options) => scan(input, options); /** @@ -241,7 +234,6 @@ picomatch.scan = (input, options) => scan(input, options); * @return {RegExp} * @api public */ - picomatch.compileRe = (state, options, returnOutput = false, returnState = false) => { if (returnOutput === true) { return state.output; @@ -338,5 +330,4 @@ picomatch.constants = constants; /** * Expose "picomatch" */ - -module.exports = picomatch; +export default picomatch; diff --git a/lib/scan.js b/lib/scan.js index e59cd7a..4b4f3a6 100644 --- a/lib/scan.js +++ b/lib/scan.js @@ -1,7 +1,7 @@ -'use strict'; -const utils = require('./utils'); -const { +import * as utils from './utils.js'; + +import { CHAR_ASTERISK, /* * */ CHAR_AT, /* @ */ CHAR_BACKWARD_SLASH, /* \ */ @@ -17,7 +17,7 @@ const { CHAR_RIGHT_CURLY_BRACE, /* } */ CHAR_RIGHT_PARENTHESES, /* ) */ CHAR_RIGHT_SQUARE_BRACKET /* ] */ -} = require('./constants'); +} from './constants.js'; const isPathSeparator = code => { return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH; @@ -46,7 +46,7 @@ const depth = token => { * @api public */ -const scan = (input, options) => { +export const scan = (input, options) => { const opts = options || {}; const length = input.length - 1; @@ -388,4 +388,3 @@ const scan = (input, options) => { return state; }; -module.exports = scan; diff --git a/lib/utils.js b/lib/utils.js index c3ca766..fd060df 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,27 +1,26 @@ -'use strict'; -const path = require('path'); -const win32 = process.platform === 'win32'; -const { +import path from 'path'; +import { REGEX_BACKSLASH, REGEX_REMOVE_BACKSLASH, REGEX_SPECIAL_CHARS, REGEX_SPECIAL_CHARS_GLOBAL -} = require('./constants'); +} from './constants.js'; +const win32 = process.platform === 'win32'; -exports.isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); -exports.hasRegexChars = str => REGEX_SPECIAL_CHARS.test(str); -exports.isRegexChar = str => str.length === 1 && exports.hasRegexChars(str); -exports.escapeRegex = str => str.replace(REGEX_SPECIAL_CHARS_GLOBAL, '\\$1'); -exports.toPosixSlashes = str => str.replace(REGEX_BACKSLASH, '/'); +export const isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val); +export const hasRegexChars = str => REGEX_SPECIAL_CHARS.test(str); +export const isRegexChar = str => str.length === 1 && hasRegexChars(str); +export const escapeRegex = str => str.replace(REGEX_SPECIAL_CHARS_GLOBAL, '\\$1'); +export const toPosixSlashes = str => str.replace(REGEX_BACKSLASH, '/'); -exports.removeBackslashes = str => { +export const removeBackslashes = str => { return str.replace(REGEX_REMOVE_BACKSLASH, match => { return match === '\\' ? '' : match; }); }; -exports.supportsLookbehinds = () => { +export const supportsLookbehinds = () => { const segs = process.version.slice(1).split('.').map(Number); if (segs.length === 3 && segs[0] >= 9 || (segs[0] === 8 && segs[1] >= 10)) { return true; @@ -29,21 +28,22 @@ exports.supportsLookbehinds = () => { return false; }; -exports.isWindows = options => { +export const isWindows = options => { if (options && typeof options.windows === 'boolean') { return options.windows; } return win32 === true || path.sep === '\\'; }; -exports.escapeLast = (input, char, lastIdx) => { +export const escapeLast = (input, char, lastIdx) => { const idx = input.lastIndexOf(char, lastIdx); if (idx === -1) return input; - if (input[idx - 1] === '\\') return exports.escapeLast(input, char, idx - 1); - return `${input.slice(0, idx)}\\${input.slice(idx)}`; + return input[idx - 1] === '\\' + ? escapeLast(input, char, idx - 1) + : input.slice(0, idx) + '\\' + input.slice(idx); }; -exports.removePrefix = (input, state = {}) => { +export const removePrefix = (input, state = {}) => { let output = input; if (output.startsWith('./')) { output = output.slice(2); @@ -52,7 +52,7 @@ exports.removePrefix = (input, state = {}) => { return output; }; -exports.wrapOutput = (input, state = {}, options = {}) => { +export const wrapOutput = (input, state = {}, options = {}) => { const prepend = options.contains ? '' : '^'; const append = options.contains ? '' : '$'; diff --git a/package.json b/package.json index 3db22d4..920dac6 100644 --- a/package.json +++ b/package.json @@ -11,15 +11,25 @@ }, "license": "MIT", "files": [ - "index.js", - "lib" + "dist" ], - "main": "index.js", + "type": "module", + "main": "dist/index.cjs", + "module": "dist/index.js", + "exports": { + ".": { + "require": "./dist/index.cjs", + "import": "./dist/index.js" + } + }, "engines": { - "node": ">=8.6" + "node": ">=12" }, "scripts": { - "lint": "eslint --cache --cache-location node_modules/.cache/.eslintcache --report-unused-disable-directives --ignore-path .gitignore .", + "build": "tsup lib/index.js --format=esm,cjs --clean", + "lint": "run-p lint:*", + "lint:lib": "eslint ./lib/**/*.js --fix", + "lint:test": "eslint ./test/**/*.js --fix", "mocha": "mocha --reporter dot", "test": "npm run lint && npm run mocha", "test:ci": "npm run test:cover", @@ -29,9 +39,13 @@ "eslint": "^6.8.0", "fill-range": "^7.0.1", "gulp-format-md": "^2.0.0", - "mocha": "^6.2.2", - "nyc": "^15.0.0", - "time-require": "github:jonschlinkert/time-require" + "mocha": "^10.0.0", + "npm-run-all": "^4.1.5", + "nyc": "^15.1.0", + "time-require": "github:jonschlinkert/time-require", + "ts-node": "^10.9.1", + "tsup": "^6.1.3", + "typescript": "^4.7.4" }, "keywords": [ "glob", @@ -78,4 +92,4 @@ "picomatch" ] } -} +} \ No newline at end of file diff --git a/test/api.picomatch.js b/test/api.picomatch.js index c659a64..9baf2bb 100644 --- a/test/api.picomatch.js +++ b/test/api.picomatch.js @@ -1,9 +1,7 @@ -'use strict'; +import assert from 'assert'; +import picomatch from '../lib/picomatch.js'; -const assert = require('assert'); -const picomatch = require('..'); const { isMatch } = picomatch; - const assertTokens = (actual, expected) => { const keyValuePairs = actual.map(token => [token.type, token.value]); assert.deepStrictEqual(keyValuePairs, expected); diff --git a/test/api.scan.js b/test/api.scan.js index b1e63db..68da4c1 100644 --- a/test/api.scan.js +++ b/test/api.scan.js @@ -1,7 +1,6 @@ -'use strict'; -const assert = require('assert'); -const scan = require('../lib/scan'); +import assert from 'assert'; +import { scan } from '../lib/scan.js'; const base = (...args) => scan(...args).base; const both = (...args) => { const { base, glob } = scan(...args); diff --git a/test/bash.js b/test/bash.js index 2ef4bb1..650d8f2 100644 --- a/test/bash.js +++ b/test/bash.js @@ -1,7 +1,7 @@ -'use strict'; -const assert = require('assert'); -const { isMatch } = require('..'); +import assert from 'assert'; +import picomatch from '../lib/index.js'; +const isMatch = picomatch.isMatch; // $echo a/{1..3}/b describe('from the Bash 4.3 spec/unit tests', () => { diff --git a/test/bash.spec.js b/test/bash.spec.js index 7cd276b..826e2ac 100644 --- a/test/bash.spec.js +++ b/test/bash.spec.js @@ -1,7 +1,7 @@ -'use strict'; -const assert = require('assert'); -const { isMatch } = require('..'); +import assert from 'assert'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; describe('bash.spec', () => { describe('dotglob', () => { diff --git a/test/braces.js b/test/braces.js index a343c31..8550ab3 100644 --- a/test/braces.js +++ b/test/braces.js @@ -1,9 +1,9 @@ -'use strict'; -const assert = require('assert'); -const fill = require('fill-range'); -const match = require('./support/match'); -const { isMatch } = require('..'); +import assert from 'assert'; +import fill from 'fill-range'; +import match from './support/match.js'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; describe('braces', () => { it('should not match with brace patterns when disabled', () => { diff --git a/test/brackets.js b/test/brackets.js index c510625..088799e 100644 --- a/test/brackets.js +++ b/test/brackets.js @@ -1,7 +1,7 @@ -'use strict'; -const assert = require('assert'); -const { isMatch } = require('..'); +import assert from 'assert'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; describe('brackets', () => { describe('trailing stars', () => { diff --git a/test/dotfiles.js b/test/dotfiles.js index e72e0f6..2602fc4 100644 --- a/test/dotfiles.js +++ b/test/dotfiles.js @@ -1,8 +1,8 @@ -'use strict'; -const assert = require('assert'); -const match = require('./support/match'); -const { isMatch } = require('..'); +import assert from 'assert'; +import match from './support/match.js'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; describe('dotfiles', () => { describe('normal', () => { @@ -224,7 +224,7 @@ describe('dotfiles', () => { assert(isMatch('abc/../abc', '*/../*')); }); - it('should not match double dots when not defined in pattern', async() => { + it('should not match double dots when not defined in pattern', async () => { assert(!isMatch('../abc', '**/*')); assert(!isMatch('../abc', '**/**/**')); assert(!isMatch('../abc', '**/**/abc')); @@ -291,7 +291,7 @@ describe('dotfiles', () => { assert(!isMatch('abc/abc/..', 'abc/*/**/*', { strictSlashes: true })); }); - it('should not match single exclusive dots when not defined in pattern', async() => { + it('should not match single exclusive dots when not defined in pattern', async () => { assert(!isMatch('.', '**')); assert(!isMatch('abc/./abc', '**')); assert(!isMatch('abc/abc/.', '**')); diff --git a/test/dots-invalid.js b/test/dots-invalid.js index ff730a8..34484c7 100644 --- a/test/dots-invalid.js +++ b/test/dots-invalid.js @@ -1,7 +1,7 @@ -'use strict'; -const assert = require('assert'); -const { isMatch } = require('..'); +import assert from 'assert'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; describe('invalid (exclusive) dots', () => { describe('double dots', () => { diff --git a/test/extglobs-bash.js b/test/extglobs-bash.js index 49560c1..d304cef 100644 --- a/test/extglobs-bash.js +++ b/test/extglobs-bash.js @@ -1,8 +1,8 @@ -'use strict'; -const assert = require('assert'); -const support = require('./support'); -const { isMatch } = require('..'); +import assert from 'assert'; +import support from './support/index.js'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; /** * Some of tests were converted from bash 4.3, 4.4, and minimatch unit tests. diff --git a/test/extglobs-minimatch.js b/test/extglobs-minimatch.js index ae3e309..0e604dd 100644 --- a/test/extglobs-minimatch.js +++ b/test/extglobs-minimatch.js @@ -1,8 +1,8 @@ -'use strict'; -const assert = require('assert'); -const support = require('./support'); -const { isMatch } = require('..'); +import assert from 'assert'; +import support from './support/index.js'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; /** * Some of tests were converted from bash 4.3, 4.4, and minimatch unit tests. diff --git a/test/extglobs-temp.js b/test/extglobs-temp.js index 991fb50..da1bea0 100644 --- a/test/extglobs-temp.js +++ b/test/extglobs-temp.js @@ -1,8 +1,8 @@ -'use strict'; -const assert = require('assert'); -const support = require('./support'); -const { isMatch } = require('..'); +import assert from 'assert'; +import support from './support/index.js'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; /** * Some of tests were converted from bash 4.3, 4.4, and minimatch unit tests. diff --git a/test/extglobs.js b/test/extglobs.js index ea436d1..fe69248 100644 --- a/test/extglobs.js +++ b/test/extglobs.js @@ -1,8 +1,8 @@ -'use strict'; -const assert = require('assert'); -const match = require('./support/match'); -const { isMatch, makeRe } = require('..'); +import assert from 'assert'; +import match from './support/match.js'; +import picomatch from '../lib/index.js'; +const { isMatch, makeRe } = picomatch; /** * Ported from Bash 4.3 and 4.4 unit tests diff --git a/test/globstars.js b/test/globstars.js index 9d10134..4149a3f 100644 --- a/test/globstars.js +++ b/test/globstars.js @@ -1,8 +1,8 @@ -'use strict'; -const assert = require('assert'); -const match = require('./support/match'); -const { isMatch } = require('..'); +import assert from 'assert'; +import match from './support/match.js'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; describe('stars', () => { describe('issue related', () => { diff --git a/test/issue-related.js b/test/issue-related.js index f85b3e6..3f89e4a 100644 --- a/test/issue-related.js +++ b/test/issue-related.js @@ -1,7 +1,7 @@ -'use strict'; -const assert = require('assert'); -const { isMatch } = require('..'); +import assert from 'assert'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; describe('issue-related tests', () => { it('should match with braces (see picomatch/issues#8)', () => { diff --git a/test/malicious.js b/test/malicious.js index 33cf6b8..e733fc6 100644 --- a/test/malicious.js +++ b/test/malicious.js @@ -1,7 +1,7 @@ -'use strict'; -const assert = require('assert'); -const { isMatch } = require('..'); +import assert from 'assert'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; const repeat = n => '\\'.repeat(n); /** diff --git a/test/minimatch.js b/test/minimatch.js index 853e120..35f4268 100644 --- a/test/minimatch.js +++ b/test/minimatch.js @@ -1,8 +1,8 @@ -'use strict'; -const assert = require('assert'); +import assert from 'assert'; const format = str => str.replace(/^\.\//, ''); -const { isMatch, makeRe } = require('..'); +import picomatch from '../lib/index.js'; +const { isMatch, makeRe } = picomatch; describe('minimatch parity:', () => { describe('minimatch issues (as of 12/7/2016)', () => { diff --git a/test/negation.js b/test/negation.js index a3a6a83..ab98639 100644 --- a/test/negation.js +++ b/test/negation.js @@ -1,7 +1,7 @@ -'use strict'; -const assert = require('assert'); -const { isMatch } = require('..'); +import assert from 'assert'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; describe('negation patterns - "!"', () => { it('should patterns with a leading "!" as negated/inverted globs', () => { diff --git a/test/non-globs.js b/test/non-globs.js index 48bcf85..bed6a76 100644 --- a/test/non-globs.js +++ b/test/non-globs.js @@ -1,8 +1,8 @@ -'use strict'; -const assert = require('assert'); -const support = require('./support'); -const { isMatch } = require('..'); +import assert from 'assert'; +import support from './support/index.js'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; describe('non-globs', () => { before(() => support.resetPathSep()); diff --git a/test/options.expandRange.js b/test/options.expandRange.js index 0eb05fc..1e2d98f 100644 --- a/test/options.expandRange.js +++ b/test/options.expandRange.js @@ -1,8 +1,8 @@ -'use strict'; -const assert = require('assert'); -const fill = require('fill-range'); -const { isMatch } = require('..'); +import assert from 'assert'; +import fill from 'fill-range'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; describe('options.expandRange', () => { it('should support a custom function for expanding ranges in brace patterns', () => { diff --git a/test/options.format.js b/test/options.format.js index b4f3444..0f9e0de 100644 --- a/test/options.format.js +++ b/test/options.format.js @@ -1,8 +1,8 @@ -'use strict'; -const assert = require('assert'); -const match = require('./support/match'); -const { isMatch } = require('..'); +import assert from 'assert'; +import match from './support/match.js'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; const equal = (actual, expected, msg) => { assert.deepStrictEqual([].concat(actual).sort(), [].concat(expected).sort(), msg); diff --git a/test/options.ignore.js b/test/options.ignore.js index e8cc628..fde1758 100644 --- a/test/options.ignore.js +++ b/test/options.ignore.js @@ -1,8 +1,8 @@ -'use strict'; -const assert = require('assert'); -const match = require('./support/match'); -const { isMatch } = require('..'); +import assert from 'assert'; +import match from './support/match.js'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; describe('options.ignore', () => { it('should not match ignored patterns', () => { diff --git a/test/options.js b/test/options.js index 1702974..11b9c03 100644 --- a/test/options.js +++ b/test/options.js @@ -1,9 +1,9 @@ -'use strict'; -const assert = require('assert'); -const support = require('./support'); -const match = require('./support/match'); -const { isMatch } = require('..'); +import assert from 'assert'; +import support from './support/index.js'; +import match from './support/match.js'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; describe('options', () => { beforeEach(() => support.windowsPathSep()); diff --git a/test/options.noextglob.js b/test/options.noextglob.js index 3ff6bfa..000c1e6 100644 --- a/test/options.noextglob.js +++ b/test/options.noextglob.js @@ -1,7 +1,7 @@ -'use strict'; -const assert = require('assert'); -const { isMatch } = require('..'); +import assert from 'assert'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; describe('options.noextglob', () => { it('should disable extglob support when options.noextglob is true', () => { diff --git a/test/options.noglobstar.js b/test/options.noglobstar.js index 9f8757e..094658c 100644 --- a/test/options.noglobstar.js +++ b/test/options.noglobstar.js @@ -1,7 +1,7 @@ -'use strict'; -const assert = require('assert'); -const { isMatch } = require('..'); +import assert from 'assert'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; describe('options.noglobstar', () => { it('should disable extglob support when options.noglobstar is true', () => { diff --git a/test/options.onMatch.js b/test/options.onMatch.js index caf2335..c727513 100644 --- a/test/options.onMatch.js +++ b/test/options.onMatch.js @@ -1,8 +1,7 @@ -'use strict'; -const assert = require('assert'); -const match = require('./support/match'); -const picomatch = require('..'); +import assert from 'assert'; +import match from './support/match.js'; +import picomatch from '../lib/index.js'; const { isMatch } = picomatch; const equal = (actual, expected, msg) => { diff --git a/test/parens.js b/test/parens.js index d73bf63..43e16d0 100644 --- a/test/parens.js +++ b/test/parens.js @@ -1,7 +1,7 @@ -'use strict'; -const assert = require('assert'); -const { isMatch } = require('..'); +import assert from 'assert'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; describe('parens (non-extglobs)', () => { it('should support stars following parens', () => { diff --git a/test/posix-classes.js b/test/posix-classes.js index f3eed94..d5a10fe 100644 --- a/test/posix-classes.js +++ b/test/posix-classes.js @@ -1,9 +1,8 @@ -'use strict'; - -const assert = require('assert'); -const pm = require('..'); -const { makeRe, parse } = pm; +import assert from 'assert'; +import pm from '../lib/index.js'; +import { parse } from '../lib/parse.js'; +const { makeRe } = pm; const opts = { strictSlashes: true, posix: true, regex: true }; const isMatch = (...args) => pm.isMatch(...args, opts); const convert = (...args) => { diff --git a/test/qmarks.js b/test/qmarks.js index 1a2dadf..831370c 100644 --- a/test/qmarks.js +++ b/test/qmarks.js @@ -1,8 +1,8 @@ -'use strict'; -const assert = require('assert'); -const match = require('./support/match'); -const { isMatch } = require('..'); +import assert from 'assert'; +import match from './support/match.js'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; describe('qmarks and stars', () => { it('should match question marks with question marks', () => { diff --git a/test/regex-features.js b/test/regex-features.js index 9e3b692..56f7af4 100644 --- a/test/regex-features.js +++ b/test/regex-features.js @@ -1,9 +1,9 @@ -'use strict'; const { version } = process; -const assert = require('assert'); -const utils = require('../lib/utils'); -const { isMatch } = require('..'); +import assert from 'assert'; +import * as utils from '../lib/utils.js'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; describe('regex features', () => { describe('word boundaries', () => { diff --git a/test/slashes-posix.js b/test/slashes-posix.js index 50abfd6..44a56c2 100644 --- a/test/slashes-posix.js +++ b/test/slashes-posix.js @@ -1,8 +1,8 @@ -'use strict'; -const assert = require('assert'); -const support = require('./support'); -const { isMatch } = require('..'); +import assert from 'assert'; +import support from './support/index.js'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; describe('slash handling - posix', () => { before(() => support.resetPathSep()); diff --git a/test/slashes-windows.js b/test/slashes-windows.js index 234afab..7f8ba0c 100644 --- a/test/slashes-windows.js +++ b/test/slashes-windows.js @@ -1,8 +1,8 @@ -'use strict'; -const assert = require('assert'); -const support = require('./support'); -const { isMatch, makeRe } = require('..'); +import assert from 'assert'; +import support from './support/index.js'; +import picomatch from '../lib/index.js'; +const { isMatch, makeRe } = picomatch; describe('slash handling - windows', () => { beforeEach(() => support.windowsPathSep()); diff --git a/test/special-characters.js b/test/special-characters.js index 7ff8920..b249307 100644 --- a/test/special-characters.js +++ b/test/special-characters.js @@ -1,9 +1,9 @@ -'use strict'; -const path = require('path'); -const assert = require('assert'); -const support = require('./support'); -const { isMatch, makeRe } = require('..'); +import path from 'path'; +import assert from 'assert'; +import support from './support/index.js'; +import picomatch from '../lib/index.js'; +const { isMatch, makeRe } = picomatch; describe('special characters', () => { before(() => support.resetPathSep()); @@ -232,7 +232,7 @@ describe('special characters', () => { assert(isMatch('foo(bar)baz', 'foo*baz')); }); - it('should match literal parens with brackets', async() => { + it('should match literal parens with brackets', async () => { assert(isMatch('foo(bar)baz', 'foo[bar()]+baz')); }); diff --git a/test/stars.js b/test/stars.js index 910b9f2..9f92cb6 100644 --- a/test/stars.js +++ b/test/stars.js @@ -1,7 +1,7 @@ -'use strict'; -const assert = require('assert'); -const { isMatch } = require('..'); +import assert from 'assert'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; describe('stars', () => { describe('issue related', () => { diff --git a/test/support/index.js b/test/support/index.js index 7e6c632..7be3deb 100644 --- a/test/support/index.js +++ b/test/support/index.js @@ -1,13 +1,12 @@ -'use strict'; -const path = require('path'); +import path from 'path'; // Don't use "path.sep" here, as it's conceivable that it might have been // modified somewhere by the user. Node.js only handles these two path separators // with similar logic, and this is only for unit tests, so we should be fine. const sep = process.platform === 'win32' ? '\\' : '/'; -module.exports = { +export default { windowsPathSep() { path.sep = '\\'; }, diff --git a/test/support/match.js b/test/support/match.js index f932cbd..fd7c248 100644 --- a/test/support/match.js +++ b/test/support/match.js @@ -1,8 +1,6 @@ -'use strict'; +import picomatch from '../../lib/picomatch.js'; -const picomatch = require('../..'); - -module.exports = (list, pattern, options = {}) => { +export default (list, pattern, options = {}) => { const isMatch = picomatch(pattern, options, true); const matches = options.matches || new Set(); diff --git a/test/wildmat.js b/test/wildmat.js index c61195e..52c8a62 100644 --- a/test/wildmat.js +++ b/test/wildmat.js @@ -1,7 +1,7 @@ -'use strict'; -const assert = require('assert'); -const { isMatch } = require('..'); +import assert from 'assert'; +import picomatch from '../lib/index.js'; +const { isMatch } = picomatch; describe('Wildmat (git) tests', () => { it('Basic wildmat features', () => {