regex-recursion
Advanced tools
Comparing version 2.0.0 to 3.1.0
@@ -1,23 +0,21 @@ | ||
var Regex;(Regex||={}).ext=(()=>{var y=Object.defineProperty;var de=Object.getOwnPropertyDescriptor;var ge=Object.getOwnPropertyNames;var me=Object.prototype.hasOwnProperty;var Ae=(e,t)=>{for(var n in t)y(e,n,{get:t[n],enumerable:!0})},he=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of ge(t))!me.call(e,s)&&s!==n&&y(e,s,{get:()=>t[s],enumerable:!(r=de(t,s))||r.enumerable});return e};var Ne=e=>he(y({},"__esModule",{value:!0}),e);var be={};Ae(be,{recursion:()=>Ee,rregex:()=>De});var E={DEFAULT:"DEFAULT",CHAR_CLASS:"CHAR_CLASS"};function A(e,t,n,r){let s=new RegExp(String.raw`${t}|(?<skip>\\?.)`,"gsu"),a=0,o="";for(let u of e.matchAll(s)){let{0:c,groups:{skip:l}}=u;if(!l&&(!r||r===E.DEFAULT==!a)){n instanceof Function?o+=n(u):o+=n;continue}c==="["?a++:c==="]"&&a&&a--,o+=c}return o}function I(e,t,n,r){A(e,t,n,r)}function F(e,t,n=0,r){if(!new RegExp(t,"su").test(e))return null;let s=new RegExp(String.raw`${t}|(?<skip>\\?.)`,"gsu");s.lastIndex=n;let a=0,o;for(;o=s.exec(e);){let{0:u,groups:{skip:c}}=o;if(!c&&(!r||r===E.DEFAULT==!a))return o;u==="["?a++:u==="]"&&a&&a--,s.lastIndex==o.index&&s.lastIndex++}return null}function h(e,t,n){return!!F(e,t,0,n)}function P(e,t){let n=/\\?./gsu;n.lastIndex=t;let r=e.length,s=0,a=1,o;for(;o=n.exec(e);){let[u]=o;if(u==="[")s++;else if(s)u==="]"&&s--;else if(u==="(")a++;else if(u===")"&&(a--,!a)){r=o.index;break}}return e.slice(t,r)}var L=class{#e;constructor(t){this.#e=t}toString(){return String(this.#e)}};function V(e,...t){if(Array.isArray(e?.raw))return new L(e.raw.flatMap((n,r)=>r<e.raw.length-1?[n,t[r]]:n).join(""));if(!t.length)return new L(e??"");throw new Error(`Unexpected arguments: ${JSON.stringify([e,...t])}`)}var p={DEFAULT:"R_DEFAULT",CHAR_CLASS:"R_CHAR_CLASS",GROUP_NAME:"R_GROUP_NAME",ENCLOSED_TOKEN:"R_ENCLOSED_TOKEN",INTERVAL_QUANTIFIER:"R_INTERVAL_QUANTIFIER",INVALID_INCOMPLETE_TOKEN:"R_INVALID_INCOMPLETE_TOKEN"},g={DEFAULT:"CC_DEFAULT",RANGE:"CC_RANGE",ENCLOSED_TOKEN:"CC_ENCLOSED_TOKEN",Q_TOKEN:"CC_Q_TOKEN",INVALID_INCOMPLETE_TOKEN:"CC_INVALID_INCOMPLETE_TOKEN"},x=(()=>{let e=!0;try{new RegExp("(?i-ms:)")}catch{e=!1}return e})(),k="&!#$%*+,.:;<=>?@^`~",$=String.raw`\(\?(?:[:=!>A-Za-z\-]|<[=!])`;function j(e,t){return t===E.CHAR_CLASS?e.replace(new RegExp(String.raw`[()\[\]{}|\\/\-${k}]`,"g"),"\\$&"):e.replace(/[()\[\]{}|\\^$*+?.]/g,"\\$&")}function G(e){return e.replace(new RegExp(String.raw`^([${k}])(?!\1)`),(t,n,r)=>`\\${t}${r+1===e.length?"":t}`)}function X(e){return e.replace(/^\^/,"\\^^")}function D(e,t){return A(e,String.raw`\\0(?!\d)`,"\\u{0}",t)}function Z(e,t,n){let r=0;for(let[s]of e.matchAll(new RegExp(`[${j(t+n,E.CHAR_CLASS)}]`,"g")))if(r+=s===t?1:-1,r<0)return n;return r>0?t:""}function v(e,t,n){let r=e.replace(/\\./gsu,"");if(r.at(-1)==="\\")return"\\";if(t===p.DEFAULT)return Z(r,"(",")");if(t===p.CHAR_CLASS&&!(n===g.ENCLOSED_TOKEN||n===g.Q_TOKEN))return Z(r,"[","]");if(t===p.ENCLOSED_TOKEN||t===p.INTERVAL_QUANTIFIER||n===g.ENCLOSED_TOKEN||n===g.Q_TOKEN){if(r.includes("}"))return"}"}else if(t===p.GROUP_NAME&&r.includes(">"))return">";return""}var J=new RegExp(String.raw` | ||
(?<groupN> \(\?< (?! [=!] ) | \\[gk]< ) | ||
| (?<enclosedT> \\[pPu]\{ ) | ||
| (?<qT> \\q\{ ) | ||
| (?<intervalQ> \{ ) | ||
| (?<incompleteT> \\ (?: | ||
$ | ||
| c (?! [A-Za-z] ) | ||
| u (?! [A-Fa-f\d]{4} ) [A-Fa-f\d]{0,3} | ||
| x (?! [A-Fa-f\d]{2} ) [A-Fa-f\d]? | ||
var Regex;(Regex||={}).ext=(()=>{var y=Object.defineProperty;var me=Object.getOwnPropertyDescriptor;var Ne=Object.getOwnPropertyNames;var Ae=Object.prototype.hasOwnProperty;var Te=(e,t)=>{for(var n in t)y(e,n,{get:t[n],enumerable:!0})},Se=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Ne(t))!Ae.call(e,o)&&o!==n&&y(e,o,{get:()=>t[o],enumerable:!(r=me(t,o))||r.enumerable});return e};var _e=e=>Se(y({},"__esModule",{value:!0}),e);var Xe={};Te(Xe,{recursion:()=>we,rregex:()=>Je});var w=Object.freeze({DEFAULT:"DEFAULT",CHAR_CLASS:"CHAR_CLASS"});function T(e,t,n,r){let o=new RegExp(`${t}|(?<skip>\\\\?.)`,"gsu"),i=0,s="";for(let a of e.matchAll(o)){let{0:u,groups:{skip:l}}=a;if(!l&&(!r||r===w.DEFAULT==!i)){n instanceof Function?s+=n(a):s+=n;continue}u==="["?i++:u==="]"&&i&&i--,s+=u}return s}function H(e,t,n,r){T(e,t,n,r)}function x(e,t,n=0,r){if(!new RegExp(t,"su").test(e))return null;let o=new RegExp(`${t}|(?<skip>\\\\?.)`,"gsu");o.lastIndex=n;let i=0,s;for(;s=o.exec(e);){let{0:a,groups:{skip:u}}=s;if(!u&&(!r||r===w.DEFAULT==!i))return s;a==="["?i++:a==="]"&&i&&i--,o.lastIndex==s.index&&o.lastIndex++}return null}function P(e,t,n){return!!x(e,t,0,n)}function oe(e,t){let n=/\\?./gsu;n.lastIndex=t;let r=e.length,o=0,i=1,s;for(;s=n.exec(e);){let[a]=s;if(a==="[")o++;else if(o)a==="]"&&o--;else if(a==="(")i++;else if(a===")"&&(i--,!i)){r=s.index;break}}return e.slice(t,r)}var U=class{#e;constructor(e){this.#e=e}toString(){return String(this.#e)}};function Le(e,...t){if(Array.isArray(e?.raw))return new U(e.raw.flatMap((n,r)=>r<e.raw.length-1?[n,t[r]]:n).join(""));if(!t.length)return new U(e??"");throw new Error(`Unexpected arguments: ${JSON.stringify([e,...t])}`)}var E={DEFAULT:"R_DEFAULT",CHAR_CLASS:"R_CHAR_CLASS",GROUP_NAME:"R_GROUP_NAME",ENCLOSED_TOKEN:"R_ENCLOSED_TOKEN",INTERVAL_QUANTIFIER:"R_INTERVAL_QUANTIFIER",INVALID_INCOMPLETE_TOKEN:"R_INVALID_INCOMPLETE_TOKEN"},g={DEFAULT:"CC_DEFAULT",RANGE:"CC_RANGE",ENCLOSED_TOKEN:"CC_ENCLOSED_TOKEN",Q_TOKEN:"CC_Q_TOKEN",INVALID_INCOMPLETE_TOKEN:"CC_INVALID_INCOMPLETE_TOKEN"},b=(()=>{try{new RegExp("(?i:)")}catch{return!1}return!0})(),Ie=(()=>{try{new RegExp("","v")}catch{return!1}return!0})(),v="&!#$%*+,.:;<=>?@^`~",Q=String.raw`\(\?<(?![=!])(?<captureName>[^>]+)>`,q=String.raw`\((?!\?)(?!(?<=\(\?\()DEFINE\))|${Q}`,W=String.raw`\(\?(?:[:=!>A-Za-z\-]|<[=!]|\(DEFINE\))`;function ie(e,t){return t===w.CHAR_CLASS?e.replace(new RegExp(String.raw`[()\[\]{}|\\/\-${v}]`,"g"),"\\$&"):e.replace(/[()\[\]{}|\\^$*+?.]/g,"\\$&")}function ae(e){return e.replace(new RegExp(`^([${v}])(?!\\1)`),(t,n,r)=>`\\${t}${r+1===e.length?"":t}`)}function $e(e){return e.replace(/^\^/,"\\^^")}function z(e,t){return T(e,String.raw`\\0(?!\d)`,"\\u{0}",t)}function X(e,t,n){let r=0;for(let[o]of e.matchAll(new RegExp(`[${ie(t+n,w.CHAR_CLASS)}]`,"g")))if(r+=o===t?1:-1,r<0)return n;return r>0?t:""}function Re(e,t,n){let r=e.replace(/\\./gsu,"");if(r.endsWith("\\"))return"\\";if(t===E.DEFAULT)return X(r,"(",")");if(t===E.CHAR_CLASS&&!(n===g.ENCLOSED_TOKEN||n===g.Q_TOKEN))return X(r,"[","]");if(t===E.ENCLOSED_TOKEN||t===E.INTERVAL_QUANTIFIER||n===g.ENCLOSED_TOKEN||n===g.Q_TOKEN){if(r.includes("}"))return"}"}else if(t===E.GROUP_NAME&&r.includes(">"))return">";return""}var Y=new RegExp(String.raw` | ||
(?<groupN>\(\?<(?![=!])|\\[gk]<) | ||
| (?<enclosedT>\\[pPu]\{) | ||
| (?<qT>\\q\{) | ||
| (?<intervalQ>\{) | ||
| (?<incompleteT>\\(?: $ | ||
| c(?![A-Za-z]) | ||
| u(?![A-Fa-f\d]{4})[A-Fa-f\d]{0,3} | ||
| x(?![A-Fa-f\d]{2})[A-Fa-f\d]? | ||
) | ||
) | ||
| -- | ||
| \\? . | ||
`.replace(/\s+/g,""),"gsu");function U(e,{regexContext:t=p.DEFAULT,charClassContext:n=g.DEFAULT,charClassDepth:r=0,lastPos:s=0}){J.lastIndex=s;let a;for(;a=J.exec(e);){let{0:o,groups:{groupN:u,enclosedT:c,qT:l,intervalQ:f,incompleteT:i}}=a;o==="["?(r++,t=p.CHAR_CLASS,n=g.DEFAULT):o==="]"&&t===p.CHAR_CLASS?(r&&r--,r||(t=p.DEFAULT),n=g.DEFAULT):t===p.CHAR_CLASS?i?n=g.INVALID_INCOMPLETE_TOKEN:o==="-"?n=g.RANGE:c?n=g.ENCLOSED_TOKEN:l?n=g.Q_TOKEN:(o==="}"&&(n===g.ENCLOSED_TOKEN||n===g.Q_TOKEN)||n===g.INVALID_INCOMPLETE_TOKEN||n===g.RANGE)&&(n=g.DEFAULT):i?t=p.INVALID_INCOMPLETE_TOKEN:u?t=p.GROUP_NAME:c?t=p.ENCLOSED_TOKEN:f?t=p.INTERVAL_QUANTIFIER:(o===">"&&t===p.GROUP_NAME||o==="}"&&(t===p.ENCLOSED_TOKEN||t===p.INTERVAL_QUANTIFIER)||t===p.INVALID_INCOMPLETE_TOKEN)&&(t=p.DEFAULT)}return{regexContext:t,charClassContext:n,charClassDepth:r,lastPos:e.length}}function b(e){let t=0;return I(e,String.raw`\((?:(?!\?)|\?<[^>]+>)`,()=>t++,E.DEFAULT),t}function Y(e,t){return A(e,String.raw`\\(?<num>[1-9]\d*)`,({groups:{num:n}})=>`\\${+n+t}`,E.DEFAULT)}var we=["Basic_Emoji","Emoji_Keycap_Sequence","RGI_Emoji_Modifier_Sequence","RGI_Emoji_Flag_Sequence","RGI_Emoji_Tag_Sequence","RGI_Emoji_ZWJ_Sequence","RGI_Emoji"].join("|"),Se=new RegExp(String.raw` | ||
\\ (?: | ||
c [A-Za-z] | ||
| p \{ (?<pStrProp> ${we} ) \} | ||
| [pP] \{ [^\}]+ \} | ||
| (?<qStrProp> q ) | ||
| u (?: [A-Fa-f\d]{4} | \{ [A-Fa-f\d]+ \} ) | ||
| x [A-Fa-f\d]{2} | ||
| \\?. | ||
`.replace(/\s+/g,""),"gsu");function B(e,{regexContext:t=E.DEFAULT,charClassContext:n=g.DEFAULT,charClassDepth:r=0,lastPos:o=0}){Y.lastIndex=o;let i;for(;i=Y.exec(e);){let{0:s,groups:{groupN:a,enclosedT:u,qT:l,intervalQ:p,incompleteT:c}}=i;s==="["?(r++,t=E.CHAR_CLASS,n=g.DEFAULT):s==="]"&&t===E.CHAR_CLASS?(r&&r--,r||(t=E.DEFAULT),n=g.DEFAULT):t===E.CHAR_CLASS?c?n=g.INVALID_INCOMPLETE_TOKEN:s==="-"?n=g.RANGE:u?n=g.ENCLOSED_TOKEN:l?n=g.Q_TOKEN:(s==="}"&&(n===g.ENCLOSED_TOKEN||n===g.Q_TOKEN)||n===g.INVALID_INCOMPLETE_TOKEN||n===g.RANGE)&&(n=g.DEFAULT):c?t=E.INVALID_INCOMPLETE_TOKEN:a?t=E.GROUP_NAME:u?t=E.ENCLOSED_TOKEN:p?t=E.INTERVAL_QUANTIFIER:(s===">"&&t===E.GROUP_NAME||s==="}"&&(t===E.ENCLOSED_TOKEN||t===E.INTERVAL_QUANTIFIER)||t===E.INVALID_INCOMPLETE_TOKEN)&&(t=E.DEFAULT)}return{regexContext:t,charClassContext:n,charClassDepth:r,lastPos:e.length}}function k(e){let t=0;return H(e,q,()=>t++,w.DEFAULT),t}function De(e,t){return T(e,String.raw`\\(?<num>[1-9]\d*)`,({groups:{num:n}})=>`\\${+n+t}`,w.DEFAULT)}var Oe=["Basic_Emoji","Emoji_Keycap_Sequence","RGI_Emoji_Modifier_Sequence","RGI_Emoji_Flag_Sequence","RGI_Emoji_Tag_Sequence","RGI_Emoji_ZWJ_Sequence","RGI_Emoji"].join("|"),Ce=new RegExp(String.raw` | ||
\\(?: c[A-Za-z] | ||
| p\{(?<pStrProp>${Oe})\} | ||
| [pP]\{[^\}]+\} | ||
| (?<qStrProp>q) | ||
| u(?:[A-Fa-f\d]{4}|\{[A-Fa-f\d]+\}) | ||
| x[A-Fa-f\d]{2} | ||
| . | ||
@@ -28,35 +26,36 @@ ) | ||
| . | ||
`.replace(/\s+/g,""),"gsu");function Q(e){let t=!1,n;for(let{0:r,groups:s}of e.matchAll(Se)){if(s.pStrProp||s.qStrProp||r==="["&&t)return!0;if(["-","--","&&"].includes(r))t=!1;else if(!["[","]"].includes(r)){if(t||n==="]")return!0;t=!0}n=r}return!1}function H(e,t,n){let r={raw:[]},s=[],a={};return e.raw.forEach((o,u)=>{let c=n(o,{...a,lastPos:0});if(r.raw.push(c.transformed),a=c.runningContext,u<e.raw.length-1){let l=t[u];if(l instanceof L){let f=n(l,{...a,lastPos:0});s.push(V(f.transformed)),a=f.runningContext}else s.push(l)}}),{template:r,values:s}}function ee(e){if(!h(e,String.raw`\(\?>`,E.DEFAULT))return e;let t=new RegExp(String.raw`(?<noncapturingStart>${$})|(?<capturingStart>\((?:\?<[^>]+>)?)|(?<backrefNum>\\[1-9]\d*)|\\?.`,"gsu"),n="(?>",r="(?:(?=(",s=0,a=0,o=NaN,u;do{u=!1;let c=0,l=0,f=!1,i;for(t.lastIndex=Number.isNaN(o)?0:o+r.length;i=t.exec(e);){let{0:m,index:d,groups:{backrefNum:_,capturingStart:R,noncapturingStart:C}}=i;if(m==="[")c++;else if(c)m==="]"&&c--;else if(m===n&&!f)o=d,f=!0;else if(f&&C)l++;else if(R)f&&l++,s++;else if(m===")"&&f){if(!l){a++,e=`${e.slice(0,o)}${r}${e.slice(o+n.length,d)}))\\k<$$${a+s}>)${e.slice(d+1)}`,u=!0;break}l--}else if(_)throw new Error(`Invalid decimal escape "${m}" in interpolated regex; cannot be used with atomic group`)}}while(u);return e=A(e,String.raw`\\k<\$\$(?<backrefNum>\d+)>`,({groups:{backrefNum:c}})=>`\\${c}`,E.DEFAULT),e}var Te=new RegExp(String.raw` | ||
${$} | ||
`.replace(/\s+/g,""),"gsu");function ee(e){let t=!1,n;for(let{0:r,groups:o}of e.matchAll(Ce)){if(o.pStrProp||o.qStrProp||r==="["&&t)return!0;if(["-","--","&&"].includes(r))t=!1;else if(!["[","]"].includes(r)){if(t||n==="]")return!0;t=!0}n=r}return!1}function te(e,t,n){let r={raw:[]},o=[],i={};return e.raw.forEach((s,a)=>{let u=n(s,{...i,lastPos:0});if(r.raw.push(u.transformed),i=u.runningContext,a<e.raw.length-1){let l=t[a];if(l instanceof U){let p=n(l,{...i,lastPos:0});o.push(Le(p.transformed)),i=p.runningContext}else o.push(l)}}),{template:r,substitutions:o}}var Fe=new RegExp(String.raw` | ||
${W} | ||
| \(\?< | ||
| (?<backrefNum> \\[1-9]\d* ) | ||
| \\? . | ||
`.replace(/\s+/g,""),"gsu");function te(e,t){e=String(e);let n="",r="";for(let{0:s,groups:{backrefNum:a}}of e.matchAll(Te)){n+=s,t=U(n,t);let{regexContext:o}=t;if(o===p.DEFAULT)if(s==="(")r+="(?:";else{if(a)throw new Error(`Invalid decimal escape "${s}" with implicit flag n; replace with named backreference`);r+=s}else r+=s}return{transformed:r,runningContext:t}}var ne=/^\s$/,Le=/^\\[\s#]$/,re=/^[ \t]$/,_e=/^\\[ \t]$/,Ce=new RegExp(String.raw` | ||
\\ (?: | ||
[gk] < | ||
| [pPu] \{ | ||
| c [A-Za-z] | ||
| u [A-Fa-f\d]{4} | ||
| x [A-Fa-f\d]{2} | ||
| 0 \d+ | ||
| (?<backrefNum>\\[1-9]\d*) | ||
| \\?. | ||
`.replace(/\s+/g,""),"gsu");function Ue(e,t){e=String(e);let n="",r="";for(let{0:o,groups:{backrefNum:i}}of e.matchAll(Fe)){n+=o,t=B(n,t);let{regexContext:s}=t;if(s===E.DEFAULT)if(o==="(")r+="(?:";else{if(i)throw new Error(`Invalid decimal escape "${o}" with implicit flag n; replace with named backreference`);r+=o}else r+=o}return{transformed:r,runningContext:t}}var ne=/^\s$/,be=/^\\[\s#]$/,re=/^[ \t]$/,ke=/^\\[ \t]$/,Pe=new RegExp(String.raw` | ||
\\(?: [gk]< | ||
| [pPu]\{ | ||
| c[A-Za-z] | ||
| u[A-Fa-f\d]{4} | ||
| x[A-Fa-f\d]{2} | ||
| 0\d+ | ||
) | ||
| \[\^ | ||
| ${$} | ||
| ${W} | ||
| \(\?< | ||
| (?<dp> [${k}] ) \k<dp> | ||
| (?<dp>[${v}])\k<dp> | ||
| -- | ||
| \\? . | ||
`.replace(/\s+/g,""),"gsu");function oe(e,t){e=String(e);let n=!1,r=!1,s=!1,a="",o="",u="",c="",l=!1,f=(i,{prefix:m=!0,postfix:d=!1}={})=>(i=(l&&m?"(?:)":"")+i+(d?"(?:)":""),l=!1,i);for(let[i]of e.matchAll(Ce)){if(s){i===` | ||
`&&(s=!1,l=!0);continue}if(n){if(ne.test(i))continue;n=!1,l=!0}else if(r){if(re.test(i))continue;r=!1}a+=i,t=U(a,t);let{regexContext:m,charClassContext:d}=t;if(i==="-"&&m===p.CHAR_CLASS&&c===g.RANGE)throw new Error("Invalid unescaped hyphen as the end value for a range");if(m===p.DEFAULT&&/^(?:[?*+]|\?\?)$/.test(i)||m===p.INTERVAL_QUANTIFIER&&i==="{")o+=f(i,{prefix:!1,postfix:u==="("&&i==="?"});else if(m===p.DEFAULT)ne.test(i)?n=!0:i.startsWith("#")?s=!0:Le.test(i)?o+=f(i[1],{prefix:!1}):o+=f(i);else if(m===p.CHAR_CLASS&&i!=="["&&i!=="[^")if(re.test(i)&&(d===g.DEFAULT||d===g.RANGE||d===g.Q_TOKEN))r=!0;else{if(d===g.INVALID_INCOMPLETE_TOKEN)throw new Error(`Invalid incomplete token in character class: "${i}"`);_e.test(i)&&(d===g.DEFAULT||d===g.Q_TOKEN)?o+=f(i[1],{prefix:!1}):d===g.DEFAULT?o+=f(G(D(i))):o+=f(i)}else o+=f(i);n||r||s||(u=i,c=d)}return{transformed:o,runningContext:t}}function se(e){let t=String.raw`\(\?:\)`;return e=A(e,`(?:${t}){2,}`,"(?:)",E.DEFAULT),e=A(e,String.raw`^${t}(?![?*+{])|${t}$|${t}(?=[()|$\\])|(?<=[()|>^]|\(\?(?:[:=!]|<[=!]))${t}`,"",E.DEFAULT),e}var ie=String.raw`\\g<(?<subroutineName>[^>&]+)>`,q=String.raw`\((?:(?!\?)|\?<(?![=!])(?<captureName>[^>]+)>)`,O=new RegExp(String.raw` | ||
${ie} | ||
| (?<capturingStart> ${q} ) | ||
| \\ (?<backrefNum> [1-9]\d* ) | ||
| \\k< (?<backrefName> [^>]+ ) > | ||
| \\? . | ||
`.replace(/\s+/g,""),"gsu");function ae(e){if(!h(e,"\\\\g<",E.DEFAULT))return e;let t=$e(e),n=[0],r=Re(e),s=0,a=0,o=new Map,u=[],c=0,l=e,f;for(O.lastIndex=0;f=O.exec(l);){let{0:i,index:m,groups:{subroutineName:d,capturingStart:_,backrefNum:R,backrefName:C}}=f;if(i==="[")c++;else if(c)i==="]"&&c--;else{let N=o.size?o.get(u.at(-1)):null;if(d){if(!t.has(d))throw new Error(`Invalid named capture referenced by subroutine ${i}`);if(o.has(d))throw new Error(`Subroutine ${i} followed a recursive reference`);let w=t.get(d)[0].contents,S=b(w)+1;a+=S;let T=`(${w})`;o.set(d,{contents:w,unclosedGroupCount:Ue(T),numCaptures:S}),u.push(d),l=K(l,m,i,T),O.lastIndex-=i.length}else if(_)o.size?(i!=="("&&(l=K(l,m,i,"("),O.lastIndex-=i.length),n.push(n.at(-1)+N.numCaptures)):(s++,n.length===s&&n.push(n.at(-1)));else if(R){let w=+R,S;if(o.size?w>r&&(S=s+a-r-N.numCaptures):S=n[w],S){let T=`\\${w+S}`;l=K(l,m,i,T),O.lastIndex+=T.length-i.length}}else if(C){if(o.size){let w=!1;for(let S of u){let T=o.get(S).contents;if(h(T,String.raw`\(\?<${C}>`,E.DEFAULT)){w=!0;break}}if(w){let T=`\\${Ie(e,C)+1}`;l=K(l,m,i,T),O.lastIndex-=i.length}}}else i===")"&&o.size&&(N.unclosedGroupCount--,N.unclosedGroupCount||o.delete(u.pop()))}}return l}function Re(e){let t=new Set;I(e,ie,({groups:{subroutineName:a}})=>{t.add(a)},E.DEFAULT);let n=0,r=0,s;for(;s=F(e,q,r,E.DEFAULT);){let{0:a,index:o,groups:{captureName:u}}=s;if(t.has(u))break;n++,r=o+a.length}return n}function Ie(e,t){let n=0,r=0,s;for(;s=F(e,q,r,E.DEFAULT);){let{0:a,index:o,groups:{captureName:u}}=s;if(u===t)break;n++,r=o+a.length}return n}function K(e,t,n,r){return e.slice(0,t)+r+e.slice(t+n.length)}function $e(e){let t=new Map;return I(e,String.raw`\(\?<(?<captureName>[^>]+)>`,({0:n,index:r,groups:{captureName:s}})=>{t.has(s)||t.set(s,[]);let a=r+n.length,o=P(e,a);t.get(s).push({contents:o,endPos:a+o.length})},E.DEFAULT),t}function Ue(e){let t=0;return I(e,String.raw`\(`,()=>t++,E.DEFAULT),t}var z=function(e,...t){let n=this instanceof Function?this:RegExp;if(Array.isArray(e?.raw))return B(n,{flags:""},e,...t);if((typeof e=="string"||e===void 0)&&!t.length)return B.bind(null,n,{flags:e});if({}.toString.call(e)==="[object Object]"&&!t.length)return B.bind(null,n,e);throw new Error(`Unexpected arguments: ${JSON.stringify([e,...t])}`)};function B(e,t,n,...r){let{flags:s="",postprocessors:a=[],__flagN:o=!0,__flagX:u=!0,__rake:c=!0}=t;if(/[vu]/.test(s))throw new Error("Flags v/u cannot be explicitly added since v is always enabled");u&&({template:n,values:r}=H(n,r,oe)),o&&({template:n,values:r}=H(n,r,te));let l=0,f="",i={};return n.raw.forEach((m,d)=>{let _=n.raw[d]||n.raw[d+1];l+=b(m),f+=D(m,E.CHAR_CLASS),i=U(f,i);let{regexContext:R,charClassContext:C}=i;if(d<n.raw.length-1){let N=r[d];f+=Oe(N,s,R,C,_,l),(N instanceof RegExp||N instanceof L)&&(l+=b(N.source||String(N)))}}),[...a,ee,ae,...c?[se]:[]].forEach(m=>f=m(f)),new e(f,`v${s}`)}function Oe(e,t,n,r,s,a){if(e instanceof RegExp&&n!==p.DEFAULT)throw new Error("Cannot interpolate a RegExp at this position because the syntax context does not match");if(n===p.INVALID_INCOMPLETE_TOKEN||r===g.INVALID_INCOMPLETE_TOKEN)throw new Error("Interpolation preceded by invalid incomplete token");let o=e instanceof L,u;if(!(e instanceof RegExp)){e=String(e),o||(u=j(e,n===p.CHAR_CLASS?E.CHAR_CLASS:E.DEFAULT));let c=v(u||e,n,r);if(c)throw new Error(`Unescaped stray "${c}" in the interpolated value would have side effects outside it`)}if(n===p.ENCLOSED_TOKEN||n===p.INTERVAL_QUANTIFIER||n===p.GROUP_NAME||r===g.ENCLOSED_TOKEN||r===g.Q_TOKEN)return o?e:u;if(n===p.CHAR_CLASS){if(o){if(h(e,"^-|^&&|-$|&&$"))throw new Error("In character classes, a partial cannot use a range or set operator at its boundary; move the operation into the partial or the operator outside of it");let c=X(G(e));return Q(e)?`[${c}]`:D(c)}return Q(u)?`[${u}]`:u}if(e instanceof RegExp){let c=xe(e,t),l=Y(c.value,a);return c.usedModifier?l:`(?:${l})`}return o?`(?:${e})`:s?`(?:${u})`:u}function xe(e,t){let n={i:null,m:null,s:null},r="\\n\\r\\u2028\\u2029",s=e.source;if(e.ignoreCase!==t.includes("i"))if(x)n.i=e.ignoreCase;else throw new Error("Pattern modifiers not supported, so the value of flag i on the interpolated RegExp must match the outer regex");if(e.dotAll!==t.includes("s")&&(x?n.s=e.dotAll:s=A(s,"\\.",e.dotAll?"[^]":`[^${r}]`,E.DEFAULT)),e.multiline!==t.includes("m")&&(x?n.m=e.multiline:(s=A(s,"\\^",e.multiline?`(?<=^|[${r}])`:"(?<![^])",E.DEFAULT),s=A(s,"\\$",e.multiline?`(?=$|[${r}])`:"(?![^])",E.DEFAULT))),x){let a=Object.keys(n),o=a.filter(c=>n[c]===!0).join(""),u=a.filter(c=>n[c]===!1).join("");if(u&&(o+=`-${u}`),o)return{value:`(?${o}:${s})`,usedModifier:!0}}return{value:s}}function De(e,...t){let n=(e?.postprocessors||[]).concat(Ee),r=this instanceof Function?z.bind(this):z;if(Array.isArray(e?.raw))return r({flags:"",postprocessors:n})(e,...t);if((typeof e=="string"||e===void 0)&&!t.length)return r({flags:e,postprocessors:n});if({}.toString.call(e)==="[object Object]"&&!t.length)return r({...e,postprocessors:n});throw new Error(`Unexpected arguments: ${JSON.stringify([e,...t])}`)}var pe=String.raw`\\g<(?<gRName>[^>&]+)&R=(?<gRDepth>\d+)>`,W=String.raw`\(\?R=(?<rDepth>\d+)\)|${pe}`,M=new RegExp(String.raw`\(\?<(?![=!])(?<capturingGroupName>[^>]+)>|${W}|\\?.`,"gsu");function Ee(e){if(!h(e,W,E.DEFAULT))return e;if(h(e,String.raw`\\[1-9]`,E.DEFAULT))throw new Error("Invalid decimal escape in interpolated regex; cannot be used with recursion");let t=new Map,n=0,r;for(M.lastIndex=0;r=M.exec(e);){let{0:s,groups:{capturingGroupName:a,rDepth:o,gRName:u,gRDepth:c}}=r;if(s==="[")n++;else if(n)s==="]"&&n--;else if(a)t.set(a,M.lastIndex);else if(o){let l=+o;ue(l);let f=e.slice(0,r.index),i=e.slice(M.lastIndex);return ce(i),le(f,i,l)}else if(u){let l=+c;ue(l);let f=`Recursion via \\g<${u}&R=${c}> must be used within the referenced group`;if(!t.has(u))throw new Error(f);let i=t.get(u),m=P(e,i);if(!h(m,pe,E.DEFAULT))throw new Error(f);let d=e.slice(i,r.index),_=m.slice(d.length+s.length);return ce(_),e.slice(0,i)+le(d,_,l)+e.slice(i+m.length)}}throw new Error("Unexpected error; recursion was not processed")}function ue(e){if(e<2||e>100)throw new Error(`Max depth must be between 2 and 100; used ${e}`)}function ce(e){if(h(e,W,E.DEFAULT))throw new Error("Cannot use recursion more than once in a pattern")}function le(e,t,n){let r=n-1;return`${e}${fe(`(?:${e}`,r)}(?:)${fe(`${t})`,r,"backward")}${t}`}function fe(e,t,n="forward"){let s=o=>n==="backward"?t-o+2-1:o+2,a="";for(let o=0;o<t;o++){let u=s(o);a+=A(e,String.raw`\(\?<(?<captureName>[^>]+)>|\\k<(?<backref>[^>]+)>`,({groups:{captureName:c,backref:l}})=>{let f=`_$${u}`;return c?`(?<${c}${f}>`:`\\k<${l}${f}>`},E.DEFAULT)}return a}return Ne(be);})(); | ||
/*! Bundled license information: | ||
regex/src/index.js: | ||
(*! regex 2.0.0; Steven Levithan; MIT License *) | ||
*/ | ||
//# sourceMappingURL=regex-recursion.min.js.map | ||
| \\?. | ||
`.replace(/\s+/g,""),"gsu");function ve(e,t){e=String(e);let n=!1,r=!1,o=!1,i="",s="",a="",u="",l=!1,p=(c,{prefix:f=!0,postfix:d=!1}={})=>(c=(l&&f?"(?:)":"")+c+(d?"(?:)":""),l=!1,c);for(let[c]of e.matchAll(Pe)){if(o){c===` | ||
`&&(o=!1,l=!0);continue}if(n){if(ne.test(c))continue;n=!1,l=!0}else if(r){if(re.test(c))continue;r=!1}i+=c,t=B(i,t);let{regexContext:f,charClassContext:d}=t;if(c==="-"&&f===E.CHAR_CLASS&&u===g.RANGE)throw new Error("Invalid unescaped hyphen as the end value for a range");if(f===E.DEFAULT&&/^(?:[?*+]|\?\?)$/.test(c)||f===E.INTERVAL_QUANTIFIER&&c==="{")s+=p(c,{prefix:!1,postfix:a==="("&&c==="?"});else if(f===E.DEFAULT)ne.test(c)?n=!0:c.startsWith("#")?o=!0:be.test(c)?s+=p(c[1],{prefix:!1}):s+=p(c);else if(f===E.CHAR_CLASS&&c!=="["&&c!=="[^")if(re.test(c)&&(d===g.DEFAULT||d===g.RANGE||d===g.Q_TOKEN))r=!0;else{if(d===g.INVALID_INCOMPLETE_TOKEN)throw new Error(`Invalid incomplete token in character class: "${c}"`);ke.test(c)&&(d===g.DEFAULT||d===g.Q_TOKEN)?s+=p(c[1],{prefix:!1}):d===g.DEFAULT?s+=p(ae(z(c))):s+=p(c)}else s+=p(c);n||r||o||(a=c,u=d)}return{transformed:s,runningContext:t}}function Ge(e){let t=String.raw`\(\?:\)`;return e=T(e,`(?:${t}){2,}`,"(?:)",w.DEFAULT),e=T(e,String.raw`${t}(?=[)|.[$\\]|\((?!DEFINE)|$)|(?<=[()|.\]^>]|\\[bBdDfnrsStvwW]|\(\?(?:[:=!]|<[=!])|^)${t}(?![?*+{])`,"",w.DEFAULT),e}function ye(e){if(!P(e,"\\(\\?>",w.DEFAULT))return e;let t=new RegExp(String.raw`(?<noncapturingStart>${W})|(?<capturingStart>\((?:\?<[^>]+>)?)|(?<backrefNum>\\[1-9]\d*)|\\?.`,"gsu"),n="(?>",r="(?:(?=(",o=0,i=0,s=NaN,a;do{a=!1;let u=0,l=0,p=!1,c;for(t.lastIndex=Number.isNaN(s)?0:s+r.length;c=t.exec(e);){let{0:f,index:d,groups:{backrefNum:h,capturingStart:A,noncapturingStart:N}}=c;if(f==="[")u++;else if(u)f==="]"&&u--;else if(f===n&&!p)s=d,p=!0;else if(p&&N)l++;else if(A)p&&l++,o++;else if(f===")"&&p){if(!l){i++,e=`${e.slice(0,s)}${r}${e.slice(s+n.length,d)}))\\k<$$${i+o}>)${e.slice(d+1)}`,a=!0;break}l--}else if(h)throw new Error(`Invalid decimal escape "${f}" in interpolated regex; cannot be used with atomic group`)}}while(a);return e=T(e,String.raw`\\k<\$\$(?<backrefNum>\d+)>`,({groups:{backrefNum:u}})=>`\\${u}`,w.DEFAULT),e}function Ke(e){let t=ue(e,{includeContents:!0}),n=Ve(e,t);return je(n,t)}var Me=String.raw`\\g<(?<subroutineName>[^>&]+)>`,F=new RegExp(String.raw` | ||
${Me} | ||
| (?<capturingStart>${q}) | ||
| \\(?<backrefNum>[1-9]\d*) | ||
| \\k<(?<backrefName>[^>]+)> | ||
| \\?. | ||
`.replace(/\s+/g,""),"gsu");function Ve(e,t){if(!P(e,"\\\\g<",w.DEFAULT))return e;let n=P(e,"\\\\(?:[1-9]|k<[^>]+>)",w.DEFAULT),r=n?"(":"(?:",o=new Map,i=[],s=[0],a=0,u=0,l=0,p=0,c=0,f=e,d;for(F.lastIndex=0;d=F.exec(f);){let{0:h,index:A,groups:{subroutineName:N,capturingStart:O,backrefNum:L,backrefName:R}}=d;if(h==="[")c++;else if(c)h==="]"&&c--;else if(N){if(!t.has(N))throw new Error(`Invalid named capture referenced by subroutine ${h}`);if(o.has(N))throw new Error(`Subroutine ${h} followed a recursive reference`);let m=t.get(N).contents,I=`${r}${m})`;n&&(l=0,u++),o.set(N,{unclosedGroupCount:He(I)}),i.push(N),f=V(f,A,h,I),F.lastIndex-=h.length-r.length}else if(O)o.size?(n&&(l++,u++),h!=="("&&(f=V(f,A,h,r),F.lastIndex-=h.length-r.length)):n&&(s.push(M(s)+1+u-p),p=u,a++);else if((L||R)&&o.size){let m=L?+L:t.get(R)?.groupNum,I=!1;for(let _ of i){let $=t.get(_);if(m>=$.groupNum&&m<=$.groupNum+$.numCaptures){I=!0;break}}if(I){let _=t.get(M(i)),$=a+u-l,C=`\\k<$$b${m}s${$}r${_.groupNum}c${_.numCaptures}>`;f=V(f,A,h,C),F.lastIndex+=C.length-h.length}}else if(h===")"&&o.size){let m=o.get(M(i));m.unclosedGroupCount--,m.unclosedGroupCount||o.delete(i.pop())}}return n&&(f=T(f,String.raw`\\(?:(?<bNum>[1-9]\d*)|k<\$\$b(?<bNumSub>\d+)s(?<subNum>\d+)r(?<refNum>\d+)c(?<refCaps>\d+)>)`,({0:h,groups:{bNum:A,bNumSub:N,subNum:O,refNum:L,refCaps:R}})=>{if(A){let C=+A;if(C>s.length-1)throw new Error(`Backref "${h}" greater than number of captures`);return`\\${s[C]}`}let m=+N,I=+O,_=+L,$=+R;return m<_||m>_+$?`\\${s[m]}`:`\\${I-_+m}`},w.DEFAULT)),f}var K=new RegExp(String.raw`${Q}|\(\?:\)|(?<invalid>\\?.)`,"gsu");function je(e,t){let n=x(e,String.raw`\(\?\(DEFINE\)`,0,w.DEFAULT);if(!n)return e;let r=se(e,n);if(r.afterPos<e.length)throw new Error("DEFINE group allowed only at the end of a regex");if(r.afterPos>e.length)throw new Error("DEFINE group is unclosed");let o;for(K.lastIndex=0;o=K.exec(r.contents);){let{captureName:i,invalid:s}=o.groups;if(i){let a=se(r.contents,o),u;if(!t.get(i).isUnique)u=i;else{let l=ue(a.contents);for(let p of l.keys())if(!t.get(p).isUnique){u=p;break}}if(u)throw new Error(`Duplicate group name "${u}" within DEFINE`);K.lastIndex=a.afterPos}else if(s)throw new Error("DEFINE group includes unsupported syntax at top level")}return e.slice(0,n.index)}function He(e){let t=0;return H(e,"\\(",()=>t++,w.DEFAULT),t}function xe(e,t){let n=0,r=0,o;for(;o=x(e,q,r,w.DEFAULT);){let{0:i,index:s,groups:{captureName:a}}=o;if(n++,a===t)break;r=s+i.length}return n}function se(e,t){let n=t.index+t[0].length,r=oe(e,n),o=n+r.length+1;return{contents:r,afterPos:o}}function ue(e,{includeContents:t}={}){let n=new Map;return H(e,Q,({0:r,index:o,groups:{captureName:i}})=>{if(n.has(i))n.get(i).isUnique=!1;else{let s={isUnique:!0};if(t){let a=oe(e,o+r.length);Object.assign(s,{contents:a,groupNum:xe(e,i),numCaptures:k(a)})}n.set(i,s)}},w.DEFAULT),n}function M(e){return e[e.length-1]}function V(e,t,n,r){return e.slice(0,t)+r+e.slice(t+n.length)}var Qe="&!#%,:;<=>@`~",qe=new RegExp(String.raw` | ||
\[\^?-? | ||
| --?\] | ||
| (?<dp>[${v}])\k<dp> | ||
| -- | ||
| \\(?<vOnlyEscape>[${Qe}]) | ||
| \\[pPu]\{[^}]+\} | ||
| \\?. | ||
`.replace(/\s+/g,""),"gsu");function We(e,t){let n='Invalid unescaped "-" in character class',r=!1,o=!1,i="";for(let{0:s,groups:{dp:a,vOnlyEscape:u}}of e.matchAll(qe)){if(s[0]==="["){if(r)throw new Error("Invalid nested character class when flag v not supported; possibly from interpolation");if(s.endsWith("-"))throw new Error(n);r=!0,o=s[1]==="^"}else if(s.endsWith("]")){if(s[0]==="-")throw new Error(n);r=o=!1}else if(r){if(s==="&&"||s==="--")throw new Error(`Invalid set operator "${s}" when flag v not supported`);if(a)throw new Error(`Invalid double punctuator "${s}", reserved by flag v`);if("(){}/|".includes(s))throw new Error(`Invalid unescaped "${s}" in character class`);if(o&&s.startsWith("\\P")&&t.includes("i"))throw new Error("Negated \\P in negated character class with flag i works differently with flag v");if(u){i+=u;continue}}i+=s}return i}function Z(e,...t){let n=this instanceof Function?this:RegExp;if(Array.isArray(e?.raw))return j(n,{flags:""},e,...t);if((typeof e=="string"||e===void 0)&&!t.length)return j.bind(null,n,{flags:e});if({}.toString.call(e)==="[object Object]"&&!t.length)return j.bind(null,n,e);throw new Error(`Unexpected arguments: ${JSON.stringify([e,...t])}`)}function j(e,t,n,...r){let{flags:o="",postprocessors:i=[],__extendSyntax:s=t.__flagN??!0,__flagN:a=!0,__flagV:u=Ie,__flagX:l=!0,__rake:p=!0}=t;if(/[vu]/.test(o))throw new Error("Flags v/u cannot be explicitly added");l&&({template:n,substitutions:r}=te(n,r,ve)),a&&({template:n,substitutions:r}=te(n,r,Ue));let c=0,f="",d={};n.raw.forEach((A,N)=>{let O=!!(n.raw[N]||n.raw[N+1]);c+=k(A),f+=z(A,w.CHAR_CLASS),d=B(f,d);let{regexContext:L,charClassContext:R}=d;if(N<n.raw.length-1){let m=r[N];f+=ze(m,o,L,R,O,c),m instanceof RegExp?c+=k(m.source):m instanceof U&&(c+=k(String(m)))}});let h=[...i];return s&&h.push(ye,Ke),u||h.push(We),p&&h.push(Ge),h.forEach(A=>f=A(f,o)),new e(f,(u?"v":"u")+o)}function ze(e,t,n,r,o,i){if(e instanceof RegExp&&n!==E.DEFAULT)throw new Error("Cannot interpolate a RegExp at this position because the syntax context does not match");if(n===E.INVALID_INCOMPLETE_TOKEN||r===g.INVALID_INCOMPLETE_TOKEN)throw new Error("Interpolation preceded by invalid incomplete token");let s=e instanceof U,a;if(!(e instanceof RegExp)){e=String(e),s||(a=ie(e,n===E.CHAR_CLASS?w.CHAR_CLASS:w.DEFAULT));let u=Re(a||e,n,r);if(u)throw new Error(`Unescaped stray "${u}" in the interpolated value would have side effects outside it`)}if(n===E.ENCLOSED_TOKEN||n===E.INTERVAL_QUANTIFIER||n===E.GROUP_NAME||r===g.ENCLOSED_TOKEN||r===g.Q_TOKEN)return s?e:a;if(n===E.CHAR_CLASS){if(s){if(P(e,"^-|^&&|-$|&&$"))throw new Error("Cannot use range or set operator at boundary of interpolated pattern; move the operation into the pattern or the operator outside of it");let u=$e(ae(e));return ee(e)?`[${u}]`:z(u)}return ee(a)?`[${a}]`:a}if(e instanceof RegExp){let u=Be(e,t),l=De(u.value,i);return u.usedModifier?l:`(?:${l})`}return s?`(?:${e})`:o?`(?:${a})`:a}function Be(e,t){let n={i:null,m:null,s:null},r="\\n\\r\\u2028\\u2029",o=e.source;if(e.ignoreCase!==t.includes("i"))if(b)n.i=e.ignoreCase;else throw new Error("Pattern modifiers not supported, so the value of flag i on the interpolated RegExp must match the outer regex");if(e.dotAll!==t.includes("s")&&(b?n.s=e.dotAll:o=T(o,"\\.",e.dotAll?"[^]":`[^${r}]`,w.DEFAULT)),e.multiline!==t.includes("m")&&(b?n.m=e.multiline:(o=T(o,"\\^",e.multiline?`(?<=^|[${r}])`:"(?<![^])",w.DEFAULT),o=T(o,"\\$",e.multiline?`(?=$|[${r}])`:"(?![^])",w.DEFAULT))),b){let i=Object.keys(n),s=i.filter(u=>n[u]===!0).join(""),a=i.filter(u=>n[u]===!1).join("");if(a&&(s+=`-${a}`),s)return{value:`(?${s}:${o})`,usedModifier:!0}}return{value:o}}var S=Object.freeze({DEFAULT:"DEFAULT",CHAR_CLASS:"CHAR_CLASS"});function ce(e,t,n,r){let o=new RegExp(`${t}|(?<skip>\\\\?.)`,"gsu"),i=0,s="";for(let a of e.matchAll(o)){let{0:u,groups:{skip:l}}=a;if(!l&&(!r||r===S.DEFAULT==!i)){n instanceof Function?s+=n(a):s+=n;continue}u==="["?i++:u==="]"&&i&&i--,s+=u}return s}function Ze(e,t,n=0,r){if(!new RegExp(t,"su").test(e))return null;let o=new RegExp(`${t}|(?<skip>\\\\?.)`,"gsu");o.lastIndex=n;let i=0,s;for(;s=o.exec(e);){let{0:a,groups:{skip:u}}=s;if(!u&&(!r||r===S.DEFAULT==!i))return s;a==="["?i++:a==="]"&&i&&i--,o.lastIndex==s.index&&o.lastIndex++}return null}function D(e,t,n){return!!Ze(e,t,0,n)}function le(e,t){let n=/\\?./gsu;n.lastIndex=t;let r=e.length,o=0,i=1,s;for(;s=n.exec(e);){let[a]=s;if(a==="[")o++;else if(o)a==="]"&&o--;else if(a==="(")i++;else if(a===")"&&(i--,!i)){r=s.index;break}}return e.slice(t,r)}function Je(e,...t){let n=(e?.postprocessors||[]).concat(we),r=this instanceof Function?Z.bind(this):Z;if(Array.isArray(e?.raw))return r({flags:"",postprocessors:n})(e,...t);if((typeof e=="string"||e===void 0)&&!t.length)return r({flags:e,postprocessors:n});if({}.toString.call(e)==="[object Object]"&&!t.length)return r({...e,postprocessors:n});throw new Error(`Unexpected arguments: ${JSON.stringify([e,...t])}`)}var de=String.raw`\\g<(?<gRName>[^>&]+)&R=(?<gRDepth>\d+)>`,J=String.raw`\(\?R=(?<rDepth>\d+)\)|${de}`,he=String.raw`\(\?<(?![=!])(?<captureName>[^>]+)>`,G=new RegExp(String.raw`${he}|${J}|\\?.`,"gsu");function we(e){if(!D(e,J,S.DEFAULT))return e;if(D(e,String.raw`\\[1-9]`,S.DEFAULT))throw new Error("Invalid decimal escape in interpolated regex; cannot be used with recursion");if(D(e,String.raw`\(\?\(DEFINE\)`,S.DEFAULT))throw new Error("Definition groups cannot be used with recursion");let t=new Map,n=0,r;for(G.lastIndex=0;r=G.exec(e);){let{0:o,groups:{captureName:i,rDepth:s,gRName:a,gRDepth:u}}=r;if(o==="[")n++;else if(n)o==="]"&&n--;else if(i)t.set(i,G.lastIndex);else if(s){let l=+s;fe(l);let p=e.slice(0,r.index),c=e.slice(G.lastIndex);return pe(c),Ee(p,c,l)}else if(a){let l=+u;fe(l);let p=`Recursion via \\g<${a}&R=${u}> must be used within the referenced group`;if(!t.has(a))throw new Error(p);let c=t.get(a),f=le(e,c);if(!D(f,de,S.DEFAULT))throw new Error(p);let d=e.slice(c,r.index),h=f.slice(d.length+o.length);return pe(h),e.slice(0,c)+Ee(d,h,l)+e.slice(c+f.length)}}throw new Error("Unexpected error; recursion was not processed")}function fe(e){if(e<2||e>100)throw new Error(`Max depth must be between 2 and 100; used ${e}`)}function pe(e){if(D(e,J,S.DEFAULT))throw new Error("Recursion can only be used once per regex")}function Ee(e,t,n){let r=n-1;return`${e}${ge(`(?:${e}`,r)}(?:)${ge(`${t})`,r,"backward")}${t}`}function ge(e,t,n="forward"){let o=s=>n==="backward"?t-s+2-1:s+2,i="";for(let s=0;s<t;s++){let a=o(s);i+=ce(e,String.raw`${he}|\\k<(?<backref>[^>]+)>`,({groups:{captureName:u,backref:l}})=>{let p=`_$${a}`;return u?`(?<${u}${p}>`:`\\k<${l}${p}>`},S.DEFAULT)}return i}return _e(Xe);})(); |
{ | ||
"name": "regex-recursion", | ||
"version": "2.0.0", | ||
"version": "3.1.0", | ||
"description": "Recursive matching extension for the regex package", | ||
@@ -10,6 +10,7 @@ "author": "Steven Levithan", | ||
"scripts": { | ||
"build": "esbuild src/index.js --bundle --minify --sourcemap --outfile=dist/regex-recursion.min.js --global-name=Regex.ext", | ||
"prebuild": "rimraf --glob dist/*", | ||
"build": "esbuild src/index.js --bundle --minify --outfile=dist/regex-recursion.min.js --global-name=Regex.ext", | ||
"pretest": "npm run build", | ||
"test": "jasmine", | ||
"prepublish": "npm test" | ||
"prepare": "npm test" | ||
}, | ||
@@ -30,9 +31,10 @@ "files": [ | ||
"dependencies": { | ||
"regex": "^2.0.0", | ||
"regex-utilities": "^2.0.0" | ||
"regex": "^3.1.0", | ||
"regex-utilities": "^2.1.0" | ||
}, | ||
"devDependencies": { | ||
"esbuild": "^0.21.5", | ||
"jasmine": "^5.1.0" | ||
"esbuild": "^0.23.0", | ||
"jasmine": "^5.2.0", | ||
"rimraf": "^6.0.1" | ||
} | ||
} |
@@ -1,19 +0,38 @@ | ||
# `regex-recursion` | ||
# regex-recursion [![npm](https://img.shields.io/npm/v/regex-recursion)](https://www.npmjs.com/package/regex-recursion) | ||
This is an extension for the [`regex`](https://github.com/slevithan/regex) package that adds support for matching recursive patterns up to a specified max depth *N*, where *N* must be 2–100. | ||
This is an extension for the [`regex`](https://github.com/slevithan/regex) package that adds support for recursive matching up to a specified max depth *N*, where *N* must be between 2 and 100. Generated regexes are native `RegExp` instances, and support all JavaScript regular expression features. | ||
Recursive matching is added to a regex pattern via one of the following: | ||
Recursive matching is added to a regex via one of the following: | ||
- `(?R=N)` — Recursively match the entire pattern at this position. | ||
- `\g<name&R=N>` — Recursively match the contents of group *name* at this position. The `\g` subroutine must be called within the referenced group. | ||
- `(?R=N)` — Recursively match the entire regex at this position. | ||
- `\g<name&R=N>` — Recursively match the contents of group *name* at this position. The `\g` subroutine must be called *within* the referenced group. | ||
Recursive matching supports named captures and backreferences, and makes them independent per depth level. So e.g. `groups.name` on a `RegExp` match array is the value captured by group `name` at the top level of the recursion stack. | ||
Recursive matching supports named captures/backreferences, and makes them independent per depth level. So e.g. `groups.name` on a match object is the value captured by group `name` at the top level of the recursion stack. | ||
## Examples | ||
## Install and use | ||
Match an equal number of two different patterns: | ||
```sh | ||
npm install regex-recursion | ||
``` | ||
```js | ||
import {rregex} from 'regex-recursion'; | ||
``` | ||
In browsers: | ||
```html | ||
<script src="https://cdn.jsdelivr.net/npm/regex-recursion/dist/regex-recursion.min.js"></script> | ||
<script> | ||
const {rregex} = Regex.ext; | ||
</script> | ||
``` | ||
## Examples | ||
### Match an equal number of two different subpatterns | ||
#### Anywhere within a string | ||
```js | ||
// Matches sequences of up to 50 'a' chars followed by the same number of 'b' | ||
@@ -24,7 +43,5 @@ rregex`a(?R=50)?b`.exec('test aaaaaabbb')[0]; | ||
Match an equal number of two different patterns, as the entire string: | ||
#### As the entire string | ||
```js | ||
import {rregex} from 'regex-recursion'; | ||
const re = rregex`^ | ||
@@ -42,7 +59,5 @@ (?<balanced> | ||
Match balanced parentheses: | ||
### Match balanced parentheses | ||
```js | ||
import {rregex} from 'regex-recursion'; | ||
// Matches all balanced parentheses up to depth 50 | ||
@@ -53,24 +68,29 @@ const parens = rregex('g')`\( | ||
'test (balanced ((parens))) ) () ((a)) ((b)'.match(parens); | ||
// → ['(balanced ((parens)))', '()', '((a))', '(b)'] | ||
'test ) (balanced ((parens))) () ((a)) ( (b)'.match(parens); | ||
/* → [ | ||
'(balanced ((parens)))', | ||
'()', | ||
'((a))', | ||
'(b)' | ||
] */ | ||
``` | ||
// ---------- | ||
// Here's an alternative that matches the same strings | ||
Here's an alternative that matches the same strings, but adds a nested quantifier. It then uses an atomic group to prevent this nested quantifier from creating the potential for runaway backtracking: | ||
```js | ||
const parens = rregex('g')`\( | ||
( (?> [^\(\)]+ ) | (?R=50) )* | ||
\)`; | ||
// This matches sequences of non-parens in one step with the `+` quantifier, | ||
// and avoids backtracking into these sequences by using an atomic group | ||
// `(?>…)`. Given the nested quantifier, the atomic group is important here. | ||
// It avoids runaway backtracking when matching long strings with unbalanced | ||
// parens. Atomic groups are provided by the base `regex` package | ||
``` | ||
Match palindromes: | ||
This matches sequences of non-parens in one step with the nested `+` quantifier, and avoids backtracking into these sequences by wrapping it with an atomic group `(?>…)`. Given that what the nested quantifier `+` matches overlaps with what the outer group can match with its `*` quantifier, the atomic group is important here. It avoids runaway backtracking when matching long strings with unbalanced parens. | ||
Atomic groups are provided by the base `regex` package. | ||
### Match palindromes | ||
#### Match palindroms anywhere within a string | ||
```js | ||
import {rregex} from 'regex-recursion'; | ||
const palindromes = rregex('gi')`(?<char>\w) ((?R=15)|\w?) \k<char>`; | ||
// Palindrome max length: 31 = 2 chars (left + right) × depth 15 + 1 in center | ||
@@ -81,7 +101,7 @@ 'Racecar, ABBA, and redivided'.match(palindromes); | ||
Match palindromes as complete words: | ||
In this example, the max length of matched palindromes is 31. That's because it sets the max recursion depth to 15 with `(?R=15)`. So, depth 15 × 2 chars (left + right) for each depth level + 1 optional unbalanced char in the center = 31. The max recursion depth can increased (up to a max of 100) to match longer palindromes. | ||
#### Match palindromes as complete words | ||
```js | ||
import {rregex} from 'regex-recursion'; | ||
const palindromeWords = rregex('gi')`\b | ||
@@ -110,20 +130,1 @@ (?<palindrome> | ||
``` | ||
## Install and use | ||
```sh | ||
npm install regex-recursion | ||
``` | ||
```js | ||
import {rregex} from 'regex-recursion'; | ||
``` | ||
In browsers: | ||
```html | ||
<script src="https://cdn.jsdelivr.net/npm/regex-recursion/dist/regex-recursion.min.js"></script> | ||
<script> | ||
const {rregex} = Regex.ext; | ||
</script> | ||
``` |
@@ -23,13 +23,14 @@ import {regex} from 'regex'; | ||
const recursiveToken = String.raw`\(\?R=(?<rDepth>\d+)\)|${gRToken}`; | ||
const token = new RegExp(String.raw`\(\?<(?![=!])(?<capturingGroupName>[^>]+)>|${recursiveToken}|\\?.`, 'gsu'); | ||
const namedCapturingDelim = String.raw`\(\?<(?![=!])(?<captureName>[^>]+)>`; | ||
const token = new RegExp(String.raw`${namedCapturingDelim}|${recursiveToken}|\\?.`, 'gsu'); | ||
/** | ||
@param {string} pattern | ||
@param {string} expression | ||
@returns {string} | ||
*/ | ||
export function recursion(pattern) { | ||
if (!hasUnescaped(pattern, recursiveToken, Context.DEFAULT)) { | ||
return pattern; | ||
export function recursion(expression) { | ||
if (!hasUnescaped(expression, recursiveToken, Context.DEFAULT)) { | ||
return expression; | ||
} | ||
if (hasUnescaped(pattern, String.raw`\\[1-9]`, Context.DEFAULT)) { | ||
if (hasUnescaped(expression, String.raw`\\[1-9]`, Context.DEFAULT)) { | ||
// Could allow this with extra effort but it's probably not worth it. To trigger this, the | ||
@@ -43,2 +44,5 @@ // regex must contain both recursion and an interpolated regex with a numbered backref (since | ||
} | ||
if (hasUnescaped(expression, String.raw`\(\?\(DEFINE\)`, Context.DEFAULT)) { | ||
throw new Error(`Definition groups cannot be used with recursion`); | ||
} | ||
const groupContentsStartPos = new Map(); | ||
@@ -48,4 +52,4 @@ let numCharClassesOpen = 0; | ||
token.lastIndex = 0; | ||
while (match = token.exec(pattern)) { | ||
const {0: m, groups: {capturingGroupName, rDepth, gRName, gRDepth}} = match; | ||
while (match = token.exec(expression)) { | ||
const {0: m, groups: {captureName, rDepth, gRName, gRDepth}} = match; | ||
if (m === '[') { | ||
@@ -55,4 +59,4 @@ numCharClassesOpen++; | ||
if (capturingGroupName) { | ||
groupContentsStartPos.set(capturingGroupName, token.lastIndex); | ||
if (captureName) { | ||
groupContentsStartPos.set(captureName, token.lastIndex); | ||
// (?R=N) | ||
@@ -62,4 +66,4 @@ } else if (rDepth) { | ||
assertMaxInBounds(maxDepth); | ||
const pre = pattern.slice(0, match.index); | ||
const post = pattern.slice(token.lastIndex); | ||
const pre = expression.slice(0, match.index); | ||
const post = expression.slice(token.lastIndex); | ||
assertNoFollowingRecursion(post); | ||
@@ -77,3 +81,3 @@ return makeRecursive(pre, post, maxDepth); | ||
const startPos = groupContentsStartPos.get(gRName); | ||
const recursiveGroupContents = getGroupContents(pattern, startPos); | ||
const recursiveGroupContents = getGroupContents(expression, startPos); | ||
// Appears after/outside the referenced group | ||
@@ -83,8 +87,8 @@ if (!hasUnescaped(recursiveGroupContents, gRToken, Context.DEFAULT)) { | ||
} | ||
const pre = pattern.slice(startPos, match.index); | ||
const pre = expression.slice(startPos, match.index); | ||
const post = recursiveGroupContents.slice(pre.length + m.length); | ||
assertNoFollowingRecursion(post); | ||
return pattern.slice(0, startPos) + | ||
return expression.slice(0, startPos) + | ||
makeRecursive(pre, post, maxDepth) + | ||
pattern.slice(startPos + recursiveGroupContents.length); | ||
expression.slice(startPos + recursiveGroupContents.length); | ||
} | ||
@@ -108,5 +112,5 @@ | ||
function assertNoFollowingRecursion(remainingPattern) { | ||
if (hasUnescaped(remainingPattern, recursiveToken, Context.DEFAULT)) { | ||
throw new Error('Cannot use recursion more than once in a pattern'); | ||
function assertNoFollowingRecursion(remainingExpression) { | ||
if (hasUnescaped(remainingExpression, recursiveToken, Context.DEFAULT)) { | ||
throw new Error('Recursion can only be used once per regex'); | ||
} | ||
@@ -129,8 +133,8 @@ } | ||
/** | ||
@param {string} pattern | ||
@param {string} expression | ||
@param {number} reps | ||
@param {'forward' | 'backward'} [direction] | ||
@returns {string} | ||
*/ | ||
function repeatWithDepth(pattern, reps, direction = 'forward') { | ||
*/ | ||
function repeatWithDepth(expression, reps, direction = 'forward') { | ||
const startNum = 2; | ||
@@ -142,4 +146,4 @@ const depthNum = i => direction === 'backward' ? reps - i + startNum - 1 : i + startNum; | ||
result += replaceUnescaped( | ||
pattern, | ||
String.raw`\(\?<(?<captureName>[^>]+)>|\\k<(?<backref>[^>]+)>`, | ||
expression, | ||
String.raw`${namedCapturingDelim}|\\k<(?<backref>[^>]+)>`, | ||
({groups: {captureName, backref}}) => { | ||
@@ -146,0 +150,0 @@ const suffix = `_$${captureNum}`; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
259
126
29909
3
5
+ Addedregex@3.1.0(transitive)
- Removedregex@2.1.0(transitive)
Updatedregex@^3.1.0
Updatedregex-utilities@^2.1.0