{"mappings":";AACO,IAAMA,EAAU,OAAO,OAAO,CACnC,QAAS,UACT,WAAY,YACd,CAAC,EAyBM,SAASC,EAAiBC,EAAYC,EAAQC,EAAaC,EAAS,CACzE,IAAMC,EAAK,IAAI,OAAO,OAAO,MAAMH,CAAM,wBAAyB,KAAK,EACjEI,EAAU,CAAC,EAAK,EAClBC,EAAqB,EACrBC,EAAS,GACb,QAAWC,KAASR,EAAW,SAASI,CAAE,EAAG,CAC3C,GAAM,CAAC,EAAGK,EAAG,OAAQ,CAAC,MAAAC,CAAK,CAAC,EAAIF,EAChC,GAAI,CAACE,IAAU,CAACP,GAAYA,IAAYL,EAAQ,SAAa,CAACQ,GAAqB,CAC7EJ,aAAuB,SACzBK,GAAUL,EAAYM,EAAO,CAC3B,QAASF,EAAqBR,EAAQ,WAAaA,EAAQ,QAC3D,QAASO,EAAQA,EAAQ,OAAS,CAAC,CACrC,CAAC,EAEDE,GAAUL,EAEZ,QACF,CACIO,EAAE,CAAC,IAAM,KACXH,IACAD,EAAQ,KAAKI,EAAE,CAAC,IAAM,GAAG,GAChBA,IAAM,KAAOH,IACtBA,IACAD,EAAQ,IAAI,GAEdE,GAAUE,CACZ,CACA,OAAOF,CACT,CAeO,SAASI,EAAiBX,EAAYC,EAAQW,EAAUT,EAAS,CAEtEJ,EAAiBC,EAAYC,EAAQW,EAAUT,CAAO,CACxD,CAcO,SAASU,EAAcb,EAAYC,EAAQa,EAAM,EAAGX,EAAS,CAElE,GAAI,CAAE,IAAI,OAAOF,EAAQ,IAAI,EAAE,KAAKD,CAAU,EAC5C,OAAO,KAET,IAAMI,EAAK,IAAI,OAAO,GAAGH,CAAM,oBAAqB,KAAK,EACzDG,EAAG,UAAYU,EACf,IAAIR,EAAqB,EACrBE,EACJ,KAAOA,EAAQJ,EAAG,KAAKJ,CAAU,GAAG,CAClC,GAAM,CAAC,EAAGS,EAAG,OAAQ,CAAC,MAAAC,CAAK,CAAC,EAAIF,EAChC,GAAI,CAACE,IAAU,CAACP,GAAYA,IAAYL,EAAQ,SAAa,CAACQ,GAC5D,OAAOE,EAELC,IAAM,IACRH,IACSG,IAAM,KAAOH,GACtBA,IAGEF,EAAG,WAAaI,EAAM,OACxBJ,EAAG,WAEP,CACA,OAAO,IACT,CAYO,SAASW,EAAaf,EAAYC,EAAQE,EAAS,CAExD,MAAO,CAAC,CAACU,EAAcb,EAAYC,EAAQ,EAAGE,CAAO,CACvD,CAaO,SAASa,EAAiBhB,EAAYiB,EAAkB,CAC7D,IAAMC,EAAQ,UACdA,EAAM,UAAYD,EAClB,IAAIE,EAAiBnB,EAAW,OAC5BM,EAAqB,EAErBc,EAAgB,EAChBZ,EACJ,KAAOA,EAAQU,EAAM,KAAKlB,CAAU,GAAG,CACrC,GAAM,CAACS,CAAC,EAAID,EACZ,GAAIC,IAAM,IACRH,YACUA,EAUDG,IAAM,KACfH,YAVIG,IAAM,IACRW,YACSX,IAAM,MACfW,IACI,CAACA,GAAe,CAClBD,EAAiBX,EAAM,MACvB,KACF,CAKN,CACA,OAAOR,EAAW,MAAMiB,EAAkBE,CAAc,CAC1D","names":["Context","replaceUnescaped","expression","needle","replacement","context","re","negated","numCharClassesOpen","result","match","m","$skip","forEachUnescaped","callback","execUnescaped","pos","hasUnescaped","getGroupContents","contentsStartPos","token","contentsEndPos","numGroupsOpen"],"sources":["../esm/npm/regex-utilities@2.3.0/node_modules/regex-utilities/src/index.js"],"sourcesContent":["// Constant properties for tracking regex syntax context\nexport const Context = Object.freeze({\n  DEFAULT: 'DEFAULT',\n  CHAR_CLASS: 'CHAR_CLASS',\n});\n\n/**\nReplaces all unescaped instances of a regex pattern in the given context, using a replacement\nstring or callback.\n\nDoesn't skip over complete multicharacter tokens (only `\\` plus its folowing char) so must be used\nwith knowledge of what's safe to do given regex syntax. Assumes UnicodeSets-mode syntax.\n@param {string} expression Search target\n@param {string} needle Search as a regex pattern, with flags `su` applied\n@param {string | (match: RegExpExecArray, details: {\n  context: 'DEFAULT' | 'CHAR_CLASS';\n  negated: boolean;\n}) =\u003e string} replacement\n@param {'DEFAULT' | 'CHAR_CLASS'} [context] All contexts if not specified\n@returns {string} Updated expression\n@example\nconst str = '.\\\\.\\\\\\\\.[[\\\\.].].';\nreplaceUnescaped(str, '\\\\.', '@');\n// → '@\\\\.\\\\\\\\@[[\\\\.]@]@'\nreplaceUnescaped(str, '\\\\.', '@', Context.DEFAULT);\n// → '@\\\\.\\\\\\\\@[[\\\\.].]@'\nreplaceUnescaped(str, '\\\\.', '@', Context.CHAR_CLASS);\n// → '.\\\\.\\\\\\\\.[[\\\\.]@].'\n*/\nexport function replaceUnescaped(expression, needle, replacement, context) {\n  const re = new RegExp(String.raw`${needle}|(?\u003c$skip\u003e\\[\\^?|\\\\?.)`, 'gsu');\n  const negated = [false];\n  let numCharClassesOpen = 0;\n  let result = '';\n  for (const match of expression.matchAll(re)) {\n    const {0: m, groups: {$skip}} = match;\n    if (!$skip \u0026\u0026 (!context || (context === Context.DEFAULT) === !numCharClassesOpen)) {\n      if (replacement instanceof Function) {\n        result += replacement(match, {\n          context: numCharClassesOpen ? Context.CHAR_CLASS : Context.DEFAULT,\n          negated: negated[negated.length - 1],\n        });\n      } else {\n        result += replacement;\n      }\n      continue;\n    }\n    if (m[0] === '[') {\n      numCharClassesOpen++;\n      negated.push(m[1] === '^');\n    } else if (m === ']' \u0026\u0026 numCharClassesOpen) {\n      numCharClassesOpen--;\n      negated.pop();\n    }\n    result += m;\n  }\n  return result;\n}\n\n/**\nRuns a callback for each unescaped instance of a regex pattern in the given context.\n\nDoesn't skip over complete multicharacter tokens (only `\\` plus its folowing char) so must be used\nwith knowledge of what's safe to do given regex syntax. Assumes UnicodeSets-mode syntax.\n@param {string} expression Search target\n@param {string} needle Search as a regex pattern, with flags `su` applied\n@param {(match: RegExpExecArray, details: {\n  context: 'DEFAULT' | 'CHAR_CLASS';\n  negated: boolean;\n}) =\u003e void} callback\n@param {'DEFAULT' | 'CHAR_CLASS'} [context] All contexts if not specified\n*/\nexport function forEachUnescaped(expression, needle, callback, context) {\n  // Do this the easy way\n  replaceUnescaped(expression, needle, callback, context);\n}\n\n/**\nReturns a match object for the first unescaped instance of a regex pattern in the given context, or\n`null`.\n\nDoesn't skip over complete multicharacter tokens (only `\\` plus its folowing char) so must be used\nwith knowledge of what's safe to do given regex syntax. Assumes UnicodeSets-mode syntax.\n@param {string} expression Search target\n@param {string} needle Search as a regex pattern, with flags `su` applied\n@param {number} [pos] Offset to start the search\n@param {'DEFAULT' | 'CHAR_CLASS'} [context] All contexts if not specified\n@returns {RegExpExecArray | null}\n*/\nexport function execUnescaped(expression, needle, pos = 0, context) {\n  // Quick partial test; avoid the loop if not needed\n  if (!(new RegExp(needle, 'su').test(expression))) {\n    return null;\n  }\n  const re = new RegExp(`${needle}|(?\u003c$skip\u003e\\\\\\\\?.)`, 'gsu');\n  re.lastIndex = pos;\n  let numCharClassesOpen = 0;\n  let match;\n  while (match = re.exec(expression)) {\n    const {0: m, groups: {$skip}} = match;\n    if (!$skip \u0026\u0026 (!context || (context === Context.DEFAULT) === !numCharClassesOpen)) {\n      return match;\n    }\n    if (m === '[') {\n      numCharClassesOpen++;\n    } else if (m === ']' \u0026\u0026 numCharClassesOpen) {\n      numCharClassesOpen--;\n    }\n    // Avoid an infinite loop on zero-length matches\n    if (re.lastIndex == match.index) {\n      re.lastIndex++;\n    }\n  }\n  return null;\n}\n\n/**\nChecks whether an unescaped instance of a regex pattern appears in the given context.\n\nDoesn't skip over complete multicharacter tokens (only `\\` plus its folowing char) so must be used\nwith knowledge of what's safe to do given regex syntax. Assumes UnicodeSets-mode syntax.\n@param {string} expression Search target\n@param {string} needle Search as a regex pattern, with flags `su` applied\n@param {'DEFAULT' | 'CHAR_CLASS'} [context] All contexts if not specified\n@returns {boolean} Whether the pattern was found\n*/\nexport function hasUnescaped(expression, needle, context) {\n  // Do this the easy way\n  return !!execUnescaped(expression, needle, 0, context);\n}\n\n/**\nExtracts the full contents of a group (subpattern) from the given expression, accounting for\nescaped characters, nested groups, and character classes. The group is identified by the position\nwhere its contents start (the string index just after the group's opening delimiter). Returns the\nrest of the string if the group is unclosed.\n\nAssumes UnicodeSets-mode syntax.\n@param {string} expression Search target\n@param {number} contentsStartPos\n@returns {string}\n*/\nexport function getGroupContents(expression, contentsStartPos) {\n  const token = /\\\\?./gsu;\n  token.lastIndex = contentsStartPos;\n  let contentsEndPos = expression.length;\n  let numCharClassesOpen = 0;\n  // Starting search within an open group, after the group's opening\n  let numGroupsOpen = 1;\n  let match;\n  while (match = token.exec(expression)) {\n    const [m] = match;\n    if (m === '[') {\n      numCharClassesOpen++;\n    } else if (!numCharClassesOpen) {\n      if (m === '(') {\n        numGroupsOpen++;\n      } else if (m === ')') {\n        numGroupsOpen--;\n        if (!numGroupsOpen) {\n          contentsEndPos = match.index;\n          break;\n        }\n      }\n    } else if (m === ']') {\n      numCharClassesOpen--;\n    }\n  }\n  return expression.slice(contentsStartPos, contentsEndPos);\n}\n"],"version":3}
