rsbuild-plugin-dts
Version:
Rsbuild plugin that supports emitting declaration files for TypeScript.
1,153 lines (1,152 loc) • 212 kB
JavaScript
import { logger } from "@rsbuild/core";
import node_path, { basename, dirname, extname, isAbsolute, join, normalize, relative as external_node_path_relative, resolve } from "node:path";
import node_fs from "node:fs";
import node_module, { createRequire } from "node:module";
import fs_0, * as __rspack_external_fs from "fs";
import { readdir, readdirSync, realpath, realpathSync, stat as external_fs_stat, statSync } from "fs";
import os from "os";
import path_0, { basename as external_path_basename, dirname as external_path_dirname, isAbsolute as external_path_isAbsolute, normalize as external_path_normalize, posix, relative as external_path_relative, resolve as external_path_resolve, sep as external_path_sep } from "path";
import promises from "node:fs/promises";
import { platform } from "node:os";
import { styleText } from "node:util";
import { fileURLToPath } from "url";
import { createRequire as external_module_createRequire } from "module";
import { __webpack_require__ } from "./rslib-runtime.js";
import { createRequire as __rspack_createRequire } from "node:module";
const __rspack_createRequire_require = __rspack_createRequire(import.meta.url);
__webpack_require__.add({
"../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/index.js" (module, __unused_rspack_exports, __webpack_require__) {
const pico = __webpack_require__("../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/picomatch.js");
const utils = __webpack_require__("../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/utils.js");
function picomatch(glob, options, returnState = false) {
if (options && (null === options.windows || void 0 === options.windows)) options = {
...options,
windows: utils.isWindows()
};
return pico(glob, options, returnState);
}
Object.assign(picomatch, pico);
module.exports = picomatch;
},
"../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/constants.js" (module) {
const WIN_SLASH = '\\\\/';
const WIN_NO_SLASH = `[^${WIN_SLASH}]`;
const DEFAULT_MAX_EXTGLOB_RECURSION = 0;
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 SEP = '/';
const 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,
SEP
};
const 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}]|$)`,
SEP: '\\'
};
const POSIX_REGEX_SOURCE = {
__proto__: null,
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'
};
module.exports = {
DEFAULT_MAX_EXTGLOB_RECURSION,
MAX_LENGTH: 65536,
POSIX_REGEX_SOURCE,
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,
REPLACEMENTS: {
__proto__: null,
'***': '*',
'**/**': '**',
'**/**/**': '**'
},
CHAR_0: 48,
CHAR_9: 57,
CHAR_UPPERCASE_A: 65,
CHAR_LOWERCASE_A: 97,
CHAR_UPPERCASE_Z: 90,
CHAR_LOWERCASE_Z: 122,
CHAR_LEFT_PARENTHESES: 40,
CHAR_RIGHT_PARENTHESES: 41,
CHAR_ASTERISK: 42,
CHAR_AMPERSAND: 38,
CHAR_AT: 64,
CHAR_BACKWARD_SLASH: 92,
CHAR_CARRIAGE_RETURN: 13,
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,
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,
CHAR_NO_BREAK_SPACE: 160,
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,
CHAR_UNDERSCORE: 95,
CHAR_VERTICAL_LINE: 124,
CHAR_ZERO_WIDTH_NOBREAK_SPACE: 65279,
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 true === win32 ? WINDOWS_CHARS : POSIX_CHARS;
}
};
},
"../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/parse.js" (module, __unused_rspack_exports, __webpack_require__) {
const constants = __webpack_require__("../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/constants.js");
const utils = __webpack_require__("../../node_modules/.pnpm/picomatch@4.0.4/node_modules/picomatch/lib/utils.js");
const { MAX_LENGTH, POSIX_REGEX_SOURCE, REGEX_NON_SPECIAL_CHARS, REGEX_SPECIAL_CHARS_BACKREF, REPLACEMENTS } = constants;
const expandRange = (args, options)=>{
if ('function' == typeof options.expandRange) return options.expandRange(...args, options);
args.sort();
const value = `[${args.join('-')}]`;
try {
new RegExp(value);
} catch (ex) {
return args.map((v)=>utils.escapeRegex(v)).join('..');
}
return value;
};
const syntaxError = (type, char)=>`Missing ${type}: "${char}" - use "\\\\${char}" to match literal characters`;
const splitTopLevel = (input)=>{
const parts = [];
let bracket = 0;
let paren = 0;
let quote = 0;
let value = '';
let escaped = false;
for (const ch of input){
if (true === escaped) {
value += ch;
escaped = false;
continue;
}
if ('\\' === ch) {
value += ch;
escaped = true;
continue;
}
if ('"' === ch) {
quote = 1 === quote ? 0 : 1;
value += ch;
continue;
}
if (0 === quote) {
if ('[' === ch) bracket++;
else if (']' === ch && bracket > 0) bracket--;
else if (0 === bracket) {
if ('(' === ch) paren++;
else if (')' === ch && paren > 0) paren--;
else if ('|' === ch && 0 === paren) {
parts.push(value);
value = '';
continue;
}
}
}
value += ch;
}
parts.push(value);
return parts;
};
const isPlainBranch = (branch)=>{
let escaped = false;
for (const ch of branch){
if (true === escaped) {
escaped = false;
continue;
}
if ('\\' === ch) {
escaped = true;
continue;
}
if (/[?*+@!()[\]{}]/.test(ch)) return false;
}
return true;
};
const normalizeSimpleBranch = (branch)=>{
let value = branch.trim();
let changed = true;
while(true === changed){
changed = false;
if (/^@\([^\\()[\]{}|]+\)$/.test(value)) {
value = value.slice(2, -1);
changed = true;
}
}
if (!isPlainBranch(value)) return;
return value.replace(/\\(.)/g, '$1');
};
const hasRepeatedCharPrefixOverlap = (branches)=>{
const values = branches.map(normalizeSimpleBranch).filter(Boolean);
for(let i = 0; i < values.length; i++)for(let j = i + 1; j < values.length; j++){
const a = values[i];
const b = values[j];
const char = a[0];
if (char && a === char.repeat(a.length) && b === char.repeat(b.length)) {
if (a === b || a.startsWith(b) || b.startsWith(a)) return true;
}
}
return false;
};
const parseRepeatedExtglob = (pattern, requireEnd = true)=>{
if ('+' !== pattern[0] && '*' !== pattern[0] || '(' !== pattern[1]) return;
let bracket = 0;
let paren = 0;
let quote = 0;
let escaped = false;
for(let i = 1; i < pattern.length; i++){
const ch = pattern[i];
if (true === escaped) {
escaped = false;
continue;
}
if ('\\' === ch) {
escaped = true;
continue;
}
if ('"' === ch) {
quote = 1 === quote ? 0 : 1;
continue;
}
if (1 !== quote) {
if ('[' === ch) {
bracket++;
continue;
}
if (']' === ch && bracket > 0) {
bracket--;
continue;
}
if (!(bracket > 0)) {
if ('(' === ch) {
paren++;
continue;
}
if (')' === ch) {
paren--;
if (0 === paren) {
if (true === requireEnd && i !== pattern.length - 1) return;
return {
type: pattern[0],
body: pattern.slice(2, i),
end: i
};
}
}
}
}
}
};
const getStarExtglobSequenceOutput = (pattern)=>{
let index = 0;
const chars = [];
while(index < pattern.length){
const match = parseRepeatedExtglob(pattern.slice(index), false);
if (!match || '*' !== match.type) return;
const branches = splitTopLevel(match.body).map((branch)=>branch.trim());
if (1 !== branches.length) return;
const branch = normalizeSimpleBranch(branches[0]);
if (!branch || 1 !== branch.length) return;
chars.push(branch);
index += match.end + 1;
}
if (chars.length < 1) return;
const source = 1 === chars.length ? utils.escapeRegex(chars[0]) : `[${chars.map((ch)=>utils.escapeRegex(ch)).join('')}]`;
return `${source}*`;
};
const repeatedExtglobRecursion = (pattern)=>{
let depth = 0;
let value = pattern.trim();
let match = parseRepeatedExtglob(value);
while(match){
depth++;
value = match.body.trim();
match = parseRepeatedExtglob(value);
}
return depth;
};
const analyzeRepeatedExtglob = (body, options)=>{
if (false === options.maxExtglobRecursion) return {
risky: false
};
const max = 'number' == typeof options.maxExtglobRecursion ? options.maxExtglobRecursion : constants.DEFAULT_MAX_EXTGLOB_RECURSION;
const branches = splitTopLevel(body).map((branch)=>branch.trim());
if (branches.length > 1) {
if (branches.some((branch)=>'' === branch) || branches.some((branch)=>/^[*?]+$/.test(branch)) || hasRepeatedCharPrefixOverlap(branches)) return {
risky: true
};
}
for (const branch of branches){
const safeOutput = getStarExtglobSequenceOutput(branch);
if (safeOutput) return {
risky: true,
safeOutput
};
if (repeatedExtglobRecursion(branch) > max) return {
risky: true
};
}
return {
risky: false
};
};
const parse = (input, options)=>{
if ('string' != typeof input) throw new TypeError('Expected a string');
input = REPLACEMENTS[input] || input;
const opts = {
...options
};
const max = 'number' == typeof opts.maxLength ? 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 PLATFORM_CHARS = constants.globChars(opts.windows);
const EXTGLOB_CHARS = constants.extglobChars(PLATFORM_CHARS);
const { DOT_LITERAL, PLUS_LITERAL, SLASH_LITERAL, ONE_CHAR, DOTS_SLASH, NO_DOT, NO_DOT_SLASH, NO_DOTS_SLASH, QMARK, QMARK_NO_DOT, STAR, START_ANCHOR } = PLATFORM_CHARS;
const globstar = (opts)=>`(${capture}(?:(?!${START_ANCHOR}${opts.dot ? DOTS_SLASH : DOT_LITERAL}).)*?)`;
const nodot = opts.dot ? '' : NO_DOT;
const qmarkNoDot = opts.dot ? QMARK : QMARK_NO_DOT;
let star = true === opts.bash ? globstar(opts) : STAR;
if (opts.capture) star = `(${star})`;
if ('boolean' == typeof opts.noext) opts.noextglob = opts.noext;
const state = {
input,
index: -1,
start: 0,
dot: true === opts.dot,
consumed: '',
output: '',
prefix: '',
backtrack: false,
negated: false,
brackets: 0,
braces: 0,
parens: 0,
quotes: 0,
globstar: false,
tokens
};
input = utils.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 = (value = '', num = 0)=>{
state.consumed += value;
state.index += num;
};
const append = (token)=>{
state.output += null != token.output ? 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 ('globstar' === prev.type) {
const isBrace = state.braces > 0 && ('comma' === tok.type || 'brace' === tok.type);
const isExtglob = true === tok.extglob || extglobs.length && ('pipe' === tok.type || 'paren' === tok.type);
if ('slash' !== tok.type && 'paren' !== tok.type && !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 && 'paren' !== tok.type) extglobs[extglobs.length - 1].inner += tok.value;
if (tok.value || tok.output) append(tok);
if (prev && 'text' === prev.type && 'text' === tok.type) {
prev.output = (prev.output || prev.value) + tok.value;
prev.value += tok.value;
return;
}
tok.prev = prev;
tokens.push(tok);
prev = tok;
};
const extglobOpen = (type, value)=>{
const token = {
...EXTGLOB_CHARS[value],
conditions: 1,
inner: ''
};
token.prev = prev;
token.parens = state.parens;
token.output = state.output;
token.startIndex = state.index;
token.tokensIndex = tokens.length;
const output = (opts.capture ? '(' : '') + token.open;
increment('parens');
push({
type,
value,
output: state.output ? '' : ONE_CHAR
});
push({
type: 'paren',
extglob: true,
value: advance(),
output
});
extglobs.push(token);
};
const extglobClose = (token)=>{
const literal = input.slice(token.startIndex, state.index + 1);
const body = input.slice(token.startIndex + 2, state.index);
const analysis = analyzeRepeatedExtglob(body, opts);
if (('plus' === token.type || 'star' === token.type) && analysis.risky) {
const safeOutput = analysis.safeOutput ? (token.output ? '' : ONE_CHAR) + (opts.capture ? `(${analysis.safeOutput})` : analysis.safeOutput) : void 0;
const open = tokens[token.tokensIndex];
open.type = 'text';
open.value = literal;
open.output = safeOutput || utils.escapeRegex(literal);
for(let i = token.tokensIndex + 1; i < tokens.length; i++){
tokens[i].value = '';
tokens[i].output = '';
delete tokens[i].suffix;
}
state.output = token.output + open.output;
state.backtrack = true;
push({
type: 'paren',
extglob: true,
value,
output: ''
});
decrement('parens');
return;
}
let output = token.close + (opts.capture ? ')' : '');
let rest;
if ('negate' === token.type) {
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 ('bos' === token.prev.type) state.negatedExtglob = true;
}
push({
type: 'paren',
extglob: true,
value,
output
});
decrement('parens');
};
if (false !== opts.fastpaths && !/(^[*!]|[/()[\]{}"])/.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 ? QMARK.repeat(rest.length) : '');
if (0 === index) return qmarkNoDot + (rest ? QMARK.repeat(rest.length) : '');
return QMARK.repeat(chars.length);
}
if ('.' === first) return DOT_LITERAL.repeat(chars.length);
if ('*' === first) {
if (esc) return esc + first + (rest ? star : '');
return star;
}
return esc ? m : `\\${m}`;
});
if (true === backslashes) output = true === opts.unescape ? output.replace(/\\/g, '') : output.replace(/\\+/g, (m)=>m.length % 2 === 0 ? '\\\\' : m ? '\\' : '');
if (output === input && true === opts.contains) {
state.output = input;
return state;
}
state.output = utils.wrapOutput(output, state, options);
return state;
}
while(!eos()){
value = advance();
if ('\u0000' === value) continue;
if ('\\' === value) {
const next = peek();
if ('/' === next && true !== opts.bash) 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 (true === opts.unescape) value = advance();
else value += advance();
if (0 === state.brackets) {
push({
type: 'text',
value
});
continue;
}
}
if (state.brackets > 0 && (']' !== value || '[' === prev.value || '[^' === prev.value)) {
if (false !== opts.posix && ':' === 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 rest = prev.value.slice(idx + 2);
const posix = POSIX_REGEX_SOURCE[rest];
if (posix) {
prev.value = pre + posix;
state.backtrack = true;
advance();
if (!bos.output && 1 === tokens.indexOf(prev)) bos.output = ONE_CHAR;
continue;
}
}
}
}
if ('[' === value && ':' !== peek() || '-' === value && ']' === peek()) value = `\\${value}`;
if (']' === value && ('[' === prev.value || '[^' === prev.value)) value = `\\${value}`;
if (true === opts.posix && '!' === value && '[' === prev.value) value = '^';
prev.value += value;
append({
value
});
continue;
}
if (1 === state.quotes && '"' !== value) {
value = utils.escapeRegex(value);
prev.value += value;
append({
value
});
continue;
}
if ('"' === value) {
state.quotes = 1 === state.quotes ? 0 : 1;
if (true === opts.keepQuotes) push({
type: 'text',
value
});
continue;
}
if ('(' === value) {
increment('parens');
push({
type: 'paren',
value
});
continue;
}
if (')' === value) {
if (0 === state.parens && true === opts.strictBrackets) 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 (true !== opts.nobracket && remaining().includes(']')) increment('brackets');
else {
if (true !== opts.nobracket && true === opts.strictBrackets) throw new SyntaxError(syntaxError('closing', ']'));
value = `\\${value}`;
}
push({
type: 'bracket',
value
});
continue;
}
if (']' === value) {
if (true === opts.nobracket || prev && 'bracket' === prev.type && 1 === prev.value.length) {
push({
type: 'text',
value,
output: `\\${value}`
});
continue;
}
if (0 === state.brackets) {
if (true === opts.strictBrackets) throw new SyntaxError(syntaxError('opening', '['));
push({
type: 'text',
value,
output: `\\${value}`
});
continue;
}
decrement('brackets');
const prevValue = prev.value.slice(1);
if (true !== prev.posix && '^' === prevValue[0] && !prevValue.includes('/')) value = `/${value}`;
prev.value += value;
append({
value
});
if (false === opts.literalBrackets || utils.hasRegexChars(prevValue)) continue;
const escaped = utils.escapeRegex(prev.value);
state.output = state.output.slice(0, -prev.value.length);
if (true === opts.literalBrackets) {
state.output += escaped;
prev.value = escaped;
continue;
}
prev.value = `(${capture}${escaped}|${prev.value})`;
state.output += prev.value;
continue;
}
if ('{' === value && true !== opts.nobrace) {
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 (true === opts.nobrace || !brace) {
push({
type: 'text',
value,
output: value
});
continue;
}
let output = ')';
if (true === brace.dots) {
const arr = tokens.slice();
const range = [];
for(let i = arr.length - 1; i >= 0; i--){
tokens.pop();
if ('brace' === arr[i].type) break;
if ('dots' !== arr[i].type) range.unshift(arr[i].value);
}
output = expandRange(range, opts);
state.backtrack = true;
}
if (true !== brace.comma && true !== brace.dots) {
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 && 'braces' === stack[stack.length - 1]) {
brace.comma = true;
output = '|';
}
push({
type: 'comma',
value,
output
});
continue;
}
if ('/' === value) {
if ('dot' === prev.type && 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_LITERAL
});
continue;
}
if ('.' === value) {
if (state.braces > 0 && 'dot' === prev.type) {
if ('.' === prev.value) prev.output = DOT_LITERAL;
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 && 'bos' !== prev.type && 'slash' !== prev.type) {
push({
type: 'text',
value,
output: DOT_LITERAL
});
continue;
}
push({
type: 'dot',
value,
output: DOT_LITERAL
});
continue;
}
if ('?' === value) {
const isGroup = prev && '(' === prev.value;
if (!isGroup && true !== opts.noextglob && '(' === peek() && '?' !== peek(2)) {
extglobOpen('qmark', value);
continue;
}
if (prev && 'paren' === prev.type) {
const next = peek();
let output = value;
if ('(' === prev.value && !/[!=<:]/.test(next) || '<' === next && !/<([!=]|\w+>)/.test(remaining())) output = `\\${value}`;
push({
type: 'text',
value,
output
});
continue;
}
if (true !== opts.dot && ('slash' === prev.type || 'bos' === prev.type)) {
push({
type: 'qmark',
value,
output: QMARK_NO_DOT
});
continue;
}
push({
type: 'qmark',
value,
output: QMARK
});
continue;
}
if ('!' === value) {
if (true !== opts.noextglob && '(' === peek()) {
if ('?' !== peek(2) || !/[!=<:]/.test(peek(3))) {
extglobOpen('negate', value);
continue;
}
}
if (true !== opts.nonegate && 0 === state.index) {
negate();
continue;
}
}
if ('+' === value) {
if (true !== opts.noextglob && '(' === peek() && '?' !== peek(2)) {
extglobOpen('plus', value);
continue;
}
if (prev && '(' === prev.value || false === opts.regex) {
push({
type: 'plus',
value,
output: PLUS_LITERAL
});
continue;
}
if (prev && ('bracket' === prev.type || 'paren' === prev.type || 'brace' === prev.type) || state.parens > 0) {
push({
type: 'plus',
value
});
continue;
}
push({
type: 'plus',
value: PLUS_LITERAL
});
continue;
}
if ('@' === value) {
if (true !== opts.noextglob && '(' === 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 && ('globstar' === prev.type || true === prev.star)) {
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 (true !== opts.noextglob && /^\([^?]/.test(rest)) {
extglobOpen('star', value);
continue;
}
if ('star' === prev.type) {
if (true === opts.noglobstar) {
consume(value);
continue;
}
const prior = prev.prev;
const before = prior.prev;
const isStart = 'slash' === prior.type || 'bos' === prior.type;
const afterStar = before && ('star' === before.type || 'globstar' === before.type);
if (true === opts.bash && (!isStart || rest[0] && '/' !== rest[0])) {
push({
type: 'star',
value,
output: ''
});
continue;
}
const isBrace = state.braces > 0 && ('comma' === prior.type || 'brace' === prior.type);
const isExtglob = extglobs.length && ('pipe' === prior.type || 'paren' === prior.type);
if (!isStart && 'paren' !== prior.type && !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 ('bos' === prior.type && eos()) {
prev.type = 'globstar';
prev.value += value;
prev.output = globstar(opts);
state.output = prev.output;
state.globstar = true;
consume(value);
continue;
}
if ('slash' === prior.type && 'bos' !== prior.prev.type && !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 ('slash' === prior.type && 'bos' !== prior.prev.type && '/' === rest[0]) {
const end = void 0 !== rest[1] ? '|$' : '';
state.output = state.output.slice(0, -(prior.output + prev.output).length);
prior.output = `(?:${prior.output}`;
prev.type = 'globstar';
prev.output = `${globstar(opts)}${SLASH_LITERAL}|${SLASH_LITERAL}${end})`;
prev.value += value;
state.output += prior.output + prev.output;
state.globstar = true;
consume(value + advance());
push({
type: 'slash',
value: '/',
output: ''
});
continue;
}
if ('bos' === prior.type && '/' === rest[0]) {
prev.type = 'globstar';
prev.value += value;
prev.output = `(?:^|${SLASH_LITERAL}|${globstar(opts)}${SLASH_LITERAL})`;
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 (true === opts.bash) {
token.output = '.*?';
if ('bos' === prev.type || 'slash' === prev.type) token.output = nodot + token.output;
push(token);
continue;
}
if (prev && ('bracket' === prev.type || 'paren' === prev.type) && true === opts.regex) {
token.output = value;
push(token);
continue;
}
if (state.index === state.start || 'slash' === prev.type || 'dot' === prev.type) {
if ('dot' === prev.type) {
state.output += NO_DOT_SLASH;
prev.output += NO_DOT_SLASH;
} else if (true === opts.dot) {
state.output += NO_DOTS_SLASH;
prev.output += NO_DOTS_SLASH;
} else {
state.output += nodot;
prev.output += nodot;
}
if ('*' !== peek()) {
state.output += ONE_CHAR;
prev.output += ONE_CHAR;
}
}
push(token);
}
while(state.brackets > 0){
if (true === opts.strictBrackets) throw new SyntaxError(syntaxError('closing', ']'));
state.output = utils.escapeLast(state.output, '[');
decrement('brackets');
}
while(state.parens > 0){
if (true === opts.strictBrackets) throw new SyntaxError(syntaxError('closing', ')'));
state.output = utils.escapeLast(state.output, '(');
decrement('parens');
}
while(state.braces > 0){
if (true === opts.strictBrackets) throw new SyntaxError(syntaxError('closing', '}'));
state.output = utils.escapeLast(state.output, '{');
decrement('braces');
}
if (true !== opts.strictSlashes && ('star' === prev.type || 'bracket' === prev.type)) push({
type: 'maybe_slash',
value: '',
output: `${SLASH_LITERAL}?`
});
if (true === state.backtrack) {
state.output = '';
for (const token of state.tokens){
state.output += null != token.output ? token.output : token.value;
if (token.suffix) state.output += token.suffix;
}
}
return state;
};
parse.fastpaths = (input, options)=>{
const opts = {
...options
};
const max = 'number' == typeof opts.maxLength ? 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 { DOT_LITERAL, SLASH_LITERAL, ONE_CHAR, DOTS_SLASH, NO_DOT, NO_DOTS, NO_DOTS_SLASH, STAR, START_ANCHOR } = constants.globChars(opts.windows);
const nodot = opts.dot ? NO_DOTS : NO_DOT;
const slashDot = opts.dot ? NO_DOTS_SLASH : NO_DOT;
const capture = opts.capture ? '' : '?:';
const state = {
negated: false,
prefix: ''
};
let star = true === opts.bash ? '.*?' : STAR;
if (opts.capture) star = `(${star})`;