Skip to content

Commit cb58300

Browse files
committed
emit smaller regexp
1 parent ceab366 commit cb58300

4 files changed

Lines changed: 14 additions & 11 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,4 @@ type T = InferParams<'/book{s/:id}?'>; // { id: string | undefined }
6262
```
6363

6464
## Compability
65-
This library requires [`RegExp.escape()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/escape#browser_compatibility) and [duplicate named capture groups in different disjunction feature](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Named_capturing_group#browser_compatibility) support.
65+
This library requires RegExp [duplicate named capture groups in different disjunction feature](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Named_capturing_group#browser_compatibility) support.

snapshots/complex api.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
return 'POST /admin/impersonate';
3333
}
3434
let r =
35-
/^(?:\/(?:\x75ser(?:\/notifications\/(?<notification>[^/]+)\/read()$|\/(?<user>[^/]+)(?:()$|\/invites(?:()$|\/(?<invite>[^/]+)\/(?:\x61ccept()$|\x72esend()$))))|\x6frg\/(?<org>[^/]+)\/(?:\x6dembers(?:()$|\/(?<member>[^/]+)()$)|\x72oles(?:()$|\/(?<role>[^/]+)()$)|\x64omains(?:()$|\/(?<domain>[^/]+)()$)|\x70rojects(?:()$|\/(?<project>[^/]+)\/(?:\x6dembers()$|\x74asks(?:()$|\/(?:\x74(?:\x69me\x2dentries(?:()$|\/(?<entry>[^/]+)()$)|\x61gs()$)|\x61ttachments()$))))|\x74asks\/(?<task>[^/]+)\/(?:\x61(?:\x73sign()$|\x74tachments()$)|\x73tatus()$|\x63omments()$|\x74(?:\x69me\x2dentries(?:()$|\/(?<entry>[^/]+)\/stop()$)|\x61gs()$))|\x62illing\/(?:\x73ubscription(?:()$|\/cancel()$)|\x69nvoices\/(?<invoice>[^/]+)()$|\x70ayment\x2dmethods()$)|\x61pi\x2dkeys()$|\x77ebhooks()$))|$.)/.exec(
35+
/^(?:\/(?:user(?:\/notifications\/(?<notification>[^/]+)\/read()$|\/(?<user>[^/]+)(?:()$|\/invites(?:()$|\/(?<invite>[^/]+)\/(?:accept()$|resend()$))))|org\/(?<org>[^/]+)\/(?:members(?:()$|\/(?<member>[^/]+)()$)|roles(?:()$|\/(?<role>[^/]+)()$)|domains(?:()$|\/(?<domain>[^/]+)()$)|projects(?:()$|\/(?<project>[^/]+)\/(?:members()$|tasks(?:()$|\/(?:t(?:ime-entries(?:()$|\/(?<entry>[^/]+)()$)|ags()$)|attachments()$))))|tasks\/(?<task>[^/]+)\/(?:a(?:ssign()$|ttachments()$)|status()$|comments()$|t(?:ime-entries(?:()$|\/(?<entry>[^/]+)\/stop()$)|ags()$))|billing\/(?:subscription(?:()$|\/cancel()$)|invoices\/(?<invoice>[^/]+)()$|payment-methods()$)|api-keys()$|webhooks()$))|$.)/.exec(
3636
p,
3737
);
3838
if (r !== null) {
@@ -131,7 +131,7 @@
131131
return 'GET /admin/stats';
132132
}
133133
let r =
134-
/^(?:\/(?:\x75ser\/(?<user>[^/]+)(?:()$|\/(?:\x6eotifications()$|\x69nvites\/(?<invite>[^/]+)()$))|\x6frg\/(?<org>[^/]+)(?:()$|\/(?:\x6dembers()$|\x72oles()$|\x64omains()$|\x70rojects\/(?<project>[^/]+)(?:()$|\/(?:\x6dembers()$|\x61ctivity()$|\x74asks(?:()$|\/(?:\x74ime\x2dentries()$|\x61ttachments()$))))|\x74asks(?:()$|\/(?<task>[^/]+)(?:()$|\/(?:\x63omments()$|\x74ime\x2dentries()$|\x61ttachments()$)))|\x62illing\/(?:\x70(?:\x6cans()$|\x61yment\x2dmethods()$)|\x73ubscription()$|\x69nvoices(?:()$|\/(?<invoice>[^/]+)()$))|\x61pi\x2dkeys()$|\x77ebhooks(?:()$|\/(?<hook>[^/]+)\/deliveries(?:()$|\/(?<delivery>[^/]+)()$))))|\x66iles\/(?<file>.+)()$|\x61dmin\/reports\/(?:\x70rojects\/(?<project>[^/]+)\/summary()$|\x75sers\/(?<user>[^/]+)\/activity()$))|$.)/.exec(
134+
/^(?:\/(?:user\/(?<user>[^/]+)(?:()$|\/(?:notifications()$|invites\/(?<invite>[^/]+)()$))|org\/(?<org>[^/]+)(?:()$|\/(?:members()$|roles()$|domains()$|projects\/(?<project>[^/]+)(?:()$|\/(?:members()$|activity()$|tasks(?:()$|\/(?:time-entries()$|attachments()$))))|tasks(?:()$|\/(?<task>[^/]+)(?:()$|\/(?:comments()$|time-entries()$|attachments()$)))|billing\/(?:p(?:lans()$|ayment-methods()$)|subscription()$|invoices(?:()$|\/(?<invoice>[^/]+)()$))|api-keys()$|webhooks(?:()$|\/(?<hook>[^/]+)\/deliveries(?:()$|\/(?<delivery>[^/]+)()$))))|files\/(?<file>.+)()$|admin\/reports\/(?:projects\/(?<project>[^/]+)\/summary()$|users\/(?<user>[^/]+)\/activity()$))|$.)/.exec(
135135
p,
136136
);
137137
if (r !== null) {
@@ -202,7 +202,7 @@
202202
return 'PATCH /user/me/preferences';
203203
}
204204
let r =
205-
/^(?:\/(?:\x6frg\/(?<org>[^/]+)(?:()$|\/(?:\x70rojects\/(?<project>[^/]+)()$|\x74asks\/(?<task>[^/]+)()$|\x77ebhooks\/(?<hook>[^/]+)()$))|\x73earch\/filters\/(?<filter>[^/]+)()$|\x74ags\/(?<tag>[^/]+)()$)|$.)/.exec(
205+
/^(?:\/(?:org\/(?<org>[^/]+)(?:()$|\/(?:projects\/(?<project>[^/]+)()$|tasks\/(?<task>[^/]+)()$|webhooks\/(?<hook>[^/]+)()$))|search\/filters\/(?<filter>[^/]+)()$|tags\/(?<tag>[^/]+)()$)|$.)/.exec(
206206
p,
207207
);
208208
if (r !== null) {
@@ -222,7 +222,7 @@
222222
}
223223
} else if (m === 'DELETE') {
224224
let r =
225-
/^(?:\/(?:\x75ser\/me\/sessions\/(?<session>[^/]+)()$|\x6frg\/(?<org>[^/]+)(?:()$|\/(?:\x70rojects\/(?<project>[^/]+)(?:()$|\/tasks\/(?:\x74ags()$|\x66ields\/(?<field>[^/]+)()$))|\x74asks\/(?<task>[^/]+)(?:()$|\/(?:\x74ags()$|\x66ields\/(?<field>[^/]+)()$))|\x62illing\/payment\x2dmethods\/(?<method>[^/]+)()$|\x61pi\x2dkeys\/(?<key>[^/]+)()$|\x77ebhooks\/(?<hook>[^/]+)()$))|\x66iles\/(?<file>.+)()$|\x73earch\/filters\/(?<filter>[^/]+)()$|\x74ags\/(?<tag>[^/]+)()$)|$.)/.exec(
225+
/^(?:\/(?:user\/me\/sessions\/(?<session>[^/]+)()$|org\/(?<org>[^/]+)(?:()$|\/(?:projects\/(?<project>[^/]+)(?:()$|\/tasks\/(?:tags()$|fields\/(?<field>[^/]+)()$))|tasks\/(?<task>[^/]+)(?:()$|\/(?:tags()$|fields\/(?<field>[^/]+)()$))|billing\/payment-methods\/(?<method>[^/]+)()$|api-keys\/(?<key>[^/]+)()$|webhooks\/(?<hook>[^/]+)()$))|files\/(?<file>.+)()$|search\/filters\/(?<filter>[^/]+)()$|tags\/(?<tag>[^/]+)()$)|$.)/.exec(
226226
p,
227227
);
228228
if (r !== null) {
@@ -258,7 +258,7 @@
258258
}
259259
} else if (m === 'PUT') {
260260
let r =
261-
/^(?:\/org\/(?<org>[^/]+)\/(?:\x70rojects\/(?<project>[^/]+)\/tasks\/fields\/(?<field>[^/]+)()$|\x74asks\/(?<task>[^/]+)\/fields\/(?<field>[^/]+)()$)|$.)/.exec(
261+
/^(?:\/org\/(?<org>[^/]+)\/(?:projects\/(?<project>[^/]+)\/tasks\/fields\/(?<field>[^/]+)()$|tasks\/(?<task>[^/]+)\/fields\/(?<field>[^/]+)()$)|$.)/.exec(
262262
p,
263263
);
264264
if (r !== null) {

snapshots/simple api.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
return 'GET /very/deeply/nested/route/hello/there';
1313
}
1414
let r =
15-
/^(?:\/(?:\x75ser\/lookup\/(?:\x75sername\/(?<username>[^/]+)()$|\x65mail\/(?<email>[^/]+)()$)|\x65vent\/(?<event>[^/]+)(?:()$|\/comments()$)|\x6dap\/(?<location>[^/]+)\/events()$|\x73tatic\/(?<file>.+)()$)|$.)/.exec(
15+
/^(?:\/(?:user\/lookup\/(?:username\/(?<username>[^/]+)()$|email\/(?<email>[^/]+)()$)|event\/(?<event>[^/]+)(?:()$|\/comments()$)|map\/(?<location>[^/]+)\/events()$|static\/(?<file>.+)()$)|$.)/.exec(
1616
p,
1717
);
1818
if (r !== null) {

src/tree/regex.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import { findNamedGroupEnd, findUnnamedGroupEnd, isModifier } from './utils.ts';
33

44
export type Handlers<T> = (T | null)[];
55

6+
export const escapeStaticPart = (str: string): string =>
7+
str.replace(/([.+*?^${}()[\]|/\\])/g, '\\$1');
8+
69
export const parseNamedGroup = (key: string, curIdx: number, endIdx: number): string => {
710
let autoGroupPrefixing = key[curIdx] === '/',
811
startIdx = curIdx + (autoGroupPrefixing ? 2 : 1);
@@ -101,7 +104,7 @@ export const node_compile_to_regexp = (node: Node<unknown>): string => {
101104
const patternRegexEnd = findUnnamedGroupEnd(pattern, patternIdx + 1);
102105

103106
parts +=
104-
RegExp.escape(pattern.slice(patternPrevIdx, patternIdx)) +
107+
escapeStaticPart(pattern.slice(patternPrevIdx, patternIdx)) +
105108
'(?:' +
106109
pattern.slice(patternIdx + 1, patternRegexEnd);
107110

@@ -114,7 +117,7 @@ export const node_compile_to_regexp = (node: Node<unknown>): string => {
114117

115118
HANDLERS.push(null);
116119
parts +=
117-
RegExp.escape(pattern.slice(patternPrevIdx, patternIdx)) +
120+
escapeStaticPart(pattern.slice(patternPrevIdx, patternIdx)) +
118121
parseNamedGroup(pattern, patternIdx, groupEndIdx);
119122

120123
patternPrevIdx = patternIdx = groupEndIdx + 1;
@@ -125,7 +128,7 @@ export const node_compile_to_regexp = (node: Node<unknown>): string => {
125128
patternIdx++;
126129
}
127130
parts +=
128-
RegExp.escape(pattern.slice(patternPrevIdx, patternLen)) +
131+
escapeStaticPart(pattern.slice(patternPrevIdx, patternLen)) +
129132
(hasModifier ? ')' + modifier : '') +
130133
connect_node_compile_to_regexp(connectNodes[i]);
131134
}
@@ -157,7 +160,7 @@ export const node_compile_to_regexp = (node: Node<unknown>): string => {
157160
}
158161

159162
parts = partsCnt > 1 ? `(?:${parts.slice(0, -1)})` : parts.slice(0, -1);
160-
return node[0].length > 0 ? RegExp.escape(node[0]) + parts : parts;
163+
return node[0].length > 0 ? escapeStaticPart(node[0]) + parts : parts;
161164
};
162165

163166
export const node_compile_root_to_regexp = (root: Node<unknown>): string =>

0 commit comments

Comments
 (0)