Skip to content

Instantly share code, notes, and snippets.

@shannonmoeller
Last active April 12, 2021 22:16
Show Gist options
  • Save shannonmoeller/b4f6fbab2ffec56213e7 to your computer and use it in GitHub Desktop.
Save shannonmoeller/b4f6fbab2ffec56213e7 to your computer and use it in GitHub Desktop.
Multiline Regular Expressions using ES6 Template Strings
/**
* Inspired by XRegExp via 2ality
* http://www.2ality.com/2012/12/template-strings-xregexp.html
* http://xregexp.com/
*/
import test from 'ava';
export function rx(flags) {
const trailingComments = /\s+#.*$/gm;
const surroundingWhitespace = /^\s+|\s+$/gm;
const literalNewlines = /[\r\n]/g;
return (strings, ...values) => {
function toPattern(pattern, rawString, i) {
var value = values[i];
if (value == null) {
return pattern + rawString;
}
if (value instanceof RegExp) {
value = value.source;
}
return pattern + rawString + value;
}
const compiledPattern = strings.raw
.reduce(toPattern, '')
.replace(trailingComments, '')
.replace(surroundingWhitespace, '')
.replace(literalNewlines, '');
return new RegExp(compiledPattern, flags);
};
}
test('should compile a multiline RegExp', async assert => {
// flags on partials are ignored
const open = /\/\*\*/g;
const close = /\*\//m;
const expression = rx('gm')`
# Match a non-recursive block comment
(
# Must be first thing on a line
^[\t ]*
${open} # Trailing comment
(
# Match any character including newlines (non-greedy)
[\s\S]*?
)
${close}
)
# Grab trailing newlines and discard them
[\r\n]*
`;
assert.same(expression, /(^[\t ]*\/\*\*([\s\S]*?)\*\/)[\r\n]*/gm);
});
@MaudDibb
Copy link

MaudDibb commented Mar 4, 2019

brilliant...helped make a parser im working on MUCH easier to work with

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment