diff --git a/packages/router-core/src/path.ts b/packages/router-core/src/path.ts index 88b489d8aa..3c1bc4db7a 100644 --- a/packages/router-core/src/path.ts +++ b/packages/router-core/src/path.ts @@ -208,8 +208,10 @@ export function resolvePath({ interface InterpolatePathOptions { path?: string params: Record - // Map of encoded chars to decoded chars (e.g. '%40' -> '@') that should remain decoded in path params + /** Map of encoded chars to decoded chars (e.g. '%40' -> '@') that should remain decoded in path params */ decodeCharMap?: Map + /** whether to encode the interpolated params (defaults: true) */ + encode?: boolean } type InterPolatePathResult = { @@ -248,6 +250,7 @@ export function interpolatePath({ path, params, decodeCharMap, + encode = true, }: InterpolatePathOptions): InterPolatePathResult { // Tracking if any params are missing in the `params` object // when interpolating the path @@ -298,7 +301,9 @@ export function interpolatePath({ continue } - const value = encodeParam('_splat', params, decodeCharMap) + const value = encode + ? encodeParam('_splat', params, decodeCharMap) + : params._splat joined += '/' + prefix + value + suffix continue } @@ -312,7 +317,9 @@ export function interpolatePath({ const prefix = path.substring(start, segment[1]) const suffix = path.substring(segment[4], end) - const value = encodeParam(key, params, decodeCharMap) ?? 'undefined' + const value = + (encode ? encodeParam(key, params, decodeCharMap) : params[key]) ?? + 'undefined' joined += '/' + prefix + value + suffix continue } @@ -335,7 +342,8 @@ export function interpolatePath({ usedParams[key] = valueRaw - const value = encodeParam(key, params, decodeCharMap) ?? '' + const value = + (encode ? encodeParam(key, params, decodeCharMap) : params[key]) ?? '' joined += '/' + prefix + value + suffix continue } diff --git a/packages/router-core/src/router.ts b/packages/router-core/src/router.ts index e0f6246eab..3c3c10f8ac 100644 --- a/packages/router-core/src/router.ts +++ b/packages/router-core/src/router.ts @@ -1184,7 +1184,7 @@ export class RouterCore< pathname: decodePath(pathname), searchStr, search: replaceEqualDeep(previousLocation?.search, parsedSearch) as any, - hash: hash.split('#').reverse()[0] ?? '', + hash: last(hash.split('#')) ?? '', state: replaceEqualDeep(previousLocation?.state, state), } } @@ -1681,13 +1681,11 @@ export class RouterCore< ? // Use the original template path for interpolation // This preserves the original parameter syntax including optional parameters nextTo - : decodePath( - interpolatePath({ - path: nextTo, - params: nextParams, - decodeCharMap: this.pathParamsDecodeCharMap, - }).interpolatedPath, - ) + : interpolatePath({ + path: nextTo, + params: nextParams, + encode: false, + }).interpolatedPath // Resolve the next search let nextSearch = fromSearch