Skip to content

Commit c909d1f

Browse files
committed
Stringify names with unsafe text chars after
1 parent e537daa commit c909d1f

File tree

2 files changed

+35
-13
lines changed

2 files changed

+35
-13
lines changed

src/cases.spec.ts

+16
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@ export const PARSER_TESTS: ParserTestSet[] = [
9292
{ type: "wildcard", name: "path" },
9393
]),
9494
},
95+
{
96+
path: '/:"test"stuff',
97+
expected: new TokenData([
98+
{ type: "text", value: "/" },
99+
{ type: "param", name: "test" },
100+
{ type: "text", value: "stuff" },
101+
]),
102+
},
95103
];
96104

97105
export const STRINGIFY_TESTS: StringifyTestSet[] = [
@@ -152,6 +160,14 @@ export const STRINGIFY_TESTS: StringifyTestSet[] = [
152160
data: new TokenData([{ type: "text", value: "/:+?*" }]),
153161
expected: "/\\:\\+\\?\\*",
154162
},
163+
{
164+
data: new TokenData([
165+
{ type: "text", value: "/" },
166+
{ type: "param", name: "test" },
167+
{ type: "text", value: "stuff" },
168+
]),
169+
expected: '/:"test"stuff',
170+
},
155171
];
156172

157173
export const COMPILE_TESTS: CompileTestSet[] = [

src/index.ts

+19-13
Original file line numberDiff line numberDiff line change
@@ -607,25 +607,31 @@ function negate(delimiter: string, backtrack: string) {
607607
* Stringify token data into a path string.
608608
*/
609609
export function stringify(data: TokenData) {
610-
return data.tokens.map(stringifyToken).join("");
611-
}
612-
613-
function stringifyToken(token: Token): string {
614-
if (token.type === "text") return escapeText(token.value);
615-
if (token.type === "group") {
616-
return `{${token.tokens.map(stringifyToken).join("")}}`;
617-
}
610+
return data.tokens
611+
.map(function stringifyToken(token, index, tokens): string {
612+
if (token.type === "text") return escapeText(token.value);
613+
if (token.type === "group") {
614+
return `{${token.tokens.map(stringifyToken).join("")}}`;
615+
}
618616

619-
const isSafe = isNameSafe(token.name);
620-
const key = isSafe ? token.name : JSON.stringify(token.name);
617+
const isSafe =
618+
isNameSafe(token.name) && isNextNameSafe(tokens[index + 1]);
619+
const key = isSafe ? token.name : JSON.stringify(token.name);
621620

622-
if (token.type === "param") return `:${key}`;
623-
if (token.type === "wildcard") return `*${key}`;
624-
throw new TypeError(`Unexpected token: ${token}`);
621+
if (token.type === "param") return `:${key}`;
622+
if (token.type === "wildcard") return `*${key}`;
623+
throw new TypeError(`Unexpected token: ${token}`);
624+
})
625+
.join("");
625626
}
626627

627628
function isNameSafe(name: string) {
628629
const [first, ...rest] = name;
629630
if (!ID_START.test(first)) return false;
630631
return rest.every((char) => ID_CONTINUE.test(char));
631632
}
633+
634+
function isNextNameSafe(token: Token | undefined) {
635+
if (token?.type !== "text") return true;
636+
return !ID_CONTINUE.test(token.value[0]);
637+
}

0 commit comments

Comments
 (0)