@regex-designer/js 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,249 @@
1
- # Temporary Holding Version
1
+ # Regular Expression Designer | JavaScript
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A small TypeScript library for composing native JavaScript regular expressions in a readable, reusable way.
4
+
5
+ ## API
6
+
7
+ - [default](#default)
8
+ - [set / var](#set--var)
9
+ - [tpl](#tpl)
10
+ - [raw](#raw)
11
+ - [start / end / whole](#start--end--whole)
12
+ - [group](#group)
13
+ - [named](#named)
14
+ - [ref](#ref)
15
+ - [opt](#opt)
16
+ - [qty](#qty)
17
+ - [or](#or)
18
+ - [ahead / ahead_pos / ahead_neg](#ahead--ahead_pos--ahead_neg)
19
+ - [behind / behind_pos / behind_neg](#behind--behind_pos--behind_neg)
20
+
21
+ The JavaScript package exposes a default factory and a `JSRegexDesigner` class. It extends the abstract `RegexDesigner` contract from `@regex-designer/core`. Templates are compiled to a native `RegExp`.
22
+
23
+ ```ts
24
+ import createDesigner from "@regex-designer/js";
25
+
26
+ const r$ = createDesigner();
27
+
28
+ r$.set("number", r$.qty([1, Infinity], "[0-9]"));
29
+ r$.set("identifier", r$.qty([1, Infinity], "[a-z0-9-]"));
30
+
31
+ // (?<version>(?:[0-9]){1,}\.(?:[0-9]){1,}\.(?:[0-9]){1,}(?:-(?<prerelease>(?:[a-z0-9-]){1,}))?)
32
+ const template = r$.named(
33
+ "version",
34
+ r$.var("number"), "\\.", r$.var("number"), "\\.", r$.var("number"),
35
+ r$.opt("-", r$.named("prerelease", r$.var("identifier"))),
36
+ );
37
+ const regex = template("i"); // Compile the template to a native RegExp
38
+
39
+ regex.test("12.3.4-beta-1"); // true
40
+ regex.exec("12.3.4-beta-1")?.groups; // { version: "12.3.4-beta-1", prerelease: "beta-1" }
41
+ ```
42
+
43
+ ### default
44
+
45
+ ```ts
46
+ default function(): JSRegexDesigner
47
+ ```
48
+
49
+ Create a new JavaScript regex designer with its own variable scope.
50
+
51
+ ```ts
52
+ import createDesigner from "@regex-designer/js";
53
+
54
+ const r$: JSRegexDesigner = createDesigner();
55
+ ```
56
+
57
+ ### set / var
58
+
59
+ ```ts
60
+ set(name: string, ...patterns: RegexValue[]): this
61
+ var(name: string): RegexTemplate
62
+ ```
63
+
64
+ Define a reusable lazy variable on a designer, then reference it when composing
65
+ a pattern. The variable resolves when the template is rendered. Rendering an unset variable or circular dependencies between variables throws an error.
66
+
67
+ ```ts
68
+ r$.set("word", r$.or("cat", "dog"));
69
+ r$.var("word"); // cat|dog
70
+ ```
71
+
72
+ ### tpl
73
+
74
+ ```ts
75
+ tpl(...patterns: RegexValue[]): RegexTemplate
76
+ ```
77
+
78
+ Concatenate patterns without adding groups or escaping.
79
+
80
+ ```ts
81
+ r$.tpl("A", "B"); // AB
82
+ ```
83
+
84
+ ### raw
85
+
86
+ ```ts
87
+ raw(...patterns: string[]): RegexTemplate
88
+ ```
89
+
90
+ Escape literal text for use in a regex pattern.
91
+
92
+ ```ts
93
+ r$.raw("a.b", "*"); // \x61\.b\*
94
+ r$.raw("https://example.com"); // \x68ttps\x3a\/\/example\.com
95
+ ```
96
+
97
+ ### start / end / whole
98
+
99
+ ```ts
100
+ start(...patterns: RegexValue[]): RegexTemplate
101
+ end(...patterns: RegexValue[]): RegexTemplate
102
+ whole(...patterns: RegexValue[]): RegexTemplate
103
+ ```
104
+
105
+ Choose whether the concatenated patterns must match at the [start, end, or across the whole input](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Input_boundary_assertion).
106
+
107
+ ```ts
108
+ r$.start("foo"); // ^(?:foo)
109
+ r$.end("bar"); // (?:bar)$
110
+ r$.whole("baz"); // ^(?:baz)$
111
+ ```
112
+
113
+ ### group
114
+
115
+ ```ts
116
+ group(options: boolean, ...patterns: RegexValue[]): RegexTemplate
117
+ group(options: { name: string }, ...patterns: RegexValue[]): RegexTemplate
118
+ group(options: { capture?: boolean }, ...patterns: RegexValue[]): RegexTemplate
119
+ ```
120
+
121
+ Group patterns using [capturing](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Capturing_group)
122
+ or [non-capturing groups](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Non-capturing_group),
123
+ optionally assigning a [capture name](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Named_capturing_group).
124
+
125
+ ```ts
126
+ r$.group(true, "A"); // (A)
127
+ r$.group(false, "A", "B"); // (?:AB)
128
+ r$.group({ name: "part" }, "A", "B"); // (?<part>AB)
129
+ r$.group({ capture: true }, "A"); // (A)
130
+ r$.group({ capture: false }, "A", "B"); // (?:AB)
131
+ ```
132
+
133
+ ### named
134
+
135
+ ```ts
136
+ named(name: string, ...patterns: RegexValue[]): RegexTemplate
137
+ ```
138
+
139
+ Create a [named capturing group](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Named_capturing_group)
140
+ around the concatenated patterns.
141
+
142
+ ```ts
143
+ r$.named("value", "A", "B"); // (?<value>AB)
144
+ r$.named("word", r$.or("cat", "dog")); // (?<word>cat|dog)
145
+ ```
146
+
147
+ ### ref
148
+
149
+ ```ts
150
+ ref(reference: number | string): RegexTemplate
151
+ ```
152
+
153
+ Create a [numeric](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Backreference) or [named](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Named_backreference) backreference.
154
+
155
+ ```ts
156
+ r$.tpl(
157
+ r$.group(true, "B"),
158
+ r$.ref(1),
159
+ ); // (B)\1
160
+
161
+ r$.tpl(
162
+ r$.named("name", "B"),
163
+ r$.ref("name"),
164
+ ); // (?<name>B)\k<name>
165
+ ```
166
+
167
+ ### opt
168
+
169
+ ```ts
170
+ opt(...patterns: RegexValue[]): RegexTemplate
171
+ ```
172
+
173
+ Make the concatenated patterns [optional](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Quantifier) using a non-capturing group.
174
+
175
+ ```ts
176
+ r$.opt("C"); // (?:C)?
177
+ r$.opt(r$.named("value", "A", "B")); // (?:(?<value>AB))?
178
+ ```
179
+
180
+ ### qty
181
+
182
+ ```ts
183
+ qty(quantity: number, ...patterns: RegexValue[]): RegexTemplate
184
+ qty(quantity: [min: number, max?: number], ...patterns: RegexValue[]): RegexTemplate
185
+ qty(quantity: { exact: number; greedy?: boolean }, ...patterns: RegexValue[]): RegexTemplate
186
+ qty(quantity: { min: number; max?: number; greedy?: boolean }, ...patterns: RegexValue[]): RegexTemplate
187
+ ```
188
+
189
+ [Repeat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Quantifier) the concatenated patterns according to the supplied bounds.
190
+
191
+ ```ts
192
+ r$.qty(3, "A", "B"); // (?:AB){3}
193
+ r$.qty([3, 3], "A", "B"); // (?:AB){3}
194
+ r$.qty([1, 3], "A", "B"); // (?:AB){1,3}
195
+ r$.qty([1, Infinity], "A", "B"); // (?:AB){1,}
196
+ r$.qty({ exact: 3 }, "A", "B"); // (?:AB){3}
197
+ r$.qty({ exact: 3, greedy: false }, "A", "B"); // (?:AB){3}?
198
+ r$.qty({ min: 2 }, "A", "B"); // (?:AB){2,}
199
+ r$.qty({ min: 2, max: 5 }, "A", "B"); // (?:AB){2,5}
200
+ r$.qty({ min: 2, max: 5, greedy: false }, "A", "B"); // (?:AB){2,5}?
201
+ ```
202
+
203
+ ### or
204
+
205
+ ```ts
206
+ or(...patterns: RegexValue[]): RegexTemplate
207
+ ```
208
+
209
+ Join patterns with [disjunction](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Disjunction)
210
+ without adding groups.
211
+
212
+ ```ts
213
+ r$.or("cat", "dog"); // cat|dog
214
+ r$.or("foo", "bar", r$.raw("baz")); // foo|bar|\x62az
215
+ ```
216
+
217
+ ### ahead / ahead_pos / ahead_neg
218
+
219
+ ```ts
220
+ ahead(positive: boolean, ...patterns: RegexValue[]): RegexTemplate
221
+ ahead_pos(...patterns: RegexValue[]): RegexTemplate
222
+ ahead_neg(...patterns: RegexValue[]): RegexTemplate
223
+ ```
224
+
225
+ Create a positive or negative [lookahead assertion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Lookahead_assertion).
226
+
227
+ ```ts
228
+ r$.ahead(true, "foo"); // (?=foo)
229
+ r$.ahead(false, "foo"); // (?!foo)
230
+ r$.ahead_pos("foo"); // (?=foo)
231
+ r$.ahead_neg("bar"); // (?!bar)
232
+ ```
233
+
234
+ ### behind / behind_pos / behind_neg
235
+
236
+ ```ts
237
+ behind(positive: boolean, ...patterns: RegexValue[]): RegexTemplate
238
+ behind_pos(...patterns: RegexValue[]): RegexTemplate
239
+ behind_neg(...patterns: RegexValue[]): RegexTemplate
240
+ ```
241
+
242
+ Create a positive or negative [lookbehind assertion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Lookbehind_assertion).
243
+
244
+ ```ts
245
+ r$.behind(true, "foo"); // (?<=foo)
246
+ r$.behind(false, "foo"); // (?<!foo)
247
+ r$.behind_pos("foo"); // (?<=foo)
248
+ r$.behind_neg("bar"); // (?<!bar)
249
+ ```
@@ -0,0 +1,55 @@
1
+ /**
2
+ * The JavaScript package exposes a default factory and a `JSRegexDesigner` class. It extends the abstract `RegexDesigner` contract from `@regex-designer/core`. Templates are compiled to a native `RegExp`.
3
+ */
4
+ import type { GroupOptions, QuantityOptions, RegexDesignerWithBackreferences, RegexDesignerWithLookarounds, RegexTemplate as CoreRegexTemplate, RegexValue as CoreRegexValue } from "@regex-designer/core";
5
+ import { RegexDesigner } from "@regex-designer/core";
6
+ export type { GroupNamedOptions, GroupOptions, QuantityNamedOptions, QuantityOptions, RegexDesignerWithBackreferences, RegexDesignerWithLookarounds, } from "@regex-designer/core";
7
+ export type RegexTemplate = CoreRegexTemplate<RegExp>;
8
+ export type RegexValue = CoreRegexValue<RegExp>;
9
+ export { isRegexTemplate } from "@regex-designer/core";
10
+ /**
11
+ * Create a new JavaScript regex designer with its own variable scope.
12
+ * @readme default
13
+ */
14
+ export default function create(): JSRegexDesigner;
15
+ /**
16
+ * Templates are compiled to a native `RegExp`.
17
+ */
18
+ export declare class JSRegexDesigner extends RegexDesigner<RegExp> implements RegexDesignerWithBackreferences<RegExp>, RegexDesignerWithLookarounds<RegExp> {
19
+ protected createTemplate(render: (flags: string | undefined, compiling: boolean) => string): RegexTemplate;
20
+ /** Concatenate patterns without adding groups or escaping. */
21
+ tpl(...patterns: RegexValue[]): RegexTemplate;
22
+ /** Escape literal text for use in a regex pattern. */
23
+ raw(...patterns: string[]): RegexTemplate;
24
+ /** Match the concatenated patterns at the start of the input. */
25
+ start(...patterns: RegexValue[]): RegexTemplate;
26
+ /** Match the concatenated patterns at the end of the input. */
27
+ end(...patterns: RegexValue[]): RegexTemplate;
28
+ /** Match the concatenated patterns across the whole input. */
29
+ whole(...patterns: RegexValue[]): RegexTemplate;
30
+ /** Group patterns, optionally capturing them or assigning a capture name. */
31
+ group(options: GroupOptions, ...patterns: RegexValue[]): RegexTemplate;
32
+ /** Create a named capturing group around the concatenated patterns. */
33
+ named(name: string, ...patterns: RegexValue[]): RegexTemplate;
34
+ /** Create a numeric or named backreference. */
35
+ ref(reference: number | string): RegexTemplate;
36
+ /** Make the concatenated patterns optional using a non-capturing group. */
37
+ opt(...patterns: RegexValue[]): RegexTemplate;
38
+ /** Repeat the concatenated patterns according to the supplied bounds. */
39
+ qty(quantity: QuantityOptions, ...patterns: RegexValue[]): RegexTemplate;
40
+ /** Join patterns with alternation without adding groups. */
41
+ or(...patterns: RegexValue[]): RegexTemplate;
42
+ /** Create a positive or negative [lookahead assertion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Lookahead_assertion). */
43
+ ahead(positive: boolean, ...patterns: RegexValue[]): RegexTemplate;
44
+ /** Create a positive [lookahead assertion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Lookahead_assertion). */
45
+ ahead_pos(...patterns: RegexValue[]): RegexTemplate;
46
+ /** Create a negative [lookahead assertion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Lookahead_assertion). */
47
+ ahead_neg(...patterns: RegexValue[]): RegexTemplate;
48
+ /** Create a positive or negative [lookbehind assertion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Lookbehind_assertion). */
49
+ behind(positive: boolean, ...patterns: RegexValue[]): RegexTemplate;
50
+ /** Create a positive [lookbehind assertion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Lookbehind_assertion). */
51
+ behind_pos(...patterns: RegexValue[]): RegexTemplate;
52
+ /** Create a negative [lookbehind assertion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Lookbehind_assertion). */
53
+ behind_neg(...patterns: RegexValue[]): RegexTemplate;
54
+ }
55
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,eAAe,EACf,+BAA+B,EAC/B,4BAA4B,EAC5B,aAAa,IAAI,iBAAiB,EAClC,UAAU,IAAI,cAAc,EAC7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,aAAa,EAEd,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EACV,iBAAiB,EACjB,YAAY,EACZ,oBAAoB,EACpB,eAAe,EACf,+BAA+B,EAC/B,4BAA4B,GAC7B,MAAM,sBAAsB,CAAC;AAC9B,MAAM,MAAM,aAAa,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;AACtD,MAAM,MAAM,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AA8FvD;;;GAGG;AACH,MAAM,CAAC,OAAO,UAAU,MAAM,IAAI,eAAe,CAEhD;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,aAAa,CAAC,MAAM,CAAE,YAAW,+BAA+B,CAAC,MAAM,CAAC,EAAE,4BAA4B,CAAC,MAAM,CAAC;cAC9H,cAAc,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,OAAO,KAAK,MAAM,GAAG,aAAa;IAInH,8DAA8D;IACrD,GAAG,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,aAAa;IAItD,sDAAsD;IAC7C,GAAG,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,aAAa;IAIlD,iEAAiE;IACxD,KAAK,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,aAAa;IAIxD,+DAA+D;IACtD,GAAG,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,aAAa;IAItD,8DAA8D;IACrD,KAAK,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,aAAa;IAIxD,6EAA6E;IACpE,KAAK,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,aAAa;IAI/E,uEAAuE;IAC9D,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,aAAa;IAItE,+CAA+C;IAC/C,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa;IAI9C,2EAA2E;IAClE,GAAG,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,aAAa;IAItD,yEAAyE;IAChE,GAAG,CAAC,QAAQ,EAAE,eAAe,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,aAAa;IAIjF,4DAA4D;IACnD,EAAE,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,aAAa;IAIrD,sKAAsK;IAC7J,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,aAAa;IAI3E,0JAA0J;IACjJ,SAAS,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,aAAa;IAI5D,0JAA0J;IACjJ,SAAS,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,aAAa;IAI5D,wKAAwK;IAC/J,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,aAAa;IAI5E,4JAA4J;IACnJ,UAAU,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,aAAa;IAI7D,4JAA4J;IACnJ,UAAU,CAAC,GAAG,QAAQ,EAAE,UAAU,EAAE,GAAG,aAAa;CAI9D"}
package/dist/index.js ADDED
@@ -0,0 +1,167 @@
1
+ /**
2
+ * The JavaScript package exposes a default factory and a `JSRegexDesigner` class. It extends the abstract `RegexDesigner` contract from `@regex-designer/core`. Templates are compiled to a native `RegExp`.
3
+ */
4
+ import { RegexDesigner, isRegexTemplate, } from "@regex-designer/core";
5
+ export { isRegexTemplate } from "@regex-designer/core";
6
+ function patternString(pattern, flags, compiling) {
7
+ if (pattern instanceof RegExp) {
8
+ const unicodeFlag = pattern.flags.includes("v") ? "v" : pattern.flags.includes("u") ? "u" : undefined;
9
+ if (compiling && unicodeFlag !== undefined && !flags?.includes(unicodeFlag)) {
10
+ throw new TypeError(`RegExp flag "${unicodeFlag}" must be passed when compiling the composed pattern`);
11
+ }
12
+ const scopedFlags = pattern.flags.replace(/[dgyuv]/g, "");
13
+ return scopedFlags === "" ? pattern.source : `(?${scopedFlags}:${pattern.source})`;
14
+ }
15
+ if (isRegexTemplate(pattern)) {
16
+ return pattern.render(flags, compiling);
17
+ }
18
+ return pattern.toString();
19
+ }
20
+ function template(render) {
21
+ const regex = (flags) => new RegExp(regex.render(flags, true), flags);
22
+ regex.render = (flags, compiling = false) => render(flags, compiling);
23
+ regex.toString = () => regex.render();
24
+ return regex;
25
+ }
26
+ function tpl(...patterns) {
27
+ return template((flags, compiling) => patterns.map(pattern => patternString(pattern, flags, compiling)).join(""));
28
+ }
29
+ function or(...patterns) {
30
+ return template((flags, compiling) => patterns.map(pattern => patternString(pattern, flags, compiling)).join("|"));
31
+ }
32
+ function group(options, ...patterns) {
33
+ if (typeof options !== "boolean" && options.name !== undefined && options.capture !== undefined) {
34
+ throw new TypeError("Group options \"name\" and \"capture\" are mutually exclusive");
35
+ }
36
+ return template((flags, compiling) => {
37
+ const name = typeof options === "boolean" ? undefined : options.name;
38
+ const capture = typeof options === "boolean" ? options : options.capture ?? true;
39
+ const prefix = name !== undefined ? `?<${name}>` : capture ? "" : "?:";
40
+ return `(${prefix}${patterns.map(pattern => patternString(pattern, flags, compiling)).join("")})`;
41
+ });
42
+ }
43
+ function anchor(start, end, patterns) {
44
+ return template((flags, compiling) => `${start ? "^" : ""}${patternString(group(false, ...patterns), flags, compiling)}${end ? "$" : ""}`);
45
+ }
46
+ function named(name, ...patterns) {
47
+ return group({ name }, ...patterns);
48
+ }
49
+ function opt(...patterns) {
50
+ return template((flags, compiling) => `${patternString(group(false, ...patterns), flags, compiling)}?`);
51
+ }
52
+ function qty(quantity, ...patterns) {
53
+ let min;
54
+ let max;
55
+ let greedy = true;
56
+ if (typeof quantity === "number") {
57
+ min = quantity;
58
+ max = quantity;
59
+ }
60
+ else if (Array.isArray(quantity)) {
61
+ [min, max] = quantity;
62
+ }
63
+ else if ("exact" in quantity) {
64
+ min = quantity.exact;
65
+ max = quantity.exact;
66
+ greedy = quantity.greedy ?? true;
67
+ }
68
+ else {
69
+ min = quantity.min;
70
+ max = quantity.max;
71
+ greedy = quantity.greedy ?? true;
72
+ }
73
+ if (!Number.isInteger(min) || min < 0 || (max !== undefined && max !== Infinity && (!Number.isInteger(max) || max < min))) {
74
+ throw new RangeError("Quantity bounds must be non-negative integers with max >= min");
75
+ }
76
+ return template((flags, compiling) => `${patternString(group(false, ...patterns), flags, compiling)}{${min}${max === undefined || max === Infinity ? "," : max === min ? "" : `,${max}`}}${greedy ? "" : "?"}`);
77
+ }
78
+ function look(prefix, positive, patterns) {
79
+ return template((flags, compiling) => `(${prefix}${positive ? "=" : "!"}${patterns.map(pattern => patternString(pattern, flags, compiling)).join("")})`);
80
+ }
81
+ function raw(...patterns) {
82
+ return template(() => patterns.map(p => RegExp.escape(p)).join(""));
83
+ }
84
+ /**
85
+ * Create a new JavaScript regex designer with its own variable scope.
86
+ * @readme default
87
+ */
88
+ export default function create() {
89
+ return new JSRegexDesigner();
90
+ }
91
+ /**
92
+ * Templates are compiled to a native `RegExp`.
93
+ */
94
+ export class JSRegexDesigner extends RegexDesigner {
95
+ createTemplate(render) {
96
+ return template(render);
97
+ }
98
+ /** Concatenate patterns without adding groups or escaping. */
99
+ tpl(...patterns) {
100
+ return tpl(...patterns);
101
+ }
102
+ /** Escape literal text for use in a regex pattern. */
103
+ raw(...patterns) {
104
+ return raw(...patterns);
105
+ }
106
+ /** Match the concatenated patterns at the start of the input. */
107
+ start(...patterns) {
108
+ return anchor(true, false, patterns);
109
+ }
110
+ /** Match the concatenated patterns at the end of the input. */
111
+ end(...patterns) {
112
+ return anchor(false, true, patterns);
113
+ }
114
+ /** Match the concatenated patterns across the whole input. */
115
+ whole(...patterns) {
116
+ return anchor(true, true, patterns);
117
+ }
118
+ /** Group patterns, optionally capturing them or assigning a capture name. */
119
+ group(options, ...patterns) {
120
+ return group(options, ...patterns);
121
+ }
122
+ /** Create a named capturing group around the concatenated patterns. */
123
+ named(name, ...patterns) {
124
+ return named(name, ...patterns);
125
+ }
126
+ /** Create a numeric or named backreference. */
127
+ ref(reference) {
128
+ return template(() => typeof reference === "number" ? `\\${reference}` : `\\k<${reference}>`);
129
+ }
130
+ /** Make the concatenated patterns optional using a non-capturing group. */
131
+ opt(...patterns) {
132
+ return opt(...patterns);
133
+ }
134
+ /** Repeat the concatenated patterns according to the supplied bounds. */
135
+ qty(quantity, ...patterns) {
136
+ return qty(quantity, ...patterns);
137
+ }
138
+ /** Join patterns with alternation without adding groups. */
139
+ or(...patterns) {
140
+ return or(...patterns);
141
+ }
142
+ /** Create a positive or negative [lookahead assertion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Lookahead_assertion). */
143
+ ahead(positive, ...patterns) {
144
+ return look("?", positive, patterns);
145
+ }
146
+ /** Create a positive [lookahead assertion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Lookahead_assertion). */
147
+ ahead_pos(...patterns) {
148
+ return look("?", true, patterns);
149
+ }
150
+ /** Create a negative [lookahead assertion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Lookahead_assertion). */
151
+ ahead_neg(...patterns) {
152
+ return look("?", false, patterns);
153
+ }
154
+ /** Create a positive or negative [lookbehind assertion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Lookbehind_assertion). */
155
+ behind(positive, ...patterns) {
156
+ return look("?<", positive, patterns);
157
+ }
158
+ /** Create a positive [lookbehind assertion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Lookbehind_assertion). */
159
+ behind_pos(...patterns) {
160
+ return look("?<", true, patterns);
161
+ }
162
+ /** Create a negative [lookbehind assertion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Lookbehind_assertion). */
163
+ behind_neg(...patterns) {
164
+ return look("?<", false, patterns);
165
+ }
166
+ }
167
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,36 @@
1
1
  {
2
2
  "name": "@regex-designer/js",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.2.0",
4
+ "description": "A small TypeScript library for composing JavaScript regular expressions in a readable, reusable way.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "regex",
9
+ "regexp",
10
+ "pattern",
11
+ "builder"
12
+ ],
13
+ "engines": {
14
+ "node": ">=24.0.0"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "types": "./dist/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "import": "./dist/index.js"
24
+ }
25
+ },
26
+ "sideEffects": false,
27
+ "dependencies": {
28
+ "@regex-designer/core": "0.2.0"
29
+ },
30
+ "scripts": {
31
+ "build": "tsc -p tsconfig.json",
32
+ "lint": "eslint --config ../../eslint.config.* .",
33
+ "test": "npm run build && tsc -p tsconfig.test.json && node --test test/*.test.ts",
34
+ "check": "npm run lint && npm run test"
35
+ }
36
+ }