|
9 | 9 | > A compiled-away, type-safe, readable RegExp alternative |
10 | 10 |
|
11 | 11 | - [✨ Changelog](https://github.com/danielroe/magic-regexp/blob/main/CHANGELOG.md) |
| 12 | +- [📖 Documentation](https://magic-regexp.roe.dev) |
12 | 13 | - [▶️ Online playground](https://stackblitz.com/github/danielroe/magic-regexp/tree/main/playground) |
13 | 14 |
|
14 | 15 | ## Features |
|
21 | 22 | - Packed with useful utilities: `charIn`, `charNotIn`, `anyOf`, `char`, `word`, `digit`, `whitespace`, `letter`, `tab`, `linefeed`, `carriageReturn`, `not`, `maybe`, `exactly`, `oneOrMore` |
22 | 23 | - All chainable with `and`, `or`, `after`, `before`, `notAfter`, `notBefore`, `times`, `as`, `at`, `optionally` |
23 | 24 |
|
24 | | -**Future ideas** |
25 | | - |
26 | | -- [ ] More TypeScript guard-rails |
27 | | -- [ ] More complex RegExp features/syntax |
28 | | -- [ ] Instrumentation for accurately getting coverage on RegExps |
29 | | -- [ ] Hybrid/partially-compiled RegExps for better dynamic support |
30 | | - |
31 | | -## Setup |
32 | | - |
33 | | -Install package: |
34 | | - |
35 | | -```sh |
36 | | -# npm |
37 | | -npm install magic-regexp |
38 | | - |
39 | | -# yarn |
40 | | -yarn add magic-regexp |
41 | | - |
42 | | -# pnpm |
43 | | -pnpm install magic-regexp |
44 | | -``` |
45 | | - |
46 | | -```js |
47 | | -import { createRegExp, exactly } from 'magic-regexp' |
48 | | - |
49 | | -const regExp = createRegExp(exactly('foo/test.js').after('bar/')) |
50 | | -console.log(regExp) |
51 | | - |
52 | | -// /(?<=bar\/)foo\/test\.js/ |
53 | | -``` |
54 | | - |
55 | | -## Usage |
56 | | - |
57 | | -Every pattern you create with the library should be wrapped in `createRegExp`. It also takes a second argument, which is an array of flags. |
58 | | - |
59 | | -```js |
60 | | -import { createRegExp, global, multiline } from 'magic-regexp' |
61 | | -createRegExp('string-to-match', [global, multiline]) |
62 | | -// you can also pass flags directly as strings |
63 | | -createRegExp('string-to-match', ['g', 'm']) |
64 | | -``` |
65 | | - |
66 | | -> **Note** |
67 | | -> 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. |
68 | | -
|
69 | | -There are a range of helpers that can be used to activate pattern matching, and they can be chained. |
70 | | - |
71 | | -They are: |
72 | | - |
73 | | -- `charIn`, `charNotIn` - this matches or doesn't match any character in the string provided. |
74 | | -- `anyOf` - this takes an array of inputs and matches any of them. |
75 | | -- `char`, `word`, `digit`, `whitespace`, `letter`, `tab`, `linefeed` and `carriageReturn` - these are helpers for specific RegExp characters. |
76 | | -- `not` - this can prefix `word`, `digit`, `whitespace`, `letter`, `tab`, `linefeed` or `carriageReturn`. For example `createRegExp(not.letter)`. |
77 | | -- `maybe` - equivalent to `?` - this marks the input as optional. |
78 | | -- `oneOrMore` - equivalent to `+` - this marks the input as repeatable, any number of times but at least once. |
79 | | -- `exactly` - this escapes a string input to match it exactly. |
80 | | - |
81 | | -All of these helpers return an object of type `Input` that can be chained with the following helpers: |
82 | | - |
83 | | -- `and` - this adds a new pattern to the current input. |
84 | | -- `or` - this provides an alternative to the current input. |
85 | | -- `after`, `before`, `notAfter` and `notBefore` - these activate positive/negative lookahead/lookbehinds. Make sure to check [browser support](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#browser_compatibility) as not all browsers support lookbehinds (notably Safari). |
86 | | -- `times` - this 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(num)` to indicate it must repeat x times or `times.any()` to indicate it can repeat any number of times, _including none_. |
87 | | -- `optionally` - this is a function you can call to mark the current input as optional. |
88 | | -- `as` - this defines the entire input so far as a named capture group. You will get type safety when using the resulting RegExp with `String.match()`. |
89 | | -- `at` - this allows you to match beginning/ends of lines with `at.lineStart()` and `at.lineEnd()`. |
90 | | - |
91 | | -## Compilation at build |
92 | | - |
93 | | -The best way to use `magic-regexp` is by making use of the included transform. |
94 | | - |
95 | | -```js |
96 | | -const regExp = createRegExp(exactly('foo/test.js').after('bar/')) |
97 | | -// => gets _compiled_ to |
98 | | -const regExp = /(?<=bar\/)foo\/test\.js/ |
99 | | -``` |
100 | | - |
101 | | -Of course, this only works with non-dynamic regexps. Within the `createRegExp` block you have to include all the helpers you are using from `magic-regexp` - and not rely on any external variables. This, for example, will not statically compile into a RegExp, although it will still continue to work with a minimal runtime: |
102 | | - |
103 | | -```js |
104 | | -const someString = 'test' |
105 | | -const regExp = createRegExp(exactly(someString)) |
106 | | -``` |
107 | | - |
108 | | -### Nuxt |
109 | | - |
110 | | -```js |
111 | | -import { defineNuxtConfig } from 'nuxt' |
112 | | - |
113 | | -// https://v3.nuxtjs.org/api/configuration/nuxt.config |
114 | | -export default defineNuxtConfig({ |
115 | | - // This will also enable auto-imports of magic-regexp helpers |
116 | | - modules: ['magic-regexp/nuxt'], |
117 | | -}) |
118 | | -``` |
119 | | - |
120 | | -### Vite |
121 | | - |
122 | | -```js |
123 | | -import { defineConfig } from 'vite' |
124 | | -import { MagicRegExpTransformPlugin } from 'magic-regexp/transform' |
125 | | - |
126 | | -export default defineConfig({ |
127 | | - plugins: [MagicRegExpTransformPlugin.vite()], |
128 | | -}) |
129 | | -``` |
130 | | - |
131 | | -### Next.js |
132 | | - |
133 | | -For Next, you will need to ensure you are using `next.config.mjs` or have set `"type": "module"` in your `package.json. |
134 | | - |
135 | | -```js |
136 | | -import { MagicRegExpTransformPlugin } from 'magic-regexp/transform' |
137 | | - |
138 | | -export default { |
139 | | - webpack(config) { |
140 | | - config.plugins = config.plugins || [] |
141 | | - config.plugins.push(MagicRegExpTransformPlugin.webpack()) |
142 | | - return config |
143 | | - }, |
144 | | -} |
145 | | -``` |
146 | | - |
147 | | -### unbuild |
148 | | - |
149 | | -```js |
150 | | -import { defineBuildConfig } from 'unbuild' |
151 | | -import { MagicRegExpTransformPlugin } from 'magic-regexp/transform' |
152 | | - |
153 | | -export default defineBuildConfig({ |
154 | | - hooks: { |
155 | | - 'rollup:options': (options, config) => { |
156 | | - config.plugins.push(MagicRegExpTransformPlugin.rollup()) |
157 | | - }, |
158 | | - }, |
159 | | -}) |
160 | | -``` |
161 | | - |
162 | | -## Examples |
163 | | - |
164 | | -```js |
165 | | -import { createRegExp, exactly, oneOrMore, digit } from 'magic-regexp' |
166 | | - |
167 | | -// Quick-and-dirty semver |
168 | | -createRegExp( |
169 | | - oneOrMore(digit) |
170 | | - .as('major') |
171 | | - .and('.') |
172 | | - .and(oneOrMore(digit).as('minor')) |
173 | | - .and(exactly('.').and(oneOrMore(char).as('patch')).optionally()) |
174 | | -) |
175 | | -// /(?<major>(\d)+)\.(?<minor>(\d)+)(\.(?<patch>(.)+))?/ |
176 | | -``` |
| 25 | +[📖 Read more](https://magic-regexp.roe.dev) |
177 | 26 |
|
178 | 27 | ## 💻 Development |
179 | 28 |
|
|
0 commit comments