{"version":3,"sources":["../../../src/lib/metadata/get-metadata-route.ts"],"sourcesContent":["import { isMetadataPage } from './is-metadata-route'\nimport path from '../../shared/lib/isomorphic/path'\nimport { interpolateDynamicPath } from '../../server/server-utils'\nimport { getNamedRouteRegex } from '../../shared/lib/router/utils/route-regex'\nimport { djb2Hash } from '../../shared/lib/hash'\nimport { normalizeAppPath } from '../../shared/lib/router/utils/app-paths'\nimport { normalizePathSep } from '../../shared/lib/page-path/normalize-path-sep'\nimport {\n  isGroupSegment,\n  isParallelRouteSegment,\n} from '../../shared/lib/segment'\n\n/*\n * If there's special convention like (...) or @ in the page path,\n * Give it a unique hash suffix to avoid conflicts\n *\n * e.g.\n * /opengraph-image -> /opengraph-image\n * /(post)/opengraph-image.tsx -> /opengraph-image-[0-9a-z]{6}\n *\n * Sitemap is an exception, it should not have a suffix.\n * Each sitemap contains all the urls of sub routes, we don't have the case of duplicates `/(group)/sitemap.[ext]` and `/sitemap.[ext]` since they should be the same.\n * Hence we always normalize the urls for sitemap and do not append hash suffix, and ensure user-land only contains one sitemap per pathname.\n *\n * /sitemap -> /sitemap\n * /(post)/sitemap -> /sitemap\n */\nfunction getMetadataRouteSuffix(page: string) {\n  // Remove the last segment and get the parent pathname\n  // e.g. /parent/a/b/c -> /parent/a/b\n  // e.g. /parent/opengraph-image -> /parent\n  const parentPathname = path.dirname(page)\n  // Only apply suffix to metadata routes except for sitemaps\n  if (page.endsWith('/sitemap') || page.endsWith('/sitemap.xml')) {\n    return ''\n  }\n\n  // Calculate the hash suffix based on the parent path\n  let suffix = ''\n  // Check if there's any special characters in the parent pathname.\n  const segments = parentPathname.split('/')\n  if (\n    segments.some((seg) => isGroupSegment(seg) || isParallelRouteSegment(seg))\n  ) {\n    // Hash the parent path to get a unique suffix\n    suffix = djb2Hash(parentPathname).toString(36).slice(0, 6)\n  }\n  return suffix\n}\n\n/**\n * Fill the dynamic segment in the metadata route\n *\n * Example:\n * fillMetadataSegment('/a/[slug]', { params: { slug: 'b' } }, 'open-graph', false) -> '/a/b/open-graph'\n *\n * When isStatic is true, all dynamic segments are filled with \"-\" placeholder\n * since static metadata files have consistent responses regardless of params.\n * Example:\n * fillMetadataSegment('/a/[slug]', {}, 'icon.png', true) -> '/a/-/icon.png'\n *\n */\nexport function fillMetadataSegment(\n  segment: string,\n  params: any,\n  lastSegment: string,\n  isStatic: boolean\n) {\n  const pathname = normalizeAppPath(segment)\n  const routeRegex = getNamedRouteRegex(pathname, {\n    prefixRouteKeys: false,\n  })\n\n  // For static metadata files, fill all dynamic segments with \"-\" placeholder\n  const routeParams = isStatic\n    ? Object.keys(routeRegex.groups).reduce(\n        (acc, key) => {\n          const { repeat } = routeRegex.groups[key]\n          // Use array for catch-all segments, string for regular segments\n          acc[key] = repeat ? ['-'] : '-'\n          return acc\n        },\n        {} as Record<string, string | string[]>\n      )\n    : params\n\n  const route = interpolateDynamicPath(pathname, routeParams, routeRegex)\n  const { name, ext } = path.parse(lastSegment)\n  const pagePath = path.posix.join(segment, name)\n  const suffix = getMetadataRouteSuffix(pagePath)\n  const routeSuffix = suffix ? `-${suffix}` : ''\n\n  return normalizePathSep(path.join(route, `${name}${routeSuffix}${ext}`))\n}\n\n/**\n * Map metadata page key to the corresponding route\n *\n * static file page key:    /app/robots.txt -> /robots.xml -> /robots.txt/route\n * dynamic route page key:  /app/robots.tsx -> /robots -> /robots.txt/route\n *\n * @param page\n * @returns\n */\nexport function normalizeMetadataRoute(page: string) {\n  if (!isMetadataPage(page)) {\n    return page\n  }\n  let route = page\n  let suffix = ''\n  if (page === '/robots') {\n    route += '.txt'\n  } else if (page === '/manifest') {\n    route += '.webmanifest'\n  } else {\n    suffix = getMetadataRouteSuffix(page)\n  }\n  // Support both /<metadata-route.ext> and custom routes /<metadata-route>/route.ts.\n  // If it's a metadata file route, we need to append /[id]/route to the page.\n  if (!route.endsWith('/route')) {\n    const { dir, name: baseName, ext } = path.parse(route)\n    route = path.posix.join(\n      dir,\n      `${baseName}${suffix ? `-${suffix}` : ''}${ext}`,\n      'route'\n    )\n  }\n\n  return route\n}\n\n// Normalize metadata route page to either a single route or a dynamic route.\n// e.g. Input: /sitemap/route\n// when isDynamic is false, single route -> /sitemap.xml/route\n// when isDynamic is false, dynamic route -> /sitemap/[__metadata_id__]/route\n// also works for pathname such as /sitemap -> /sitemap.xml, but will not append /route suffix\nexport function normalizeMetadataPageToRoute(page: string, isDynamic: boolean) {\n  const isRoute = page.endsWith('/route')\n  const routePagePath = isRoute ? page.slice(0, -'/route'.length) : page\n  const metadataRouteExtension = routePagePath.endsWith('/sitemap')\n    ? '.xml'\n    : ''\n  const mapped = isDynamic\n    ? `${routePagePath}/[__metadata_id__]`\n    : `${routePagePath}${metadataRouteExtension}`\n\n  return mapped + (isRoute ? '/route' : '')\n}\n"],"names":["fillMetadataSegment","normalizeMetadataPageToRoute","normalizeMetadataRoute","getMetadataRouteSuffix","page","parentPathname","path","dirname","endsWith","suffix","segments","split","some","seg","isGroupSegment","isParallelRouteSegment","djb2Hash","toString","slice","segment","params","lastSegment","isStatic","pathname","normalizeAppPath","routeRegex","getNamedRouteRegex","prefixRouteKeys","routeParams","Object","keys","groups","reduce","acc","key","repeat","route","interpolateDynamicPath","name","ext","parse","pagePath","posix","join","routeSuffix","normalizePathSep","isMetadataPage","dir","baseName","isDynamic","isRoute","routePagePath","length","metadataRouteExtension","mapped"],"mappings":"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","ignoreList":[0]}