import { createRegExp, exactly } from 'magic-regexp'
const regExp = createRegExp(exactly('foo/test.js').after('bar/'))
console.log(regExp)
// /(?<=bar\/)foo\/test\.js/

createRegExp

Every pattern you create with the library should be wrapped in createRegExp, which enables the build-time transform.

createRegExp accepts an arbitrary number of arguments of type string or Input (built up using helpers from magic-regexp), and an optional final argument of an array of flags or a flags string. It creates a MagicRegExp, which concatenates all the patterns from the arguments that were passed in.

import { createRegExp, global, multiline, exactly } from 'magic-regexp'
createRegExp(exactly('foo').or('bar'))
createRegExp('string-to-match', [global, multiline])
// you can also pass flags directly as strings or Sets
createRegExp('string-to-match', ['g', 'm'])
// or pass in multiple `string` and `input patterns`,
// all inputs will be concatenated to one RegExp pattern
createRegExp(
'foo',
maybe('bar').groupedAs('g1'),
'baz',
[global, multiline]
)
// equivalent to /foo(?<g1>(?:bar)?)baz/gm
By default, all helpers from magic-regexp assume that input that is passed should be escaped - so no special RegExp characters apply. So createRegExp('foo?\d') will not match food3 but only foo?\d exactly.

Creating inputs

There are a range of helpers that can be used to activate pattern matching, and they can be chained. Each one of these returns an object of type Input that can be passed directly to new RegExp, createRegExp, to another helper or chained to produce more complex patterns.

charIn, charNotInthis matches or doesn't match any character in the string provided.
anyOfthis takes a variable number of inputs and matches any of them.
char, word, wordChar, wordBoundary, digit, whitespace, letter, letter.lowercase, letter.uppercase, tab, linefeed and carriageReturnthese are helpers for specific RegExp characters.
notthis can prefix word, wordChar, wordBoundary, digit, whitespace, letter, letter.lowercase, letter.uppercase, tab, linefeed or carriageReturn. For example createRegExp(not.letter).
maybeequivalent to ? - this takes a variable number of inputs and marks them as optional.
oneOrMoreEquivalent to + - this takes a variable number of inputs and marks them as repeatable, any number of times but at least once.
exactlyThis takes a variable number of inputs and concatenate their patterns, and escapes string inputs to match it exactly.
All helpers that takes string and Input are variadic functions, so you can pass in one or multiple arguments of string or Input to them and they will be concatenated to one pattern. for example,s exactly('foo', maybe('bar')) is equivalent to exactly('foo').and(maybe('bar')).

Chaining inputs

All of the helpers above return an object of type Input that can be chained with the following helpers:

andthis takes a variable number of inputs and adds them as new pattern to the current input, or you can use and.referenceTo(groupName) to adds a new pattern referencing to a named group.
orthis takes a variable number of inputs and provides as an alternative to the current input.
after, before, notAfter and notBeforethese takes a variable number of inputs and activate positive/negative lookahead/lookbehinds. Make sure to check browser support as not all browsers support lookbehinds (notably Safari).
timesthis is a function you can call directly to repeat the previous pattern an exact number of times, or you can use times.between(min, max) to specify a range, times.atLeast(x) to indicate it must repeat at least x times, times.atMost(x) to indicate it must repeat at most x times or times.any() to indicate it can repeat any number of times, including none.
optionallythis is a function you can call to mark the current input as optional.
asalias for groupedAs
groupedAsthis defines the entire input so far as a named capture group. You will get type safety when using the resulting RegExp with String.match().
groupedthis defines the entire input so far as an anonymous group.
atthis allows you to match beginning/ends of lines with at.lineStart() and at.lineEnd().
By default, for better regex performance, creation input helpers such as anyOf, maybe, oneOrMore, and chaining input helpers such as or, times(.between/atLeast/any), or optionally will wrap the input in a non-capturing group with (?:). You can use chaining input helper grouped after any Input type to capture it as an anonymous group.

Debugging

When using magic-regexp, a TypeScript generic is generated for you that should show the RegExp that you are constructing, as you go.

This is true not just for the final RegExp, but also for the pieces you create along the way.

So, for example:

import { exactly } from 'magic-regexp'
exactly('test.mjs')
// (alias) exactly<"test.mjs">(input: "test.mjs"): Input<"test\\.mjs", never>
exactly('test.mjs').or('something.else')
// (property) Input<"test\\.mjs", never>.or: <"something.else">(input: "something.else") => Input<"(?:test\\.mjs|something\\.else)", never>

Each function, if you hover over it, shows what's going in, and what's coming out by way of regular expression

You can also call .toString() on any input to see the same information at runtime.