{"version":3,"file":"router.cjs","names":[],"sources":["../../src/ui/router.ts"],"sourcesContent":["import type { AnyRouter } from \"@tanstack/react-router\";\nimport type { HeadData, HeadLink, HeadMeta, HeadScript } from \"./types\";\n\nexport function getMetaKey(meta: HeadMeta): string {\n  if (!meta) return \"null\";\n  if (\"title\" in meta) return \"title\";\n  if (\"charSet\" in meta) return \"charSet\";\n  if (\"name\" in meta) return `name:${(meta as { name: string }).name}`;\n  if (\"property\" in meta) {\n    return `property:${(meta as { property: string }).property}`;\n  }\n  if (\"httpEquiv\" in meta) {\n    return `httpEquiv:${(meta as { httpEquiv: string }).httpEquiv}`;\n  }\n  return JSON.stringify(meta);\n}\n\nexport function getLinkKey(link: HeadLink): string {\n  const rel = (link as { rel?: string }).rel ?? \"\";\n  const href = (link as { href?: string }).href ?? \"\";\n  return `${rel}:${href}`;\n}\n\nexport function getScriptKey(script: HeadScript): string {\n  if (!script) return \"null\";\n  if (\"src\" in script && script.src) return `src:${script.src}`;\n  if (\"children\" in script && script.children) {\n    return `children:${typeof script.children === \"string\" ? script.children : JSON.stringify(script.children)}`;\n  }\n  return JSON.stringify(script);\n}\n\nexport async function collectHeadData(router: AnyRouter): Promise<HeadData> {\n  await router.load();\n\n  const metaMap = new Map<string, HeadMeta>();\n  const linkMap = new Map<string, HeadLink>();\n  const scriptMap = new Map<string, HeadScript>();\n\n  for (const match of router.state.matches) {\n    const route =\n      (\n        router as AnyRouter & {\n          routesById?: Record<string, { options?: { head?: (...args: unknown[]) => unknown } }>;\n        }\n      ).routesById?.[(match as { routeId: string }).routeId] ??\n      (match as { route?: { options?: { head?: (...args: unknown[]) => unknown } } }).route;\n    const headFn = route?.options?.head;\n    if (!headFn) continue;\n\n    try {\n      const headResult = (await headFn({\n        loaderData: match.loaderData,\n        matches: router.state.matches,\n        match,\n        params: match.params,\n      })) as {\n        meta?: HeadMeta[];\n        links?: HeadLink[];\n        scripts?: HeadScript[];\n      };\n\n      if (headResult?.meta) {\n        for (const meta of headResult.meta) {\n          metaMap.set(getMetaKey(meta), meta);\n        }\n      }\n      if (headResult?.links) {\n        for (const link of headResult.links) {\n          linkMap.set(getLinkKey(link), link);\n        }\n      }\n      if (headResult?.scripts) {\n        for (const script of headResult.scripts) {\n          scriptMap.set(getScriptKey(script), script);\n        }\n      }\n    } catch (error) {\n      console.warn(`[collectHeadData] head() failed for ${match.routeId}:`, error);\n    }\n  }\n\n  return {\n    meta: [...metaMap.values()],\n    links: [...linkMap.values()],\n    scripts: [...scriptMap.values()],\n  };\n}\n\nfunction escapeHtml(s: string): string {\n  return s\n    .replace(/&/g, \"&amp;\")\n    .replace(/\"/g, \"&quot;\")\n    .replace(/</g, \"&lt;\")\n    .replace(/>/g, \"&gt;\");\n}\n\nfunction serializeMeta(meta: HeadMeta): string {\n  if (!meta) return \"\";\n  if (\"charSet\" in meta) return `<meta charset=\"${escapeHtml(String(meta.charSet))}\">`;\n  if (\"title\" in meta) return `<title>${escapeHtml(String(meta.title))}</title>`;\n  const attrs = Object.entries(meta as Record<string, unknown>)\n    .filter(([, v]) => v != null)\n    .map(([k, v]) => `${k}=\"${escapeHtml(String(v))}\"`)\n    .join(\" \");\n  return `<meta ${attrs}>`;\n}\n\nfunction serializeLink(link: HeadLink): string {\n  if (!link) return \"\";\n  const attrs = Object.entries(link as Record<string, unknown>)\n    .filter(([, v]) => v != null)\n    .map(([k, v]) => `${k}=\"${escapeHtml(String(v))}\"`)\n    .join(\" \");\n  return `<link ${attrs}>`;\n}\n\nfunction serializeScript(script: HeadScript, cspNonce?: string): string {\n  if (!script) return \"\";\n  if (\"src\" in script && script.src) {\n    const attrs: string[] = [`src=\"${escapeHtml(script.src)}\"`];\n    if (script.integrity) attrs.push(`integrity=\"${escapeHtml(script.integrity)}\"`);\n    if (script.crossOrigin) attrs.push(`crossorigin=\"${escapeHtml(script.crossOrigin)}\"`);\n    if (script.type) attrs.push(`type=\"${escapeHtml(script.type)}\"`);\n    if (cspNonce) attrs.push(`nonce=\"${cspNonce}\"`);\n    return `<script ${attrs.join(\" \")}></script>`;\n  }\n  if (\"children\" in script) {\n    const attrs: string[] = [];\n    if (script.type) attrs.push(`type=\"${escapeHtml(script.type)}\"`);\n    if (cspNonce) attrs.push(`nonce=\"${cspNonce}\"`);\n    const content =\n      typeof script.children === \"string\" ? script.children : JSON.stringify(script.children);\n    return `<script${attrs.length ? ` ${attrs.join(\" \")}` : \"\"}>${content}</script>`;\n  }\n  return \"\";\n}\n\nexport function serializeHeadData(\n  headData: HeadData,\n  cspNonce?: string,\n): { metaHtml: string; linkHtml: string; scriptHtml: string } {\n  return {\n    metaHtml: headData.meta\n      .filter(Boolean)\n      .map((m) => serializeMeta(m))\n      .join(\"\\n\"),\n    linkHtml: headData.links\n      .filter(Boolean)\n      .map((l) => serializeLink(l))\n      .join(\"\\n\"),\n    scriptHtml: headData.scripts\n      .filter(Boolean)\n      .map((s) => serializeScript(s, cspNonce))\n      .join(\"\\n\"),\n  };\n}\n"],"mappings":"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"}