RXP Guide
Import the Library
RXP can be installed directly through NPM / Yarn:
npm i rxp
yarn add rxp
Once installed, the RXP object can be imported, which contains every aspect of the library
import { RXP } from "rxp"
const { init, optional, either } = RXP
If you want to install specific functions directly, you can specify them in the import:
import { init, optional, either } from "rxp"
Alternatively, you can bypass importing the library altogether and just use the live code editor on the playground page to construct a regex and then copy it directly into your application
Initialize the Constructor
The RXP init
function works by accepting text to search for, creating an object with methods to modify the search conditions, and then converts it to a standard regex through the construct
command.
init("sample").construct() // /sample/
init("sample").atStart.construct() // /^(?:sample)/
init("sample").occurs(5).and.atStart.construct("g") // /^(?:(?:sample){5})/g
The init
function combines any number of arguments into a text to search for. String, regex, and even other RXP constructors can be provided to init
. String arguments will automatically be escaped, so you can enter the text exactly as you expect to see it:
init("search", " for ", "me").construct() // /search for me/
init("() and []").construct() // /\(\) and \[\]/
const sample = init("sample")
init("test ", /out /, sample).construct() // /test out sample/
Once the search text has been specified with init
, alternative text can be specified with or
. Any RXP methods used after or
will then be applied to both options:
const thisOrThat = init("this").or("that")
thisOrThat.construct()
// result: /(?:this)|(?:that)/
thisOrThat.occurs(5).construct()
// result: /(?:(?:this)|(?:that)){5}/
Using this pattern, regex built through RXP become modular and composable, making it easy to reuse or extend them:
const name = init("Jeff")
const namePattern = init(
name.or("Jefe"),
"some stuff",
name.isOptional);
const patternsAndPatternsOhMy = init(
namePattern,
namePattern,
namePattern.occurs(999)
).construct()
Modify Search Conditions
After creating the RXP constructor object, the provided text can be modified with regex search conditions:
sample.occurs(2).construct() // /(?:sample){2}/
sample.precededBy("ID: ").construct() // /(?<=ID: )sample/
sample.atStart.construct() // /^(?:sample)/
sample.isOptional.construct() // /(?:sample)?/
There are a large number of modifiers available to give full coverage to regex search conditions. You can review these individually on the API page.
By default, groups are noncapturing and searches are lazy, but both settings can be overridden:
sample.isCaptured.construct() // /(sample)/
sample.occursOnceOrMore.construct() // /(?:sample)+?/
sample.occursOnceOrMore.and.isGreedy.construct() // /(?:sample)+/
Regex variables can be defined with the isVariable
method and then passed to other RXP constructors through init
as often as needed. When using the construct
method, the variables will be rewritten in order of appearance to work as expected. Here is an example using the preset anyDigit
(covered below):
const regexVar = anyDigit.occurs(3).and.isVariable("var")
init(regexVar, " with ", regexVar).construct()
// /(?<var>d{3}) with //k<var>/
Convert to Regex
The construct
function can be passed arguments to define the search flags:
sample.construct("g") // /sample/g
sample.construct("global", "s", "I") // /sample/gsi
If init
is passed a regex argument including a flag, the flag will be stripped from it and would need to be added back with construct
:
init(/search/g, " for me").construct() // /search for me/
Presets
To use special characters, such as \d
to match a digit or \w
to match a letter, you can use the presets
provided with RXP, such as anyDigit
or anyLetter
. These are preloaded RXP constructor objects with all the functionality built in:
anyDigit.occurs(3).construct() // /(?:[0123456789]){3}/
anyLetter.atEnd.construct() // /(?:\w)$/
Since the init
function will automatically escape special characters, if you want to pass them in directly without using presets then you would need to use a standard regex:
// incorrect:
init("\d").construct() // result: /\\d/
// correct:
init(/\d/).construct() // result: /\d/
A full list of presets can be found on the API page
Shorthands
shorthands
are a group of functions that create an RXP object and immediately apply a desired search condition. These are provided to improve readability, and there is no functional difference between something like optional("text")
and init("text").isOptional
.
init(
optional("("),
"text",
optional(")")
.construct() // /(?:()?text(?:))?/
A variety of shorthands are available and can be found on the API page. All of these produce the standard RXP constructor object with the unique exceptions of withBoundaries
and wrapRXP
.
Error Handling
RXP has been designed with a degree of error handling built in. When combining two search conditions with and
would result in an invalid regex, the constructor will not make the subsequent option available, allowing only valid combinations.
This is designed to be intuitive for the user thanks to intellisense, and is not something you should have to think about. The options presented will naturally guide you into creating valid regex.
The actual search conditions are structured into levels, with each one locking out previous levels:
occurs
,occursAtLeast
, etc.followedBy
,notFollowedBy
, etc.atStart
,atEnd
isOptional
,isCaptured
,isVariable
By applying this structure, it is not possible to follow a method like atStart
with options such as occurs
and precededBy
, both of which would result in invalid regex:
/^(?:(?<=this )won't work)/
/(^nor will this){5}/
There is one important caveat here - when using regex or RXP constructors as arguments in init
or related functions, the resulting RXP constructor will provide all of the possible options initially, so it is still possible to write invalid regex:
const example = init("text").precededBy("stuff")
example.atEnd // works
example.atStart // X - unavailable
init(example).atStart // invalid regex, but due to RXP composition
// the constructor will still allow this
RXP does a lot to deter mistakes, but it is not fullproof and regex should still be built in a careful manner