function negate(regex) {
return new RegExp(
String.raw`^(?![\s\S]*${regex.source})[\s\S]*$`,
regex.flags,
)
}
const tests = [
{ regex: /(ma|(t){1})/, matches: ['ma', 't'], nonMatches: ['bla'] },
{ regex: /foo/, matches: ['foo'], nonMatches: ['bar'] },
{ regex: /(foo|bar)/, matches: ['foo', 'bar'], nonMatches: ['baz'] },
{ regex: /\d{3}/, matches: ['123', '456', '999'], nonMatches: ['foo'] },
]
for (const { regex, matches, nonMatches } of tests) {
for (const text of matches) {
const atStart = `${text} ...`
const atEnd = `... ${text}`
const inMiddle = `... ${text} ...`
check(regex.test(text), `${regex} matches ${JSON.stringify(text)}`)
check(regex.test(atStart), `${regex} matches ${JSON.stringify(atStart)}`)
check(regex.test(atEnd), `${regex} matches ${JSON.stringify(atEnd)}`)
check(regex.test(inMiddle), `${regex} matches ${JSON.stringify(inMiddle)}`)
const negated = negate(regex)
check(!negated.test(text), `${negated} doesn't match ${JSON.stringify(text)}`)
check(!negated.test(atStart), `${negated} doesn't match ${JSON.stringify(atStart)}`)
check(!negated.test(atEnd), `${negated} doesn't match ${JSON.stringify(atEnd)}`)
check(!negated.test(inMiddle), `${negated} doesn't match ${JSON.stringify(inMiddle)}`)
const doubleNegated = negate(negated)
check(doubleNegated.test(text), `${doubleNegated} matches ${JSON.stringify(text)}`)
check(doubleNegated.test(atStart), `${doubleNegated} matches ${JSON.stringify(atStart)}`)
check(doubleNegated.test(atEnd), `${doubleNegated} matches ${JSON.stringify(atEnd)}`)
check(doubleNegated.test(inMiddle), `${doubleNegated} matches ${JSON.stringify(inMiddle)}`)
}
for (const text of nonMatches) {
const atStart = `${text} ...`
const atEnd = `... ${text}`
const inMiddle = `... ${text} ...`
check(!regex.test(text), `${regex} doesn't match ${JSON.stringify(text)}`)
check(!regex.test(atStart), `${regex} doesn't match ${JSON.stringify(atStart)}`)
check(!regex.test(atEnd), `${regex} doesn't match ${JSON.stringify(atEnd)}`)
check(!regex.test(inMiddle), `${regex} doesn't match ${JSON.stringify(inMiddle)}`)
const negated = negate(regex)
check(negated.test(text), `${negated} matches ${JSON.stringify(text)}`)
check(negated.test(atStart), `${negated} matches ${JSON.stringify(atStart)}`)
check(negated.test(atEnd), `${negated} matches ${JSON.stringify(atEnd)}`)
check(negated.test(inMiddle), `${negated} matches ${JSON.stringify(inMiddle)}`)
const doubleNegated = negate(negated)
check(!doubleNegated.test(text), `${doubleNegated} doesn't match ${JSON.stringify(text)}`)
check(!doubleNegated.test(atStart), `${doubleNegated} doesn't match ${JSON.stringify(atStart)}`)
check(!doubleNegated.test(atEnd), `${doubleNegated} doesn't match ${JSON.stringify(atEnd)}`)
check(!doubleNegated.test(inMiddle), `${doubleNegated} doesn't match ${JSON.stringify(inMiddle)}`)
}
}
console.info('Tests passed')
function check(condition, message = 'Condition failed') {
if (!condition) {
throw new Error(message)
}
console.info(message)
}
{1}
is completely useless. (If you do think it provides some value, why don't you write((m{1}a{1}){1}|(t){1}){1}
?) – Mayramays