Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

regex

Package Overview
Dependencies
Maintainers
2
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

regex - npm Package Compare versions

Comparing version 1.1.1 to 2.0.0

src/subroutines.js

52

dist/regex.min.js

@@ -1,3 +0,3 @@

var Regex=(()=>{var R=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var J=Object.getOwnPropertyNames;var X=Object.prototype.hasOwnProperty;var Y=(e,t)=>{for(var r in t)R(e,r,{get:t[r],enumerable:!0})},ee=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of J(t))!X.call(e,o)&&o!==r&&R(e,o,{get:()=>t[o],enumerable:!(n=B(t,o))||n.enumerable});return e};var te=e=>ee(R({},"__esModule",{value:!0}),e);var le={};Y(le,{default:()=>fe,make:()=>Z,partial:()=>O,regex:()=>b});var A={DEFAULT:"DEFAULT",CHAR_CLASS:"CHAR_CLASS"};function m(e,t,r,n){let o=new RegExp(String.raw`(?<found>${t})|\\?.`,"gsu"),a=0,s="";for(let l of e.matchAll(o)){let{0:u,groups:{found:E}}=l;if(E&&(!n||n===A.DEFAULT==!a)){r instanceof Function?s+=r(l):s+=r;continue}u==="["?a++:u==="]"&&a&&a--,s+=u}return s}function re(e,t,r,n){if(!new RegExp(t,"su").test(e))return!1;let o=new RegExp(String.raw`(?<found>${t})|\\?.`,"gsu"),a=0;for(let s of e.matchAll(o)){let{0:l,groups:{found:u}}=s;if(u&&(!n||n===A.DEFAULT==!a))return r&&r(s),!0;l==="["?a++:l==="]"&&a&&a--}return!1}function K(e,t,r){return re(e,t,null,r)}function k(e){if(!K(e,String.raw`\(\?>`,A.DEFAULT))return e;let t=new RegExp(String.raw`(?<noncapturingStart>\(\?(?:[:=!>A-Za-z\-]|<[=!]))|(?<capturingStart>\((?:\?<[^>]+>)?)|(?<backrefNum>\\[1-9]\d*)|\\?.`,"gsu"),r=3,n,o=0,a=0,s=NaN;do{n=!1;let l=0,u=0,E=!1,p;for(t.lastIndex=Number.isNaN(s)?0:s+r;p=t.exec(e);){let{0:i,index:N,groups:{backrefNum:d,capturingStart:_,noncapturingStart:h}}=p;if(i==="[")l++;else if(l)i==="]"&&l--;else if(i==="(?>"&&!E)s=N,E=!0;else if(E&&h)u++;else if(_)E&&u++,o++;else if(i===")"&&E){if(!u){a++,e=`${e.slice(0,s)}(?:(?=(${e.slice(s+r,N)}))\\k<${a+o}>)${e.slice(N+1)}`,n=!0,o--;break}u--}else if(d)throw new Error(`Invalid decimal escape "${i}" in interpolated regex; cannot be used with atomic group`)}}while(n);return e=m(e,String.raw`\\k<(?<backrefNum>\d+)>`,({groups:{backrefNum:l}})=>`\\${l}`,A.DEFAULT),e}var T=class{#e;constructor(t){this.#e=t}toString(){return String(this.#e)}};function O(e,...t){if(Array.isArray(e?.raw))return new T(e.raw.flatMap((r,n)=>n<e.raw.length-1?[r,t[n]]:r).join(""));if(!t.length)return new T(e??"");throw new Error(`Unexpected arguments: ${JSON.stringify([e,...t])}`)}var f={...A,GROUP_NAME:"GROUP_NAME",ENCLOSED_TOKEN:"ENCLOSED_TOKEN",INTERVAL_QUANTIFIER:"INTERVAL_QUANTIFIER",INVALID_INCOMPLETE_TOKEN:"INVALID_INCOMPLETE_TOKEN"},c={DEFAULT:"CC_DEFAULT",RANGE:"CC_RANGE",ENCLOSED_TOKEN:"CC_ENCLOSED_TOKEN",Q_TOKEN:"CC_Q_TOKEN",INVALID_INCOMPLETE_TOKEN:"CC_INVALID_INCOMPLETE_TOKEN"},S=(()=>{let e=!0;try{new RegExp("(?i-ms:)")}catch{e=!1}return e})(),U="&!#$%*+,.:;<=>?@^`~";function C(e,t){return t===f.CHAR_CLASS?e.replace(new RegExp(String.raw`[()\[\]{}|\\/\-${U}]`,"g"),"\\$&"):e.replace(/[()\[\]{}|\\^$*+?.]/g,"\\$&")}function I(e){return e.replace(new RegExp(String.raw`^([${U}])(?!\1)`),(t,r,n)=>`\\${t}${n+1===e.length?"":t}`)}function V(e){return e.replace(/^\^/,"\\^^")}function w(e,t){return m(e,String.raw`\\0(?!\d)`,"\\u{0}",t)}function G(e,t,r){let n=0;for(let[o]of e.matchAll(new RegExp(`[${C(t+r)}]`,"g")))if(n+=o===t?1:-1,n<0)return r;return n>0?t:""}function M(e,t,r){let n=e.replace(/\\./gsu,"");if(n.at(-1)==="\\")return"\\";if(t===f.DEFAULT)return G(n,"(",")");if(t===f.CHAR_CLASS&&!(r===c.ENCLOSED_TOKEN||r===c.Q_TOKEN))return G(n,"[","]");if(t===f.ENCLOSED_TOKEN||t===f.INTERVAL_QUANTIFIER||r===c.ENCLOSED_TOKEN||r===c.Q_TOKEN){if(n.includes("}"))return"}"}else if(t===f.GROUP_NAME&&n.includes(">"))return">";return""}var g=new RegExp(String.raw`
(?<groupN> \(\?< (?! [=!] ) | \\k< )
var Regex=(()=>{var M=Object.defineProperty;var se=Object.getOwnPropertyDescriptor;var ie=Object.getOwnPropertyNames;var ae=Object.prototype.hasOwnProperty;var ue=(e,t)=>{for(var n in t)M(e,n,{get:t[n],enumerable:!0})},ce=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of ie(t))!ae.call(e,o)&&o!==n&&M(e,o,{get:()=>t[o],enumerable:!(r=se(t,o))||r.enumerable});return e};var le=e=>ce(M({},"__esModule",{value:!0}),e);var we={};ue(we,{partial:()=>P,regex:()=>he});var d={DEFAULT:"DEFAULT",CHAR_CLASS:"CHAR_CLASS"};function A(e,t,n,r){let o=new RegExp(String.raw`${t}|(?<skip>\\?.)`,"gsu"),a=0,s="";for(let u of e.matchAll(o)){let{0:c,groups:{skip:l}}=u;if(!l&&(!r||r===d.DEFAULT==!a)){n instanceof Function?s+=n(u):s+=n;continue}c==="["?a++:c==="]"&&a&&a--,s+=c}return s}function I(e,t,n,r){A(e,t,n,r)}function x(e,t,n=0,r){if(!new RegExp(t,"su").test(e))return null;let o=new RegExp(String.raw`${t}|(?<skip>\\?.)`,"gsu");o.lastIndex=n;let a=0,s;for(;s=o.exec(e);){let{0:u,groups:{skip:c}}=s;if(!c&&(!r||r===d.DEFAULT==!a))return s;u==="["?a++:u==="]"&&a&&a--,o.lastIndex==s.index&&o.lastIndex++}return null}function w(e,t,n){return!!x(e,t,0,n)}function q(e,t){let n=/\\?./gsu;n.lastIndex=t;let r=e.length,o=0,a=1,s;for(;s=n.exec(e);){let[u]=s;if(u==="[")o++;else if(o)u==="]"&&o--;else if(u==="(")a++;else if(u===")"&&(a--,!a)){r=s.index;break}}return e.slice(t,r)}var _=class{#e;constructor(t){this.#e=t}toString(){return String(this.#e)}};function P(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 f={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"},p={DEFAULT:"CC_DEFAULT",RANGE:"CC_RANGE",ENCLOSED_TOKEN:"CC_ENCLOSED_TOKEN",Q_TOKEN:"CC_Q_TOKEN",INVALID_INCOMPLETE_TOKEN:"CC_INVALID_INCOMPLETE_TOKEN"},F=(()=>{let e=!0;try{new RegExp("(?i-ms:)")}catch{e=!1}return e})(),k="&!#$%*+,.:;<=>?@^`~",R=String.raw`\(\?(?:[:=!>A-Za-z\-]|<[=!])`;function V(e,t){return t===d.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 W(e){return e.replace(/^\^/,"\\^^")}function b(e,t){return A(e,String.raw`\\0(?!\d)`,"\\u{0}",t)}function B(e,t,n){let r=0;for(let[o]of e.matchAll(new RegExp(`[${V(t+n,d.CHAR_CLASS)}]`,"g")))if(r+=o===t?1:-1,r<0)return n;return r>0?t:""}function Z(e,t,n){let r=e.replace(/\\./gsu,"");if(r.at(-1)==="\\")return"\\";if(t===f.DEFAULT)return B(r,"(",")");if(t===f.CHAR_CLASS&&!(n===p.ENCLOSED_TOKEN||n===p.Q_TOKEN))return B(r,"[","]");if(t===f.ENCLOSED_TOKEN||t===f.INTERVAL_QUANTIFIER||n===p.ENCLOSED_TOKEN||n===p.Q_TOKEN){if(r.includes("}"))return"}"}else if(t===f.GROUP_NAME&&r.includes(">"))return">";return""}var z=new RegExp(String.raw`
(?<groupN> \(\?< (?! [=!] ) | \\[gk]< )
| (?<enclosedT> \\[pPu]\{ )

@@ -13,20 +13,10 @@ | (?<qT> \\q\{ )

)
| \\ (?:
c [A-Za-z]
| u [A-Fa-f\d]{4}
| x [A-Fa-f\d]{2}
| 0 \d+
)
| \[\^
| \(\? [:=!<>A-Za-z\-]
| (?<dp> [${U}] ) \k<dp>
| \\[1-9]\d*
| --
| \\? .
`.replace(/\s+/g,""),"gsu");function L(e,{regexContext:t=f.DEFAULT,charClassContext:r=c.DEFAULT,charClassDepth:n=0,lastPos:o=0}){g.lastIndex=o;let a;for(;a=g.exec(e);){let{0:s,groups:{groupN:l,enclosedT:u,qT:E,intervalQ:p,incompleteT:i}}=a;s==="["||s==="[^"?(n++,t=f.CHAR_CLASS,r=c.DEFAULT):s==="]"&&t===f.CHAR_CLASS?(n&&n--,n||(t=f.DEFAULT),r=c.DEFAULT):t===f.CHAR_CLASS?i?r=c.INVALID_INCOMPLETE_TOKEN:s==="-"?r=c.RANGE:u?r=c.ENCLOSED_TOKEN:E?r=c.Q_TOKEN:(s==="}"&&(r===c.ENCLOSED_TOKEN||r===c.Q_TOKEN)||r===c.INVALID_INCOMPLETE_TOKEN||r===c.RANGE)&&(r=c.DEFAULT):i?t=f.INVALID_INCOMPLETE_TOKEN:l?t=f.GROUP_NAME:u?t=f.ENCLOSED_TOKEN:p?t=f.INTERVAL_QUANTIFIER:(s===">"&&t===f.GROUP_NAME||s==="}"&&(t===f.ENCLOSED_TOKEN||t===f.INTERVAL_QUANTIFIER)||t===f.INVALID_INCOMPLETE_TOKEN)&&(t=f.DEFAULT)}return{regexContext:t,charClassContext:r,charClassDepth:n,lastPos:e.length}}function F(e){let t=/(?<capture>\((?:(?!\?)|\?<[^>]+>))|\\?./gsu;return Array.from(e.matchAll(t)).filter(r=>r.groups.capture).length}function y(e,t){return e.replace(/\\([1-9]\d*)|\\?./gsu,(r,n)=>n?"\\"+(Number(n)+t):r)}var ne=["Basic_Emoji","Emoji_Keycap_Sequence","RGI_Emoji_Modifier_Sequence","RGI_Emoji_Flag_Sequence","RGI_Emoji_Tag_Sequence","RGI_Emoji_ZWJ_Sequence","RGI_Emoji"].join("|");function $(e){let t=new RegExp(String.raw`
`.replace(/\s+/g,""),"gsu");function O(e,{regexContext:t=f.DEFAULT,charClassContext:n=p.DEFAULT,charClassDepth:r=0,lastPos:o=0}){z.lastIndex=o;let a;for(;a=z.exec(e);){let{0:s,groups:{groupN:u,enclosedT:c,qT:l,intervalQ:E,incompleteT:i}}=a;s==="["?(r++,t=f.CHAR_CLASS,n=p.DEFAULT):s==="]"&&t===f.CHAR_CLASS?(r&&r--,r||(t=f.DEFAULT),n=p.DEFAULT):t===f.CHAR_CLASS?i?n=p.INVALID_INCOMPLETE_TOKEN:s==="-"?n=p.RANGE:c?n=p.ENCLOSED_TOKEN:l?n=p.Q_TOKEN:(s==="}"&&(n===p.ENCLOSED_TOKEN||n===p.Q_TOKEN)||n===p.INVALID_INCOMPLETE_TOKEN||n===p.RANGE)&&(n=p.DEFAULT):i?t=f.INVALID_INCOMPLETE_TOKEN:u?t=f.GROUP_NAME:c?t=f.ENCLOSED_TOKEN:E?t=f.INTERVAL_QUANTIFIER:(s===">"&&t===f.GROUP_NAME||s==="}"&&(t===f.ENCLOSED_TOKEN||t===f.INTERVAL_QUANTIFIER)||t===f.INVALID_INCOMPLETE_TOKEN)&&(t=f.DEFAULT)}return{regexContext:t,charClassContext:n,charClassDepth:r,lastPos:e.length}}function D(e){let t=0;return I(e,String.raw`\((?:(?!\?)|\?<[^>]+>)`,()=>t++,d.DEFAULT),t}function J(e,t){return A(e,String.raw`\\(?<num>[1-9]\d*)`,({groups:{num:n}})=>`\\${+n+t}`,d.DEFAULT)}var fe=["Basic_Emoji","Emoji_Keycap_Sequence","RGI_Emoji_Modifier_Sequence","RGI_Emoji_Flag_Sequence","RGI_Emoji_Tag_Sequence","RGI_Emoji_ZWJ_Sequence","RGI_Emoji"].join("|"),pe=new RegExp(String.raw`
\\ (?:
c [A-Za-z]
| p \{ (?<pPropOfStr> ${ne} ) \}
| p \{ (?<pStrProp> ${fe} ) \}
| [pP] \{ [^\}]+ \}
| (?<qPropOfStr> q )
| (?<qStrProp> q )
| u (?: [A-Fa-f\d]{4} | \{ [A-Fa-f\d]+ \} )

@@ -39,5 +29,31 @@ | x [A-Fa-f\d]{2}

| .
`.replace(/\s+/g,""),"gsu"),r=!1,n;for(let{0:o,groups:a}of e.matchAll(t)){if(a.pPropOfStr||a.qPropOfStr||o==="["&&r)return!0;if(["-","--","&&"].includes(o))r=!1;else if(!["[","]"].includes(o)){if(r||n==="]")return!0;r=!0}n=o}return!1}function D(e,t,r){let n={raw:[]},o=[],a={};return e.raw.forEach((s,l)=>{let u=r(s,{...a,lastPos:0});if(n.raw.push(u.transformed),a=u.runningContext,l<e.raw.length-1){let E=t[l];if(E instanceof T){let p=r(E,{...a,lastPos:0});o.push(O(p.transformed)),a=p.runningContext}else o.push(E)}}),{template:n,values:o}}function j(e,t){e=String(e);let r="",n="";for(let[o]of e.matchAll(g)){r+=o,t=L(r,t);let{regexContext:a}=t;if(a===f.DEFAULT)if(o==="(")n+="(?:";else{if(/^\\[1-9]/.test(o))throw new Error(`Invalid decimal escape "${o}" with implicit flag n; replace with named backreference`);n+=o}else n+=o}return{transformed:n,runningContext:t}}var Q=/^\s$/,oe=/^\\[\s#]$/,H=/^[ \t]$/,se=/^\\[ \t]$/;function q(e,t){e=String(e);let r=!1,n=!1,o=!1,a="",s="",l="",u="",E=!1,p=(i,{prefix:N=!0,postfix:d=!1}={})=>(i=(E&&N?"(?:)":"")+i+(d?"(?:)":""),E=!1,i);for(let[i]of e.matchAll(g)){if(o){i===`
`&&(o=!1,E=!0);continue}if(r){if(Q.test(i))continue;r=!1,E=!0}else if(n){if(H.test(i))continue;n=!1}a+=i,t=L(a,t);let{regexContext:N,charClassContext:d}=t;if(i==="-"&&N===f.CHAR_CLASS&&u===c.RANGE)throw new Error("Invalid unescaped hyphen as the end value for a range");if(N===f.DEFAULT&&/^[?*+]\??$/.test(i)||N===f.INTERVAL_QUANTIFIER&&i==="{")s+=p(i,{prefix:!1,postfix:l==="("});else if(N===f.DEFAULT)Q.test(i)?r=!0:i.startsWith("#")?o=!0:oe.test(i)?s+=p(i[1],{prefix:!1}):s+=p(i);else if(N===f.CHAR_CLASS&&i!=="["&&i!=="[^")if(H.test(i)&&(d===c.DEFAULT||d===c.RANGE||d===c.Q_TOKEN))n=!0;else{if(d===c.INVALID_INCOMPLETE_TOKEN)throw new Error(`Invalid incomplete token in character class: "${i}"`);se.test(i)&&(d===c.DEFAULT||d===c.Q_TOKEN)?s+=p(i[1],{prefix:!1}):d===c.DEFAULT?s+=p(I(w(i))):s+=p(i)}else s+=p(i);r||n||o||(l=i,u=d)}return{transformed:s,runningContext:t}}function W(e){let t=String.raw`\(\?:\)`;return e=m(e,`${t}(?:${t})+`,"(?:)",A.DEFAULT),e=m(e,String.raw`^${t}(?![?*+{])|${t}$|${t}(?=[()|$\\])|(?<=[()|>^]|\(\?(?:[:=!]|<[=!]))${t}`,"",A.DEFAULT),e}var b=function(e,...t){let r=this instanceof Function?this:RegExp;if(Array.isArray(e?.raw))return P(r,{flags:""},e,...t);if((typeof e=="string"||e===void 0)&&!t.length)return P.bind(null,r,{flags:e});if({}.toString.call(e)==="[object Object]"&&!t.length)return P.bind(null,r,e);throw new Error(`Unexpected arguments: ${JSON.stringify([e,...t])}`)};function P(e,t,r,...n){let{flags:o="",postprocessors:a=[],__flagN:s=!0,__flagX:l=!0,__rake:u=!0}=t;if(/[vu]/.test(o))throw new Error("Flags v/u cannot be explicitly added since v is always enabled");l&&({template:r,values:n}=D(r,n,q)),s&&({template:r,values:n}=D(r,n,j));let E=0,p="",i={};r.raw.forEach((d,_)=>{let h=r.raw[_]||r.raw[_+1];E+=F(d),p+=w(d,A.CHAR_CLASS),i=L(p,i);let{regexContext:v,charClassContext:z}=i;if(_<r.raw.length-1){let x=ie(n[_],o,v,z,h,E);E+=x.capturesAdded||0,p+=x.value}});let N=[k,...a];u&&N.push(W);for(let d of N)p=d(p);return new e(p,`v${o}`)}function ie(e,t,r,n,o,a){if(e instanceof RegExp&&r!==f.DEFAULT)throw new Error("Cannot interpolate a RegExp at this position because the syntax context does not match");if(r===f.INVALID_INCOMPLETE_TOKEN||n===c.INVALID_INCOMPLETE_TOKEN)throw new Error("Interpolation preceded by invalid incomplete token");let s=e instanceof T,l;if(!(e instanceof RegExp)){e=String(e),s||(l=C(e,r));let u=M(l||e,r,n);if(u)throw new Error(`Unescaped stray "${u}" in the interpolated value would have side effects outside it`)}if(r===f.ENCLOSED_TOKEN||r===f.INTERVAL_QUANTIFIER||r===f.GROUP_NAME||n===c.ENCLOSED_TOKEN||n===c.Q_TOKEN)return{value:s?e:l};if(r===f.CHAR_CLASS){if(s){if(m(e,"^-|^&&|-$|&&$","")!==e)throw new Error("In character classes, a partial cannot use a range/set operator at its boundary; move the operation into the partial or the operator outside of it");let E=V(I(e));return{value:$(e)?`[${E}]`:w(E)}}return{value:$(l)?`[${l}]`:l}}if(e instanceof RegExp){let u=ae(e,t),E=y(u.value,a);return{value:u.usedModifier?E:`(?:${E})`,capturesAdded:F(e.source)}}return s?{value:`(?:${e})`}:{value:o?`(?:${l})`:l}}function ae(e,t){let r={i:null,m:null,s:null},n="\\n\\r\\u2028\\u2029",o=e.source;if(e.ignoreCase!==t.includes("i"))if(S)r.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")&&(S?r.s=e.dotAll:o=m(o,"\\.",e.dotAll?"[^]":`[^${n}]`,A.DEFAULT)),e.multiline!==t.includes("m")&&(S?r.m=e.multiline:(o=m(o,"\\^",e.multiline?`(?<=^|[${n}])`:"(?<![^])",A.DEFAULT),o=m(o,"\\$",e.multiline?`(?=$|[${n}])`:"(?![^])",A.DEFAULT))),S){let a=Object.keys(r),s=a.filter(u=>r[u]===!0).join(""),l=a.filter(u=>r[u]===!1).join("");if(l&&(s+=`-${l}`),s)return{value:`(?${s}:${o})`,usedModifier:!0}}return{value:o}}var Z=b;var fe={make:Z,partial:O,regex:b};return te(le);})();
//! regex 1.1.1; Steven Levithan; MIT License
`.replace(/\s+/g,""),"gsu");function y(e){let t=!1,n;for(let{0:r,groups:o}of e.matchAll(pe)){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 j(e,t,n){let r={raw:[]},o=[],a={};return e.raw.forEach((s,u)=>{let c=n(s,{...a,lastPos:0});if(r.raw.push(c.transformed),a=c.runningContext,u<e.raw.length-1){let l=t[u];if(l instanceof _){let E=n(l,{...a,lastPos:0});o.push(P(E.transformed)),a=E.runningContext}else o.push(l)}}),{template:r,values:o}}function X(e){if(!w(e,String.raw`\(\?>`,d.DEFAULT))return e;let t=new RegExp(String.raw`(?<noncapturingStart>${R})|(?<capturingStart>\((?:\?<[^>]+>)?)|(?<backrefNum>\\[1-9]\d*)|\\?.`,"gsu"),n="(?>",r="(?:(?=(",o=0,a=0,s=NaN,u;do{u=!1;let c=0,l=0,E=!1,i;for(t.lastIndex=Number.isNaN(s)?0:s+r.length;i=t.exec(e);){let{0:m,index:g,groups:{backrefNum:$,capturingStart:C,noncapturingStart:L}}=i;if(m==="[")c++;else if(c)m==="]"&&c--;else if(m===n&&!E)s=g,E=!0;else if(E&&L)l++;else if(C)E&&l++,o++;else if(m===")"&&E){if(!l){a++,e=`${e.slice(0,s)}${r}${e.slice(s+n.length,g)}))\\k<$$${a+o}>)${e.slice(g+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}`,d.DEFAULT),e}var Ee=new RegExp(String.raw`
${R}
| \(\?<
| (?<backrefNum> \\[1-9]\d* )
| \\? .
`.replace(/\s+/g,""),"gsu");function v(e,t){e=String(e);let n="",r="";for(let{0:o,groups:{backrefNum:a}}of e.matchAll(Ee)){n+=o,t=O(n,t);let{regexContext:s}=t;if(s===f.DEFAULT)if(o==="(")r+="(?:";else{if(a)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 Y=/^\s$/,de=/^\\[\s#]$/,ee=/^[ \t]$/,ge=/^\\[ \t]$/,me=new RegExp(String.raw`
\\ (?:
[gk] <
| [pPu] \{
| c [A-Za-z]
| u [A-Fa-f\d]{4}
| x [A-Fa-f\d]{2}
| 0 \d+
)
| \[\^
| ${R}
| \(\?<
| (?<dp> [${k}] ) \k<dp>
| --
| \\? .
`.replace(/\s+/g,""),"gsu");function te(e,t){e=String(e);let n=!1,r=!1,o=!1,a="",s="",u="",c="",l=!1,E=(i,{prefix:m=!0,postfix:g=!1}={})=>(i=(l&&m?"(?:)":"")+i+(g?"(?:)":""),l=!1,i);for(let[i]of e.matchAll(me)){if(o){i===`
`&&(o=!1,l=!0);continue}if(n){if(Y.test(i))continue;n=!1,l=!0}else if(r){if(ee.test(i))continue;r=!1}a+=i,t=O(a,t);let{regexContext:m,charClassContext:g}=t;if(i==="-"&&m===f.CHAR_CLASS&&c===p.RANGE)throw new Error("Invalid unescaped hyphen as the end value for a range");if(m===f.DEFAULT&&/^(?:[?*+]|\?\?)$/.test(i)||m===f.INTERVAL_QUANTIFIER&&i==="{")s+=E(i,{prefix:!1,postfix:u==="("&&i==="?"});else if(m===f.DEFAULT)Y.test(i)?n=!0:i.startsWith("#")?o=!0:de.test(i)?s+=E(i[1],{prefix:!1}):s+=E(i);else if(m===f.CHAR_CLASS&&i!=="["&&i!=="[^")if(ee.test(i)&&(g===p.DEFAULT||g===p.RANGE||g===p.Q_TOKEN))r=!0;else{if(g===p.INVALID_INCOMPLETE_TOKEN)throw new Error(`Invalid incomplete token in character class: "${i}"`);ge.test(i)&&(g===p.DEFAULT||g===p.Q_TOKEN)?s+=E(i[1],{prefix:!1}):g===p.DEFAULT?s+=E(G(b(i))):s+=E(i)}else s+=E(i);n||r||o||(u=i,c=g)}return{transformed:s,runningContext:t}}function ne(e){let t=String.raw`\(\?:\)`;return e=A(e,`(?:${t}){2,}`,"(?:)",d.DEFAULT),e=A(e,String.raw`^${t}(?![?*+{])|${t}$|${t}(?=[()|$\\])|(?<=[()|>^]|\(\?(?:[:=!]|<[=!]))${t}`,"",d.DEFAULT),e}var re=String.raw`\\g<(?<subroutineName>[^>&]+)>`,Q=String.raw`\((?:(?!\?)|\?<(?![=!])(?<captureName>[^>]+)>)`,U=new RegExp(String.raw`
${re}
| (?<capturingStart> ${Q} )
| \\ (?<backrefNum> [1-9]\d* )
| \\k< (?<backrefName> [^>]+ ) >
| \\? .
`.replace(/\s+/g,""),"gsu");function oe(e){if(!w(e,"\\\\g<",d.DEFAULT))return e;let t=Se(e),n=[0],r=Ae(e),o=0,a=0,s=new Map,u=[],c=0,l=e,E;for(U.lastIndex=0;E=U.exec(l);){let{0:i,index:m,groups:{subroutineName:g,capturingStart:$,backrefNum:C,backrefName:L}}=E;if(i==="[")c++;else if(c)i==="]"&&c--;else{let N=s.size?s.get(u.at(-1)):null;if(g){if(!t.has(g))throw new Error(`Invalid named capture referenced by subroutine ${i}`);if(s.has(g))throw new Error(`Subroutine ${i} followed a recursive reference`);let S=t.get(g)[0].contents,T=D(S)+1;a+=T;let h=`(${S})`;s.set(g,{contents:S,unclosedGroupCount:Te(h),numCaptures:T}),u.push(g),l=K(l,m,i,h),U.lastIndex-=i.length}else if($)s.size?(i!=="("&&(l=K(l,m,i,"("),U.lastIndex-=i.length),n.push(n.at(-1)+N.numCaptures)):(o++,n.length===o&&n.push(n.at(-1)));else if(C){let S=+C,T;if(s.size?S>r&&(T=o+a-r-N.numCaptures):T=n[S],T){let h=`\\${S+T}`;l=K(l,m,i,h),U.lastIndex+=h.length-i.length}}else if(L){if(s.size){let S=!1;for(let T of u){let h=s.get(T).contents;if(w(h,String.raw`\(\?<${L}>`,d.DEFAULT)){S=!0;break}}if(S){let h=`\\${Ne(e,L)+1}`;l=K(l,m,i,h),U.lastIndex-=i.length}}}else i===")"&&s.size&&(N.unclosedGroupCount--,N.unclosedGroupCount||s.delete(u.pop()))}}return l}function Ae(e){let t=new Set;I(e,re,({groups:{subroutineName:a}})=>{t.add(a)},d.DEFAULT);let n=0,r=0,o;for(;o=x(e,Q,r,d.DEFAULT);){let{0:a,index:s,groups:{captureName:u}}=o;if(t.has(u))break;n++,r=s+a.length}return n}function Ne(e,t){let n=0,r=0,o;for(;o=x(e,Q,r,d.DEFAULT);){let{0:a,index:s,groups:{captureName:u}}=o;if(u===t)break;n++,r=s+a.length}return n}function K(e,t,n,r){return e.slice(0,t)+r+e.slice(t+n.length)}function Se(e){let t=new Map;return I(e,String.raw`\(\?<(?<captureName>[^>]+)>`,({0:n,index:r,groups:{captureName:o}})=>{t.has(o)||t.set(o,[]);let a=r+n.length,s=q(e,a);t.get(o).push({contents:s,endPos:a+s.length})},d.DEFAULT),t}function Te(e){let t=0;return I(e,String.raw`\(`,()=>t++,d.DEFAULT),t}var he=function(e,...t){let n=this instanceof Function?this:RegExp;if(Array.isArray(e?.raw))return H(n,{flags:""},e,...t);if((typeof e=="string"||e===void 0)&&!t.length)return H.bind(null,n,{flags:e});if({}.toString.call(e)==="[object Object]"&&!t.length)return H.bind(null,n,e);throw new Error(`Unexpected arguments: ${JSON.stringify([e,...t])}`)};function H(e,t,n,...r){let{flags:o="",postprocessors:a=[],__flagN:s=!0,__flagX:u=!0,__rake:c=!0}=t;if(/[vu]/.test(o))throw new Error("Flags v/u cannot be explicitly added since v is always enabled");u&&({template:n,values:r}=j(n,r,te)),s&&({template:n,values:r}=j(n,r,v));let l=0,E="",i={};return n.raw.forEach((m,g)=>{let $=n.raw[g]||n.raw[g+1];l+=D(m),E+=b(m,d.CHAR_CLASS),i=O(E,i);let{regexContext:C,charClassContext:L}=i;if(g<n.raw.length-1){let N=r[g];E+=_e(N,o,C,L,$,l),(N instanceof RegExp||N instanceof _)&&(l+=D(N.source||String(N)))}}),[...a,X,oe,...c?[ne]:[]].forEach(m=>E=m(E)),new e(E,`v${o}`)}function _e(e,t,n,r,o,a){if(e instanceof RegExp&&n!==f.DEFAULT)throw new Error("Cannot interpolate a RegExp at this position because the syntax context does not match");if(n===f.INVALID_INCOMPLETE_TOKEN||r===p.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=V(e,n===f.CHAR_CLASS?d.CHAR_CLASS:d.DEFAULT));let c=Z(u||e,n,r);if(c)throw new Error(`Unescaped stray "${c}" in the interpolated value would have side effects outside it`)}if(n===f.ENCLOSED_TOKEN||n===f.INTERVAL_QUANTIFIER||n===f.GROUP_NAME||r===p.ENCLOSED_TOKEN||r===p.Q_TOKEN)return s?e:u;if(n===f.CHAR_CLASS){if(s){if(w(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=W(G(e));return y(e)?`[${c}]`:b(c)}return y(u)?`[${u}]`:u}if(e instanceof RegExp){let c=Le(e,t),l=J(c.value,a);return c.usedModifier?l:`(?:${l})`}return s?`(?:${e})`:o?`(?:${u})`:u}function Le(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(F)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")&&(F?n.s=e.dotAll:o=A(o,"\\.",e.dotAll?"[^]":`[^${r}]`,d.DEFAULT)),e.multiline!==t.includes("m")&&(F?n.m=e.multiline:(o=A(o,"\\^",e.multiline?`(?<=^|[${r}])`:"(?<![^])",d.DEFAULT),o=A(o,"\\$",e.multiline?`(?=$|[${r}])`:"(?![^])",d.DEFAULT))),F){let a=Object.keys(n),s=a.filter(c=>n[c]===!0).join(""),u=a.filter(c=>n[c]===!1).join("");if(u&&(s+=`-${u}`),s)return{value:`(?${s}:${o})`,usedModifier:!0}}return{value:o}}return le(we);})();
//! regex 2.0.0; Steven Levithan; MIT License
//# sourceMappingURL=regex.min.js.map
{
"name": "regex",
"version": "1.1.1",
"version": "2.0.0",
"description": "Context-aware regex template tag with best practices built-in and advanced features",
"author": "Steven Levithan",
"license": "MIT",
"type": "module",
"exports": "./src/index.js",
"type": "module",
"scripts": {

@@ -13,4 +15,6 @@ "build": "esbuild src/index.js --bundle --minify --sourcemap --outfile=dist/regex.min.js --global-name=Regex",

},
"author": "Steven Levithan",
"license": "MIT",
"files": [
"src",
"dist"
],
"repository": {

@@ -25,8 +29,8 @@ "type": "git",

"dependencies": {
"regex-utilities": "^1.0.0"
"regex-utilities": "^2.0.0"
},
"devDependencies": {
"esbuild": "^0.21.4",
"esbuild": "^0.21.5",
"jasmine": "^5.1.0"
}
}

@@ -6,9 +6,9 @@ # `regex`

`regex` is a template tag for dynamically creating readable, high performance, native JavaScript regular expressions with advanced features. It's lightweight (5.6KB) and supports all ES2024+ regex features.
`regex` is a template tag for dynamically creating readable, high performance, native JavaScript regular expressions with advanced features. It's lightweight and supports all ES2024+ regex features.
Highlights include using whitespace and comments in regexes, atomic groups via `(?>…)` which can help you avoid [ReDoS](https://en.wikipedia.org/wiki/ReDoS), and context-aware interpolation of `RegExp` instances, escaped strings, and partial patterns.
Highlights include using whitespace and comments in regexes, atomic groups via `(?>…)` which can help you avoid [ReDoS](https://en.wikipedia.org/wiki/ReDoS), subroutines via `\g<name>` which enable powerful pattern composition, and context-aware interpolation of `RegExp` instances, escaped strings, and partial patterns.
## 🕹️ Install and use
```bash
```sh
npm install regex

@@ -38,2 +38,4 @@ ```

- [Atomic groups](#atomic-groups)
- [Subroutines](#subroutines)
- [Recursion](#recursion)
- [Flags](#-flags)

@@ -50,2 +52,3 @@ - [Implicit flags](#implicit-flags)

- [Interpolation contexts](#interpolation-contexts)
- [Performance](#-performance)
- [Compatibility](#-compatibility)

@@ -61,3 +64,6 @@ - [About](#️-about)

- No unreadable escaped backslashes `\\\\` since it's a raw string template tag.
- Atomic groups via `(?>…)` that can dramatically improve performance and prevent ReDoS.
- New regex syntax.
- Atomic groups via `(?>…)` can dramatically improve performance and prevent ReDoS.
- Subroutines via `\g<name>` enable powerful composition and improve readability.
- Recursive matching is enabled by an extension.
- Context-aware and safe interpolation of regexes, strings, and partial patterns.

@@ -76,3 +82,3 @@ - Interpolated strings have their special characters escaped.

|
# Only the inner regex is case insensitive (flag i)
# Only the inner regex is case insensitive (flag i).
# Also, the outer regex's flag m is not applied to it

@@ -86,2 +92,7 @@ ${/^a.b$/i}

(?> \w+ \s? )+
|
# Subroutines
^ Born: (?<date> \d{4}-\d{2}-\d{2} ) \n
Admitted: \g<date> \n
Released: \g<date> $
`;

@@ -103,3 +114,3 @@ ```

Additionally, JavaScript regex syntax is hard to write and even harder to read and refactor. But it doesn't have to be that way! With a few key features — raw multiline template strings, insignificant whitespace, comments, *named capture only* mode, and interpolation (coming soon: definition blocks and subexpressions as subroutines) — even long and complex regexes can be beautiful, grammatical, and easy to understand.
Additionally, JavaScript regex syntax is hard to write and even harder to read and refactor. But it doesn't have to be that way! With a few key features — raw multiline template strings, insignificant whitespace, comments, subroutines, interpolation, and *named capture only* mode — even long and complex regexes can be beautiful, grammatical, and easy to understand.

@@ -127,10 +138,74 @@ `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. It 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.

### Coming soon
### Subroutines
The following new regex syntax is planned for upcoming versions:
Subroutines, written as `\g<name>` where *name* refers to a named group, treat the referenced group as an independent subpattern that they try to match at the current position. This enables pattern composition, and is used to improve readability and maintainability, with potentially dramatic improvements for more complex regexes.
- Subexpressions as subroutines: `\g<name>`.
- Definition blocks: `(?(DEFINE)…)`.
- Recursion, up to a specified max depth: `(?R=N)`.
Here's a simple example that compares the behavior of subroutines and backreferences:
```js
// A standard backreference with \k<name>
regex`(?<prefix>Sens|Respons)e \+ \k<prefix>ibility`
// Matches only 'Sense+Sensibility' or 'Response+Responsibility'
// A subroutine with \g<name>
regex`(?<prefix>Sens|Respons)e \+ \g<prefix>ibility`
// In addition to the strings matched by the prior regex, this also matches
// 'Sense+Responsibility' and 'Response+Sensibility'
```
Subroutines go beyond the composition benefits of [interpolation](#-interpolation). Apart from the obvious difference that they don't require variables to be defined outside of the regex, they also don't simply insert the referenced subpattern.
1. They can reference groups that themselves contain subroutines, chained to any depth.
2. Any capturing groups that are set during the subroutine call revert to their previous values afterwards.
3. They don't create named captures that are visible outside of the subroutine, so using subroutines doesn't lead to "duplicate capture group name" errors.
To illustrate points 2 and 3, consider:
```js
regex`(?<n> (?<char>[ab]) \k<char> ) \g<n> \k<n>`
// The backreference \k<n> matches whatever was matched by capturing group n,
// regardless of what was matched by the subroutine. For example, the regex can
// match 'aabbaa' but not 'aabbbb'
```
More examples:
```js
// Matches an IPv4 address such as '192.168.12.123'
regex`
# Define a subpattern without matching it, due to the {0} quantifier
(?<byte> 2[0-4]\d | 25[0-5] | 1\d\d | [1-9]?\d ){0}
# Match the 4 parts, separated by dots
\b \g<byte> (\.\g<byte>){3} \b
`
// Matches an admittance record
regex`^
( (?<date> \g<year>-\g<month>-\g<day>)
(?<year> \d{4})
(?<month> \d{2})
(?<day> \d{2})
){0}
Name:\ (.*)\n
Born:\ \g<date>\n
Admitted:\ \g<date>\n
Released:\ \g<date>
$`
```
More details:
- Subroutines can appear before the group that they reference.
- Subroutines are applied after interpolation, giving them maximum flexibility.
- Subroutines can't be used recursively. For that, see the next section.
> [!NOTE]
> Subroutines are based on the feature in PCRE and Perl, although Perl uses `(?&name)` as the syntax. Ruby also supports subroutines using the `\g<name>` syntax like PCRE, but it has behavior differences related to capturing and backreferences.
### Recursion
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.
## 🚩 Flags

@@ -222,5 +297,5 @@

> [!NOTE]
> Flag <kbd>n</kbd> is based on .NET, C++, PCRE, Perl, and XRegExp, which share the <kbd>n</kbd> flag letter but call it *explicit capture*, *no auto capture*, or *nosubs*. In `regex`, the implicit flag <kbd>n</kbd> also prevents using numbered backreferences to named groups in the outer regex, which follows the behavior of C++. Referring to named groups by number is a footgun, and the way that named groups are numbered is inconsistent across regex flavors.
> Flag <kbd>n</kbd> is based on .NET, C++, PCRE, Perl, and XRegExp, which share the <kbd>n</kbd> flag letter but call it *explicit capture*, *no auto capture*, or *nosubs*. In `regex`, the implicit flag <kbd>n</kbd> also prevents using numbered backreferences to refer to named groups in the outer regex, which follows the behavior of C++ (Ruby also prevents this even without flag <kbd>n</kbd>). Referring to named groups by number is a footgun, and the way that named groups are numbered is inconsistent across regex flavors.
> Aside: Flag <kbd>n</kbd>'s behavior also enables `regex` to emulate atomic groups and recursion.
> Aside: Flag <kbd>n</kbd>'s behavior also enables `regex` to emulate atomic groups, subroutines, and recursion.

@@ -290,5 +365,5 @@ ## 🧩 Interpolation

These and other issues (including the effects of current and future flags like `x`) make escaping without context unsafe to use at arbitrary positions in a regex, or at least complicated to get right. The existing popular regex escaping libraries are all pretty bad at giving you something you can use reliably.
These and other issues (including the effects of current and future flags like `x`) make escaping without context unsafe to use at arbitrary positions in a regex, or at least complicated to get right. The existing popular regex escaping libraries don't even attempt to handle these kinds of issues.
`regex` solves this via context awareness. So instead of remembering anything above, you should just switch to always safely escaping regex syntax via `regex`.
`regex` solves all of this via context awareness. So instead of remembering anything above, you should just switch to always safely escaping regex syntax via `regex`.

@@ -304,3 +379,3 @@ ### Interpolating partial patterns

For all of these cases, you can interpolate `partial(value)` to avoid escaping special characters in the string or creating an intermediary `RegExp` instance. You can also use `` partial`…` `` as a tag, as shorthand for ``partial(String.raw`…`)``.
For all of these cases, you can interpolate `partial(str)` to avoid escaping special characters in the string or creating an intermediary `RegExp` instance. You can also use `` partial`…` `` as a tag, as shorthand for ``partial(String.raw`…`)``.

@@ -319,4 +394,4 @@ Apart from edge cases, `partial` just embeds the provided string or other value directly. But because it handles the edge cases, partial patterns can safely be interpolated anywhere in a regex without worrying about their meaning being changed by (or making unintended changes in meaning to) the surrounding pattern.

```js
regex`[${partial('^')}]`
regex`[a${partial('^')}]`
regex`[${partial`^`}]`
regex`[a${partial`^`}]`
```

@@ -326,3 +401,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. `partial('^^')` 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 `^`. They don't change the meaning of the surrounding character class. However, note that the `^` is not simply escaped. `` partial`^^` `` embedded in character class context would still correctly lead to an "invalid set operation" error due to the use of a reserved double-punctuator.

@@ -365,4 +440,4 @@ > If you wanted to dynamically choose whether to negate a character class, you could put the whole character class inside the partial.

/* 1.*/ regex`\u${'000A'}`
/* 2.*/ regex`\u{${partial('A}')}`
/* 3.*/ regex`(${partial('?:')}…)`
/* 2.*/ regex`\u{${partial`A}`}`
/* 3.*/ regex`(${partial`?:`}…)`
```

@@ -463,4 +538,3 @@

<tr>
<td>Group name: <code>(?<…>)</code>, <code>\k<…></code>
</td>
<td>Group name: <code>(?<…>)</code>, <code>\k<…></code>, <code>\g<…></code></td>
<td><code>regex`…\k<${'a'}>`</code></td>

@@ -476,2 +550,8 @@ </tr>

## ⚡ Performance
`regex` compiles to native `RegExp` instances. Therefore regexes built with `regex` perform just as fast as native regular expressions. There is a tiny extra cost when compiling a pattern.
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`.
## 🪶 Compatibility

@@ -485,7 +565,5 @@

`regex` was partly inspired by and significantly improves upon [`XRegExp`](https://github.com/slevithan/xregexp)`.tag` and [regexp-make-js](https://github.com/mikesamuel/regexp-make-js).
`regex` was partly inspired by and significantly improves upon [`XRegExp`](https://github.com/slevithan/xregexp)`.tag` and [regexp-make-js](https://github.com/mikesamuel/regexp-make-js). Version 1.0.0 was named Regex.make.
Version 1.0.0 was named Regex.make and used tag name `make` instead of `regex`. `make` is still available as an alias.
Crafted by Steven Levithan with ❤︎ for regular expressions and their enthusiasts.<br>
MIT License.
import {Context, hasUnescaped, replaceUnescaped} from 'regex-utilities';
import {noncapturingStart} from './utils.js';
export function transformAtomicGroups(pattern) {
/**
@param {string} pattern
@returns {string}
*/
export function atomicGroupsPostprocessor(pattern) {
if (!hasUnescaped(pattern, String.raw`\(\?>`, Context.DEFAULT)) {
return pattern;
}
const token = new RegExp(String.raw`(?<noncapturingStart>\(\?(?:[:=!>A-Za-z\-]|<[=!]))|(?<capturingStart>\((?:\?<[^>]+>)?)|(?<backrefNum>\\[1-9]\d*)|\\?.`, 'gsu');
const aGDelimLen = '(?>'.length;
let hasProcessedAG;
const token = new RegExp(String.raw`(?<noncapturingStart>${noncapturingStart})|(?<capturingStart>\((?:\?<[^>]+>)?)|(?<backrefNum>\\[1-9]\d*)|\\?.`, 'gsu');
const aGDelim = '(?>';
const emulatedAGDelim = '(?:(?=(';
let capturingGroupCount = 0;
let aGCount = 0;
let aGPos = NaN;
let hasProcessedAG;
do {

@@ -19,3 +25,3 @@ hasProcessedAG = false;

let match;
token.lastIndex = Number.isNaN(aGPos) ? 0 : aGPos + aGDelimLen;
token.lastIndex = Number.isNaN(aGPos) ? 0 : aGPos + emulatedAGDelim.length;
while (match = token.exec(pattern)) {

@@ -26,3 +32,3 @@ const {0: m, index: pos, groups: {backrefNum, capturingStart, noncapturingStart}} = match;

} else if (!numCharClassesOpen) {
if (m === '(?>' && !inAG) {
if (m === aGDelim && !inAG) {
aGPos = pos;

@@ -40,8 +46,8 @@ inAG = true;

aGCount++;
// Replace `pattern` and start over from the opening position of the atomic group, in
// case the processed group contains additional atomic groups
pattern = `${pattern.slice(0, aGPos)}(?:(?=(${pattern.slice(aGPos + aGDelimLen, pos)}))\\k<${aGCount + capturingGroupCount}>)${pattern.slice(pos + 1)}`;
// Replace pattern and use `\k<$$N>` as a temporary shield for the backref since
// numbered backrefs are prevented separately
pattern = `${pattern.slice(0, aGPos)}${emulatedAGDelim}${
pattern.slice(aGPos + aGDelim.length, pos)
}))\\k<$$${aGCount + capturingGroupCount}>)${pattern.slice(pos + 1)}`;
hasProcessedAG = true;
// Subtract the capturing group we just added as part of emulating an atomic group
capturingGroupCount--;
break;

@@ -51,6 +57,6 @@ }

} else if (backrefNum) {
// Could allow this with extra effort (adjusting both the backreferences found and those
// used to emulate atomic groups) but it's probably not worth it. To trigger this, the
// regex must contain both an atomic group and an interpolated RegExp instance with a
// numbered backreference
// Could allow this with extra effort (adjusting both the backrefs found and those used
// to emulate atomic groups) but it's probably not worth it. To trigger this, the regex
// must contain both an atomic group and an interpolated regex with a numbered backref
// (since numbered backrefs outside regex interpolation are prevented by implicit flag n)
throw new Error(`Invalid decimal escape "${m}" in interpolated regex; cannot be used with atomic group`);

@@ -62,7 +68,9 @@ }

}
// Start over from the beginning of the last atomic group's contents, in case the processed group
// contains additional atomic groups
} while (hasProcessedAG);
// Replace the `\k<…>` added as a shield from the check for invalid numbered backreferences
// Replace `\k<$$N>` added as a shield from the check for invalid numbered backrefs
pattern = replaceUnescaped(
pattern,
String.raw`\\k<(?<backrefNum>\d+)>`,
String.raw`\\k<\$\$(?<backrefNum>\d+)>`,
({groups: {backrefNum}}) => `\\${backrefNum}`,

@@ -69,0 +77,0 @@ Context.DEFAULT

@@ -1,9 +0,16 @@

import {RegexContext, contextToken, getEndContextForIncompletePattern} from './utils.js';
import {RegexContext, getEndContextForIncompletePattern, noncapturingStart} from './utils.js';
const token = new RegExp(String.raw`
${noncapturingStart}
| \(\?<
| (?<backrefNum> \\[1-9]\d* )
| \\? .
`.replace(/\s+/g, ''), 'gsu');
// Applied to the outer regex and interpolated partials, but not interpolated regexes or strings
export function flagNProcessor(value, runningContext) {
export function flagNPreprocessor(value, runningContext) {
value = String(value);
let pattern = '';
let transformed = '';
for (const [m] of value.matchAll(contextToken)) {
for (const {0: m, groups: {backrefNum}} of value.matchAll(token)) {
pattern += m;

@@ -15,3 +22,3 @@ runningContext = getEndContextForIncompletePattern(pattern, runningContext);

transformed += '(?:';
} else if (/^\\[1-9]/.test(m)) {
} else if (backrefNum) {
throw new Error(`Invalid decimal escape "${m}" with implicit flag n; replace with named backreference`);

@@ -18,0 +25,0 @@ } else {

import {Context, replaceUnescaped} from 'regex-utilities';
import {CharClassContext, RegexContext, contextToken, getEndContextForIncompletePattern, sandboxLoneDoublePunctuatorChar, sandboxUnsafeNulls} from './utils.js';
import {CharClassContext, RegexContext, doublePunctuatorChars, getEndContextForIncompletePattern, noncapturingStart, sandboxLoneDoublePunctuatorChar, sandboxUnsafeNulls} from './utils.js';

@@ -8,5 +8,21 @@ const ws = /^\s$/;

const escapedCharClassWs = /^\\[ \t]$/;
const token = new RegExp(String.raw`
\\ (?:
[gk] <
| [pPu] \{
| c [A-Za-z]
| u [A-Fa-f\d]{4}
| x [A-Fa-f\d]{2}
| 0 \d+
)
| \[\^
| ${noncapturingStart}
| \(\?<
| (?<dp> [${doublePunctuatorChars}] ) \k<dp>
| --
| \\? .
`.replace(/\s+/g, ''), 'gsu');
// Applied to the outer regex and interpolated partials, but not interpolated regexes or strings
export function flagXProcessor(value, runningContext) {
export function flagXPreprocessor(value, runningContext) {
value = String(value);

@@ -20,13 +36,13 @@ let ignoringWs = false;

let lastSignificantCharClassContext = '';
let divNeeded = false;
let separatorNeeded = false;
const update = (str, {prefix = true, postfix = false} = {}) => {
str = (divNeeded && prefix ? '(?:)' : '') + str + (postfix ? '(?:)' : '');
divNeeded = false;
str = (separatorNeeded && prefix ? '(?:)' : '') + str + (postfix ? '(?:)' : '');
separatorNeeded = false;
return str;
};
for (const [m] of value.matchAll(contextToken)) {
for (const [m] of value.matchAll(token)) {
if (ignoringComment) {
if (m === '\n') {
ignoringComment = false;
divNeeded = true;
separatorNeeded = true;
}

@@ -40,3 +56,3 @@ continue;

ignoringWs = false;
divNeeded = true;
separatorNeeded = true;
} else if (ignoringCharClassWs) {

@@ -52,15 +68,24 @@ if (charClassWs.test(m)) {

const {regexContext, charClassContext} = runningContext;
if (m === '-' && regexContext === RegexContext.CHAR_CLASS && lastSignificantCharClassContext === CharClassContext.RANGE) {
if (
m === '-' &&
regexContext === RegexContext.CHAR_CLASS &&
lastSignificantCharClassContext === CharClassContext.RANGE
) {
// Need to handle this here since the main regex-parsing code would think the hyphen forms
// part of a subtraction operator since we've removed preceding ws
// part of a subtraction operator since we've removed preceding whitespace
throw new Error('Invalid unescaped hyphen as the end value for a range');
}
if ((regexContext === RegexContext.DEFAULT && /^[?*+]\??$/.test(m)) || (regexContext === RegexContext.INTERVAL_QUANTIFIER && m === '{')) {
// Skip the separator prefix and connect the quantifier to the previous token. Add a
// separator postfix if `m` is `?` to sandbox it from follwing tokens since `?` can be a
// group-type marker. Ex: `( ?:)` becomes `(?(?:):)` and throws. The loop we're in matches
// valid group openings in one step, so we won't arrive here if matching e.g. `(?:`. Flag n
// precludes the need for the postfix since bare `(` is converted to `(?:`, but flag n can be
// turned off
transformed += update(m, {prefix: false, postfix: lastSignificantToken === '('});
if (
// `??` is matched in one step by the double punctuator token
(regexContext === RegexContext.DEFAULT && /^(?:[?*+]|\?\?)$/.test(m)) ||
(regexContext === RegexContext.INTERVAL_QUANTIFIER && m === '{')
) {
// Skip the separator prefix and connect the quantifier to the previous token. This also
// allows whitespace between a quantifier and the `?` that makes it lazy. Add a postfix
// separator if `m` is `?` and we're following token `(`, to sandbox the `?` from following
// tokens (since `?` can be a group-type marker). Ex: `( ?:)` becomes `(?(?:):)` and throws.
// The loop we're in matches valid group openings in one step, so we won't arrive here if
// matching e.g. `(?:`. Flag n could prevent the need for the postfix since bare `(` is
// converted to `(?:`, but flag x handling always comes first and flag n can be turned off
transformed += update(m, {prefix: false, postfix: lastSignificantToken === '(' && m === '?'});
} else if (regexContext === RegexContext.DEFAULT) {

@@ -87,3 +112,4 @@ if (ws.test(m)) {

// Need to handle this here since the main regex-parsing code wouldn't know where the token
// ends if we removed ws after it that was followed by something that completes the token
// ends if we removed whitespace after an incomplete token that is followed by something
// that completes the token
throw new Error(`Invalid incomplete token in character class: "${m}"`);

@@ -115,6 +141,6 @@ } else if (

// Remove `(?:)` separators (most likely added by flag x) in cases where it's safe to do so
export function rakeSeparators(pattern) {
export function rakePostprocessor(pattern) {
const sep = String.raw`\(\?:\)`;
// No need for repeated separators
pattern = replaceUnescaped(pattern, `${sep}(?:${sep})+`, '(?:)', Context.DEFAULT);
pattern = replaceUnescaped(pattern, `(?:${sep}){2,}`, '(?:)', Context.DEFAULT);
// No need for separators at:

@@ -124,3 +150,3 @@ // - The beginning, if not followed by a quantifier.

// - Before one of `()|$\`.
// - After one of `()|>^` or the opening of a non-capturing group or lookaround.
// - After one of `()|>^`, `(?:`, or a lookaround opening.
pattern = replaceUnescaped(

@@ -127,0 +153,0 @@ pattern,

@@ -1,9 +0,10 @@

//! regex 1.1.1; Steven Levithan; MIT License
//! regex 2.0.0; Steven Levithan; MIT License
import {Context, replaceUnescaped} from 'regex-utilities';
import {transformAtomicGroups} from './atomic-groups.js';
import {flagNProcessor} from './flag-n.js';
import {flagXProcessor, rakeSeparators} from './flag-x.js';
import {Context, hasUnescaped, replaceUnescaped} from 'regex-utilities';
import {atomicGroupsPostprocessor} from './atomic-groups.js';
import {flagNPreprocessor} from './flag-n.js';
import {flagXPreprocessor, rakePostprocessor} from './flag-x.js';
import {PartialPattern, partial} from './partial.js';
import {CharClassContext, RegexContext, adjustNumberedBackrefs, containsCharClassUnion, countCaptures, escapeV, getBreakoutChar, getEndContextForIncompletePattern, patternModsOn, sandboxLoneCharClassCaret, sandboxLoneDoublePunctuatorChar, sandboxUnsafeNulls, transformTemplateAndValues} from './utils.js';
import {subroutinesPostprocessor} from './subroutines.js';
import {CharClassContext, RegexContext, adjustNumberedBackrefs, containsCharClassUnion, countCaptures, escapeV, getBreakoutChar, getEndContextForIncompletePattern, patternModsSupported, preprocess, sandboxLoneCharClassCaret, sandboxLoneDoublePunctuatorChar, sandboxUnsafeNulls} from './utils.js';

@@ -13,3 +14,3 @@ /**

@prop {string} [flags]
@prop {Array<Function>} [postprocessors]
@prop {Array<(pattern: string) => string>} [postprocessors]
@prop {boolean} [__flagN]

@@ -75,6 +76,6 @@ @prop {boolean} [__flagX]

if (__flagX) {
({template, values} = transformTemplateAndValues(template, values, flagXProcessor));
({template, values} = preprocess(template, values, flagXPreprocessor));
}
if (__flagN) {
({template, values} = transformTemplateAndValues(template, values, flagNProcessor));
({template, values} = preprocess(template, values, flagNPreprocessor));
}

@@ -96,15 +97,15 @@

if (i < template.raw.length - 1) {
const interpolated = interpolate(values[i], flags, regexContext, charClassContext, wrapEscapedStr, precedingCaptures);
precedingCaptures += interpolated.capturesAdded || 0;
pattern += interpolated.value;
const value = values[i];
pattern += interpolate(value, flags, regexContext, charClassContext, wrapEscapedStr, precedingCaptures);
if (value instanceof RegExp || value instanceof PartialPattern) {
precedingCaptures += countCaptures(value.source || String(value));
}
}
});
const postp = [transformAtomicGroups, ...postprocessors];
if (__rake) {
postp.push(rakeSeparators);
}
for (const p of postp) {
pattern = p(pattern);
}
[ ...postprocessors,
atomicGroupsPostprocessor,
subroutinesPostprocessor,
...(__rake ? [rakePostprocessor] : []),
].forEach(pp => pattern = pp(pattern));
return new constructor(pattern, `v${flags}`);

@@ -127,5 +128,8 @@ }

if (!isPartial) {
escapedValue = escapeV(value, regexContext);
escapedValue = escapeV(
value,
regexContext === RegexContext.CHAR_CLASS ? Context.CHAR_CLASS : Context.DEFAULT
);
}
// Check within escaped values (not just partials) since possible breakout char > isn't escaped
// Check escaped values (not just partials) since possible breakout char `>` isn't escaped
const breakoutChar = getBreakoutChar(escapedValue || value, regexContext, charClassContext);

@@ -144,10 +148,9 @@ if (breakoutChar) {

) {
return {value: isPartial ? value : escapedValue};
return isPartial ? value : escapedValue;
} else if (regexContext === RegexContext.CHAR_CLASS) {
if (isPartial) {
const boundaryOperatorsRemoved = replaceUnescaped(value, '^-|^&&|-$|&&$', '');
if (boundaryOperatorsRemoved !== value) {
if (hasUnescaped(value, '^-|^&&|-$|&&$')) {
// Sandboxing so we don't change the chars outside the partial into being part of an
// operation they didn't initiate. Same as starting a partial with a quantifier
throw new Error('In character classes, a partial cannot use a range/set operator at its boundary; move the operation into the partial or the operator outside of it');
// operation they didn't initiate. Same problem as starting a partial with a quantifier
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');
}

@@ -157,6 +160,6 @@ const sandboxedValue = sandboxLoneCharClassCaret(sandboxLoneDoublePunctuatorChar(value));

// the unadjusted value)
return {value: containsCharClassUnion(value) ? `[${sandboxedValue}]` : sandboxUnsafeNulls(sandboxedValue)};
return containsCharClassUnion(value) ? `[${sandboxedValue}]` : sandboxUnsafeNulls(sandboxedValue);
}
// Atomize via nested character class `[…]` if more than one node
return {value: containsCharClassUnion(escapedValue) ? `[${escapedValue}]` : escapedValue};
return containsCharClassUnion(escapedValue) ? `[${escapedValue}]` : escapedValue;
}

@@ -168,13 +171,10 @@ // `RegexContext.DEFAULT`

// Sandbox and atomize; if we used a pattern modifier it has the same effect
return {
value: transformed.usedModifier ? backrefsAdjusted : `(?:${backrefsAdjusted})`,
capturesAdded: countCaptures(value.source),
};
return transformed.usedModifier ? backrefsAdjusted : `(?:${backrefsAdjusted})`;
}
if (isPartial) {
// Sandbox and atomize
return {value: `(?:${value})`};
return `(?:${value})`;
}
// Sandbox and atomize
return {value: wrapEscapedStr ? `(?:${escapedValue})` : escapedValue};
return wrapEscapedStr ? `(?:${escapedValue})` : escapedValue;
}

@@ -197,3 +197,3 @@

if (re.ignoreCase !== outerFlags.includes('i')) {
if (patternModsOn) {
if (patternModsSupported) {
modFlagsObj.i = re.ignoreCase;

@@ -205,3 +205,3 @@ } else {

if (re.dotAll !== outerFlags.includes('s')) {
if (patternModsOn) {
if (patternModsSupported) {
modFlagsObj.s = re.dotAll;

@@ -213,3 +213,3 @@ } else {

if (re.multiline !== outerFlags.includes('m')) {
if (patternModsOn) {
if (patternModsSupported) {
modFlagsObj.m = re.multiline;

@@ -222,3 +222,3 @@ } else {

if (patternModsOn) {
if (patternModsSupported) {
const keys = Object.keys(modFlagsObj);

@@ -240,8 +240,2 @@ let modifier = keys.filter(k => modFlagsObj[k] === true).join('');

// Alias for backcompat with v1.0.0; might be removed in v2
const make = regex;
export {make, partial, regex};
// The default export is deprecated and might be removed in v2
export default {make, partial, regex};
export {regex, partial};

@@ -1,10 +0,11 @@

import {Context, replaceUnescaped} from 'regex-utilities';
import {Context, forEachUnescaped, replaceUnescaped} from 'regex-utilities';
import {PartialPattern, partial} from './partial.js';
export const RegexContext = {
...Context,
GROUP_NAME: 'GROUP_NAME',
ENCLOSED_TOKEN: 'ENCLOSED_TOKEN',
INTERVAL_QUANTIFIER: 'INTERVAL_QUANTIFIER',
INVALID_INCOMPLETE_TOKEN: 'INVALID_INCOMPLETE_TOKEN',
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',
};

@@ -20,3 +21,3 @@

export const patternModsOn = (() => {
export const patternModsSupported = (() => {
let supported = true;

@@ -31,11 +32,14 @@ try {

const doublePunctuatorChars = '&!#$%*+,.:;<=>?@^`~';
export const doublePunctuatorChars = '&!#$%*+,.:;<=>?@^`~';
export const noncapturingStart = String.raw`\(\?(?:[:=!>A-Za-z\-]|<[=!])`;
/**
@param {string} str
@param {'DEFAULT' | 'CHAR_CLASS'} regexContext
@returns {string}
Escape special characters for the given context, assuming flag v.
@param {string} str String to escape
@param {'DEFAULT' | 'CHAR_CLASS'} context `Context` option from lib `regex-utilities`
@returns {string} Escaped string
*/
export function escapeV(str, regexContext) {
if (regexContext === RegexContext.CHAR_CLASS) {
export function escapeV(str, context) {
if (context === Context.CHAR_CLASS) {
// Escape all double punctuators (including ^, which is special on its own in the first

@@ -69,7 +73,13 @@ // position) in case they're bordered by the same character in or outside of the escaped string

// regex`[\0${0}]` and regex`[${partial`\0`}0]` can't be guarded against via nested `[…]`
// sandboxing in character classes if the interpolated value doesn't contain union (since it might
// be placed on a range boundary). So escape \0 in character classes as \u{0}
export function sandboxUnsafeNulls(str, inContext) {
return replaceUnescaped(str, String.raw`\\0(?!\d)`, '\\u{0}', inContext);
/**
Converts `\0` tokens to `\u{0}` in the given context.
@param {string} str
@param {'DEFAULT' | 'CHAR_CLASS'} [context] `Context` option from lib `regex-utilities`
@returns {string}
*/
export function sandboxUnsafeNulls(str, context) {
// regex`[\0${0}]` and regex`[${partial`\0`}0]` can't be guarded against via nested `[…]`
// sandboxing in character classes if the interpolated value doesn't contain union (since it
// might be placed on a range boundary). So escape \0 in character classes as \u{0}
return replaceUnescaped(str, String.raw`\\0(?!\d)`, '\\u{0}', context);
}

@@ -80,3 +90,3 @@

let numOpen = 0;
for (const [m] of pattern.matchAll(new RegExp(`[${escapeV(leftChar + rightChar)}]`, 'g'))) {
for (const [m] of pattern.matchAll(new RegExp(`[${escapeV(leftChar + rightChar, Context.CHAR_CLASS)}]`, 'g'))) {
numOpen += m === leftChar ? 1 : -1;

@@ -125,15 +135,4 @@ if (numOpen < 0) {

// To support flag x handling (where this regex is reused as a tokenizer, which isn't really its
// purpose in `getEndContextForIncompletePattern`), the following tokens are added which would
// otherwise not need special handling here:
// - Partial token versions of `\\[cux]`. Without serving dual purpose for flag x, `incompleteT`
// would only *need* to know about trailing unescaped `\\`.
// - Complete token versions of `\\[cux0]`.
// - Negated character class opener `[^`.
// - Group openings, so they can be stepped past (also relied on by flag n).
// - Double-punctuators.
// To support flag n, complete backreference numbers were also added so they can be shown in error
// messages. To support atomic groups, `(?>` was added
export const contextToken = new RegExp(String.raw`
(?<groupN> \(\?< (?! [=!] ) | \\k< )
const contextToken = new RegExp(String.raw`
(?<groupN> \(\?< (?! [=!] ) | \\[gk]< )
| (?<enclosedT> \\[pPu]\{ )

@@ -149,12 +148,2 @@ | (?<qT> \\q\{ )

)
| \\ (?:
c [A-Za-z]
| u [A-Fa-f\d]{4}
| x [A-Fa-f\d]{2}
| 0 \d+
)
| \[\^
| \(\? [:=!<>A-Za-z\-]
| (?<dp> [${doublePunctuatorChars}] ) \k<dp>
| \\[1-9]\d*
| --

@@ -176,3 +165,3 @@ | \\? .

const {0: m, groups: {groupN, enclosedT, qT, intervalQ, incompleteT}} = match;
if (m === '[' || m === '[^') {
if (m === '[') {
charClassDepth++;

@@ -188,4 +177,2 @@ regexContext = RegexContext.CHAR_CLASS;

}
// Reset for accuracy, but it will end up being an error if there is an unclosed context
// (ex: `\q{…` without closing `}`) in the character class
charClassContext = CharClassContext.DEFAULT;

@@ -203,3 +190,3 @@ } else if (regexContext === RegexContext.CHAR_CLASS) {

(m === '}' && (charClassContext === CharClassContext.ENCLOSED_TOKEN || charClassContext === CharClassContext.Q_TOKEN)) ||
// Don't want to continue in these contexts if we've advanced another token
// Don't continue in these contexts since we've advanced another token
charClassContext === CharClassContext.INVALID_INCOMPLETE_TOKEN ||

@@ -222,3 +209,3 @@ charClassContext === CharClassContext.RANGE

(m === '}' && (regexContext === RegexContext.ENCLOSED_TOKEN || regexContext === RegexContext.INTERVAL_QUANTIFIER)) ||
// Don't want to continue in this context if we've advanced another token
// Don't continue in this context since we've advanced another token
regexContext === RegexContext.INVALID_INCOMPLETE_TOKEN

@@ -238,25 +225,19 @@ ) {

// Assumes flag v and doesn't worry about syntax errors that are caught by it
export function countCaptures(pattern) {
const re = /(?<capture>\((?:(?!\?)|\?<[^>]+>))|\\?./gsu;
// Don't worry about tracking if we're in a character class or other invalid context for an
// unescaped `(`, because (given flag v) the unescaped `(` is invalid anyway. However, that means
// backrefs in subsequent interpolated regexes might be adjusted using an incorrect count, which
// is displayed in the error message about the overall regex being invalid
return Array.from(pattern.matchAll(re)).filter(m => m.groups.capture).length;
let num = 0;
forEachUnescaped(pattern, String.raw`\((?:(?!\?)|\?<[^>]+>)`, () => num++, Context.DEFAULT);
return num;
}
// Assumes flag v and doesn't worry about syntax errors that are caught by it
export function adjustNumberedBackrefs(pattern, precedingCaptures) {
// Note: Because this doesn't track whether matches are in a character class, it renumbers
// regardless. That's not a significant issue because the regex would be invalid even without
// renumbering (given flag v), but the error is more confusing when e.g. an invalid `[\1]` is
// shown as `[\2]`
return pattern.replace(
/\\([1-9]\d*)|\\?./gsu,
(m, b1) => b1 ? '\\' + (Number(b1) + precedingCaptures) : m
return replaceUnescaped(
pattern,
String.raw`\\(?<num>[1-9]\d*)`,
({groups: {num}}) => `\\${+num + precedingCaptures}`,
Context.DEFAULT
);
}
const propertiesOfStringsNames = [
// Properties of strings as of ES2024
const stringPropertyNames = [
'Basic_Emoji',

@@ -271,2 +252,17 @@ 'Emoji_Keycap_Sequence',

const charClassUnionToken = new RegExp(String.raw`
\\ (?:
c [A-Za-z]
| p \{ (?<pStrProp> ${stringPropertyNames} ) \}
| [pP] \{ [^\}]+ \}
| (?<qStrProp> q )
| u (?: [A-Fa-f\d]{4} | \{ [A-Fa-f\d]+ \} )
| x [A-Fa-f\d]{2}
| .
)
| --
| &&
| .
`.replace(/\s+/g, ''), 'gsu');
// Assumes flag v and doesn't worry about syntax errors that are caught by it

@@ -284,20 +280,6 @@ export function containsCharClassUnion(charClassPattern) {

// Supports any number of nested classes
const re = new RegExp(String.raw`
\\ (?:
c [A-Za-z]
| p \{ (?<pPropOfStr> ${propertiesOfStringsNames} ) \}
| [pP] \{ [^\}]+ \}
| (?<qPropOfStr> q )
| u (?: [A-Fa-f\d]{4} | \{ [A-Fa-f\d]+ \} )
| x [A-Fa-f\d]{2}
| .
)
| --
| &&
| .
`.replace(/\s+/g, ''), 'gsu');
let hasFirst = false;
let lastM;
for (const {0: m, groups} of charClassPattern.matchAll(re)) {
if (groups.pPropOfStr || groups.qPropOfStr) {
for (const {0: m, groups} of charClassPattern.matchAll(charClassUnionToken)) {
if (groups.pStrProp || groups.qStrProp) {
return true;

@@ -322,9 +304,10 @@ }

/**
The template's `raw` array is processed, along with (only) values that are instanceof `PartialPattern`.
Returns transformed versions of a template and values, using the given preprocessor. Expects the
template to contain a `raw` array, and only processes values that are instanceof `PartialPattern`.
@param {TemplateStringsArray} template
@param {any[]} values
@param {(value, runningContext) => {transformed: string; runningContext: Object}} processor
@param {(value, runningContext) => {transformed: string; runningContext: Object}} preprocessor
@returns {{template: TemplateStringsArray; values: any[]}}
*/
export function transformTemplateAndValues(template, values, processor) {
export function preprocess(template, values, preprocessor) {
let newTemplate = {raw: []};

@@ -334,3 +317,3 @@ let newValues = [];

template.raw.forEach((raw, i) => {
const result = processor(raw, {...runningContext, lastPos: 0});
const result = preprocessor(raw, {...runningContext, lastPos: 0});
newTemplate.raw.push(result.transformed);

@@ -341,3 +324,3 @@ runningContext = result.runningContext;

if (value instanceof PartialPattern) {
const result = processor(value, {...runningContext, lastPos: 0});
const result = preprocessor(value, {...runningContext, lastPos: 0});
newValues.push(partial(result.transformed));

@@ -344,0 +327,0 @@ runningContext = result.runningContext;

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc