A JavaScript library to generate complex regular expressions more easily.
⚠️ WARNING: This library still under development and should not be used in production!
Want to help? Found a bug or have any suggestion? Find how to contribute in the CONTRIBUTING.md file.
The library can be used in the browser using the CDN:
<script src="https://cdn.jsdelivr.net/npm/@regexp-template/core/dist/regexp-template.min.js"></script>
or via npm:
npm i @regexp-template/core
Using the script tag the RegExpTemplate class becomes available on the global scope.
On Node.js can be required using:
const RegExpTemplate = require('@regexp-template/core');
Lets start with a simple example: concatenation of two regular expressions, /hello/
and /world/
.
We first create a RegExpTemplate instance with our regular expressions as arguments:
var hwTemplate = new RegExpTemplate(/hello/, /world/);
then we can compile our template to a RegExp:
var re = hwTemplate.compile();
// outputs /helloworld/
The compile method joins the two regular expressions into a new one.
In this case we only passed two regular expressions but you can pass as many template elements (see below) as you want.
The template is constructed using pieces called elements.
In the hello world example above, /hello/
and /world/
are two elements of that template.
Template elements have 4 types:
-
RegExp - used to add regular expression segments to the template. Also allow use of template variables.
-
string - all characters are interpreted as literal characters (except especials characters of strings like
\n
). -
RegExpTemplate - this allows templates to be used inside another templates. See the subtemplates section.
-
extension - a custom user defined class. See the template extension section for more info.
Any other type passed to the template gets converted to a string.
Template Variables let you introduce new template elements inside of regular expressions.
Template variables can be declared by using the notation \VAR{varname}
inside regular expressions, where the varname
is the name of the variable.
Note that in \VAR
doesn't need to be uppercase. '\VAR'
, \Var
or \var
all work the same way.
In the code below a template is created and a variable called myVar
is defined.
new RegExpTemplate(/\VAR{ myVar }/);
Note: whitespace can be used inside the curly braces.
variables are unique, any reference to varname
refers to the same variable.
new RegExpTemplate(
/\VAR{ foo } is the/,
/same as \VAR{ foo } but not \VAR{ bar }/
);
Once defined a variable can then be assigned. This is done using the applyVars
method.
const myTemplate = new RegExpTemplate(/\VAR{ myVar }/);
myTemplate.applyVars({
myVar: "myValue"
});
The applyVars
method expects an object that maps the name of the template variable to its value.
The value can be any template element.
After the method is called then all references of the variables passed are going to be replaced by the corresponding value.
const myTemplate =
new RegExpTemplate(
/\VAR{ foo } is the/,
/same as \VAR{ foo } but not \VAR{ bar }/
);
myTemplate.applyVars({
foo: "dog",
bar: "cat"
});
myTemplate.compile();
// outputs /dog is the same as dog but not cat/
You don't need to set variables at once. you can do something like:
myTemplate.applyVars({foo: "dog"});
myTemplate.applyVars({bar: "cat"});
or in chain:
myTemplate
.applyVars({foo: "dog"})
.applyVars({bar: "cat"});
keep in mind however that all variables must be assigned before compiling the template:
const myTemplate = new RegExpTemplate(
/\VAR{ myVar } was not assigned/
);
myTemplate.compile();
// throws an error because 'myVar' is not assigned
If you assign a value that contains new variables, that variable will be defined/referenced once the variable is applied.
const myTemplate = new RegExpTemplate(
/\VAR{ oldVar }/
);
myTemplate
.applyVars({oldVar: /\(\VAR{ newVar }\)/})
.applyVars({newVar: '2'});
In the example above a regular expression defines a variable called oldVar
.
The first applyVars
call replaces the oldVar
by a new Regular Expression that contains a variable reference wrapped in parentesis.
Once added to the template the new variable newVar
is defined.
Then the second applyVars
replaces newVar
with the string '2'
.
Since all variables (oldVar
and newVar
) defined are assigned, the template can now be compiled.
myTemplate.compile();
// outputs /(2)/
Templates can be included inside other templates.
// this template might be more complex
// but we keep it simple for the example
const numberTemplate = new RegExpTemplate(/\d+\.\d*/);
// parent template using the numberTemplate
const sumTemplate = new RegExpTemplate(
numberTemplate, ' + ', numberTemplate
);
sumTemplate.compile();
// outputs /\d+\.\d* \+ \d+\.\d*/
This allows you split parts of a complex regular expression into smaller ones, making it easier to read and edit. It also allows the reuse of these smaller parts in different contexts that might be common e.g. the number template in the example above might be used in other contexts than sum.
The subtemplates are independent. The template variables assigned to the parent template will not propagate to the subtemplate.
When the parent template compile method is called the subtemplate compile method is called as well and used to compute the result of the parent. This means that the subtemplate must be ready to compile when the compile is called on the parent (see template variables).
This feature is not implemented yet.
The RegExpTemplate provides an API that allows you to make your own template elements.
MIT