@tenphi/renderer 0.19.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.
- package/LICENSE +21 -0
- package/README.md +23 -0
- package/dist/client/appearance.d.ts +12 -0
- package/dist/client/appearance.d.ts.map +1 -0
- package/dist/client/appearance.js +66 -0
- package/dist/client/appearance.js.map +1 -0
- package/dist/client/code-copy.d.ts +1 -0
- package/dist/client/code-copy.js +63 -0
- package/dist/client/code-copy.js.map +1 -0
- package/dist/client/heading-links.d.ts +6 -0
- package/dist/client/heading-links.d.ts.map +1 -0
- package/dist/client/heading-links.js +87 -0
- package/dist/client/heading-links.js.map +1 -0
- package/dist/client/mobile-toc.d.ts +1 -0
- package/dist/client/mobile-toc.js +28 -0
- package/dist/client/mobile-toc.js.map +1 -0
- package/dist/client/navigation.d.ts +1 -0
- package/dist/client/navigation.js +112 -0
- package/dist/client/navigation.js.map +1 -0
- package/dist/client/page-copy.d.ts +1 -0
- package/dist/client/page-copy.js +34 -0
- package/dist/client/page-copy.js.map +1 -0
- package/dist/client/search.d.ts +13 -0
- package/dist/client/search.d.ts.map +1 -0
- package/dist/client/search.js +87 -0
- package/dist/client/search.js.map +1 -0
- package/dist/client/sidebar.d.ts +1 -0
- package/dist/client/sidebar.js +93 -0
- package/dist/client/sidebar.js.map +1 -0
- package/dist/client/tabs.d.ts +6 -0
- package/dist/client/tabs.d.ts.map +1 -0
- package/dist/client/tabs.js +64 -0
- package/dist/client/tabs.js.map +1 -0
- package/dist/components/Callout.astro +15 -0
- package/dist/components/Card.astro +13 -0
- package/dist/components/CodeGroup.astro +47 -0
- package/dist/components/ContrastIcon.astro +29 -0
- package/dist/components/EditLink.astro +11 -0
- package/dist/components/GlobalStyles.js +1675 -0
- package/dist/components/HeaderLinks.astro +84 -0
- package/dist/components/Icon.astro +39 -0
- package/dist/components/LastUpdated.astro +17 -0
- package/dist/components/LayoutComponents.js +866 -0
- package/dist/components/Logo.astro +37 -0
- package/dist/components/MobileNavigationTabs.astro +79 -0
- package/dist/components/MobileTocList.astro +22 -0
- package/dist/components/PackageVersion.astro +25 -0
- package/dist/components/PageActions.astro +29 -0
- package/dist/components/Pagination.astro +29 -0
- package/dist/components/Preview.astro +34 -0
- package/dist/components/SidebarList.astro +122 -0
- package/dist/components/SiteLogo.astro +40 -0
- package/dist/components/SiteTitle.astro +7 -0
- package/dist/components/Steps.astro +6 -0
- package/dist/components/Tab.astro +10 -0
- package/dist/components/TableOfContents.astro +23 -0
- package/dist/components/Tabs.astro +16 -0
- package/dist/components/TastyComponents.js +255 -0
- package/dist/components/VersionSwitcher.astro +44 -0
- package/dist/components/appearance-preferences.test.ts +91 -0
- package/dist/components/appearance-preferences.ts +57 -0
- package/dist/components/component-styles.test.ts +129 -0
- package/dist/components/component-styles.ts +65 -0
- package/dist/components/customize-component.js +8 -0
- package/dist/components/props.d.ts +38 -0
- package/dist/components/props.d.ts.map +1 -0
- package/dist/components/props.js +1 -0
- package/dist/components/props.ts +30 -0
- package/dist/components/svg-icon.test.ts +11 -0
- package/dist/components/svg-icon.ts +11 -0
- package/dist/components/tasty-states.d.ts +2 -0
- package/dist/components/tasty-states.js +42 -0
- package/dist/components-public.d.ts +21 -0
- package/dist/components.d.ts +10 -0
- package/dist/components.js +9 -0
- package/dist/content.d.ts +11 -0
- package/dist/content.d.ts.map +1 -0
- package/dist/content.js +16 -0
- package/dist/content.js.map +1 -0
- package/dist/eslint-plugin.d.ts +32 -0
- package/dist/eslint-plugin.d.ts.map +1 -0
- package/dist/eslint-plugin.js +155 -0
- package/dist/eslint-plugin.js.map +1 -0
- package/dist/icons/arrow-left.svg +1 -0
- package/dist/icons/arrow-right.svg +1 -0
- package/dist/icons/check.svg +1 -0
- package/dist/icons/chevron-down.svg +1 -0
- package/dist/icons/chevron-right.svg +1 -0
- package/dist/icons/close.svg +1 -0
- package/dist/icons/copy.svg +1 -0
- package/dist/icons/device-desktop.svg +1 -0
- package/dist/icons/favicon.svg +11 -0
- package/dist/icons/menu.svg +1 -0
- package/dist/icons/moon.svg +1 -0
- package/dist/icons/palette.svg +1 -0
- package/dist/icons/search.svg +1 -0
- package/dist/icons/sun.svg +1 -0
- package/dist/index-BuX_Sb5c.d.ts +10 -0
- package/dist/index-BuX_Sb5c.d.ts.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1648 -0
- package/dist/index.js.map +1 -0
- package/dist/localization.d.ts +69 -0
- package/dist/localization.d.ts.map +1 -0
- package/dist/localization.js +195 -0
- package/dist/localization.js.map +1 -0
- package/dist/markdown/rendered-content.d.ts +6 -0
- package/dist/markdown/rendered-content.d.ts.map +1 -0
- package/dist/markdown/rendered-content.js +34 -0
- package/dist/markdown/rendered-content.js.map +1 -0
- package/dist/messages-B_3xUzUb.js +14 -0
- package/dist/messages-B_3xUzUb.js.map +1 -0
- package/dist/navigation.d.ts +31 -0
- package/dist/navigation.d.ts.map +1 -0
- package/dist/navigation.js +165 -0
- package/dist/navigation.js.map +1 -0
- package/dist/overrides/DraftContentNotice.astro +8 -0
- package/dist/overrides/EmptyFooter.astro +3 -0
- package/dist/overrides/Footer.astro +23 -0
- package/dist/overrides/Head.astro +59 -0
- package/dist/overrides/Header.astro +139 -0
- package/dist/overrides/Hero.astro +73 -0
- package/dist/overrides/LanguageSelect.astro +63 -0
- package/dist/overrides/MarkdownContent.astro +14 -0
- package/dist/overrides/MobileMenuFooter.astro +15 -0
- package/dist/overrides/MobileMenuToggle.astro +36 -0
- package/dist/overrides/MobileTableOfContents.astro +37 -0
- package/dist/overrides/PageFrame.astro +35 -0
- package/dist/overrides/Search.astro +64 -0
- package/dist/overrides/Sidebar.astro +89 -0
- package/dist/overrides/SocialIcons.astro +27 -0
- package/dist/overrides/ThemeSelect.astro +148 -0
- package/dist/page-metadata.d.ts +13 -0
- package/dist/page-metadata.d.ts.map +1 -0
- package/dist/page-metadata.js +109 -0
- package/dist/page-metadata.js.map +1 -0
- package/dist/route-context.d.ts +85 -0
- package/dist/route-context.d.ts.map +1 -0
- package/dist/route-context.js +116 -0
- package/dist/route-context.js.map +1 -0
- package/dist/routes/DocsPage.astro +91 -0
- package/dist/routes/NotFound.astro +12 -0
- package/dist/routes/Page.astro +120 -0
- package/dist/styling.d.ts +17 -0
- package/dist/styling.d.ts.map +1 -0
- package/dist/styling.js +17 -0
- package/dist/styling.js.map +1 -0
- package/dist/tasty-states-BDKIbfw2.js +65 -0
- package/dist/tasty-states-BDKIbfw2.js.map +1 -0
- package/dist/theme/defaults.d.ts +21 -0
- package/dist/theme/defaults.d.ts.map +1 -0
- package/dist/theme/defaults.js +93 -0
- package/dist/theme/defaults.js.map +1 -0
- package/dist/theme/fonts.ts +64 -0
- package/dist/theme/shiki-theme.d.ts +13 -0
- package/dist/theme/shiki-theme.d.ts.map +1 -0
- package/dist/theme/shiki-theme.js +328 -0
- package/dist/theme/shiki-theme.js.map +1 -0
- package/dist/theme/tasty-config.d.ts +13 -0
- package/dist/theme/tasty-config.d.ts.map +1 -0
- package/dist/theme/tasty-config.js +16 -0
- package/dist/theme/tasty-config.js.map +1 -0
- package/dist/ui.d.ts +6 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +53 -0
- package/dist/ui.js.map +1 -0
- package/dist/versioning.d.ts +11 -0
- package/dist/versioning.d.ts.map +1 -0
- package/dist/versioning.js +38 -0
- package/dist/versioning.js.map +1 -0
- package/package.json +92 -0
- package/tasty.config.mjs +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["errorMessage"],"sources":["../src/hero-image.ts","../src/plugin-contract.ts","../src/site-logo.ts","../src/output-styles.ts","../src/markdown/rehype-mermaid.ts","../src/markdown/rehype-alerts.ts","../src/markdown/rehype-table-scroll.ts","../src/markdown/rehype-page-affordances.ts","../src/theme/fonts.ts","../src/theme/index.ts","../src/theme/font-cache.ts","../src/theme/font-loading.ts","../src/component-overrides.ts","../src/site-icons.ts","../src/output-path.ts","../src/agent-discovery.ts","../src/integration.ts"],"sourcesContent":["import { stat } from \"node:fs/promises\";\nimport { extname } from \"node:path\";\nimport sharp from \"sharp\";\nimport type { DocsEntry } from \"@tenphi/docs\";\n\nconst metadataCache = new Map<\n string,\n Promise<{ width: number; height: number; format: string }>\n>();\nexport async function resolveHeroMetadata(\n entry: Pick<DocsEntry, \"frontmatter\" | \"assets\" | \"sourcePath\">,\n) {\n const hero = entry.frontmatter.hero;\n const image = hero?.image;\n if (!hero || !image || \"html\" in image) return hero;\n const read = async (src: string) => {\n const asset = entry.assets.find(\n (asset) => asset.resolved === src || asset.publicPath === src,\n );\n let dimensions: { width: number; height: number; format: string };\n if (asset?.sourcePath) {\n const file = await stat(asset.sourcePath);\n const key = `${asset.sourcePath}:${file.mtimeMs}:${file.size}`;\n if (!metadataCache.has(key))\n metadataCache.set(\n key,\n sharp(asset.sourcePath)\n .metadata()\n .then((meta) => {\n const { width, height } = meta.autoOrient ?? meta;\n if (!width || !height || !meta.format)\n throw Error(\n `Cannot determine hero image dimensions for ${entry.sourcePath}.`,\n );\n return { width, height, format: meta.format };\n }),\n );\n dimensions = await metadataCache.get(key)!;\n } else if (image.width && image.height) {\n dimensions = {\n width: image.width,\n height: image.height,\n format:\n extname(src.split(/[?#]/, 1)[0] ?? src)\n .slice(1)\n .replace(\"jpg\", \"jpeg\") || \"png\",\n };\n } else\n throw Error(\n `Hero image ${src} in ${entry.sourcePath} needs width and height, or a relative local file whose dimensions can be read.`,\n );\n if (\n image.width &&\n image.height &&\n Math.abs(\n image.width / image.height - dimensions.width / dimensions.height,\n ) > 0.01\n )\n throw Error(\n `hero.image width/height in ${entry.sourcePath} must preserve the source aspect ratio.`,\n );\n return { src, ...dimensions };\n };\n if (\"file\" in image)\n return { ...hero, image: { ...image, file: await read(image.file) } };\n const [dark, light] = await Promise.all([\n read(image.dark),\n read(image.light),\n ]);\n if (Math.abs(dark.width / dark.height - light.width / light.height) > 0.01)\n throw Error(\n `Hero light/dark images in ${entry.sourcePath} must have the same aspect ratio.`,\n );\n return { ...hero, image: { ...image, dark, light } };\n}\n","import { DOCS_FRONTMATTER_KEYS, type DocsEntry } from \"@tenphi/docs\";\n\nexport type FrontmatterSchema =\n | {\n parseAsync(value: unknown): Promise<Record<string, unknown>>;\n }\n | {\n parse(value: unknown): Record<string, unknown>;\n };\n\nexport async function validatePluginFrontmatter(\n entries: DocsEntry[],\n schema: FrontmatterSchema | undefined,\n): Promise<void> {\n if (!schema) return;\n for (const entry of entries) {\n try {\n const parsed =\n \"parseAsync\" in schema\n ? await schema.parseAsync(structuredClone(entry.metadata))\n : schema.parse(structuredClone(entry.metadata));\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed))\n throw new Error(\"The schema must return a frontmatter object.\");\n for (const key of Object.keys(parsed)) {\n if (DOCS_FRONTMATTER_KEYS.has(key))\n throw new Error(\n `Custom schemas cannot set reserved field \"${key}\". Set it in source frontmatter instead.`,\n );\n }\n // Metadata crosses a JSON virtual module boundary, so reject lossy values.\n assertJsonMetadata(parsed);\n entry.metadata = { ...entry.metadata, ...parsed };\n } catch (error) {\n throw new Error(\n `Invalid plugin frontmatter in ${entry.sourcePath}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n}\n\nfunction assertJsonMetadata(\n value: unknown,\n ancestors = new Set<object>(),\n): void {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\")\n return;\n if (typeof value === \"number\" && Number.isFinite(value)) return;\n if (\n typeof value !== \"object\" ||\n value === null ||\n ancestors.has(value) ||\n (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype)\n )\n throw new Error(\n \"Custom metadata must contain only JSON values (no dates, functions, cycles, or undefined).\",\n );\n ancestors.add(value);\n for (const item of Object.values(value)) assertJsonMetadata(item, ancestors);\n ancestors.delete(value);\n}\n","import { createHash } from \"node:crypto\";\nimport { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport sharp from \"sharp\";\nimport type { SiteConfig } from \"@tenphi/docs\";\n\ninterface LogoImage {\n src: string;\n width: number;\n height: number;\n}\ninterface ResolvedSiteLogo {\n light: LogoImage;\n dark?: LogoImage;\n alt: string;\n href?: string;\n decorative: boolean;\n}\nexport interface SiteLogoSet {\n logo: ResolvedSiteLogo | false | undefined;\n sourcePaths: string[];\n assets: Array<{\n body: Buffer;\n contentType: string;\n outputPath: string;\n publicPath: string;\n }>;\n}\n\nexport async function resolveSiteLogo(\n root: string,\n base: string,\n site: SiteConfig = {},\n): Promise<SiteLogoSet> {\n if (site.logo === undefined || site.logo === false)\n return { logo: site.logo, sourcePaths: [], assets: [] };\n const config = typeof site.logo === \"string\" ? { src: site.logo } : site.logo;\n const assets: SiteLogoSet[\"assets\"] = [];\n const sourcePaths: string[] = [];\n const image = async (source: string, role: string): Promise<LogoImage> => {\n const path = resolve(root, source);\n const body = await readFile(path).catch(() => {\n throw new Error(`site.logo.${role}: cannot read local image ${path}.`);\n });\n const metadata = await sharp(body, { animated: false })\n .metadata()\n .catch(() => {\n throw new Error(`site.logo.${role}: ${path} is not a supported image.`);\n });\n const format = metadata.format;\n if (\n !format ||\n ![\"svg\", \"png\", \"jpeg\", \"webp\", \"avif\", \"gif\"].includes(format)\n )\n throw new Error(\n `site.logo.${role}: use an SVG, PNG, JPEG, WebP, AVIF, or GIF image.`,\n );\n const width =\n config.width ??\n (config.height && metadata.width && metadata.height\n ? (config.height * metadata.width) / metadata.height\n : metadata.width);\n const height =\n config.height ??\n (config.width && metadata.width && metadata.height\n ? (config.width * metadata.height) / metadata.width\n : metadata.height);\n if (!width || !height)\n throw new Error(\n `site.logo.${role}: provide intrinsic width and height for ${path}.`,\n );\n const hash = createHash(\"sha256\").update(body).digest(\"hex\").slice(0, 20);\n const outputPath = `_cookbook/logos/${hash}.${format === \"jpeg\" ? \"jpg\" : format}`;\n const publicPath = `${base.replace(/\\/$/, \"\")}/${outputPath}`;\n sourcePaths.push(path);\n if (!assets.some((asset) => asset.outputPath === outputPath))\n assets.push({\n body,\n outputPath,\n publicPath,\n contentType: format === \"svg\" ? \"image/svg+xml\" : `image/${format}`,\n });\n return { src: publicPath, width, height };\n };\n const light = await image(\n config.src ?? config.light!,\n config.src ? \"src\" : \"light\",\n );\n const dark = config.dark ? await image(config.dark, \"dark\") : undefined;\n if (\n dark &&\n Math.abs(light.width / light.height - dark.width / dark.height) > 0.01\n )\n throw new Error(\n \"site.logo: light and dark variants must have the same aspect ratio to prevent layout shifts. Set matching intrinsic dimensions or use matching artwork.\",\n );\n return {\n logo: {\n light,\n ...(dark ? { dark } : {}),\n alt: config.alt || site.title || \"Documentation\",\n decorative: config.decorative ?? true,\n ...(config.href ? { href: config.href } : {}),\n },\n assets,\n sourcePaths,\n };\n}\n","import { fromHtml } from \"hast-util-from-html\";\n\n/** Parse attributes rather than matching text in code, scripts or escaped srcdoc. */\nexport function assertTastyOutput(html: string, path: string): void {\n const tree = fromHtml(html);\n const visit = (node: {\n type: string;\n tagName?: string;\n properties?: Record<string, unknown>;\n children?: unknown[];\n content?: unknown;\n }) => {\n const props = node.properties ?? {};\n const stylesheet =\n node.tagName === \"link\" &&\n Array.isArray(props.rel) &&\n props.rel.includes(\"stylesheet\");\n if (\n node.tagName === \"style\" ||\n Object.hasOwn(props, \"style\") ||\n (stylesheet && !Object.hasOwn(props, \"dataTastySsr\"))\n ) {\n throw new Error(\n `Non-Tasty CSS found in ${path}: <${node.tagName}${Object.hasOwn(props, \"style\") ? \" style=…\" : \"\"}>. Use theme.styles or Tasty components; isolate example CSS in a sandboxed Preview.`,\n );\n }\n // srcdoc is another document. Only a sandbox without same-origin access may\n // contain authored styles. A template/shadow root is still part of this one.\n if (\n typeof props.srcDoc === \"string\" &&\n (!Array.isArray(props.sandbox) ||\n props.sandbox.includes(\"allow-same-origin\"))\n )\n assertTastyOutput(props.srcDoc, `${path} (unsandboxed iframe)`);\n node.children?.forEach((child) => visit(child as typeof node));\n if (node.content) visit(node.content as typeof node);\n };\n visit(tree);\n}\n","import { renderMermaidSVG } from \"beautiful-mermaid\";\n\ntype HastNode = {\n type: string;\n value?: string;\n tagName?: string;\n properties?: Record<string, unknown>;\n children?: HastNode[];\n};\n\ntype SatteriContext = {\n replaceNode(node: Readonly<HastNode>, replacement: HastNode): void;\n setProperty(node: Readonly<HastNode>, key: string, value: unknown): void;\n textContent(node: Readonly<HastNode>): string;\n};\n\nconst sourceStyleDirective = /^\\s*(?:classDef|style|linkStyle)\\s+.*$/gim;\nconst accessibilityDirective = /^\\s*acc(?:Title|Descr):\\s*.*$/gim;\nconst svgStyleBlock = /\\s*<style>[\\s\\S]*?<\\/style>\\s*/gi;\nconst supportedDiagram =\n /^(?:(?:flowchart|graph)(?:\\s+(?:TB|TD|BT|RL|LR))?|stateDiagram(?:-v2)?|sequenceDiagram|classDiagram|erDiagram)\\b/i;\n\n/** Render supported Mermaid fences to theme-responsive SVG at build time. */\nexport function rehypeMermaid() {\n return (tree: HastNode): void => {\n replaceMermaidCodeBlocks(tree);\n };\n}\n\n/** Sätteri adapter for Astro's default Markdown processor. */\nexport const satteriMermaid = {\n name: \"cookbook:mermaid\",\n element: {\n filter: [\"pre\"],\n visit(node: Readonly<HastNode>, context: SatteriContext): void {\n if (!isMermaidCodeBlock(node)) return;\n try {\n context.replaceNode(node, {\n type: \"raw\",\n value: renderMermaidElement(context.textContent(node)),\n });\n } catch {\n context.setProperty(node, \"data-mermaid-state\", \"error\");\n }\n },\n },\n};\n\nfunction replaceMermaidCodeBlocks(parent: HastNode): void {\n if (!parent.children) return;\n for (const [index, child] of parent.children.entries()) {\n if (isMermaidCodeBlock(child)) {\n const source = textContent(child);\n try {\n parent.children[index] = {\n type: \"raw\",\n value: renderMermaidElement(source),\n };\n } catch {\n child.properties = {\n ...child.properties,\n \"data-mermaid-state\": \"error\",\n };\n }\n continue;\n }\n replaceMermaidCodeBlocks(child);\n }\n}\n\nfunction renderMermaidElement(source: string): string {\n const svg = accessibleSvg(render(source), source);\n return `<div class=\"td-mermaid\" data-mermaid-state=\"ready\">${svg}</div>`;\n}\n\nfunction isMermaidCodeBlock(node: HastNode): boolean {\n if (node.type !== \"element\" || node.tagName !== \"pre\") return false;\n return (\n node.properties?.dataLanguage === \"mermaid\" ||\n node.properties?.[\"data-language\"] === \"mermaid\"\n );\n}\n\nfunction render(source: string): string {\n const header = source\n .split(\"\\n\")\n .map((line) => line.trim())\n .find(\n (line) =>\n line && !line.startsWith(\"%%\") && !/^acc(?:Title|Descr):/i.test(line),\n );\n if (!header || !supportedDiagram.test(header)) {\n throw new Error(\"Unsupported Mermaid diagram type\");\n }\n\n // Cookbook renders package Markdown too. Do not allow diagram-authored CSS\n // to escape the diagram's visual boundary; the site theme owns all colors.\n const safeSource = source\n .replace(sourceStyleDirective, \"\")\n .replace(accessibilityDirective, \"\");\n return (\n renderMermaidSVG(safeSource, {\n bg: \"var(--surface-2-color)\",\n fg: \"var(--text-color)\",\n line: \"var(--text-soft-color)\",\n accent: \"var(--accent-text-color)\",\n muted: \"var(--text-soft-color)\",\n surface: \"var(--surface-color)\",\n border: \"var(--border-strong-color)\",\n font: \"var(--body-font-family)\",\n transparent: true,\n })\n .replace(svgStyleBlock, \"\")\n // The root variables are owned by theme.styles.Mermaid.Diagram.\n .replace(/(<svg\\b[^>]*?)\\sstyle=\"[^\"]*\"/, \"$1\")\n );\n}\n\nfunction accessibleSvg(svg: string, source: string): string {\n const title = directive(source, \"accTitle\") ?? \"Diagram\";\n const description =\n directive(source, \"accDescr\") ?? \"Rendered from a Mermaid code block.\";\n return svg\n .replace(\"<svg \", `<svg role=\"img\" aria-label=\"${escapeAttribute(title)}\" `)\n .replace(\n /(<svg\\b[^>]*>)/,\n `$1<title>${escapeText(title)}</title><desc>${escapeText(description)}</desc>`,\n );\n}\n\nfunction directive(source: string, name: string): string | undefined {\n const match = source.match(new RegExp(`^\\\\s*${name}:\\\\s*(.+)$`, \"im\"));\n return match?.[1]?.trim();\n}\n\nfunction textContent(node: HastNode): string {\n if (node.type === \"text\") return node.value ?? \"\";\n return node.children?.map(textContent).join(\"\") ?? \"\";\n}\n\nfunction escapeAttribute(value: string): string {\n return escapeText(value).replaceAll('\"', \""\").replaceAll(\"'\", \"'\");\n}\n\nfunction escapeText(value: string): string {\n return value\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\");\n}\n","type Node = {\n type: string;\n tagName?: string;\n value?: string;\n properties?: Record<string, unknown>;\n children?: Node[];\n};\n\nconst alerts: Record<string, { kind: string; title: string }> = {\n NOTE: { kind: \"note\", title: \"Note\" },\n TIP: { kind: \"tip\", title: \"Tip\" },\n IMPORTANT: { kind: \"tip\", title: \"Important\" },\n WARNING: { kind: \"caution\", title: \"Warning\" },\n CAUTION: { kind: \"danger\", title: \"Caution\" },\n};\n\n/** Keep GitHub alert syntax useful in repository Markdown and MDX. */\nexport function rehypeAlerts() {\n return (tree: Node): void => visit(tree);\n}\n\nexport const satteriAlerts = {\n name: \"cookbook:alerts\",\n element: {\n filter: [\"blockquote\"],\n visit(\n node: Readonly<Node>,\n context: { replaceNode(node: Readonly<Node>, replacement: Node): void },\n ): void {\n const replacement = alert(node as Node);\n if (replacement) context.replaceNode(node, replacement);\n },\n },\n};\n\nfunction visit(parent: Node): void {\n if (!parent.children) return;\n for (const [index, child] of parent.children.entries()) {\n const replacement = alert(child);\n if (replacement) parent.children[index] = replacement;\n else visit(child);\n }\n}\n\nfunction alert(blockquote: Node): Node | undefined {\n if (blockquote.type !== \"element\" || blockquote.tagName !== \"blockquote\")\n return;\n const first = blockquote.children?.find((child) => child.type === \"element\");\n if (first?.tagName !== \"p\") return;\n const marker = first.children?.find((child) => child.type === \"text\");\n if (!marker?.value) return;\n const match = /^\\s*\\[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\\](?:\\s|$)/i.exec(\n marker.value,\n );\n if (!match) return;\n const { kind, title } = alerts[match[1]!.toUpperCase()]!;\n const updatedFirst: Node = {\n ...first,\n children: first.children!.map((child) =>\n child === marker\n ? { ...child, value: child.value!.slice(match[0].length).trimStart() }\n : child,\n ),\n };\n const body =\n blockquote.children\n ?.map((child) => (child === first ? updatedFirst : child))\n .filter(\n (child) =>\n child !== updatedFirst ||\n updatedFirst.children?.some(\n (part) => part.type !== \"text\" || Boolean(part.value?.trim()),\n ),\n ) ?? [];\n return {\n type: \"element\",\n tagName: \"aside\",\n properties: {\n className: [\"cookbook-alert\", `cookbook-alert--${kind}`],\n ariaLabel: title,\n },\n children: [\n {\n type: \"element\",\n tagName: \"p\",\n properties: { className: [\"cookbook-alert__title\"] },\n children: [{ type: \"text\", value: title }],\n },\n {\n type: \"element\",\n tagName: \"div\",\n properties: { className: [\"cookbook-alert__content\"] },\n children: body,\n },\n ],\n };\n}\n","type HastNode = {\n type: string;\n tagName?: string;\n properties?: Record<string, unknown>;\n children?: HastNode[];\n};\n\ntype SatteriContext = {\n replaceNode(node: Readonly<HastNode>, replacement: HastNode): void;\n};\n\nconst containerClass = \"td-table-scroll\";\n\n/** Wrap Markdown tables in a dedicated horizontal scroll container. */\nexport function rehypeTableScroll() {\n return (tree: HastNode): void => {\n wrapTables(tree);\n };\n}\n\n/** Sätteri adapter for Astro's default Markdown processor. */\nexport const satteriTableScroll = {\n name: \"cookbook:table-scroll\",\n element: {\n filter: [\"table\"],\n visit(node: Readonly<HastNode>, context: SatteriContext): void {\n context.replaceNode(node, scrollContainer(node as HastNode));\n },\n },\n};\n\nfunction wrapTables(parent: HastNode): void {\n if (!parent.children || isScrollContainer(parent)) return;\n for (const [index, child] of parent.children.entries()) {\n if (child.type === \"element\" && child.tagName === \"table\") {\n parent.children[index] = scrollContainer(child);\n continue;\n }\n wrapTables(child);\n }\n}\n\nfunction scrollContainer(table: HastNode): HastNode {\n return {\n type: \"element\",\n tagName: \"div\",\n properties: { className: [containerClass] },\n children: [table],\n };\n}\n\nfunction isScrollContainer(node: HastNode): boolean {\n const className = node.properties?.className;\n return (\n node.type === \"element\" &&\n node.tagName === \"div\" &&\n Array.isArray(className) &&\n className.includes(containerClass)\n );\n}\n","type HastNode = {\n type: string;\n value?: string;\n tagName?: string;\n properties?: Record<string, unknown>;\n children?: HastNode[];\n};\n\ntype SatteriContext = {\n replaceNode(node: Readonly<HastNode>, replacement: HastNode): void;\n textContent(node: Readonly<HastNode>): string;\n};\n\n/** Add copy controls to rendered Markdown code blocks. */\nexport function rehypePageAffordances() {\n return (tree: HastNode): void => addPageAffordances(tree);\n}\n\n/** Sätteri adapter for Astro's default Markdown processor. */\nexport const satteriPageAffordances = {\n name: \"cookbook:page-affordances\",\n element: {\n filter: [\"pre\"],\n visit(node: Readonly<HastNode>, context: SatteriContext): void {\n const replacement = pageAffordance(node as HastNode);\n if (replacement !== node) context.replaceNode(node, replacement);\n },\n },\n};\n\nfunction addPageAffordances(parent: HastNode): void {\n if (!parent.children) return;\n for (const [index, child] of parent.children.entries()) {\n const replacement = pageAffordance(child);\n if (replacement !== child) {\n parent.children[index] = replacement;\n continue;\n }\n addPageAffordances(child);\n }\n}\n\nfunction pageAffordance(node: HastNode): HastNode {\n if (isOrdinaryCodeBlock(node)) return codeBlockWithCopy(node);\n return node;\n}\n\nfunction isOrdinaryCodeBlock(node: HastNode): boolean {\n if (node.type !== \"element\" || node.tagName !== \"pre\") return false;\n const language =\n node.properties?.dataLanguage ?? node.properties?.[\"data-language\"];\n return language !== \"mermaid\" && node.children?.[0]?.tagName === \"code\";\n}\n\nfunction codeBlockWithCopy(pre: HastNode): HastNode {\n return element(\n \"cookbook-code-block\",\n { className: [\"td-code-block\"], dataTastyAnatomy: \"MarkdownCodeBlock\" },\n [\n pre,\n element(\n \"button\",\n {\n type: \"button\",\n dataCopyCode: \"\",\n ariaLabel: \"Copy code\",\n title: \"Copy code\",\n },\n [element(\"span\", { dataCopyIcon: \"\", ariaHidden: \"true\" }, [])],\n ),\n ],\n );\n}\n\nfunction element(\n tagName: string,\n properties: Record<string, unknown>,\n children: HastNode[],\n): HastNode {\n return { type: \"element\", tagName, properties, children };\n}\n","import type { FontLoadingConfig, ThemeFont, ThemeFonts } from \"@tenphi/docs\";\nimport type { FontFaceDescriptors } from \"@tenphi/tasty/core\";\n\nexport interface ResolvedFontFace {\n family: string;\n descriptors: FontFaceDescriptors;\n}\n\nconst sharedFonts = globalThis as typeof globalThis & {\n __tenphiCookbookFontFaces?: ResolvedFontFace[];\n __tenphiCookbookDefaultFontUsage?: {\n onest: boolean;\n mono: boolean;\n display?: FontLoadingConfig[\"display\"];\n };\n};\n\nconst fallback = {\n body: \"system-ui, sans-serif\",\n heading: \"system-ui, sans-serif\",\n code: \"ui-monospace, monospace\",\n} as const;\n\nexport function fontFamilies(\n fonts: ThemeFonts = {},\n): Partial<Record<keyof ThemeFonts, string>> {\n return Object.fromEntries(\n (\n Object.entries(fonts).filter(([, font]) => font !== undefined) as [\n keyof ThemeFonts,\n ThemeFont,\n ][]\n ).map(([role, font]) => [\n role,\n `'${typeof font === \"string\" ? font : \"google\" in font ? font.google : font.family}', ${fallback[role]}`,\n ]),\n );\n}\n\nexport function configureFontFaces(\n faces: ResolvedFontFace[],\n defaults: {\n onest: boolean;\n mono: boolean;\n display?: FontLoadingConfig[\"display\"];\n },\n): void {\n sharedFonts.__tenphiCookbookFontFaces = faces;\n sharedFonts.__tenphiCookbookDefaultFontUsage = defaults;\n}\n\nexport function getFontFaces(): ResolvedFontFace[] {\n return sharedFonts.__tenphiCookbookFontFaces ?? [];\n}\n\nexport function getDefaultFontUsage(): {\n onest: boolean;\n mono: boolean;\n display?: FontLoadingConfig[\"display\"];\n} {\n return (\n sharedFonts.__tenphiCookbookDefaultFontUsage ?? { onest: true, mono: true }\n );\n}\n","import {\n resolveColorTheme,\n type ThemeConfig,\n type ThemeTokens,\n type TypographyPreset,\n} from \"@tenphi/docs\";\nimport { resolveThemeTokens, resolveTypographyPresets } from \"./defaults.js\";\nimport { fontFamilies } from \"./fonts.js\";\n\nexport interface ResolvedDocsTheme extends ReturnType<\n typeof resolveColorTheme\n> {\n tokens: ThemeTokens;\n presets: Record<string, TypographyPreset>;\n}\n\nexport function resolveDocsTheme(theme: ThemeConfig = {}): ResolvedDocsTheme {\n return {\n ...resolveColorTheme(theme),\n tokens: resolveThemeTokens(theme.tokens),\n presets: resolveTypographyPresets(theme.presets, fontFamilies(theme.fonts)),\n };\n}\n","import { createHash, randomUUID } from \"node:crypto\";\nimport { mkdir, readFile, rename, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { FontLoadingConfig } from \"@tenphi/docs\";\n\nexport const fontHash = (bytes: string | Uint8Array): string =>\n createHash(\"sha256\").update(bytes).digest(\"hex\");\nconst userAgent =\n \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36\";\n\n/** Content-verified, atomic cache entries. Cache keys include the fixed browser profile. */\nexport function createFontFetcher(\n directory: string | undefined,\n mode: FontLoadingConfig[\"cache\"] = \"reuse\",\n fetchFont: typeof fetch = fetch,\n) {\n const pending = new Map<string, Promise<{ status: number; body: Buffer }>>();\n return (url: string) => {\n const load = async () => {\n const key = fontHash(`${userAgent}\\n${url}`);\n const path = directory ? join(directory, `${key}.json`) : undefined;\n if (path && mode !== \"refresh\") {\n try {\n const cached = JSON.parse(await readFile(path, \"utf8\"));\n const body = Buffer.from(cached.body, \"base64\");\n if (\n ![200, 400].includes(cached.status) ||\n cached.url !== url ||\n fontHash(body) !== cached.sha256\n )\n throw new Error(\"Invalid font cache entry\");\n return { status: cached.status as number, body };\n } catch {\n /* Fetch a missing or corrupted entry unless offline. */\n }\n }\n if (mode === \"offline\")\n throw new Error(\n `Google font cache is missing or corrupt for ${url}. Run once with theme.fontLoading.cache: \"reuse\" and preserve the Astro cache directory.`,\n );\n let response: Response;\n try {\n response = await fetchFont(url, {\n headers: { \"User-Agent\": userAgent },\n signal: AbortSignal.timeout(15_000),\n });\n } catch (error) {\n throw new Error(\n `Could not download Google font resource ${url}: ${String(error)}. Preserve the Astro cache for offline builds, or use local font files.`,\n );\n }\n const body = Buffer.from(await response.arrayBuffer());\n if (![200, 400].includes(response.status))\n throw new Error(\n `Google font request failed (${response.status}): ${url}.`,\n );\n if (path) {\n await mkdir(directory!, { recursive: true });\n const temporary = `${path}.${randomUUID()}.tmp`;\n await writeFile(\n temporary,\n JSON.stringify({\n url,\n status: response.status,\n sha256: fontHash(body),\n body: body.toString(\"base64\"),\n }),\n );\n await rename(temporary, path);\n }\n return { status: response.status, body };\n };\n if (!pending.has(url)) pending.set(url, load());\n return pending.get(url)!;\n };\n}\n","import type {\n FontLoadingConfig,\n ThemeFonts,\n ThemeFont,\n TypographyPreset,\n} from \"@tenphi/docs\";\nimport { fontFamilies, type ResolvedFontFace } from \"./fonts.js\";\nimport { resolveTypographyPresets } from \"./defaults.js\";\nimport { createFontFetcher, fontHash } from \"./font-cache.js\";\n\nexport interface FontAsset {\n publicPath: string;\n outputPath: string;\n contentType: string;\n body: Buffer;\n}\ntype Weight = number | `${number} ${number}`;\ntype Span = [number, number];\ntype Options = {\n base?: string;\n cacheDir?: string;\n loading?: FontLoadingConfig;\n presets?: Record<string, TypographyPreset>;\n fetch?: typeof fetch;\n warn?: (message: string) => void;\n};\n\n/** Merge overlapping/touching ranges, as required by the Google CSS2 API. */\nexport function fontWeightSpans(weights: Weight[]): Span[] {\n const spans = weights\n .map((weight): Span =>\n typeof weight === \"number\"\n ? [weight, weight]\n : (weight.split(\" \").map(Number) as Span),\n )\n .sort((a, b) => a[0] - b[0]);\n return spans.reduce<Span[]>((result, span) => {\n const previous = result.at(-1);\n if (previous && span[0] <= previous[1])\n previous[1] = Math.max(previous[1], span[1]);\n else result.push([...span]);\n return result;\n }, []);\n}\n\nfunction presetWeights(\n family: string,\n presets: Record<string, TypographyPreset>,\n): number[] {\n const resolveValue = (value: unknown, seen = new Set<string>()): unknown => {\n if (typeof value !== \"string\") return value;\n const ref =\n /^var\\(--(.+)-(font-family|bold-font-weight|font-weight)\\)$/.exec(value);\n if (!ref || seen.has(value)) return value;\n seen.add(value);\n const key =\n ref[2] === \"font-family\"\n ? \"fontFamily\"\n : ref[2] === \"font-weight\"\n ? \"fontWeight\"\n : \"boldFontWeight\";\n return resolveValue(presets[ref[1]!]?.[key], seen);\n };\n const values = Object.values(presets)\n .flatMap((preset) => {\n const resolvedFamily = resolveValue(preset.fontFamily);\n if (\n typeof resolvedFamily !== \"string\" ||\n resolvedFamily\n .split(\",\")[0]\n ?.trim()\n .replace(/^['\"]|['\"]$/g, \"\") !== family\n )\n return [];\n return [\n resolveValue(preset.fontWeight),\n resolveValue(preset.boldFontWeight),\n ];\n })\n .map((value) =>\n value === \"bold\" ? 700 : value === \"normal\" ? 400 : Number(value),\n )\n .filter((value) => Number.isInteger(value) && value >= 1 && value <= 1000);\n return [...new Set(values.length ? values : [400, 700])];\n}\n\n/** Resolve CSS and optional font assets before rendering; all faces are emitted by Tasty. */\nexport async function resolveThemeFonts(\n fonts: ThemeFonts = {},\n options: Options = {},\n): Promise<{ faces: ResolvedFontFace[]; assets: FontAsset[] }> {\n const base = (options.base ?? \"/\").replace(/\\/$/, \"\");\n const loading = options.loading ?? {};\n const download = createFontFetcher(\n options.cacheDir,\n loading.cache,\n options.fetch,\n );\n const presets =\n options.presets ?? resolveTypographyPresets({}, fontFamilies(fonts));\n const faces: ResolvedFontFace[] = [];\n const assets = new Map<string, FontAsset>();\n const google = new Map<\n string,\n { explicit: Map<string, Weight[]>; inferred: Map<string, number[]> }\n >();\n for (const font of Object.values(fonts).filter(\n (font): font is ThemeFont => font !== undefined,\n )) {\n if (typeof font === \"string\" || \"google\" in font) {\n const family = typeof font === \"string\" ? font : font.google;\n const requested = google.get(family) ?? {\n explicit: new Map(),\n inferred: new Map(),\n };\n const weights = typeof font === \"string\" ? undefined : font.weights;\n const styles =\n typeof font === \"string\"\n ? [\"normal\", \"italic\"]\n : (font.styles ?? [\"normal\", \"italic\"]);\n for (const style of styles) {\n if (weights)\n requested.explicit.set(style, [\n ...(requested.explicit.get(style) ?? []),\n ...weights,\n ]);\n else\n requested.inferred.set(style, [\n ...(requested.inferred.get(style) ?? []),\n ...presetWeights(family, presets),\n ]);\n }\n google.set(family, requested);\n } else\n for (const file of font.files) {\n const extension = file.src.split(\".\").at(-1);\n const format =\n extension === \"ttf\"\n ? \"truetype\"\n : extension === \"otf\"\n ? \"opentype\"\n : extension;\n faces.push({\n family: font.family,\n descriptors: {\n src: `url(\"${base}${file.src}\") format(\"${format}\")`,\n fontWeight: file.weight ?? 400,\n fontStyle: file.style ?? \"normal\",\n fontDisplay: loading.display ?? \"swap\",\n },\n });\n }\n }\n for (const [family, request] of google) {\n const fetchFaces = async (\n byStyle: Map<string, Weight[]>,\n strict: boolean,\n ): Promise<ResolvedFontFace[]> => {\n if (!byStyle.size) return [];\n const tuples = [...byStyle]\n .sort(([a], [b]) => (a === \"normal\" ? 0 : 1) - (b === \"normal\" ? 0 : 1))\n .flatMap(([style, weights]) =>\n fontWeightSpans(weights).map(\n ([min, max]) =>\n `${style === \"italic\" ? 1 : 0},${min === max ? min : `${min}..${max}`}`,\n ),\n );\n const url = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(family).replaceAll(\"%20\", \"+\")}:ital,wght@${tuples.join(\";\")}&display=${loading.display ?? \"swap\"}`;\n const response = await download(url);\n if (response.status === 400) {\n if (!strict) return [];\n throw new Error(\n `Google Fonts rejected \"${family}\" (400). Check theme.fonts weights/ranges/styles against the family's supported axes.`,\n );\n }\n const parsed = parseGoogleFontCss(\n response.body.toString(\"utf8\"),\n family,\n loading.display ?? \"swap\",\n );\n if (!parsed.length)\n throw new Error(\n `Google Fonts returned no usable font files for \"${family}\".`,\n );\n if (strict) {\n for (const [style, weights] of byStyle)\n for (const [lo, hi] of fontWeightSpans(weights)) {\n const available = fontWeightSpans(\n parsed\n .filter((face) => face.descriptors.fontStyle === style)\n .map((face) =>\n String(face.descriptors.fontWeight).includes(\" \")\n ? (String(face.descriptors.fontWeight) as Weight)\n : Number(face.descriptors.fontWeight),\n ),\n );\n if (!available.some(([min, max]) => min <= lo && max >= hi))\n throw new Error(\n `Google Fonts did not provide ${family} ${style} weight ${lo === hi ? lo : `${lo} ${hi}`}. Choose supported theme.fonts weights/styles or use local font files.`,\n );\n }\n }\n return parsed;\n };\n const familyFaces = await fetchFaces(request.explicit, true);\n if (request.inferred.size) {\n const ranges = new Map(\n [...request.inferred].map(([style, weights]): [string, Weight[]] => [\n style,\n [\n Math.min(...weights) === Math.max(...weights)\n ? weights[0]!\n : (`${Math.min(...weights)} ${Math.max(...weights)}` as Weight),\n ],\n ]),\n );\n let inferred = await fetchFaces(ranges, false);\n if (!inferred.length) {\n // Static families can omit unavailable intermediate weights. Include the\n // two conventional neighbors so the browser can select a real face.\n const statics = new Map(\n [...request.inferred].map(([style, weights]): [string, Weight[]] => [\n style,\n [\n ...new Set(\n weights.flatMap((weight) => [\n weight,\n Math.max(100, Math.floor(weight / 100) * 100),\n Math.min(900, Math.ceil(weight / 100) * 100),\n ]),\n ),\n ],\n ]),\n );\n inferred = await fetchFaces(statics, false);\n if (!inferred.length)\n throw new Error(\n `Google Fonts rejected \"${family}\". Check the family name or provide explicit supported theme.fonts weights/styles.`,\n );\n }\n for (const style of request.inferred.keys())\n if (!inferred.some((face) => face.descriptors.fontStyle === style))\n options.warn?.(\n `Google Font \"${family}\" has no ${style} face for these presets. Choose a family with that style, or set theme.fonts styles explicitly.`,\n );\n familyFaces.push(...inferred);\n }\n for (const face of familyFaces) {\n if (loading.google !== \"remote\") {\n const source = /url\\(\"([^\"]+)\"\\) format\\(\"([^\"]+)\"\\)/.exec(\n String(face.descriptors.src),\n )!;\n const response = await download(source[1]!);\n if (\n response.status !== 200 ||\n response.body.length < 12 ||\n ![\n \"wOF2\",\n \"wOFF\",\n \"OTTO\",\n \"ttcf\",\n \"\\u0000\\u0001\\u0000\\u0000\",\n ].includes(response.body.subarray(0, 4).toString(\"binary\"))\n )\n throw new Error(\n `Could not download Google Font \"${family}\" from ${source[1]}.`,\n );\n const extension =\n source[2] === \"truetype\"\n ? \"ttf\"\n : source[2] === \"opentype\"\n ? \"otf\"\n : source[2];\n const outputPath = `_cookbook/fonts/${fontHash(response.body)}.${extension}`;\n const publicPath = `${base}/${outputPath}`;\n assets.set(outputPath, {\n outputPath,\n publicPath,\n body: response.body,\n contentType: `font/${extension}`,\n });\n face.descriptors.src = `url(\"${publicPath}\") format(\"${source[2]}\")`;\n }\n faces.push(face);\n }\n }\n return {\n faces: [\n ...new Map(faces.map((face) => [JSON.stringify(face), face])).values(),\n ],\n assets: [...assets.values()],\n };\n}\n\nfunction parseGoogleFontCss(\n css: string,\n family: string,\n display: NonNullable<FontLoadingConfig[\"display\"]>,\n): ResolvedFontFace[] {\n const faces: ResolvedFontFace[] = [];\n for (const block of css.matchAll(/@font-face\\s*\\{([^}]*)\\}/g)) {\n const declarations = Object.fromEntries(\n [...(block[1] ?? \"\").matchAll(/([\\w-]+)\\s*:\\s*([^;]+);/g)].map(\n (match) => [match[1], match[2]!.trim()],\n ),\n );\n const source = declarations.src?.match(\n /url\\(['\"]?(https:\\/\\/fonts\\.gstatic\\.com\\/[^'\"()\\s]+)['\"]?\\)\\s*format\\(['\"]?(woff2?|truetype|opentype)['\"]?\\)/,\n );\n if (\n !source ||\n declarations[\"font-family\"]?.replaceAll(/[\"']/g, \"\").toLowerCase() !==\n family.toLowerCase()\n )\n continue;\n faces.push({\n family,\n descriptors: {\n src: `url(\"${source[1]}\") format(\"${source[2]}\")`,\n fontWeight: declarations[\"font-weight\"] ?? 400,\n fontStyle: declarations[\"font-style\"] ?? \"normal\",\n fontDisplay: display,\n ...(declarations[\"unicode-range\"]\n ? { unicodeRange: declarations[\"unicode-range\"] }\n : {}),\n },\n });\n }\n return faces;\n}\n","export function resolveComponentOverrides(\n defaults: Record<string, string>,\n overrides: Record<string, string | false> | undefined,\n disabledFooterPath: string,\n): Record<string, string> {\n const resolved = { ...defaults };\n\n for (const [name, override] of Object.entries(overrides ?? {})) {\n if (name === \"Footer\" && override === false) {\n resolved.Footer = disabledFooterPath;\n } else if (typeof override === \"string\") {\n resolved[name] = override;\n }\n }\n\n return resolved;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { extname, isAbsolute, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { HeadConfig, SiteConfig } from \"@tenphi/docs\";\nimport sharp from \"sharp\";\n\nconst ICON_DIRECTORY = \"_cookbook/icons\";\nconst DEFAULT_ICON_BACKGROUND = \"#4b6dc3\";\nconst SUPPORTED_SOURCE_FORMATS = new Set([\n \"avif\",\n \"gif\",\n \"heif\",\n \"jpeg\",\n \"jpg\",\n \"png\",\n \"svg\",\n \"webp\",\n]);\n\ninterface SiteIconAsset {\n body: Buffer;\n contentType: string;\n outputPath: string;\n publicPath: string;\n}\n\nexport interface SiteIconSet {\n assets: SiteIconAsset[];\n faviconPath: string;\n head: HeadConfig[];\n sourcePath: string;\n}\n\ninterface SiteIconOptions {\n base: string;\n root: string;\n site?: SiteConfig;\n themeColors: {\n dark: string;\n light: string;\n };\n}\n\nexport async function createSiteIcons({\n base,\n root,\n site = {},\n themeColors,\n}: SiteIconOptions): Promise<SiteIconSet> {\n const configured = site.favicon;\n const source =\n typeof configured === \"string\" ? configured : configured?.source;\n const sourcePath = source\n ? resolveSourcePath(source, root)\n : fileURLToPath(new URL(\"./icons/favicon.svg\", import.meta.url));\n const background =\n typeof configured === \"object\" && configured?.background\n ? configured.background\n : DEFAULT_ICON_BACKGROUND;\n const input = await readFile(sourcePath).catch((error: unknown) => {\n throw new Error(\n `Unable to read site.favicon source at ${sourcePath}: ${errorMessage(error)}`,\n );\n });\n const metadata = await sharp(input, { animated: false }).metadata();\n const format = metadata.format?.toLowerCase();\n if (!format || !SUPPORTED_SOURCE_FORMATS.has(format)) {\n throw new Error(\n \"site.favicon must point to an SVG, PNG, JPEG, WebP, AVIF, or GIF image.\",\n );\n }\n\n const definitions = [\n await pngAsset(input, base, \"favicon-32x32.png\", 32),\n await safePngAsset(input, base, \"apple-touch-icon.png\", 180, background),\n await pngAsset(input, base, \"icon-192x192.png\", 192),\n await pngAsset(input, base, \"icon-512x512.png\", 512),\n await safePngAsset(\n input,\n base,\n \"icon-192x192-maskable.png\",\n 192,\n background,\n ),\n await safePngAsset(\n input,\n base,\n \"icon-512x512-maskable.png\",\n 512,\n background,\n ),\n ];\n\n const scalable =\n format === \"svg\"\n ? asset(base, \"favicon.svg\", input, \"image/svg+xml\")\n : undefined;\n const faviconPath = `/${ICON_DIRECTORY}/${scalable ? \"favicon.svg\" : \"favicon-32x32.png\"}`;\n const iconEntries = [\n {\n src: pathWithBase(base, `/${ICON_DIRECTORY}/icon-192x192.png`),\n sizes: \"192x192\",\n type: \"image/png\",\n purpose: \"any\",\n },\n {\n src: pathWithBase(base, `/${ICON_DIRECTORY}/icon-512x512.png`),\n sizes: \"512x512\",\n type: \"image/png\",\n purpose: \"any\",\n },\n {\n src: pathWithBase(base, `/${ICON_DIRECTORY}/icon-192x192-maskable.png`),\n sizes: \"192x192\",\n type: \"image/png\",\n purpose: \"maskable\",\n },\n {\n src: pathWithBase(base, `/${ICON_DIRECTORY}/icon-512x512-maskable.png`),\n sizes: \"512x512\",\n type: \"image/png\",\n purpose: \"maskable\",\n },\n ...(scalable\n ? [\n {\n src: scalable.publicPath,\n sizes: \"any\",\n type: \"image/svg+xml\",\n purpose: \"any\",\n },\n ]\n : []),\n ];\n const manifest = asset(\n base,\n \"site.webmanifest\",\n Buffer.from(\n `${JSON.stringify(\n {\n name: site.title ?? \"Documentation\",\n short_name: site.title ?? \"Documentation\",\n ...(site.description ? { description: site.description } : {}),\n id: normalizedBase(base),\n start_url: normalizedBase(base),\n scope: normalizedBase(base),\n display: \"standalone\",\n background_color: background,\n theme_color: themeColors.light,\n icons: iconEntries,\n },\n null,\n 2,\n )}\\n`,\n ),\n \"application/manifest+json\",\n );\n const favicon32 = definitions[0];\n const appleTouchIcon = definitions[1];\n if (!favicon32 || !appleTouchIcon) {\n throw new Error(\"Cookbook failed to generate the required site icons.\");\n }\n\n return {\n assets: [...definitions, ...(scalable ? [scalable] : []), manifest],\n faviconPath,\n head: [\n {\n tag: \"link\",\n attrs: {\n rel: \"icon\",\n href: favicon32.publicPath,\n sizes: \"32x32\",\n type: favicon32.contentType,\n },\n },\n ...(scalable\n ? [\n {\n tag: \"link\",\n attrs: {\n rel: \"icon\",\n href: scalable.publicPath,\n sizes: \"any\",\n type: scalable.contentType,\n },\n } satisfies HeadConfig,\n ]\n : []),\n {\n tag: \"link\",\n attrs: {\n rel: \"apple-touch-icon\",\n href: appleTouchIcon.publicPath,\n sizes: \"180x180\",\n },\n },\n {\n tag: \"link\",\n attrs: { rel: \"manifest\", href: manifest.publicPath },\n },\n {\n tag: \"meta\",\n attrs: {\n name: \"theme-color\",\n content: themeColors.light,\n media: \"(prefers-color-scheme: light)\",\n },\n },\n {\n tag: \"meta\",\n attrs: {\n name: \"theme-color\",\n content: themeColors.dark,\n media: \"(prefers-color-scheme: dark)\",\n },\n },\n ],\n sourcePath,\n };\n}\n\nasync function pngAsset(\n input: Buffer,\n base: string,\n name: string,\n size: number,\n): Promise<SiteIconAsset> {\n const body = await sharp(input, { animated: false, density: 512 })\n .resize(size, size, {\n fit: \"contain\",\n background: { r: 0, g: 0, b: 0, alpha: 0 },\n })\n .png()\n .toBuffer();\n return asset(base, name, body, \"image/png\");\n}\n\nasync function safePngAsset(\n input: Buffer,\n base: string,\n name: string,\n size: number,\n background: string,\n): Promise<SiteIconAsset> {\n const safeSize = Math.round(size * 0.8);\n const foreground = await sharp(input, { animated: false, density: 512 })\n .resize(safeSize, safeSize, {\n fit: \"contain\",\n background: { r: 0, g: 0, b: 0, alpha: 0 },\n })\n .png()\n .toBuffer();\n const body = await sharp({\n create: {\n width: size,\n height: size,\n channels: 4,\n background,\n },\n })\n .composite([{ input: foreground, gravity: \"center\" }])\n .png()\n .toBuffer()\n .catch((error: unknown) => {\n throw new Error(\n `Unable to use site.favicon.background ${JSON.stringify(background)}: ${errorMessage(error)}`,\n );\n });\n return asset(base, name, body, \"image/png\");\n}\n\nfunction asset(\n base: string,\n name: string,\n body: Buffer,\n contentType: string,\n): SiteIconAsset {\n const outputPath = `${ICON_DIRECTORY}/${name}`;\n return {\n body,\n contentType,\n outputPath,\n publicPath: pathWithBase(base, `/${outputPath}`),\n };\n}\n\nfunction resolveSourcePath(source: string, root: string): string {\n if (/^[a-z][a-z\\d+.-]*:/i.test(source)) {\n throw new Error(\"site.favicon must reference a local image path.\");\n }\n return isAbsolute(source) ? source : resolve(root, source);\n}\n\nfunction pathWithBase(base: string, pathname: string): string {\n const prefix = normalizedBase(base);\n return `${prefix === \"/\" ? \"\" : prefix.replace(/\\/$/, \"\")}${pathname}`;\n}\n\nfunction normalizedBase(base: string): string {\n const value = base.replace(/^\\/+|\\/+$/g, \"\");\n return value ? `/${value}/` : \"/\";\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n","function normalizedBasePath(base: string): string {\n const path = base.replace(/^\\/+|\\/+$/g, \"\");\n return path ? `/${path}/` : \"/\";\n}\n\nexport function outputPathForPublicAsset(\n publicPath: string,\n base: string,\n): string {\n const normalizedPublicPath = `/${publicPath.replace(/^\\/+/, \"\")}`;\n const prefix = normalizedBasePath(base);\n if (!normalizedPublicPath.startsWith(prefix)) {\n throw new Error(\n `Cookbook asset path ${publicPath} is outside the configured base ${base}.`,\n );\n }\n\n const outputPath = normalizedPublicPath.slice(prefix.length);\n if (\n !outputPath ||\n outputPath.split(\"/\").some((segment) => segment === \".\" || segment === \"..\")\n ) {\n throw new Error(`Cookbook asset path ${publicPath} is not safe to emit.`);\n }\n return outputPath;\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { renderAgentMarkdown, type DocsGraph } from \"@tenphi/docs\";\nimport { agentPagePath } from \"./page-metadata.js\";\nimport { outputPathForPublicAsset } from \"./output-path.js\";\n\nfunction sitePath(base: string, route: string): string {\n const prefix = base === \"/\" ? \"\" : `/${base.replace(/^\\/+|\\/+$/g, \"\")}`;\n return `${prefix}${route === \"/\" ? \"/\" : `${route}/`}`;\n}\n\nfunction pageUrl(site: string | undefined, path: string): string {\n return site ? new URL(path, site).href : path;\n}\n\nfunction singleLine(value: string): string {\n return value.replace(/\\s+/g, \" \").trim();\n}\n\nfunction markdownLabel(value: string): string {\n return singleLine(value).replace(/[\\\\[\\]]/g, \"\\\\$&\");\n}\n\nexport function renderLlmsTxt(graph: DocsGraph): string {\n const { site, build } = graph.config;\n const lines = [`# ${singleLine(site.title ?? \"Documentation\")}`, \"\"];\n if (site.description) lines.push(`> ${singleLine(site.description)}`, \"\");\n lines.push(\"## Documentation\", \"\");\n const discoverable = new Set(\n graph.routes\n .filter(\n (route) => route.discoverable !== false && route.sitemap !== false,\n )\n .map((route) => route.route),\n );\n for (const entry of graph.entries) {\n if (!discoverable.has(entry.route)) continue;\n const url = pageUrl(site.url, sitePath(build.base, entry.route));\n lines.push(\n `- [${markdownLabel(entry.title)}](${url})${entry.description ? `: ${singleLine(entry.description)}` : \"\"}${site.seo?.copyPage === false ? \"\" : ` ([Markdown](${pageUrl(site.url, agentPagePath(entry.route, build.base))}))`}`,\n );\n }\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nexport function renderRobotsTxt(site: string, sitemap = true): string {\n return `User-agent: *\\nAllow: /\\n${sitemap ? `Sitemap: ${new URL(\"/sitemap-index.xml\", site).href}\\n` : \"\"}`;\n}\n\nasync function writeUnlessPresent(path: string, body: string): Promise<void> {\n try {\n await writeFile(path, body, { flag: \"wx\" });\n } catch (error) {\n if (\n error &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"EEXIST\"\n ) {\n return;\n }\n throw error;\n }\n}\n\nexport async function writeAgentDiscovery(\n output: string,\n graph: DocsGraph,\n): Promise<void> {\n await writeUnlessPresent(join(output, \"llms.txt\"), renderLlmsTxt(graph));\n await mkdir(join(output, \"_cookbook/pages\"), { recursive: true });\n const pages = [];\n for (const entry of graph.entries) {\n if (entry.frontmatter.draft) continue;\n const route = graph.routes.find((route) => route.route === entry.route)!;\n const markdown =\n !entry.frontmatter.draft && graph.config.site.seo?.copyPage !== false\n ? agentPagePath(entry.route, graph.config.build.base)\n : undefined;\n if (markdown)\n await writeFile(\n join(\n output,\n outputPathForPublicAsset(markdown, graph.config.build.base),\n ),\n renderAgentMarkdown(entry, graph.config),\n );\n pages.push({\n route: entry.route,\n url: pageUrl(\n graph.config.site.url,\n sitePath(graph.config.build.base, entry.route),\n ),\n canonical: route.canonical,\n index: route.indexable !== false,\n discoverable: route.discoverable !== false,\n sitemap: route.sitemap !== false,\n ...(markdown ? { markdown } : {}),\n });\n }\n await writeFile(\n join(output, \"_cookbook/publishing.json\"),\n JSON.stringify(\n { base: graph.config.build.base, site: graph.config.site.url, pages },\n null,\n 2,\n ) + \"\\n\",\n );\n if (graph.config.build.base === \"/\" && graph.config.site.url) {\n await writeUnlessPresent(\n join(output, \"robots.txt\"),\n renderRobotsTxt(\n graph.config.site.url,\n graph.routes.some((route) => route.sitemap !== false),\n ),\n );\n }\n}\n","import { resolveHeroMetadata } from \"./hero-image.js\";\nimport {\n validatePluginFrontmatter,\n type FrontmatterSchema,\n} from \"./plugin-contract.js\";\nimport { resolveSiteLogo, type SiteLogoSet } from \"./site-logo.js\";\nimport { assertTastyOutput } from \"./output-styles.js\";\nimport { adaptPagefindUI } from \"./pagefind-adapter.js\";\nimport { existsSync } from \"node:fs\";\nimport {\n cp,\n mkdir,\n readFile,\n readdir,\n stat,\n unlink,\n writeFile,\n} from \"node:fs/promises\";\nimport { createRequire } from \"node:module\";\nimport { dirname, extname, join, resolve } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport mdx from \"@astrojs/mdx\";\nimport * as pagefind from \"pagefind\";\nimport sitemap from \"@astrojs/sitemap\";\nimport { localeAlternates } from \"./localization.js\";\nimport {\n createDocsGraph,\n assertValidDocs,\n resolveDocsProject,\n type DocsConfig,\n} from \"@tenphi/docs\";\nimport {\n configure,\n type ConfigTokens,\n type Styles,\n type TypographyPreset,\n} from \"@tenphi/tasty/core\";\nimport { tastyIntegration } from \"@tenphi/tasty/ssr/astro\";\nimport type { AstroIntegration, HookParameters } from \"astro\";\nimport {\n navigationPath,\n resolveNavigationLayout,\n type ResolvedNavigationLayout,\n} from \"./navigation.js\";\nimport { rehypeMermaid, satteriMermaid } from \"./markdown/rehype-mermaid.js\";\nimport { rehypeAlerts, satteriAlerts } from \"./markdown/rehype-alerts.js\";\nimport {\n rehypeTableScroll,\n satteriTableScroll,\n} from \"./markdown/rehype-table-scroll.js\";\nimport {\n rehypePageAffordances,\n satteriPageAffordances,\n} from \"./markdown/rehype-page-affordances.js\";\nimport { resolveDocsTheme } from \"./theme/index.js\";\nimport { configureFontFaces } from \"./theme/fonts.js\";\nimport { resolveThemeFonts, type FontAsset } from \"./theme/font-loading.js\";\nimport {\n cookbookShikiConfig,\n configureCodeHighlighting,\n} from \"./theme/shiki-theme.js\";\nimport { TASTY_UNITS, tastyTokens } from \"./theme/tasty-config.js\";\nimport {\n configureComponentStyles,\n resolveLegacyAnatomyStyles,\n unusedCustomStyleNames,\n} from \"./components/component-styles.js\";\nimport { resolveComponentOverrides } from \"./component-overrides.js\";\nimport { cookbookStates } from \"./components/tasty-states.js\";\nimport { createSiteIcons, type SiteIconSet } from \"./site-icons.js\";\nimport { outputPathForPublicAsset } from \"./output-path.js\";\nimport { agentPagePath } from \"./page-metadata.js\";\nimport { renderAgentMarkdown } from \"@tenphi/docs\";\nimport { writeAgentDiscovery } from \"./agent-discovery.js\";\n\nconst stylingRuntimeError =\n \"Cookbook styles are build/server-only. Do not import @tenphi/cookbook/styling, Tasty, or Glaze in browser scripts or client:* islands. Render styled markup on the server and attach a small client script for interactions.\";\nfunction isStylingRuntime(id: string): boolean {\n const path = id.replaceAll(\"\\\\\", \"/\");\n return (\n /^@tenphi\\/(?:tasty|glaze)(?:\\/|$)/.test(path) ||\n /^@tenphi\\/(?:cookbook|renderer)\\/styling$/.test(path) ||\n /(?:^|\\/)node_modules\\/@tenphi\\/(?:tasty|glaze)(?:\\/|$)/.test(path)\n );\n}\n\nconst packageRequire = createRequire(import.meta.url);\nconst tastyStaticMiddleware = packageRequire.resolve(\n \"@tenphi/tasty/ssr/astro-middleware-static\",\n);\nconst tastyExtractStaticMiddleware = packageRequire.resolve(\n \"@tenphi/tasty/ssr/astro-middleware-extract-static\",\n);\nconst astroReactServer = packageRequire.resolve(\"@astrojs/react/server.js\");\nconst astroReactClient = packageRequire.resolve(\"@astrojs/react/client.js\");\nconst astroReactIntegration = packageRequire.resolve(\"@astrojs/react\");\nconst importNative = new Function(\"specifier\", \"return import(specifier)\") as (\n specifier: string,\n) => Promise<{ default: () => AstroIntegration }>;\n\nexport interface CookbookOptions {\n config?: DocsConfig;\n root?: string;\n configFile?: string | false;\n /** Validate custom metadata only; reserved routing/frontmatter fields cannot be changed. */\n frontmatterSchema?: FrontmatterSchema;\n}\n\nexport default function cookbook(\n options: CookbookOptions = {},\n): AstroIntegration {\n let integration: AstroIntegration | undefined;\n return {\n name: \"cookbook\",\n hooks: {\n \"astro:config:setup\": async (context) => {\n const project = await resolveDocsProject({\n ...options,\n root: options.root ?? fileURLToPath(context.config.root),\n });\n if (project.configFile) context.addWatchFile(project.configFile);\n integration = configuredCookbook({\n config: project.config,\n root: project.root,\n ...(options.frontmatterSchema\n ? { frontmatterSchema: options.frontmatterSchema }\n : {}),\n });\n await callInner([integration], \"astro:config:setup\", context);\n },\n \"astro:config:done\": async (context) => {\n if (integration)\n await callInner([integration], \"astro:config:done\", context);\n },\n \"astro:server:setup\": async (context) => {\n if (integration)\n await callInner([integration], \"astro:server:setup\", context);\n },\n \"astro:build:start\": async (context) => {\n if (integration)\n await callInner([integration], \"astro:build:start\", context);\n },\n \"astro:build:done\": async (context) => {\n if (integration)\n await callInner([integration], \"astro:build:done\", context);\n },\n },\n };\n}\n\nfunction configuredCookbook(options: CookbookOptions): AstroIntegration {\n const docsTheme = resolveDocsTheme(options.config?.theme);\n if (\n docsTheme.diagnostics.some((diagnostic) => diagnostic.severity === \"error\")\n ) {\n throw new Error(\n docsTheme.diagnostics.map((diagnostic) => diagnostic.message).join(\"\\n\"),\n );\n }\n configureTastyTheme(options.config?.theme, docsTheme);\n configureComponentStyles({\n ...options.config?.theme?.customStyles,\n ...options.config?.theme?.styles,\n });\n const headerPath = fileURLToPath(\n new URL(\"./overrides/Header.astro\", import.meta.url),\n );\n const footerPath = fileURLToPath(\n new URL(\"./overrides/Footer.astro\", import.meta.url),\n );\n const heroPath = fileURLToPath(\n new URL(\"./overrides/Hero.astro\", import.meta.url),\n );\n const emptyFooterPath = fileURLToPath(\n new URL(\"./overrides/EmptyFooter.astro\", import.meta.url),\n );\n const sidebarPath = fileURLToPath(\n new URL(\"./overrides/Sidebar.astro\", import.meta.url),\n );\n const mobileMenuFooterPath = fileURLToPath(\n new URL(\"./overrides/MobileMenuFooter.astro\", import.meta.url),\n );\n const mobileMenuTogglePath = fileURLToPath(\n new URL(\"./overrides/MobileMenuToggle.astro\", import.meta.url),\n );\n const markdownContentPath = fileURLToPath(\n new URL(\"./overrides/MarkdownContent.astro\", import.meta.url),\n );\n const themeSelectPath = fileURLToPath(\n new URL(\"./overrides/ThemeSelect.astro\", import.meta.url),\n );\n const components = resolveComponentOverrides(\n {\n DraftContentNotice: fileURLToPath(\n new URL(\"./overrides/DraftContentNotice.astro\", import.meta.url),\n ),\n Search: fileURLToPath(\n new URL(\"./overrides/Search.astro\", import.meta.url),\n ),\n Head: fileURLToPath(new URL(\"./overrides/Head.astro\", import.meta.url)),\n LanguageSelect: fileURLToPath(\n new URL(\"./overrides/LanguageSelect.astro\", import.meta.url),\n ),\n PageFrame: fileURLToPath(\n new URL(\"./overrides/PageFrame.astro\", import.meta.url),\n ),\n MobileTableOfContents: fileURLToPath(\n new URL(\"./overrides/MobileTableOfContents.astro\", import.meta.url),\n ),\n Footer: footerPath,\n Header: headerPath,\n Hero: heroPath,\n MarkdownContent: markdownContentPath,\n Sidebar: sidebarPath,\n MobileMenuFooter: mobileMenuFooterPath,\n MobileMenuToggle: mobileMenuTogglePath,\n ThemeSelect: themeSelectPath,\n SocialIcons: fileURLToPath(\n new URL(\"./overrides/SocialIcons.astro\", import.meta.url),\n ),\n SiteTitle: fileURLToPath(\n new URL(\"./components/SiteTitle.astro\", import.meta.url),\n ),\n EditLink: fileURLToPath(\n new URL(\"./components/EditLink.astro\", import.meta.url),\n ),\n LastUpdated: fileURLToPath(\n new URL(\"./components/LastUpdated.astro\", import.meta.url),\n ),\n Pagination: fileURLToPath(\n new URL(\"./components/Pagination.astro\", import.meta.url),\n ),\n TableOfContents: fileURLToPath(\n new URL(\"./components/TableOfContents.astro\", import.meta.url),\n ),\n },\n options.config?.components?.overrides,\n emptyFooterPath,\n );\n const navigation = resolveNavigationLayout(options.config?.navigation);\n // Tasty 3.8's integration shape is structurally compatible with Astro 7;\n // its published helper type still models `site` as URL-only.\n const tasty = tastyIntegration({\n islands: false,\n css: { mode: \"extract\" },\n }) as unknown as AstroIntegration;\n let inner: AstroIntegration[] = [tasty];\n let projectRoot = options.root;\n let graphConfig = options.config;\n let graphBase = \"/\";\n let graph: Awaited<ReturnType<typeof createDocsGraph>> | undefined;\n let siteIconBase = \"/\";\n let siteIcons: SiteIconSet | undefined;\n let fontAssets: FontAsset[] = [];\n let siteLogo: SiteLogoSet | undefined;\n\n async function loadGraph(refresh = false) {\n if (!graph || refresh) {\n graph = await createDocsGraph({\n ...(projectRoot ? { root: projectRoot } : {}),\n ...(graphConfig ? { config: graphConfig } : {}),\n base: graphBase,\n });\n assertValidDocs(graph);\n await validatePluginFrontmatter(graph.entries, options.frontmatterSchema);\n }\n return graph;\n }\n\n async function loadSiteIcons(): Promise<SiteIconSet> {\n if (!projectRoot) {\n throw new Error(\n \"Cookbook cannot generate site icons without a project root.\",\n );\n }\n return createSiteIcons({\n base: siteIconBase,\n root: projectRoot,\n ...(options.config?.site ? { site: options.config.site } : {}),\n themeColors: {\n light: docsTheme.colors.surface.light ?? \"#ffffff\",\n dark: docsTheme.colors.surface.dark ?? \"#20232a\",\n },\n });\n }\n\n return {\n name: \"cookbook\",\n hooks: {\n \"astro:config:setup\": async (context) => {\n const react = (\n await importNative(pathToFileURL(astroReactIntegration).href)\n ).default();\n projectRoot ??= fileURLToPath(context.config.root);\n const base = context.config.base;\n for (const [role, font] of Object.entries(\n options.config?.theme?.fonts ?? {},\n )) {\n if (!font || typeof font === \"string\" || \"google\" in font) continue;\n for (const file of font.files) {\n const path = join(\n fileURLToPath(context.config.publicDir),\n file.src.slice(1),\n );\n let isFile = false;\n try {\n isFile = (await stat(path)).isFile();\n } catch {\n // Report missing or unreadable files with the configuration path.\n }\n if (!isFile)\n throw new Error(\n `theme.fonts.${role}: ${file.src} must be a readable file in the site's public directory.`,\n );\n }\n }\n const resolvedFonts = await resolveThemeFonts(\n options.config?.theme?.fonts,\n {\n base,\n cacheDir: join(\n fileURLToPath(context.config.cacheDir),\n \"cookbook-fonts\",\n ),\n loading: options.config?.theme?.fontLoading ?? {},\n presets: docsTheme.presets,\n warn: (message) => context.logger.warn(message),\n },\n );\n const fontFaces = resolvedFonts.faces;\n fontAssets = resolvedFonts.assets;\n const usedFamilies = Object.values(docsTheme.presets).map(\n (preset) => preset.fontFamily ?? \"\",\n );\n configureFontFaces(fontFaces, {\n display: options.config?.theme?.fontLoading?.display ?? \"swap\",\n onest: usedFamilies.some((family) =>\n family.includes(\"Onest Variable\"),\n ),\n mono: usedFamilies.some((family) =>\n family.includes(\"JetBrains Mono Variable\"),\n ),\n });\n const configuredSite = options.config?.site?.url;\n const astroSite = context.config.site\n ? new URL(context.config.site).href\n : undefined;\n if (\n configuredSite &&\n astroSite &&\n astroSite !== new URL(configuredSite).href\n ) {\n throw new Error(\n `Cookbook site.url (${configuredSite}) conflicts with Astro site (${astroSite}).`,\n );\n }\n if (configuredSite || astroSite)\n graphConfig = {\n ...graphConfig,\n site: { ...graphConfig?.site, url: (configuredSite ?? astroSite)! },\n };\n siteIconBase = base;\n graphBase = base;\n context.config.integrations.push(\n sitemap({\n serialize: (item) => {\n if (!graph?.config.locales) return item;\n const route = navigationPath(\n decodeURI(new URL(item.url).pathname),\n graphBase,\n );\n return {\n ...item,\n links: localeAlternates(\n route,\n graph.routes.filter((route) => route.sitemap !== false),\n graph.config,\n ).map(({ lang, route }) => ({\n lang,\n url: new URL(\n `${graphBase.replace(/\\/$/, \"\")}${route === \"/\" ? \"/\" : `${route}/`}`,\n item.url,\n ).href,\n })),\n };\n },\n filter: (url) => {\n const pathname = decodeURI(new URL(url).pathname);\n const route = navigationPath(pathname, graphBase);\n return (\n graph?.routes.some(\n (entry) =>\n entry.route === route &&\n entry.discoverable !== false &&\n entry.sitemap !== false,\n ) ?? false\n );\n },\n }),\n );\n siteIcons = await loadSiteIcons();\n siteLogo = await resolveSiteLogo(\n projectRoot!,\n base,\n options.config?.site,\n );\n registerCookbookMarkdownPlugins(context.config.markdown.processor);\n inner = [react, tasty, mdx()];\n let markdownRuntime = {\n image: context.config.image,\n markdown: {\n ...context.config.markdown,\n syntaxHighlight: \"shiki\" as const,\n shikiConfig: cookbookShikiConfig(\n context.config.markdown.shikiConfig,\n ),\n },\n srcDir: context.config.srcDir,\n };\n let markdownRenderer: ReturnType<\n typeof markdownRuntime.markdown.processor.createRenderer\n >;\n context.updateConfig({\n ...(configuredSite && !context.config.site\n ? { site: configuredSite }\n : {}),\n base,\n output: \"static\",\n markdown: {\n syntaxHighlight: \"shiki\",\n shikiConfig: cookbookShikiConfig(\n context.config.markdown.shikiConfig,\n ),\n },\n vite: {\n ssr: {\n external: [\"@tenphi/docs\", \"react\", \"react-dom\"],\n },\n plugins: [\n {\n name: \"cookbook-server-only-styling\",\n enforce: \"pre\",\n resolveId(id, _importer, settings) {\n if (\n settings?.ssr ||\n this.environment.config.consumer === \"server\"\n )\n return;\n if (isStylingRuntime(id)) this.error(stylingRuntimeError);\n },\n generateBundle() {\n if (this.environment.config.consumer === \"server\") return;\n for (const id of this.getModuleIds())\n if (isStylingRuntime(id)) this.error(stylingRuntimeError);\n },\n },\n {\n name: \"cookbook-react-runtime\",\n enforce: \"post\",\n configResolved(config) {\n for (const environment of Object.values(\n config.environments,\n )) {\n if (environment.consumer === \"server\")\n environment.resolve.dedupe =\n environment.resolve.dedupe.filter(\n (id) => id !== \"react\" && id !== \"react-dom\",\n );\n if (environment.consumer === \"client\")\n environment.optimizeDeps.include =\n environment.optimizeDeps.include?.map((id) =>\n /^react(?:-dom)?(?:\\/|$)/.test(id)\n ? packageRequire.resolve(id)\n : id,\n ) ?? [];\n }\n },\n resolveId(id, _importer, settings) {\n if (\n !settings?.ssr &&\n this.environment.config.consumer !== \"server\" &&\n /^react(?:-dom)?(?:\\/|$)/.test(id)\n ) {\n return packageRequire.resolve(id);\n }\n },\n },\n componentOverridesPlugin(\n components,\n fileURLToPath(context.config.root),\n ),\n virtualDocsPlugin(\n async () => {\n const loaded = await loadGraph(true);\n const entries = await Promise.all(\n loaded.entries.map(async (entry) => {\n const hero = await resolveHeroMetadata(entry);\n if (\n entry.trust === \"mdx\" &&\n entry.sourcePath.toLowerCase().endsWith(\".mdx\")\n ) {\n return { ...entry, hero, mdx: true };\n }\n const { image, markdown, srcDir } = markdownRuntime;\n markdownRenderer ??= markdown.processor.createRenderer({\n image,\n syntaxHighlight: markdown.syntaxHighlight,\n shikiConfig: markdown.shikiConfig,\n gfm: markdown.gfm,\n smartypants: markdown.smartypants,\n } as unknown as Parameters<\n typeof markdown.processor.createRenderer\n >[0]);\n const renderer = await markdownRenderer;\n const rendered = await renderer.render(\n entry.transformedBody,\n {\n frontmatter: entry.frontmatter,\n fileURL: docsContentUrl(entry.route, srcDir),\n },\n );\n return {\n ...entry,\n hero,\n rendered: {\n html: rendered.code,\n headings: rendered.metadata.headings,\n },\n };\n }),\n );\n return {\n entries,\n routes: loaded.routes,\n redirects: loaded.redirects,\n tableOfContents: loaded.config.tableOfContents,\n site: documentedSite(loaded),\n base: loaded.config.build.base,\n search:\n loaded.config.search.enabled ||\n typeof options.config?.components?.overrides?.Search ===\n \"string\",\n logo: siteLogo?.logo,\n locales: loaded.config.locales,\n defaultLocale: loaded.config.defaultLocale,\n translations: loaded.config.translations,\n head: [\n ...(siteIcons?.head ?? []),\n ...(options.config?.head ?? []),\n ],\n };\n },\n navigation,\n () => [\n projectRoot!,\n ...(graphConfig?.content?.sources ?? []).flatMap((source) =>\n \"package\" in source\n ? []\n : [resolve(projectRoot!, source.root ?? \".\")],\n ),\n ...(graph?.entries.map((entry) => entry.sourceRoot) ?? []),\n ],\n ),\n ],\n resolve: {\n alias: [\n {\n find: \"@tenphi/tasty/ssr/astro-middleware-static\",\n replacement: tastyStaticMiddleware,\n },\n {\n find: \"@tenphi/tasty/ssr/astro-middleware-extract-static\",\n replacement: tastyExtractStaticMiddleware,\n },\n {\n find: \"@astrojs/react/server.js\",\n replacement: astroReactServer,\n },\n {\n find: \"@astrojs/react/client.js\",\n replacement: astroReactClient,\n },\n ],\n },\n },\n });\n await callInner(inner, \"astro:config:setup\", context);\n\n graph = await createDocsGraph({\n root: projectRoot,\n ...(graphConfig ? { config: graphConfig } : {}),\n base: graphBase,\n });\n assertValidDocs(graph);\n context.injectRoute({\n pattern: \"[...route]\",\n entrypoint: new URL(\"./routes/DocsPage.astro\", import.meta.url),\n prerender: true,\n });\n if (!graph.entryByRoute(\"/404\")) {\n context.injectRoute({\n pattern: \"404\",\n entrypoint: new URL(\"./routes/NotFound.astro\", import.meta.url),\n prerender: true,\n });\n }\n\n context.config.integrations.push({\n name: \"cookbook-markdown-renderer\",\n hooks: {\n \"astro:config:setup\": ({ config }) => {\n markdownRuntime = {\n image: config.image,\n markdown: {\n ...config.markdown,\n syntaxHighlight: \"shiki\" as const,\n shikiConfig: cookbookShikiConfig(config.markdown.shikiConfig),\n },\n srcDir: config.srcDir,\n };\n },\n },\n });\n },\n \"astro:config:done\": async (context) => {\n configureCodeHighlighting(\n cookbookShikiConfig(context.config.markdown.shikiConfig),\n );\n await callInner(inner, \"astro:config:done\", context);\n },\n \"astro:server:setup\": async ({ server, logger }) => {\n let assets = docsAssetMap(await loadGraph());\n if (siteLogo?.sourcePaths.length) {\n server.watcher.add(siteLogo.sourcePaths);\n server.watcher.on(\"change\", (path) => {\n if (siteLogo?.sourcePaths.includes(path)) void server.restart();\n });\n }\n if (options.config?.site?.favicon && siteIcons) {\n server.watcher.add(siteIcons.sourcePath);\n server.watcher.on(\"change\", async (changedPath) => {\n if (changedPath !== siteIcons?.sourcePath) return;\n try {\n siteIcons = await loadSiteIcons();\n server.ws.send({ type: \"full-reload\" });\n } catch (error) {\n logger.error(errorMessage(error));\n }\n });\n }\n server.middlewares.use(async (request, response, next) => {\n if (request.method !== \"GET\" && request.method !== \"HEAD\") {\n next();\n return;\n }\n const requestPathname = requestPath(request.url);\n // Vite strips Astro's base before invoking development middleware.\n const pathname =\n graphBase !== \"/\" && !requestPathname.startsWith(graphBase)\n ? `${graphBase.replace(/\\/$/, \"\")}${requestPathname}`\n : requestPathname;\n if (pathname.includes(\"/_cookbook/pages/\")) {\n try {\n const current = await loadGraph(true);\n const entry = current.entries.find(\n (entry) =>\n !entry.frontmatter.draft &&\n agentPagePath(entry.route, current.config.build.base) ===\n pathname,\n );\n if (entry && current.config.site.seo?.copyPage !== false) {\n response.statusCode = 200;\n response.setHeader(\n \"Content-Type\",\n \"text/markdown; charset=utf-8\",\n );\n response.setHeader(\"X-Robots-Tag\", \"noindex\");\n response.end(\n request.method === \"HEAD\"\n ? undefined\n : renderAgentMarkdown(entry, current.config),\n );\n return;\n }\n } catch (error) {\n logger.error(errorMessage(error));\n }\n }\n const fontAsset = [...fontAssets, ...(siteLogo?.assets ?? [])].find(\n (asset) => asset.publicPath === pathname,\n );\n if (fontAsset) {\n response.statusCode = 200;\n response.setHeader(\"Content-Type\", fontAsset.contentType);\n response.setHeader(\"Content-Length\", fontAsset.body.byteLength);\n response.setHeader(\n \"Cache-Control\",\n \"public, max-age=31536000, immutable\",\n );\n response.end(\n request.method === \"HEAD\" ? undefined : fontAsset.body,\n );\n return;\n }\n const siteIcon = siteIcons?.assets.find(\n (asset) => asset.publicPath === pathname,\n );\n if (siteIcon) {\n response.statusCode = 200;\n response.setHeader(\"Content-Type\", siteIcon.contentType);\n response.setHeader(\"Content-Length\", siteIcon.body.byteLength);\n response.setHeader(\"Cache-Control\", \"no-cache\");\n response.end(request.method === \"HEAD\" ? undefined : siteIcon.body);\n return;\n }\n if (!pathname.includes(\"/_tasty-assets/\")) {\n next();\n return;\n }\n let asset = assets.get(pathname);\n if (!asset) {\n try {\n assets = docsAssetMap(await loadGraph(true));\n } catch {\n next();\n return;\n }\n asset = assets.get(pathname);\n }\n if (!asset?.sourcePath) {\n next();\n return;\n }\n try {\n const body = await readFile(asset.sourcePath);\n response.statusCode = 200;\n response.setHeader(\"Content-Type\", assetContentType(pathname));\n response.setHeader(\"Content-Length\", body.byteLength);\n response.setHeader(\"Cache-Control\", \"no-cache\");\n response.end(request.method === \"HEAD\" ? undefined : body);\n } catch {\n next();\n }\n });\n },\n \"astro:build:start\": async (context) => {\n siteIcons = await loadSiteIcons();\n await loadGraph();\n await callInner(inner, \"astro:build:start\", context);\n },\n \"astro:build:done\": async (context) => {\n await callInner(inner, \"astro:build:done\", context);\n const output = fileURLToPath(context.dir);\n const anatomyNames = new Set<string>();\n for (const relativePath of await readdir(output, { recursive: true })) {\n if (extname(relativePath) !== \".html\") continue;\n const path = join(output, relativePath);\n const html = await readFile(path, \"utf8\");\n for (const match of html.matchAll(/\\bdata-tasty-anatomy=\"([^\"]+)\"/g))\n anatomyNames.add(match[1]!);\n const sanitized = html\n .replace(\n /\\s*<link\\b(?=[^>]*rel=\"stylesheet\")(?=[^>]*href=\"data:text\\/css,\")[^>]*>/g,\n \"\",\n )\n .replace(/\\s*<style>\\s*<\\/style>/g, \"\")\n .replace(\n /<style>astro-island,astro-slot,astro-static-slot\\{display:contents\\}<\\/style>/g,\n \"\",\n );\n assertTastyOutput(sanitized, relativePath);\n if (sanitized !== html) await writeFile(path, sanitized);\n }\n for (const name of unusedCustomStyleNames(\n options.config?.theme?.customStyles,\n anatomyNames,\n )) {\n context.logger.warn(\n `theme.customStyles.${name} did not match a component style resolver or rendered data-tasty-anatomy attribute. Check that its name matches defineComponent() or resolveComponentStyles().`,\n );\n }\n if (graph?.config.search.enabled !== false) {\n try {\n const { index, errors } = await pagefind.createIndex();\n if (errors.length || !index)\n throw new Error(\n errors.join(\"\\n\") || \"Pagefind did not create an index.\",\n );\n const added = await index.addDirectory({ path: output });\n if (added.errors.length) throw new Error(added.errors.join(\"\\n\"));\n const written = await index.writeFiles({\n outputPath: join(output, \"pagefind\"),\n });\n if (written.errors.length)\n throw new Error(written.errors.join(\"\\n\"));\n } finally {\n await pagefind.close();\n }\n }\n const pagefindOutput = join(output, \"pagefind\");\n if (existsSync(pagefindOutput)) {\n for (const name of await readdir(pagefindOutput)) {\n if (extname(name) === \".css\") {\n await unlink(join(pagefindOutput, name));\n }\n }\n }\n for (const relativePath of await readdir(output, { recursive: true })) {\n if (\n extname(relativePath) === \".css\" &&\n !/^tasty\\.[^/]+\\.css$/.test(\n relativePath.split(/[/\\\\]/).at(-1) ?? \"\",\n )\n ) {\n throw new Error(\n `Non-Tasty stylesheet found in ${relativePath}. Use theme.styles or Tasty components for visual changes.`,\n );\n }\n }\n for (const asset of [\n ...(siteIcons?.assets ?? []),\n ...fontAssets,\n ...(siteLogo?.assets ?? []),\n ]) {\n const target = join(output, asset.outputPath);\n await mkdir(dirname(target), { recursive: true });\n await writeFile(target, asset.body);\n }\n if (!graph) return;\n for (const asset of graph.assets) {\n if (!asset.sourcePath || !asset.publicPath) continue;\n const target = join(\n output,\n outputPathForPublicAsset(asset.publicPath, graph.config.build.base),\n );\n await mkdir(dirname(target), { recursive: true });\n await cp(asset.sourcePath, target);\n }\n await writeAgentDiscovery(output, graph);\n },\n },\n };\n}\n\nfunction registerCookbookMarkdownPlugins(processor: {\n name: string;\n options: object;\n}): void {\n if (processor.name === \"unified\") {\n const options = processor.options as { rehypePlugins?: unknown };\n const plugins = Array.isArray(options.rehypePlugins)\n ? options.rehypePlugins\n : [];\n if (!plugins.includes(rehypeMermaid)) plugins.push(rehypeMermaid);\n if (!plugins.includes(rehypeAlerts)) plugins.push(rehypeAlerts);\n if (!plugins.includes(rehypeTableScroll)) plugins.push(rehypeTableScroll);\n if (!plugins.includes(rehypePageAffordances))\n plugins.push(rehypePageAffordances);\n options.rehypePlugins = plugins;\n } else if (processor.name === \"satteri\") {\n const options = processor.options as { hastPlugins?: unknown };\n const plugins = Array.isArray(options.hastPlugins)\n ? options.hastPlugins\n : [];\n if (!plugins.includes(satteriMermaid)) plugins.push(satteriMermaid);\n if (!plugins.includes(satteriAlerts)) plugins.push(satteriAlerts);\n if (!plugins.includes(satteriTableScroll)) plugins.push(satteriTableScroll);\n if (!plugins.includes(satteriPageAffordances))\n plugins.push(satteriPageAffordances);\n options.hastPlugins = plugins;\n }\n}\n\nfunction docsContentUrl(route: string, srcDir: URL): URL {\n const slug = route === \"/\" ? \"index\" : route.replace(/^\\/+|\\/+$/g, \"\");\n return new URL(`content/docs/${slug}.md`, srcDir);\n}\n\nfunction componentOverridesPlugin(\n components: Record<string, string>,\n astroRoot: string,\n) {\n const prefix = \"virtual:cookbook/components/\";\n return {\n name: \"cookbook-component-overrides\",\n resolveId(id: string) {\n const name = id.startsWith(prefix) ? id.slice(prefix.length) : undefined;\n return name && components[name] ? `\\0${id}` : undefined;\n },\n load(id: string) {\n const name = id.startsWith(`\\0${prefix}`)\n ? id.slice(prefix.length + 1)\n : undefined;\n if (!name || !components[name]) return undefined;\n const configured = components[name];\n const target = configured.startsWith(\".\")\n ? resolve(astroRoot, configured)\n : configured;\n return `export { default } from ${JSON.stringify(target)};`;\n },\n };\n}\n\nfunction docsAssetMap(graph: Awaited<ReturnType<typeof createDocsGraph>>) {\n return new Map(\n graph.assets.flatMap((asset) =>\n asset.publicPath && asset.sourcePath\n ? [[asset.publicPath, asset] as const]\n : [],\n ),\n );\n}\n\nfunction documentedSite(\n graph: Awaited<ReturnType<typeof createDocsGraph>>,\n): Awaited<ReturnType<typeof createDocsGraph>>[\"config\"][\"site\"] {\n if (graph.config.site.version) return graph.config.site;\n const packages = new Set(\n graph.entries.flatMap((entry) =>\n entry.package?.resolved ? [entry.package.resolved] : [],\n ),\n );\n if (packages.size !== 1) return graph.config.site;\n const resolved = packages.values().next().value;\n if (!resolved) return graph.config.site;\n const separator = resolved.lastIndexOf(\"@\");\n if (separator <= 0 || separator === resolved.length - 1)\n return graph.config.site;\n return { ...graph.config.site, version: resolved.slice(separator + 1) };\n}\n\nfunction requestPath(url: string | undefined): string {\n try {\n return decodeURIComponent(new URL(url ?? \"/\", \"http://localhost\").pathname);\n } catch {\n return \"\";\n }\n}\n\nfunction assetContentType(pathname: string): string {\n switch (extname(pathname).toLowerCase()) {\n case \".avif\":\n return \"image/avif\";\n case \".gif\":\n return \"image/gif\";\n case \".jpeg\":\n case \".jpg\":\n return \"image/jpeg\";\n case \".png\":\n return \"image/png\";\n case \".svg\":\n return \"image/svg+xml\";\n case \".webp\":\n return \"image/webp\";\n default:\n return \"application/octet-stream\";\n }\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction configureTastyTheme(\n theme: DocsConfig[\"theme\"],\n resolved: ReturnType<typeof resolveDocsTheme>,\n): void {\n const tokens = tastyTokens(resolved) as ConfigTokens;\n const globalStyles = resolveLegacyAnatomyStyles(theme?.customStyles);\n\n // Recipes and custom parser units are module-local in Tasty. Astro evaluates\n // renderer code in a separate server module graph. Share configuration only\n // inside the build process; never serialize this state into the page.\n (\n globalThis as typeof globalThis & { __tenphiCookbookTastyRuntime?: unknown }\n ).__tenphiCookbookTastyRuntime = {\n units: { ...TASTY_UNITS, ...theme?.units },\n recipes: theme?.recipes ?? {},\n states: theme?.states ?? {},\n presets: resolved.presets,\n tokens,\n };\n configure({\n states: {\n ...cookbookStates,\n ...theme?.states,\n },\n units: { ...TASTY_UNITS, ...theme?.units },\n recipes: theme?.recipes ?? {},\n tokens,\n presets: resolved.presets as Record<string, TypographyPreset>,\n ...(globalStyles\n ? { globalStyles: globalStyles as Record<string, Styles> }\n : {}),\n });\n}\n\nasync function callInner<K extends keyof AstroIntegration[\"hooks\"]>(\n integrations: AstroIntegration[],\n hook: K,\n context: HookParameters<K>,\n): Promise<void> {\n for (const integration of integrations) {\n const handler = integration.hooks[hook];\n if (typeof handler === \"function\") {\n await (handler as (value: HookParameters<K>) => void | Promise<void>)(\n context,\n );\n }\n }\n}\n\nfunction virtualDocsPlugin(\n getContent: () => unknown | Promise<unknown>,\n layout: ResolvedNavigationLayout,\n getWatchRoots: () => string[],\n) {\n const configId = \"\\0virtual:cookbook/config\";\n const layoutId = \"\\0virtual:cookbook/layout\";\n const mdxPrefix = \"virtual:cookbook/mdx/\";\n type VirtualContent = {\n entries: Array<{\n absolutePath: string;\n assets?: Array<{ sourcePath?: string }>;\n mdx?: boolean;\n route: string;\n transformedBody: string;\n }>;\n };\n type MdxRecord = {\n entry: VirtualContent[\"entries\"][number];\n sourceId: string;\n virtualId: string;\n };\n let contentPromise: Promise<VirtualContent> | undefined;\n let mdxRecords: MdxRecord[] = [];\n const watchedPaths = new Set<string>();\n\n async function loadContent(): Promise<VirtualContent> {\n contentPromise ??= Promise.resolve(getContent()) as Promise<VirtualContent>;\n let content: VirtualContent;\n try {\n content = await contentPromise;\n } catch (error) {\n contentPromise = undefined;\n throw error;\n }\n mdxRecords = content.entries.flatMap((entry, index) =>\n entry.mdx\n ? [\n {\n entry,\n sourceId: entry.absolutePath.replace(\n /\\.mdx$/i,\n `.cookbook-${index}.mdx`,\n ),\n virtualId: `${mdxPrefix}${index}`,\n },\n ]\n : [],\n );\n return content;\n }\n\n return {\n name: \"cookbook-data\",\n enforce: \"pre\" as const,\n configureServer(server: HookParameters<\"astro:server:setup\">[\"server\"]) {\n const roots = [...new Set(getWatchRoots())];\n server.watcher.add(roots);\n const changed = (_event: string, path: string) => {\n const owned = roots.some(\n (root) => path === root || path.startsWith(`${root}/`),\n );\n if (\n !watchedPaths.has(path) &&\n !(\n owned &&\n (/\\.mdx?$/i.test(path) || path.endsWith(\"/cookbook.lock.json\"))\n )\n )\n return;\n contentPromise = undefined;\n mdxRecords = [];\n for (const environment of Object.values(server.environments))\n environment.moduleGraph.invalidateAll();\n server.ws.send({ type: \"full-reload\" });\n };\n server.watcher.on(\"all\", changed);\n server.httpServer?.once(\"close\", () =>\n server.watcher.off(\"all\", changed),\n );\n },\n async resolveId(\n id: string,\n _importer: string | undefined,\n resolveOptions: { ssr?: boolean },\n ) {\n if (id === \"virtual:cookbook/config\") {\n if (resolveOptions.ssr === false)\n throw new Error(\n \"Cookbook content queries are build-time only. Pass selected public data to a client component as props instead.\",\n );\n return configId;\n }\n if (id === \"virtual:cookbook/layout\") return layoutId;\n if (id.startsWith(mdxPrefix)) {\n await loadContent();\n return mdxRecords.find((record) => record.virtualId === id)?.sourceId;\n }\n return undefined;\n },\n async load(this: { addWatchFile(path: string): void }, id: string) {\n if (id === configId) {\n const content = await loadContent();\n watchedPaths.clear();\n for (const entry of content.entries) {\n watchedPaths.add(entry.absolutePath);\n this.addWatchFile(entry.absolutePath);\n for (const asset of entry.assets ?? []) {\n if (!asset.sourcePath) continue;\n watchedPaths.add(asset.sourcePath);\n this.addWatchFile(asset.sourcePath);\n }\n }\n const loaders = mdxRecords\n .map(\n ({ entry, virtualId }) =>\n `${JSON.stringify(entry.route)}: () => import(${JSON.stringify(virtualId)})`,\n )\n .join(\",\\n\");\n return `export const content = ${JSON.stringify(content)};\\nexport const mdxLoaders = {${loaders}};`;\n }\n if (id === layoutId) {\n return `export const layout = ${JSON.stringify(layout)};`;\n }\n const mdx = mdxRecords.find((record) => record.sourceId === id);\n if (mdx) return mdx.entry.transformedBody;\n return undefined;\n },\n watchChange(id: string) {\n if (!watchedPaths.has(id)) return;\n contentPromise = undefined;\n mdxRecords = [];\n },\n };\n}\n\nfunction repositoryIcon(repository: string): \"github\" | \"gitlab\" | \"link\" {\n try {\n const host = new URL(repository).hostname;\n if (host === \"github.com\" || host.endsWith(\".github.com\")) return \"github\";\n if (host === \"gitlab.com\" || host.endsWith(\".gitlab.com\")) return \"gitlab\";\n } catch {\n // Configuration validation reports invalid repository URLs.\n }\n return \"link\";\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { ResolvedNavigationLayout } from "./navigation.js";
|
|
2
|
+
import { DocsConfig, DocsRoute } from "@tenphi/docs";
|
|
3
|
+
//#region src/localization.d.ts
|
|
4
|
+
type LocaleOptions = {
|
|
5
|
+
locales?: DocsConfig["locales"] | undefined;
|
|
6
|
+
defaultLocale?: DocsConfig["defaultLocale"] | undefined;
|
|
7
|
+
translations?: DocsConfig["translations"] | undefined;
|
|
8
|
+
};
|
|
9
|
+
declare function routeLocale(path: string, options: LocaleOptions): string;
|
|
10
|
+
/** Author components can render before the page initializes route locals. */
|
|
11
|
+
declare function requestLanguage(pathname: string, base: string, options: LocaleOptions): string;
|
|
12
|
+
declare function localePath(path: string, options: LocaleOptions): string;
|
|
13
|
+
declare function localizedRoute(path: string, locale: string, options: LocaleOptions): string;
|
|
14
|
+
/** Missing translations use a real default-language page, then a real locale home. */
|
|
15
|
+
declare function localeTarget(path: string, locale: string, routes: DocsRoute[], options: LocaleOptions): string | undefined;
|
|
16
|
+
declare function localeHref(link: string, currentPath: string, routes: DocsRoute[], options: LocaleOptions, base?: string): string;
|
|
17
|
+
/** Resolve navigation against the current locale's available routes. */
|
|
18
|
+
declare function localizedNavigation(layout: ResolvedNavigationLayout, routes: DocsRoute[], currentPath: string, options: LocaleOptions): {
|
|
19
|
+
layout: ResolvedNavigationLayout;
|
|
20
|
+
routes: DocsRoute[];
|
|
21
|
+
};
|
|
22
|
+
declare const ENGLISH_MESSAGES: {
|
|
23
|
+
readonly copyPage: "Copy page";
|
|
24
|
+
readonly viewMarkdown: "Download Markdown";
|
|
25
|
+
readonly pageCopied: "Page copied";
|
|
26
|
+
readonly pageCopyError: "Could not copy. Download Markdown to read or copy the text.";
|
|
27
|
+
readonly draftTitle: "Draft";
|
|
28
|
+
readonly draftNotice: "This page is available by direct link and excluded from navigation and indexes.";
|
|
29
|
+
readonly searchError: "Search could not load. Close and try again.";
|
|
30
|
+
readonly appearance: "Appearance";
|
|
31
|
+
readonly colorScheme: "Color scheme";
|
|
32
|
+
readonly contrast: "Contrast";
|
|
33
|
+
readonly normalContrast: "Normal";
|
|
34
|
+
readonly highContrast: "High";
|
|
35
|
+
readonly auto: "Auto";
|
|
36
|
+
readonly closeNavigation: "Close navigation";
|
|
37
|
+
readonly primary: "Primary";
|
|
38
|
+
readonly sections: "Sections";
|
|
39
|
+
readonly chooseSection: "Choose section";
|
|
40
|
+
readonly headerLinks: "Header links";
|
|
41
|
+
readonly more: "More";
|
|
42
|
+
readonly closeMore: "Close more menu";
|
|
43
|
+
readonly moreLinks: "More links";
|
|
44
|
+
readonly versions: "Versions";
|
|
45
|
+
readonly documentationVersion: "Documentation version";
|
|
46
|
+
readonly documentationVersions: "Documentation versions";
|
|
47
|
+
readonly version: "Version";
|
|
48
|
+
readonly home: "Home";
|
|
49
|
+
readonly generatedWith: "Generated with";
|
|
50
|
+
readonly viewSource: "View source";
|
|
51
|
+
readonly copyCode: "Copy code";
|
|
52
|
+
readonly codeCopied: "Code copied";
|
|
53
|
+
readonly codeCopyError: "Could not copy code";
|
|
54
|
+
readonly copyHeading: "Copy link to “{heading}”";
|
|
55
|
+
readonly linkCopied: "Link copied";
|
|
56
|
+
readonly linkCopyError: "Could not copy link";
|
|
57
|
+
readonly notFound: "Page not found";
|
|
58
|
+
readonly notFoundDescription: "The page you requested could not be found.";
|
|
59
|
+
readonly fallback: "fallback";
|
|
60
|
+
};
|
|
61
|
+
type MessageKey = keyof typeof ENGLISH_MESSAGES;
|
|
62
|
+
declare function messages(lang: string, options?: LocaleOptions): Record<MessageKey, string>;
|
|
63
|
+
declare function localeAlternates(path: string, routes: DocsRoute[], options: LocaleOptions): Array<{
|
|
64
|
+
lang: string;
|
|
65
|
+
route: string;
|
|
66
|
+
}>;
|
|
67
|
+
//#endregion
|
|
68
|
+
export { ENGLISH_MESSAGES, MessageKey, localeAlternates, localeHref, localePath, localeTarget, localizedNavigation, localizedRoute, messages, requestLanguage, routeLocale };
|
|
69
|
+
//# sourceMappingURL=localization.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localization.d.ts","names":[],"sources":["../src/localization.ts"],"mappings":";;;KAMK;EACH,UAAU;EACV,gBAAgB;EAChB,eAAe;;iBAGD,YAAY,cAAc,SAAS;;iBAMnC,gBACd,kBACA,cACA,SAAS;iBAWK,WAAW,cAAc,SAAS;iBAQlC,eACd,cACA,gBACA,SAAS;;iBASK,aACd,cACA,gBACA,QAAQ,aACR,SAAS;iBAoBK,WACd,cACA,qBACA,QAAQ,aACR,SAAS,eACT;;iBAec,oBACd,QAAQ,0BACR,QAAQ,aACR,qBACA,SAAS;EACN,QAAQ;EAA0B,QAAQ;;cAiElC;WACX;WACA;WACA;WACA;WACA;WACA;WAEA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;WACA;;KAEU,0BAA0B;iBA0CtB,SACd,cACA,UAAS,gBACR,OAAO;iBAUM,iBACd,cACA,QAAQ,aACR,SAAS,gBACR;EAAQ;EAAc"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { normalizeNavigationPath } from "./navigation.js";
|
|
2
|
+
//#region src/localization.ts
|
|
3
|
+
function routeLocale(path, options) {
|
|
4
|
+
const first = normalizeNavigationPath(path).split("/")[1];
|
|
5
|
+
return first && first !== "root" && options.locales?.[first] ? first : "root";
|
|
6
|
+
}
|
|
7
|
+
/** Author components can render before the page initializes route locals. */
|
|
8
|
+
function requestLanguage(pathname, base, options) {
|
|
9
|
+
const prefix = base.replace(/\/$/, "");
|
|
10
|
+
const locale = routeLocale(prefix && (pathname === prefix || pathname.startsWith(`${prefix}/`)) ? pathname.slice(prefix.length) : pathname, options);
|
|
11
|
+
return options.locales?.[locale]?.lang ?? (locale === "root" ? "en" : locale);
|
|
12
|
+
}
|
|
13
|
+
function localePath(path, options) {
|
|
14
|
+
const route = normalizeNavigationPath(path);
|
|
15
|
+
const locale = routeLocale(route, options);
|
|
16
|
+
return locale === "root" ? route : normalizeNavigationPath(route.slice(locale.length + 1));
|
|
17
|
+
}
|
|
18
|
+
function localizedRoute(path, locale, options) {
|
|
19
|
+
const suffix = localePath(path, options);
|
|
20
|
+
return normalizeNavigationPath(`${locale === "root" ? "" : `/${locale}`}${suffix}`);
|
|
21
|
+
}
|
|
22
|
+
/** Missing translations use a real default-language page, then a real locale home. */
|
|
23
|
+
function localeTarget(path, locale, routes, options) {
|
|
24
|
+
const visible = new Set(routes.filter((route) => route.discoverable !== false).map((route) => route.route));
|
|
25
|
+
const fallback = options.defaultLocale ?? (options.locales?.root ? "root" : Object.keys(options.locales ?? {})[0] ?? "root");
|
|
26
|
+
return [
|
|
27
|
+
localizedRoute(path, locale, options),
|
|
28
|
+
localizedRoute(path, fallback, options),
|
|
29
|
+
localizedRoute("/", locale, options),
|
|
30
|
+
localizedRoute("/", fallback, options)
|
|
31
|
+
].find((route) => visible.has(route));
|
|
32
|
+
}
|
|
33
|
+
function localeHref(link, currentPath, routes, options, base = "/") {
|
|
34
|
+
if (!link.startsWith("/") || link.startsWith("//")) return link;
|
|
35
|
+
const suffix = /[?#].*$/.exec(link)?.[0] ?? "";
|
|
36
|
+
const path = suffix ? link.slice(0, -suffix.length) : link;
|
|
37
|
+
const target = options.locales ? localeTarget(path, routeLocale(currentPath, options), routes, options) : normalizeNavigationPath(path);
|
|
38
|
+
return `${base.replace(/\/$/, "")}${target ?? normalizeNavigationPath(path)}${suffix}` || "/";
|
|
39
|
+
}
|
|
40
|
+
/** Resolve navigation against the current locale's available routes. */
|
|
41
|
+
function localizedNavigation(layout, routes, currentPath, options) {
|
|
42
|
+
if (!options.locales) return {
|
|
43
|
+
layout,
|
|
44
|
+
routes
|
|
45
|
+
};
|
|
46
|
+
const locale = routeLocale(currentPath, options);
|
|
47
|
+
const language = options.locales[locale]?.lang ?? (locale === "root" ? "en" : locale);
|
|
48
|
+
const label = (value) => options.translations?.[language]?.[`navigation.${value}`] ?? options.translations?.[language.split("-")[0]]?.[`navigation.${value}`] ?? value;
|
|
49
|
+
const localRoutes = routes.filter((route) => routeLocale(route.route, options) === locale).map((route) => ({
|
|
50
|
+
...route,
|
|
51
|
+
route: localePath(route.route, options)
|
|
52
|
+
}));
|
|
53
|
+
const available = new Set(localRoutes.filter((route) => route.discoverable !== false).map((route) => route.route));
|
|
54
|
+
const convert = (items) => items.flatMap((item) => {
|
|
55
|
+
const link = typeof item === "string" ? item : item.link;
|
|
56
|
+
const internal = link?.startsWith("/") && !link.startsWith("//");
|
|
57
|
+
const translated = internal ? localePath(link, options) : link;
|
|
58
|
+
if (typeof item === "string") return !internal || available.has(translated) ? [translated] : [];
|
|
59
|
+
if ("items" in item || "autogenerate" in item) {
|
|
60
|
+
const { link: _link, ...group } = item;
|
|
61
|
+
return [{
|
|
62
|
+
...group,
|
|
63
|
+
label: label(group.label),
|
|
64
|
+
...translated && (!internal || available.has(translated)) ? { link: translated } : {},
|
|
65
|
+
..."items" in item ? { items: convert(item.items) } : { autogenerate: { directory: localePath(item.autogenerate.directory, options) } }
|
|
66
|
+
}];
|
|
67
|
+
}
|
|
68
|
+
return !internal || available.has(translated) ? [{
|
|
69
|
+
...item,
|
|
70
|
+
label: label(item.label),
|
|
71
|
+
link: translated
|
|
72
|
+
}] : [];
|
|
73
|
+
});
|
|
74
|
+
return {
|
|
75
|
+
layout: {
|
|
76
|
+
...layout,
|
|
77
|
+
...layout.items ? { items: convert(layout.items) } : {},
|
|
78
|
+
tabs: layout.tabs.map((tab) => ({
|
|
79
|
+
...tab,
|
|
80
|
+
label: label(tab.label),
|
|
81
|
+
link: tab.link.startsWith("/") && !tab.link.startsWith("//") ? localePath(tab.link, options) : tab.link,
|
|
82
|
+
...tab.items ? { items: convert(tab.items) } : {}
|
|
83
|
+
}))
|
|
84
|
+
},
|
|
85
|
+
routes: localRoutes
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const ENGLISH_MESSAGES = {
|
|
89
|
+
copyPage: "Copy page",
|
|
90
|
+
viewMarkdown: "Download Markdown",
|
|
91
|
+
pageCopied: "Page copied",
|
|
92
|
+
pageCopyError: "Could not copy. Download Markdown to read or copy the text.",
|
|
93
|
+
draftTitle: "Draft",
|
|
94
|
+
draftNotice: "This page is available by direct link and excluded from navigation and indexes.",
|
|
95
|
+
searchError: "Search could not load. Close and try again.",
|
|
96
|
+
appearance: "Appearance",
|
|
97
|
+
colorScheme: "Color scheme",
|
|
98
|
+
contrast: "Contrast",
|
|
99
|
+
normalContrast: "Normal",
|
|
100
|
+
highContrast: "High",
|
|
101
|
+
auto: "Auto",
|
|
102
|
+
closeNavigation: "Close navigation",
|
|
103
|
+
primary: "Primary",
|
|
104
|
+
sections: "Sections",
|
|
105
|
+
chooseSection: "Choose section",
|
|
106
|
+
headerLinks: "Header links",
|
|
107
|
+
more: "More",
|
|
108
|
+
closeMore: "Close more menu",
|
|
109
|
+
moreLinks: "More links",
|
|
110
|
+
versions: "Versions",
|
|
111
|
+
documentationVersion: "Documentation version",
|
|
112
|
+
documentationVersions: "Documentation versions",
|
|
113
|
+
version: "Version",
|
|
114
|
+
home: "Home",
|
|
115
|
+
generatedWith: "Generated with",
|
|
116
|
+
viewSource: "View source",
|
|
117
|
+
copyCode: "Copy code",
|
|
118
|
+
codeCopied: "Code copied",
|
|
119
|
+
codeCopyError: "Could not copy code",
|
|
120
|
+
copyHeading: "Copy link to “{heading}”",
|
|
121
|
+
linkCopied: "Link copied",
|
|
122
|
+
linkCopyError: "Could not copy link",
|
|
123
|
+
notFound: "Page not found",
|
|
124
|
+
notFoundDescription: "The page you requested could not be found.",
|
|
125
|
+
fallback: "fallback"
|
|
126
|
+
};
|
|
127
|
+
const FRENCH_MESSAGES = {
|
|
128
|
+
copyPage: "Copier la page",
|
|
129
|
+
viewMarkdown: "Télécharger le Markdown",
|
|
130
|
+
pageCopied: "Page copiée",
|
|
131
|
+
pageCopyError: "Copie impossible. Téléchargez le Markdown pour lire ou copier le texte.",
|
|
132
|
+
draftTitle: "Brouillon",
|
|
133
|
+
draftNotice: "Cette page est accessible par son lien direct et exclue de la navigation et des index.",
|
|
134
|
+
searchError: "La recherche n’a pas pu se charger. Fermez et réessayez.",
|
|
135
|
+
appearance: "Apparence",
|
|
136
|
+
colorScheme: "Thème de couleur",
|
|
137
|
+
contrast: "Contraste",
|
|
138
|
+
normalContrast: "Normal",
|
|
139
|
+
highContrast: "Élevé",
|
|
140
|
+
auto: "Auto",
|
|
141
|
+
closeNavigation: "Fermer la navigation",
|
|
142
|
+
primary: "Navigation principale",
|
|
143
|
+
sections: "Sections",
|
|
144
|
+
chooseSection: "Choisir une section",
|
|
145
|
+
headerLinks: "Liens d’en-tête",
|
|
146
|
+
more: "Plus",
|
|
147
|
+
closeMore: "Fermer le menu",
|
|
148
|
+
moreLinks: "Autres liens",
|
|
149
|
+
versions: "Versions",
|
|
150
|
+
documentationVersion: "Version de la documentation",
|
|
151
|
+
documentationVersions: "Versions de la documentation",
|
|
152
|
+
version: "Version",
|
|
153
|
+
home: "Accueil",
|
|
154
|
+
generatedWith: "Créé avec",
|
|
155
|
+
viewSource: "Voir le code source",
|
|
156
|
+
copyCode: "Copier le code",
|
|
157
|
+
codeCopied: "Code copié",
|
|
158
|
+
codeCopyError: "Impossible de copier le code",
|
|
159
|
+
copyHeading: "Copier le lien vers « {heading} »",
|
|
160
|
+
linkCopied: "Lien copié",
|
|
161
|
+
linkCopyError: "Impossible de copier le lien",
|
|
162
|
+
notFound: "Page introuvable",
|
|
163
|
+
notFoundDescription: "La page demandée est introuvable.",
|
|
164
|
+
fallback: "langue de secours"
|
|
165
|
+
};
|
|
166
|
+
function messages(lang, options = {}) {
|
|
167
|
+
const language = lang.split("-")[0] ?? "en";
|
|
168
|
+
return {
|
|
169
|
+
...ENGLISH_MESSAGES,
|
|
170
|
+
...language === "fr" ? FRENCH_MESSAGES : {},
|
|
171
|
+
...options.translations?.[language],
|
|
172
|
+
...options.translations?.[lang]
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
function localeAlternates(path, routes, options) {
|
|
176
|
+
const available = new Set(routes.filter((route) => route.discoverable !== false).map((route) => route.route));
|
|
177
|
+
if (!options.locales || !available.has(path)) return [];
|
|
178
|
+
const alternates = Object.entries(options.locales).flatMap(([locale, config]) => {
|
|
179
|
+
const route = localizedRoute(path, locale, options);
|
|
180
|
+
return available.has(route) ? [{
|
|
181
|
+
lang: config.lang ?? locale,
|
|
182
|
+
route
|
|
183
|
+
}] : [];
|
|
184
|
+
});
|
|
185
|
+
const fallback = localizedRoute(path, options.defaultLocale ?? (options.locales.root ? "root" : Object.keys(options.locales)[0]), options);
|
|
186
|
+
if (available.has(fallback)) alternates.push({
|
|
187
|
+
lang: "x-default",
|
|
188
|
+
route: fallback
|
|
189
|
+
});
|
|
190
|
+
return alternates;
|
|
191
|
+
}
|
|
192
|
+
//#endregion
|
|
193
|
+
export { ENGLISH_MESSAGES, localeAlternates, localeHref, localePath, localeTarget, localizedNavigation, localizedRoute, messages, requestLanguage, routeLocale };
|
|
194
|
+
|
|
195
|
+
//# sourceMappingURL=localization.js.map
|