Skip to content

Commit 425266f

Browse files
committed
Default noop encode/decode, use ID start/continue
1 parent afd1402 commit 425266f

File tree

2 files changed

+38
-33
lines changed

2 files changed

+38
-33
lines changed

src/index.spec.ts

+14-9
Original file line numberDiff line numberDiff line change
@@ -172,13 +172,13 @@ const TESTS: Test[] = [
172172
[
173173
"/caf%C3%A9",
174174
["/caf%C3%A9", "caf%C3%A9"],
175-
{ path: "/caf%C3%A9", index: 0, params: { test: "café" } },
175+
{ path: "/caf%C3%A9", index: 0, params: { test: "caf%C3%A9" } },
176176
],
177177
],
178178
[
179179
[{}, null],
180180
[{ test: "abc" }, "/abc"],
181-
[{ test: "a+b" }, "/a+b", { encode: (x) => x }],
181+
[{ test: "a+b" }, "/a+b"],
182182
[{ test: "a+b" }, "/test", { encode: () => "test" }],
183183
[{ test: "a+b" }, "/a%2Bb", { encode: encodeURIComponent }],
184184
],
@@ -272,7 +272,7 @@ const TESTS: Test[] = [
272272
[
273273
[{}, null],
274274
[{ test: "abc" }, "/abc"],
275-
[{ test: "a+b" }, "/a+b", { encode: (x) => x }],
275+
[{ test: "a+b" }, "/a+b"],
276276
[{ test: "a+b" }, "/test", { encode: () => "test" }],
277277
[{ test: "a+b" }, "/a%2Bb", { encode: encodeURIComponent }],
278278
],
@@ -1034,8 +1034,13 @@ const TESTS: Test[] = [
10341034
[
10351035
[{ test: "" }, "/"],
10361036
[{ test: "abc" }, "/abc"],
1037-
[{ test: "abc/123" }, "/abc%2F123"],
1038-
[{ test: "abc/123/456" }, "/abc%2F123%2F456"],
1037+
[{ test: "abc/123" }, "/abc/123"],
1038+
[{ test: "abc/123" }, "/abc%2F123", { encode: encodeURIComponent }],
1039+
[
1040+
{ test: "abc/123/456" },
1041+
"/abc%2F123%2F456",
1042+
{ encode: encodeURIComponent },
1043+
],
10391044
],
10401045
],
10411046
[
@@ -1639,7 +1644,7 @@ const TESTS: Test[] = [
16391644
")",
16401645
],
16411646
[["/route(\\123\\)", ["/route(\\123\\)", "123\\"]]],
1642-
[[["123\\"], "/route(\\123\\)", { encode: (x) => x }]],
1647+
[[["123\\"], "/route(\\123\\)"]],
16431648
],
16441649
[
16451650
"{/login}?",
@@ -2281,8 +2286,8 @@ const TESTS: Test[] = [
22812286
],
22822287
[["/café", ["/café", "café"]]],
22832288
[
2284-
[{ foo: "café" }, "/café", { encode: (x) => x }],
2285-
[{ foo: "café" }, "/caf%C3%A9"],
2289+
[{ foo: "café" }, "/café"],
2290+
[{ foo: "café" }, "/caf%C3%A9", { encode: encodeURIComponent }],
22862291
],
22872292
],
22882293
[
@@ -2792,7 +2797,7 @@ describe("path-to-regexp", () => {
27922797
it("should throw on missing name", () => {
27932798
expect(() => {
27942799
pathToRegexp.pathToRegexp("/:(test)");
2795-
}).toThrow(new TypeError("Missing parameter name at 1"));
2800+
}).toThrow(new TypeError("Missing parameter name at 2"));
27962801
});
27972802

27982803
it("should throw on nested groups", () => {

src/index.ts

+24-24
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ const DEFAULT_PREFIXES = "./";
22
const DEFAULT_DELIMITER = "/";
33
const GROUPS_RE = /\((?:\?<(.*?)>)?(?!\?)/g;
44
const NOOP_VALUE = (value: string) => value;
5-
const NAME_RE = /^[\p{L}\p{Nl}\p{Mn}\p{Mc}\p{Nd}\p{Pc}$]$/u;
5+
const ID_START = /^[$_\p{ID_Start}]$/u;
6+
const ID_CONTINUE = /^[$_\u200C\u200D\p{ID_Continue}]$/u;
67

78
/**
89
* Encode a string into another string.
@@ -133,56 +134,55 @@ function lexer(str: string) {
133134
}
134135

135136
if (char === ":") {
136-
let name = "";
137-
let j = i + 1;
137+
let name = chars[++i];
138138

139-
while (NAME_RE.test(chars[j])) {
140-
name += chars[j++];
139+
if (!ID_START.test(chars[i])) {
140+
throw new TypeError(`Missing parameter name at ${i}`);
141141
}
142142

143-
if (!name) throw new TypeError(`Missing parameter name at ${i}`);
143+
while (ID_CONTINUE.test(chars[++i])) {
144+
name += chars[i];
145+
}
144146

145147
tokens.push({ type: "NAME", index: i, value: name });
146-
i = j;
147148
continue;
148149
}
149150

150151
if (char === "(") {
152+
const pos = i++;
151153
let count = 1;
152154
let pattern = "";
153-
let j = i + 1;
154155

155-
if (chars[j] === "?") {
156-
throw new TypeError(`Pattern cannot start with "?" at ${j}`);
156+
if (chars[i] === "?") {
157+
throw new TypeError(`Pattern cannot start with "?" at ${i}`);
157158
}
158159

159-
while (j < chars.length) {
160-
if (chars[j] === "\\") {
161-
pattern += chars[j++] + chars[j++];
160+
while (i < chars.length) {
161+
if (chars[i] === "\\") {
162+
pattern += chars[i++] + chars[i++];
162163
continue;
163164
}
164165

165-
if (chars[j] === ")") {
166+
if (chars[i] === ")") {
166167
count--;
167168
if (count === 0) {
168-
j++;
169+
i++;
169170
break;
170171
}
171-
} else if (chars[j] === "(") {
172+
} else if (chars[i] === "(") {
172173
count++;
173-
if (chars[j + 1] !== "?") {
174-
throw new TypeError(`Capturing groups are not allowed at ${j}`);
174+
if (chars[i + 1] !== "?") {
175+
throw new TypeError(`Capturing groups are not allowed at ${i}`);
175176
}
176177
}
177178

178-
pattern += chars[j++];
179+
pattern += chars[i++];
179180
}
180181

181-
if (count) throw new TypeError(`Unbalanced pattern at ${i}`);
182-
if (!pattern) throw new TypeError(`Missing pattern at ${i}`);
182+
if (count) throw new TypeError(`Unbalanced pattern at ${pos}`);
183+
if (!pattern) throw new TypeError(`Missing pattern at ${pos}`);
183184

184185
tokens.push({ type: "PATTERN", index: i, value: pattern });
185-
i = j;
186186
continue;
187187
}
188188

@@ -440,7 +440,7 @@ function compileTokens<P extends ParamData>(
440440
options: CompileOptions,
441441
): PathFunction<P> {
442442
const {
443-
encode = encodeURIComponent,
443+
encode = NOOP_VALUE,
444444
validate = true,
445445
loose = DEFAULT_DELIMITER,
446446
} = options;
@@ -514,7 +514,7 @@ function matchRegexp<P extends ParamData>(
514514
keys: Key[],
515515
options: MatchOptions,
516516
): MatchFunction<P> {
517-
const { decode = decodeURIComponent, loose = DEFAULT_DELIMITER } = options;
517+
const { decode = NOOP_VALUE, loose = DEFAULT_DELIMITER } = options;
518518
const stringify = toStringify(loose);
519519

520520
const decoders = keys.map((key) => {

0 commit comments

Comments
 (0)