{"version":3,"file":"path.cjs","names":[],"sources":["../../src/path.ts"],"sourcesContent":["import { isServer } from '@tanstack/router-core/isServer'\nimport { last } from './utils'\nimport {\n  SEGMENT_TYPE_OPTIONAL_PARAM,\n  SEGMENT_TYPE_PARAM,\n  SEGMENT_TYPE_PATHNAME,\n  SEGMENT_TYPE_WILDCARD,\n  parseSegment,\n} from './new-process-route-tree'\nimport type { LRUCache } from './lru-cache'\n\n/** Join path segments, cleaning duplicate slashes between parts. */\nexport function joinPaths(paths: Array<string | undefined>) {\n  return cleanPath(\n    paths\n      .filter((val) => {\n        return val !== undefined\n      })\n      .join('/'),\n  )\n}\n\n/** Remove repeated slashes from a path string. */\nexport function cleanPath(path: string) {\n  // remove double slashes\n  return path.replace(/\\/{2,}/g, '/')\n}\n\n/** Trim leading slashes (except preserving root '/'). */\nexport function trimPathLeft(path: string) {\n  return path === '/' ? path : path.replace(/^\\/{1,}/, '')\n}\n\n/** Trim trailing slashes (except preserving root '/'). */\nexport function trimPathRight(path: string) {\n  const len = path.length\n  return len > 1 && path[len - 1] === '/' ? path.replace(/\\/{1,}$/, '') : path\n}\n\n/** Trim both leading and trailing slashes. */\nexport function trimPath(path: string) {\n  return trimPathRight(trimPathLeft(path))\n}\n\n/** Remove a trailing slash from value when appropriate for comparisons. */\nexport function removeTrailingSlash(value: string, basepath: string): string {\n  if (value?.endsWith('/') && value !== '/' && value !== `${basepath}/`) {\n    return value.slice(0, -1)\n  }\n  return value\n}\n\n// intended to only compare path name\n// see the usage in the isActive under useLinkProps\n// /sample/path1 = /sample/path1/\n// /sample/path1/some <> /sample/path1\n/**\n * Compare two pathnames for exact equality after normalizing trailing slashes\n * relative to the provided `basepath`.\n */\nexport function exactPathTest(\n  pathName1: string,\n  pathName2: string,\n  basepath: string,\n): boolean {\n  return (\n    removeTrailingSlash(pathName1, basepath) ===\n    removeTrailingSlash(pathName2, basepath)\n  )\n}\n\n// When resolving relative paths, we treat all paths as if they are trailing slash\n// documents. All trailing slashes are removed after the path is resolved.\n// Here are a few examples:\n//\n// /a/b/c + ./d = /a/b/c/d\n// /a/b/c + ../d = /a/b/d\n// /a/b/c + ./d/ = /a/b/c/d\n// /a/b/c + ../d/ = /a/b/d\n// /a/b/c + ./ = /a/b/c\n//\n// Absolute paths that start with `/` short circuit the resolution process to the root\n// path.\n//\n// Here are some examples:\n//\n// /a/b/c + /d = /d\n// /a/b/c + /d/ = /d\n// /a/b/c + / = /\n//\n// Non-.-prefixed paths are still treated as relative paths, resolved like `./`\n//\n// Here are some examples:\n//\n// /a/b/c + d = /a/b/c/d\n// /a/b/c + d/ = /a/b/c/d\n// /a/b/c + d/e = /a/b/c/d/e\ninterface ResolvePathOptions {\n  base: string\n  to: string\n  trailingSlash?: 'always' | 'never' | 'preserve'\n  cache?: LRUCache<string, string>\n}\n\n/**\n * Resolve a destination path against a base, honoring trailing-slash policy\n * and supporting relative segments (`.`/`..`) and absolute `to` values.\n */\nexport function resolvePath({\n  base,\n  to,\n  trailingSlash = 'never',\n  cache,\n}: ResolvePathOptions) {\n  const isAbsolute = to.startsWith('/')\n  const isBase = !isAbsolute && to === '.'\n\n  let key\n  if (cache) {\n    // `trailingSlash` is static per router, so it doesn't need to be part of the cache key\n    key = isAbsolute ? to : isBase ? base : base + '\\0' + to\n    const cached = cache.get(key)\n    if (cached) return cached\n  }\n\n  let baseSegments: Array<string>\n  if (isBase) {\n    baseSegments = base.split('/')\n  } else if (isAbsolute) {\n    baseSegments = to.split('/')\n  } else {\n    baseSegments = base.split('/')\n    while (baseSegments.length > 1 && last(baseSegments) === '') {\n      baseSegments.pop()\n    }\n\n    const toSegments = to.split('/')\n    for (let index = 0, length = toSegments.length; index < length; index++) {\n      const value = toSegments[index]!\n      if (value === '') {\n        if (!index) {\n          // Leading slash\n          baseSegments = [value]\n        } else if (index === length - 1) {\n          // Trailing Slash\n          baseSegments.push(value)\n        } else {\n          // ignore inter-slashes\n        }\n      } else if (value === '..') {\n        baseSegments.pop()\n      } else if (value === '.') {\n        // ignore\n      } else {\n        baseSegments.push(value)\n      }\n    }\n  }\n\n  if (baseSegments.length > 1) {\n    if (last(baseSegments) === '') {\n      if (trailingSlash === 'never') {\n        baseSegments.pop()\n      }\n    } else if (trailingSlash === 'always') {\n      baseSegments.push('')\n    }\n  }\n\n  let segment\n  let joined = ''\n  for (let i = 0; i < baseSegments.length; i++) {\n    if (i > 0) joined += '/'\n    const part = baseSegments[i]!\n    if (!part) continue\n    segment = parseSegment(part, 0, segment)\n    const kind = segment[0]\n    if (kind === SEGMENT_TYPE_PATHNAME) {\n      joined += part\n      continue\n    }\n    const end = segment[5]\n    const prefix = part.substring(0, segment[1])\n    const suffix = part.substring(segment[4], end)\n    const value = part.substring(segment[2], segment[3])\n    if (kind === SEGMENT_TYPE_PARAM) {\n      joined += prefix || suffix ? `${prefix}{$${value}}${suffix}` : `$${value}`\n    } else if (kind === SEGMENT_TYPE_WILDCARD) {\n      joined += prefix || suffix ? `${prefix}{$}${suffix}` : '$'\n    } else {\n      // SEGMENT_TYPE_OPTIONAL_PARAM\n      joined += `${prefix}{-$${value}}${suffix}`\n    }\n  }\n  joined = cleanPath(joined)\n  const result = joined || '/'\n  if (key && cache) cache.set(key, result)\n  return result\n}\n\n/**\n * Create a pre-compiled decode config from allowed characters.\n * This should be called once at router initialization.\n */\nexport function compileDecodeCharMap(\n  pathParamsAllowedCharacters: ReadonlyArray<string>,\n) {\n  const charMap = new Map(\n    pathParamsAllowedCharacters.map((char) => [encodeURIComponent(char), char]),\n  )\n  // Escape special regex characters and join with |\n  const pattern = Array.from(charMap.keys())\n    .map((key) => key.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'))\n    .join('|')\n  const regex = new RegExp(pattern, 'g')\n  return (encoded: string) =>\n    encoded.replace(regex, (match) => charMap.get(match) ?? match)\n}\n\ninterface InterpolatePathOptions {\n  path?: string\n  params: Record<string, unknown>\n  /**\n   * A function that decodes a path parameter value.\n   * Obtained from `compileDecodeCharMap(pathParamsAllowedCharacters)`.\n   */\n  decoder?: (encoded: string) => string\n  /**\n   * @internal\n   * For testing only, in development mode we use the router.isServer value\n   */\n  server?: boolean\n}\n\ntype InterPolatePathResult = {\n  interpolatedPath: string\n  usedParams: Record<string, unknown>\n  isMissingParams: boolean // true if any params were not available when being looked up in the params object\n}\n\nfunction encodeParam(\n  key: string,\n  params: InterpolatePathOptions['params'],\n  decoder: InterpolatePathOptions['decoder'],\n): any {\n  const value = params[key]\n  if (typeof value !== 'string') return value\n\n  if (key === '_splat') {\n    // Early return if value only contains URL-safe characters (performance optimization)\n    if (/^[a-zA-Z0-9\\-._~!/]*$/.test(value)) return value\n    // the splat/catch-all routes shouldn't have the '/' encoded out\n    // Use encodeURIComponent for each segment to properly encode spaces,\n    // plus signs, and other special characters that encodeURI leaves unencoded\n    return value\n      .split('/')\n      .map((segment) => encodePathParam(segment, decoder))\n      .join('/')\n  } else {\n    return encodePathParam(value, decoder)\n  }\n}\n\n/**\n * Interpolate params and wildcards into a route path template.\n *\n * - Encodes params safely (configurable allowed characters)\n * - Supports `{-$optional}` segments, `{prefix{$id}suffix}` and `{$}` wildcards\n */\nexport function interpolatePath({\n  path,\n  params,\n  decoder,\n  // `server` is marked @internal and stripped from .d.ts by `stripInternal`.\n  // We avoid destructuring it in the function signature so the emitted\n  // declaration doesn't reference a property that no longer exists.\n  ...rest\n}: InterpolatePathOptions): InterPolatePathResult {\n  // Tracking if any params are missing in the `params` object\n  // when interpolating the path\n  let isMissingParams = false\n  const usedParams: Record<string, unknown> = Object.create(null)\n\n  if (!path || path === '/')\n    return { interpolatedPath: '/', usedParams, isMissingParams }\n  if (!path.includes('$'))\n    return { interpolatedPath: path, usedParams, isMissingParams }\n\n  if (isServer ?? rest.server) {\n    // Fast path for common templates like `/posts/$id` or `/files/$`.\n    // Braced segments (`{...}`) are more complex (prefix/suffix/optional) and are\n    // handled by the general parser below.\n    if (path.indexOf('{') === -1) {\n      const length = path.length\n      let cursor = 0\n      let joined = ''\n\n      while (cursor < length) {\n        // Skip slashes between segments. '/' code is 47\n        while (cursor < length && path.charCodeAt(cursor) === 47) cursor++\n        if (cursor >= length) break\n\n        const start = cursor\n        let end = path.indexOf('/', cursor)\n        if (end === -1) end = length\n        cursor = end\n\n        const part = path.substring(start, end)\n        if (!part) continue\n\n        // `$id` or `$` (splat). '$' code is 36\n        if (part.charCodeAt(0) === 36) {\n          if (part.length === 1) {\n            const splat = params._splat\n            usedParams._splat = splat\n            // TODO: Deprecate *\n            usedParams['*'] = splat\n\n            if (!splat) {\n              isMissingParams = true\n              continue\n            }\n\n            const value = encodeParam('_splat', params, decoder)\n            joined += '/' + value\n          } else {\n            const key = part.substring(1)\n            if (!isMissingParams && !(key in params)) {\n              isMissingParams = true\n            }\n            usedParams[key] = params[key]\n\n            const value = encodeParam(key, params, decoder) ?? 'undefined'\n            joined += '/' + value\n          }\n        } else {\n          joined += '/' + part\n        }\n      }\n\n      if (path.endsWith('/')) joined += '/'\n\n      const interpolatedPath = joined || '/'\n      return { usedParams, interpolatedPath, isMissingParams }\n    }\n  }\n\n  const length = path.length\n  let cursor = 0\n  let segment\n  let joined = ''\n  while (cursor < length) {\n    const start = cursor\n    segment = parseSegment(path, start, segment)\n    const end = segment[5]\n    cursor = end + 1\n\n    if (start === end) continue\n\n    const kind = segment[0]\n\n    if (kind === SEGMENT_TYPE_PATHNAME) {\n      joined += '/' + path.substring(start, end)\n      continue\n    }\n\n    if (kind === SEGMENT_TYPE_WILDCARD) {\n      const splat = params._splat\n      usedParams._splat = splat\n      // TODO: Deprecate *\n      usedParams['*'] = splat\n\n      const prefix = path.substring(start, segment[1])\n      const suffix = path.substring(segment[4], end)\n\n      // Check if _splat parameter is missing. _splat could be missing if undefined or an empty string or some other falsy value.\n      if (!splat) {\n        isMissingParams = true\n        // For missing splat parameters, just return the prefix and suffix without the wildcard\n        // If there is a prefix or suffix, return them joined, otherwise omit the segment\n        if (prefix || suffix) {\n          joined += '/' + prefix + suffix\n        }\n        continue\n      }\n\n      const value = encodeParam('_splat', params, decoder)\n      joined += '/' + prefix + value + suffix\n      continue\n    }\n\n    if (kind === SEGMENT_TYPE_PARAM) {\n      const key = path.substring(segment[2], segment[3])\n      if (!isMissingParams && !(key in params)) {\n        isMissingParams = true\n      }\n      usedParams[key] = params[key]\n\n      const prefix = path.substring(start, segment[1])\n      const suffix = path.substring(segment[4], end)\n      const value = encodeParam(key, params, decoder) ?? 'undefined'\n      joined += '/' + prefix + value + suffix\n      continue\n    }\n\n    if (kind === SEGMENT_TYPE_OPTIONAL_PARAM) {\n      const key = path.substring(segment[2], segment[3])\n      const valueRaw = params[key]\n\n      // Check if optional parameter is missing or undefined\n      if (valueRaw == null) continue\n\n      usedParams[key] = valueRaw\n\n      const prefix = path.substring(start, segment[1])\n      const suffix = path.substring(segment[4], end)\n      const value = encodeParam(key, params, decoder) ?? ''\n      joined += '/' + prefix + value + suffix\n      continue\n    }\n  }\n\n  if (path.endsWith('/')) joined += '/'\n\n  const interpolatedPath = joined || '/'\n\n  return { usedParams, interpolatedPath, isMissingParams }\n}\n\nfunction encodePathParam(\n  value: string,\n  decoder?: InterpolatePathOptions['decoder'],\n) {\n  const encoded = encodeURIComponent(value)\n  return decoder?.(encoded) ?? encoded\n}\n"],"mappings":"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"}