diff --git a/src/cases.spec.ts b/src/cases.spec.ts index 30bea83..dee3f29 100644 --- a/src/cases.spec.ts +++ b/src/cases.spec.ts @@ -92,6 +92,14 @@ export const PARSER_TESTS: ParserTestSet[] = [ { type: "wildcard", name: "path" }, ]), }, + { + path: '/:"test"stuff', + expected: new TokenData([ + { type: "text", value: "/" }, + { type: "param", name: "test" }, + { type: "text", value: "stuff" }, + ]), + }, ]; export const STRINGIFY_TESTS: StringifyTestSet[] = [ @@ -152,6 +160,14 @@ export const STRINGIFY_TESTS: StringifyTestSet[] = [ data: new TokenData([{ type: "text", value: "/:+?*" }]), expected: "/\\:\\+\\?\\*", }, + { + data: new TokenData([ + { type: "text", value: "/" }, + { type: "param", name: "test" }, + { type: "text", value: "stuff" }, + ]), + expected: '/:"test"stuff', + }, ]; export const COMPILE_TESTS: CompileTestSet[] = [ diff --git a/src/index.ts b/src/index.ts index 8daab82..2c5a088 100644 --- a/src/index.ts +++ b/src/index.ts @@ -607,21 +607,22 @@ function negate(delimiter: string, backtrack: string) { * Stringify token data into a path string. */ export function stringify(data: TokenData) { - return data.tokens.map(stringifyToken).join(""); -} - -function stringifyToken(token: Token): string { - if (token.type === "text") return escapeText(token.value); - if (token.type === "group") { - return `{${token.tokens.map(stringifyToken).join("")}}`; - } + return data.tokens + .map(function stringifyToken(token, index, tokens): string { + if (token.type === "text") return escapeText(token.value); + if (token.type === "group") { + return `{${token.tokens.map(stringifyToken).join("")}}`; + } - const isSafe = isNameSafe(token.name); - const key = isSafe ? token.name : JSON.stringify(token.name); + const isSafe = + isNameSafe(token.name) && isNextNameSafe(tokens[index + 1]); + const key = isSafe ? token.name : JSON.stringify(token.name); - if (token.type === "param") return `:${key}`; - if (token.type === "wildcard") return `*${key}`; - throw new TypeError(`Unexpected token: ${token}`); + if (token.type === "param") return `:${key}`; + if (token.type === "wildcard") return `*${key}`; + throw new TypeError(`Unexpected token: ${token}`); + }) + .join(""); } function isNameSafe(name: string) { @@ -629,3 +630,8 @@ function isNameSafe(name: string) { if (!ID_START.test(first)) return false; return rest.every((char) => ID_CONTINUE.test(char)); } + +function isNextNameSafe(token: Token | undefined) { + if (token?.type !== "text") return true; + return !ID_CONTINUE.test(token.value[0]); +}