diff --git a/.changeset/rich-walls-doubt.md b/.changeset/rich-walls-doubt.md new file mode 100644 index 000000000000..c56fd899fea4 --- /dev/null +++ b/.changeset/rich-walls-doubt.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +Fix pattern matching for routes starting with an encoded `@` symbol diff --git a/packages/kit/src/utils/routing.js b/packages/kit/src/utils/routing.js index fb6d219ad4fb..826c75a4d602 100644 --- a/packages/kit/src/utils/routing.js +++ b/packages/kit/src/utils/routing.js @@ -16,11 +16,12 @@ export function parse_route_id(id) { id === '' ? /^\/$/ : new RegExp( - `^${decodeURIComponent(id) + `^${id .split(/(?:@[a-zA-Z0-9_-]+)?(?:\/|$)/) .map((segment, i, segments) => { + const decoded_segment = decodeURIComponent(segment); // special case — /[...rest]/ could contain zero segments - const match = /^\[\.\.\.(\w+)(?:=(\w+))?\]$/.exec(segment); + const match = /^\[\.\.\.(\w+)(?:=(\w+))?\]$/.exec(decoded_segment); if (match) { names.push(match[1]); types.push(match[2]); @@ -30,9 +31,9 @@ export function parse_route_id(id) { const is_last = i === segments.length - 1; return ( - segment && + decoded_segment && '/' + - segment + decoded_segment .split(/\[(.+?)\]/) .map((content, i) => { if (i % 2) { diff --git a/packages/kit/src/utils/routing.spec.js b/packages/kit/src/utils/routing.spec.js index dd14241c0e23..3c14ce927936 100644 --- a/packages/kit/src/utils/routing.spec.js +++ b/packages/kit/src/utils/routing.spec.js @@ -42,6 +42,16 @@ const tests = { pattern: /^\/matched\/([^/]+?)\/?$/, names: ['id'], types: ['uuid'] + }, + '%23hash-encoded': { + pattern: /^\/%23hash-encoded\/?$/, + names: [], + types: [] + }, + '%40at-encoded/[id]': { + pattern: /^\/@at-encoded\/([^/]+?)\/?$/, + names: ['id'], + types: [undefined] } };