demo · v136
Multi-term Highlighter
The headline use case from the TC39 proposal: take arbitrary user terms, escape each one, glue them into a single (a|b|c) alternation and highlight every match. With RegExp.escape, strings like C++, .NET, or a.b match literally instead of crashing or silently overmatching.
RegExp.escape support…naive: new RegExp(terms.join("|"))
safe: terms.map(RegExp.escape).join("|")
the code
function buildHighlighter(terms) {
// Pre-136: hand-rolled escape, easy to get wrong on Unicode + leading digit cases.
// 136+: one standard escape, no string-of-special-chars to maintain.
const alt = terms
.map(t => t.trim())
.filter(Boolean)
.map(RegExp.escape)
.join("|");
return new RegExp(alt, "gi");
}
document.body.innerHTML = document.body.innerHTML.replace(
buildHighlighter(["C++", "$100", "(parens)", ".NET"]),
m => `<mark>${m}</mark>`
);
why this angle
The single-input demo answers "does it escape?" — useful but minimal. The proposal's motivating example is exactly this: building one regex from many untrusted strings (autocomplete terms, tag filters, search-box history) and putting them through join("|"). That join has two traps: a stray ( or + can turn the whole alternation into a syntax error, while a valid pattern such as .NET|a.b quietly treats dots as "any character" and highlights the wrong text. The two presets above show both failure modes.