README
fancy-regex
JS/TS regexes with whitespace, comments, and interpolation!
Usage
regex
regex
is used to create a fancy regex, which compiles to a native JavaScript RegExp
at runtime.
import { regex } from 'fancy-regex'
const myFancyRegex = regex`
hello,\ world! # escaped whitespace with backslash
`
// β /hello, world!/
If you donβt need to use any flags, the regex
function is directly callable on template strings. Otherwise, you can pass the flags to regex
first:
const myGlobalRegex = regex('g')`π`
// β /π/g
If you like, you can pass an options object instead of string flags:
const myRegexWithOptions = regex({
unicode: true,
global: true,
})`
^
π©+ # with unicode enabled, this matches by codepoint
$
`
// β /^π©+$/gu
Interpolation is simple:
const myInterpolatedRegex = regex('i')`
^
${'abc'} # seamlessly interpolate strings...
${myFancyRegex} # ...and other regexes
${myGlobalRegex} # inner flags are ignored when interpolated
\w\d\b\0\\ # look Mom, no double escaping!
...
\r\n\t\x20 # you can also use "\x20" to match a literal space
$
`
// β /abchello, world!π\w\d\b\0\\...\r\n\t\x20/i
regex
also provides some utility functions β regexEscape
, exact
, and unwrap
.
and regexEscapeexact
regexEscape
escapes arbitrary string data for interpolation into a regex, exactly matching the input string. exact
works similarly, except it returns a regex without the need for interpolation.
For example, exact('.[xy]')
matches the exact string ".[xy]"
, rather than matching a single character followed by an x or y. These functions can be useful, for example, sanitizing user for insertion into a regex.
// sanitizing user input
const textMatcher = regex('gi')`
\b
${regexEscape(searchText)}
\b
`
// using `exact`
exact('.[xy]').test('.[xy]') // β true
exact('.[xy]').test('ax') // β false
// or with flags...
exact('.[xy]', 'i').test('.[XY]') // β true
unwrap
Removes start-of-string and end-of-string matchers from a regex. Useful for interpolating or repurposing single-match regexes:
const singleHex = /^[0-9a-f]$/i
const hex = unwrap(singleHex)
// β /[0-9a-f]/i
const singleUuid = regex`
^
${hex}{8}
-
${hex}{4}
-
${hex}{4}
-
${hex}{4}
-
${hex}{12}
$
`
// β /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
const multipleUuid = unwrap(singleUuid, 'g')
// β /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/g
Experimental Proxy API
To enable the experimental Proxy-based API, which provides syntax sugar for setting flags, change the import
statement as follows:
- import { regex } from 'fancy-regex'
+ import { proxy as regex } from 'fancy-regex'
You can then use the syntax regex.<flags>`...`
as an additional alternative to regex('<flags>')`...`
. For example:
regex.gi`
${'I have global and ignore-case flags set!'}
`
regex._`
${'_ can be used to indicate no flags'}
`
Note that, if you're using TypeScript, the type checking for this syntax requires that the flags are given in alphabetical order:
// OK!
regex.gimsuy`π`
// Property 'yusmig' does not exist on type [...]
regex.yusmig`β`