diff --git a/packages/router-core/src/path.ts b/packages/router-core/src/path.ts index da410e9c7d..f0be7df53c 100644 --- a/packages/router-core/src/path.ts +++ b/packages/router-core/src/path.ts @@ -1,4 +1,3 @@ -import { isServer } from '@tanstack/router-core/isServer' import { last } from './utils' import { SEGMENT_TYPE_OPTIONAL_PARAM, @@ -254,73 +253,84 @@ export function interpolatePath({ // declaration doesn't reference a property that no longer exists. ...rest }: InterpolatePathOptions): InterPolatePathResult { + void rest // Tracking if any params are missing in the `params` object // when interpolating the path let isMissingParams = false const usedParams: Record = Object.create(null) - if (!path || path === '/') + if (!path || path === '/') { return { interpolatedPath: '/', usedParams, isMissingParams } - if (!path.includes('$')) + } + if (!path.includes('$')) { return { interpolatedPath: path, usedParams, isMissingParams } + } + + // Fast path for common templates like `/posts/$id` or `/files/$`. + // Braced segments (`{...}`) are more complex (prefix/suffix/optional) and are + // handled by the general parser below. + if (path.indexOf('{') === -1) { + const length = path.length + let cursor = 0 + let joined = '' + + while (cursor < length) { + // Skip slashes between segments. '/' code is 47 + while (cursor < length && path.charCodeAt(cursor) === 47) { + cursor++ + } + if (cursor >= length) { + break + } - if (isServer ?? rest.server) { - // Fast path for common templates like `/posts/$id` or `/files/$`. - // Braced segments (`{...}`) are more complex (prefix/suffix/optional) and are - // handled by the general parser below. - if (path.indexOf('{') === -1) { - const length = path.length - let cursor = 0 - let joined = '' - - while (cursor < length) { - // Skip slashes between segments. '/' code is 47 - while (cursor < length && path.charCodeAt(cursor) === 47) cursor++ - if (cursor >= length) break - - const start = cursor - let end = path.indexOf('/', cursor) - if (end === -1) end = length - cursor = end - - const part = path.substring(start, end) - if (!part) continue - - // `$id` or `$` (splat). '$' code is 36 - if (part.charCodeAt(0) === 36) { - if (part.length === 1) { - const splat = params._splat - usedParams._splat = splat - // TODO: Deprecate * - usedParams['*'] = splat - - if (!splat) { - isMissingParams = true - continue - } - - const value = encodeParam('_splat', params, decoder) - joined += '/' + value - } else { - const key = part.substring(1) - if (!isMissingParams && !(key in params)) { - isMissingParams = true - } - usedParams[key] = params[key] - - const value = encodeParam(key, params, decoder) ?? 'undefined' - joined += '/' + value + const start = cursor + let end = path.indexOf('/', cursor) + if (end === -1) { + end = length + } + cursor = end + + const part = path.substring(start, end) + if (!part) { + continue + } + + // `$id` or `$` (splat). '$' code is 36 + if (part.charCodeAt(0) === 36) { + if (part.length === 1) { + const splat = params._splat + usedParams._splat = splat + // TODO: Deprecate * + usedParams['*'] = splat + + if (!splat) { + isMissingParams = true + continue } + + const value = encodeParam('_splat', params, decoder) + joined += '/' + value } else { - joined += '/' + part + const key = part.substring(1) + if (!isMissingParams && !(key in params)) { + isMissingParams = true + } + usedParams[key] = params[key] + + const value = encodeParam(key, params, decoder) ?? 'undefined' + joined += '/' + value } + } else { + joined += '/' + part } + } - if (path.endsWith('/')) joined += '/' - - const interpolatedPath = joined || '/' - return { usedParams, interpolatedPath, isMissingParams } + if (path.endsWith('/')) { + joined += '/' } + + const interpolatedPath = joined || '/' + return { usedParams, interpolatedPath, isMissingParams } } const length = path.length