@tenphi/cookbook 0.18.2 → 0.19.1

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/README.md CHANGED
@@ -43,7 +43,7 @@ See [Theme and components](./docs/theme-and-components.md) for all named
43
43
  sub-elements and the custom component flow.
44
44
 
45
45
  Without configuration, a root `README.md` becomes `/` and
46
- `docs/**/*.{md,mdx}` supplies the remaining pages. Cookbook includes Starlight,
46
+ `docs/**/*.{md,mdx}` supplies the remaining pages. Cookbook includes its Astro renderer,
47
47
  generates only static output, and derives its URL base from Astro. Adding other
48
48
  Astro content collections does not require a Cookbook collection adapter.
49
49
 
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { resolveDocsTheme } from "@tenphi/starlight";
2
+ import { resolveDocsTheme } from "@tenphi/renderer";
3
3
  import { createDocsGraph, formatDiagnostics, materializePackage, normalizeDocsConfig, readDocsLock, reconcileDocsLock, resolveDocsProject, validateBuiltDocs, validateProjectAssets, writeDocsLock } from "@tenphi/docs";
4
4
  import { cp, mkdir } from "node:fs/promises";
5
5
  import { dirname, resolve } from "node:path";
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["import { cp, mkdir } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport {\n createDocsGraph,\n formatDiagnostics,\n materializePackage,\n normalizeDocsConfig,\n readDocsLock,\n reconcileDocsLock,\n resolveDocsProject,\n writeDocsLock,\n validateProjectAssets,\n validateBuiltDocs,\n type DocsDiagnostic,\n type DocsProject,\n} from \"@tenphi/docs\";\nimport { resolveDocsTheme } from \"@tenphi/starlight\";\n\nlet jsonOutput = process.argv.slice(2).includes(\"--json\");\n\ntry {\n const { positionals, values } = parseArgs({\n allowPositionals: true,\n options: {\n json: { type: \"boolean\", default: false },\n root: { type: \"string\" },\n config: { type: \"string\" },\n out: { type: \"string\" },\n url: { type: \"string\" },\n \"public-dir\": { type: \"string\" },\n \"dry-run\": { type: \"boolean\", default: false },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n jsonOutput = values.json;\n if (values.help || positionals.length === 0) {\n printHelp();\n } else {\n const command = positionals[0];\n if (![\"doctor\", \"update\", \"check-build\"].includes(command!)) {\n throw new Error(`Unknown command: ${command ?? \"\"}.`);\n }\n if (command !== \"update\" && (positionals.length > 1 || values[\"dry-run\"])) {\n throw new Error(\n `${command} does not accept package selectors or --dry-run.`,\n );\n }\n if (command !== \"check-build\" && (values.out || values.url))\n throw new Error(\"--out and --url are only supported by check-build.\");\n if (values[\"public-dir\"] && command !== \"doctor\")\n throw new Error(\"--public-dir is only supported by doctor.\");\n const project = await resolveDocsProject({\n root: resolve(values.root ?? process.cwd()),\n ...(values.config ? { configFile: values.config } : {}),\n });\n if (command === \"doctor\")\n await doctor(\n project,\n values.json,\n values[\"public-dir\"]\n ? resolve(values.root ?? process.cwd(), values[\"public-dir\"])\n : resolve(values.root ?? process.cwd(), \"public\"),\n );\n else if (command === \"check-build\") {\n const graph = await createDocsGraph(project);\n const report = await validateBuiltDocs({\n directory: resolve(values.root ?? process.cwd(), values.out ?? \"dist\"),\n graph,\n ...(values.url ? { deployedUrl: values.url } : {}),\n });\n report.diagnostics.unshift(...graph.diagnostics);\n report.ok = !report.diagnostics.some((d) => d.severity === \"error\");\n if (values.json) console.log(JSON.stringify(report, null, 2));\n else {\n if (report.diagnostics.length)\n console.log(formatDiagnostics(report.diagnostics));\n console.log(\n `${report.ok ? \"Passed\" : \"Failed\"} ${report.scope} checks: ${report.pages} pages, ${report.assets} assets${report.checkedUrls ? `, ${report.checkedUrls} deployed URLs` : \"\"}.`,\n );\n }\n if (!report.ok) process.exitCode = 1;\n } else\n await update(\n project,\n positionals.slice(1),\n values.json,\n values[\"dry-run\"],\n );\n }\n} catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const diagnostics: DocsDiagnostic[] =\n error && typeof error === \"object\" && \"diagnostics\" in error\n ? (error.diagnostics as DocsDiagnostic[])\n : [{ code: \"COOKBOOK_CLI_ERROR\", severity: \"error\", message }];\n if (jsonOutput) {\n console.log(\n JSON.stringify({ ok: false, pages: 0, assets: 0, diagnostics }, null, 2),\n );\n } else {\n console.error(formatDiagnostics(diagnostics));\n }\n process.exitCode = 1;\n}\n\nasync function doctor(\n project: DocsProject,\n json: boolean,\n publicDirectory?: string,\n): Promise<void> {\n const theme = resolveDocsTheme(project.config.theme);\n const graph = await createDocsGraph(project);\n const diagnostics = [\n ...graph.diagnostics,\n ...theme.diagnostics,\n ...(await validateProjectAssets(project, graph, publicDirectory)),\n ];\n const hasErrors = diagnostics.some(\n (diagnostic) => diagnostic.severity === \"error\",\n );\n if (json) {\n console.log(\n JSON.stringify(\n {\n ok: !hasErrors,\n scope: \"preflight\",\n buildVerified: false,\n pages: graph.entries.length,\n assets: graph.assets.length,\n diagnostics,\n },\n null,\n 2,\n ),\n );\n } else if (diagnostics.length > 0) {\n console.log(formatDiagnostics(diagnostics));\n } else {\n console.log(\n `Preflight passed: ${graph.entries.length} pages, ${graph.assets.length} content assets. MDX compilation, remote fonts, and deployment are not checked. Run astro build and cookbook check-build.`,\n );\n }\n if (hasErrors) process.exitCode = 1;\n}\n\nasync function update(\n project: DocsProject,\n packages: string[],\n json: boolean,\n dryRun: boolean,\n): Promise<void> {\n const existing = await readDocsLock(project.root);\n const next = await reconcileDocsLock(project.config, existing, { packages });\n const changes = next.sources.map((source) => ({\n requested: source.requested,\n from:\n existing?.sources.find(\n (current) => current.requested === source.requested,\n )?.resolved ?? null,\n to: source.resolved,\n }));\n const removed =\n existing?.sources\n .filter(\n (source) =>\n !next.sources.some(\n (current) => current.requested === source.requested,\n ),\n )\n .map((source) => source.requested) ?? [];\n if (!dryRun) {\n const build = normalizeDocsConfig(project.config).build;\n for (const source of next.sources) {\n if (!source.vendored) continue;\n const current = existing?.sources.find(\n (entry) => entry.requested === source.requested,\n );\n if (\n current?.vendored === source.vendored &&\n current.integrity === source.integrity\n )\n continue;\n const { vendored, ...remote } = source;\n const artifact = await materializePackage(remote, build, project.root);\n const destination = resolve(project.root, vendored);\n await mkdir(dirname(destination), { recursive: true });\n await cp(artifact, destination, { recursive: true });\n }\n await writeDocsLock(project.root, next);\n }\n if (json) {\n console.log(\n JSON.stringify(\n {\n ok: true,\n pages: 0,\n assets: 0,\n diagnostics: [],\n dryRun,\n changes,\n removed,\n lock: next,\n },\n null,\n 2,\n ),\n );\n } else {\n for (const change of changes)\n console.log(\n `${change.requested}: ${change.from ?? \"(new)\"} -> ${change.to}`,\n );\n for (const source of removed) console.log(`Removed ${source}`);\n console.log(\n dryRun\n ? \"Dry run: cookbook.lock.json is unchanged.\"\n : \"Updated cookbook.lock.json.\",\n );\n }\n}\n\nfunction printHelp(): never {\n console.log(\n `Usage: cookbook <command> [options]\\n\\nCommands:\\n doctor Check configuration, content graph, theme, and local files\\n check-build Inspect production output and optionally deployed URLs\\n update [packages] Reconcile configured package sources and their lock\\n\\nOptions:\\n --root <directory>\\n --config <path>\\n --public-dir <directory> Local public assets for doctor (default: public)\\n --out <directory> Built output (default: dist)\\n --url <base-url> Also check a deployed site\\n --dry-run Preview an update without writing files\\n --json\\n -h, --help`,\n );\n process.exit(0);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","names":[],"sources":["../src/cli.ts"],"sourcesContent":["import { cp, mkdir } from \"node:fs/promises\";\nimport { dirname, resolve } from \"node:path\";\nimport { parseArgs } from \"node:util\";\nimport {\n createDocsGraph,\n formatDiagnostics,\n materializePackage,\n normalizeDocsConfig,\n readDocsLock,\n reconcileDocsLock,\n resolveDocsProject,\n writeDocsLock,\n validateProjectAssets,\n validateBuiltDocs,\n type DocsDiagnostic,\n type DocsProject,\n} from \"@tenphi/docs\";\nimport { resolveDocsTheme } from \"@tenphi/renderer\";\n\nlet jsonOutput = process.argv.slice(2).includes(\"--json\");\n\ntry {\n const { positionals, values } = parseArgs({\n allowPositionals: true,\n options: {\n json: { type: \"boolean\", default: false },\n root: { type: \"string\" },\n config: { type: \"string\" },\n out: { type: \"string\" },\n url: { type: \"string\" },\n \"public-dir\": { type: \"string\" },\n \"dry-run\": { type: \"boolean\", default: false },\n help: { type: \"boolean\", short: \"h\", default: false },\n },\n });\n jsonOutput = values.json;\n if (values.help || positionals.length === 0) {\n printHelp();\n } else {\n const command = positionals[0];\n if (![\"doctor\", \"update\", \"check-build\"].includes(command!)) {\n throw new Error(`Unknown command: ${command ?? \"\"}.`);\n }\n if (command !== \"update\" && (positionals.length > 1 || values[\"dry-run\"])) {\n throw new Error(\n `${command} does not accept package selectors or --dry-run.`,\n );\n }\n if (command !== \"check-build\" && (values.out || values.url))\n throw new Error(\"--out and --url are only supported by check-build.\");\n if (values[\"public-dir\"] && command !== \"doctor\")\n throw new Error(\"--public-dir is only supported by doctor.\");\n const project = await resolveDocsProject({\n root: resolve(values.root ?? process.cwd()),\n ...(values.config ? { configFile: values.config } : {}),\n });\n if (command === \"doctor\")\n await doctor(\n project,\n values.json,\n values[\"public-dir\"]\n ? resolve(values.root ?? process.cwd(), values[\"public-dir\"])\n : resolve(values.root ?? process.cwd(), \"public\"),\n );\n else if (command === \"check-build\") {\n const graph = await createDocsGraph(project);\n const report = await validateBuiltDocs({\n directory: resolve(values.root ?? process.cwd(), values.out ?? \"dist\"),\n graph,\n ...(values.url ? { deployedUrl: values.url } : {}),\n });\n report.diagnostics.unshift(...graph.diagnostics);\n report.ok = !report.diagnostics.some((d) => d.severity === \"error\");\n if (values.json) console.log(JSON.stringify(report, null, 2));\n else {\n if (report.diagnostics.length)\n console.log(formatDiagnostics(report.diagnostics));\n console.log(\n `${report.ok ? \"Passed\" : \"Failed\"} ${report.scope} checks: ${report.pages} pages, ${report.assets} assets${report.checkedUrls ? `, ${report.checkedUrls} deployed URLs` : \"\"}.`,\n );\n }\n if (!report.ok) process.exitCode = 1;\n } else\n await update(\n project,\n positionals.slice(1),\n values.json,\n values[\"dry-run\"],\n );\n }\n} catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n const diagnostics: DocsDiagnostic[] =\n error && typeof error === \"object\" && \"diagnostics\" in error\n ? (error.diagnostics as DocsDiagnostic[])\n : [{ code: \"COOKBOOK_CLI_ERROR\", severity: \"error\", message }];\n if (jsonOutput) {\n console.log(\n JSON.stringify({ ok: false, pages: 0, assets: 0, diagnostics }, null, 2),\n );\n } else {\n console.error(formatDiagnostics(diagnostics));\n }\n process.exitCode = 1;\n}\n\nasync function doctor(\n project: DocsProject,\n json: boolean,\n publicDirectory?: string,\n): Promise<void> {\n const theme = resolveDocsTheme(project.config.theme);\n const graph = await createDocsGraph(project);\n const diagnostics = [\n ...graph.diagnostics,\n ...theme.diagnostics,\n ...(await validateProjectAssets(project, graph, publicDirectory)),\n ];\n const hasErrors = diagnostics.some(\n (diagnostic) => diagnostic.severity === \"error\",\n );\n if (json) {\n console.log(\n JSON.stringify(\n {\n ok: !hasErrors,\n scope: \"preflight\",\n buildVerified: false,\n pages: graph.entries.length,\n assets: graph.assets.length,\n diagnostics,\n },\n null,\n 2,\n ),\n );\n } else if (diagnostics.length > 0) {\n console.log(formatDiagnostics(diagnostics));\n } else {\n console.log(\n `Preflight passed: ${graph.entries.length} pages, ${graph.assets.length} content assets. MDX compilation, remote fonts, and deployment are not checked. Run astro build and cookbook check-build.`,\n );\n }\n if (hasErrors) process.exitCode = 1;\n}\n\nasync function update(\n project: DocsProject,\n packages: string[],\n json: boolean,\n dryRun: boolean,\n): Promise<void> {\n const existing = await readDocsLock(project.root);\n const next = await reconcileDocsLock(project.config, existing, { packages });\n const changes = next.sources.map((source) => ({\n requested: source.requested,\n from:\n existing?.sources.find(\n (current) => current.requested === source.requested,\n )?.resolved ?? null,\n to: source.resolved,\n }));\n const removed =\n existing?.sources\n .filter(\n (source) =>\n !next.sources.some(\n (current) => current.requested === source.requested,\n ),\n )\n .map((source) => source.requested) ?? [];\n if (!dryRun) {\n const build = normalizeDocsConfig(project.config).build;\n for (const source of next.sources) {\n if (!source.vendored) continue;\n const current = existing?.sources.find(\n (entry) => entry.requested === source.requested,\n );\n if (\n current?.vendored === source.vendored &&\n current.integrity === source.integrity\n )\n continue;\n const { vendored, ...remote } = source;\n const artifact = await materializePackage(remote, build, project.root);\n const destination = resolve(project.root, vendored);\n await mkdir(dirname(destination), { recursive: true });\n await cp(artifact, destination, { recursive: true });\n }\n await writeDocsLock(project.root, next);\n }\n if (json) {\n console.log(\n JSON.stringify(\n {\n ok: true,\n pages: 0,\n assets: 0,\n diagnostics: [],\n dryRun,\n changes,\n removed,\n lock: next,\n },\n null,\n 2,\n ),\n );\n } else {\n for (const change of changes)\n console.log(\n `${change.requested}: ${change.from ?? \"(new)\"} -> ${change.to}`,\n );\n for (const source of removed) console.log(`Removed ${source}`);\n console.log(\n dryRun\n ? \"Dry run: cookbook.lock.json is unchanged.\"\n : \"Updated cookbook.lock.json.\",\n );\n }\n}\n\nfunction printHelp(): never {\n console.log(\n `Usage: cookbook <command> [options]\\n\\nCommands:\\n doctor Check configuration, content graph, theme, and local files\\n check-build Inspect production output and optionally deployed URLs\\n update [packages] Reconcile configured package sources and their lock\\n\\nOptions:\\n --root <directory>\\n --config <path>\\n --public-dir <directory> Local public assets for doctor (default: public)\\n --out <directory> Built output (default: dist)\\n --url <base-url> Also check a deployed site\\n --dry-run Preview an update without writing files\\n --json\\n -h, --help`,\n );\n process.exit(0);\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
 
2
- import { Callout, Card, CodeGroup, Logo, Preview, Steps, Tab, Tabs } from "@tenphi/starlight/components";
3
- export type * from "@tenphi/starlight/components";
2
+ import { Callout, Card, CodeGroup, Logo, Preview, Steps, Tab, Tabs } from "@tenphi/renderer/components";
3
+ export type * from "@tenphi/renderer/components";
4
4
  export { Callout, Card, CodeGroup, Logo, Preview, Steps, Tab, Tabs };
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { Callout, Card, CodeGroup, Logo, Preview, Steps, Tab, Tabs } from "@tenphi/starlight/components";
2
+ import { Callout, Card, CodeGroup, Logo, Preview, Steps, Tab, Tabs } from "@tenphi/renderer/components";
3
3
  export { Callout, Card, CodeGroup, Logo, Preview, Steps, Tab, Tabs };
package/dist/content.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
 
2
- import { getCookbookCollection, getCookbookEntry } from "@tenphi/starlight/content";
2
+ import { getCookbookCollection, getCookbookEntry } from "@tenphi/renderer/content";
3
3
  export { getCookbookCollection, getCookbookEntry };
package/dist/content.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { getCookbookCollection, getCookbookEntry } from "@tenphi/starlight/content";
2
+ import { getCookbookCollection, getCookbookEntry } from "@tenphi/renderer/content";
3
3
  export { getCookbookCollection, getCookbookEntry };
@@ -1,3 +1,3 @@
1
1
 
2
- import eslint_plugin_default, { ResolvedConfig, StyleFunctionConfig, TastyValidationConfig, createValidationConfig, recommended, strict, validationConfig } from "@tenphi/starlight/eslint-plugin";
2
+ import eslint_plugin_default, { ResolvedConfig, StyleFunctionConfig, TastyValidationConfig, createValidationConfig, recommended, strict, validationConfig } from "@tenphi/renderer/eslint-plugin";
3
3
  export { type ResolvedConfig, type StyleFunctionConfig, type TastyValidationConfig, createValidationConfig, eslint_plugin_default as default, recommended, strict, validationConfig };
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import eslint_plugin_default, { createValidationConfig, recommended, strict, validationConfig } from "@tenphi/starlight/eslint-plugin";
2
+ import eslint_plugin_default, { createValidationConfig, recommended, strict, validationConfig } from "@tenphi/renderer/eslint-plugin";
3
3
  export { createValidationConfig, eslint_plugin_default as default, recommended, strict, validationConfig };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
 
2
- import starlight_default, { CookbookOptions, DEFAULT_THEME_TOKENS, DEFAULT_TYPOGRAPHY_PRESETS } from "@tenphi/starlight";
2
+ import renderer_default, { CookbookOptions, DEFAULT_THEME_TOKENS, DEFAULT_TYPOGRAPHY_PRESETS } from "@tenphi/renderer";
3
3
  import { BrandConfig, BrandDeclaration, BreadcrumbItem, BuildConfig, COOKBOOK_COMPONENT_NAMES, COOKBOOK_COMPONENT_SUB_ELEMENTS, COOKBOOK_PALETTE_NAMES, ComponentStyleConfig, ComponentStyles, ComponentStylesConfig, ComponentsConfig, ContentConfig, CookbookComponentName, CookbookComponentStyles, CookbookComponentSubElementName, DocsAsset, DocsConfig, DocsDiagnostic, DocsEntry, DocsFrontmatter, DocsGraph, DocsRoute, DocsSource, EditLinkConfig, FontLoadingConfig, HeadConfig, LocaleConfig, MarkdownConfig, NavigationConfig, NavigationItem, NavigationPlacement, NavigationTab, PageSeoConfig, SearchConfig, SiteConfig, SiteIconConfig, SiteLogoConfig, SiteSeoConfig, SiteVersion, SocialImage, TableOfContentsConfig, ThemeConfig, ThemeFont, ThemeFontFile, ThemeFonts, ThemePaletteColor, ThemePaletteConfig, ThemeTokenValue, ThemeTokens, TypographyPreset, TypographyPresets, defineDocsConfig, mergeDocsConfig } from "@tenphi/docs";
4
- export { type BrandConfig, type BrandDeclaration, type BreadcrumbItem, type BuildConfig, COOKBOOK_COMPONENT_NAMES, COOKBOOK_COMPONENT_SUB_ELEMENTS, COOKBOOK_PALETTE_NAMES, type ComponentStyleConfig, type ComponentStyles, type ComponentStylesConfig, type ComponentsConfig, type ContentConfig, type CookbookComponentName, type CookbookComponentStyles, type CookbookComponentSubElementName, type CookbookOptions, DEFAULT_THEME_TOKENS, DEFAULT_TYPOGRAPHY_PRESETS, type DocsAsset, type DocsConfig, type DocsDiagnostic, type DocsEntry, type DocsFrontmatter, type DocsGraph, type DocsRoute, type DocsSource, type EditLinkConfig, type FontLoadingConfig, type HeadConfig, type LocaleConfig, type MarkdownConfig, type NavigationConfig, type NavigationItem, type NavigationPlacement, type NavigationTab, type PageSeoConfig, type SearchConfig, type SiteConfig, type SiteIconConfig, type SiteLogoConfig, type SiteSeoConfig, type SiteVersion, type SocialImage, type TableOfContentsConfig, type ThemeConfig, type ThemeFont, type ThemeFontFile, type ThemeFonts, type ThemePaletteColor, type ThemePaletteConfig, type ThemeTokenValue, type ThemeTokens, type TypographyPreset, type TypographyPresets, starlight_default as default, defineDocsConfig, mergeDocsConfig };
4
+ export { type BrandConfig, type BrandDeclaration, type BreadcrumbItem, type BuildConfig, COOKBOOK_COMPONENT_NAMES, COOKBOOK_COMPONENT_SUB_ELEMENTS, COOKBOOK_PALETTE_NAMES, type ComponentStyleConfig, type ComponentStyles, type ComponentStylesConfig, type ComponentsConfig, type ContentConfig, type CookbookComponentName, type CookbookComponentStyles, type CookbookComponentSubElementName, type CookbookOptions, DEFAULT_THEME_TOKENS, DEFAULT_TYPOGRAPHY_PRESETS, type DocsAsset, type DocsConfig, type DocsDiagnostic, type DocsEntry, type DocsFrontmatter, type DocsGraph, type DocsRoute, type DocsSource, type EditLinkConfig, type FontLoadingConfig, type HeadConfig, type LocaleConfig, type MarkdownConfig, type NavigationConfig, type NavigationItem, type NavigationPlacement, type NavigationTab, type PageSeoConfig, type SearchConfig, type SiteConfig, type SiteIconConfig, type SiteLogoConfig, type SiteSeoConfig, type SiteVersion, type SocialImage, type TableOfContentsConfig, type ThemeConfig, type ThemeFont, type ThemeFontFile, type ThemeFonts, type ThemePaletteColor, type ThemePaletteConfig, type ThemeTokenValue, type ThemeTokens, type TypographyPreset, type TypographyPresets, renderer_default as default, defineDocsConfig, mergeDocsConfig };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import starlight_default, { DEFAULT_THEME_TOKENS, DEFAULT_TYPOGRAPHY_PRESETS } from "@tenphi/starlight";
2
+ import renderer_default, { DEFAULT_THEME_TOKENS, DEFAULT_TYPOGRAPHY_PRESETS } from "@tenphi/renderer";
3
3
  import { COOKBOOK_COMPONENT_NAMES, COOKBOOK_COMPONENT_SUB_ELEMENTS, COOKBOOK_PALETTE_NAMES, defineDocsConfig, mergeDocsConfig } from "@tenphi/docs";
4
- export { COOKBOOK_COMPONENT_NAMES, COOKBOOK_COMPONENT_SUB_ELEMENTS, COOKBOOK_PALETTE_NAMES, DEFAULT_THEME_TOKENS, DEFAULT_TYPOGRAPHY_PRESETS, starlight_default as default, defineDocsConfig, mergeDocsConfig };
4
+ export { COOKBOOK_COMPONENT_NAMES, COOKBOOK_COMPONENT_SUB_ELEMENTS, COOKBOOK_PALETTE_NAMES, DEFAULT_THEME_TOKENS, DEFAULT_TYPOGRAPHY_PRESETS, renderer_default as default, defineDocsConfig, mergeDocsConfig };
package/dist/styling.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
 
2
- import { Styles, defineComponent, mergeStyles, resolveComponentStyles, tasty, useGlobalStyles } from "@tenphi/starlight/styling";
2
+ import { Styles, defineComponent, mergeStyles, resolveComponentStyles, tasty, useGlobalStyles } from "@tenphi/renderer/styling";
3
3
  export { type Styles, defineComponent, mergeStyles, resolveComponentStyles, tasty, useGlobalStyles };
package/dist/styling.js CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { defineComponent, mergeStyles, resolveComponentStyles, tasty, useGlobalStyles } from "@tenphi/starlight/styling";
2
+ import { defineComponent, mergeStyles, resolveComponentStyles, tasty, useGlobalStyles } from "@tenphi/renderer/styling";
3
3
  export { defineComponent, mergeStyles, resolveComponentStyles, tasty, useGlobalStyles };
@@ -8,17 +8,21 @@ sidebar:
8
8
  Cookbook keeps content concerns separate from rendering so another renderer
9
9
  can consume the same validated graph in the future.
10
10
 
11
+ Cookbook's early documentation experience was inspired by
12
+ [Astro Starlight](https://starlight.astro.build/). Its current renderer is
13
+ maintained in this repository.
14
+
11
15
  ## Packages
12
16
 
13
- | Package | Responsibility |
14
- | ------------------------- | ----------------------------------------------------------------------------------------------------------- |
15
- | `@tenphi/create-cookbook` | Inspect an npm artifact and scaffold a reproducible documentation project |
16
- | `@tenphi/cookbook` | Provide the memorable Astro integration, public config exports, and CLI |
17
- | `@tenphi/docs` | Discover sources, resolve packages, build the content graph, transform Markdown, and report diagnostics |
18
- | `@tenphi/starlight` | Adapt the graph to Astro/Starlight and provide the Tasty/Glaze theme, components, search, and static assets |
17
+ | Package | Responsibility |
18
+ | ------------------------- | ------------------------------------------------------------------------------------------------------- |
19
+ | `@tenphi/create-cookbook` | Inspect an npm artifact and scaffold a reproducible documentation project |
20
+ | `@tenphi/cookbook` | Provide the memorable Astro integration, public config exports, and CLI |
21
+ | `@tenphi/docs` | Discover sources, resolve packages, build the content graph, transform Markdown, and report diagnostics |
22
+ | `@tenphi/renderer` | Render the graph with Astro and provide the Tasty/Glaze theme, components, search, and static assets |
19
23
 
20
24
  The `@tenphi/cookbook` default export represents the complete product. Consumers do
21
- not compose Starlight or renderer internals themselves.
25
+ not compose renderer internals themselves.
22
26
 
23
27
  ## Build pipeline
24
28
 
@@ -28,7 +32,7 @@ not compose Starlight or renderer internals themselves.
28
32
  4. Parse Markdown and collect headings, links, and assets.
29
33
  5. Rewrite internal references through the completed route graph.
30
34
  6. Reject unsafe paths and report strict diagnostics.
31
- 7. Render static pages through Astro and Starlight.
35
+ 7. Render static pages through Astro and Cookbook components.
32
36
  8. Copy content-hashed assets and build the local Pagefind index.
33
37
 
34
38
  Source documents are read-only throughout this process. The transformed body
@@ -44,7 +48,7 @@ Theme resolution has three deliberately separate layers:
44
48
  2. The Glaze values, design tokens, typography presets, states, and units are
45
49
  registered directly with Tasty.
46
50
  3. Cookbook components use `tasty()` and the Tasty selector bridge styles DOM
47
- owned by Astro, Starlight, Expressive Code, Pagefind, and rendered Markdown.
51
+ owned by Astro, Pagefind, and rendered Markdown.
48
52
 
49
53
  The palette owns color relationships. Components never choose raw light/dark
50
54
  colors, and shape tokens never contain palette logic. This keeps a palette
@@ -78,7 +82,7 @@ for (const route of graph.routes) {
78
82
  ```
79
83
 
80
84
  The graph exposes normalized entries, routes, assets, and structured
81
- diagnostics without importing Starlight.
85
+ diagnostics without importing the renderer.
82
86
 
83
87
  ## Reference app
84
88
 
@@ -98,6 +98,8 @@ tableOfContents: { mobile: true, minHeadingLevel: 2, maxHeadingLevel: 3 }
98
98
  The same frontmatter field can change heading levels or set `mobile: false` on
99
99
  one page. `tableOfContents: false` disables both versions. Selecting a mobile
100
100
  contents link closes the disclosure and moves keyboard focus to the heading.
101
+ The desktop contents list highlights the current section and scrolls its own
102
+ list when the active link moves out of view.
101
103
  Customize `theme.styles.MobileTableOfContents` and `TableOfContentsLayout`.
102
104
 
103
105
  ## Hero images
@@ -0,0 +1,129 @@
1
+ ---
2
+ title: Compare documentation tools
3
+ description: Choose between Cookbook, documentation site builders, hosted docs, and generated API or component references.
4
+ sidebar:
5
+ order: 2
6
+ ---
7
+
8
+ Two choices shape a documentation site: **how closely it should follow your
9
+ product's design system** and **where its content comes from**. Cookbook was
10
+ built for both. Its theme is configurable down to named component parts, and
11
+ its content can come from existing repository files or a published npm package.
12
+ Turning Markdown into pages is only one part of that workflow.
13
+
14
+ The comparisons below describe each tool's documented starting workflow, not
15
+ every integration its users could build. They are a selection of established
16
+ options, not a popularity ranking or an exhaustive list.
17
+
18
+ ## Why choose Cookbook for customization?
19
+
20
+ Cookbook treats appearance as a supported configuration surface rather than a
21
+ set of selectors to override after rendering:
22
+
23
+ - Set one `theme.brand` color or define semantic `theme.palette` roles. Glaze
24
+ resolves them for light, dark, normal, and high-contrast modes, with contrast
25
+ targets and diagnostics.
26
+ - Configure shared `theme.tokens`, font roles, typography `theme.presets`, and
27
+ responsive `theme.states` once. Components consume those roles consistently.
28
+ - Change a built-in component through a **partial**
29
+ `theme.styles.<ComponentName>` Tasty object. Cookbook merges it into the full
30
+ base style before extracting CSS. Its [named component parts](./theme-and-components.md#style-customization)
31
+ are published so a header title, search field, or sidebar item can be changed
32
+ without copying an entire component.
33
+ - Add a styled component with `defineComponent()` or replace markup and behavior
34
+ through an Astro component override when the supported anatomy is not enough.
35
+ Tasty and Glaze run during the build; the browser receives static CSS, not
36
+ their styling runtimes.
37
+
38
+ For example, this changes the brand, a shared radius, heading typography, and
39
+ one part of the header while keeping the other default component styles:
40
+
41
+ ```ts
42
+ import { defineDocsConfig } from "@tenphi/cookbook/config";
43
+
44
+ export default defineDocsConfig({
45
+ theme: {
46
+ brand: { from: "#315efb" },
47
+ tokens: { $radius: "10px" },
48
+ presets: { heading: { fontWeight: 650 } },
49
+ styles: { Header: { SiteTitle: { preset: "h4 / strong" } } },
50
+ },
51
+ });
52
+ ```
53
+
54
+ This style contract is specific to Cookbook's Tasty and Glaze system. Structural
55
+ changes still require an Astro override. Read the [customization rules](./customization-rules.md)
56
+ and [theme reference](./theme-and-components.md) for the supported names and
57
+ the full design-system API.
58
+
59
+ ## Start with the material you have
60
+
61
+ - **A repository `README.md` and `docs/` tree:** Start with
62
+ [Cookbook](./getting-started.md), [Starlight](https://starlight.astro.build/getting-started/),
63
+ [VitePress](https://vitepress.dev/guide/getting-started), or another site
64
+ builder. Choose the framework and editing workflow you prefer; Cookbook can
65
+ read the existing files in place.
66
+ - **Markdown inside a published npm package:**
67
+ [Cookbook's package source](./content-sources.md#npm-package-sources) reads
68
+ the published artifact, pins its version and integrity, and builds without
69
+ installing that package.
70
+ - **TypeScript exports and code comments:** [TypeDoc](https://typedoc.org/index.html)
71
+ generates reference pages from the code model and can use package entry
72
+ points.
73
+ - **UI components and their stories:** [Storybook Autodocs](https://storybook.js.org/docs/writing-docs)
74
+ documents components alongside rendered stories.
75
+ - **An OpenAPI specification:** Choose [Cookbook's static reference](./content-sources.md#openapi-references)
76
+ or a tool with an [interactive API playground](https://mintlify.com/docs/api-playground/overview)
77
+ if readers need to make requests from the docs.
78
+
79
+ ## Compare complete documentation sites
80
+
81
+ All of these tools support visual customization. Their default content and
82
+ styling contracts differ:
83
+
84
+ | Tool and usual source | Documented customization path |
85
+ | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
86
+ | **Cookbook** — Astro site reading repository paths, locked npm artifacts, or local OpenAPI. | Semantic Glaze palette, Tasty tokens and presets, partial named component styles, and Astro overrides; extracted static CSS. |
87
+ | [**Starlight**](https://starlight.astro.build/guides/pages/) — Astro docs collection with [plugins](https://starlight.astro.build/reference/plugins/). | [CSS variables, custom CSS or Tailwind](https://starlight.astro.build/guides/css-and-tailwind/), themes, and component overrides. |
88
+ | [**Docusaurus**](https://docusaurus.io/docs/docs-introduction) — React/MDX docs with [version snapshots](https://docusaurus.io/docs/versioning). | [Infima variables and custom CSS](https://docusaurus.io/docs/styling-layout), plus [swizzled React components](https://docusaurus.io/docs/swizzling). |
89
+ | [**VitePress**](https://vitepress.dev/guide/what-is-vitepress) — Markdown site with Vue components. | [Theme config, CSS variables, Vue layout slots, or a custom theme](https://vitepress.dev/guide/extending-default-theme). |
90
+ | [**Nextra**](https://nextra.site/docs) — Next.js/React site with Markdown and MDX. | [Next.js CSS](https://nextra.site/docs/guide/custom-css) or a [custom React theme](https://nextra.site/docs/custom-theme). |
91
+ | [**Material for MkDocs**](https://squidfunk.github.io/mkdocs-material/getting-started/) — Python/MkDocs site with Markdown. | [Palette settings and CSS variables](https://squidfunk.github.io/mkdocs-material/setup/changing-the-colors/), [extra CSS and template overrides](https://squidfunk.github.io/mkdocs-material/customization/). |
92
+ | [**Mintlify**](https://mintlify.com/docs/quickstart) — Managed MDX and OpenAPI site with Git-connected deployment and a web editor. | [Prebuilt themes](https://mintlify.com/docs/themes), configuration for colors and fonts, and visual editing. |
93
+
94
+ The table compares documented approaches, not a ceiling on what each tool can
95
+ do. Choose the styling model you want to maintain. Cookbook's model is useful
96
+ when brand, typography, semantic colors, and component anatomy must move
97
+ together across the whole site. Starlight, Docusaurus, VitePress, Nextra, and
98
+ Material for MkDocs provide their own routes to theme or component changes;
99
+ Mintlify provides a managed editing and hosting workflow. Cookbook requires an
100
+ Astro build and a host for its static output. Starlight plugins target its own
101
+ APIs and do not run in Cookbook; see [Cookbook extensions](./plugins.md).
102
+
103
+ ## When the package _is_ the source
104
+
105
+ “Package to website” can mean two different jobs:
106
+
107
+ 1. **Publish the prose included in an npm release.** Cookbook reads the actual
108
+ tarball's selected `README.md` and Markdown files. Package MDX requires an
109
+ explicit trust opt-in before its code can run. `cookbook update`
110
+ records the requested specifier, resolved version, and integrity in
111
+ `cookbook.lock.json`; a production build uses that lock. This is useful when
112
+ the docs site should describe exactly what package consumers received. See
113
+ [package sources](./content-sources.md#npm-package-sources) and the
114
+ [package quick start](./getting-started.md#document-a-published-npm-package).
115
+ 2. **Generate reference pages from source code.** [TypeDoc](https://typedoc.org/index.html)
116
+ reads TypeScript exports and comments, including entry points discovered
117
+ from `package.json`, and emits an HTML or JSON reference. It is the direct
118
+ choice when exported types and signatures are the documentation.
119
+
120
+ For a component library, [Storybook](https://storybook.js.org/docs/writing-docs)
121
+ is a separate option when the main experience should be runnable component
122
+ examples. TypeDoc or Storybook can complement a guide site; link to their output
123
+ from Cookbook navigation when each serves a different reader need.
124
+
125
+ Cookbook does not extract API signatures from TypeScript or provide an
126
+ interactive OpenAPI client. Its strengths are design system customization,
127
+ source-aware prose, validated links and assets, and a reproducible npm artifact
128
+ input. See [content sources](./content-sources.md) and
129
+ [theme and components](./theme-and-components.md) for the supported scope.
@@ -185,13 +185,10 @@ path, not a generated content-collection path. Set `editUrl: false` or
185
185
  sources show a timestamp only when their materialized file has Git history or
186
186
  the page supplies one explicitly.
187
187
 
188
- These settings intentionally mirror Starlight's
189
- [`editLink`](https://starlight.astro.build/reference/configuration/#editlink)
190
- and
191
- [`lastUpdated`](https://starlight.astro.build/reference/configuration/#lastupdated)
192
- configuration while preserving Cookbook's original source paths.
188
+ These settings use Cookbook's original source paths when constructing links and
189
+ timestamps.
193
190
 
194
- Cookbook also accepts Starlight-compatible page presentation frontmatter:
191
+ Cookbook also accepts page presentation frontmatter:
195
192
 
196
193
  ```yaml
197
194
  tableOfContents:
@@ -227,7 +224,7 @@ discoverable on the next build. A draft URL is public; this is not access contro
227
224
 
228
225
  ## Languages
229
226
 
230
- Expose Starlight's multilingual routing and language picker directly:
227
+ Configure Cookbook's multilingual routing and language picker:
231
228
 
232
229
  ```ts
233
230
  locales: {
@@ -483,19 +480,9 @@ Configure renderer-level Markdown options such as custom remark or rehype
483
480
  plugins and Shiki languages through Astro's top-level `markdown` configuration.
484
481
  Cookbook preserves those settings while adding its own build-time transforms.
485
482
 
486
- Starlight content and behavior plugins can be supplied to the Astro integration:
487
-
488
- ```ts
489
- import myStarlightPlugin from "./plugins/my-starlight-plugin.js";
490
-
491
- export default defineConfig({
492
- integrations: [cookbook({ plugins: [myStarlightPlugin()] })],
493
- });
494
- ```
495
-
496
- Cookbook preserves custom metadata for route middleware and supports custom schemas.
497
- See the [plugin compatibility guide](./plugins.md) for the tested ecosystem matrix,
498
- content query API, Tasty adapters, and collection/style limitations.
483
+ Cookbook preserves custom metadata and supports custom schemas. See
484
+ [extending Cookbook](./plugins.md) for Astro Markdown plugins, native GitHub
485
+ alerts, the content query API, and styling limits.
499
486
 
500
487
  Cookbook renders fenced `mermaid` blocks as responsive, theme-aware SVG during
501
488
  the static build. Flowcharts, state, sequence, class, and entity-relationship
@@ -624,8 +611,7 @@ a 120ms slide transition; customize these through `theme.styles.Sidebar`.
624
611
  ### Translate Cookbook controls
625
612
 
626
613
  Cookbook includes English and French interface messages. Other languages use
627
- English for missing Cookbook messages while Starlight supplies its own built-in
628
- translations. Override messages by language code; regional codes fall back to the
614
+ English for missing messages. Override messages by language code; regional codes fall back to the
629
615
  base language and then English:
630
616
 
631
617
  ```ts
@@ -170,7 +170,7 @@ Package Markdown is untrusted by default. Raw HTML is sanitized to safe
170
170
  elements, HTML-capable frontmatter is stripped, custom `head` entries are discarded,
171
171
  unsafe URL protocols are rejected, and MDX cannot execute. Set `trust: "mdx"`
172
172
  only after reviewing the exact locked artifact; doing so allows its build-time
173
- code to run. Trusted MDX is compiled by Starlight, including relative component
173
+ code to run. Trusted MDX is compiled by Astro, including relative component
174
174
  imports from the source file's directory. Package-provided indexes, include
175
175
  patterns, exclude patterns, and every discovered file are confined to the
176
176
  extracted artifact root.
@@ -45,7 +45,7 @@ import { defineDocsConfig } from "@tenphi/cookbook/config";
45
45
  export default defineDocsConfig({
46
46
  theme: {
47
47
  styles: {
48
- StarlightHeader: { SiteTitle: { preset: "h4 / strong" } },
48
+ Header: { SiteTitle: { preset: "h4 / strong" } },
49
49
  },
50
50
  },
51
51
  });
@@ -68,7 +68,7 @@ integration or calling upstream `configure()` is unnecessary. Shared settings
68
68
  belong in `docs.config.ts`.
69
69
 
70
70
  * Express styles with Tasty. Do not add CSS files, CSS modules, Astro `<style>`
71
- blocks, inline `style` attributes, or imported Starlight styles to customize
71
+ blocks, inline `style` attributes, or imported component styles to customize
72
72
  the documentation interface. The isolated content of `Preview` is a separate
73
73
  demonstration surface.
74
74
  * Model descendants and pseudo-elements as named sub-elements inside the
@@ -67,7 +67,7 @@ import cookbook from "@tenphi/cookbook";
67
67
  export default defineConfig({ integrations: [cookbook()] });
68
68
  ```
69
69
 
70
- Cookbook includes Starlight and discovers `docs.config.ts` automatically.
70
+ Cookbook includes its Astro renderer and discovers `docs.config.ts` automatically.
71
71
  With no documentation configuration, it uses README/docs conventions.
72
72
 
73
73
  ## Configure the site
package/docs/index.md CHANGED
@@ -1,18 +1,18 @@
1
1
  ---
2
2
  title: Cookbook
3
- description: Build a polished static documentation site from the Markdown your project already owns.
3
+ description: Build a customizable static documentation site from the Markdown your project already owns.
4
4
  template: splash
5
5
  hero:
6
6
  title: Documentation that stays with the code.
7
- tagline: Turn repository Markdown or a locked npm package into a polished, searchable Astro site—without creating a second source of truth.
7
+ tagline: Turn repository Markdown or a locked npm package into an Astro docs site that fits your design system—without creating a second source of truth.
8
8
  image:
9
9
  html: '<svg xmlns="http://www.w3.org/2000/svg" width="240" height="240" viewBox="0 0 64 64" aria-hidden="true"><rect width="64" height="64" rx="14" fill="currentColor"/><path fill="#fff" d="M14.8 16c6.7.2 12.3 2 16.7 5.4v28.4c-4.4-3.1-10-4.7-16.6-4.9a3 3 0 0 1-2.9-3V19a3 3 0 0 1 2.8-3Z"/><path fill="#fff" d="M49.2 16c-6.7.2-12.3 2-16.7 5.4v28.4c4.4-3.1 10-4.7 16.6-4.9a3 3 0 0 0 2.9-3V19a3 3 0 0 0-2.8-3Z"/></svg>'
10
10
  actions:
11
11
  - text: Get started
12
12
  link: /getting-started/
13
13
  variant: primary
14
- - text: See how it compares
15
- link: /starlight-comparison/
14
+ - text: Compare tools
15
+ link: /comparison/
16
16
  variant: secondary
17
17
  sidebar:
18
18
  order: 1
@@ -20,7 +20,7 @@ sidebar:
20
20
  ## Keep documentation close to its source
21
21
 
22
22
  Cookbook combines [Astro](https://astro.build) and
23
- [Starlight](https://starlight.astro.build) with repository-aware content,
23
+ an Astro renderer with repository-aware content,
24
24
  strict validation, local Pagefind search, and a theme powered by
25
25
  [Tasty](./upstream/tasty/README.md) and [Glaze](./upstream/glaze/README.md).
26
26
 
@@ -57,11 +57,12 @@ states, and named component styles.
57
57
  | I want to… | Start here | Then read |
58
58
  | ------------------------------------ | --------------------------------------- | --------------------------------------------------------------------- |
59
59
  | Start a site | [Getting started](./getting-started.md) | [Validate and deploy](./deployment.md) |
60
+ | Choose a documentation tool | [Compare tools](./comparison.md) | [Getting started](./getting-started.md) |
60
61
  | Have an agent set it up | [AI agent workflow](./ai-agents.md) | [Customization rules](./customization-rules.md) |
61
62
  | Bring existing Markdown or an API | [Content sources](./content-sources.md) | [Working examples](./examples.md) |
62
63
  | Write pages and interactive examples | [Authoring](./authoring.mdx) | [Mobile contents and hero images](./authoring.mdx#on-page-navigation) |
63
64
  | Change brand, fonts, or logo | [Configuration recipes](./recipes.md) | [Theme reference](./theme-and-components.md) |
64
- | Add a Starlight plugin | [Plugin compatibility](./plugins.md) | [Architecture](./architecture.md) |
65
+ | Add a Markdown extension | [Extend Cookbook](./plugins.md) | [Architecture](./architecture.md) |
65
66
  | Publish for people and agents | [Deployment](./deployment.md) | [Publishing metadata](./publishing.md) |
66
67
  | Update or fix an existing site | [Upgrade Cookbook](./migration.md) | [Troubleshooting](./troubleshooting.md) |
67
68
 
package/docs/migration.md CHANGED
@@ -38,9 +38,40 @@ upgrade the site's Cookbook runtime or package-manager dependencies. Commit the
38
38
  documentation lock separately when intentionally updating imported content.
39
39
  Local Markdown needs no lock update.
40
40
 
41
+ ## 0.18.x to 0.19
42
+
43
+ Cookbook now renders documentation with its own Astro components. The public
44
+ `@tenphi/cookbook` integration remains the normal entry point. Projects that
45
+ import the renderer package directly should replace `@tenphi/starlight` with
46
+ `@tenphi/renderer`.
47
+
48
+ The page and theme contracts remain familiar, but component overrides now read
49
+ `Astro.locals.cookbookRoute`. Replace uses of `Astro.locals.starlightRoute` in
50
+ your own overrides. The named style surfaces `StarlightHeader` and
51
+ `StarlightAside` become `Header` and `MarkdownAlert`; the unused Starlight card,
52
+ link-card, badge, and steps bridges are removed. Cookbook's `Card`, `Callout`,
53
+ and `Steps` components remain available.
54
+
55
+ Renderer class names now use Cookbook-owned names. Update any custom CSS or
56
+ scripts that target generated markup, and prefer the named `theme.styles`
57
+ surfaces in the [theme reference](./theme-and-components.md).
58
+
59
+ The `plugins` integration option no longer forwards Starlight hooks. Move
60
+ content transforms to Astro's `markdown` configuration and use
61
+ `frontmatterSchema` for custom page metadata. GitHub alert blockquotes render
62
+ directly in Markdown and MDX, so `starlight-github-alerts` is no longer needed.
63
+ Use `cookbook doctor` and `cookbook check-build` instead of plugins that inspect
64
+ Starlight's content collection or physical docs files. See
65
+ [extending Cookbook](./plugins.md) for examples.
66
+
67
+ Build and preview each site after updating its package manifest. Check custom
68
+ component overrides, locale navigation, search, and Tasty style names before
69
+ deploying. Cookbook-saved appearance choices remain. Older Starlight-only
70
+ choices are ignored; visitors who relied on one can select their scheme again.
71
+
41
72
  ## 0.17.x to 0.18
42
73
 
43
- These changes are included in the next minor release:
74
+ These changes were introduced in 0.18:
44
75
 
45
76
  - **Google fonts:** family-name shorthand loads preset weights and italics and
46
77
  self-hosts the files. The initial build requires network access. Preserve the
@@ -63,7 +94,7 @@ These changes are included in the next minor release:
63
94
  - **Plugins:** custom metadata is available to route middleware and through
64
95
  Cookbook's content API. Plugins that need Astro's synthetic content files or
65
96
  inject their own CSS require adaptation. See the tested
66
- [plugin matrix](./plugins.md#verified-compatibility).
97
+ [extension guide](./plugins.md).
67
98
  - **Styles:** rendered inline styles are rejected. Move custom styling to Tasty
68
99
  and registered theme style trees. Keep these components server-rendered;
69
100
  browser scripts and `client:*` islands cannot import Cookbook styling, Tasty,
package/docs/plugins.md CHANGED
@@ -1,120 +1,99 @@
1
1
  ---
2
- title: Starlight plugins
2
+ title: Extend Cookbook
3
+ description: Add Markdown transforms, validate custom metadata, and query the content graph.
4
+ sidebar:
5
+ order: 7
3
6
  ---
4
7
 
5
- Cookbook accepts Starlight content and behavior plugins in `astro.config.mjs`:
8
+ Cookbook renders with Astro and accepts Astro Markdown integrations. Configure
9
+ remark and rehype plugins in `astro.config.ts`; Cookbook adds its own transforms
10
+ to the same processor. Extensions that emit CSS must be adapted to Tasty because
11
+ the finished site ships only Tasty-generated styles.
6
12
 
7
- ```js cookbook-verify=github-alerts
8
- import cookbook from "@tenphi/cookbook";
9
- import githubAlerts from "starlight-github-alerts";
13
+ ```ts
14
+ import { defineConfig } from "astro/config";
10
15
  import { unified } from "@astrojs/markdown-remark";
16
+ import cookbook from "@tenphi/cookbook";
17
+ import myRemarkPlugin from "./plugins/my-remark-plugin.js";
11
18
 
12
- export default {
13
- markdown: { processor: unified() },
14
- integrations: [cookbook({ plugins: [githubAlerts()] })],
15
- };
19
+ export default defineConfig({
20
+ markdown: { processor: unified({ remarkPlugins: [myRemarkPlugin] }) },
21
+ integrations: [cookbook()],
22
+ });
16
23
  ```
17
24
 
18
- Install `starlight-github-alerts` and `@astrojs/markdown-remark` in your project. Cookbook supplies the Starlight runtime; respect
19
- plugins' peer dependency ranges when upgrading. See [configuration](./configuration.md)
20
- for Astro Markdown hooks and [customization](./theme-and-components.md) for styling.
25
+ ## GitHub alerts
21
26
 
22
- ## Verified compatibility
27
+ Cookbook renders GitHub alert blockquotes in Markdown and MDX without an extra
28
+ plugin. `NOTE`, `TIP`, `IMPORTANT`, `WARNING`, and `CAUTION` map to the semantic
29
+ note, tip, caution, and danger surfaces. For example:
23
30
 
24
- The consumer check `pnpm check:plugins` tests these versions with the repository's
25
- pinned Astro and Starlight versions. Compatibility with other versions is not implied.
31
+ The default Astro integration is sufficient for alert rendering:
26
32
 
27
- | Integration | Tested version | Contract |
28
- | ------------------------------------------------------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
29
- | `starlight-github-alerts` | 0.4.0 | With `unified()`, Markdown and MDX alert syntax uses Cookbook's Tasty `StarlightAside` adapter. |
30
- | `starlight-links-validator` | 0.26.0 | Incompatible with mounted sources: error reporting assumes physical `src/content/docs` files. Cookbook rejects it with a diagnostic. |
31
- | Route middleware and `i18n:setup` | Starlight 0.42.4 | Custom metadata, body, file path, and translations survive in real consumer builds with locales and a base path. |
32
- | Plugins requiring `astro:content`'s `docs` collection | — | Cookbook's renderer uses its own graph. Adapt to the content API below; no native collection is populated automatically. |
33
- | Plugins supplying CSS, styled Astro components, or Expressive Code | — | Require an adapter built with Tasty. The build rejects incompatible output. |
34
-
35
- GitHub Alerts 0.4.0 assumes an older Sätteri plugin structure and silently skips
36
- alerts with Starlight 0.42.4's default processor. Cookbook rejects that combination
37
- with a configuration hint. Use `unified()` as above, or Starlight's native
38
- `:::note` / `:::tip` directives with the default processor.
33
+ ```js cookbook-verify=github-alerts
34
+ import cookbook from "@tenphi/cookbook";
39
35
 
40
- GitHub alerts inherit the semantic blue, green, yellow, and red surfaces. Customize
41
- `theme.styles.StarlightAside` with `Note`, `Tip`, `Caution`, `Danger`, `Title`, `Icon`,
42
- and `FirstContent`. Styles merge into the full owned tree; the plugin's stylesheet
43
- is unnecessary. All supported appearance modes use the Glaze palette.
36
+ export default { integrations: [cookbook()] };
37
+ ```
44
38
 
45
- Cookbook validates graph links itself. `starlight-links-validator` 0.26.0 loads,
46
- but fails while reporting broken links because it tries to read synthesized
47
- `src/content/docs` paths. Its middleware also cannot add previously absent links
48
- to its validation store. Use Cookbook's doctor and built-output checks for mounted
49
- sources. Plugins that depend on native collection IDs or mutate routing after
50
- graph creation need a Cookbook-specific adapter.
39
+ Write the alert in a Markdown or MDX page:
51
40
 
52
- ## Custom metadata and schemas
41
+ ```md
42
+ > [!TIP]
43
+ > Keep source documentation next to the code it describes.
44
+ ```
53
45
 
54
- Unknown source frontmatter is preserved as `entry.metadata` by default, and is
55
- available to route middleware as `locals.starlightRoute.entry.data`. Cookbook's
56
- validated built-in fields take precedence. Set `content.frontmatter: "reject"`
57
- only if your site does not use custom metadata.
46
+ Customize the result through `theme.styles.MarkdownAlert`. Its named
47
+ sub-elements are `Note`, `Tip`, `Caution`, `Danger`, `Title`, and
48
+ `FirstContent`.
58
49
 
59
- Optionally validate custom fields or supply defaults with a Zod-compatible schema:
50
+ ## Custom frontmatter
60
51
 
61
- ```js
62
- import cookbook from "@tenphi/cookbook";
63
- import { z } from "astro/zod";
52
+ Unknown frontmatter fields can be preserved as JSON metadata. Set
53
+ `content.frontmatter: "preserve"`, then validate or add custom fields with
54
+ `frontmatterSchema`:
64
55
 
65
- export default {
56
+ ```ts
57
+ export default defineConfig({
66
58
  integrations: [
67
59
  cookbook({
68
- frontmatterSchema: z.object({
69
- owner: z.string().default("docs-team"),
70
- }),
60
+ frontmatterSchema: {
61
+ parse(metadata) {
62
+ return { ...metadata, owner: metadata.owner ?? "maintainers" };
63
+ },
64
+ },
71
65
  }),
72
66
  ],
73
- };
67
+ });
74
68
  ```
75
69
 
76
- The schema receives **custom metadata only** and may use `parse` or `parseAsync`.
77
- Returned fields merge with preserved metadata. Values must be JSON-compatible;
78
- errors identify the source file. Reserved fields such as `title`, `slug`, `draft`,
79
- and `aliases` belong in source frontmatter and cannot be set by this schema.
80
- A schema cannot change routing or discovery after the graph is built.
70
+ The schema receives only custom metadata. It cannot change route, title, draft,
71
+ or other reserved page fields. Returned values must be JSON-safe because the
72
+ renderer passes them through a build-time virtual module.
81
73
 
82
- Route middleware also receives the transformed Markdown source in `entry.body`
83
- and the actual source location in `entry.filePath`. Presentation changes made by
84
- middleware do not update the graph, sitemap, or agent text. Put shared publishing
85
- metadata in source configuration so every output agrees.
74
+ ## Read the content graph
86
75
 
87
- ## Query Cookbook content
76
+ Server-rendered Astro components can query the validated graph:
88
77
 
89
- Use this build-time API in Astro components and route middleware:
90
-
91
- ```js
78
+ ```ts
92
79
  import {
93
80
  getCookbookCollection,
94
81
  getCookbookEntry,
95
82
  } from "@tenphi/cookbook/content";
96
83
 
97
- const pages = getCookbookCollection();
98
- const allPages = getCookbookCollection({ includeDrafts: true });
99
- const page = getCookbookEntry("/guide");
84
+ const visiblePages = getCookbookCollection();
85
+ const guide = getCookbookEntry("/guide");
100
86
  ```
101
87
 
102
- The renderer package exposes the same functions at `@tenphi/starlight/content`.
103
- Routes include locale/version prefixes but exclude Astro's deployment `base`.
104
- Collection queries omit drafts by default; exact lookups can retrieve a draft.
105
- Results are independent snapshots, including `metadata`, `frontmatter`, `body`,
106
- `transformedBody`, source information, headings, and links. Mutating a result does
107
- not change generated pages. Do not import this API into client-side code: it is
108
- backed by the site's build-time content graph.
109
-
110
- ## Diagnose incompatible plugins
111
-
112
- - **Plugin adds `customCss`:** disable its stylesheet option and provide a Tasty
113
- adapter, or choose a content-only plugin. The configuration error names the plugin.
114
- - **Inline styles or external stylesheet in built output:** replace that visual
115
- component with owned markup styled through `tasty()` and registered
116
- `theme.styles` anatomy. See [customization rules](./customization-rules.md).
117
- - **Empty `getCollection("docs")`:** use the Cookbook content API above. Cookbook
118
- does not create a second, potentially conflicting Starlight content collection.
119
- - **Missing custom field:** keep `content.frontmatter` at its default `"preserve"`,
120
- validate its shape, and read it after the Cookbook route bridge has run.
88
+ Queries return snapshots. Drafts are omitted from the collection by default;
89
+ `getCookbookEntry()` can retrieve one by its exact route. The same API is
90
+ available at `@tenphi/renderer/content` for renderer-only projects.
91
+
92
+ Component overrides receive page data from `Astro.locals.cookbookRoute`,
93
+ including the current entry, locale, navigation, table of contents, and head
94
+ tags. See [theme and components](./theme-and-components.md) for Tasty styling
95
+ and [configuration](./configuration.md) for structural overrides.
96
+
97
+ Use Astro's Markdown plugin APIs for content transforms, and Cookbook's graph
98
+ and built-output checks for link validation. Extensions tied to another
99
+ renderer need an adapter built against Cookbook's APIs.
@@ -130,8 +130,8 @@ Components consume semantic colors consistently: `surface`, `header`, `surface-2
130
130
  Tasty components can use these as `#surface`, `#text`, `#border`, and so on; the Astro shell consumes the
131
131
  same resolved values. Glaze also generates hover and pressed states, subtle
132
132
  accent fills, overlays, shadows, and the orange, green, blue, purple, and red
133
- roles used by Starlight content components. No browser color mixes or
134
- Starlight fallback palette values participate in the rendered theme. Surface
133
+ roles used by Cookbook content components. No browser color mixes or
134
+ upstream fallback palette values participate in the rendered theme. Surface
135
135
  elevation uses Glaze's contrast-uniform tone axis: `surface-2` advances two tone
136
136
  steps and `surface-3` advances four from the base surface, with proportionally
137
137
  wider steps in high-contrast mode. Their saturation also steps down to 75% and
@@ -145,7 +145,7 @@ change border tone, not that restrained saturation relationship.
145
145
  The Appearance button in the desktop and mobile header opens one panel with
146
146
  Color scheme and Contrast sections. Color scheme offers Light, Dark, and Auto;
147
147
  Contrast offers Normal, High, and Auto. Each preference is independent, and
148
- existing saved choices are preserved. The panel supports keyboard navigation,
148
+ selections are saved in the browser. The panel supports keyboard navigation,
149
149
  Escape, and outside-click dismissal. The popover fades and scales vertically
150
150
  from 96% to 100% over 120ms using native entry and exit transitions. Reduced
151
151
  motion disables the transition. Customize these states with
@@ -361,10 +361,9 @@ are useful when building a theme editor or presenting a reset action.
361
361
  ## Style customization
362
362
 
363
363
  Cookbook-owned interface elements are direct `tasty()` components. Supported
364
- Starlight-rendered surfaces use the same Tasty style trees through the global
365
- bridge. Customize either kind by name under `theme.styles`; the configuration
366
- is resolved before CSS generation, so this is not a selector-based CSS
367
- override.
364
+ Cookbook components and generated Markdown surfaces use Tasty style trees.
365
+ Customize them by name under `theme.styles`; the configuration is resolved
366
+ before CSS generation, so this is not a selector-based CSS override.
368
367
 
369
368
  > **Direct styles, without a specificity battle.** Cookbook merges your partial
370
369
  > style object with the component's base styles before Tasty extracts CSS. The
@@ -377,13 +376,13 @@ below to find its exact anatomy:
377
376
 
378
377
  | Page area | Style names to inspect |
379
378
  | ----------------------------- | ------------------------------------------------------------------------------------ |
380
- | Header, title, and navigation | `HeaderFrame`, `StarlightHeader`, `SiteLogo`, `HeaderLinks`, `TopNavigation` |
379
+ | Header, title, and navigation | `HeaderFrame`, `Header`, `SiteLogo`, `HeaderLinks`, `TopNavigation` |
381
380
  | Sidebar and mobile menu | `Sidebar`, `MobileMenuToggle`, `MobileNavigationTabs`, `MobileMenuFooter` |
382
381
  | Article text and headings | `Markdown`, `MarkdownHeading`, `Heading`, `MainContent` |
383
382
  | Code and diagrams | `MarkdownCodeBlock`, `MarkdownInlineCode`, `SyntaxHighlight`, `CodeGroup`, `Mermaid` |
384
383
  | Search | `SearchButton`, `Search`, `SearchResults` |
385
384
  | Table of contents | `TableOfContents`, `MobileTableOfContents`, `TableOfContentsLayout` |
386
- | Cards, notes, and tabs | `Card`, `StarlightCard`, `StarlightAside`, `Tabs` |
385
+ | Cards, notes, and tabs | `Card`, `Callout`, `MarkdownAlert`, `Tabs` |
387
386
  | Footer and page controls | `Footer`, `Pagination`, `PageActions`, `ThemeSelect` |
388
387
 
389
388
  For example, this changes a typography role and one named element without
@@ -464,7 +463,7 @@ sub-elements:
464
463
  | `MobileTableOfContents` | `Summary`, `List`, `NestedList`, `Item`, `Link`, `HoverLink`, `Focus` |
465
464
  | `PageActions` | `Control`, `Hover`, `Focus`, `Pending`, `Status` |
466
465
  | `Footer` | `Meta`, `LoneMetaItem`, `MetaLink`, `HoverMetaLink`, `Credit`, `CreditLink`, `HoverCreditLink` |
467
- | `Hero` | `Visual`, `Stack`, `Copy`, `Title`, `Tagline`, `Actions`, `Action`, `HoverAction`, `PrimaryAction`, `SecondaryAction`, `MinimalAction`, `ActionIcon` |
466
+ | `Hero` | `Visual`, `DarkVisual`, `LightVisual`, `Stack`, `Copy`, `Title`, `Tagline`, `Actions`, `Action`, `HoverAction`, `PrimaryAction`, `SecondaryAction`, `MinimalAction`, `ActionIcon` |
468
467
  | `LanguageSelect` | `Label`, `HoverLabel`, `LabelIcon`, `Select`, `Caret`, `Option` |
469
468
  | `Logo` | `Svg`, `Mark` |
470
469
  | `SiteLogo` | `Image`, `Light`, `Dark` |
@@ -482,7 +481,7 @@ sub-elements:
482
481
  | `Preview` | `Caption`, `Stage`, `Frame`, `Code`, `Summary`, `Pre` |
483
482
  | `Sidebar` | `Backdrop`, `OpenBackdrop`, `MobileHeading`, `HomeLink`, `HomeLogo`, `HomeLabel`, `Close`, `HoverClose`, `CloseIcon`, `CurrentLink`, `OpenPane`, `EnteredPane`, `Content`, `Tree`, `List`, `Item`, `TopLevelSpacing`, `GroupSpacing`, `NestedItem`, `SectionHeading`, `Control`, `Summary`, `GroupLabel`, `GroupLabelText`, `Link`, `LinkLabel`, `InteractiveControl`, `SummaryMarker`, `Caret`, `ExpandedCaret`, `LinkedSummary`, `GroupLink`, `LinkedSectionHeading`, `SectionLink`, `Badge`, `TopLevelLink` |
484
483
  | `SocialIcons` | `Link`, `HoverLink`, `Icon` |
485
- | `StarlightHeader` | `Primary`, `TitleAndSearch`, `Title`, `LogoLink`, `Logo`, `SiteTitle`, `Search`, `SearchElement`, `Tools`, `ToolItem`, `Social`, `MobileTheme` |
484
+ | `Header` | `Primary`, `TitleAndSearch`, `Title`, `LogoLink`, `Logo`, `SiteTitle`, `Search`, `SearchElement`, `Tools`, `ToolItem`, `Social`, `MobileTheme` |
486
485
  | `TableOfContentsLayout` | `WithMobile`, `Content` |
487
486
  | `SearchButton` | `PendingShortcut`, `Label`, `Shortcut`, `Hover`, `Active`, `NativeIcon`, `Icon` |
488
487
  | `Layout` | `Islands`, `LockedPage`, `Light`, `Auto` |
@@ -495,7 +494,7 @@ sub-elements:
495
494
  | `TableOfContents` | `Heading`, `List`, `Item`, `Link`, `LinkLabel`, `HoverLink`, `CurrentLink` |
496
495
  | `ThemeSelect` | `Trigger`, `HoverTrigger`, `ActiveTrigger`, `Icon`, `Panel`, `OpenPanel`, `Section`, `SectionSpacing`, `SectionLabel`, `Option`, `HoverOption`, `CheckedOption`, `FocusedOption`, `Input`, `OptionIcon`, `Checkmark`, `SelectedCheckmark` |
497
496
  | `TopNavigation` | `Scrollbar`, `Link`, `HoverLink`, `CurrentLink`, `ActiveIndicator` |
498
- | `Document` | `All`, `Body`, `Control`, `Pointer`, `ResponsiveWidth`, `ResponsiveHeight`, `Hidden`, `DesktopBlock`, `DesktopFlex`, `ScreenReaderOnly`, `Strong`, `Link`, `NarrowBlock`, `MobileBlock`, `Code`, `FocusRing`, `CurrentLink`, `SearchOpen` |
497
+ | `Document` | `All`, `Body`, `Control`, `Pointer`, `ResponsiveWidth`, `ResponsiveHeight`, `Hidden`, `PrintHidden`, `DesktopBlock`, `DesktopFlex`, `ScreenReaderOnly`, `Strong`, `Link`, `NarrowBlock`, `MobileBlock`, `Code`, `FocusRing`, `CurrentLink`, `SearchOpen` |
499
498
  | `MainPane` | `WithSidebars` |
500
499
  | `MainContent` | `ContentSpacing`, `Container`, `Panel`, `FirstPanel`, `BodyPanel` |
501
500
  | `Banner` | `Link` |
@@ -504,11 +503,7 @@ sub-elements:
504
503
  | `Pagination` | `Link`, `PreviousLink`, `NextLink`, `NextIcon`, `NextLabel`, `HoverLink`, `ActiveLink`, `Title`, `LoneNextLink`, `Icon`, `PreviousIconRtl`, `NextIconRtl` |
505
504
  | `Markdown` | `Block`, `BlockSpacing`, `HeadingSpacing`, `List`, `CompactItem`, `ListItem`, `DefinitionTerm`, `DefinitionDescription`, `Link`, `HoverLink`, `Quote`, `Rule`, `Details`, `HoverDetails`, `Summary`, `OpenSummary`, `SummaryMarker`, `SummaryIcon`, `OpenSummaryIcon`, `Code` |
506
505
  | `MermaidSource` | None |
507
- | `StarlightAside` | `Note`, `Tip`, `Caution`, `Danger`, `Title`, `Icon`, `FirstContent` |
508
- | `StarlightCard` | `Title` |
509
- | `StarlightLinkCard` | `Hover`, `Stack`, `Link`, `LinkOverlay`, `DescriptionAndIcon` |
510
- | `StarlightBadge` | None |
511
- | `StarlightSteps` | `Item`, `Counter`, `Connector` |
506
+ | `MarkdownAlert` | `Note`, `Tip`, `Caution`, `Danger`, `Title`, `FirstContent` |
512
507
  | `SyntaxHighlight` | `Scroll`, `Wrap`, `Marker`, `Comment`, `Punctuation`, `Keyword`, `String`, `Token`, `Property`, `Number`, `Function`, `Value`, `Operator`, `Text`, `Bg`, `Inserted`, `Deleted`, `Italic`, `Strong`, `Underline` |
513
508
  | `SearchResults` | `Form`, `Input`, `Clear`, `Results`, `Result`, `ResultLink`, `SearchIcon`, `ClearIcon`, `SuppressedClear`, `Message`, `List`, `Title`, `Excerpt`, `NestedResult`, `Match`, `More`, `HoverMore` |
514
509
 
@@ -608,7 +603,7 @@ source.
608
603
  Import styling tools from `@tenphi/cookbook/styling`. They use the same Tasty
609
604
  runtime as Cookbook, with its semantic colors, typography presets, units, and
610
605
  responsive states. The renderer package also exposes them from
611
- `@tenphi/starlight/styling`.
606
+ `@tenphi/renderer/styling`.
612
607
 
613
608
  | Export | Purpose |
614
609
  | ------------------------ | ---------------------------------------------------------------------------------- |
@@ -700,7 +695,7 @@ theme: {
700
695
  Custom image assets keep their authored colors; use `light`/`dark` files when
701
696
  you want distinct artwork. Header and drawer home links center logos with the
702
697
  site title regardless of their aspect ratio. Use `theme.styles.SiteLogo` for
703
- image size and `theme.styles.StarlightHeader.SiteTitle` / `Sidebar.HomeLink`
698
+ image size and `theme.styles.Header.SiteTitle` / `Sidebar.HomeLink`
704
699
  for typography; they do not need baseline offsets for a different preset.
705
700
 
706
701
  ### Advanced site title markup
@@ -748,7 +743,7 @@ Then create `docs/components/SiteTitle.astro`, using an SVG whose paths use
748
743
  import ProjectLogo from "../../public/logo.svg";
749
744
  import { SiteTitleRoot } from "./site-title.js";
750
745
 
751
- const { siteTitle, siteTitleHref } = Astro.locals.starlightRoute;
746
+ const { siteTitle, siteTitleHref } = Astro.locals.cookbookRoute;
752
747
  ---
753
748
 
754
749
  <SiteTitleRoot href={siteTitleHref}>
@@ -827,7 +822,7 @@ components using the compatibility bridge described above.
827
822
 
828
823
  `@tenphi/cookbook/eslint-plugin` re-exports the Tasty ESLint plugin together with
829
824
  Cookbook's `validationConfig`. The renderer offers the same exports from
830
- `@tenphi/starlight/eslint-plugin`. Keep style definitions in `.ts` or `.tsx`
825
+ `@tenphi/renderer/eslint-plugin`. Keep style definitions in `.ts` or `.tsx`
831
826
  modules, as in the site title example above, to lint them with either ESLint or
832
827
  oxlint.
833
828
 
@@ -839,7 +834,7 @@ export default {
839
834
  };
840
835
  ```
841
836
 
842
- Renderer-only consumers can use `extends: "@tenphi/starlight"` instead.
837
+ Renderer-only consumers can use `extends: "@tenphi/renderer"` instead.
843
838
  The preset registers both Cookbook styling import paths, its built-in tokens,
844
839
  units, responsive states, and typography presets. It also describes
845
840
  `defineComponent`, `resolveComponentStyles`, and `mergeStyles`, so their inline
@@ -937,7 +932,7 @@ output.
937
932
  The header uses `#header`, generated from `theme.palette.header` (or the page
938
933
  surface) at 70% opacity in all four appearance modes, with a 16px backdrop blur.
939
934
  Customize the outer bar with `theme.styles.HeaderFrame`, its contents with
940
- `StarlightHeader`, and header buttons with `HeaderLinks` and `SearchButton`.
935
+ `Header`, and header buttons with `HeaderLinks` and `SearchButton`.
941
936
 
942
937
  Below 50rem, page navigation moves into a header row and opens a left drawer.
943
938
  `MobileMenuToggle.Section` and `Page` style its breadcrumb labels. The drawer
@@ -956,6 +951,9 @@ for the close button. The inset divider above the tabs belongs to `TopNavigation
956
951
 
957
952
  The desktop table of contents is hidden below 72rem. Set
958
953
  `tableOfContents: { mobile: true }` to show an optional compact disclosure there.
954
+ On desktop, the current section is marked as the page scrolls and its link stays
955
+ visible in a long contents list. Customize its appearance with
956
+ `theme.styles.TableOfContents.CurrentLink`.
959
957
  `MobileTableOfContents` owns its summary and links; `TableOfContentsLayout`
960
958
  controls placement. `Layout` controls shared
961
959
  navigation dimensions and the drawer's scroll lock; `PageFrame` styles the
@@ -1176,8 +1174,8 @@ theme: {
1176
1174
  and accessibility utilities. `MainPane` and `MainContent` own the content
1177
1175
  layout. `Markdown` owns prose, lists, links, quotations, and disclosure
1178
1176
  anatomy. `Search` owns the dialog; `SearchResults` owns the Pagefind UI.
1179
- The `Starlight*` trees style compatible upstream component markup; Cookbook's
1180
- own `Card`, `Callout`, and `Steps` use their respective trees.
1177
+ `MarkdownAlert` styles rendered alert blockquotes; `Card`, `Callout`, and
1178
+ `Steps` style Cookbook components.
1181
1179
 
1182
1180
  Custom components created with `defineComponent()` receive `theme.customStyles`
1183
1181
  overrides during server rendering. Units, recipes, states, and presets are
@@ -1197,7 +1195,11 @@ snippets. The padding follows the `code` preset's line height. Override it with
1197
1195
 
1198
1196
  Shiki classifies code; Tasty renders every token using Glaze's semantic syntax
1199
1197
  colors. Customize token rules with `theme.styles.SyntaxHighlight`, or their
1200
- colors with `theme.palette` (for example `syntax-keyword`). Code fences, including
1198
+ colors with `theme.palette` (for example `syntax-keyword`). The default
1199
+ `syntax-bg` stays white in light mode and takes a slight brand-hued tint, close
1200
+ to the page background's saturation, in dark mode. Set
1201
+ `theme.palette["syntax-bg"]` to give code its own color seed;
1202
+ syntax text and token contrast resolve against that surface. Code fences, including
1201
1203
  MDX and diff blocks, use classes without inline style attributes. Custom Shiki
1202
1204
  transformers should emit classes; unsupported inline declarations fail with a
1203
1205
  configuration hint.
@@ -49,15 +49,13 @@ contrast. Browser checks complement the numeric diagnostics.
49
49
 
50
50
  ## Incompatible plugins
51
51
 
52
- Use the [tested plugin matrix](./plugins.md#verified-compatibility). Cookbook
53
- owns content routing and all rendered styles. Plugins that read Astro's docs
54
- collection filesystem or inject CSS are not automatically compatible.
55
- `starlight-github-alerts` requires the documented unified Markdown processor;
56
- `starlight-links-validator` is unsupported because it reads synthetic paths.
57
- Use Cookbook's graph and built-output checks for links.
58
-
59
- For your own plugin, read custom frontmatter through route middleware or the
60
- server-only `@tenphi/cookbook/content` API. If a schema rejects data, check that
52
+ Cookbook owns content routing and all rendered styles. Plugins that assume a
53
+ different docs collection or inject CSS cannot run in the renderer. GitHub
54
+ alerts are supported directly; use Cookbook's graph and built-output checks
55
+ for links. See [extending Cookbook](./plugins.md) for Astro Markdown plugins.
56
+
57
+ Read custom frontmatter through the server-only `@tenphi/cookbook/content` API
58
+ or `Astro.locals.cookbookRoute` in a component override. If a schema rejects data, check that
61
59
  custom fields do not replace reserved Cookbook frontmatter and that parsed
62
60
  values are JSON-safe. A plugin's successful registration is not proof that its
63
61
  rendered output works.
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@tenphi/cookbook",
3
- "version": "0.18.2",
3
+ "version": "0.19.1",
4
4
  "description": "Repository-native static documentation for Astro",
5
5
  "type": "module",
6
6
  "keywords": [
7
7
  "astro-integration",
8
8
  "astro",
9
9
  "documentation",
10
- "starlight",
10
+ "documentation",
11
11
  "static-site"
12
12
  ],
13
13
  "bin": {
@@ -68,8 +68,8 @@
68
68
  "author": "Andrey Yamanov",
69
69
  "license": "MIT",
70
70
  "dependencies": {
71
- "@tenphi/docs": "0.18.2",
72
- "@tenphi/starlight": "0.18.2"
71
+ "@tenphi/docs": "0.19.1",
72
+ "@tenphi/renderer": "0.19.1"
73
73
  },
74
74
  "peerDependencies": {
75
75
  "astro": "^7.3.2"
@@ -1,124 +0,0 @@
1
- ---
2
- title: Cookbook and Starlight
3
- description: Understand which Starlight authoring conventions Cookbook preserves and where its repository and theme model differs.
4
- sidebar:
5
- order: 5
6
- ---
7
- Cookbook uses [Astro Starlight](https://starlight.astro.build/) as its
8
- documentation shell. It keeps familiar page-authoring conventions while adding
9
- repository and npm content sources, stricter validation, and a Tasty/Glaze
10
- theme model.
11
-
12
- ## Cookbook or Starlight?
13
-
14
- Start with the place where the documentation must live. Starlight is a strong
15
- choice when an Astro site owns its content. Cookbook is designed for projects
16
- where the repository Markdown—or the documentation actually published in an
17
- npm package—must remain the source of truth.
18
-
19
- | Concern | Starlight | Cookbook |
20
- | ----------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
21
- | Starting point | Add Starlight to an Astro project and author its documentation content collection. | Add one integration to an Astro project, or generate a complete site directly from a published npm package. |
22
- | Content ownership | The documentation site conventionally owns its Markdown under `src/content/docs/`. | Reads `README.md`, repository `docs/` trees, files outside the Astro app, and selected files from npm artifacts without copying or rewriting them. |
23
- | Reproducible releases | Follows the dependencies and content committed with the site. | Can lock an npm package to its exact resolved version and integrity, then rebuild from the files users actually receive. |
24
- | Build guarantees | Provides Starlight's content schema and Astro build pipeline. | Adds strict checks for duplicate routes, broken links, missing assets, unsafe paths, and invalid navigation with source-aware diagnostics. |
25
- | Design system | Supports CSS variables, custom CSS, and component overrides. | Exposes the full [Tasty styling DSL](./upstream/tasty/docs/dsl.md) through configuration, with Glaze-generated semantic colors and named style trees for Cookbook and shell surfaces. |
26
- | Familiar authoring | Defines the Starlight page, navigation, i18n, and frontmatter conventions. | Preserves those conventions—including splash pages, locales, edit links, and last-updated metadata—while resolving them against each original source. |
27
- | Structural escape hatch | Replaces Starlight components when markup or behavior must change. | Supports Astro component overrides for structural changes; visual changes normally stay in typed `theme` configuration. |
28
-
29
- Choose Starlight when the documentation site is the natural home for the
30
- content and its CSS-oriented customization model fits the project. Choose
31
- Cookbook when documentation must stay beside the code, match a published
32
- package, fail strictly when references drift, or expose a reusable design
33
- system entirely through configuration.
34
-
35
- ## Customize with Tasty's DSL
36
-
37
- Cookbook customization is not limited to replacing token values. Every entry
38
- under `theme.styles` is a partial Tasty style object that Cookbook merges into
39
- the component's base style tree. That gives configuration access to the same
40
- responsive values, state maps, calculations, semantic tokens, typography
41
- presets, and named sub-elements used by Cookbook itself:
42
-
43
- ```ts
44
- export default defineDocsConfig({
45
- theme: {
46
- states: {
47
- "@touch": "@media(pointer: coarse)",
48
- },
49
- styles: {
50
- MarkdownCodeBlock: {
51
- Pre: {
52
- padding: {
53
- "": "2x 4x",
54
- "@mobile": "1.5x 3x",
55
- },
56
- radius: "$card-radius",
57
- },
58
- CopyButton: {
59
- inlineSize: {
60
- "": "2rem",
61
- "@touch": "2.5rem",
62
- },
63
- scale: {
64
- "": "1",
65
- ":active": "0.94",
66
- },
67
- },
68
- },
69
- },
70
- },
71
- });
72
- ```
73
-
74
- The user supplies only overrides; the merge happens inside Cookbook. See
75
- [Theme and components](./theme-and-components.md#style-customization) for the
76
- complete component and sub-element inventory, and the
77
- [Tasty documentation](./upstream/tasty/docs/README.md) for the DSL's properties and
78
- conditional syntax. Structural Astro overrides remain available when a change
79
- requires different markup or behavior rather than styling.
80
-
81
- ## Configure the shared capabilities
82
-
83
- ```ts
84
- export default defineDocsConfig({
85
- editLink: {
86
- baseUrl: "https://github.com/example/project/edit/main/",
87
- },
88
- lastUpdated: true,
89
- locales: {
90
- root: { label: "English", lang: "en" },
91
- fr: { label: "Français", lang: "fr" },
92
- },
93
- defaultLocale: "root",
94
- });
95
- ```
96
-
97
- The keys deliberately match Starlight so an existing Starlight author does not
98
- need to relearn page metadata or i18n. Cookbook resolves edit and Git metadata
99
- before handing each page to Starlight because its source may live in a root
100
- `docs/` directory, outside the Astro app, or inside a locked npm artifact.
101
-
102
- ## Create a splash page
103
-
104
- ```yaml
105
- ---
106
- title: Example
107
- template: splash
108
- hero:
109
- title: Build something clear.
110
- tagline: A short explanation of the value your project provides.
111
- actions:
112
- - text: Get started
113
- link: /getting-started/
114
- variant: primary
115
- - text: View API
116
- link: /reference/
117
- variant: secondary
118
- ---
119
- ```
120
-
121
- Use `template: doc` (the default) for conventional reference pages. See
122
- Starlight's [page guide](https://starlight.astro.build/guides/pages/) for the
123
- authoring model Cookbook builds on, then use [Theme and
124
- components](./theme-and-components.md) for Cookbook-specific styling.