|
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