compose-regexp
Advanced tools
Comparing version 0.6.27 to 0.6.28
# Change Log | ||
## v0.6.28 | ||
*2023-01-27* | ||
- ES6 conversion, bump babel, switch to terser. The .min.br file is 92 bytes lighter as a result. | ||
## v0.6.27 | ||
*2022-01-14* | ||
*2023-01-14* | ||
@@ -11,3 +17,3 @@ - More logo tweaks | ||
*2022-01-13* | ||
*2023-01-13* | ||
@@ -18,3 +24,3 @@ - Merge README fixes (version bump for the npm README). | ||
*2022-01-13* | ||
*2023-01-13* | ||
@@ -21,0 +27,0 @@ - Cosmetic tweaks to the logo (version bump for the npm README). |
@@ -8,3 +8,3 @@ (function (global, factory) { | ||
// Flag detection (conservatively, future flags may break our logic) | ||
var allFlags = []; | ||
const allFlags = []; | ||
"dgimsuy".split('').forEach(function(flag) { | ||
@@ -18,9 +18,7 @@ try { | ||
// This is currently used for modern vs legacy feature detection | ||
var supportsU = allFlags.indexOf('u') !== -1; | ||
var supportsLookBehind = false; | ||
try {new RegExp('(?<=)'); supportsLookBehind = true;} catch(e){} | ||
var hasOwn = ({}).hasOwnProperty; | ||
const supportsU = allFlags.indexOf('u') !== -1; | ||
const supportsLookBehind = (()=>{try {new RegExp('(?<=)'); return true} catch(e){return false}})(); | ||
const hasOwn = ({}).hasOwnProperty; | ||
function identity(x) {return x} | ||
var map = [].map; | ||
var slice = [].slice; | ||
const map = [].map; | ||
@@ -30,5 +28,6 @@ // Used only for type checking | ||
// This lets us set the global RegExp to a dummy function when testing, | ||
// to ensure that the API is throwing SyntaxErrors, not the | ||
// RegExp constructor downstream. | ||
var RegExpRef = RegExp; | ||
// to ensure that our API is throwing early SyntaxErrors, not the | ||
// RegExp constructor downstream (we have more info and can give more | ||
// precise feedback). | ||
const RegExpRef = RegExp; | ||
@@ -45,7 +44,7 @@ // We decode \x.. and \u{......} escapes manually, and defer to JSON.parse | ||
var propDesc = {value: void 0, writable:false, enumerable:false, configurable: false}; | ||
const propDesc = {value: void 0, writable:false, enumerable:false, configurable: false}; | ||
function randId(){return "_" + Math.floor(Math.random() * Math.pow(2,32)).toString(36)} | ||
var store = | ||
const store = | ||
(typeof WeakMap !== 'undefined') ? new WeakMap : | ||
@@ -57,5 +56,5 @@ // degenerate WeakMap polyfill | ||
set: function(k, v) { | ||
var type = typeof k; | ||
const type = typeof k; | ||
if (k == null || type !== 'object' && type !== 'function') {throw new TypeError("Bad WeakMap key")} | ||
var secret = k[store.key]; | ||
const secret = k[store.key]; | ||
if (!secret) { | ||
@@ -66,3 +65,3 @@ propDesc.value = {keys:[this], values:[v]}; | ||
} | ||
var index = secret.keys.indexOf(this); | ||
const index = secret.keys.indexOf(this); | ||
if (index === 0) return (secret.keys.push(this), secret.values.push(v), this) | ||
@@ -72,5 +71,5 @@ return (secret.values[index] = v, this) | ||
get: function(k) { | ||
var secret = k[store.key]; | ||
const secret = k[store.key]; | ||
if (secret) { | ||
var index = secret.keys.indexOf(this); | ||
const index = secret.keys.indexOf(this); | ||
if (index !== -1) return secret.values[index] | ||
@@ -84,45 +83,45 @@ } | ||
var captureMatcher = /\\[^]|\(\?(?::|<?[=!])|[\[\](]/g; | ||
const captureMatcher = /\\[^]|\(\?(?::|<?[=!])|[\[\](]/g; | ||
var dotMDotSMatcher = /\\.|\.|\(\?:\^\|\(\?<=\[\\n\\r\\u2028\\u2029\]\)\)|\(\?:\$\|\(\?=\[\\n\\r\\u2028\\u2029\]\)\)|\[|\]|\^|\$/g; | ||
const dotMDotSMatcher = /\\.|\.|\(\?:\^\|\(\?<=\[\\n\\r\\u2028\\u2029\]\)\)|\(\?:\$\|\(\?=\[\\n\\r\\u2028\\u2029\]\)\)|\[|\]|\^|\$/g; | ||
var groupNameMatcher = supportsU && new RegExp("^[_$\\p{ID_Start}][$\\p{ID_Continue}]*$", 'u'); | ||
const groupNameMatcher = supportsU && new RegExp("^[_$\\p{ID_Start}][$\\p{ID_Continue}]*$", 'u'); | ||
var loneBracketMatcher = /\\.|\{\d+,?\d*\}|(\[|\]|\{|\})/g; | ||
const loneBracketMatcher = /\\.|\{\d+,?\d*\}|(\[|\]|\{|\})/g; | ||
var mEndAnchor = /(?:$|(?=[\n\r\u2028\u2029]))/; | ||
const mEndAnchor = /(?:$|(?=[\n\r\u2028\u2029]))/; | ||
var mStartAnchor = /(?:^|(?<=[\n\r\u2028\u2029]))/; | ||
const mStartAnchor = /(?:^|(?<=[\n\r\u2028\u2029]))/; | ||
var numRefMatcher = /\\[^1-9]|[\[\]]|\\(\d{1,2})|\$d:(\d+),n:(\d+)\^/g; | ||
const numRefMatcher = /\\[^1-9]|[\[\]]|\\(\d{1,2})|\$d:(\d+),n:(\d+)\^/g; | ||
var oneEscapeOrCharClassMatcher = /^(?:\\.|\[(?:[^\]\\]|\\.)*\])$/; | ||
const oneEscapeOrCharClassMatcher = /^(?:\\.|\[(?:[^\]\\]|\\.)*\])$/; | ||
var pEscapeMatcher = /^\\p\{[A-Za-z][A-Za-z=]*\}$/; | ||
const pEscapeMatcher = /^\\p\{[A-Za-z][A-Za-z=]*\}$/; | ||
var stringNormalizerMatcher = /[.?*+^$[\]\\(){}|]/g; | ||
const stringNormalizerMatcher = /[.?*+^$[\]\\(){}|]/g; | ||
var suffixMatcher = /^(?:[+*?]|\{(?=((\d+)))\1,?(\d*)\})\??$/; | ||
const suffixMatcher = /^(?:[+*?]|\{(?=((\d+)))\1,?(\d*)\})\??$/; | ||
var tokenMatcher = /(\\.)|[-()|\[\]]((?=\?<?[=!]))?/g; | ||
const tokenMatcher = /(\\.)|[-()|\[\]]((?=\?<?[=!]))?/g; | ||
var uProblemCharClassMatcher = /\\u[0-9A-Fa-f]{4}|\\x[0-9A-Fa-f]{2}|\\c[A-Za-z]|\\([^.?*+^$[\]\\(){}|\/DSWdswfnrtv-])|(\\[DSWdsw]-[^\]]|.-\\[DSWdsw])|\\.|\]/g; | ||
const uProblemCharClassMatcher = /\\u[0-9A-Fa-f]{4}|\\x[0-9A-Fa-f]{2}|\\c[A-Za-z]|\\([^.?*+^$[\]\\(){}|\/DSWdswfnrtv-])|(\\[DSWdsw]-[^\]]|.-\\[DSWdsw])|\\.|\]/g; | ||
var uProblemDefaultMatcher = /\\u[0-9A-Fa-f]{4}|\\x[0-9A-Fa-f]{2}|\\c[A-Za-z]|\\k<(.*?)>|\\([^.?*+^$[\]\\(){}|\/DSWdswBbfnrtv])|\\.|\.|\[\^\]|\[|(\((?:\?[^])?)|(\)(?:[+?*]|\{\d+,?\d*\})?)/g; | ||
const uProblemDefaultMatcher = /\\u[0-9A-Fa-f]{4}|\\x[0-9A-Fa-f]{2}|\\c[A-Za-z]|\\k<(.*?)>|\\([^.?*+^$[\]\\(){}|\/DSWdswBbfnrtv])|\\.|\.|\[\^\]|\[|(\((?:\?[^])?)|(\)(?:[+?*]|\{\d+,?\d*\})?)/g; | ||
// General notes: | ||
// | ||
// | ||
// 1. Most functions here take an `x` parameter, which is our internal representation | ||
@@ -171,3 +170,3 @@ // of regexps, strings, etc... it has the following structure | ||
if (target instanceof RegExpRef) { | ||
var md = store.get(target); | ||
let md = store.get(target); | ||
if (md == null) store.set(target, md = MetaData()); | ||
@@ -180,6 +179,6 @@ return md | ||
var metadata = { | ||
const metadata = { | ||
set: function(target, property, value) { | ||
var md = findOrCreateMd(target); | ||
return (typeof property === 'object') | ||
const md = findOrCreateMd(target); | ||
return (typeof property === 'object') | ||
? Object.assign(md, property) | ||
@@ -189,3 +188,3 @@ : md[property] = value | ||
get: function(target, property) { | ||
var md = findOrCreateMd(target); | ||
const md = findOrCreateMd(target); | ||
return md[property] | ||
@@ -197,3 +196,3 @@ } | ||
return Object.defineProperty(function(x) { | ||
var cached = metadata.get(x.key, property); | ||
const cached = metadata.get(x.key, property); | ||
if (cached != null) return cached | ||
@@ -227,5 +226,6 @@ return metadata.set(x.key, property, f(x)) | ||
// a lookahead assertion | ||
var openGroups = []; | ||
const openGroups = []; | ||
function hasUProblem(x) { | ||
var matcher = uProblemDefaultMatcher, result; | ||
let matcher = uProblemDefaultMatcher; | ||
let result; | ||
openGroups.length = 0; | ||
@@ -274,4 +274,4 @@ function use(x) { | ||
var countCaptures = mdMemo('captureCount', function countCaptures(x) { | ||
var count = 0, result; | ||
const countCaptures = mdMemo('captureCount', function countCaptures(x) { | ||
let count = 0, result; | ||
captureMatcher.lastIndex = 0; | ||
@@ -287,4 +287,4 @@ while(result = captureMatcher.exec(x.source)) { | ||
var hasRefs = mdMemo('hasRefs', function hasRefs(x) { | ||
var hasRefs = false, hasFinalRef = false, inCClass = false, result; | ||
const hasRefs = mdMemo('hasRefs', function hasRefs(x) { | ||
let hasRefs = false, hasFinalRef = false, inCClass = false, result; | ||
numRefMatcher.lastIndex = 0; | ||
@@ -309,5 +309,5 @@ while(result = numRefMatcher.exec(x.source)) { | ||
var isDisjunction = mdMemo('isDisjunction', function isDisjunction(x) { | ||
const isDisjunction = mdMemo('isDisjunction', function isDisjunction(x) { | ||
if (x.source.indexOf('|') === -1) return false | ||
var depth = 0, inCClass = false, result; | ||
let depth = 0, inCClass = false, result; | ||
tokenMatcher.lastIndex = 0; | ||
@@ -327,6 +327,6 @@ while(result = tokenMatcher.exec(x.source)) { | ||
// Helper function for needsWrappingForQuantifier | ||
var isOneGroupOrAssertion = mdMemo('isOneGroupOrAssertion', function isOneGroupOrAssertion(x) { | ||
var source = x.source; | ||
const isOneGroupOrAssertion = mdMemo('isOneGroupOrAssertion', function isOneGroupOrAssertion(x) { | ||
const source = x.source; | ||
if (source.charAt(0) !== '(' || source.charAt(source.length - 1) !== ')') return false | ||
var depth = 0, inCClass = false, result; | ||
let depth = 0, inCClass = false, result; | ||
tokenMatcher.lastIndex = 0; | ||
@@ -356,14 +356,17 @@ while(result = tokenMatcher.exec(source)) { | ||
function needsWrappingForQuantifier(x) { | ||
var source = x.source; | ||
if (source == null || source === '^' || source === '$' || source === '\\b' || source === '\\B') throw new SyntaxError("Nothing to repeat: /"+(source || '(?:)')+"/") | ||
const source = x.source; | ||
if (source == null || source === '^' || source === '$' || source === '\\b' || source === '\\B') { | ||
throw new SyntaxError(`Nothing to repeat: / ${source || '(?:)' }/`) | ||
} | ||
// No need to look for standalone \k escapes, the are illegal in U and N mode, an non-atomic otherwise. | ||
if ( | ||
source.length === 1 | ||
|| oneEscapeOrCharClassMatcher.test(source) | ||
source.length === 1 | ||
|| oneEscapeOrCharClassMatcher.test(source) | ||
|| $flagValidator.U && pEscapeMatcher.test(source) | ||
) return false | ||
var og = isOneGroupOrAssertion(x); | ||
const og = isOneGroupOrAssertion(x); | ||
if (!og) return true | ||
if (/^\(\?<?[!=]/.test(source)) throw new SyntaxError("Nothing to repeat: /"+source+"/") | ||
// Reject look-arounds | ||
if (/^\(\?<?[!=]/.test(source)) throw new SyntaxError(`Nothing to repeat: /${ source }/`) | ||
return false | ||
@@ -390,3 +393,3 @@ } | ||
function promoteNonUnicodeToUnicode (source) { | ||
var inCClass = false; | ||
let inCClass = false; | ||
return source.replace(loneBracketMatcher, function(match, bracket) { | ||
@@ -408,3 +411,3 @@ if (match === ']') { | ||
function $$_fixRefs(initialOffset) { | ||
var count = initialOffset; | ||
let count = initialOffset; | ||
return function (x) { | ||
@@ -414,7 +417,7 @@ if (x.kind === 'regexp' || x.kind === 'result') { | ||
$refAndCap.hasRefs = true; | ||
var inCClass = false; | ||
let inCClass = false; | ||
x.source = x.source.replace(numRefMatcher, function(match, refIndex, depth, thunkIndex) { | ||
if (!inCClass) { | ||
if (refIndex != null) { | ||
var fixedRefIndex = (Number(refIndex) + count); | ||
const fixedRefIndex = (Number(refIndex) + count); | ||
if (fixedRefIndex > 99) throw new RangeError("Back reference index larger than 99") | ||
@@ -425,7 +428,7 @@ | ||
if (depth === '0') { | ||
var fixedRefIndex = Number(thunkIndex) + initialOffset; | ||
const fixedRefIndex = Number(thunkIndex) + initialOffset; | ||
if (fixedRefIndex > 99) throw new RangeError("Back reference index larger than 99") | ||
return '\\' + String(fixedRefIndex) | ||
} | ||
else return '$d:' + (Number(depth) -1) + ',n:' + thunkIndex + '^' | ||
else return `$d:${ Number(depth) - 1 },n:${ thunkIndex }^` | ||
} | ||
@@ -449,12 +452,14 @@ } | ||
function fixForFlags(x) { | ||
var source = x.source; | ||
if($flagValidator.U && (x.kind === 'regexp' && !x.key.unicode || x.kind === 'result' && !metadata.get(x.key, 'unicode'))) { | ||
if(hasUProblem(source)) throw new SyntaxError("Can't upgrade the RegExp to Unicode /"+ source + "/" + (x.kind === 'regexp' ? x.key.flags : '')) | ||
x.source = promoteNonUnicodeToUnicode(source); | ||
const source = x.source; | ||
if ($flagValidator.U && (x.kind === 'regexp' && !x.key.unicode || x.kind === 'result' && !metadata.get(x.key, 'unicode'))) { | ||
if(hasUProblem(source)) { | ||
throw new SyntaxError(`Can't upgrade the RegExp to Unicode /${ source }/${ x.kind === 'regexp' ? x.key.flags : '' }`) | ||
} | ||
x.source = promoteNonUnicodeToUnicode(source); | ||
} | ||
var inCClass = false; | ||
let inCClass = false; | ||
if (x.kind === 'regexp' && (x.key.dotAll || x.key.multiline)) x.source = source.replace(dotMDotSMatcher, function(match) { | ||
if (!inCClass) { | ||
if (match === '[') inCClass = true; | ||
return (x.key.dotAll && match === '.') ? '[^]' | ||
return (x.key.dotAll && match === '.') ? '[^]' | ||
: (x.key.multiline && match === '^'&& supportsLookBehind) ? mStartAnchor.source | ||
@@ -467,3 +472,3 @@ : (x.key.multiline && match === '$' && supportsLookBehind) ? mEndAnchor.source | ||
} | ||
}); | ||
@@ -474,15 +479,22 @@ return x | ||
// ensures that each flag appears only once | ||
var flagsMatcher = new RegExp('^(?:([' + allFlags.join('') + '])(?!.*\\1))*$'); | ||
const flagsMatcher = new RegExp(`^(?:([${ allFlags.join('') }])(?!.*\\1))*$`); | ||
const flagFinder = new RegExp(`[${ allFlags.join() }]`, 'g'); | ||
function $$_checkFlags(x) { | ||
var flags = x.key.flags; | ||
const flags = x.key.flags; | ||
if (!flagsMatcher.test(flags)) throw new TypeError("Unkown flags: " + flags.replace(new RegExp('['+allFlags.join()+']', 'g'), '')) | ||
if (!flagsMatcher.test(flags)) { | ||
throw new TypeError(`Unkown flag(s): ${ flags.replace(flagFinder, '')}`) | ||
} | ||
var hasU = !!x.key.unicode; | ||
var hasI = x.key.ignoreCase; | ||
var hasM = x.key.multiline; | ||
const hasU = !!x.key.unicode; | ||
const hasI = x.key.ignoreCase; | ||
const hasM = x.key.multiline; | ||
if ($flagValidator.I != null && hasI !== $flagValidator.I) throw new SyntaxError("Can't combine i and non-i regexps: " + x.key) | ||
if (!supportsLookBehind && $flagValidator.M != null && hasM !== $flagValidator.M) throw new SyntaxError("Can't combine m and non-m regexps: " + x.key) | ||
if ($flagValidator.I != null && hasI !== $flagValidator.I) { | ||
throw new SyntaxError("Can't combine i and non-i regexps: " + x.key) | ||
} | ||
if (!supportsLookBehind && $flagValidator.M != null && hasM !== $flagValidator.M) { | ||
throw new SyntaxError("Can't combine m and non-m regexps: " + x.key) | ||
} | ||
@@ -497,7 +509,13 @@ $flagValidator.I = hasI; | ||
//+ | ||
var directionNames = {'-1': 'backward', '1': 'forward'}; | ||
const directionNames = {'-1': 'backward', '1': 'forward'}; | ||
function $$_checkDirection(x) { | ||
var d = metadata.get(x.key, 'direction'); | ||
const d = metadata.get(x.key, 'direction'); | ||
if (d * $direction.current === -1) throw new TypeError( | ||
"Illegal " + directionNames[d] + " RegExp argument while building a " + directionNames[$direction.current] + " one: /" + x.source + "/" | ||
`Illegal ${ | ||
directionNames[d] | ||
} RegExp argument while building a ${ | ||
directionNames[$direction.current] | ||
} one: /${ | ||
x.source | ||
}/` | ||
) | ||
@@ -515,14 +533,14 @@ if (d !== 0) $refAndCap.hasRefs = true; | ||
? function(x2, x1){ | ||
x2.source = x2.source == null ? x1.source : x1.source + '|' + x2.source; | ||
x2.source = x2.source == null ? x1.source : `${ x1.source }|${ x2.source }`; | ||
return x2 | ||
} | ||
: function(x2, x1){ | ||
x2.source = x2.source == null | ||
? x1.source | ||
x2.source = x2.source == null | ||
? x1.source | ||
: x1.source + ( | ||
// corner case where a numeric ref is followed by a number | ||
x1.kind !== 'string' | ||
x1.kind !== 'string' | ||
// sets the 'hasFinalRef' metadata as a side effect | ||
&& hasRefs(x1) | ||
&& metadata.get(x1.key, 'hasFinalRef') | ||
&& metadata.get(x1.key, 'hasFinalRef') | ||
&& (/^\d/.test(x2.source)) | ||
@@ -532,3 +550,3 @@ ? '(?:)' | ||
) + x2.source; | ||
return x2 | ||
@@ -559,8 +577,8 @@ } | ||
// goes the other way. | ||
var $direction = { | ||
let $direction = { | ||
current: 1, | ||
}; | ||
var $flagValidator; | ||
var $refAndCap; | ||
let $flagValidator; | ||
let $refAndCap; | ||
@@ -579,4 +597,4 @@ function $$_resetRefCapsAndFlags() { | ||
function $$_reentrantRefCapFlag(f) { | ||
var previousRnC = $refAndCap; | ||
var previousFV = $flagValidator; | ||
const previousRnC = $refAndCap; | ||
const previousFV = $flagValidator; | ||
try {return f()} finally { | ||
@@ -609,3 +627,3 @@ $refAndCap = previousRnC; | ||
} | ||
throw new TypeError("Can't compose type " + typeof x + " as RegExp") | ||
throw new TypeError(`Can't compose type ${ typeof x } as RegExp`) | ||
} | ||
@@ -639,6 +657,9 @@ | ||
direction: $refAndCap.hasRefs ? $direction.current : 0, | ||
isDisjunction: either && (patterns.length > 1 || patterns.length === 1 && (patterns[0] instanceof RegExpRef) && metadata.get(patterns[0], 'isDisjunction')), | ||
isDisjunction: either && ( | ||
patterns.length > 1 | ||
|| patterns.length === 1 && (patterns[0] instanceof RegExpRef) && metadata.get(patterns[0], 'isDisjunction') | ||
), | ||
unicode: $flagValidator.U | ||
}, $refAndCap)), | ||
kind: 'result', | ||
kind: 'result', | ||
source: null | ||
@@ -654,5 +675,5 @@ }) | ||
options = options || {}; | ||
var flags = hasOwn.call(options, 'flags') ? options.flagsOp(getFlags(), options.flags) : getFlags(); | ||
var either = options.either; | ||
var result = new RegExp((either ? x.source || '[]': x.source || ''), flags); | ||
const flags = hasOwn.call(options, 'flags') ? options.flagsOp(getFlags(), options.flags) : getFlags(); | ||
const either = options.either; | ||
const result = new RegExp((either ? x.source || '[]': x.source || ''), flags); | ||
metadata.set(result, metadata.set(x.key, {})); | ||
@@ -677,4 +698,4 @@ metadata.set(result, 'source', x.source); | ||
var empty = /(?:)/; | ||
var never = /[]/; | ||
const empty = /(?:)/; | ||
const never = /[]/; | ||
@@ -685,27 +706,27 @@ function throwIfNoLookBehind(name) { | ||
function either() { | ||
if (!arguments.length) return never | ||
function either(...args) { | ||
if (args.length === 0) return never | ||
$$_resetRefCapsAndFlags(); | ||
return finalize(assemble(arguments, true, false, 0), {either: true}) | ||
return finalize(assemble(args, true, false, 0), {either: true}) | ||
} | ||
function _sequence() { | ||
return assemble(arguments, false, false, 0) | ||
function _sequence(...args) { | ||
return assemble(args, false, false, 0) | ||
} | ||
function sequence() { | ||
if (!arguments.length) return empty | ||
function sequence(...args) { | ||
if (args.length === 0) return empty | ||
$$_resetRefCapsAndFlags(); | ||
return finalize(_sequence.apply(null, arguments)) | ||
return finalize(_sequence(...args)) | ||
} | ||
function makeAssertion (before, direction, emptyFallback, gate, name) { | ||
return function () { | ||
return function (...args) { | ||
if (gate != null) gate(name); | ||
if (!arguments.length) return emptyFallback | ||
var previousDir = $direction.current; | ||
if (!args.length) return emptyFallback | ||
const previousDir = $direction.current; | ||
$direction.current = direction; | ||
try { | ||
$$_resetRefCapsAndFlags(); | ||
var result = _sequence.apply(null, arguments); | ||
const result = _sequence(...args); | ||
return finalize(decorate(result, {open: before}), {direction: 0}) | ||
@@ -718,10 +739,10 @@ } finally { | ||
var lookAhead = makeAssertion('(?=', 1, empty); | ||
var notAhead = makeAssertion('(?!', 1, never); | ||
var lookBehind = makeAssertion('(?<=', -1, empty, throwIfNoLookBehind, "lookBehind"); | ||
var notBehind = makeAssertion('(?<!', -1, never, throwIfNoLookBehind, "notBehind"); | ||
const lookAhead = makeAssertion('(?=', 1, empty); | ||
const notAhead = makeAssertion('(?!', 1, never); | ||
const lookBehind = makeAssertion('(?<=', -1, empty, throwIfNoLookBehind, "lookBehind"); | ||
const notBehind = makeAssertion('(?<!', -1, never, throwIfNoLookBehind, "notBehind"); | ||
var call = _suffix.call; | ||
_suffix.call; | ||
function _suffix() { | ||
function _suffix(quantifier, ...args) { | ||
// the quantifier is passed as context | ||
@@ -731,17 +752,17 @@ $$_resetRefCapsAndFlags(); | ||
// without allocating an array. The operator is passed as `this` which is ignored. | ||
if (arguments.length === 1) throw new SyntaxError("Suffix to an empty prefix") | ||
var res = call.apply(_sequence, arguments); | ||
return finalize(decorate(res, {condition: needsWrappingForQuantifier, open: '(?:', suffix: this})) | ||
if (args.length === 0) throw new SyntaxError("Suffix to an empty prefix") | ||
const res = _sequence(...args); | ||
return finalize(decorate(res, {condition: needsWrappingForQuantifier, open: '(?:', suffix: quantifier})) | ||
} | ||
function suffix(quantifier) { | ||
function suffix(quantifier, ...args) { | ||
if (typeof quantifier !== 'string') quantifier = '{' + String(quantifier) + '}'; | ||
var match = quantifier.match(suffixMatcher); | ||
const match = quantifier.match(suffixMatcher); | ||
if (!match || match[3] && Number(match[3]) < Number(match[2])) throw new SyntaxError("Invalid suffix '" + quantifier+ "'.") | ||
return arguments.length === 1 | ||
? _suffix.bind(quantifier, quantifier) | ||
: _suffix.apply(quantifier, arguments) | ||
return args.length === 0 | ||
? _suffix.bind(null, quantifier) | ||
: _suffix(quantifier, ...args) | ||
} | ||
var maybe = suffix('?'); | ||
const maybe = suffix('?'); | ||
@@ -760,3 +781,3 @@ | ||
function checkRef(name) { | ||
var type = typeof name; | ||
const type = typeof name; | ||
return type === 'string' && validateGroupName(name) | ||
@@ -770,3 +791,3 @@ || type === 'number' && 0 < name && Math.round(name) === name | ||
if (typeof n === 'string') return new RegExp('\\k<' + n + '>') | ||
var result = new RegExp('$d:' + (depth || '0')+ ",n:" + n + "^"); | ||
const result = new RegExp('$d:' + (depth || '0')+ ",n:" + n + "^"); | ||
metadata.set(result, { | ||
@@ -780,20 +801,20 @@ direction: $direction.current, | ||
function capture() { | ||
function capture(...args) { | ||
$$_resetRefCapsAndFlags(); | ||
var res = assemble(arguments, false, false, 1); | ||
const res = assemble(args, false, false, 1); | ||
return finalize(decorate(res, {open: '('})) | ||
} | ||
function _namedCapture(name) { | ||
function _namedCapture(name, ...args) { | ||
if (typeof name !== 'string') throw new TypeError("String expected, got " + typeof name) | ||
validateGroupName(name); | ||
$$_resetRefCapsAndFlags(); | ||
var res = assemble(slice.call(arguments, 1), false, false, 1); | ||
const res = assemble(args, false, false, 1); | ||
return finalize(decorate(res, {open: '(?<' + name + '>'})) | ||
} | ||
function namedCapture(name) { | ||
return (arguments.length === 1 | ||
function namedCapture(name, ...args) { | ||
return (args.length === 0 | ||
? _namedCapture.bind(null, name) | ||
: _namedCapture.apply(null, arguments)) | ||
: _namedCapture(name, ...args)) | ||
} | ||
@@ -821,3 +842,3 @@ | ||
function _flags(fl) { | ||
function _flags(fl, ...args) { | ||
// the operation is passed as context | ||
@@ -829,12 +850,12 @@ $$_resetRefCapsAndFlags(); | ||
// bad hack, see _suffix | ||
var source = call.apply(_sequence, arguments); | ||
return finalize(source, {flagsOp: this, flags: fl}) | ||
const source = _sequence(...args); | ||
return finalize(source, {flagsOp: flagAdd, flags: fl}) | ||
} | ||
var flags = {add: function add(flags) { | ||
const flags = {add: function add(flags, ...args) { | ||
if (typeof flags !== 'string') throw TypeError("String expected as first argument, got " + typeof flags) | ||
if (!flagsMatcher.test(flags)) throw new SyntaxError("Invalid flags: " + flags) | ||
return arguments.length === 1 | ||
? _flags.bind(flagAdd, flags) | ||
: _flags.apply(flagAdd, arguments) | ||
return args.length === 0 | ||
? _flags.bind(null, flags) | ||
: _flags(flags, ...args) | ||
}}; | ||
@@ -845,11 +866,11 @@ | ||
function atomic() { | ||
function atomic(...args) { | ||
return $direction.current === 1 | ||
// forward: | ||
? sequence(lookAhead(capture.apply(null, arguments)), ref(1)) | ||
? sequence(lookAhead(capture(...args)), ref(1)) | ||
// backward: | ||
: sequence(ref(1), lookBehind(capture.apply(null, arguments))) | ||
: sequence(ref(1), lookBehind(capture(...args))) | ||
} | ||
var allU = supportsU && new RegExp('[^]', 'u'); | ||
const allU = supportsU && new RegExp('[^]', 'u'); | ||
function csDiff(a, b) {return sequence(notAhead(b), a)} | ||
@@ -859,3 +880,3 @@ function csInter(a, b) {return sequence(lookAhead(b), a)} | ||
var charSet = { | ||
const charSet = { | ||
difference: csDiff, | ||
@@ -899,4 +920,2 @@ intersection: csInter, | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
})); |
@@ -36,2 +36,5 @@ | ||
export declare function suffix<BQ extends BracketQuantifier>( | ||
s: SimpleQuantifier | HackyQuantifier | Subtract<BQ, NotInInteger> | ||
) : typeof sequence | ||
export declare function suffix<BQ extends BracketQuantifier>( | ||
s: SimpleQuantifier | HackyQuantifier | Subtract<BQ, NotInInteger>, | ||
@@ -140,2 +143,1 @@ ...x: Param[] | ||
} | ||
## Contributing to compose-regexp.js | ||
`compose-regexp` is most likely feature-complete. You may suggest improvements, but be warned that they are likely not to be accepted... However, don't let that stop you from proposing ideas, just don't set your expectations too high, and be courteous with the people you interact with around here. | ||
`compose-regexp` is most likely feature-complete (beside advanced type checking). You may suggest improvements, but be warned that they are likely not to be accepted... However, don't let that stop you from proposing ideas, just don't set your expectations too high, and be courteous with the people you interact with around here. | ||
If you found a bug feel free to open an issue or submit a PR. | ||
The coding style may be a bit awkward. | ||
`compose-regexp` was started at a time where I still cared about IE compatibility and wanted to support ES6 modules. To keep the tooling minimal, I decided to write it in ES5 + ES6 modules, using Rollup as a bundler to create the UMD (and the bragging artefacts in `./dist`). The old version of Rollup that I use understands exactly that dialect, and I kept it when I started updating the lib in 2022. It is annoying when dealing with vararg functions, but otherwise a soothing experience for me, actually. | ||
The core has comments that will hopefully help you navigate the code base. Single quoted strings are used everywhere except for error messages. | ||
The tests are written using [ospec](https://github.com/MithrilJS/ospec), which has a very shallow learning curve, using two dedicated `.satisfies()` helpers (`m()` and `r()`) that should be self-documenting in context. |
@@ -1,2 +0,1 @@ | ||
/**@license MIT-compose-regexp.js-©Pierre-Yves Gérardy*/ | ||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define("compose-regexp",["exports"],n):(e="undefined"!=typeof globalThis?globalThis:e||self,n(e.composeRegexp={}))}(this,function(e){"use strict";function n(e){return e}function r(e){return-1===e.indexOf("\\")?e:JSON.parse('"'+e.replace(/$|"|\\x([\dA-Fa-f]{2})|\\u\{([\dA-Fa-f]{1,6})\}/g,function(e,n,r){return""===e?'"':'"'===e?'\\"':String.fromCodePoint(parseInt(n||r,16))}))}function t(){return"_"+Math.floor(Math.random()*Math.pow(2,32)).toString(36)}function u(){return{captureCount:null,direction:0,hasRefs:null,hasFinalRef:null,isDisjunction:null,isOneGroupOrAssertion:null,source:null,unicode:null}}function i(e){if(e instanceof Y){var n=ne.get(e);return null==n&&ne.set(e,n=u()),n}return e||u()}function o(e,n){return Object.defineProperty(function(r){var t=ye.get(r.key,e);return null!=t?t:ye.set(r.key,e,n(r))},"name",{value:e})}function f(e){return ye.get(e,"source")||ye.set(e,"source",e.source)}function c(e){function n(e){e.lastIndex=u.lastIndex,u=e}var t,u=he;for(xe.length=0,he.lastIndex=0;t=u.exec(e);)if(u===he)if("["===t[0])n(ge);else{if("."===t[0]||"[^]"===t[0]||null!=t[1]&&!ue.test(r(t[1]))||null!=t[2])return!0;if(null!=t[3])xe.unshift(t[3]);else if(null!=t[4]){if(("(?="===xe[0]||"(?!"===xe[0])&&")"!==t[4])return!0;xe.shift()}}else if("]"===t[0])n(he);else if(null!=t[1]||null!=t[2])return!0;return!1}function l(e){var n=e.source;if(null==n||"^"===n||"$"===n||"\\b"===n||"\\B"===n)throw new SyntaxError("Nothing to repeat: /"+(n||"(?:)")+"/");if(1===n.length||le.test(n)||K.U&&ae.test(n))return!1;if(!me(e))return!0;if(/^\(\?<?[!=]/.test(n))throw new SyntaxError("Nothing to repeat: /"+n+"/");return!1}function a(e){var n=!1;return e.replace(ie,function(e,r){if("]"===e){if(!n)return"\\]";n=!1}else if(!n&&null!=r){if("["!==r)return"\\"+r;n=!0}return e})}function s(e){var n=e;return function(r){if("regexp"===r.kind||"result"===r.kind){if(ke(r)){L.hasRefs=!0;var t=!1;r.source=r.source.replace(ce,function(r,u,i,o){if(!t){if(null!=u){var f=Number(u)+n;if(f>99)throw new RangeError("Back reference index larger than 99");return"\\"+String(f)}if(null!=i){if("0"===i){var f=Number(o)+e;if(f>99)throw new RangeError("Back reference index larger than 99");return"\\"+String(f)}return"$d:"+(Number(i)-1)+",n:"+o+"^"}}return"["===r?t=!0:"]"===r&&(t=!1),r})}L.hasFinalRef=!!ye.get(r.key,"hasFinalRef"),n+=we(r)}return L.captureCount=n,r}}function p(e){var n=e.source;if(K.U&&("regexp"===e.kind&&!e.key.unicode||"result"===e.kind&&!ye.get(e.key,"unicode"))){if(c(n))throw new SyntaxError("Can't upgrade the RegExp to Unicode /"+n+"/"+("regexp"===e.kind?e.key.flags:""));e.source=a(n)}var r=!1;return"regexp"===e.kind&&(e.key.dotAll||e.key.multiline)&&(e.source=n.replace(te,function(n){return r?("]"===n&&(r=!1),n):("["===n&&(r=!0),e.key.dotAll&&"."===n?"[^]":e.key.multiline&&"^"===n&&H?fe.source:e.key.multiline&&"$"===n&&H?oe.source:n)})),e}function d(e){var n=e.key.flags;if(!be.test(n))throw new TypeError("Unkown flags: "+n.replace(new RegExp("["+G.join()+"]","g"),""));var r=!!e.key.unicode,t=e.key.ignoreCase,u=e.key.multiline;if(null!=K.I&&t!==K.I)throw new SyntaxError("Can't combine i and non-i regexps: "+e.key);if(!H&&null!=K.M&&u!==K.M)throw new SyntaxError("Can't combine m and non-m regexps: "+e.key);return K.I=t,K.M=u,K.U=K.U||r,e}function g(e){var n=ye.get(e.key,"direction");if(n*Re.current==-1)throw new TypeError("Illegal "+Ee[n]+" RegExp argument while building a "+Ee[Re.current]+" one: /"+e.source+"/");return 0!==n&&(L.hasRefs=!0),e}function h(e){return e?function(e,n){return e.source=null==e.source?n.source:n.source+"|"+e.source,e}:function(e,n){return e.source=null==e.source?n.source:n.source+("string"!==n.kind&&ke(n)&&ye.get(n.key,"hasFinalRef")&&/^\d/.test(e.source)?"(?:)":"")+e.source,e}}function y(){L={hasRefs:!1,hasFinalRef:!1,captureCount:0},K={U:!1,I:null,M:null}}function x(e){var n=L,r=K;try{return e()}finally{L=n,K=r}}function w(e,n){return n.condition&&!n.condition(e)||(e.source=n.open+(e.source||"")+")"),n.suffix&&(e.source+=n.suffix),e}function k(e){return w(e,{condition:function(e){return("regexp"===e.kind||"result"===e.kind)&&ve(e)},open:"(?:"})}function v(e){if("number"==typeof e||"string"==typeof e)return{key:null,kind:"string",source:String(e).replace(se,"\\$&")};throw new TypeError("Can't compose type "+typeof e+" as RegExp")}function m(e,r,t,u){return t=t||e.length>1,V.call(e,function e(u){return(!r&&t?k:n)(Array.isArray(u)?m(u,!1,t,0):"function"==typeof u?e(x(u)):u instanceof Y?g(d({key:u,kind:"regexp",source:f(u)})):v(u))}).map(p).map(s(u)).reduceRight(h(r),{key:ye.set(null,Object.assign({direction:L.hasRefs?Re.current:0,isDisjunction:r&&(e.length>1||1===e.length&&e[0]instanceof Y&&ye.get(e[0],"isDisjunction")),unicode:K.U},L)),kind:"result",source:null})}function b(){return(K.I?"i":"")+(H?"":K.M?"m":"")+(K.U?"u":"")}function E(e,n){n=n||{};var r=Q.call(n,"flags")?n.flagsOp(b(),n.flags):b(),t=n.either,u=new RegExp(t?e.source||"[]":e.source||"",r);return ye.set(u,ye.set(e.key,{})),ye.set(u,"source",e.source),Q.call(n,"direction")&&ye.set(u,"direction",n.direction),u}function R(e){if(!H)throw new Error("no support for /(?<=...)/ which is required by "+e+"()")}function S(){return arguments.length?(y(),E(m(arguments,!0,!1,0),{either:!0})):$e}function $(){return m(arguments,!1,!1,0)}function A(){return arguments.length?(y(),E($.apply(null,arguments))):Se}function O(e,n,r,t,u){return function(){if(null!=t&&t(u),!arguments.length)return r;var i=Re.current;Re.current=n;try{y();return E(w($.apply(null,arguments),{open:e}),{direction:0})}finally{Re.current=i}}}function I(){if(y(),1===arguments.length)throw new SyntaxError("Suffix to an empty prefix");return E(w(_e.apply($,arguments),{condition:l,open:"(?:",suffix:this}))}function j(e){"string"!=typeof e&&(e="{"+String(e)+"}");var n=e.match(pe);if(!n||n[3]&&Number(n[3])<Number(n[2]))throw new SyntaxError("Invalid suffix '"+e+"'.");return 1===arguments.length?I.bind(e,e):I.apply(e,arguments)}function _(e){return!J||ue.test(r(e))}function B(e){var n=typeof e;return"string"===n&&_(e)||"number"===n&&0<e&&Math.round(e)===e}function F(e,n){if(!B(e))throw new SyntaxError("Bad ref: "+e);if(null!=n&&("number"!=typeof n||n<1||n!==n|0))throw new RangeError("Bad depth: "+n);if("string"==typeof e)return new RegExp("\\k<"+e+">");var r=new RegExp("$d:"+(n||"0")+",n:"+e+"^");return ye.set(r,{direction:Re.current,hasFinalRef:!0,hasRefs:!0}),r}function M(){return y(),E(w(m(arguments,!1,!1,1),{open:"("}))}function C(e){if("string"!=typeof e)throw new TypeError("String expected, got "+typeof e);return _(e),y(),E(w(m(X.call(arguments,1),!1,!1,1),{open:"(?<"+e+">"}))}function D(e){return 1===arguments.length?C.bind(null,e):C.apply(null,arguments)}function U(e,n){return e=e.split(""),n.split("").forEach(function(n){-1===e.indexOf(n)&&e.push(n)}),e.sort().join("")}function N(e){return y(),-1!==e.indexOf("u")&&(K.U=!0),E(_e.apply($,arguments),{flagsOp:this,flags:e})}function T(){return 1===Re.current?A(Ae(M.apply(null,arguments)),F(1)):A(F(1),Ie(M.apply(null,arguments)))}function W(e,n){return A(Oe(n),e)}function P(e,n){return A(Ae(n),e)}function z(e){return W(J&&e.unicode?Me:/[^]/,e)}function Z(e){return R("bound"),S([je(e),Ae(e)],[Ie(e),Oe(e)])}function q(e){return R("noBound"),S([je(e),Oe(e)],[Ie(e),Ae(e)])}var G=[];"dgimsuy".split("").forEach(function(e){try{new RegExp("",e),G.push(e)}catch(e){}});var J=-1!==G.indexOf("u"),H=!1;try{new RegExp("(?<=)"),H=!0}catch(e){}var K,L,Q={}.hasOwnProperty,V=[].map,X=[].slice,Y=RegExp,ee={value:void 0,writable:!1,enumerable:!1,configurable:!1},ne="undefined"!=typeof WeakMap?new WeakMap:{key:"__$$__compose_regexp__$$__"+t()+t()+t()+t(),set:function(e,n){var r=typeof e;if(null==e||"object"!==r&&"function"!==r)throw new TypeError("Bad WeakMap key");var t=e[ne.key];if(!t)return ee.value={keys:[this],values:[n]},Object.defineProperty(e,ne.key,ee),this;var u=t.keys.indexOf(this);return 0===u?(t.keys.push(this),t.values.push(n),this):(t.values[u]=n,this)},get:function(e){var n=e[ne.key];if(n){var r=n.keys.indexOf(this);if(-1!==r)return n.values[r]}}},re=/\\[^]|\(\?(?::|<?[=!])|[\[\](]/g,te=/\\.|\.|\(\?:\^\|\(\?<=\[\\n\\r\\u2028\\u2029\]\)\)|\(\?:\$\|\(\?=\[\\n\\r\\u2028\\u2029\]\)\)|\[|\]|\^|\$/g,ue=J&&new RegExp("^[_$\\p{ID_Start}][$\\p{ID_Continue}]*$","u"),ie=/\\.|\{\d+,?\d*\}|(\[|\]|\{|\})/g,oe=/(?:$|(?=[\n\r\u2028\u2029]))/,fe=/(?:^|(?<=[\n\r\u2028\u2029]))/,ce=/\\[^1-9]|[\[\]]|\\(\d{1,2})|\$d:(\d+),n:(\d+)\^/g,le=/^(?:\\.|\[(?:[^\]\\]|\\.)*\])$/,ae=/^\\p\{[A-Za-z][A-Za-z=]*\}$/,se=/[.?*+^$[\]\\(){}|]/g,pe=/^(?:[+*?]|\{(?=((\d+)))\1,?(\d*)\})\??$/,de=/(\\.)|[-()|\[\]]((?=\?<?[=!]))?/g,ge=/\\u[0-9A-Fa-f]{4}|\\x[0-9A-Fa-f]{2}|\\c[A-Za-z]|\\([^.?*+^$[\]\\(){}|\/DSWdswfnrtv-])|(\\[DSWdsw]-[^\]]|.-\\[DSWdsw])|\\.|\]/g,he=/\\u[0-9A-Fa-f]{4}|\\x[0-9A-Fa-f]{2}|\\c[A-Za-z]|\\k<(.*?)>|\\([^.?*+^$[\]\\(){}|\/DSWdswBbfnrtv])|\\.|\.|\[\^\]|\[|(\((?:\?[^])?)|(\)(?:[+?*]|\{\d+,?\d*\})?)/g,ye={set:function(e,n,r){var t=i(e);return"object"==typeof n?Object.assign(t,n):t[n]=r},get:function(e,n){return i(e)[n]}},xe=[],we=o("captureCount",function(e){var n,r=0;for(re.lastIndex=0;n=re.exec(e.source);)"("===n[0]&&(r+=1);return r}),ke=o("hasRefs",function(e){var n,r=!1,t=!1,u=!1;for(ce.lastIndex=0;n=ce.exec(e.source);)u||null==n[1]&&null==n[2]?"["===n[0]?u=!0:"]"===n[0]&&(u=!1):(r=!0,ce.lastIndex===e.source.length&&(t=!0));return ye.set(e.key,"hasFinalRef",t),r}),ve=o("isDisjunction",function(e){if(-1===e.source.indexOf("|"))return!1;var n,r=0,t=!1;for(de.lastIndex=0;n=de.exec(e.source);)if(null==n[1]&&(t||"("!==n[0]||r++,t||")"!==n[0]||r--,t||"["!==n[0]&&"[-"!==n[0]||(t=!0),t&&"]"===n[0]&&(t=!1),0===r&&!t&&"|"===n[0]))return!0;return!1}),me=o("isOneGroupOrAssertion",function(e){var n=e.source;if("("!==n.charAt(0)||")"!==n.charAt(n.length-1))return!1;var r,t=0,u=!1;for(de.lastIndex=0;r=de.exec(n);)if(null==r[1]){if(u||"("!==r[0]||t++,!u&&")"===r[0]&&0===--t&&r.index!==n.length-1)return!1;u||"["!==r[0]&&"[-"!==r||(u=!0),u&&"]"===r[0]&&(u=!1)}else if(r.index===n.length-2)return!1;return!0}),be=new RegExp("^(?:(["+G.join("")+"])(?!.*\\1))*$"),Ee={"-1":"backward",1:"forward"},Re={current:1},Se=/(?:)/,$e=/[]/,Ae=O("(?=",1,Se),Oe=O("(?!",1,$e),Ie=O("(?<=",-1,Se,R,"lookBehind"),je=O("(?<!",-1,$e,R,"notBehind"),_e=I.call,Be=j("?"),Fe={add:function(e){if("string"!=typeof e)throw TypeError("String expected as first argument, got "+typeof e);if(!be.test(e))throw new SyntaxError("Invalid flags: "+e);return 1===arguments.length?N.bind(U,e):N.apply(U,arguments)}},Me=J&&new RegExp("[^]","u"),Ce={difference:W,intersection:P,complement:z,union:S};e.atomic=T,e.bound=Z,e.capture=M,e.charSet=Ce,e.either=S,e.flags=Fe,e.lookAhead=Ae,e.lookBehind=Ie,e.maybe=Be,e.namedCapture=D,e.noBound=q,e.notAhead=Oe,e.notBehind=je,e.ref=F,e.sequence=A,e.suffix=j,Object.defineProperty(e,"__esModule",{value:!0})}); | ||
!function(n,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define("compose-regexp",["exports"],e):e((n="undefined"!=typeof globalThis?globalThis:n||self).composeRegexp={})}(this,(function(n){"use strict";const e=[];"dgimsuy".split("").forEach((function(n){try{new RegExp("",n),e.push(n)}catch(n){}}));const t=-1!==e.indexOf("u"),r=(()=>{try{return new RegExp("(?<=)"),!0}catch(n){return!1}})(),u={}.hasOwnProperty;function o(n){return n}const i=[].map,c=RegExp;function s(n){return-1===n.indexOf("\\")?n:JSON.parse('"'+n.replace(/$|"|\\x([\dA-Fa-f]{2})|\\u\{([\dA-Fa-f]{1,6})\}/g,(function(n,e,t){return""===n?'"':'"'===n?'\\"':String.fromCodePoint(parseInt(e||t,16))})))}const f={value:void 0,writable:!1,enumerable:!1,configurable:!1};function l(){return"_"+Math.floor(Math.random()*Math.pow(2,32)).toString(36)}const a="undefined"!=typeof WeakMap?new WeakMap:{key:"__$$__compose_regexp__$$__"+l()+l()+l()+l(),set:function(n,e){const t=typeof n;if(null==n||"object"!==t&&"function"!==t)throw new TypeError("Bad WeakMap key");const r=n[a.key];if(!r)return f.value={keys:[this],values:[e]},Object.defineProperty(n,a.key,f),this;const u=r.keys.indexOf(this);return 0===u?(r.keys.push(this),r.values.push(e),this):(r.values[u]=e,this)},get:function(n){const e=n[a.key];if(e){const n=e.keys.indexOf(this);if(-1!==n)return e.values[n]}}},d=/\\[^]|\(\?(?::|<?[=!])|[\[\](]/g,p=/\\.|\.|\(\?:\^\|\(\?<=\[\\n\\r\\u2028\\u2029\]\)\)|\(\?:\$\|\(\?=\[\\n\\r\\u2028\\u2029\]\)\)|\[|\]|\^|\$/g,g=t&&new RegExp("^[_$\\p{ID_Start}][$\\p{ID_Continue}]*$","u"),h=/\\.|\{\d+,?\d*\}|(\[|\]|\{|\})/g,y=/(?:$|(?=[\n\r\u2028\u2029]))/,x=/(?:^|(?<=[\n\r\u2028\u2029]))/,w=/\\[^1-9]|[\[\]]|\\(\d{1,2})|\$d:(\d+),n:(\d+)\^/g,k=/^(?:\\.|\[(?:[^\]\\]|\\.)*\])$/,m=/^\\p\{[A-Za-z][A-Za-z=]*\}$/,$=/[.?*+^$[\]\\(){}|]/g,E=/^(?:[+*?]|\{(?=((\d+)))\1,?(\d*)\})\??$/,R=/(\\.)|[-()|\[\]]((?=\?<?[=!]))?/g,b=/\\u[0-9A-Fa-f]{4}|\\x[0-9A-Fa-f]{2}|\\c[A-Za-z]|\\([^.?*+^$[\]\\(){}|\/DSWdswfnrtv-])|(\\[DSWdsw]-[^\]]|.-\\[DSWdsw])|\\.|\]/g,S=/\\u[0-9A-Fa-f]{4}|\\x[0-9A-Fa-f]{2}|\\c[A-Za-z]|\\k<(.*?)>|\\([^.?*+^$[\]\\(){}|\/DSWdswBbfnrtv])|\\.|\.|\[\^\]|\[|(\((?:\?[^])?)|(\)(?:[+?*]|\{\d+,?\d*\})?)/g;function A(n){if(n instanceof c){let e=a.get(n);return null==e&&a.set(n,e={captureCount:null,direction:0,hasRefs:null,hasFinalRef:null,isDisjunction:null,isOneGroupOrAssertion:null,source:null,unicode:null}),e}return n||{captureCount:null,direction:0,hasRefs:null,hasFinalRef:null,isDisjunction:null,isOneGroupOrAssertion:null,source:null,unicode:null}}const O=function(n,e,t){const r=A(n);return"object"==typeof e?Object.assign(r,e):r[e]=t},I=function(n,e){return A(n)[e]};function j(n,e){return Object.defineProperty((function(t){const r=I(t.key,n);return null!=r?r:O(t.key,n,e(t))}),"name",{value:n})}const F=[];const v=j("captureCount",(function(n){let e,t=0;for(d.lastIndex=0;e=d.exec(n.source);)"("===e[0]&&(t+=1);return t})),B=j("hasRefs",(function(n){let e,t=!1,r=!1,u=!1;for(w.lastIndex=0;e=w.exec(n.source);)u||null==e[1]&&null==e[2]?"["===e[0]?u=!0:"]"===e[0]&&(u=!1):(t=!0,w.lastIndex===n.source.length&&(r=!0));return O(n.key,"hasFinalRef",r),t})),C=j("isDisjunction",(function(n){if(-1===n.source.indexOf("|"))return!1;let e,t=0,r=!1;for(R.lastIndex=0;e=R.exec(n.source);)if(null==e[1]&&(r||"("!==e[0]||t++,r||")"!==e[0]||t--,r||"["!==e[0]&&"[-"!==e[0]||(r=!0),r&&"]"===e[0]&&(r=!1),0===t&&!r&&"|"===e[0]))return!0;return!1})),_=j("isOneGroupOrAssertion",(function(n){const e=n.source;if("("!==e.charAt(0)||")"!==e.charAt(e.length-1))return!1;let t,r=0,u=!1;for(R.lastIndex=0;t=R.exec(e);)if(null==t[1]){if(u||"("!==t[0]||r++,!u&&")"===t[0]&&(r--,0===r&&t.index!==e.length-1))return!1;u||"["!==t[0]&&"[-"!==t||(u=!0),u&&"]"===t[0]&&(u=!1)}else if(t.index===e.length-2)return!1;return!0}));function M(n){const e=n.source;if(null==e||"^"===e||"$"===e||"\\b"===e||"\\B"===e)throw new SyntaxError(`Nothing to repeat: / ${e||"(?:)"}/`);if(1===e.length||k.test(e)||W.U&&m.test(e))return!1;if(!_(n))return!0;if(/^\(\?<?[!=]/.test(e))throw new SyntaxError(`Nothing to repeat: /${e}/`);return!1}function D(n){const e=n.source;if(W.U&&("regexp"===n.kind&&!n.key.unicode||"result"===n.kind&&!I(n.key,"unicode"))){if(function(n){let e,t=S;function r(n){n.lastIndex=t.lastIndex,t=n}for(F.length=0,S.lastIndex=0;e=t.exec(n);)if(t===S)if("["===e[0])r(b);else{if("."===e[0]||"[^]"===e[0]||null!=e[1]&&!g.test(s(e[1]))||null!=e[2])return!0;if(null!=e[3])F.unshift(e[3]);else if(null!=e[4]){if(("(?="===F[0]||"(?!"===F[0])&&")"!==e[4])return!0;F.shift()}}else if("]"===e[0])r(S);else if(null!=e[1]||null!=e[2])return!0;return!1}(e))throw new SyntaxError(`Can't upgrade the RegExp to Unicode /${e}/${"regexp"===n.kind?n.key.flags:""}`);n.source=function(n){let e=!1;return n.replace(h,(function(n,t){if("]"===n){if(!e)return"\\]";e=!1}else if(!e&&null!=t){if("["!==t)return"\\"+t;e=!0}return n}))}(e)}let t=!1;return"regexp"===n.kind&&(n.key.dotAll||n.key.multiline)&&(n.source=e.replace(p,(function(e){return t?("]"===e&&(t=!1),e):("["===e&&(t=!0),n.key.dotAll&&"."===e?"[^]":n.key.multiline&&"^"===e&&r?x.source:n.key.multiline&&"$"===e&&r?y.source:e)}))),n}const U=new RegExp(`^(?:([${e.join("")}])(?!.*\\1))*$`),N=new RegExp(`[${e.join()}]`,"g");const T={"-1":"backward",1:"forward"};let W,z,P={current:1};function Z(){z={hasRefs:!1,hasFinalRef:!1,captureCount:0},W={U:!1,I:null,M:null}}function G(n,e){return e.condition&&!e.condition(n)||(n.source=e.open+(n.source||"")+")"),e.suffix&&(n.source+=e.suffix),n}function q(n){return G(n,{condition:function(n){return("regexp"===n.kind||"result"===n.kind)&&C(n)},open:"(?:"})}function J(n,e,t,u){return t=t||n.length>1,i.call(n,(function n(u){return(!e&&t?q:o)(Array.isArray(u)?J(u,!1,t,0):"function"==typeof u?n(function(n){const e=z,t=W;try{return n()}finally{z=e,W=t}}(u)):u instanceof c?function(n){const e=I(n.key,"direction");if(e*P.current==-1)throw new TypeError(`Illegal ${T[e]} RegExp argument while building a ${T[P.current]} one: /${n.source}/`);return 0!==e&&(z.hasRefs=!0),n}(function(n){const e=n.key.flags;if(!U.test(e))throw new TypeError(`Unkown flag(s): ${e.replace(N,"")}`);const t=!!n.key.unicode,u=n.key.ignoreCase,o=n.key.multiline;if(null!=W.I&&u!==W.I)throw new SyntaxError("Can't combine i and non-i regexps: "+n.key);if(!r&&null!=W.M&&o!==W.M)throw new SyntaxError("Can't combine m and non-m regexps: "+n.key);return W.I=u,W.M=o,W.U=W.U||t,n}({key:u,kind:"regexp",source:(i=u,I(i,"source")||O(i,"source",i.source))})):function(n){if("number"==typeof n||"string"==typeof n)return{key:null,kind:"string",source:String(n).replace($,"\\$&")};throw new TypeError(`Can't compose type ${typeof n} as RegExp`)}(u));var i})).map(D).map(function(n){let e=n;return function(t){if("regexp"===t.kind||"result"===t.kind){if(B(t)){z.hasRefs=!0;let r=!1;t.source=t.source.replace(w,(function(t,u,o,i){if(!r){if(null!=u){const n=Number(u)+e;if(n>99)throw new RangeError("Back reference index larger than 99");return"\\"+String(n)}if(null!=o){if("0"===o){const e=Number(i)+n;if(e>99)throw new RangeError("Back reference index larger than 99");return"\\"+String(e)}return`$d:${Number(o)-1},n:${i}^`}}return"["===t?r=!0:"]"===t&&(r=!1),t}))}z.hasFinalRef=!!I(t.key,"hasFinalRef"),e+=v(t)}return z.captureCount=e,t}}(u)).reduceRight(e?function(n,e){return n.source=null==n.source?e.source:`${e.source}|${n.source}`,n}:function(n,e){return n.source=null==n.source?e.source:e.source+("string"!==e.kind&&B(e)&&I(e.key,"hasFinalRef")&&/^\d/.test(n.source)?"(?:)":"")+n.source,n},{key:O(null,Object.assign({direction:z.hasRefs?P.current:0,isDisjunction:e&&(n.length>1||1===n.length&&n[0]instanceof c&&I(n[0],"isDisjunction")),unicode:W.U},z)),kind:"result",source:null})}function H(){return(W.I?"i":"")+(r?"":W.M?"m":"")+(W.U?"u":"")}function K(n,e){e=e||{};const t=u.call(e,"flags")?e.flagsOp(H(),e.flags):H(),r=e.either,o=new RegExp(r?n.source||"[]":n.source||"",t);return O(o,O(n.key,{})),O(o,"source",n.source),u.call(e,"direction")&&O(o,"direction",e.direction),o}const L=/(?:)/,Q=/[]/;function V(n){if(!r)throw new Error("no support for /(?<=...)/ which is required by "+n+"()")}function X(...n){return 0===n.length?Q:(Z(),K(J(n,!0,!1,0),{either:!0}))}function Y(...n){return J(n,!1,!1,0)}function nn(...n){return 0===n.length?L:(Z(),K(Y(...n)))}function en(n,e,t,r,u){return function(...o){if(null!=r&&r(u),!o.length)return t;const i=P.current;P.current=e;try{Z();return K(G(Y(...o),{open:n}),{direction:0})}finally{P.current=i}}}const tn=en("(?=",1,L),rn=en("(?!",1,Q),un=en("(?<=",-1,L,V,"lookBehind"),on=en("(?<!",-1,Q,V,"notBehind");function cn(n,...e){if(Z(),0===e.length)throw new SyntaxError("Suffix to an empty prefix");return K(G(Y(...e),{condition:M,open:"(?:",suffix:n}))}function sn(n,...e){"string"!=typeof n&&(n="{"+String(n)+"}");const t=n.match(E);if(!t||t[3]&&Number(t[3])<Number(t[2]))throw new SyntaxError("Invalid suffix '"+n+"'.");return 0===e.length?cn.bind(null,n):cn(n,...e)}cn.call;const fn=sn("?");function ln(n){return!t||g.test(s(n))}function an(n,e){if(!function(n){const e=typeof n;return"string"===e&&ln(n)||"number"===e&&0<n&&Math.round(n)===n}(n))throw new SyntaxError("Bad ref: "+n);if(null!=e&&("number"!=typeof e||e<1||e!=e|0))throw new RangeError("Bad depth: "+e);if("string"==typeof n)return new RegExp("\\k<"+n+">");const t=new RegExp("$d:"+(e||"0")+",n:"+n+"^");return O(t,{direction:P.current,hasFinalRef:!0,hasRefs:!0}),t}function dn(...n){Z();return K(G(J(n,!1,!1,1),{open:"("}))}function pn(n,...e){if("string"!=typeof n)throw new TypeError("String expected, got "+typeof n);ln(n),Z();return K(G(J(e,!1,!1,1),{open:"(?<"+n+">"}))}function gn(n,e){return n=n.split(""),e.split("").forEach((function(e){-1===n.indexOf(e)&&n.push(e)})),n.sort().join("")}function hn(n,...e){Z(),-1!==n.indexOf("u")&&(W.U=!0);return K(Y(...e),{flagsOp:gn,flags:n})}const yn={add:function(n,...e){if("string"!=typeof n)throw TypeError("String expected as first argument, got "+typeof n);if(!U.test(n))throw new SyntaxError("Invalid flags: "+n);return 0===e.length?hn.bind(null,n):hn(n,...e)}};const xn=t&&new RegExp("[^]","u");function wn(n,e){return nn(rn(e),n)}const kn={difference:wn,intersection:function(n,e){return nn(tn(e),n)},complement:function(n){return wn(t&&n.unicode?xn:/[^]/,n)},union:X};n.atomic=function(...n){return 1===P.current?nn(tn(dn(...n)),an(1)):nn(an(1),un(dn(...n)))},n.bound=function(n){return V("bound"),X([on(n),tn(n)],[un(n),rn(n)])},n.capture=dn,n.charSet=kn,n.either=X,n.flags=yn,n.lookAhead=tn,n.lookBehind=un,n.maybe=fn,n.namedCapture=function(n,...e){return 0===e.length?pn.bind(null,n):pn(n,...e)},n.noBound=function(n){return V("noBound"),X([on(n),rn(n)],[un(n),tn(n)])},n.notAhead=rn,n.notBehind=on,n.ref=an,n.sequence=nn,n.suffix=sn})); |
{ | ||
"name": "compose-regexp", | ||
"version": "0.6.27", | ||
"version": "0.6.28", | ||
"description": "A set of functions to build and compose complex regular expressions", | ||
@@ -22,5 +22,5 @@ "type": "module", | ||
"cover": "gosub build-regexp && c8 ./node_modules/.bin/ospec", | ||
"compress": "gosub compress-uglify && gosub compress-brotli", | ||
"compress": "gosub compress-terser && gosub compress-brotli", | ||
"compress-brotli": "brotli -f -o dist/compose-regexp.min.js.br dist/compose-regexp.min.js", | ||
"compress-uglify": "uglifyjs commonjs/compose-regexp.js -cm --preamble '/**@license MIT-compose-regexp.js-©Pierre-Yves Gérardy*/' > dist/compose-regexp.min.js", | ||
"compress-terser": "terser commonjs/compose-regexp.js -cm --preamble '/**@license MIT-compose-regexp.js-©Pierre-Yves Gérardy*/' > dist/compose-regexp.min.js", | ||
"prepublishOnly": "node --no-warnings scripts/prepublish.js", | ||
@@ -53,5 +53,5 @@ "postpublish": "node ./scripts/postpublish.js", | ||
"ospec": "^4.1.4", | ||
"rollup": "^2.70.1", | ||
"stable-version": "npm:compose-regexp@0.6.26", | ||
"uglify-js": "^2.6.1" | ||
"rollup": "^3.11.0", | ||
"stable-version": "npm:compose-regexp@0.6.27", | ||
"terser": "^5.16.1" | ||
}, | ||
@@ -73,2 +73,2 @@ "c8": { | ||
} | ||
} | ||
} |
@@ -147,6 +147,7 @@ import {atomic, capture, either, flags, lookAhead, maybe, sequence, suffix} from 'stable-version' | ||
${ | ||
// kept for ES5 compat after compiling. | ||
Object.entries(output).sort().map(([name, rx]) => rx.unicode ? ` | ||
var ${name} = supportsU && new RegExp(${JSON.stringify(rx.source)}, 'u') | ||
const ${name} = supportsU && new RegExp(${JSON.stringify(rx.source)}, 'u') | ||
`:` | ||
var ${name} = ${rx} | ||
const ${name} = ${rx} | ||
` | ||
@@ -153,0 +154,0 @@ ).join('\n') |
100
src/API.js
@@ -19,4 +19,4 @@ import {slice, supportsLookBehind, supportsU, unescape} from './utils.js' | ||
var empty = /(?:)/ | ||
var never = /[]/ | ||
const empty = /(?:)/ | ||
const never = /[]/ | ||
@@ -27,27 +27,27 @@ function throwIfNoLookBehind(name) { | ||
export function either() { | ||
if (!arguments.length) return never | ||
export function either(...args) { | ||
if (args.length === 0) return never | ||
$$_resetRefCapsAndFlags() | ||
return finalize(assemble(arguments, true, false, 0), {either: true}) | ||
return finalize(assemble(args, true, false, 0), {either: true}) | ||
} | ||
function _sequence() { | ||
return assemble(arguments, false, false, 0) | ||
function _sequence(...args) { | ||
return assemble(args, false, false, 0) | ||
} | ||
export function sequence() { | ||
if (!arguments.length) return empty | ||
export function sequence(...args) { | ||
if (args.length === 0) return empty | ||
$$_resetRefCapsAndFlags() | ||
return finalize(_sequence.apply(null, arguments)) | ||
return finalize(_sequence(...args)) | ||
} | ||
function makeAssertion (before, direction, emptyFallback, gate, name) { | ||
return function () { | ||
return function (...args) { | ||
if (gate != null) gate(name) | ||
if (!arguments.length) return emptyFallback | ||
var previousDir = $direction.current | ||
if (!args.length) return emptyFallback | ||
const previousDir = $direction.current | ||
$direction.current = direction | ||
try { | ||
$$_resetRefCapsAndFlags() | ||
var result = _sequence.apply(null, arguments) | ||
const result = _sequence(...args) | ||
return finalize(decorate(result, {open: before}), {direction: 0}) | ||
@@ -60,10 +60,10 @@ } finally { | ||
export var lookAhead = makeAssertion('(?=', 1, empty) | ||
export var notAhead = makeAssertion('(?!', 1, never) | ||
export var lookBehind = makeAssertion('(?<=', -1, empty, throwIfNoLookBehind, "lookBehind") | ||
export var notBehind = makeAssertion('(?<!', -1, never, throwIfNoLookBehind, "notBehind") | ||
export const lookAhead = makeAssertion('(?=', 1, empty) | ||
export const notAhead = makeAssertion('(?!', 1, never) | ||
export const lookBehind = makeAssertion('(?<=', -1, empty, throwIfNoLookBehind, "lookBehind") | ||
export const notBehind = makeAssertion('(?<!', -1, never, throwIfNoLookBehind, "notBehind") | ||
var call = _suffix.call | ||
const call = _suffix.call | ||
function _suffix() { | ||
function _suffix(quantifier, ...args) { | ||
// the quantifier is passed as context | ||
@@ -73,17 +73,17 @@ $$_resetRefCapsAndFlags() | ||
// without allocating an array. The operator is passed as `this` which is ignored. | ||
if (arguments.length === 1) throw new SyntaxError("Suffix to an empty prefix") | ||
var res = call.apply(_sequence, arguments) | ||
return finalize(decorate(res, {condition: needsWrappingForQuantifier, open: '(?:', suffix: this})) | ||
if (args.length === 0) throw new SyntaxError("Suffix to an empty prefix") | ||
const res = _sequence(...args) | ||
return finalize(decorate(res, {condition: needsWrappingForQuantifier, open: '(?:', suffix: quantifier})) | ||
} | ||
export function suffix(quantifier) { | ||
export function suffix(quantifier, ...args) { | ||
if (typeof quantifier !== 'string') quantifier = '{' + String(quantifier) + '}' | ||
var match = quantifier.match(suffixMatcher) | ||
const match = quantifier.match(suffixMatcher) | ||
if (!match || match[3] && Number(match[3]) < Number(match[2])) throw new SyntaxError("Invalid suffix '" + quantifier+ "'.") | ||
return arguments.length === 1 | ||
? _suffix.bind(quantifier, quantifier) | ||
: _suffix.apply(quantifier, arguments) | ||
return args.length === 0 | ||
? _suffix.bind(null, quantifier) | ||
: _suffix(quantifier, ...args) | ||
} | ||
export var maybe = suffix('?') | ||
export const maybe = suffix('?') | ||
@@ -102,3 +102,3 @@ | ||
function checkRef(name) { | ||
var type = typeof name | ||
const type = typeof name | ||
return type === 'string' && validateGroupName(name) | ||
@@ -112,3 +112,3 @@ || type === 'number' && 0 < name && Math.round(name) === name | ||
if (typeof n === 'string') return new RegExp('\\k<' + n + '>') | ||
var result = new RegExp('$d:' + (depth || '0')+ ",n:" + n + "^") | ||
const result = new RegExp('$d:' + (depth || '0')+ ",n:" + n + "^") | ||
metadata.set(result, { | ||
@@ -122,20 +122,20 @@ direction: $direction.current, | ||
export function capture() { | ||
export function capture(...args) { | ||
$$_resetRefCapsAndFlags() | ||
var res = assemble(arguments, false, false, 1) | ||
const res = assemble(args, false, false, 1) | ||
return finalize(decorate(res, {open: '('})) | ||
} | ||
function _namedCapture(name) { | ||
function _namedCapture(name, ...args) { | ||
if (typeof name !== 'string') throw new TypeError("String expected, got " + typeof name) | ||
validateGroupName(name) | ||
$$_resetRefCapsAndFlags() | ||
var res = assemble(slice.call(arguments, 1), false, false, 1) | ||
const res = assemble(args, false, false, 1) | ||
return finalize(decorate(res, {open: '(?<' + name + '>'})) | ||
} | ||
export function namedCapture(name) { | ||
return (arguments.length === 1 | ||
export function namedCapture(name, ...args) { | ||
return (args.length === 0 | ||
? _namedCapture.bind(null, name) | ||
: _namedCapture.apply(null, arguments)) | ||
: _namedCapture(name, ...args)) | ||
} | ||
@@ -163,3 +163,3 @@ | ||
function _flags(fl) { | ||
function _flags(fl, ...args) { | ||
// the operation is passed as context | ||
@@ -171,12 +171,12 @@ $$_resetRefCapsAndFlags() | ||
// bad hack, see _suffix | ||
var source = call.apply(_sequence, arguments) | ||
return finalize(source, {flagsOp: this, flags: fl}) | ||
const source = _sequence(...args) | ||
return finalize(source, {flagsOp: flagAdd, flags: fl}) | ||
} | ||
export var flags = {add: function add(flags) { | ||
export const flags = {add: function add(flags, ...args) { | ||
if (typeof flags !== 'string') throw TypeError("String expected as first argument, got " + typeof flags) | ||
if (!flagsMatcher.test(flags)) throw new SyntaxError("Invalid flags: " + flags) | ||
return arguments.length === 1 | ||
? _flags.bind(flagAdd, flags) | ||
: _flags.apply(flagAdd, arguments) | ||
return args.length === 0 | ||
? _flags.bind(null, flags) | ||
: _flags(flags, ...args) | ||
}} | ||
@@ -187,11 +187,11 @@ | ||
export function atomic() { | ||
export function atomic(...args) { | ||
return $direction.current === 1 | ||
// forward: | ||
? sequence(lookAhead(capture.apply(null, arguments)), ref(1)) | ||
? sequence(lookAhead(capture(...args)), ref(1)) | ||
// backward: | ||
: sequence(ref(1), lookBehind(capture.apply(null, arguments))) | ||
: sequence(ref(1), lookBehind(capture(...args))) | ||
} | ||
var allU = supportsU && new RegExp('[^]', 'u') | ||
const allU = supportsU && new RegExp('[^]', 'u') | ||
function csDiff(a, b) {return sequence(notAhead(b), a)} | ||
@@ -201,3 +201,3 @@ function csInter(a, b) {return sequence(lookAhead(b), a)} | ||
export var charSet = { | ||
export const charSet = { | ||
difference: csDiff, | ||
@@ -204,0 +204,0 @@ intersection: csInter, |
158
src/core.js
import {allFlags, supportsLookBehind, hasOwn, identity, map, RegExpRef, store, unescape} from './utils.js' | ||
import {captureMatcher, dotMDotSMatcher, groupNameMatcher, loneBracketMatcher, mEndAnchor, mStartAnchor, numRefMatcher, oneEscapeOrCharClassMatcher, pEscapeMatcher, stringNormalizerMatcher, tokenMatcher, uProblemCharClassMatcher, uProblemDefaultMatcher} from './regexps.js' | ||
import { | ||
captureMatcher, dotMDotSMatcher, groupNameMatcher, loneBracketMatcher, mEndAnchor, | ||
mStartAnchor, numRefMatcher, oneEscapeOrCharClassMatcher, pEscapeMatcher, | ||
stringNormalizerMatcher, tokenMatcher, uProblemCharClassMatcher, uProblemDefaultMatcher | ||
} from './regexps.js' | ||
// General notes: | ||
// | ||
// | ||
// 1. Most functions here take an `x` parameter, which is our internal representation | ||
@@ -50,3 +54,3 @@ // of regexps, strings, etc... it has the following structure | ||
if (target instanceof RegExpRef) { | ||
var md = store.get(target) | ||
let md = store.get(target) | ||
if (md == null) store.set(target, md = MetaData()) | ||
@@ -59,6 +63,6 @@ return md | ||
export var metadata = { | ||
export const metadata = { | ||
set: function(target, property, value) { | ||
var md = findOrCreateMd(target) | ||
return (typeof property === 'object') | ||
const md = findOrCreateMd(target) | ||
return (typeof property === 'object') | ||
? Object.assign(md, property) | ||
@@ -68,3 +72,3 @@ : md[property] = value | ||
get: function(target, property) { | ||
var md = findOrCreateMd(target) | ||
const md = findOrCreateMd(target) | ||
return md[property] | ||
@@ -76,3 +80,3 @@ } | ||
return Object.defineProperty(function(x) { | ||
var cached = metadata.get(x.key, property) | ||
const cached = metadata.get(x.key, property) | ||
if (cached != null) return cached | ||
@@ -106,5 +110,6 @@ return metadata.set(x.key, property, f(x)) | ||
// a lookahead assertion | ||
var openGroups = [] | ||
const openGroups = [] | ||
function hasUProblem(x) { | ||
var matcher = uProblemDefaultMatcher, result | ||
let matcher = uProblemDefaultMatcher | ||
let result | ||
openGroups.length = 0 | ||
@@ -153,4 +158,4 @@ function use(x) { | ||
var countCaptures = mdMemo('captureCount', function countCaptures(x) { | ||
var count = 0, inCClass = false, result | ||
const countCaptures = mdMemo('captureCount', function countCaptures(x) { | ||
let count = 0, inCClass = false, result | ||
captureMatcher.lastIndex = 0 | ||
@@ -168,4 +173,4 @@ while(result = captureMatcher.exec(x.source)) { | ||
var hasRefs = mdMemo('hasRefs', function hasRefs(x) { | ||
var hasRefs = false, hasFinalRef = false, inCClass = false, result | ||
const hasRefs = mdMemo('hasRefs', function hasRefs(x) { | ||
let hasRefs = false, hasFinalRef = false, inCClass = false, result | ||
numRefMatcher.lastIndex = 0 | ||
@@ -190,5 +195,5 @@ while(result = numRefMatcher.exec(x.source)) { | ||
export var isDisjunction = mdMemo('isDisjunction', function isDisjunction(x) { | ||
export const isDisjunction = mdMemo('isDisjunction', function isDisjunction(x) { | ||
if (x.source.indexOf('|') === -1) return false | ||
var depth = 0, inCClass = false, result | ||
let depth = 0, inCClass = false, result | ||
tokenMatcher.lastIndex = 0 | ||
@@ -208,6 +213,6 @@ while(result = tokenMatcher.exec(x.source)) { | ||
// Helper function for needsWrappingForQuantifier | ||
export var isOneGroupOrAssertion = mdMemo('isOneGroupOrAssertion', function isOneGroupOrAssertion(x) { | ||
var source = x.source | ||
export const isOneGroupOrAssertion = mdMemo('isOneGroupOrAssertion', function isOneGroupOrAssertion(x) { | ||
const source = x.source | ||
if (source.charAt(0) !== '(' || source.charAt(source.length - 1) !== ')') return false | ||
var depth = 0, inCClass = false, result | ||
let depth = 0, inCClass = false, result | ||
tokenMatcher.lastIndex = 0 | ||
@@ -237,14 +242,17 @@ while(result = tokenMatcher.exec(source)) { | ||
export function needsWrappingForQuantifier(x) { | ||
var source = x.source | ||
if (source == null || source === '^' || source === '$' || source === '\\b' || source === '\\B') throw new SyntaxError("Nothing to repeat: /"+(source || '(?:)')+"/") | ||
const source = x.source | ||
if (source == null || source === '^' || source === '$' || source === '\\b' || source === '\\B') { | ||
throw new SyntaxError(`Nothing to repeat: / ${source || '(?:)' }/`) | ||
} | ||
// No need to look for standalone \k escapes, the are illegal in U and N mode, an non-atomic otherwise. | ||
if ( | ||
source.length === 1 | ||
|| oneEscapeOrCharClassMatcher.test(source) | ||
source.length === 1 | ||
|| oneEscapeOrCharClassMatcher.test(source) | ||
|| $flagValidator.U && pEscapeMatcher.test(source) | ||
) return false | ||
var og = isOneGroupOrAssertion(x) | ||
const og = isOneGroupOrAssertion(x) | ||
if (!og) return true | ||
if (/^\(\?<?[!=]/.test(source)) throw new SyntaxError("Nothing to repeat: /"+source+"/") | ||
// Reject look-arounds | ||
if (/^\(\?<?[!=]/.test(source)) throw new SyntaxError(`Nothing to repeat: /${ source }/`) | ||
return false | ||
@@ -271,3 +279,3 @@ } | ||
function promoteNonUnicodeToUnicode (source) { | ||
var inCClass = false | ||
let inCClass = false | ||
return source.replace(loneBracketMatcher, function(match, bracket) { | ||
@@ -289,3 +297,3 @@ if (match === ']') { | ||
function $$_fixRefs(initialOffset) { | ||
var count = initialOffset | ||
let count = initialOffset | ||
return function (x) { | ||
@@ -295,7 +303,7 @@ if (x.kind === 'regexp' || x.kind === 'result') { | ||
$refAndCap.hasRefs = true | ||
var inCClass = false | ||
let inCClass = false | ||
x.source = x.source.replace(numRefMatcher, function(match, refIndex, depth, thunkIndex) { | ||
if (!inCClass) { | ||
if (refIndex != null) { | ||
var fixedRefIndex = (Number(refIndex) + count) | ||
const fixedRefIndex = (Number(refIndex) + count) | ||
if (fixedRefIndex > 99) throw new RangeError("Back reference index larger than 99") | ||
@@ -306,7 +314,7 @@ | ||
if (depth === '0') { | ||
var fixedRefIndex = Number(thunkIndex) + initialOffset | ||
const fixedRefIndex = Number(thunkIndex) + initialOffset | ||
if (fixedRefIndex > 99) throw new RangeError("Back reference index larger than 99") | ||
return '\\' + String(fixedRefIndex) | ||
} | ||
else return '$d:' + (Number(depth) -1) + ',n:' + thunkIndex + '^' | ||
else return `$d:${ Number(depth) - 1 },n:${ thunkIndex }^` | ||
} | ||
@@ -330,12 +338,14 @@ } | ||
function fixForFlags(x) { | ||
var source = x.source | ||
if($flagValidator.U && (x.kind === 'regexp' && !x.key.unicode || x.kind === 'result' && !metadata.get(x.key, 'unicode'))) { | ||
if(hasUProblem(source)) throw new SyntaxError("Can't upgrade the RegExp to Unicode /"+ source + "/" + (x.kind === 'regexp' ? x.key.flags : '')) | ||
x.source = promoteNonUnicodeToUnicode(source) | ||
const source = x.source | ||
if ($flagValidator.U && (x.kind === 'regexp' && !x.key.unicode || x.kind === 'result' && !metadata.get(x.key, 'unicode'))) { | ||
if(hasUProblem(source)) { | ||
throw new SyntaxError(`Can't upgrade the RegExp to Unicode /${ source }/${ x.kind === 'regexp' ? x.key.flags : '' }`) | ||
} | ||
x.source = promoteNonUnicodeToUnicode(source) | ||
} | ||
var inCClass = false | ||
let inCClass = false | ||
if (x.kind === 'regexp' && (x.key.dotAll || x.key.multiline)) x.source = source.replace(dotMDotSMatcher, function(match) { | ||
if (!inCClass) { | ||
if (match === '[') inCClass = true | ||
return (x.key.dotAll && match === '.') ? '[^]' | ||
return (x.key.dotAll && match === '.') ? '[^]' | ||
: (x.key.multiline && match === '^'&& supportsLookBehind) ? mStartAnchor.source | ||
@@ -348,3 +358,3 @@ : (x.key.multiline && match === '$' && supportsLookBehind) ? mEndAnchor.source | ||
} | ||
}) | ||
@@ -355,15 +365,22 @@ return x | ||
// ensures that each flag appears only once | ||
export var flagsMatcher = new RegExp('^(?:([' + allFlags.join('') + '])(?!.*\\1))*$') | ||
export const flagsMatcher = new RegExp(`^(?:([${ allFlags.join('') }])(?!.*\\1))*$`) | ||
const flagFinder = new RegExp(`[${ allFlags.join() }]`, 'g') | ||
function $$_checkFlags(x) { | ||
var flags = x.key.flags | ||
const flags = x.key.flags | ||
if (!flagsMatcher.test(flags)) throw new TypeError("Unkown flags: " + flags.replace(new RegExp('['+allFlags.join()+']', 'g'), '')) | ||
if (!flagsMatcher.test(flags)) { | ||
throw new TypeError(`Unkown flag(s): ${ flags.replace(flagFinder, '')}`) | ||
} | ||
var hasU = !!x.key.unicode | ||
var hasI = x.key.ignoreCase | ||
var hasM = x.key.multiline | ||
const hasU = !!x.key.unicode | ||
const hasI = x.key.ignoreCase | ||
const hasM = x.key.multiline | ||
if ($flagValidator.I != null && hasI !== $flagValidator.I) throw new SyntaxError("Can't combine i and non-i regexps: " + x.key) | ||
if (!supportsLookBehind && $flagValidator.M != null && hasM !== $flagValidator.M) throw new SyntaxError("Can't combine m and non-m regexps: " + x.key) | ||
if ($flagValidator.I != null && hasI !== $flagValidator.I) { | ||
throw new SyntaxError("Can't combine i and non-i regexps: " + x.key) | ||
} | ||
if (!supportsLookBehind && $flagValidator.M != null && hasM !== $flagValidator.M) { | ||
throw new SyntaxError("Can't combine m and non-m regexps: " + x.key) | ||
} | ||
@@ -378,7 +395,13 @@ $flagValidator.I = hasI | ||
//+ | ||
var directionNames = {'-1': 'backward', '1': 'forward'} | ||
const directionNames = {'-1': 'backward', '1': 'forward'} | ||
function $$_checkDirection(x) { | ||
var d = metadata.get(x.key, 'direction') | ||
const d = metadata.get(x.key, 'direction') | ||
if (d * $direction.current === -1) throw new TypeError( | ||
"Illegal " + directionNames[d] + " RegExp argument while building a " + directionNames[$direction.current] + " one: /" + x.source + "/" | ||
`Illegal ${ | ||
directionNames[d] | ||
} RegExp argument while building a ${ | ||
directionNames[$direction.current] | ||
} one: /${ | ||
x.source | ||
}/` | ||
) | ||
@@ -396,14 +419,14 @@ if (d !== 0) $refAndCap.hasRefs = true | ||
? function(x2, x1){ | ||
x2.source = x2.source == null ? x1.source : x1.source + '|' + x2.source | ||
x2.source = x2.source == null ? x1.source : `${ x1.source }|${ x2.source }` | ||
return x2 | ||
} | ||
: function(x2, x1){ | ||
x2.source = x2.source == null | ||
? x1.source | ||
x2.source = x2.source == null | ||
? x1.source | ||
: x1.source + ( | ||
// corner case where a numeric ref is followed by a number | ||
x1.kind !== 'string' | ||
x1.kind !== 'string' | ||
// sets the 'hasFinalRef' metadata as a side effect | ||
&& hasRefs(x1) | ||
&& metadata.get(x1.key, 'hasFinalRef') | ||
&& metadata.get(x1.key, 'hasFinalRef') | ||
&& (/^\d/.test(x2.source)) | ||
@@ -413,3 +436,3 @@ ? '(?:)' | ||
) + x2.source | ||
return x2 | ||
@@ -440,8 +463,8 @@ } | ||
// goes the other way. | ||
export var $direction = { | ||
export let $direction = { | ||
current: 1, | ||
} | ||
export var $flagValidator | ||
var $refAndCap | ||
export let $flagValidator | ||
let $refAndCap | ||
@@ -460,4 +483,4 @@ export function $$_resetRefCapsAndFlags() { | ||
function $$_reentrantRefCapFlag(f) { | ||
var previousRnC = $refAndCap | ||
var previousFV = $flagValidator | ||
const previousRnC = $refAndCap | ||
const previousFV = $flagValidator | ||
try {return f()} finally { | ||
@@ -490,3 +513,3 @@ $refAndCap = previousRnC | ||
} | ||
throw new TypeError("Can't compose type " + typeof x + " as RegExp") | ||
throw new TypeError(`Can't compose type ${ typeof x } as RegExp`) | ||
} | ||
@@ -520,6 +543,9 @@ | ||
direction: $refAndCap.hasRefs ? $direction.current : 0, | ||
isDisjunction: either && (patterns.length > 1 || patterns.length === 1 && (patterns[0] instanceof RegExpRef) && metadata.get(patterns[0], 'isDisjunction')), | ||
isDisjunction: either && ( | ||
patterns.length > 1 | ||
|| patterns.length === 1 && (patterns[0] instanceof RegExpRef) && metadata.get(patterns[0], 'isDisjunction') | ||
), | ||
unicode: $flagValidator.U | ||
}, $refAndCap)), | ||
kind: 'result', | ||
kind: 'result', | ||
source: null | ||
@@ -535,5 +561,5 @@ }) | ||
options = options || {} | ||
var flags = hasOwn.call(options, 'flags') ? options.flagsOp(getFlags(), options.flags) : getFlags() | ||
var either = options.either | ||
var result = new RegExp((either ? x.source || '[]': x.source || ''), flags) | ||
const flags = hasOwn.call(options, 'flags') ? options.flagsOp(getFlags(), options.flags) : getFlags() | ||
const either = options.either | ||
const result = new RegExp((either ? x.source || '[]': x.source || ''), flags) | ||
metadata.set(result, metadata.set(x.key, {})) | ||
@@ -540,0 +566,0 @@ metadata.set(result, 'source', x.source) |
@@ -20,42 +20,42 @@ // /!\ DO NOT EDIT MANUALLY /!\ | ||
var captureMatcher = /\\[^]|\(\?(?::|<?[=!])|[\[\](]/g | ||
const captureMatcher = /\\[^]|\(\?(?::|<?[=!])|[\[\](]/g | ||
var dotMDotSMatcher = /\\.|\.|\(\?:\^\|\(\?<=\[\\n\\r\\u2028\\u2029\]\)\)|\(\?:\$\|\(\?=\[\\n\\r\\u2028\\u2029\]\)\)|\[|\]|\^|\$/g | ||
const dotMDotSMatcher = /\\.|\.|\(\?:\^\|\(\?<=\[\\n\\r\\u2028\\u2029\]\)\)|\(\?:\$\|\(\?=\[\\n\\r\\u2028\\u2029\]\)\)|\[|\]|\^|\$/g | ||
var groupNameMatcher = supportsU && new RegExp("^[_$\\p{ID_Start}][$\\p{ID_Continue}]*$", 'u') | ||
const groupNameMatcher = supportsU && new RegExp("^[_$\\p{ID_Start}][$\\p{ID_Continue}]*$", 'u') | ||
var loneBracketMatcher = /\\.|\{\d+,?\d*\}|(\[|\]|\{|\})/g | ||
const loneBracketMatcher = /\\.|\{\d+,?\d*\}|(\[|\]|\{|\})/g | ||
var mEndAnchor = /(?:$|(?=[\n\r\u2028\u2029]))/ | ||
const mEndAnchor = /(?:$|(?=[\n\r\u2028\u2029]))/ | ||
var mStartAnchor = /(?:^|(?<=[\n\r\u2028\u2029]))/ | ||
const mStartAnchor = /(?:^|(?<=[\n\r\u2028\u2029]))/ | ||
var numRefMatcher = /\\[^1-9]|[\[\]]|\\(\d{1,2})|\$d:(\d+),n:(\d+)\^/g | ||
const numRefMatcher = /\\[^1-9]|[\[\]]|\\(\d{1,2})|\$d:(\d+),n:(\d+)\^/g | ||
var oneEscapeOrCharClassMatcher = /^(?:\\.|\[(?:[^\]\\]|\\.)*\])$/ | ||
const oneEscapeOrCharClassMatcher = /^(?:\\.|\[(?:[^\]\\]|\\.)*\])$/ | ||
var pEscapeMatcher = /^\\p\{[A-Za-z][A-Za-z=]*\}$/ | ||
const pEscapeMatcher = /^\\p\{[A-Za-z][A-Za-z=]*\}$/ | ||
var stringNormalizerMatcher = /[.?*+^$[\]\\(){}|]/g | ||
const stringNormalizerMatcher = /[.?*+^$[\]\\(){}|]/g | ||
var suffixMatcher = /^(?:[+*?]|\{(?=((\d+)))\1,?(\d*)\})\??$/ | ||
const suffixMatcher = /^(?:[+*?]|\{(?=((\d+)))\1,?(\d*)\})\??$/ | ||
var tokenMatcher = /(\\.)|[-()|\[\]]((?=\?<?[=!]))?/g | ||
const tokenMatcher = /(\\.)|[-()|\[\]]((?=\?<?[=!]))?/g | ||
var uProblemCharClassMatcher = /\\u[0-9A-Fa-f]{4}|\\x[0-9A-Fa-f]{2}|\\c[A-Za-z]|\\([^.?*+^$[\]\\(){}|\/DSWdswfnrtv-])|(\\[DSWdsw]-[^\]]|.-\\[DSWdsw])|\\.|\]/g | ||
const uProblemCharClassMatcher = /\\u[0-9A-Fa-f]{4}|\\x[0-9A-Fa-f]{2}|\\c[A-Za-z]|\\([^.?*+^$[\]\\(){}|\/DSWdswfnrtv-])|(\\[DSWdsw]-[^\]]|.-\\[DSWdsw])|\\.|\]/g | ||
var uProblemDefaultMatcher = /\\u[0-9A-Fa-f]{4}|\\x[0-9A-Fa-f]{2}|\\c[A-Za-z]|\\k<(.*?)>|\\([^.?*+^$[\]\\(){}|\/DSWdswBbfnrtv])|\\.|\.|\[\^\]|\[|(\((?:\?[^])?)|(\)(?:[+?*]|\{\d+,?\d*\})?)/g | ||
const uProblemDefaultMatcher = /\\u[0-9A-Fa-f]{4}|\\x[0-9A-Fa-f]{2}|\\c[A-Za-z]|\\k<(.*?)>|\\([^.?*+^$[\]\\(){}|\/DSWdswBbfnrtv])|\\.|\.|\[\^\]|\[|(\((?:\?[^])?)|(\)(?:[+?*]|\{\d+,?\d*\})?)/g | ||
// Flag detection (conservatively, future flags may break our logic) | ||
export var allFlags = [] | ||
export const allFlags = [] | ||
"dgimsuy".split('').forEach(function(flag) { | ||
@@ -11,11 +11,10 @@ try { | ||
// This is currently used for modern vs legacy feature detection | ||
export var supportsU = allFlags.indexOf('u') !== -1 | ||
export var supportsLookBehind = false | ||
try {new RegExp('(?<=)'); supportsLookBehind = true} catch(e){} | ||
export const supportsU = allFlags.indexOf('u') !== -1 | ||
export const supportsLookBehind = (()=>{try {new RegExp('(?<=)'); return true} catch(e){return false}})() | ||
export var forEach = [].forEach | ||
export var hasOwn = ({}).hasOwnProperty | ||
export const forEach = [].forEach | ||
export const hasOwn = ({}).hasOwnProperty | ||
export function identity(x) {return x} | ||
export var map = [].map | ||
export var slice = [].slice | ||
export const map = [].map | ||
export const slice = [].slice | ||
@@ -25,5 +24,6 @@ // Used only for type checking | ||
// This lets us set the global RegExp to a dummy function when testing, | ||
// to ensure that the API is throwing SyntaxErrors, not the | ||
// RegExp constructor downstream. | ||
export var RegExpRef = RegExp | ||
// to ensure that our API is throwing early SyntaxErrors, not the | ||
// RegExp constructor downstream (we have more info and can give more | ||
// precise feedback). | ||
export const RegExpRef = RegExp | ||
@@ -40,7 +40,7 @@ // We decode \x.. and \u{......} escapes manually, and defer to JSON.parse | ||
var propDesc = {value: void 0, writable:false, enumerable:false, configurable: false} | ||
const propDesc = {value: void 0, writable:false, enumerable:false, configurable: false} | ||
function randId(){return "_" + Math.floor(Math.random() * Math.pow(2,32)).toString(36)} | ||
export var store = | ||
export const store = | ||
(typeof WeakMap !== 'undefined') ? new WeakMap : | ||
@@ -52,5 +52,5 @@ // degenerate WeakMap polyfill | ||
set: function(k, v) { | ||
var type = typeof k | ||
const type = typeof k | ||
if (k == null || type !== 'object' && type !== 'function') {throw new TypeError("Bad WeakMap key")} | ||
var secret = k[store.key] | ||
const secret = k[store.key] | ||
if (!secret) { | ||
@@ -61,3 +61,3 @@ propDesc.value = {keys:[this], values:[v]} | ||
} | ||
var index = secret.keys.indexOf(this) | ||
const index = secret.keys.indexOf(this) | ||
if (index === 0) return (secret.keys.push(this), secret.values.push(v), this) | ||
@@ -67,5 +67,5 @@ return (secret.values[index] = v, this) | ||
get: function(k) { | ||
var secret = k[store.key] | ||
const secret = k[store.key] | ||
if (secret) { | ||
var index = secret.keys.indexOf(this) | ||
const index = secret.keys.indexOf(this) | ||
if (index !== -1) return secret.values[index] | ||
@@ -72,0 +72,0 @@ } |
Sorry, the diff of this file is not supported yet
2989
174263