pagegraph 0.12.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (160) hide show
  1. package/README.md +325 -66
  2. package/dist/anthropic-messages-TqKpKmfW.js +1067 -0
  3. package/dist/anthropic-messages-TqKpKmfW.js.map +1 -0
  4. package/dist/audit.d.ts +4 -2
  5. package/dist/audit.js +5 -5
  6. package/dist/audit.js.map +1 -1
  7. package/dist/azure-openai-responses-DJjBLwoI.js +231 -0
  8. package/dist/azure-openai-responses-DJjBLwoI.js.map +1 -0
  9. package/dist/build-only/audit.js +1 -1
  10. package/dist/build-only/claims.d.ts +1 -0
  11. package/dist/build-only/claims.js +6 -0
  12. package/dist/build-only/claims.js.map +1 -0
  13. package/dist/build-only/config.js +1 -1
  14. package/dist/build-only/oxlint.d.ts +1 -0
  15. package/dist/build-only/oxlint.js +6 -0
  16. package/dist/build-only/oxlint.js.map +1 -0
  17. package/dist/build-only/tanstack-start.js +1 -1
  18. package/dist/build-only/vite.js +1 -1
  19. package/dist/{checks-uZk5Em9A.js → checks-BS-aDXB_.js} +2 -2
  20. package/dist/checks-BS-aDXB_.js.map +1 -0
  21. package/dist/claims-Bch7Lxlo.d.ts +92 -0
  22. package/dist/claims-Bv7voeEV.js +431 -0
  23. package/dist/claims-Bv7voeEV.js.map +1 -0
  24. package/dist/claims.d.ts +94 -0
  25. package/dist/claims.js +2 -0
  26. package/dist/cli.js +17607 -43387
  27. package/dist/cli.js.map +1 -1
  28. package/dist/cloudflare-workers-ai-system-one-f3ZrvNYZ.js +41 -0
  29. package/dist/cloudflare-workers-ai-system-one-f3ZrvNYZ.js.map +1 -0
  30. package/dist/config.d.ts +9 -29
  31. package/dist/config.js +2 -2
  32. package/dist/config.js.map +1 -1
  33. package/dist/{content-kcEnQdfi.js → content-CHd0X4s6.js} +2 -2
  34. package/dist/{content-kcEnQdfi.js.map → content-CHd0X4s6.js.map} +1 -1
  35. package/dist/{content-B1cPtL8b.d.ts → content-DgNr7apS.d.ts} +4 -5
  36. package/dist/declare-D5o7hwmv.js.map +1 -1
  37. package/dist/diagnostics-Wt5faNDM.js +108 -0
  38. package/dist/diagnostics-Wt5faNDM.js.map +1 -0
  39. package/dist/dist-B6zg_Z3Z.js +4794 -0
  40. package/dist/dist-B6zg_Z3Z.js.map +1 -0
  41. package/dist/document-CztEu3Vd.d.ts +109 -0
  42. package/dist/document-Dvemcv7V.js +379 -0
  43. package/dist/document-Dvemcv7V.js.map +1 -0
  44. package/dist/env-api-keys-C-OA0yM-.js +124 -0
  45. package/dist/env-api-keys-C-OA0yM-.js.map +1 -0
  46. package/dist/error-body-CyiejW4b.js +103 -0
  47. package/dist/error-body-CyiejW4b.js.map +1 -0
  48. package/dist/facts-1OKclPOk.js +115 -0
  49. package/dist/facts-1OKclPOk.js.map +1 -0
  50. package/dist/github-copilot-headers-CEpMOpQF.js +24 -0
  51. package/dist/github-copilot-headers-CEpMOpQF.js.map +1 -0
  52. package/dist/google-generative-ai-BxABKIKO.js +330 -0
  53. package/dist/google-generative-ai-BxABKIKO.js.map +1 -0
  54. package/dist/google-shared-0gpM2jFi.js +19471 -0
  55. package/dist/google-shared-0gpM2jFi.js.map +1 -0
  56. package/dist/google-vertex-D8Eb5cbu.js +376 -0
  57. package/dist/google-vertex-D8Eb5cbu.js.map +1 -0
  58. package/dist/{declare-DVgdEdOL.d.ts → graph-D1PIndsC.d.ts} +117 -6
  59. package/dist/{graph-Bcsourlv.js → graph-DMNOLXLu.js} +23 -13
  60. package/dist/graph-DMNOLXLu.js.map +1 -0
  61. package/dist/hash-Dp7EzZUo.js +18 -0
  62. package/dist/hash-Dp7EzZUo.js.map +1 -0
  63. package/dist/headers-BRNMVpzu.js +19 -0
  64. package/dist/headers-BRNMVpzu.js.map +1 -0
  65. package/dist/index-C5w9ripz.d.ts +204 -0
  66. package/dist/index.d.ts +6 -160
  67. package/dist/index.js +37 -5
  68. package/dist/index.js.map +1 -1
  69. package/dist/inline-BbS93GAT.js +682 -0
  70. package/dist/inline-BbS93GAT.js.map +1 -0
  71. package/dist/json-parse-C10znB7l.js +383 -0
  72. package/dist/json-parse-C10znB7l.js.map +1 -0
  73. package/dist/llms-Dhr_5u2O.js +19 -0
  74. package/dist/llms-Dhr_5u2O.js.map +1 -0
  75. package/dist/markdown-C6dRE9zD.js +168 -0
  76. package/dist/markdown-C6dRE9zD.js.map +1 -0
  77. package/dist/markdown-path-lJB9BAVZ.js +6 -0
  78. package/dist/markdown-path-lJB9BAVZ.js.map +1 -0
  79. package/dist/{message-DT_CjUdt.js → message-CuBjgZ74.js} +2 -2
  80. package/dist/{message-DT_CjUdt.js.map → message-CuBjgZ74.js.map} +1 -1
  81. package/dist/mistral-conversations-CvaqBWjR.js +690 -0
  82. package/dist/mistral-conversations-CvaqBWjR.js.map +1 -0
  83. package/dist/models-DcT5qOEL.js +1203 -0
  84. package/dist/models-DcT5qOEL.js.map +1 -0
  85. package/dist/node-Ccvru9GE.js +26 -0
  86. package/dist/node-Ccvru9GE.js.map +1 -0
  87. package/dist/node-MEosBOF2.js +2403 -0
  88. package/dist/node-MEosBOF2.js.map +1 -0
  89. package/dist/openai-BCBEd2eO.js +17350 -0
  90. package/dist/openai-BCBEd2eO.js.map +1 -0
  91. package/dist/openai-codex-responses-vJqxeeRC.js +1268 -0
  92. package/dist/openai-codex-responses-vJqxeeRC.js.map +1 -0
  93. package/dist/openai-completions-Cb_fRAbI.js +989 -0
  94. package/dist/openai-completions-Cb_fRAbI.js.map +1 -0
  95. package/dist/openai-prompt-cache-Bc6qNWt0.js +10 -0
  96. package/dist/openai-prompt-cache-Bc6qNWt0.js.map +1 -0
  97. package/dist/openai-responses-sDuh82G5.js +268 -0
  98. package/dist/openai-responses-sDuh82G5.js.map +1 -0
  99. package/dist/openai-responses-shared-mhuo1Jov.js +599 -0
  100. package/dist/openai-responses-shared-mhuo1Jov.js.map +1 -0
  101. package/dist/openrouter-images-CRmBkzpX.js +127 -0
  102. package/dist/openrouter-images-CRmBkzpX.js.map +1 -0
  103. package/dist/oxlint.d.ts +58 -0
  104. package/dist/oxlint.js +202 -0
  105. package/dist/oxlint.js.map +1 -0
  106. package/dist/page-heads-BfjWQvau.d.ts +108 -0
  107. package/dist/{page-heads-6y-CARRQ.js → page-heads-BgbaIjj9.js} +3 -3
  108. package/dist/page-heads-BgbaIjj9.js.map +1 -0
  109. package/dist/pi-Bvw6J0gh.js +56795 -0
  110. package/dist/pi-Bvw6J0gh.js.map +1 -0
  111. package/dist/pi-messages-CejiVYvO.js +308 -0
  112. package/dist/pi-messages-CejiVYvO.js.map +1 -0
  113. package/dist/{projections-DeEFe7XT.d.ts → projections-Bk-qOOsR.d.ts} +2 -2
  114. package/dist/provider-env-t38GK5FF.js +39 -0
  115. package/dist/provider-env-t38GK5FF.js.map +1 -0
  116. package/dist/provider-retry-DzKoh1X7.js +80 -0
  117. package/dist/provider-retry-DzKoh1X7.js.map +1 -0
  118. package/dist/react.d.ts +3 -2
  119. package/dist/react.js +2 -1
  120. package/dist/react.js.map +1 -1
  121. package/dist/rolldown-runtime-B-lAHAz2.js +37 -0
  122. package/dist/sanitize-unicode-Ds14l9Om.js +28 -0
  123. package/dist/sanitize-unicode-Ds14l9Om.js.map +1 -0
  124. package/dist/sdk-C9_wiO6w.js +12503 -0
  125. package/dist/sdk-C9_wiO6w.js.map +1 -0
  126. package/dist/state-BuJP_3Lr.js +28102 -0
  127. package/dist/state-BuJP_3Lr.js.map +1 -0
  128. package/dist/system-one-shared-Dl10ZF7Z.js +167 -0
  129. package/dist/system-one-shared-Dl10ZF7Z.js.map +1 -0
  130. package/dist/tanstack-start/index.d.ts +29 -13
  131. package/dist/tanstack-start/index.js +391 -42
  132. package/dist/tanstack-start/index.js.map +1 -1
  133. package/dist/tanstack-start/markdown.d.ts +12 -0
  134. package/dist/tanstack-start/markdown.js +149 -0
  135. package/dist/tanstack-start/markdown.js.map +1 -0
  136. package/dist/tanstack-start/prerender-worker.d.ts +2 -0
  137. package/dist/tanstack-start/prerender-worker.js +7 -0
  138. package/dist/tanstack-start/prerender-worker.js.map +1 -0
  139. package/dist/tanstack-start/react.d.ts +7 -0
  140. package/dist/tanstack-start/react.js +12 -0
  141. package/dist/tanstack-start/react.js.map +1 -0
  142. package/dist/tanstack-start/server.d.ts +9 -3
  143. package/dist/tanstack-start/server.js +26 -2
  144. package/dist/tanstack-start/server.js.map +1 -1
  145. package/dist/transform-messages-BLJ8EfK6.js +468 -0
  146. package/dist/transform-messages-BLJ8EfK6.js.map +1 -0
  147. package/dist/typesafe-system-one-CwEWMV8P.js +25 -0
  148. package/dist/typesafe-system-one-CwEWMV8P.js.map +1 -0
  149. package/dist/{vite-graph-loader-01p1WxEq.js → vite-graph-loader-CsGiYNWE.js} +6 -5
  150. package/dist/vite-graph-loader-CsGiYNWE.js.map +1 -0
  151. package/dist/vite-graph-loader-DZCwejuJ.d.ts +133 -0
  152. package/package.json +47 -10
  153. package/dist/checks-uZk5Em9A.js.map +0 -1
  154. package/dist/graph-Bcsourlv.js.map +0 -1
  155. package/dist/graph-BxCY90vq.d.ts +0 -104
  156. package/dist/graph-CBIY71w6.d.ts +0 -57
  157. package/dist/page-heads-6y-CARRQ.js.map +0 -1
  158. package/dist/page-heads-DNkjMUEN.d.ts +0 -21
  159. package/dist/vite-graph-loader-01p1WxEq.js.map +0 -1
  160. package/dist/vite-graph-loader-Btgjz5RH.d.ts +0 -56
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"react.js","names":["composeJsonLd","composeEntries"],"sources":["../src/react/breadcrumbs.tsx","../src/react/site.ts","../src/react/json-ld-composition.ts","../src/react/json-ld.ts","../src/react/create-seo.ts"],"sourcesContent":["import type { AnyRouteMatch } from \"@tanstack/react-router\";\nimport { Link, useMatches } from \"@tanstack/react-router\";\nimport { Fragment } from \"react\";\n\nexport interface CrumbTrailItem {\n name: string;\n path: string;\n}\n\n/**\n * Walk the match chain in order, keeping matches that declare `staticData.seo.crumb`,\n * resolving string | fn form. Shared by <Breadcrumbs/> and seoHead's BreadcrumbList.\n */\nexport function resolveCrumbTrail(matches: ReadonlyArray<AnyRouteMatch>): Array<CrumbTrailItem> {\n const trail: Array<CrumbTrailItem> = [];\n for (const match of matches) {\n const crumb = match.staticData.seo?.crumb;\n if (crumb === undefined) continue;\n const name = typeof crumb === \"function\" ? crumb(match) : crumb;\n trail.push({ name, path: match.pathname });\n }\n return trail;\n}\n\nexport function Breadcrumbs({ className }: { className?: string | undefined }) {\n const trail = resolveCrumbTrail(useMatches());\n if (trail.length < 2) return null;\n\n const lastIndex = trail.length - 1;\n return (\n <nav aria-label=\"Breadcrumb\" className={className}>\n <ol className=\"text-muted-foreground flex items-center gap-2 font-mono text-[11px] tracking-wide uppercase\">\n {trail.map((item, index) => {\n const isLast = index === lastIndex;\n return (\n <Fragment key={item.path}>\n {index > 0 ? (\n <li aria-hidden=\"true\" className=\"text-muted-foreground/50\">\n /\n </li>\n ) : null}\n <li\n aria-current={isLast ? \"page\" : undefined}\n className={isLast ? \"text-foreground truncate\" : undefined}\n >\n {isLast ? (\n item.name\n ) : (\n <Link to={item.path} className=\"hover:text-foreground transition-colors\">\n {item.name}\n </Link>\n )}\n </li>\n </Fragment>\n );\n })}\n </ol>\n </nav>\n );\n}\n","/**\n * Site identity — the values a package cannot know about its host.\n *\n * Bound once through {@link createSeo}, so the ~30 route call sites that render\n * a head never thread an origin or a brand name through their arguments.\n * Everything here is a *value*; the schema construction it feeds lives in\n * `json-ld.ts`.\n */\n\nimport type { SeoHead } from \"./create-seo\";\nimport type { SeoJsonLdConfig } from \"./json-ld-composition\";\n\n/** Absolute URL for an origin-relative path; an already-absolute URL passes through. */\nexport function absoluteUrl(origin: string, pathOrUrl: string): string {\n return pathOrUrl.startsWith(\"http\") ? pathOrUrl : `${origin}${pathOrUrl}`;\n}\n\nexport interface SeoSite {\n /** Brand name: Organization/WebSite `name`, Article publisher, Service provider default. */\n name: string;\n /** Organization `logo`. Origin-relative path or absolute URL. */\n logo: string;\n /** Article `publisher.logo` (Google wants an ImageObject distinct from the brand mark). */\n publisherLogo: string;\n /** Article `image` when the instance declares none. */\n defaultImage: string;\n /** Article `author` when the instance declares none. */\n defaultAuthor: { name: string; url?: string | undefined };\n}\n\n/** Public mailing address rendered as a schema.org PostalAddress. */\nexport interface SeoPostalAddress {\n streetAddress: string;\n addressLocality: string;\n addressRegion: string;\n postalCode: string;\n addressCountry: string;\n}\n\n/** The site-wide Organization entity (Knowledge Graph). */\nexport interface SeoOrganization {\n legalName?: string | undefined;\n description: string;\n sameAs: ReadonlyArray<string>;\n contactPoint: { contactType: string; email: string };\n address?: SeoPostalAddress | undefined;\n}\n\n/** The site-wide WebSite entity (sitelinks search box). */\nexport interface SeoWebsite {\n /** Origin-relative search target carrying the `{search_term_string}` placeholder. */\n searchPath: string;\n}\n\nexport interface SeoConfig {\n /** Canonical origin, no trailing slash — e.g. `https://example.com`. */\n origin: string;\n site: SeoSite;\n organization: SeoOrganization;\n website: SeoWebsite;\n jsonLd?: SeoJsonLdConfig | undefined;\n /**\n * Last-mile override for every head `seoHead` renders, e.g. to append\n * site-specific meta. Runs after the canonical, title template, and JSON-LD.\n */\n transformHead?: ((head: SeoHead) => SeoHead) | undefined;\n}\n","import type {\n Article,\n BreadcrumbList,\n FAQPage,\n Graph,\n IdReference,\n ItemList,\n Organization,\n Service,\n Thing,\n WebSite,\n WithContext,\n} from \"schema-dts\";\n\n/** Any schema.org entity accepted by `schema-dts`. */\nexport type JsonLdNode = Extract<Thing, object>;\n\nimport type { JsonLdDocument } from \"../core/declare\";\n\nexport type { JsonLdDocument };\n\nexport interface JsonLdEntityIds {\n organization: string;\n website: string;\n}\n\nexport type JsonLdEntry =\n | {\n kind: \"organization\";\n source: \"generated\";\n document: WithContext<Organization>;\n }\n | { kind: \"website\"; source: \"generated\"; document: WithContext<WebSite> }\n | { kind: \"article\"; source: \"generated\"; document: WithContext<Article> }\n | { kind: \"service\"; source: \"generated\"; document: WithContext<Service> }\n | { kind: \"faq\"; source: \"generated\"; document: WithContext<FAQPage> }\n | {\n kind: \"breadcrumb\";\n source: \"generated\";\n document: WithContext<BreadcrumbList>;\n }\n | { kind: \"item-list\"; source: \"generated\"; document: WithContext<ItemList> }\n | { kind: \"custom\"; source: \"site\" | \"page\"; document: JsonLdDocument };\n\nexport interface JsonLdTransformContext {\n /** Canonical site origin configured through `createSeo`. */\n origin: string;\n /** Stable identifiers for the plugin's generated site entities. */\n entityIds: JsonLdEntityIds;\n /** Canonical page URL when composition happens for a route. */\n canonical?: string | undefined;\n}\n\n/** Return no document to suppress an entry, one to replace it, or an array to expand it. */\nexport type JsonLdTransformResult =\n | JsonLdDocument\n | ReadonlyArray<JsonLdDocument>\n | false\n | null\n | undefined;\n\nexport type JsonLdTransform = (\n entry: JsonLdEntry,\n context: JsonLdTransformContext,\n) => JsonLdTransformResult;\n\nexport interface SeoJsonLdConfig {\n /** Custom entities included by `generateSiteGraphSchema`. */\n site?:\n | ReadonlyArray<JsonLdDocument>\n | ((entityIds: JsonLdEntityIds) => ReadonlyArray<JsonLdDocument>)\n | undefined;\n /** Open composition hook for generated and custom entries. */\n transform?: JsonLdTransform | undefined;\n}\n\n/** Add the schema.org context to an entity while preserving its concrete type. */\nexport function defineJsonLd<const Node extends JsonLdNode & object>(\n node: Node,\n): Node & { \"@context\": \"https://schema.org\" } {\n return { \"@context\": \"https://schema.org\", ...node };\n}\n\n/** Reference a canonical entity declared elsewhere in the same graph or page. */\nexport function jsonLdRef(id: string): IdReference {\n return { \"@id\": id };\n}\n\n/** Extend a generated or custom document without rebuilding its existing properties. */\nexport function extendJsonLd<\n const Document extends JsonLdDocument,\n const Extension extends object,\n>(document: Document, extension: Extension): Document & Extension {\n return { ...(document as unknown as object), ...extension } as Document &\n Extension;\n}\n\nconst documentNodes = (document: JsonLdDocument): ReadonlyArray<JsonLdNode> => {\n if (\"@graph\" in document) {\n return document[\"@graph\"] as ReadonlyArray<JsonLdNode>;\n }\n const { \"@context\": _context, ...node } = document as unknown as Record<\n string,\n unknown\n >;\n return [node as JsonLdNode];\n};\n\n/** Compose related schema.org documents into one graph without nested `@context` values. */\nexport function jsonLdGraph(documents: ReadonlyArray<JsonLdDocument>): Graph {\n return {\n \"@context\": \"https://schema.org\",\n \"@graph\": documents.flatMap(documentNodes),\n };\n}\n\n/** Apply an optional zero/one/many transform while preserving entry order. */\nexport function composeJsonLd(\n entries: ReadonlyArray<JsonLdEntry>,\n context: JsonLdTransformContext,\n transform?: JsonLdTransform,\n): Array<JsonLdDocument> {\n if (transform === undefined) {\n return entries.map((entry) => entry.document as JsonLdDocument);\n }\n\n return entries.flatMap((entry) => {\n const result = transform(entry, context);\n if (result === undefined || result === null || result === false) return [];\n return Array.isArray(result) ? [...result] : [result as JsonLdDocument];\n });\n}\n","/**\n * JSON-LD structured-data generators.\n *\n * schema.org payloads typed against `schema-dts`, which is a types-only devDep —\n * it erases at build, so this module keeps the entry's zero-runtime-dep rule.\n * The brand values (name, logo, sameAs, the Organization description) are the\n * host's, and arrive through {@link SeoConfig}; the schema construction is ours.\n *\n * @see https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data\n * @see https://schema.org/\n */\n\nimport type {\n Article,\n BreadcrumbList,\n FAQPage,\n Graph,\n ItemList,\n Organization,\n Person,\n Question,\n Service,\n WebSite,\n WithContext,\n} from \"schema-dts\";\n\nimport {\n composeJsonLd as composeEntries,\n jsonLdGraph,\n jsonLdRef,\n type JsonLdDocument,\n type JsonLdEntityIds,\n type JsonLdEntry,\n} from \"./json-ld-composition\";\nimport type { SeoFaq } from \"../core/declare\";\nimport { absoluteUrl, type SeoConfig } from \"./site\";\n\nexport interface ServiceParams {\n name: string;\n description: string;\n serviceType: string;\n provider?: string | undefined;\n areaServed?: string | undefined;\n}\n\n\nexport interface BreadcrumbItem {\n name: string;\n url: string;\n}\n\nexport interface ItemListEntry {\n name: string;\n url: string;\n}\n\nexport interface ArticleParams {\n headline: string;\n description: string;\n image?: string | undefined;\n datePublished: string;\n dateModified?: string | undefined;\n author: {\n name: string;\n url?: string | undefined;\n };\n url: string;\n}\n\n/** The JSON-LD generators, bound to one site identity. */\nexport interface JsonLd {\n readonly entityIds: JsonLdEntityIds;\n /** Brand entity for the Knowledge Graph. Render site-wide (root layout). */\n generateOrganizationSchema: () => WithContext<Organization>;\n /** WebSite entity with a sitelinks search box. Render on the homepage. */\n generateWebsiteSchema: () => WithContext<WebSite>;\n generateServiceSchema: (params: ServiceParams) => WithContext<Service>;\n generateFAQPageSchema: (faqs: SeoFaq[]) => WithContext<FAQPage>;\n generateBreadcrumbSchema: (\n items: BreadcrumbItem[],\n ) => WithContext<BreadcrumbList>;\n /** Describe a visibly rendered, ordered collection of canonical pages. */\n generateItemListSchema: (\n name: string,\n items: ReadonlyArray<ItemListEntry>,\n ) => WithContext<ItemList>;\n generateArticleSchema: (params: ArticleParams) => WithContext<Article>;\n /** Compose the Organization, WebSite, and configured site entities into one graph. */\n generateSiteGraphSchema: () => Graph | undefined;\n /** Apply the configured transform to generated or custom entries. */\n composeJsonLd: (\n entries: ReadonlyArray<JsonLdEntry>,\n context?: { canonical?: string | undefined },\n ) => Array<JsonLdDocument>;\n}\n\nexport function createJsonLd(config: SeoConfig): JsonLd {\n const { origin, site, organization, website } = config;\n const organizationId = `${origin}/#organization`;\n const websiteId = `${origin}/#website`;\n const entityIds = { organization: organizationId, website: websiteId };\n\n const generateOrganizationSchema = (): WithContext<Organization> => ({\n \"@context\": \"https://schema.org\",\n \"@type\": \"Organization\",\n \"@id\": organizationId,\n name: site.name,\n ...(organization.legalName === undefined\n ? {}\n : { legalName: organization.legalName }),\n url: origin,\n logo: absoluteUrl(origin, site.logo),\n description: organization.description,\n sameAs: [...organization.sameAs],\n contactPoint: {\n \"@type\": \"ContactPoint\",\n contactType: organization.contactPoint.contactType,\n email: organization.contactPoint.email,\n },\n ...(organization.address === undefined\n ? {}\n : {\n address: {\n \"@type\": \"PostalAddress\" as const,\n ...organization.address,\n },\n }),\n });\n\n const generateWebsiteSchema = (): WithContext<WebSite> => ({\n \"@context\": \"https://schema.org\",\n \"@type\": \"WebSite\",\n \"@id\": websiteId,\n name: site.name,\n url: origin,\n publisher: jsonLdRef(organizationId),\n potentialAction: {\n \"@type\": \"SearchAction\",\n target: {\n \"@type\": \"EntryPoint\",\n urlTemplate: absoluteUrl(origin, website.searchPath),\n },\n query: \"required name=search_term_string\",\n },\n });\n\n const generateServiceSchema = (\n params: ServiceParams,\n ): WithContext<Service> => ({\n \"@context\": \"https://schema.org\",\n \"@type\": \"Service\",\n name: params.name,\n description: params.description,\n serviceType: params.serviceType,\n provider: {\n \"@type\": \"Organization\",\n ...(params.provider === undefined\n ? { \"@id\": organizationId, url: origin }\n : {}),\n name: params.provider ?? site.name,\n },\n areaServed: params.areaServed ?? \"Worldwide\",\n });\n\n const generateFAQPageSchema = (faqs: SeoFaq[]): WithContext<FAQPage> => {\n const questions: Question[] = faqs.map((faq) => ({\n \"@type\": \"Question\",\n name: faq.question,\n acceptedAnswer: {\n \"@type\": \"Answer\",\n text: faq.answer,\n },\n }));\n\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"FAQPage\",\n mainEntity: questions,\n };\n };\n\n const generateBreadcrumbSchema = (\n items: BreadcrumbItem[],\n ): WithContext<BreadcrumbList> => ({\n \"@context\": \"https://schema.org\",\n \"@type\": \"BreadcrumbList\",\n itemListElement: items.map((item, index) => ({\n \"@type\": \"ListItem\",\n position: index + 1,\n name: item.name,\n item: `${origin}${item.url}`,\n })),\n });\n\n const generateItemListSchema = (\n name: string,\n items: ReadonlyArray<ItemListEntry>,\n ): WithContext<ItemList> => ({\n \"@context\": \"https://schema.org\",\n \"@type\": \"ItemList\",\n name,\n numberOfItems: items.length,\n itemListElement: items.map((item, index) => ({\n \"@type\": \"ListItem\",\n position: index + 1,\n name: item.name,\n url: `${origin}${item.url}`,\n })),\n });\n\n const generateArticleSchema = (\n params: ArticleParams,\n ): WithContext<Article> => {\n const authorSchema: Person = {\n \"@type\": \"Person\",\n name: params.author.name,\n ...(params.author.url && { url: params.author.url }),\n };\n\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"Article\",\n headline: params.headline,\n description: params.description,\n // Deliberately NOT absolutized: a declared instance image lands verbatim\n // (og:image is where the absolute form is required, and seoHead does that).\n image: params.image ?? absoluteUrl(origin, site.defaultImage),\n datePublished: params.datePublished,\n dateModified: params.dateModified ?? params.datePublished,\n author: authorSchema,\n publisher: {\n \"@type\": \"Organization\",\n \"@id\": organizationId,\n name: site.name,\n logo: {\n \"@type\": \"ImageObject\",\n url: absoluteUrl(origin, site.publisherLogo),\n },\n },\n mainEntityOfPage: {\n \"@type\": \"WebPage\",\n \"@id\": params.url,\n },\n };\n };\n\n const composeJsonLd: JsonLd[\"composeJsonLd\"] = (entries, context = {}) =>\n composeEntries(\n entries,\n {\n origin,\n entityIds,\n ...(context.canonical === undefined\n ? {}\n : { canonical: context.canonical }),\n },\n config.jsonLd?.transform,\n );\n\n const generateSiteGraphSchema = (): Graph | undefined => {\n const configuredSite =\n typeof config.jsonLd?.site === \"function\"\n ? config.jsonLd.site(entityIds)\n : (config.jsonLd?.site ?? []);\n const entries: Array<JsonLdEntry> = [\n {\n kind: \"organization\",\n source: \"generated\",\n document: generateOrganizationSchema(),\n },\n {\n kind: \"website\",\n source: \"generated\",\n document: generateWebsiteSchema(),\n },\n ...configuredSite.map(\n (document): JsonLdEntry => ({\n kind: \"custom\",\n source: \"site\",\n document,\n }),\n ),\n ];\n const documents = composeJsonLd(entries);\n return documents.length === 0 ? undefined : jsonLdGraph(documents);\n };\n\n return {\n entityIds,\n generateOrganizationSchema,\n generateWebsiteSchema,\n generateServiceSchema,\n generateFAQPageSchema,\n generateBreadcrumbSchema,\n generateItemListSchema,\n generateArticleSchema,\n generateSiteGraphSchema,\n composeJsonLd,\n };\n}\n","/**\n * The render layer: one route's SEO declaration plus its per-instance content,\n * composed into the meta/link descriptors TanStack Router renders into <head>,\n * with the JSON-LD that page warrants.\n *\n * {@link createSeo} binds the site identity once (see `site.ts`) and returns\n * the bound API, so a route file calls `seoHead(ctx, instance)` and never sees\n * an origin or a brand name.\n */\n\nimport type { AnyRouteMatch, MetaDescriptor } from \"@tanstack/react-router\";\n\nimport { applyTitleTemplate, type SeoPageHead } from \"../core/declare\";\n\nimport { resolveCrumbTrail } from \"./breadcrumbs\";\nimport type { JsonLdDocument, JsonLdEntry } from \"./json-ld-composition\";\nimport { absoluteUrl, type SeoConfig } from \"./site\";\nimport { createJsonLd, type JsonLd } from \"./json-ld\";\n\n/** Structural subset of TanStack's head() ctx — the leaf match plus the full chain. */\nexport interface SeoHeadCtx {\n matches: ReadonlyArray<AnyRouteMatch>;\n match: AnyRouteMatch;\n}\n\nexport interface SeoHead {\n meta: NonNullable<AnyRouteMatch[\"meta\"]>;\n links: Array<{ rel: \"canonical\"; href: string }>;\n}\n\n/** The render API, bound to one site identity. */\nexport interface Seo extends JsonLd {\n seoHead: (ctx: SeoHeadCtx, instance: SeoPageHead) => SeoHead;\n /**\n * `head()` for a static route that declares its head in `staticData.seo.head`:\n *\n * ```ts\n * createFileRoute(\"/pricing\")({\n * staticData: { seo: { kind: \"page\", sitemap, head: { title, description, faqs } } },\n * head: seo.head,\n * })\n * ```\n *\n * The graph, `pageHeads`, and the checks read the same declaration.\n *\n * Generic so TanStack infers nothing from it: a `head` typed with\n * `AnyRouteMatch` would make the route's search and loader types `any`, and\n * that spreads through the route tree.\n */\n head: <Ctx extends SeoHeadCtx>(ctx: Ctx) => SeoHead;\n}\n\n/** Strip a trailing slash from a pathname, keeping the root \"/\" intact. */\nfunction normalizePathname(pathname: string): string {\n return pathname.length > 1 && pathname.endsWith(\"/\")\n ? pathname.slice(0, -1)\n : pathname;\n}\n\nexport function createSeo(config: SeoConfig): Seo {\n const { origin, site } = config;\n const jsonLd = createJsonLd(config);\n\n const seoHead = (ctx: SeoHeadCtx, instance: SeoPageHead): SeoHead => {\n const canonical = `${origin}${instance.canonicalPath ?? normalizePathname(ctx.match.pathname)}`;\n const title = applyTitleTemplate(ctx.match.staticData.seo?.titleTemplate, instance.title);\n const resolvedOgTitle = instance.ogTitle ?? title;\n const resolvedOgDescription =\n instance.ogDescription ?? instance.description;\n const routeSeo = ctx.match.staticData.seo;\n const { article } = instance;\n const jsonLdEntries: Array<JsonLdEntry> = [];\n\n const meta: Array<MetaDescriptor> = [\n { title },\n { name: \"description\", content: instance.description },\n { property: \"og:title\", content: resolvedOgTitle },\n { property: \"og:description\", content: resolvedOgDescription },\n { property: \"og:type\", content: article ? \"article\" : \"website\" },\n { property: \"og:url\", content: canonical },\n { name: \"twitter:card\", content: \"summary_large_image\" },\n { name: \"twitter:title\", content: resolvedOgTitle },\n { name: \"twitter:description\", content: resolvedOgDescription },\n ];\n\n const robots = instance.robots ?? routeSeo?.robots;\n if (robots !== undefined) {\n meta.push({ name: \"robots\", content: robots });\n }\n\n if (article) {\n if (article.tags?.length) {\n meta.push({ name: \"keywords\", content: article.tags.join(\", \") });\n }\n meta.push(\n { property: \"article:published_time\", content: article.publishedAt },\n {\n property: \"article:modified_time\",\n content: article.modifiedAt ?? article.publishedAt,\n },\n );\n if (article.image !== undefined) {\n const imageUrl = absoluteUrl(origin, article.image);\n meta.push(\n { property: \"og:image\", content: imageUrl },\n { name: \"twitter:image\", content: imageUrl },\n );\n }\n }\n\n if (article) {\n jsonLdEntries.push({\n kind: \"article\",\n source: \"generated\",\n document: jsonLd.generateArticleSchema({\n headline: resolvedOgTitle,\n description: instance.description,\n image: article.image,\n datePublished: article.publishedAt,\n dateModified: article.modifiedAt ?? article.publishedAt,\n author: article.author ?? site.defaultAuthor,\n url: canonical,\n }),\n });\n }\n\n if (!article && instance.keywords) {\n meta.push({ name: \"keywords\", content: instance.keywords.join(\", \") });\n }\n\n if (instance.service) {\n jsonLdEntries.push({\n kind: \"service\",\n source: \"generated\",\n document: jsonLd.generateServiceSchema({\n name: instance.service.name,\n description: instance.service.description ?? instance.description,\n serviceType: instance.service.serviceType,\n }),\n });\n }\n\n if (instance.faqs) {\n jsonLdEntries.push({\n kind: \"faq\",\n source: \"generated\",\n document: jsonLd.generateFAQPageSchema([...instance.faqs]),\n });\n }\n\n if (instance.itemList) {\n jsonLdEntries.push({\n kind: \"item-list\",\n source: \"generated\",\n document: jsonLd.generateItemListSchema(\n instance.itemList.name,\n instance.itemList.items,\n ),\n });\n }\n\n // TanStack accumulates every matched route's head output. Only the current leaf\n // owns the BreadcrumbList; otherwise each parent repeats a progressively stale\n // trail alongside the leaf's canonical trail on nested pages.\n const isLeafMatch = ctx.matches.at(-1)?.id === ctx.match.id;\n const trail = isLeafMatch\n ? (instance.breadcrumbs ?? resolveCrumbTrail(ctx.matches))\n : [];\n if (trail.length >= 2) {\n jsonLdEntries.push({\n kind: \"breadcrumb\",\n source: \"generated\",\n document: jsonLd.generateBreadcrumbSchema(\n trail.map((item) => ({ name: item.name, url: item.path })),\n ),\n });\n }\n\n if (instance.jsonLd) {\n jsonLdEntries.push(\n ...instance.jsonLd.map(\n (document): JsonLdEntry => ({\n kind: \"custom\",\n source: \"page\",\n document,\n }),\n ),\n );\n }\n\n for (const document of jsonLd.composeJsonLd(jsonLdEntries, { canonical })) {\n meta.push({ \"script:ld+json\": document });\n }\n\n // React's head types (JSX.IntrinsicElements['meta']) model only <meta> attributes;\n // TanStack renders `script:ld+json` entries as JSON-LD <script> tags at runtime. The\n // installed @tanstack/react-router augments leaf head meta to those JSX attributes, so\n // the JSON-LD entries are asserted to it (same pattern as an inline root JSON-LD).\n const head: SeoHead = {\n meta: meta as NonNullable<AnyRouteMatch[\"meta\"]>,\n links: [{ rel: \"canonical\", href: canonical }],\n };\n return config.transformHead === undefined ? head : config.transformHead(head);\n };\n\n const head = <Ctx extends SeoHeadCtx>(ctx: Ctx): SeoHead => {\n const declared = ctx.match.staticData.seo?.head;\n if (declared === undefined) {\n throw new Error(`seo.head needs staticData.seo.head on route ${ctx.match.routeId}`);\n }\n return seoHead(ctx, declared);\n };\n\n return { seoHead, head, ...jsonLd };\n}\n"],"mappings":";;;;;;;;;AAaA,SAAgB,kBAAkB,SAA8D;CAC9F,MAAM,QAA+B,CAAC;CACtC,KAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,QAAQ,MAAM,WAAW,KAAK;EACpC,IAAI,UAAU,KAAA,GAAW;EACzB,MAAM,OAAO,OAAO,UAAU,aAAa,MAAM,KAAK,IAAI;EAC1D,MAAM,KAAK;GAAE;GAAM,MAAM,MAAM;EAAS,CAAC;CAC3C;CACA,OAAO;AACT;AAEA,SAAgB,YAAY,EAAE,aAAiD;CAC7E,MAAM,QAAQ,kBAAkB,WAAW,CAAC;CAC5C,IAAI,MAAM,SAAS,GAAG,OAAO;CAE7B,MAAM,YAAY,MAAM,SAAS;CACjC,OACE,oBAAC,OAAD;EAAK,cAAW;EAAwB;EACtC,UAAA,oBAAC,MAAD;GAAI,WAAU;GACX,UAAA,MAAM,KAAK,MAAM,UAAU;IAC1B,MAAM,SAAS,UAAU;IACzB,OACE,qBAAC,UAAD,EAAA,UAAA,CACG,QAAQ,IACP,oBAAC,MAAD;KAAI,eAAY;KAAO,WAAU;KAA2B,UAAA;IAExD,CAAA,IACF,MACJ,oBAAC,MAAD;KACE,gBAAc,SAAS,SAAS,KAAA;KAChC,WAAW,SAAS,6BAA6B,KAAA;KAEhD,UAAA,SACC,KAAK,OAEL,oBAAC,MAAD;MAAM,IAAI,KAAK;MAAM,WAAU;MAC5B,UAAA,KAAK;KACF,CAAA;IAEN,CAAA,CACI,EAAA,GAlBK,KAAK,IAkBV;GAEd,CAAC;EACC,CAAA;CACD,CAAA;AAET;;;;AC9CA,SAAgB,YAAY,QAAgB,WAA2B;CACrE,OAAO,UAAU,WAAW,MAAM,IAAI,YAAY,GAAG,SAAS;AAChE;;;;AC8DA,SAAgB,aACd,MAC6C;CAC7C,OAAO;EAAE,YAAY;EAAsB,GAAG;CAAK;AACrD;;AAGA,SAAgB,UAAU,IAAyB;CACjD,OAAO,EAAE,OAAO,GAAG;AACrB;;AAGA,SAAgB,aAGd,UAAoB,WAA4C;CAChE,OAAO;EAAE,GAAI;EAAgC,GAAG;CAAU;AAE5D;AAEA,MAAM,iBAAiB,aAAwD;CAC7E,IAAI,YAAY,UACd,OAAO,SAAS;CAElB,MAAM,EAAE,YAAY,UAAU,GAAG,SAAS;CAI1C,OAAO,CAAC,IAAkB;AAC5B;;AAGA,SAAgB,YAAY,WAAiD;CAC3E,OAAO;EACL,YAAY;EACZ,UAAU,UAAU,QAAQ,aAAa;CAC3C;AACF;;AAGA,SAAgB,cACd,SACA,SACA,WACuB;CACvB,IAAI,cAAc,KAAA,GAChB,OAAO,QAAQ,KAAK,UAAU,MAAM,QAA0B;CAGhE,OAAO,QAAQ,SAAS,UAAU;EAChC,MAAM,SAAS,UAAU,OAAO,OAAO;EACvC,IAAI,WAAW,KAAA,KAAa,WAAW,QAAQ,WAAW,OAAO,OAAO,CAAC;EACzE,OAAO,MAAM,QAAQ,MAAM,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,MAAwB;CACxE,CAAC;AACH;;;ACnCA,SAAgB,aAAa,QAA2B;CACtD,MAAM,EAAE,QAAQ,MAAM,cAAc,YAAY;CAChD,MAAM,iBAAiB,GAAG,OAAO;CACjC,MAAM,YAAY,GAAG,OAAO;CAC5B,MAAM,YAAY;EAAE,cAAc;EAAgB,SAAS;CAAU;CAErE,MAAM,oCAA+D;EACnE,YAAY;EACZ,SAAS;EACT,OAAO;EACP,MAAM,KAAK;EACX,GAAI,aAAa,cAAc,KAAA,IAC3B,CAAC,IACD,EAAE,WAAW,aAAa,UAAU;EACxC,KAAK;EACL,MAAM,YAAY,QAAQ,KAAK,IAAI;EACnC,aAAa,aAAa;EAC1B,QAAQ,CAAC,GAAG,aAAa,MAAM;EAC/B,cAAc;GACZ,SAAS;GACT,aAAa,aAAa,aAAa;GACvC,OAAO,aAAa,aAAa;EACnC;EACA,GAAI,aAAa,YAAY,KAAA,IACzB,CAAC,IACD,EACE,SAAS;GACP,SAAS;GACT,GAAG,aAAa;EAClB,EACF;CACN;CAEA,MAAM,+BAAqD;EACzD,YAAY;EACZ,SAAS;EACT,OAAO;EACP,MAAM,KAAK;EACX,KAAK;EACL,WAAW,UAAU,cAAc;EACnC,iBAAiB;GACf,SAAS;GACT,QAAQ;IACN,SAAS;IACT,aAAa,YAAY,QAAQ,QAAQ,UAAU;GACrD;GACA,OAAO;EACT;CACF;CAEA,MAAM,yBACJ,YAC0B;EAC1B,YAAY;EACZ,SAAS;EACT,MAAM,OAAO;EACb,aAAa,OAAO;EACpB,aAAa,OAAO;EACpB,UAAU;GACR,SAAS;GACT,GAAI,OAAO,aAAa,KAAA,IACpB;IAAE,OAAO;IAAgB,KAAK;GAAO,IACrC,CAAC;GACL,MAAM,OAAO,YAAY,KAAK;EAChC;EACA,YAAY,OAAO,cAAc;CACnC;CAEA,MAAM,yBAAyB,SAAyC;EAUtE,OAAO;GACL,YAAY;GACZ,SAAS;GACT,YAZ4B,KAAK,KAAK,SAAS;IAC/C,SAAS;IACT,MAAM,IAAI;IACV,gBAAgB;KACd,SAAS;KACT,MAAM,IAAI;IACZ;GACF,EAKsB;EACtB;CACF;CAEA,MAAM,4BACJ,WACiC;EACjC,YAAY;EACZ,SAAS;EACT,iBAAiB,MAAM,KAAK,MAAM,WAAW;GAC3C,SAAS;GACT,UAAU,QAAQ;GAClB,MAAM,KAAK;GACX,MAAM,GAAG,SAAS,KAAK;EACzB,EAAE;CACJ;CAEA,MAAM,0BACJ,MACA,WAC2B;EAC3B,YAAY;EACZ,SAAS;EACT;EACA,eAAe,MAAM;EACrB,iBAAiB,MAAM,KAAK,MAAM,WAAW;GAC3C,SAAS;GACT,UAAU,QAAQ;GAClB,MAAM,KAAK;GACX,KAAK,GAAG,SAAS,KAAK;EACxB,EAAE;CACJ;CAEA,MAAM,yBACJ,WACyB;EACzB,MAAM,eAAuB;GAC3B,SAAS;GACT,MAAM,OAAO,OAAO;GACpB,GAAI,OAAO,OAAO,OAAO,EAAE,KAAK,OAAO,OAAO,IAAI;EACpD;EAEA,OAAO;GACL,YAAY;GACZ,SAAS;GACT,UAAU,OAAO;GACjB,aAAa,OAAO;GAGpB,OAAO,OAAO,SAAS,YAAY,QAAQ,KAAK,YAAY;GAC5D,eAAe,OAAO;GACtB,cAAc,OAAO,gBAAgB,OAAO;GAC5C,QAAQ;GACR,WAAW;IACT,SAAS;IACT,OAAO;IACP,MAAM,KAAK;IACX,MAAM;KACJ,SAAS;KACT,KAAK,YAAY,QAAQ,KAAK,aAAa;IAC7C;GACF;GACA,kBAAkB;IAChB,SAAS;IACT,OAAO,OAAO;GAChB;EACF;CACF;CAEA,MAAMA,mBAA0C,SAAS,UAAU,CAAC,MAClEC,cACE,SACA;EACE;EACA;EACA,GAAI,QAAQ,cAAc,KAAA,IACtB,CAAC,IACD,EAAE,WAAW,QAAQ,UAAU;CACrC,GACA,OAAO,QAAQ,SACjB;CAEF,MAAM,gCAAmD;EACvD,MAAM,iBACJ,OAAO,OAAO,QAAQ,SAAS,aAC3B,OAAO,OAAO,KAAK,SAAS,IAC3B,OAAO,QAAQ,QAAQ,CAAC;EAC/B,MAAM,UAA8B;GAClC;IACE,MAAM;IACN,QAAQ;IACR,UAAU,2BAA2B;GACvC;GACA;IACE,MAAM;IACN,QAAQ;IACR,UAAU,sBAAsB;GAClC;GACA,GAAG,eAAe,KACf,cAA2B;IAC1B,MAAM;IACN,QAAQ;IACR;GACF,EACF;EACF;EACA,MAAM,YAAYD,gBAAc,OAAO;EACvC,OAAO,UAAU,WAAW,IAAI,KAAA,IAAY,YAAY,SAAS;CACnE;CAEA,OAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,eAAA;CACF;AACF;;;;ACtPA,SAAS,kBAAkB,UAA0B;CACnD,OAAO,SAAS,SAAS,KAAK,SAAS,SAAS,GAAG,IAC/C,SAAS,MAAM,GAAG,EAAE,IACpB;AACN;AAEA,SAAgB,UAAU,QAAwB;CAChD,MAAM,EAAE,QAAQ,SAAS;CACzB,MAAM,SAAS,aAAa,MAAM;CAElC,MAAM,WAAW,KAAiB,aAAmC;EACnE,MAAM,YAAY,GAAG,SAAS,SAAS,iBAAiB,kBAAkB,IAAI,MAAM,QAAQ;EAC5F,MAAM,QAAQ,mBAAmB,IAAI,MAAM,WAAW,KAAK,eAAe,SAAS,KAAK;EACxF,MAAM,kBAAkB,SAAS,WAAW;EAC5C,MAAM,wBACJ,SAAS,iBAAiB,SAAS;EACrC,MAAM,WAAW,IAAI,MAAM,WAAW;EACtC,MAAM,EAAE,YAAY;EACpB,MAAM,gBAAoC,CAAC;EAE3C,MAAM,OAA8B;GAClC,EAAE,MAAM;GACR;IAAE,MAAM;IAAe,SAAS,SAAS;GAAY;GACrD;IAAE,UAAU;IAAY,SAAS;GAAgB;GACjD;IAAE,UAAU;IAAkB,SAAS;GAAsB;GAC7D;IAAE,UAAU;IAAW,SAAS,UAAU,YAAY;GAAU;GAChE;IAAE,UAAU;IAAU,SAAS;GAAU;GACzC;IAAE,MAAM;IAAgB,SAAS;GAAsB;GACvD;IAAE,MAAM;IAAiB,SAAS;GAAgB;GAClD;IAAE,MAAM;IAAuB,SAAS;GAAsB;EAChE;EAEA,MAAM,SAAS,SAAS,UAAU,UAAU;EAC5C,IAAI,WAAW,KAAA,GACb,KAAK,KAAK;GAAE,MAAM;GAAU,SAAS;EAAO,CAAC;EAG/C,IAAI,SAAS;GACX,IAAI,QAAQ,MAAM,QAChB,KAAK,KAAK;IAAE,MAAM;IAAY,SAAS,QAAQ,KAAK,KAAK,IAAI;GAAE,CAAC;GAElE,KAAK,KACH;IAAE,UAAU;IAA0B,SAAS,QAAQ;GAAY,GACnE;IACE,UAAU;IACV,SAAS,QAAQ,cAAc,QAAQ;GACzC,CACF;GACA,IAAI,QAAQ,UAAU,KAAA,GAAW;IAC/B,MAAM,WAAW,YAAY,QAAQ,QAAQ,KAAK;IAClD,KAAK,KACH;KAAE,UAAU;KAAY,SAAS;IAAS,GAC1C;KAAE,MAAM;KAAiB,SAAS;IAAS,CAC7C;GACF;EACF;EAEA,IAAI,SACF,cAAc,KAAK;GACjB,MAAM;GACN,QAAQ;GACR,UAAU,OAAO,sBAAsB;IACrC,UAAU;IACV,aAAa,SAAS;IACtB,OAAO,QAAQ;IACf,eAAe,QAAQ;IACvB,cAAc,QAAQ,cAAc,QAAQ;IAC5C,QAAQ,QAAQ,UAAU,KAAK;IAC/B,KAAK;GACP,CAAC;EACH,CAAC;EAGH,IAAI,CAAC,WAAW,SAAS,UACvB,KAAK,KAAK;GAAE,MAAM;GAAY,SAAS,SAAS,SAAS,KAAK,IAAI;EAAE,CAAC;EAGvE,IAAI,SAAS,SACX,cAAc,KAAK;GACjB,MAAM;GACN,QAAQ;GACR,UAAU,OAAO,sBAAsB;IACrC,MAAM,SAAS,QAAQ;IACvB,aAAa,SAAS,QAAQ,eAAe,SAAS;IACtD,aAAa,SAAS,QAAQ;GAChC,CAAC;EACH,CAAC;EAGH,IAAI,SAAS,MACX,cAAc,KAAK;GACjB,MAAM;GACN,QAAQ;GACR,UAAU,OAAO,sBAAsB,CAAC,GAAG,SAAS,IAAI,CAAC;EAC3D,CAAC;EAGH,IAAI,SAAS,UACX,cAAc,KAAK;GACjB,MAAM;GACN,QAAQ;GACR,UAAU,OAAO,uBACf,SAAS,SAAS,MAClB,SAAS,SAAS,KACpB;EACF,CAAC;EAOH,MAAM,QADc,IAAI,QAAQ,GAAG,EAAE,CAAC,EAAE,OAAO,IAAI,MAAM,KAEpD,SAAS,eAAe,kBAAkB,IAAI,OAAO,IACtD,CAAC;EACL,IAAI,MAAM,UAAU,GAClB,cAAc,KAAK;GACjB,MAAM;GACN,QAAQ;GACR,UAAU,OAAO,yBACf,MAAM,KAAK,UAAU;IAAE,MAAM,KAAK;IAAM,KAAK,KAAK;GAAK,EAAE,CAC3D;EACF,CAAC;EAGH,IAAI,SAAS,QACX,cAAc,KACZ,GAAG,SAAS,OAAO,KAChB,cAA2B;GAC1B,MAAM;GACN,QAAQ;GACR;EACF,EACF,CACF;EAGF,KAAK,MAAM,YAAY,OAAO,cAAc,eAAe,EAAE,UAAU,CAAC,GACtE,KAAK,KAAK,EAAE,kBAAkB,SAAS,CAAC;EAO1C,MAAM,OAAgB;GACd;GACN,OAAO,CAAC;IAAE,KAAK;IAAa,MAAM;GAAU,CAAC;EAC/C;EACA,OAAO,OAAO,kBAAkB,KAAA,IAAY,OAAO,OAAO,cAAc,IAAI;CAC9E;CAEA,MAAM,QAAgC,QAAsB;EAC1D,MAAM,WAAW,IAAI,MAAM,WAAW,KAAK;EAC3C,IAAI,aAAa,KAAA,GACf,MAAM,IAAI,MAAM,+CAA+C,IAAI,MAAM,SAAS;EAEpF,OAAO,QAAQ,KAAK,QAAQ;CAC9B;CAEA,OAAO;EAAE;EAAS;EAAM,GAAG;CAAO;AACpC"}
1
+ {"version":3,"file":"react.js","names":["composeJsonLd","composeEntries"],"sources":["../src/react/breadcrumbs.tsx","../src/react/site.ts","../src/react/json-ld-composition.ts","../src/react/json-ld.ts","../src/react/create-seo.ts"],"sourcesContent":["import type { AnyRouteMatch } from \"@tanstack/react-router\";\nimport { Link, useMatches } from \"@tanstack/react-router\";\nimport { Fragment } from \"react\";\n\nexport interface CrumbTrailItem {\n name: string;\n path: string;\n}\n\n/**\n * Walk the match chain in order, keeping matches that declare `staticData.seo.crumb`,\n * resolving string | fn form. Shared by <Breadcrumbs/> and seoHead's BreadcrumbList.\n */\nexport function resolveCrumbTrail(matches: ReadonlyArray<AnyRouteMatch>): Array<CrumbTrailItem> {\n const trail: Array<CrumbTrailItem> = [];\n for (const match of matches) {\n const crumb = match.staticData.seo?.crumb;\n if (crumb === undefined) continue;\n const name = typeof crumb === \"function\" ? crumb(match) : crumb;\n trail.push({ name, path: match.pathname });\n }\n return trail;\n}\n\nexport function Breadcrumbs({ className }: { className?: string | undefined }) {\n const trail = resolveCrumbTrail(useMatches());\n if (trail.length < 2) return null;\n\n const lastIndex = trail.length - 1;\n return (\n <nav aria-label=\"Breadcrumb\" className={className}>\n <ol className=\"text-muted-foreground flex items-center gap-2 font-mono text-[11px] tracking-wide uppercase\">\n {trail.map((item, index) => {\n const isLast = index === lastIndex;\n return (\n <Fragment key={item.path}>\n {index > 0 ? (\n <li aria-hidden=\"true\" className=\"text-muted-foreground/50\">\n /\n </li>\n ) : null}\n <li\n aria-current={isLast ? \"page\" : undefined}\n className={isLast ? \"text-foreground truncate\" : undefined}\n >\n {isLast ? (\n item.name\n ) : (\n <Link to={item.path} className=\"hover:text-foreground transition-colors\">\n {item.name}\n </Link>\n )}\n </li>\n </Fragment>\n );\n })}\n </ol>\n </nav>\n );\n}\n","/**\n * Site identity — the values a package cannot know about its host.\n *\n * Bound once through {@link createSeo}, so the ~30 route call sites that render\n * a head never thread an origin or a brand name through their arguments.\n * Everything here is a *value*; the schema construction it feeds lives in\n * `json-ld.ts`.\n */\n\nimport type { SeoHead } from \"./create-seo\";\nimport type { SeoJsonLdConfig } from \"./json-ld-composition\";\n\n/** Absolute URL for an origin-relative path; an already-absolute URL passes through. */\nexport function absoluteUrl(origin: string, pathOrUrl: string): string {\n return pathOrUrl.startsWith(\"http\") ? pathOrUrl : `${origin}${pathOrUrl}`;\n}\n\nexport interface SeoSite {\n /** Brand name: Organization/WebSite `name`, Article publisher, Service provider default. */\n name: string;\n /** Organization `logo`. Origin-relative path or absolute URL. */\n logo: string;\n /** Article `publisher.logo` (Google wants an ImageObject distinct from the brand mark). */\n publisherLogo: string;\n /** Article `image` when the instance declares none. */\n defaultImage: string;\n /** Article `author` when the instance declares none. */\n defaultAuthor: { name: string; url?: string | undefined };\n}\n\n/** Public mailing address rendered as a schema.org PostalAddress. */\nexport interface SeoPostalAddress {\n streetAddress: string;\n addressLocality: string;\n addressRegion: string;\n postalCode: string;\n addressCountry: string;\n}\n\n/** The site-wide Organization entity (Knowledge Graph). */\nexport interface SeoOrganization {\n legalName?: string | undefined;\n description: string;\n sameAs: ReadonlyArray<string>;\n contactPoint: { contactType: string; email: string };\n address?: SeoPostalAddress | undefined;\n}\n\n/** The site-wide WebSite entity (sitelinks search box). */\nexport interface SeoWebsite {\n /** Origin-relative search target carrying the `{search_term_string}` placeholder. */\n searchPath: string;\n}\n\nexport interface SeoConfig {\n /** Canonical origin, no trailing slash — e.g. `https://example.com`. */\n origin: string;\n site: SeoSite;\n organization: SeoOrganization;\n website: SeoWebsite;\n jsonLd?: SeoJsonLdConfig | undefined;\n /**\n * Last-mile override for every head `seoHead` renders, e.g. to append\n * site-specific meta. Runs after the canonical, title template, and JSON-LD.\n */\n transformHead?: ((head: SeoHead) => SeoHead) | undefined;\n}\n","import type {\n Article,\n BreadcrumbList,\n FAQPage,\n Graph,\n IdReference,\n ItemList,\n Organization,\n Service,\n Thing,\n WebSite,\n WithContext,\n} from \"schema-dts\";\n\n/** Any schema.org entity accepted by `schema-dts`. */\nexport type JsonLdNode = Extract<Thing, object>;\n\nimport type { JsonLdDocument } from \"../core/declare\";\n\nexport type { JsonLdDocument };\n\nexport interface JsonLdEntityIds {\n organization: string;\n website: string;\n}\n\nexport type JsonLdEntry =\n | {\n kind: \"organization\";\n source: \"generated\";\n document: WithContext<Organization>;\n }\n | { kind: \"website\"; source: \"generated\"; document: WithContext<WebSite> }\n | { kind: \"article\"; source: \"generated\"; document: WithContext<Article> }\n | { kind: \"service\"; source: \"generated\"; document: WithContext<Service> }\n | { kind: \"faq\"; source: \"generated\"; document: WithContext<FAQPage> }\n | {\n kind: \"breadcrumb\";\n source: \"generated\";\n document: WithContext<BreadcrumbList>;\n }\n | { kind: \"item-list\"; source: \"generated\"; document: WithContext<ItemList> }\n | { kind: \"custom\"; source: \"site\" | \"page\"; document: JsonLdDocument };\n\nexport interface JsonLdTransformContext {\n /** Canonical site origin configured through `createSeo`. */\n origin: string;\n /** Stable identifiers for the plugin's generated site entities. */\n entityIds: JsonLdEntityIds;\n /** Canonical page URL when composition happens for a route. */\n canonical?: string | undefined;\n}\n\n/** Return no document to suppress an entry, one to replace it, or an array to expand it. */\nexport type JsonLdTransformResult =\n | JsonLdDocument\n | ReadonlyArray<JsonLdDocument>\n | false\n | null\n | undefined;\n\nexport type JsonLdTransform = (\n entry: JsonLdEntry,\n context: JsonLdTransformContext,\n) => JsonLdTransformResult;\n\nexport interface SeoJsonLdConfig {\n /** Custom entities included by `generateSiteGraphSchema`. */\n site?:\n | ReadonlyArray<JsonLdDocument>\n | ((entityIds: JsonLdEntityIds) => ReadonlyArray<JsonLdDocument>)\n | undefined;\n /** Open composition hook for generated and custom entries. */\n transform?: JsonLdTransform | undefined;\n}\n\n/** Add the schema.org context to an entity while preserving its concrete type. */\nexport function defineJsonLd<const Node extends JsonLdNode & object>(\n node: Node,\n): Node & { \"@context\": \"https://schema.org\" } {\n return { \"@context\": \"https://schema.org\", ...node };\n}\n\n/** Reference a canonical entity declared elsewhere in the same graph or page. */\nexport function jsonLdRef(id: string): IdReference {\n return { \"@id\": id };\n}\n\n/** Extend a generated or custom document without rebuilding its existing properties. */\nexport function extendJsonLd<\n const Document extends JsonLdDocument,\n const Extension extends object,\n>(document: Document, extension: Extension): Document & Extension {\n return { ...(document as unknown as object), ...extension } as Document &\n Extension;\n}\n\nconst documentNodes = (document: JsonLdDocument): ReadonlyArray<JsonLdNode> => {\n if (\"@graph\" in document) {\n return document[\"@graph\"] as ReadonlyArray<JsonLdNode>;\n }\n const { \"@context\": _context, ...node } = document as unknown as Record<\n string,\n unknown\n >;\n return [node as JsonLdNode];\n};\n\n/** Compose related schema.org documents into one graph without nested `@context` values. */\nexport function jsonLdGraph(documents: ReadonlyArray<JsonLdDocument>): Graph {\n return {\n \"@context\": \"https://schema.org\",\n \"@graph\": documents.flatMap(documentNodes),\n };\n}\n\n/** Apply an optional zero/one/many transform while preserving entry order. */\nexport function composeJsonLd(\n entries: ReadonlyArray<JsonLdEntry>,\n context: JsonLdTransformContext,\n transform?: JsonLdTransform,\n): Array<JsonLdDocument> {\n if (transform === undefined) {\n return entries.map((entry) => entry.document as JsonLdDocument);\n }\n\n return entries.flatMap((entry) => {\n const result = transform(entry, context);\n if (result === undefined || result === null || result === false) return [];\n return Array.isArray(result) ? [...result] : [result as JsonLdDocument];\n });\n}\n","/**\n * JSON-LD structured-data generators.\n *\n * schema.org payloads typed against `schema-dts`, which is a types-only devDep —\n * it erases at build, so this module keeps the entry's zero-runtime-dep rule.\n * The brand values (name, logo, sameAs, the Organization description) are the\n * host's, and arrive through {@link SeoConfig}; the schema construction is ours.\n *\n * @see https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data\n * @see https://schema.org/\n */\n\nimport type {\n Article,\n BreadcrumbList,\n FAQPage,\n Graph,\n ItemList,\n Organization,\n Person,\n Question,\n Service,\n WebSite,\n WithContext,\n} from \"schema-dts\";\n\nimport {\n composeJsonLd as composeEntries,\n jsonLdGraph,\n jsonLdRef,\n type JsonLdDocument,\n type JsonLdEntityIds,\n type JsonLdEntry,\n} from \"./json-ld-composition\";\nimport type { SeoFaq } from \"../core/declare\";\nimport { absoluteUrl, type SeoConfig } from \"./site\";\n\nexport interface ServiceParams {\n name: string;\n description: string;\n serviceType: string;\n provider?: string | undefined;\n areaServed?: string | undefined;\n}\n\n\nexport interface BreadcrumbItem {\n name: string;\n url: string;\n}\n\nexport interface ItemListEntry {\n name: string;\n url: string;\n}\n\nexport interface ArticleParams {\n headline: string;\n description: string;\n image?: string | undefined;\n datePublished: string;\n dateModified?: string | undefined;\n author: {\n name: string;\n url?: string | undefined;\n };\n url: string;\n}\n\n/** The JSON-LD generators, bound to one site identity. */\nexport interface JsonLd {\n readonly entityIds: JsonLdEntityIds;\n /** Brand entity for the Knowledge Graph. Render site-wide (root layout). */\n generateOrganizationSchema: () => WithContext<Organization>;\n /** WebSite entity with a sitelinks search box. Render on the homepage. */\n generateWebsiteSchema: () => WithContext<WebSite>;\n generateServiceSchema: (params: ServiceParams) => WithContext<Service>;\n generateFAQPageSchema: (faqs: SeoFaq[]) => WithContext<FAQPage>;\n generateBreadcrumbSchema: (\n items: BreadcrumbItem[],\n ) => WithContext<BreadcrumbList>;\n /** Describe a visibly rendered, ordered collection of canonical pages. */\n generateItemListSchema: (\n name: string,\n items: ReadonlyArray<ItemListEntry>,\n ) => WithContext<ItemList>;\n generateArticleSchema: (params: ArticleParams) => WithContext<Article>;\n /** Compose the Organization, WebSite, and configured site entities into one graph. */\n generateSiteGraphSchema: () => Graph | undefined;\n /** Apply the configured transform to generated or custom entries. */\n composeJsonLd: (\n entries: ReadonlyArray<JsonLdEntry>,\n context?: { canonical?: string | undefined },\n ) => Array<JsonLdDocument>;\n}\n\nexport function createJsonLd(config: SeoConfig): JsonLd {\n const { origin, site, organization, website } = config;\n const organizationId = `${origin}/#organization`;\n const websiteId = `${origin}/#website`;\n const entityIds = { organization: organizationId, website: websiteId };\n\n const generateOrganizationSchema = (): WithContext<Organization> => ({\n \"@context\": \"https://schema.org\",\n \"@type\": \"Organization\",\n \"@id\": organizationId,\n name: site.name,\n ...(organization.legalName === undefined\n ? {}\n : { legalName: organization.legalName }),\n url: origin,\n logo: absoluteUrl(origin, site.logo),\n description: organization.description,\n sameAs: [...organization.sameAs],\n contactPoint: {\n \"@type\": \"ContactPoint\",\n contactType: organization.contactPoint.contactType,\n email: organization.contactPoint.email,\n },\n ...(organization.address === undefined\n ? {}\n : {\n address: {\n \"@type\": \"PostalAddress\" as const,\n ...organization.address,\n },\n }),\n });\n\n const generateWebsiteSchema = (): WithContext<WebSite> => ({\n \"@context\": \"https://schema.org\",\n \"@type\": \"WebSite\",\n \"@id\": websiteId,\n name: site.name,\n url: origin,\n publisher: jsonLdRef(organizationId),\n potentialAction: {\n \"@type\": \"SearchAction\",\n target: {\n \"@type\": \"EntryPoint\",\n urlTemplate: absoluteUrl(origin, website.searchPath),\n },\n query: \"required name=search_term_string\",\n },\n });\n\n const generateServiceSchema = (\n params: ServiceParams,\n ): WithContext<Service> => ({\n \"@context\": \"https://schema.org\",\n \"@type\": \"Service\",\n name: params.name,\n description: params.description,\n serviceType: params.serviceType,\n provider: {\n \"@type\": \"Organization\",\n ...(params.provider === undefined\n ? { \"@id\": organizationId, url: origin }\n : {}),\n name: params.provider ?? site.name,\n },\n areaServed: params.areaServed ?? \"Worldwide\",\n });\n\n const generateFAQPageSchema = (faqs: SeoFaq[]): WithContext<FAQPage> => {\n const questions: Question[] = faqs.map((faq) => ({\n \"@type\": \"Question\",\n name: faq.question,\n acceptedAnswer: {\n \"@type\": \"Answer\",\n text: faq.answer,\n },\n }));\n\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"FAQPage\",\n mainEntity: questions,\n };\n };\n\n const generateBreadcrumbSchema = (\n items: BreadcrumbItem[],\n ): WithContext<BreadcrumbList> => ({\n \"@context\": \"https://schema.org\",\n \"@type\": \"BreadcrumbList\",\n itemListElement: items.map((item, index) => ({\n \"@type\": \"ListItem\",\n position: index + 1,\n name: item.name,\n item: `${origin}${item.url}`,\n })),\n });\n\n const generateItemListSchema = (\n name: string,\n items: ReadonlyArray<ItemListEntry>,\n ): WithContext<ItemList> => ({\n \"@context\": \"https://schema.org\",\n \"@type\": \"ItemList\",\n name,\n numberOfItems: items.length,\n itemListElement: items.map((item, index) => ({\n \"@type\": \"ListItem\",\n position: index + 1,\n name: item.name,\n url: `${origin}${item.url}`,\n })),\n });\n\n const generateArticleSchema = (\n params: ArticleParams,\n ): WithContext<Article> => {\n const authorSchema: Person = {\n \"@type\": \"Person\",\n name: params.author.name,\n ...(params.author.url && { url: params.author.url }),\n };\n\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"Article\",\n headline: params.headline,\n description: params.description,\n // Deliberately NOT absolutized: a declared instance image lands verbatim\n // (og:image is where the absolute form is required, and seoHead does that).\n image: params.image ?? absoluteUrl(origin, site.defaultImage),\n datePublished: params.datePublished,\n dateModified: params.dateModified ?? params.datePublished,\n author: authorSchema,\n publisher: {\n \"@type\": \"Organization\",\n \"@id\": organizationId,\n name: site.name,\n logo: {\n \"@type\": \"ImageObject\",\n url: absoluteUrl(origin, site.publisherLogo),\n },\n },\n mainEntityOfPage: {\n \"@type\": \"WebPage\",\n \"@id\": params.url,\n },\n };\n };\n\n const composeJsonLd: JsonLd[\"composeJsonLd\"] = (entries, context = {}) =>\n composeEntries(\n entries,\n {\n origin,\n entityIds,\n ...(context.canonical === undefined\n ? {}\n : { canonical: context.canonical }),\n },\n config.jsonLd?.transform,\n );\n\n const generateSiteGraphSchema = (): Graph | undefined => {\n const configuredSite =\n typeof config.jsonLd?.site === \"function\"\n ? config.jsonLd.site(entityIds)\n : (config.jsonLd?.site ?? []);\n const entries: Array<JsonLdEntry> = [\n {\n kind: \"organization\",\n source: \"generated\",\n document: generateOrganizationSchema(),\n },\n {\n kind: \"website\",\n source: \"generated\",\n document: generateWebsiteSchema(),\n },\n ...configuredSite.map(\n (document): JsonLdEntry => ({\n kind: \"custom\",\n source: \"site\",\n document,\n }),\n ),\n ];\n const documents = composeJsonLd(entries);\n return documents.length === 0 ? undefined : jsonLdGraph(documents);\n };\n\n return {\n entityIds,\n generateOrganizationSchema,\n generateWebsiteSchema,\n generateServiceSchema,\n generateFAQPageSchema,\n generateBreadcrumbSchema,\n generateItemListSchema,\n generateArticleSchema,\n generateSiteGraphSchema,\n composeJsonLd,\n };\n}\n","/**\n * The render layer: one route's SEO declaration plus its per-instance content,\n * composed into the meta/link descriptors TanStack Router renders into <head>,\n * with the JSON-LD that page warrants.\n *\n * {@link createSeo} binds the site identity once (see `site.ts`) and returns\n * the bound API, so a route file calls `seoHead(ctx, instance)` and never sees\n * an origin or a brand name.\n */\n\nimport type { AnyRouteMatch, MetaDescriptor } from \"@tanstack/react-router\";\n\nimport { applyTitleTemplate, type SeoPageHead } from \"../core/declare\";\n\nimport { resolveCrumbTrail } from \"./breadcrumbs\";\nimport type { JsonLdDocument, JsonLdEntry } from \"./json-ld-composition\";\nimport { absoluteUrl, type SeoConfig } from \"./site\";\nimport { createJsonLd, type JsonLd } from \"./json-ld\";\n\n/** Structural subset of TanStack's head() ctx — the leaf match plus the full chain. */\nexport interface SeoHeadCtx {\n matches: ReadonlyArray<AnyRouteMatch>;\n match: AnyRouteMatch;\n}\n\nexport interface SeoHead {\n meta: NonNullable<AnyRouteMatch[\"meta\"]>;\n links: Array<{ rel: \"canonical\"; href: string }>;\n}\n\n/** The render API, bound to one site identity. */\nexport interface Seo extends JsonLd {\n seoHead: (ctx: SeoHeadCtx, instance: SeoPageHead) => SeoHead;\n /**\n * `head()` for a static route that declares its head in `staticData.seo.head`:\n *\n * ```ts\n * createFileRoute(\"/pricing\")({\n * staticData: { seo: { kind: \"page\", sitemap, head: { title, description, faqs } } },\n * head: seo.head,\n * })\n * ```\n *\n * The graph, `pageHeads`, and the checks read the same declaration.\n *\n * Generic so TanStack infers nothing from it: a `head` typed with\n * `AnyRouteMatch` would make the route's search and loader types `any`, and\n * that spreads through the route tree.\n */\n head: <Ctx extends SeoHeadCtx>(ctx: Ctx) => SeoHead;\n}\n\n/** Strip a trailing slash from a pathname, keeping the root \"/\" intact. */\nfunction normalizePathname(pathname: string): string {\n return pathname.length > 1 && pathname.endsWith(\"/\")\n ? pathname.slice(0, -1)\n : pathname;\n}\n\nexport function createSeo(config: SeoConfig): Seo {\n const { origin, site } = config;\n const jsonLd = createJsonLd(config);\n\n const seoHead = (ctx: SeoHeadCtx, instance: SeoPageHead): SeoHead => {\n const canonical = `${origin}${instance.canonicalPath ?? normalizePathname(ctx.match.pathname)}`;\n const title = applyTitleTemplate(ctx.match.staticData.seo?.titleTemplate, instance.title);\n const resolvedOgTitle = instance.ogTitle ?? title;\n const resolvedOgDescription =\n instance.ogDescription ?? instance.description;\n const routeSeo = ctx.match.staticData.seo;\n const { article } = instance;\n const jsonLdEntries: Array<JsonLdEntry> = [];\n\n const meta: Array<MetaDescriptor> = [\n { title },\n { name: \"description\", content: instance.description },\n { property: \"og:title\", content: resolvedOgTitle },\n { property: \"og:description\", content: resolvedOgDescription },\n { property: \"og:type\", content: article ? \"article\" : \"website\" },\n { property: \"og:url\", content: canonical },\n { name: \"twitter:card\", content: \"summary_large_image\" },\n { name: \"twitter:title\", content: resolvedOgTitle },\n { name: \"twitter:description\", content: resolvedOgDescription },\n ];\n\n const robots = instance.robots ?? routeSeo?.robots;\n if (robots !== undefined) {\n meta.push({ name: \"robots\", content: robots });\n }\n\n if (article) {\n if (article.tags?.length) {\n meta.push({ name: \"keywords\", content: article.tags.join(\", \") });\n }\n meta.push(\n { property: \"article:published_time\", content: article.publishedAt },\n {\n property: \"article:modified_time\",\n content: article.modifiedAt ?? article.publishedAt,\n },\n );\n if (article.image !== undefined) {\n const imageUrl = absoluteUrl(origin, article.image);\n meta.push(\n { property: \"og:image\", content: imageUrl },\n { name: \"twitter:image\", content: imageUrl },\n );\n }\n }\n\n if (article) {\n jsonLdEntries.push({\n kind: \"article\",\n source: \"generated\",\n document: jsonLd.generateArticleSchema({\n headline: resolvedOgTitle,\n description: instance.description,\n image: article.image,\n datePublished: article.publishedAt,\n dateModified: article.modifiedAt ?? article.publishedAt,\n author: article.author ?? site.defaultAuthor,\n url: canonical,\n }),\n });\n }\n\n if (!article && instance.keywords) {\n meta.push({ name: \"keywords\", content: instance.keywords.join(\", \") });\n }\n\n if (instance.service) {\n jsonLdEntries.push({\n kind: \"service\",\n source: \"generated\",\n document: jsonLd.generateServiceSchema({\n name: instance.service.name,\n description: instance.service.description ?? instance.description,\n serviceType: instance.service.serviceType,\n }),\n });\n }\n\n if (instance.faqs) {\n jsonLdEntries.push({\n kind: \"faq\",\n source: \"generated\",\n document: jsonLd.generateFAQPageSchema([...instance.faqs]),\n });\n }\n\n if (instance.itemList) {\n jsonLdEntries.push({\n kind: \"item-list\",\n source: \"generated\",\n document: jsonLd.generateItemListSchema(\n instance.itemList.name,\n instance.itemList.items,\n ),\n });\n }\n\n // TanStack accumulates every matched route's head output. Only the current leaf\n // owns the BreadcrumbList; otherwise each parent repeats a progressively stale\n // trail alongside the leaf's canonical trail on nested pages.\n const isLeafMatch = ctx.matches.at(-1)?.id === ctx.match.id;\n const trail = isLeafMatch\n ? (instance.breadcrumbs ?? resolveCrumbTrail(ctx.matches))\n : [];\n if (trail.length >= 2) {\n jsonLdEntries.push({\n kind: \"breadcrumb\",\n source: \"generated\",\n document: jsonLd.generateBreadcrumbSchema(\n trail.map((item) => ({ name: item.name, url: item.path })),\n ),\n });\n }\n\n if (instance.jsonLd) {\n jsonLdEntries.push(\n ...instance.jsonLd.map(\n (document): JsonLdEntry => ({\n kind: \"custom\",\n source: \"page\",\n document,\n }),\n ),\n );\n }\n\n for (const document of jsonLd.composeJsonLd(jsonLdEntries, { canonical })) {\n meta.push({ \"script:ld+json\": document });\n }\n\n // React's head types (JSX.IntrinsicElements['meta']) model only <meta> attributes;\n // TanStack renders `script:ld+json` entries as JSON-LD <script> tags at runtime. The\n // installed @tanstack/react-router augments leaf head meta to those JSX attributes, so\n // the JSON-LD entries are asserted to it (same pattern as an inline root JSON-LD).\n const head: SeoHead = {\n meta: meta as NonNullable<AnyRouteMatch[\"meta\"]>,\n links: [{ rel: \"canonical\", href: canonical }],\n };\n return config.transformHead === undefined ? head : config.transformHead(head);\n };\n\n const head = <Ctx extends SeoHeadCtx>(ctx: Ctx): SeoHead => {\n const declared = ctx.match.staticData.seo?.head;\n if (declared === undefined) {\n throw new Error(`seo.head needs staticData.seo.head on route ${ctx.match.routeId}`);\n }\n return seoHead(ctx, declared);\n };\n\n return { seoHead, head, ...jsonLd };\n}\n"],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
9
+ var __exportAll = (all, no_symbols) => {
10
+ let target = {};
11
+ for (var name in all) __defProp(target, name, {
12
+ get: all[name],
13
+ enumerable: true
14
+ });
15
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
16
+ return target;
17
+ };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
20
+ key = keys[i];
21
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
22
+ get: ((k) => from[k]).bind(null, key),
23
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
24
+ });
25
+ }
26
+ return to;
27
+ };
28
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
29
+ value: mod,
30
+ enumerable: true
31
+ }) : target, mod));
32
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) {
33
+ if (typeof require !== "undefined") return require.apply(this, arguments);
34
+ throw Error("Calling `require` for \"" + x + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
35
+ });
36
+ //#endregion
37
+ export { __toESM as i, __exportAll as n, __require as r, __commonJSMin as t };
@@ -0,0 +1,28 @@
1
+ //#region node_modules/@earendil-works/pi-ai/dist/utils/sanitize-unicode.js
2
+ /**
3
+ * Removes unpaired Unicode surrogate characters from a string.
4
+ *
5
+ * Unpaired surrogates (high surrogates 0xD800-0xDBFF without matching low surrogates 0xDC00-0xDFFF,
6
+ * or vice versa) cause JSON serialization errors in many API providers.
7
+ *
8
+ * Valid emoji and other characters outside the Basic Multilingual Plane use properly paired
9
+ * surrogates and will NOT be affected by this function.
10
+ *
11
+ * @param text - The text to sanitize
12
+ * @returns The sanitized text with unpaired surrogates removed
13
+ *
14
+ * @example
15
+ * // Valid emoji (properly paired surrogates) are preserved
16
+ * sanitizeSurrogates("Hello 🙈 World") // => "Hello 🙈 World"
17
+ *
18
+ * // Unpaired high surrogate is removed
19
+ * const unpaired = String.fromCharCode(0xD83D); // high surrogate without low
20
+ * sanitizeSurrogates(`Text ${unpaired} here`) // => "Text here"
21
+ */
22
+ function sanitizeSurrogates(text) {
23
+ return text.replace(/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g, "");
24
+ }
25
+ //#endregion
26
+ export { sanitizeSurrogates as t };
27
+
28
+ //# sourceMappingURL=sanitize-unicode-Ds14l9Om.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize-unicode-Ds14l9Om.js","names":[],"sources":["../node_modules/@earendil-works/pi-ai/dist/utils/sanitize-unicode.js"],"sourcesContent":["/**\n * Removes unpaired Unicode surrogate characters from a string.\n *\n * Unpaired surrogates (high surrogates 0xD800-0xDBFF without matching low surrogates 0xDC00-0xDFFF,\n * or vice versa) cause JSON serialization errors in many API providers.\n *\n * Valid emoji and other characters outside the Basic Multilingual Plane use properly paired\n * surrogates and will NOT be affected by this function.\n *\n * @param text - The text to sanitize\n * @returns The sanitized text with unpaired surrogates removed\n *\n * @example\n * // Valid emoji (properly paired surrogates) are preserved\n * sanitizeSurrogates(\"Hello 🙈 World\") // => \"Hello 🙈 World\"\n *\n * // Unpaired high surrogate is removed\n * const unpaired = String.fromCharCode(0xD83D); // high surrogate without low\n * sanitizeSurrogates(`Text ${unpaired} here`) // => \"Text here\"\n */\nexport function sanitizeSurrogates(text) {\n // Replace unpaired high surrogates (0xD800-0xDBFF not followed by low surrogate)\n // Replace unpaired low surrogates (0xDC00-0xDFFF not preceded by high surrogate)\n return text.replace(/[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?<![\\uD800-\\uDBFF])[\\uDC00-\\uDFFF]/g, \"\");\n}\n//# sourceMappingURL=sanitize-unicode.js.map"],"x_google_ignoreList":[0],"mappings":";;;;;;;;;;;;;;;;;;;;;AAoBA,SAAgB,mBAAmB,MAAM;CAGrC,OAAO,KAAK,QAAQ,2EAA2E,EAAE;AACrG"}