Comparing version 4.0.0 to 4.1.0
@@ -1,2 +0,2 @@ | ||
var Regex=(()=>{var q=Object.defineProperty;var Ae=Object.getOwnPropertyDescriptor;var we=Object.getOwnPropertyNames;var Te=Object.prototype.hasOwnProperty;var Se=(e,t)=>{for(var n in t)q(e,n,{get:t[n],enumerable:!0})},Le=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of we(t))!Te.call(e,o)&&o!==n&&q(e,o,{get:()=>t[o],enumerable:!(r=Ae(t,o))||r.enumerable});return e};var Ce=e=>Le(q({},"__esModule",{value:!0}),e);var ve={};Se(ve,{pattern:()=>j,regex:()=>Ke});var g=Object.freeze({DEFAULT:"DEFAULT",CHAR_CLASS:"CHAR_CLASS"});function h(e,t,n,r){let o=new RegExp(`${t}|(?<skip>\\\\?.)`,"gsu"),i=0,s="";for(let u of e.matchAll(o)){let{0:l,groups:{skip:f}}=u;if(!f&&(!r||r===g.DEFAULT==!i)){n instanceof Function?s+=n(u):s+=n;continue}l==="["?i++:l==="]"&&i&&i--,s+=l}return s}function G(e,t,n,r){h(e,t,n,r)}function v(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:u,groups:{skip:l}}=s;if(!l&&(!r||r===g.DEFAULT==!i))return s;u==="["?i++:u==="]"&&i&&i--,o.lastIndex==s.index&&o.lastIndex++}return null}function O(e,t,n){return!!v(e,t,0,n)}function W(e,t){let n=/\\?./gsu;n.lastIndex=t;let r=e.length,o=0,i=1,s;for(;s=n.exec(e);){let[u]=s;if(u==="[")o++;else if(o)u==="]"&&o--;else if(u==="(")i++;else if(u===")"&&(i--,!i)){r=s.index;break}}return e.slice(t,r)}var _=class{#e;constructor(t){this.#e=t}toString(){return String(this.#e)}};function j(e,...t){if(Array.isArray(e?.raw))return new _(e.raw.flatMap((n,r)=>r<e.raw.length-1?[n,t[r]]:n).join(""));if(!t.length)return new _(e??"");throw new Error(`Unexpected arguments: ${JSON.stringify([e,...t])}`)}var c={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"},d={DEFAULT:"CC_DEFAULT",RANGE:"CC_RANGE",ENCLOSED_TOKEN:"CC_ENCLOSED_TOKEN",Q_TOKEN:"CC_Q_TOKEN",INVALID_INCOMPLETE_TOKEN:"CC_INVALID_INCOMPLETE_TOKEN"},K=(()=>{try{new RegExp("(?i:)")}catch{return!1}return!0})(),oe=(()=>{try{new RegExp("","v")}catch{return!1}return!0})(),R="&!#$%*+,.:;<=>?@^`~",C="$E$",H=String.raw`\(\?<(?![=!])(?<captureName>[^>]+)>`,U=String.raw`\((?!\?)(?!(?<=\(\?\()DEFINE\))|${H}`,b=String.raw`\(\?(?:[:=!>A-Za-z\-]|<[=!]|\(DEFINE\))`;function B(e,t){return t===g.CHAR_CLASS?e.replace(new RegExp(String.raw`[()\[\]{}|\\/\-${R}]`,"g"),"\\$&"):e.replace(/[()\[\]{}|\\^$*+?.]/g,"\\$&")}function Q(e){return e.replace(new RegExp(`^([${R}])(?!\\1)`),(t,n,r)=>`\\${t}${r+1===e.length?"":t}`)}function se(e){return e.replace(/^\^/,"\\^^")}function M(e,t){return h(e,String.raw`\\0(?!\d)`,"\\u{0}",t)}function ne(e,t,n){let r=0;for(let[o]of e.matchAll(new RegExp(`[${B(t+n,g.CHAR_CLASS)}]`,"g")))if(r+=o===t?1:-1,r<0)return n;return r>0?t:""}function ie(e,t,n){let r=e.replace(/\\./gsu,"");if(r.endsWith("\\"))return"\\";if(t===c.DEFAULT)return ne(r,"(",")");if(t===c.CHAR_CLASS&&!(n===d.ENCLOSED_TOKEN||n===d.Q_TOKEN))return ne(r,"[","]");if(t===c.ENCLOSED_TOKEN||t===c.INTERVAL_QUANTIFIER||n===d.ENCLOSED_TOKEN||n===d.Q_TOKEN){if(r.includes("}"))return"}"}else if(t===c.GROUP_NAME&&r.includes(">"))return">";return""}var re=new RegExp(String.raw` | ||
var Regex=(()=>{var q=Object.defineProperty;var Te=Object.getOwnPropertyDescriptor;var Se=Object.getOwnPropertyNames;var Le=Object.prototype.hasOwnProperty;var $e=(e,t)=>{for(var n in t)q(e,n,{get:t[n],enumerable:!0})},Ie=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Se(t))!Le.call(e,o)&&o!==n&&q(e,o,{get:()=>t[o],enumerable:!(r=Te(t,o))||r.enumerable});return e};var Ce=e=>Ie(q({},"__esModule",{value:!0}),e);var He={};$e(He,{pattern:()=>j,regex:()=>ye});var d=Object.freeze({DEFAULT:"DEFAULT",CHAR_CLASS:"CHAR_CLASS"});function N(e,t,n,r){let o=new RegExp(`${t}|(?<skip>\\\\?.)`,"gsu"),u=0,s="";for(let i of e.matchAll(o)){let{0:l,groups:{skip:f}}=i;if(!f&&(!r||r===d.DEFAULT==!u)){n instanceof Function?s+=n(i):s+=n;continue}l==="["?u++:l==="]"&&u&&u--,s+=l}return s}function G(e,t,n,r){N(e,t,n,r)}function V(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 u=0,s;for(;s=o.exec(e);){let{0:i,groups:{skip:l}}=s;if(!l&&(!r||r===d.DEFAULT==!u))return s;i==="["?u++:i==="]"&&u&&u--,o.lastIndex==s.index&&o.lastIndex++}return null}function _(e,t,n){return!!V(e,t,0,n)}function W(e,t){let n=/\\?./gsu;n.lastIndex=t;let r=e.length,o=0,u=1,s;for(;s=n.exec(e);){let[i]=s;if(i==="[")o++;else if(o)i==="]"&&o--;else if(i==="(")u++;else if(i===")"&&(u--,!u)){r=s.index;break}}return e.slice(t,r)}var I=class{#e;constructor(t){this.#e=t}toString(){return String(this.#e)}};function j(e,...t){if(Array.isArray(e?.raw))return new I(e.raw.flatMap((n,r)=>r<e.raw.length-1?[n,t[r]]:n).join(""));if(!t.length)return new I(e??"");throw new Error(`Unexpected arguments: ${JSON.stringify([e,...t])}`)}var c={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"},m={DEFAULT:"CC_DEFAULT",RANGE:"CC_RANGE",ENCLOSED_TOKEN:"CC_ENCLOSED_TOKEN",Q_TOKEN:"CC_Q_TOKEN",INVALID_INCOMPLETE_TOKEN:"CC_INVALID_INCOMPLETE_TOKEN"},K=(()=>{try{new RegExp("(?i:)")}catch{return!1}return!0})(),oe=(()=>{try{new RegExp("","v")}catch{return!1}return!0})(),R="&!#$%*+,.:;<=>?@^`~",$="$E$",Q=String.raw`\(\?<(?![=!])(?<captureName>[^>]+)>`,b=String.raw`\((?!\?)(?!(?<=\(\?\()DEFINE\))|${Q}`,U=String.raw`\(\?(?:[:=!>A-Za-z\-]|<[=!]|\(DEFINE\))`;function B(e,t){return t===d.CHAR_CLASS?e.replace(new RegExp(String.raw`[()\[\]{}|\\/\-${R}]`,"g"),"\\$&"):e.replace(/[()\[\]{}|\\^$*+?.]/g,"\\$&")}function H(e){return e.replace(new RegExp(`^([${R}])(?!\\1)`),(t,n,r)=>`\\${t}${r+1===e.length?"":t}`)}function se(e){return e.replace(/^\^/,"\\^^")}function M(e,t){return N(e,String.raw`\\0(?!\d)`,"\\u{0}",t)}function ne(e,t,n){let r=0;for(let[o]of e.matchAll(new RegExp(`[${B(t+n,d.CHAR_CLASS)}]`,"g")))if(r+=o===t?1:-1,r<0)return n;return r>0?t:""}function ie(e,t,n){let r=e.replace(/\\./gsu,"");if(r.endsWith("\\"))return"\\";if(t===c.DEFAULT)return ne(r,"(",")");if(t===c.CHAR_CLASS&&!(n===m.ENCLOSED_TOKEN||n===m.Q_TOKEN))return ne(r,"[","]");if(t===c.ENCLOSED_TOKEN||t===c.INTERVAL_QUANTIFIER||n===m.ENCLOSED_TOKEN||n===m.Q_TOKEN){if(r.includes("}"))return"}"}else if(t===c.GROUP_NAME&&r.includes(">"))return">";return""}var re=new RegExp(String.raw` | ||
(?<groupN>\(\?<(?![=!])|\\[gk]<) | ||
@@ -14,3 +14,3 @@ | (?<enclosedT>\\[pPu]\{) | ||
| \\?. | ||
`.replace(/\s+/g,""),"gsu");function F(e,{regexContext:t=c.DEFAULT,charClassContext:n=d.DEFAULT,charClassDepth:r=0,lastPos:o=0}={}){re.lastIndex=o;let i;for(;i=re.exec(e);){let{0:s,groups:{groupN:u,enclosedT:l,qT:f,intervalQ:p,incompleteT:a}}=i;s==="["?(r++,t=c.CHAR_CLASS,n=d.DEFAULT):s==="]"&&t===c.CHAR_CLASS?(r&&r--,r||(t=c.DEFAULT),n=d.DEFAULT):t===c.CHAR_CLASS?a?n=d.INVALID_INCOMPLETE_TOKEN:s==="-"?n=d.RANGE:l?n=d.ENCLOSED_TOKEN:f?n=d.Q_TOKEN:(s==="}"&&(n===d.ENCLOSED_TOKEN||n===d.Q_TOKEN)||n===d.INVALID_INCOMPLETE_TOKEN||n===d.RANGE)&&(n=d.DEFAULT):a?t=c.INVALID_INCOMPLETE_TOKEN:u?t=c.GROUP_NAME:l?t=c.ENCLOSED_TOKEN:p?t=c.INTERVAL_QUANTIFIER:(s===">"&&t===c.GROUP_NAME||s==="}"&&(t===c.ENCLOSED_TOKEN||t===c.INTERVAL_QUANTIFIER)||t===c.INVALID_INCOMPLETE_TOKEN)&&(t=c.DEFAULT)}return{regexContext:t,charClassContext:n,charClassDepth:r,lastPos:e.length}}function k(e){let t=0;return G(e,U,()=>t++,g.DEFAULT),t}function ue(e,t){return h(e,String.raw`\\(?<num>[1-9]\d*)`,({groups:{num:n}})=>`\\${+n+t}`,g.DEFAULT)}var _e=["Basic_Emoji","Emoji_Keycap_Sequence","RGI_Emoji_Modifier_Sequence","RGI_Emoji_Flag_Sequence","RGI_Emoji_Tag_Sequence","RGI_Emoji_ZWJ_Sequence","RGI_Emoji"].join("|"),Ie=new RegExp(String.raw` | ||
`.replace(/\s+/g,""),"gsu");function F(e,{regexContext:t=c.DEFAULT,charClassContext:n=m.DEFAULT,charClassDepth:r=0,lastPos:o=0}={}){re.lastIndex=o;let u;for(;u=re.exec(e);){let{0:s,groups:{groupN:i,enclosedT:l,qT:f,intervalQ:p,incompleteT:a}}=u;s==="["?(r++,t=c.CHAR_CLASS,n=m.DEFAULT):s==="]"&&t===c.CHAR_CLASS?(r&&r--,r||(t=c.DEFAULT),n=m.DEFAULT):t===c.CHAR_CLASS?a?n=m.INVALID_INCOMPLETE_TOKEN:s==="-"?n=m.RANGE:l?n=m.ENCLOSED_TOKEN:f?n=m.Q_TOKEN:(s==="}"&&(n===m.ENCLOSED_TOKEN||n===m.Q_TOKEN)||n===m.INVALID_INCOMPLETE_TOKEN||n===m.RANGE)&&(n=m.DEFAULT):a?t=c.INVALID_INCOMPLETE_TOKEN:i?t=c.GROUP_NAME:l?t=c.ENCLOSED_TOKEN:p?t=c.INTERVAL_QUANTIFIER:(s===">"&&t===c.GROUP_NAME||s==="}"&&(t===c.ENCLOSED_TOKEN||t===c.INTERVAL_QUANTIFIER)||t===c.INVALID_INCOMPLETE_TOKEN)&&(t=c.DEFAULT)}return{regexContext:t,charClassContext:n,charClassDepth:r,lastPos:e.length}}function k(e){let t=0;return G(e,b,()=>t++,d.DEFAULT),t}function ue(e,t){return N(e,String.raw`\\(?<num>[1-9]\d*)`,({groups:{num:n}})=>`\\${+n+t}`,d.DEFAULT)}var _e=["Basic_Emoji","Emoji_Keycap_Sequence","RGI_Emoji_Modifier_Sequence","RGI_Emoji_Flag_Sequence","RGI_Emoji_Tag_Sequence","RGI_Emoji_ZWJ_Sequence","RGI_Emoji"].join("|"),De=new RegExp(String.raw` | ||
\\(?: c[A-Za-z] | ||
@@ -27,8 +27,8 @@ | p\{(?<pStrProp>${_e})\} | ||
| . | ||
`.replace(/\s+/g,""),"gsu");function z(e){let t=!1,n;for(let{0:r,groups:o}of e.matchAll(Ie)){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 Z(e,t,n){let r={raw:[]},o=[],i;return e.raw.forEach((s,u)=>{let l=n(s,{...i,lastPos:0});if(r.raw.push(l.transformed),i=l.runningContext,u<e.raw.length-1){let f=t[u];if(f instanceof _){let p=n(f,{...i,lastPos:0});o.push(j(p.transformed)),i=p.runningContext}else o.push(f)}}),{template:r,substitutions:o}}var $e=new RegExp(String.raw` | ||
${b} | ||
`.replace(/\s+/g,""),"gsu");function z(e){let t=!1,n;for(let{0:r,groups:o}of e.matchAll(De)){if(o.pStrProp||o.qStrProp||r==="["&&t)return!0;if(["-","--","&&"].includes(r))t=!1;else if(r!=="["&&r!=="]"){if(t||n==="]")return!0;t=!0}n=r}return!1}function Z(e,t,n){let r={raw:[]},o=[],u;return e.raw.forEach((s,i)=>{let l=n(s,{...u,lastPos:0});if(r.raw.push(l.transformed),u=l.runningContext,i<e.raw.length-1){let f=t[i];if(f instanceof I){let p=n(f,{...u,lastPos:0});o.push(j(p.transformed)),u=p.runningContext}else o.push(f)}}),{template:r,substitutions:o}}var Oe=new RegExp(String.raw` | ||
${U} | ||
| \(\?< | ||
| (?<backrefNum>\\[1-9]\d*) | ||
| \\?. | ||
`.replace(/\s+/g,""),"gsu");function ae(e,t){e=String(e);let n="",r="";for(let{0:o,groups:{backrefNum:i}}of e.matchAll($e)){n+=o,t=F(n,t);let{regexContext:s}=t;if(s===c.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 le=/^\s$/,De=/^\\[\s#]$/,ce=/^[ \t]$/,Oe=/^\\[ \t]$/,Re=new RegExp(String.raw` | ||
`.replace(/\s+/g,""),"gsu");function ae(e,t){e=String(e);let n="",r="";for(let{0:o,groups:{backrefNum:u}}of e.matchAll(Oe)){n+=o,t=F(n,t);let{regexContext:s}=t;if(s===c.DEFAULT)if(o==="(")r+="(?:";else{if(u)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 le=/^\s$/,Re=/^\\[\s#]$/,ce=/^[ \t]$/,be=/^\\[ \t]$/,Ue=new RegExp(String.raw` | ||
\\(?: [gk]< | ||
@@ -42,3 +42,3 @@ | [pPu]\{ | ||
| \[\^ | ||
| ${b} | ||
| ${U} | ||
| \(\?< | ||
@@ -48,10 +48,25 @@ | (?<dp>[${R}])\k<dp> | ||
| \\?. | ||
`.replace(/\s+/g,""),"gsu");function fe(e,t){e=String(e);let n=!1,r=!1,o=!1,i="",s="",u="",l="",f=!1,p=(a,{prefix:m=!0,postfix:E=!1}={})=>(a=(f&&m?"(?:)":"")+a+(E?"(?:)":""),f=!1,a);for(let[a]of e.matchAll(Re)){if(o){a===` | ||
`&&(o=!1,f=!0);continue}if(n){if(le.test(a))continue;n=!1,f=!0}else if(r){if(ce.test(a))continue;r=!1}i+=a,t=F(i,t);let{regexContext:m,charClassContext:E}=t;if(a==="-"&&m===c.CHAR_CLASS&&l===d.RANGE)throw new Error("Invalid unescaped hyphen as the end value for a range");if(m===c.DEFAULT&&/^(?:[?*+]|\?\?)$/.test(a)||m===c.INTERVAL_QUANTIFIER&&a==="{")s+=p(a,{prefix:!1,postfix:u==="("&&a==="?"});else if(m===c.DEFAULT)le.test(a)?n=!0:a.startsWith("#")?o=!0:De.test(a)?s+=p(a[1],{prefix:!1}):s+=p(a);else if(m===c.CHAR_CLASS&&a!=="["&&a!=="[^")if(ce.test(a)&&(E===d.DEFAULT||E===d.RANGE||E===d.Q_TOKEN))r=!0;else{if(E===d.INVALID_INCOMPLETE_TOKEN)throw new Error(`Invalid incomplete token in character class: "${a}"`);Oe.test(a)&&(E===d.DEFAULT||E===d.Q_TOKEN)?s+=p(a[1],{prefix:!1}):E===d.DEFAULT?s+=p(Q(M(a))):s+=p(a)}else s+=p(a);n||r||o||(u=a,l=E)}return{transformed:s,runningContext:t}}function pe(e){let t=String.raw`\(\?:\)`;e=h(e,`(?:${t}){2,}`,"(?:)",g.DEFAULT);let n=C.replace(/\$/g,"\\$");return e=h(e,String.raw`(?:${t}(?=[)|.[$\\]|\((?!DEFINE)|$)|(?<=[()|.\]^>]|\\[bBdDfnrsStvwW]|\(\?(?:[:=!]|<[=!])|^)${t}(?![?*+{]))(?!${n})`,"",g.DEFAULT),e}var Ee=new RegExp(String.raw`(?<noncapturingStart>${b})|(?<capturingStart>\((?:\?<[^>]+>)?)|\\?.`,"gsu");function ge(e,t){if(!O(e,"\\(\\?>",g.DEFAULT))return e;let n="(?>",r=`(?:(?=(${t.useEmulationGroups?C:""}`,o=[0],i=0,s=0,u=NaN,l;do{l=!1;let f=0,p=0,a=!1,m;for(Ee.lastIndex=Number.isNaN(u)?0:u+r.length;m=Ee.exec(e);){let{0:E,index:A,groups:{capturingStart:N,noncapturingStart:S}}=m;if(E==="[")f++;else if(f)E==="]"&&f--;else if(E===n&&!a)u=A,a=!0;else if(a&&S)p++;else if(N)a?p++:(i++,o.push(i+s));else if(E===")"&&a){if(!p){s++,e=`${e.slice(0,u)}${r}${e.slice(u+n.length,A)}))<$$${s+i}>)${e.slice(A+1)}`,l=!0;break}p--}}}while(l);return e=h(e,String.raw`\\(?<backrefNum>[1-9]\d*)|<\$\$(?<wrappedBackrefNum>\d+)>`,({0:f,groups:{backrefNum:p,wrappedBackrefNum:a}})=>{if(p){let m=+p;if(m>o.length-1)throw new Error(`Backref "${f}" greater than number of captures`);return`\\${o[m]}`}return`\\${a}`},g.DEFAULT),e}function me(e,t){let n=Ne(e,{includeContents:!0}),r=be(e,n,t.useEmulationGroups);return Fe(r,n)}var Ue=String.raw`\\g<(?<subroutineName>[^>&]+)>`,y=new RegExp(String.raw` | ||
${Ue} | ||
| (?<capturingStart>${U}) | ||
`.replace(/\s+/g,""),"gsu");function fe(e,t){e=String(e);let n=!1,r=!1,o=!1,u="",s="",i="",l="",f=!1,p=(a,{prefix:g=!0,postfix:E=!1}={})=>(a=(f&&g?"(?:)":"")+a+(E?"(?:)":""),f=!1,a);for(let[a]of e.matchAll(Ue)){if(o){a===` | ||
`&&(o=!1,f=!0);continue}if(n){if(le.test(a))continue;n=!1,f=!0}else if(r){if(ce.test(a))continue;r=!1}u+=a,t=F(u,t);let{regexContext:g,charClassContext:E}=t;if(a==="-"&&g===c.CHAR_CLASS&&l===m.RANGE)throw new Error("Invalid unescaped hyphen as the end value for a range");if(g===c.DEFAULT&&/^(?:[?*+]|\?\?)$/.test(a)||g===c.INTERVAL_QUANTIFIER&&a==="{")s+=p(a,{prefix:!1,postfix:i==="("&&a==="?"});else if(g===c.DEFAULT)le.test(a)?n=!0:a.startsWith("#")?o=!0:Re.test(a)?s+=p(a[1],{prefix:!1}):s+=p(a);else if(g===c.CHAR_CLASS&&a!=="["&&a!=="[^")if(ce.test(a)&&(E===m.DEFAULT||E===m.RANGE||E===m.Q_TOKEN))r=!0;else{if(E===m.INVALID_INCOMPLETE_TOKEN)throw new Error(`Invalid incomplete token in character class: "${a}"`);be.test(a)&&(E===m.DEFAULT||E===m.Q_TOKEN)?s+=p(a[1],{prefix:!1}):E===m.DEFAULT?s+=p(H(M(a))):s+=p(a)}else s+=p(a);n||r||o||(i=a,l=E)}return{transformed:s,runningContext:t}}function pe(e){let t=String.raw`\(\?:\)`;e=N(e,`(?:${t}){2,}`,"(?:)",d.DEFAULT);let n=$.replace(/\$/g,"\\$");return e=N(e,String.raw`(?:${t}(?=[)|.[$\\]|\((?!DEFINE)|$)|(?<=[()|.\]^>]|\\[bBdDfnrsStvwW]|\(\?(?:[:=!]|<[=!])|^)${t}(?![?*+{]))(?!${n})`,"",d.DEFAULT),e}var Ee=new RegExp(String.raw`(?<noncapturingStart>${U})|(?<capturingStart>\((?:\?<[^>]+>)?)|\\?.`,"gsu");function de(e,t){if(!_(e,"\\(\\?>",d.DEFAULT))return e;let n="(?>",r=`(?:(?=(${t.useEmulationGroups?$:""}`,o=[0],u=0,s=0,i=NaN,l;do{l=!1;let f=0,p=0,a=!1,g;for(Ee.lastIndex=Number.isNaN(i)?0:i+r.length;g=Ee.exec(e);){let{0:E,index:A,groups:{capturingStart:h,noncapturingStart:S}}=g;if(E==="[")f++;else if(f)E==="]"&&f--;else if(E===n&&!a)i=A,a=!0;else if(a&&S)p++;else if(h)a?p++:(u++,o.push(u+s));else if(E===")"&&a){if(!p){s++,e=`${e.slice(0,i)}${r}${e.slice(i+n.length,A)}))<$$${s+u}>)${e.slice(A+1)}`,l=!0;break}p--}}}while(l);return e=N(e,String.raw`\\(?<backrefNum>[1-9]\d*)|<\$\$(?<wrappedBackrefNum>\d+)>`,({0:f,groups:{backrefNum:p,wrappedBackrefNum:a}})=>{if(p){let g=+p;if(g>o.length-1)throw new Error(`Backref "${f}" greater than number of captures`);return`\\${o[g]}`}return`\\${a}`},d.DEFAULT),e}var ge=String.raw`(?:[?*+]|\{\d+(?:,\d*)?\})`,Fe=new RegExp(String.raw` | ||
\\(?: \d+ | ||
| c[A-Za-z] | ||
| [gk]<[^>]+> | ||
| [pPu]\{[^\}]+\} | ||
| u[A-Fa-f\d]{4} | ||
| x[A-Fa-f\d]{2} | ||
) | ||
| \((?: \? (?: [:=!>] | ||
| <(?:[=!]|[^>]+>) | ||
| [A-Za-z\-]+: | ||
| \(DEFINE\) | ||
))? | ||
| ${ge}(?<possessive>\+?)(?<invalid>[?*+\{]?) | ||
| \\?. | ||
`.replace(/\s+/g,""),"gsu");function me(e){if(!_(e,`${ge}+`,d.DEFAULT))return e;let t=[],n=null,r=null,o="",u=0,s="";for(let{0:i,index:l,groups:{possessive:f,invalid:p}}of e.matchAll(Fe)){if(i==="[")u||(r=l),u++;else if(i==="]")u?u--:r=null;else if(f&&o&&!o.startsWith("(")){let a=i.slice(0,-1);if(p)throw new Error(`Invalid quantifier "${i}"`);if(o===")"||o==="]"){let g=o===")"?n:r;if(g===null)throw new Error(`Invalid unmatched "${o}"`);let E=e.slice(g,l);s=`${e.slice(0,g)}(?>${E}${a})`}else s=`${e.slice(0,s.length-o.length)}(?>${o}${a})`;continue}else i[0]==="("?t.push(l):i===")"&&(n=t.length?t.pop():null);o=i,s+=i}return s}function Ne(e,t){let n=Ae(e,{includeContents:!0}),r=Pe(e,n,t.useEmulationGroups);return xe(r,n)}var ke=String.raw`\\g<(?<subroutineName>[^>&]+)>`,v=new RegExp(String.raw` | ||
${ke} | ||
| (?<capturingStart>${b}) | ||
| \\(?<backrefNum>[1-9]\d*) | ||
| \\k<(?<backrefName>[^>]+)> | ||
| \\?. | ||
`.replace(/\s+/g,""),"gsu");function be(e,t,n){if(!O(e,"\\\\g<",g.DEFAULT))return e;let r=O(e,"\\\\(?:[1-9]|k<[^>]+>)",g.DEFAULT),o=r?`(${n?C:""}`:"(?:",i=new Map,s=[],u=[0],l=0,f=0,p=0,a=0,m=0,E=e,A;for(y.lastIndex=0;A=y.exec(E);){let{0:N,index:S,groups:{subroutineName:L,capturingStart:P,backrefNum:T,backrefName:V}}=A;if(N==="[")m++;else if(m)N==="]"&&m--;else if(L){if(!t.has(L))throw new Error(`Invalid named capture referenced by subroutine ${N}`);if(i.has(L))throw new Error(`Subroutine ${N} followed a recursive reference`);let w=t.get(L).contents,$=`${o}${w})`;r&&(p=0,f++),i.set(L,{unclosedGroupCount:ke($)}),s.push(L),E=Y(E,S,N,$),y.lastIndex-=N.length-o.length}else if(P)i.size?(r&&(p++,f++),N!=="("&&(E=Y(E,S,N,o),y.lastIndex-=N.length-o.length)):r&&(u.push(X(u)+1+f-a),a=f,l++);else if((T||V)&&i.size){let w=T?+T:t.get(V)?.groupNum,$=!1;for(let I of s){let D=t.get(I);if(w>=D.groupNum&&w<=D.groupNum+D.numCaptures){$=!0;break}}if($){let I=t.get(X(s)),D=l+f-p,x=`\\k<$$b${w}s${D}r${I.groupNum}c${I.numCaptures}>`;E=Y(E,S,N,x),y.lastIndex+=x.length-N.length}}else if(N===")"&&i.size){let w=i.get(X(s));w.unclosedGroupCount--,w.unclosedGroupCount||i.delete(s.pop())}}return r&&(E=h(E,String.raw`\\(?:(?<bNum>[1-9]\d*)|k<\$\$b(?<bNumSub>\d+)s(?<subNum>\d+)r(?<refNum>\d+)c(?<refCaps>\d+)>)`,({0:N,groups:{bNum:S,bNumSub:L,subNum:P,refNum:T,refCaps:V}})=>{if(S){let x=+S;if(x>u.length-1)throw new Error(`Backref "${N}" greater than number of captures`);return`\\${u[x]}`}let w=+L,$=+P,I=+T,D=+V;return w<I||w>I+D?`\\${u[w]}`:`\\${$-I+w}`},g.DEFAULT)),E}var J=new RegExp(String.raw`${H}|\(\?:\)|(?<invalid>\\?.)`,"gsu");function Fe(e,t){let n=v(e,String.raw`\(\?\(DEFINE\)`,0,g.DEFAULT);if(!n)return e;let r=de(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(J.lastIndex=0;o=J.exec(r.contents);){let{captureName:i,invalid:s}=o.groups;if(i){let u=de(r.contents,o),l;if(!t.get(i).isUnique)l=i;else{let f=Ne(u.contents);for(let p of f.keys())if(!t.get(p).isUnique){l=p;break}}if(l)throw new Error(`Duplicate group name "${l}" within DEFINE`);J.lastIndex=u.afterPos}else if(s)throw new Error("DEFINE group includes unsupported syntax at top level")}return e.slice(0,n.index)}function ke(e){let t=0;return G(e,"\\(",()=>t++,g.DEFAULT),t}function Pe(e,t){let n=0,r=0,o;for(;o=v(e,U,r,g.DEFAULT);){let{0:i,index:s,groups:{captureName:u}}=o;if(n++,u===t)break;r=s+i.length}return n}function de(e,t){let n=t.index+t[0].length,r=W(e,n),o=n+r.length+1;return{contents:r,afterPos:o}}function Ne(e,{includeContents:t}={}){let n=new Map;return G(e,H,({0:r,index:o,groups:{captureName:i}})=>{if(n.has(i))n.get(i).isUnique=!1;else{let s={isUnique:!0};if(t){let u=W(e,o+r.length);Object.assign(s,{contents:u,groupNum:Pe(e,i),numCaptures:k(u)})}n.set(i,s)}},g.DEFAULT),n}function X(e){return e[e.length-1]}function Y(e,t,n,r){return e.slice(0,t)+r+e.slice(t+n.length)}var xe="&!#%,:;<=>@`~",Ge=new RegExp(String.raw` | ||
`.replace(/\s+/g,""),"gsu");function Pe(e,t,n){if(!_(e,"\\\\g<",d.DEFAULT))return e;let r=_(e,"\\\\(?:[1-9]|k<[^>]+>)",d.DEFAULT),o=r?`(${n?$:""}`:"(?:",u=new Map,s=[],i=[0],l=0,f=0,p=0,a=0,g=0,E=e,A;for(v.lastIndex=0;A=v.exec(E);){let{0:h,index:S,groups:{subroutineName:L,capturingStart:P,backrefNum:T,backrefName:y}}=A;if(h==="[")g++;else if(g)h==="]"&&g--;else if(L){if(!t.has(L))throw new Error(`Invalid named capture referenced by subroutine ${h}`);if(u.has(L))throw new Error(`Subroutine ${h} followed a recursive reference`);let w=t.get(L).contents,D=`${o}${w})`;r&&(p=0,f++),u.set(L,{unclosedGroupCount:Ge(D)}),s.push(L),E=Y(E,S,h,D),v.lastIndex-=h.length-o.length}else if(P)u.size?(r&&(p++,f++),h!=="("&&(E=Y(E,S,h,o),v.lastIndex-=h.length-o.length)):r&&(i.push(X(i)+1+f-a),a=f,l++);else if((T||y)&&u.size){let w=T?+T:t.get(y)?.groupNum,D=!1;for(let C of s){let O=t.get(C);if(w>=O.groupNum&&w<=O.groupNum+O.numCaptures){D=!0;break}}if(D){let C=t.get(X(s)),O=l+f-p,x=`\\k<$$b${w}s${O}r${C.groupNum}c${C.numCaptures}>`;E=Y(E,S,h,x),v.lastIndex+=x.length-h.length}}else if(h===")"&&u.size){let w=u.get(X(s));w.unclosedGroupCount--,w.unclosedGroupCount||u.delete(s.pop())}}return r&&(E=N(E,String.raw`\\(?:(?<bNum>[1-9]\d*)|k<\$\$b(?<bNumSub>\d+)s(?<subNum>\d+)r(?<refNum>\d+)c(?<refCaps>\d+)>)`,({0:h,groups:{bNum:S,bNumSub:L,subNum:P,refNum:T,refCaps:y}})=>{if(S){let x=+S;if(x>i.length-1)throw new Error(`Backref "${h}" greater than number of captures`);return`\\${i[x]}`}let w=+L,D=+P,C=+T,O=+y;return w<C||w>C+O?`\\${i[w]}`:`\\${D-C+w}`},d.DEFAULT)),E}var J=new RegExp(String.raw`${Q}|\(\?:\)|(?<invalid>\\?.)`,"gsu");function xe(e,t){let n=V(e,String.raw`\(\?\(DEFINE\)`,0,d.DEFAULT);if(!n)return e;let r=he(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(J.lastIndex=0;o=J.exec(r.contents);){let{captureName:u,invalid:s}=o.groups;if(u){let i=he(r.contents,o),l;if(!t.get(u).isUnique)l=u;else{let f=Ae(i.contents);for(let p of f.keys())if(!t.get(p).isUnique){l=p;break}}if(l)throw new Error(`Duplicate group name "${l}" within DEFINE`);J.lastIndex=i.afterPos}else if(s)throw new Error("DEFINE group includes unsupported syntax at top level")}return e.slice(0,n.index)}function Ge(e){let t=0;return G(e,"\\(",()=>t++,d.DEFAULT),t}function Ke(e,t){let n=0,r=0,o;for(;o=V(e,b,r,d.DEFAULT);){let{0:u,index:s,groups:{captureName:i}}=o;if(n++,i===t)break;r=s+u.length}return n}function he(e,t){let n=t.index+t[0].length,r=W(e,n),o=n+r.length+1;return{contents:r,afterPos:o}}function Ae(e,{includeContents:t}={}){let n=new Map;return G(e,Q,({0:r,index:o,groups:{captureName:u}})=>{if(n.has(u))n.get(u).isUnique=!1;else{let s={isUnique:!0};if(t){let i=W(e,o+r.length);Object.assign(s,{contents:i,groupNum:Ke(e,u),numCaptures:k(i)})}n.set(u,s)}},d.DEFAULT),n}function X(e){return e[e.length-1]}function Y(e,t,n,r){return e.slice(0,t)+r+e.slice(t+n.length)}var Me="&!#%,:;<=>@`~",ve=new RegExp(String.raw` | ||
\[\^?-? | ||
@@ -61,5 +76,5 @@ | --?\] | ||
| -- | ||
| \\(?<vOnlyEscape>[${xe}]) | ||
| \\(?<vOnlyEscape>[${Me}]) | ||
| \\[pPu]\{[^}]+\} | ||
| \\?. | ||
`.replace(/\s+/g,""),"gsu");function he(e){let t='Invalid unescaped "-" in character class',n=!1,r="";for(let{0:o,groups:{dp:i,vOnlyEscape:s}}of e.matchAll(Ge)){if(o[0]==="["){if(n)throw new Error("Invalid nested character class when flag v not supported; possibly from interpolation");if(o.endsWith("-"))throw new Error(t);n=!0}else if(o.endsWith("]")){if(o[0]==="-")throw new Error(t);n=!1}else if(n){if(o==="&&"||o==="--")throw new Error(`Invalid set operator "${o}" when flag v not supported`);if(i)throw new Error(`Invalid double punctuator "${o}", reserved by flag v`);if("(){}/|".includes(o))throw new Error(`Invalid unescaped "${o}" in character class`);if(s){r+=s;continue}}r+=o}return r}var Ke=(e,...t)=>{if(Array.isArray(e?.raw))return ee({},e,...t);if((typeof e=="string"||e===void 0)&&!t.length)return ee.bind(null,{flags:e});if({}.toString.call(e)==="[object Object]"&&!t.length)return ee.bind(null,e);throw new Error(`Unexpected arguments: ${JSON.stringify([e,...t])}`)},ee=(e,t,...n)=>{let{flags:r="",subclass:o=!1,plugins:i=[],unicodeSetsPlugin:s=he,disable:u={},force:l={}}=e;if(/[vu]/.test(r))throw new Error("Flags v/u cannot be explicitly added");let f=l.v||(u.v?!1:oe),p=(f?"v":"u")+r;u.x||({template:t,substitutions:n}=Z(t,n,fe)),u.n||({template:t,substitutions:n}=Z(t,n,ae));let a=0,m="",E;if(t.raw.forEach((A,N)=>{let S=!!(t.raw[N]||t.raw[N+1]);a+=k(A),m+=M(A,g.CHAR_CLASS),E=F(m,E);let{regexContext:L,charClassContext:P}=E;if(N<t.raw.length-1){let T=n[N];m+=Me(T,r,L,P,S,a),T instanceof RegExp?a+=k(T.source):T instanceof _&&(a+=k(String(T)))}}),[...i,...u.atomic?[]:[ge],...u.subroutines?[]:[me],...u.x?[]:[pe],...f||!s?[]:[s]].forEach(A=>m=A(m,{flags:p,useEmulationGroups:o})),o){let A=Ve(m);return new te(A.expression,p,{captureNums:A.captureNums})}return new RegExp(m,p)},te=class e extends RegExp{#e;constructor(t,n,r){super(t,n),r?this.#e=r.captureNums:t instanceof e&&(this.#e=t.#e)}exec(t){let n=RegExp.prototype.exec.call(this,t);if(!n||!this.#e)return n;let r=[...n];n.length=1;for(let o=1;o<r.length;o++)this.#e[o]!==null&&n.push(r[o]);return n}};function Me(e,t,n,r,o,i){if(e instanceof RegExp&&n!==c.DEFAULT)throw new Error("Cannot interpolate a RegExp at this position because the syntax context does not match");if(n===c.INVALID_INCOMPLETE_TOKEN||r===d.INVALID_INCOMPLETE_TOKEN)throw new Error("Interpolation preceded by invalid incomplete token");let s=e instanceof _,u="";if(!(e instanceof RegExp)){e=String(e),s||(u=B(e,n===c.CHAR_CLASS?g.CHAR_CLASS:g.DEFAULT));let l=ie(u||e,n,r);if(l)throw new Error(`Unescaped stray "${l}" in the interpolated value would have side effects outside it`)}if(n===c.ENCLOSED_TOKEN||n===c.INTERVAL_QUANTIFIER||n===c.GROUP_NAME||r===d.ENCLOSED_TOKEN||r===d.Q_TOKEN)return s?String(e):u;if(n===c.CHAR_CLASS){if(s){if(O(String(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 l=se(Q(e));return z(e)?`[${l}]`:M(l)}return z(u)?`[${u}]`:u}if(e instanceof RegExp){let l=ye(e,t),f=ue(l.value,i);return l.usedModifier?f:`(?:${f})`}return s?`(?:${e})`:o?`(?:${u})`:u}function ye(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(K)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")&&(K?n.s=e.dotAll:o=h(o,"\\.",e.dotAll?"[^]":`[^${r}]`,g.DEFAULT)),e.multiline!==t.includes("m")&&(K?n.m=e.multiline:(o=h(o,"\\^",e.multiline?`(?<=^|[${r}])`:"(?<![^])",g.DEFAULT),o=h(o,"\\$",e.multiline?`(?=$|[${r}])`:"(?![^])",g.DEFAULT))),K){let i=Object.keys(n),s=i.filter(l=>n[l]===!0).join(""),u=i.filter(l=>n[l]===!1).join("");if(u&&(s+=`-${u}`),s)return{value:`(?${s}:${o})`,usedModifier:!0}}return{value:o}}function Ve(e){let t=C.replace(/\$/g,"\\$"),n=[0],r=0;return e=h(e,`(?:${U})${t}`,({0:o})=>(r++,o.endsWith(C)?(n.push(null),o.slice(0,-C.length)):(n.push(r),o)),g.DEFAULT),{captureNums:n,expression:e}}return Ce(ve);})(); | ||
`.replace(/\s+/g,""),"gsu");function we(e){let t='Invalid unescaped "-" in character class',n=!1,r="";for(let{0:o,groups:{dp:u,vOnlyEscape:s}}of e.matchAll(ve)){if(o[0]==="["){if(n)throw new Error("Invalid nested character class when flag v not supported; possibly from interpolation");if(o.endsWith("-"))throw new Error(t);n=!0}else if(o.endsWith("]")){if(o[0]==="-")throw new Error(t);n=!1}else if(n){if(o==="&&"||o==="--")throw new Error(`Invalid set operator "${o}" when flag v not supported`);if(u)throw new Error(`Invalid double punctuator "${o}", reserved by flag v`);if("(){}/|".includes(o))throw new Error(`Invalid unescaped "${o}" in character class`);if(s){r+=s;continue}}r+=o}return r}var ye=(e,...t)=>{if(Array.isArray(e?.raw))return ee({},e,...t);if((typeof e=="string"||e===void 0)&&!t.length)return ee.bind(null,{flags:e});if({}.toString.call(e)==="[object Object]"&&!t.length)return ee.bind(null,e);throw new Error(`Unexpected arguments: ${JSON.stringify([e,...t])}`)},ee=(e,t,...n)=>{let{flags:r="",subclass:o=!1,plugins:u=[],unicodeSetsPlugin:s=we,disable:i={},force:l={}}=e;if(/[vu]/.test(r))throw new Error("Flags v/u cannot be explicitly added");let f=l.v||(i.v?!1:oe),p=(f?"v":"u")+r;i.x||({template:t,substitutions:n}=Z(t,n,fe)),i.n||({template:t,substitutions:n}=Z(t,n,ae));let a=0,g="",E;if(t.raw.forEach((A,h)=>{let S=!!(t.raw[h]||t.raw[h+1]);a+=k(A),g+=M(A,d.CHAR_CLASS),E=F(g,E);let{regexContext:L,charClassContext:P}=E;if(h<t.raw.length-1){let T=n[h];g+=Ve(T,r,L,P,S,a),T instanceof RegExp?a+=k(T.source):T instanceof I&&(a+=k(String(T)))}}),[...u,...i.atomic?[]:[me,de],...i.subroutines?[]:[Ne],...i.x?[]:[pe],...f||!s?[]:[s]].forEach(A=>g=A(g,{flags:p,useEmulationGroups:o})),o){let A=Qe(g);return new te(A.expression,p,{emulationGroups:A.emulationGroups})}return new RegExp(g,p)},te=class e extends RegExp{#e;constructor(t,n,r){super(t,n),r?this.#e=r.emulationGroups:t instanceof e&&(this.#e=t.#e)}exec(t){let n=RegExp.prototype.exec.call(this,t);if(!n||!this.#e)return n;let r=[...n];n.length=1;for(let o=1;o<r.length;o++)this.#e[o]||n.push(r[o]);return n}};function Ve(e,t,n,r,o,u){if(e instanceof RegExp&&n!==c.DEFAULT)throw new Error("Cannot interpolate a RegExp at this position because the syntax context does not match");if(n===c.INVALID_INCOMPLETE_TOKEN||r===m.INVALID_INCOMPLETE_TOKEN)throw new Error("Interpolation preceded by invalid incomplete token");let s=e instanceof I,i="";if(!(e instanceof RegExp)){e=String(e),s||(i=B(e,n===c.CHAR_CLASS?d.CHAR_CLASS:d.DEFAULT));let l=ie(i||e,n,r);if(l)throw new Error(`Unescaped stray "${l}" in the interpolated value would have side effects outside it`)}if(n===c.ENCLOSED_TOKEN||n===c.INTERVAL_QUANTIFIER||n===c.GROUP_NAME||r===m.ENCLOSED_TOKEN||r===m.Q_TOKEN)return s?String(e):i;if(n===c.CHAR_CLASS){if(s){if(_(String(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 l=se(H(e));return z(e)?`[${l}]`:M(l)}return z(i)?`[${i}]`:i}if(e instanceof RegExp){let l=je(e,t),f=ue(l.value,u);return l.usedModifier?f:`(?:${f})`}return s?`(?:${e})`:o?`(?:${i})`:i}function je(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(K)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")&&(K?n.s=e.dotAll:o=N(o,"\\.",e.dotAll?"[^]":`[^${r}]`,d.DEFAULT)),e.multiline!==t.includes("m")&&(K?n.m=e.multiline:(o=N(o,"\\^",e.multiline?`(?<=^|[${r}])`:"(?<![^])",d.DEFAULT),o=N(o,"\\$",e.multiline?`(?=$|[${r}])`:"(?![^])",d.DEFAULT))),K){let u=Object.keys(n),s=u.filter(l=>n[l]===!0).join(""),i=u.filter(l=>n[l]===!1).join("");if(i&&(s+=`-${i}`),s)return{value:`(?${s}:${o})`,usedModifier:!0}}return{value:o}}function Qe(e){let t=$.replace(/\$/g,"\\$"),n=[!1];return e=N(e,`(?:${b})${t}`,({0:r})=>r.endsWith($)?(n.push(!0),r.slice(0,-$.length)):(n.push(!1),r),d.DEFAULT),{emulationGroups:n,expression:e}}return Ce(He);})(); |
{ | ||
"name": "regex", | ||
"version": "4.0.0", | ||
"version": "4.1.0", | ||
"description": "Regex template tag with extended syntax, context-aware interpolation, and always-on best practices", | ||
@@ -37,5 +37,2 @@ "author": "Steven Levithan", | ||
], | ||
"dependencies": { | ||
"regex-utilities": "^2.1.0" | ||
}, | ||
"devDependencies": { | ||
@@ -45,2 +42,3 @@ "esbuild": "^0.23.0", | ||
"jasmine": "^5.2.0", | ||
"regex-utilities": "^2.2.0", | ||
"rimraf": "^6.0.1", | ||
@@ -47,0 +45,0 @@ "typescript": "^5.5.4" |
165
README.md
<div align="center"> | ||
<a href="https://github.com/slevithan/regex#readme"> | ||
<picture> | ||
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/slevithan/regex/raw/main/media/regex-logo-dark.svg"> | ||
<img alt="regex logo" height="180" src="https://github.com/slevithan/regex/raw/main/media/regex-logo.svg"> | ||
</picture> | ||
</a> | ||
<br><br> | ||
<a href="https://github.com/slevithan/regex#readme"><img src="https://github.com/slevithan/regex/raw/main/regex-logo.svg" height="180" alt="regex logo"></a> | ||
[![build status](https://github.com/slevithan/regex/workflows/CI/badge.svg)](https://github.com/slevithan/regex/actions) | ||
[![npm](https://img.shields.io/npm/v/regex)](https://www.npmjs.com/package/regex) | ||
[![bundle size](https://deno.bundlejs.com/badge?q=regex&treeshake=[*])](https://bundlejs.com/?q=regex&treeshake=[*]) | ||
[![build status](https://github.com/slevithan/regex/workflows/CI/badge.svg)](https://github.com/slevithan/regex/actions) | ||
[![npm](https://img.shields.io/npm/v/regex)](https://www.npmjs.com/package/regex) | ||
[![bundle size](https://deno.bundlejs.com/badge?q=regex&treeshake=[*])](https://bundlejs.com/?q=regex&treeshake=[*]) | ||
</div> | ||
`regex` is a template tag that extends JavaScript regular expressions with features that make them more powerful and dramatically more readable. It returns native `RegExp` instances that equal or exceed native performance. It's also lightweight, supports all ES2025 regex features, and can be used as a [Babel plugin](https://github.com/slevithan/babel-plugin-transform-regex) to avoid any runtime dependencies or added runtime cost. | ||
`regex` is a template tag that extends JavaScript regular expressions with features from other leading regex libraries that make regexes more powerful and dramatically more readable. It returns native `RegExp` instances that run with native performance, and can exceed the performance of regex literals you'd write yourself. It's also lightweight, has no dependencies, supports all ES2025 regex features, has built-in TypeScript declarations, and can be used as a [Babel plugin](https://github.com/slevithan/babel-plugin-transform-regex) to avoid any runtime dependencies or user runtime cost. | ||
@@ -25,2 +30,3 @@ Highlights include support for free spacing and comments, atomic groups via `(?>…)` that can help you avoid [ReDoS](https://en.wikipedia.org/wiki/ReDoS), subroutines via `\g<name>` and subroutine definition groups via `(?(DEFINE)…)` that enable powerful subpattern composition, and context-aware interpolation of regexes, escaped strings, and partial patterns. | ||
- [Atomic groups](#atomic-groups) | ||
- [Possessive quantifiers](#possessive-quantifiers) | ||
- [Subroutines](#subroutines) | ||
@@ -55,9 +61,8 @@ - [Subroutine definition groups](#subroutine-definition-groups) | ||
- **Extended regex syntax**. | ||
- Atomic groups via `(?>…)` can dramatically improve performance and prevent ReDoS. | ||
- Subroutines via `\g<name>` enable powerful composition, improving readability and maintainability. | ||
- Subroutine definition groups via `(?(DEFINE)…)` allow groups within them to be used by reference only. | ||
- Recursive matching is enabled by an extension. | ||
- Atomic groups and possessive quantifiers can dramatically improve performance and prevent ReDoS. | ||
- Subroutines and definition groups enable powerful composition, improving readability and maintainability. | ||
- Recursive matching is enabled by a plugin. | ||
- **Context-aware and safe interpolation** of regexes, strings, and partial patterns. | ||
- Interpolated strings have their special characters escaped. | ||
- Interpolated regexes locally preserve the meaning of their own flags (or their absense), and any numbered backreferences are adjusted to work within the overall pattern. | ||
- Interpolated regexes locally preserve the meaning of their own flags (or their absense), and their numbered backreferences are adjusted to work within the overall pattern. | ||
@@ -69,3 +74,3 @@ ## 🪧 Examples | ||
// Subroutines and a subroutine definition group | ||
// Subroutines and subroutine definition group | ||
const record = regex` | ||
@@ -83,3 +88,3 @@ ^ Admitted:\ (?<admitted> \g<date>) \n | ||
// Atomic group. Avoids ReDoS from the nested, overlapping quantifier | ||
// Atomic group: Avoids ReDoS from the nested, overlapping quantifier | ||
const words = regex`^(?>\w+\s?)+$`; | ||
@@ -102,4 +107,4 @@ | ||
const double = /(.)\1/; | ||
const re2 = regex`^ (?first>.) ${double} ${double} $`; | ||
// re2 → /^(?<first>.)(.)\2(.)\3$/v | ||
regex`^ (?<first>.) ${double} ${double} $`; | ||
// → /^(?<first>.)(.)\2(.)\3$/v | ||
``` | ||
@@ -121,3 +126,3 @@ | ||
<script type="module"> | ||
import {regex, pattern} from 'https://cdn.jsdelivr.net/npm/regex@4.0.0/+esm'; | ||
import {regex, pattern} from 'https://cdn.jsdelivr.net/npm/regex@4.1.0/+esm'; | ||
// … | ||
@@ -131,6 +136,5 @@ </script> | ||
```html | ||
<script src="https://cdn.jsdelivr.net/npm/regex@4.0.0/dist/regex.min.js"></script> | ||
<script src="https://cdn.jsdelivr.net/npm/regex@4.1.0/dist/regex.min.js"></script> | ||
<script> | ||
const {regex, pattern} = Regex; | ||
// … | ||
</script> | ||
@@ -149,3 +153,3 @@ ``` | ||
2. Named capture mode changes the meaning of `\k` when a named capture appears anywhere in a regex. | ||
3. Unicode mode with flag <kbd>u</kbd> adds strict errors (for unreserved letter escapes, octal escapes, escaped literal digits, and unescaped special characters in some contexts), switches to code-point-based matching (changing the potential handling of the dot, negated sets like `\W`, character class ranges, and quantifiers), changes flag <kbd>i</kbd> to apply Unicode case-folding, and adds support for new syntax. | ||
3. Unicode mode with flag <kbd>u</kbd> adds strict errors (for unreserved letter escapes, octal escapes, escaped literal digits, quantified lookahead, and unescaped special characters in some contexts), switches to code-point-based matching (changing the potential handling of the dot, negated sets like `\W`, character class ranges, and quantifiers), changes flag <kbd>i</kbd> to apply Unicode case-folding, and adds support for new syntax. | ||
4. UnicodeSets mode with flag <kbd>v</kbd> (an upgrade to <kbd>u</kbd>) incompatibly changes escaping rules within character classes, fixes case-insensitive matching for `\p` and `\P` within negated `[^…]`, and adds support for new features/syntax. | ||
@@ -156,3 +160,3 @@ </details> | ||
`regex` adds all of these features and returns native `RegExp` instances. It always uses flag <kbd>v</kbd> (already a best practice for new regexes) so you never forget to turn it on and don't have to worry about the differences in other parsing modes (in environments without native <kbd>v</kbd>, flag <kbd>u</kbd> is automatically used instead while applying <kbd>v</kbd>'s escaping rules so your regexes are forward and backward compatible). It also supports atomic groups via `(?>…)` to help you improve the performance of your regexes and avoid catastrophic backtracking. And it gives you best-in-class, context-aware interpolation of `RegExp` instances, escaped strings, and partial patterns. | ||
`regex` adds all of these features and returns native `RegExp` instances. It always uses flag <kbd>v</kbd> (already a best practice for new regexes) so you never forget to turn it on and don't have to worry about the differences in other parsing modes (in environments without native <kbd>v</kbd>, flag <kbd>u</kbd> is automatically used instead while applying <kbd>v</kbd>'s escaping rules so your regexes are forward and backward compatible). It also supports atomic groups and possessive quantifiers to help you avoid catastrophic backtracking. And it gives you best-in-class, context-aware interpolation of `RegExp` instances, escaped strings, and partial patterns. | ||
@@ -165,3 +169,3 @@ ## 🦾 Extended regex syntax | ||
[Atomic groups](https://www.regular-expressions.info/atomic.html), written as `(?>…)`, automatically throw away all backtracking positions remembered by any tokens inside the group. They're most commonly used to improve performance, and are a much needed feature that `regex` brings to native JavaScript regular expressions. | ||
Atomic groups are noncapturing groups with special behavior, and are written as `(?>…)`. After matching the contents of an atomic group, the regex engine automatically throws away all backtracking positions remembered by any tokens within the group. Atomic groups are most commonly used to improve performance, and are a much needed feature that `regex` brings to native JavaScript regular expressions. | ||
@@ -178,5 +182,64 @@ Example: | ||
<details> | ||
<summary>👉 <b>Learn more with examples</b></summary> | ||
Consider `` regex`(?>a+)ab` `` vs `` regex`(a+)ab` ``. The former (with an atomic group) doesn't match `'aaaab'`, but the latter does. The former doesn't match because: | ||
- The regex engine starts by using the greedy `a+` within the atomic group to match all the `a`s in the target string. | ||
- Then, when it tries to match the additional `a` outside the group, it fails (the next character in the target string is a `b`), so the regex engine backtracks. | ||
- But because it can't backtrack into the atomic group to make the `+` give up its last matched `a`, there are no additional options to try and the overall match attempt fails. | ||
For a more useful example, consider how this can affect lazy (non-greedy) quantifiers. Let's say you want to match `<b>…</b>` tags that are followed by `!`. You might try this: | ||
```js | ||
const re = regex('gis')`<b>.*?</b>!`; | ||
// This is OK | ||
'<b>Hi</b>! <b>Bye</b>.'.match(re); | ||
// → ['<b>Hi</b>!'] | ||
// But not this | ||
'<b>Hi</b>. <b>Bye</b>!'.match(re); | ||
// → ['<b>Hi</b>. <b>Bye</b>!'] 👎 | ||
``` | ||
What happened with the second string was that, when an `!` wasn't found immediately following the first `</b>`, the regex engine backtracked and expanded the lazy `.*?` to match an additional character (in this case, the `<` of the `</b>` tag) and then continued onward, all the way to just before the `</b>!` at the end. | ||
You can prevent this by wrapping the lazily quantified token and its following delimiter in an atomic group, as follows: | ||
```js | ||
const re = regex('gis')`<b>(?>.*?</b>)!`; | ||
'<b>Hi</b>. <b>Bye</b>!'.match(re); | ||
// → ['<b>Bye</b>!'] 👍 | ||
``` | ||
Now, after the regex engine finds the first `</b>` and exits the atomic group, it can no longer backtrack into the group and change what the `.*?` already matched. As a result, the match attempt fails at the beginning of this example string. The regex engine then moves on and starts over at subsequent positions in the string, eventually finding `<b>Bye</b>!`. Success. | ||
</details> | ||
> [!NOTE] | ||
> Atomic groups are based on the JavaScript [proposal](https://github.com/tc39/proposal-regexp-atomic-operators) for them as well as support in many other regex flavors. | ||
> Atomic groups are supported in many other regex flavors. There's a [proposal](https://github.com/tc39/proposal-regexp-atomic-operators) to add them to JavaScript. | ||
### Possessive quantifiers | ||
Possessive quantifiers are created by adding `+` to a quantifier, and they're similar to greedy quantifiers except they don't allow backtracking. Although greedy quantifiers start out by matching as much as possible, if the remainder of the regex doesn't find a match, the regex engine will backtrack and try all permutations of how many times the quantifier should repeat. Possessive quantifiers prevent the regex engine from doing this. | ||
> Possessive quantifiers are syntactic sugar for [atomic groups](#atomic-groups) when their contents are a single repeated item. | ||
Like atomic groups, possessive quantifiers are mostly useful for performance and preventing ReDoS, but they can also be used to eliminate certain matches. For example, `` regex`a++.` `` matches one or more `a` followed by a character other than `a`. Unlike `/a+./`, it won't match a sequence of only `a` characters like `'aaa'`. The possessive `++` doesn't give back any of the `a`s it matched, so in this case there's nothing left for the `.` to match. | ||
Here's how possessive quantifier syntax compares to the greedy and lazy quantifiers that JavaScript supports natively: | ||
| | Greedy | Lazy | Possessive | | ||
| :- | :-: | :-: | :-: | | ||
| <b>Repeat</b> | As many times as possible,<br>giving back as needed | As few times as possible,<br>expanding as needed | As many times as possible,<br>without giving back | ||
| Zero or one | `?` | `??` | `?+` | | ||
| Zero or more | `*` | `*?` | `*+` | | ||
| One or more | `+` | `+?` | `++` | | ||
| *N* or more | `{2,}` | `{2,}?` | `{2,}+` | | ||
| Between *N* and *M* | `{0,5}` | `{0,5}?` | `{0,5}+` | | ||
> [!NOTE] | ||
> Possessive quantifiers are supported in many other regex flavors. There's a [proposal](https://github.com/tc39/proposal-regexp-atomic-operators) to add them to JavaScript. | ||
### Subroutines | ||
@@ -227,3 +290,3 @@ | ||
- If there are [duplicate capture names](https://github.com/tc39/proposal-duplicate-named-capturing-groups), subroutines refer to the first instance of the given group (matching the behavior of PCRE and Perl). | ||
- Although subroutines can be chained to any depth, a descriptive error is thrown if they're used recursively. Support for recursion can be added via an extension (see [*Recursion*](#recursion)). | ||
- Although subroutines can be chained to any depth, a descriptive error is thrown if they're used recursively. Support for recursion can be added via a plugin (see [*Recursion*](#recursion)). | ||
- Like backreferences, subroutines can't be used *within* character classes. | ||
@@ -318,3 +381,3 @@ - As with all extended syntax in `regex`, subroutines are applied after interpolation, giving them maximal flexibility. | ||
You can use the `regex` extension package [regex-recursion](https://github.com/slevithan/regex-recursion) to match recursive patterns via `(?R)` and `\g<name>`, up to a specified max depth. | ||
You can use the official `regex` plugin [regex-recursion](https://github.com/slevithan/regex-recursion) to match recursive patterns via `(?R)` and `\g<name>`, up to a specified max depth. | ||
@@ -407,4 +470,2 @@ ## 🚩 Flags | ||
> Aside: Flag <kbd>n</kbd>'s behavior also enables `regex` to emulate atomic groups, subroutines, and recursion. | ||
## 🧩 Interpolation | ||
@@ -426,3 +487,3 @@ | ||
> As with all interpolation in `regex`, embedded regexes are sandboxed and treated as complete units. For example, a following quantifier repeats the entire embedded regex rather than just its last token, and top-level alternation in the embedded regex will not break out to affect the meaning of the outer regex. Numbered backreferences are adjusted to work within the overall pattern. | ||
> As with all interpolation in `regex`, embedded regexes are sandboxed and treated as complete units. For example, a following quantifier repeats the entire embedded regex rather than just its last token, and top-level alternation in the embedded regex will not break out to affect the meaning of the outer regex. Numbered backreferences within embedded regexes are adjusted to work within the overall pattern. | ||
@@ -501,3 +562,3 @@ <details> | ||
```js | ||
regex`[${pattern`^`}]` | ||
regex`[${pattern`^`}a]` | ||
regex`[a${pattern`^`}]` | ||
@@ -508,3 +569,3 @@ ``` | ||
Both of these examples therefore match a literal `^`. They don't change the meaning of the surrounding character class. However, note that the `^` is not simply escaped. `` pattern`^^` `` embedded in character class context would still correctly lead to an "invalid set operation" error due to the use of a reserved double-punctuator. | ||
Both of these examples therefore match a literal `^`. The interpolated patterns don't change the meaning of the surrounding character class. However, note that the `^` is not simply escaped. `` pattern`^^` `` embedded in character class context would still correctly lead to an "invalid set operation" error due to the use of a reserved double-punctuator. | ||
@@ -576,26 +637,2 @@ > If you wanted to dynamically choose whether to negate a character class, you could put the whole character class inside the pattern. | ||
<details> | ||
<summary>👉 <b>Show an example of composing a dynamic number of strings</b></summary> | ||
```js | ||
// Instead of | ||
new RegExp(`^(?:${ | ||
arr.map(RegExp.escape).join('|') | ||
})$`) | ||
// You can say | ||
regex`^${pattern( | ||
arr.map(a => regex`${a}`.source).join('|') | ||
)}$` | ||
// And you could add your own sugar that returns a `pattern` value | ||
regex`^${anyOfEscaped(arr)}$` | ||
// You could do the same thing without `pattern` by calling `regex` as a | ||
// function instead of using it with backticks, then assembling the arguments | ||
// list dynamically and holding your nose | ||
regex({raw: ['^(', ...Array(arr.length - 1).fill('|'), ')$']}, ...arr) | ||
``` | ||
</details> | ||
> Implementation note: `pattern` returns an object with a custom `toString` that simply returns `String(value)`. | ||
@@ -611,3 +648,3 @@ | ||
> Examples where rule #3 is relevant: With following quantifiers, if they contain top-level alternation or unnamed backreferences, or if they're placed in a character class range or set operation. | ||
> Examples where rule #3 is relevant: With following quantifiers, if they contain top-level alternation or numbered backreferences, or if they're placed in a character class range or set operation. | ||
@@ -724,3 +761,3 @@ ### Interpolation contexts | ||
- **`v`** - Disables implicit [flag <kbd>v</kbd>](#flag-v) even when it's supported natively, resulting in flag <kbd>u</kbd> being added instead (in combination with the `unicodeSetsPlugin`). | ||
- **`atomic`** - Prevents transpiling [atomic groups](#atomic-groups), resulting in a syntax error if they're used. | ||
- **`atomic`** - Prevents transpiling [atomic groups](#atomic-groups) and [possessive quantifiers](#possessive-quantifiers), resulting in a syntax error if they're used. | ||
- **`subroutines`** - Prevents transpiling [subroutines](#subroutines) and [subroutine definition groups](#subroutine-definition-groups), resulting in a syntax error if they're used. | ||
@@ -735,5 +772,5 @@ | ||
`regex` transpiles its input to native `RegExp` instances. Therefore regexes created by `regex` perform equally as fast as native regular expressions. The use of `regex` can also be transpiled via a [Babel plugin](https://github.com/slevithan/babel-plugin-transform-regex), avoiding the tiny overhead of transpiling at runtime. | ||
`regex` transpiles its input to native `RegExp` instances. Therefore regexes created by `regex` perform equally as fast as native regexes. The use of `regex` can also be transpiled via a [Babel plugin](https://github.com/slevithan/babel-plugin-transform-regex), avoiding the tiny overhead of transpiling at runtime. | ||
For regexes that rely on or have the potential to trigger heavy backtracking, you can dramatically improve beyond native performance via the [atomic groups](#atomic-groups) feature built into `regex`. | ||
For regexes that rely on or have the potential to trigger heavy backtracking, you can dramatically improve beyond native performance via `regex`'s [atomic groups](#atomic-groups) and [possessive quantifiers](#possessive-quantifiers). | ||
@@ -747,3 +784,3 @@ ## 🪶 Compatibility | ||
- To ensure atomization, `regex` uses nested character classes (which require flag <kbd>v</kbd>) when interpolating more than one token at a time *inside character classes*. A descriptive error is thrown when this isn't supported, which you can avoid by not interpolating multi-token patterns or strings into character classes. | ||
- Using an interpolated `RegExp` instance with a different value for flag <kbd>i</kbd> than its outer regex relies on [regex modifiers](https://github.com/tc39/proposal-regexp-modifiers), a bleeding-edge feature available in Chrome/Edge 125 and Opera 111. A descriptive error is thrown in environments without support, which you can avoid by aligning the use of flag <kbd>i</kbd> on inner and outer regexes. Local-only application of other flags doesn't rely on this feature. | ||
- Using an interpolated `RegExp` instance with a different value for flag <kbd>i</kbd> than its outer regex relies on [pattern modifiers](https://github.com/tc39/proposal-regexp-modifiers), a bleeding-edge feature available in Chrome/Edge 125 and Opera 111. A descriptive error is thrown in environments without support, which you can avoid by aligning the use of flag <kbd>i</kbd> on inner and outer regexes. Local-only application of other flags doesn't rely on this feature. | ||
@@ -759,3 +796,3 @@ ## 🙋 FAQ | ||
2. **Support for advanced features** that enable easily creating patterns for common or important use cases: Here, JavaScript stepped up its game with ES2018 and ES2024. JavaScript is now best in class for some features like lookbehind (with it's infinite-length support) and Unicode properties (with multicharacter "properties of strings", character class subtraction and intersection, and Script_Extensions). These features are either not supported or not as robust in many other flavors. | ||
3. **Ability to write readable and maintainable patterns:** Here, native JavaScript has long been the worst of the major flavors, since it lacks the `x` (extended) flag that allows insignificant whitespace and comments. The `regex` library not only adds `x` and turns it on by default, but it additionally adds regex subroutines (matched only by PCRE and Perl, although some other flavors have inferior versions) which enable powerful subpattern composition and reuse. And it includes context-aware interpolation of `RegExp` instances, escaped strings, and partial patterns, all of which can also help with composition and readability. | ||
3. **Ability to write readable and maintainable patterns:** Here, native JavaScript has long been the worst of the major flavors, since it lacks the <kbd>x</kbd> (extended) flag that allows insignificant whitespace and comments. The `regex` library not only adds <kbd>x</kbd> (and turns it on by default), but it additionally adds regex subroutines and subroutine definition groups (matched only by PCRE and Perl, although some other flavors have inferior versions) which enable powerful subpattern composition and reuse. And it includes context-aware interpolation of `RegExp` instances, escaped strings, and partial patterns, all of which can also help with composition and readability. | ||
</details> | ||
@@ -766,3 +803,3 @@ | ||
Yes, although you might not need to. If you want to use `regex` with dynamic input, you can interpolate a `pattern` call as the full expression. For example: | ||
Yes, but you might not need to. If you want to use `regex` with dynamic input, you can interpolate a `pattern` call as the full expression. For example: | ||
@@ -772,3 +809,3 @@ ```js | ||
const str = '…'; | ||
const re = regex('gi')`${pattern(str)}`; | ||
const re = regex('g')`${pattern(str)}`; | ||
``` | ||
@@ -781,3 +818,3 @@ | ||
const str = '…'; | ||
const re = regex('gi')({raw: [str]}); | ||
const re = regex('g')({raw: [str]}); | ||
``` | ||
@@ -799,5 +836,5 @@ </details> | ||
`regex` was partly inspired by [XRegExp](https://github.com/slevithan/xregexp)'s `.tag` and [regexp-make-js](https://github.com/mikesamuel/regexp-make-js). `regex`'s only dependency is the ultra-lightweight [regex-utilities](https://github.com/slevithan/regex-utilities), which was separated so it can be reused by `regex` plugins. | ||
`regex` was partly inspired by [XRegExp](https://github.com/slevithan/xregexp)'s `.tag` and [regexp-make-js](https://github.com/mikesamuel/regexp-make-js). | ||
Crafted by Steven Levithan with ❤︎ for regular expressions and their enthusiasts.<br> | ||
Crafted by Steven Levithan with love for regular expressions and their enthusiasts.<br> | ||
MIT License. |
@@ -38,3 +38,2 @@ export type InterpolatedValue = string | RegExp | Pattern | number; | ||
}; | ||
export type EmulationGroupSlots = Array<number | null>; | ||
/** | ||
@@ -84,5 +83,2 @@ @typedef {string | RegExp | Pattern | number} InterpolatedValue | ||
import { Pattern } from './pattern.js'; | ||
/** | ||
@typedef {Array<number | null>} EmulationGroupSlots | ||
*/ | ||
declare class WrappedRegex extends RegExp { | ||
@@ -92,6 +88,6 @@ /** | ||
@param {string} [flags] | ||
@param {{captureNums: EmulationGroupSlots;}} [data] | ||
@param {{emulationGroups: Array<boolean>;}} [data] | ||
*/ | ||
constructor(expression: string | WrappedRegex, flags?: string, data?: { | ||
captureNums: EmulationGroupSlots; | ||
emulationGroups: Array<boolean>; | ||
}); | ||
@@ -98,0 +94,0 @@ #private; |
Sorry, the diff of this file is not supported yet
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
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
116604
0
1530
814
6
- Removedregex-utilities@^2.1.0
- Removedregex-utilities@2.3.0(transitive)