create-zudo-doc 1.0.2 → 1.2.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.
@@ -31,7 +31,7 @@ export const i18nFeature = (_choices) => {
31
31
  const stat = fs.existsSync(pagesDir) ? fs.statSync(pagesDir) : null;
32
32
  if (!stat || !stat.isDirectory() || fs.readdirSync(pagesDir).length === 0) {
33
33
  throw new Error(`i18n feature template dir is missing or empty: ${pagesDir}\n` +
34
- `Expected to find [locale]/index.tsx and [locale]/docs/[...slug].tsx.\n` +
34
+ `Expected to find [locale]/index.tsx.\n` +
35
35
  `This is a generator bug — please file an issue.`);
36
36
  }
37
37
  return {
@@ -11,13 +11,21 @@ import type { FeatureModule } from "../compose.js";
11
11
  * W7C (#1738): the versioning feature ships pages under
12
12
  * `templates/features/versioning/files/pages/`:
13
13
  *
14
- * docs/versions.tsx (always — versioning gate only)
15
- * v/[version]/docs/[...slug].tsx (always — versioning gate only)
16
- * v/[version]/[locale]/docs/[...slug].tsx (i18n + versioning — see below)
17
- * [locale]/docs/versions.tsx (i18n + versioning)
14
+ * lib/_versions-page.tsx (always — versions-listing renderer)
15
+ *
16
+ * The versioned DOC routes — `/docs/versions`, `/v/[version]/docs/[[...slug]]`,
17
+ * and `/v/[version]/[locale]/docs/[[...slug]]` are now PACKAGE-INJECTED
18
+ * (packageOwnedRoutes); their host catch-all stubs were deleted from the
19
+ * template in #2390 (supersedes #2377) so generated projects render them via
20
+ * injection through `@takazudo/zudo-doc`'s `_chrome` chrome (which wires the
21
+ * MDX content components). The package route is the functional equivalent of
22
+ * the old stub (it enumerates `settings.versions` and renders via the shared
23
+ * `renderDocPage`).
18
24
  *
19
25
  * `copyFeatureFiles` (compose.ts) auto-copies everything under `files/`.
20
- * postProcess removes the i18n-gated subset when i18n is OFF so single-
21
- * locale projects don't ship orphan routes.
26
+ * postProcess is now a defensive no-op: the i18n-gated stubs it strips
27
+ * (`[locale]/docs/versions.tsx`, `v/[version]/[locale]/**`) no longer ship in
28
+ * the template, but the cleanup is kept so a re-added stub can never leak an
29
+ * orphan locale route into a single-locale project.
22
30
  */
23
31
  export declare const versioningFeature: FeatureModule;
@@ -12,14 +12,22 @@ import path from "path";
12
12
  * W7C (#1738): the versioning feature ships pages under
13
13
  * `templates/features/versioning/files/pages/`:
14
14
  *
15
- * docs/versions.tsx (always — versioning gate only)
16
- * v/[version]/docs/[...slug].tsx (always — versioning gate only)
17
- * v/[version]/[locale]/docs/[...slug].tsx (i18n + versioning — see below)
18
- * [locale]/docs/versions.tsx (i18n + versioning)
15
+ * lib/_versions-page.tsx (always — versions-listing renderer)
16
+ *
17
+ * The versioned DOC routes — `/docs/versions`, `/v/[version]/docs/[[...slug]]`,
18
+ * and `/v/[version]/[locale]/docs/[[...slug]]` are now PACKAGE-INJECTED
19
+ * (packageOwnedRoutes); their host catch-all stubs were deleted from the
20
+ * template in #2390 (supersedes #2377) so generated projects render them via
21
+ * injection through `@takazudo/zudo-doc`'s `_chrome` chrome (which wires the
22
+ * MDX content components). The package route is the functional equivalent of
23
+ * the old stub (it enumerates `settings.versions` and renders via the shared
24
+ * `renderDocPage`).
19
25
  *
20
26
  * `copyFeatureFiles` (compose.ts) auto-copies everything under `files/`.
21
- * postProcess removes the i18n-gated subset when i18n is OFF so single-
22
- * locale projects don't ship orphan routes.
27
+ * postProcess is now a defensive no-op: the i18n-gated stubs it strips
28
+ * (`[locale]/docs/versions.tsx`, `v/[version]/[locale]/**`) no longer ship in
29
+ * the template, but the cleanup is kept so a re-added stub can never leak an
30
+ * orphan locale route into a single-locale project.
23
31
  */
24
32
  export const versioningFeature = (choices) => ({
25
33
  name: "versioning",
@@ -11,5 +11,5 @@ export { getSecondaryLang };
11
11
  *
12
12
  * Bumped in lockstep by scripts/release-create-zudo-doc.sh.
13
13
  */
14
- export declare const ZUDO_DOC_PIN = "^1.0.2";
14
+ export declare const ZUDO_DOC_PIN = "^1.2.0";
15
15
  export declare function scaffold(choices: UserChoices): Promise<void>;
package/dist/scaffold.js CHANGED
@@ -18,7 +18,7 @@ export { getSecondaryLang };
18
18
  *
19
19
  * Bumped in lockstep by scripts/release-create-zudo-doc.sh.
20
20
  */
21
- export const ZUDO_DOC_PIN = "^1.0.2";
21
+ export const ZUDO_DOC_PIN = "^1.2.0";
22
22
  /**
23
23
  * Files in `templates/base/**` that must never be copied into a generated
24
24
  * project. Each entry is matched against the path relative to `templates/base/`
@@ -470,16 +470,20 @@ function generatePackageJson(choices) {
470
470
  // multi-valued response headers (e.g. multiple Set-Cookie),
471
471
  // supplementary-plane CJK reading-time, plus CLI/server/runtime hardening
472
472
  // and render perf passes. No consumer-facing / CLI breaking change.
473
- // next.65 (current pin): dev-render of package-injected routes (zfb#1227,
473
+ // next.65: dev-render of package-injected routes (zfb#1227,
474
474
  // landed next.63) + islands bundler now seeds the host tsconfig `paths`
475
475
  // (e.g. `@/*`) into its synthetic tsconfig (zfb#1238) — fixes silent island
476
476
  // hydration failure under route injection. Unblocks packageOwnedRoutes.
477
477
  // No consumer-facing / CLI breaking change.
478
- "@takazudo/zfb": "0.1.0-next.65",
479
- "@takazudo/zfb-runtime": "0.1.0-next.65",
478
+ // next.68: routine toolchain bump from next.67, adopted in
479
+ // lockstep with the root package.json pins. No consumer-facing / CLI change.
480
+ // next.69 (current pin): routine toolchain bump from next.68, adopted in
481
+ // lockstep with the root package.json pins. No consumer-facing / CLI change.
482
+ "@takazudo/zfb": "0.1.0-next.69",
483
+ "@takazudo/zfb-runtime": "0.1.0-next.69",
480
484
  // zfb-adapter-cloudflare — required for any route with `prerender = false`.
481
485
  // Pinned in lockstep with @takazudo/zfb.
482
- "@takazudo/zfb-adapter-cloudflare": "0.1.0-next.65",
486
+ "@takazudo/zfb-adapter-cloudflare": "0.1.0-next.69",
483
487
  // @takazudo/zudo-doc — published from this monorepo via
484
488
  // .github/workflows/publish-zudo-doc.yml. The pin here is bumped in
485
489
  // lockstep by scripts/release-create-zudo-doc.sh whenever zudo-doc's
@@ -501,7 +505,7 @@ function generatePackageJson(choices) {
501
505
  // any page compiles. The Astro→zfb retarget (3f0042f7) added the
502
506
  // import without the runtime dep; W6B (#1735) consumer-build
503
507
  // verification was the first to actually exercise it.
504
- zod: "^4.0.0",
508
+ zod: "^4.3.6", // floor matches @takazudo/zudo-doc's peer dep (package.json peerDependencies)
505
509
  // ^10.29.1 floor satisfies @takazudo/zdtp's preact peer range so the app
506
510
  // and zdtp resolve a single preact instance — a lower floor can split into
507
511
  // two copies and crash hook-using SSR islands with "undefined reading __H".
@@ -562,7 +566,7 @@ function generatePackageJson(choices) {
562
566
  // @takazudo/zudo-doc/integrations/doc-history which in turn imports
563
567
  // @takazudo/zudo-doc-history-server/git-history. Without this dep the
564
568
  // plugin host fails at init with ERR_MODULE_NOT_FOUND — W8A (#1739).
565
- deps["@takazudo/zudo-doc-history-server"] = "^1.0.2";
569
+ deps["@takazudo/zudo-doc-history-server"] = "^1.2.0";
566
570
  // tsx is no longer needed here: the relocated package plugin imports the
567
571
  // runner directly (no `tsx -e` spawn) since the package ships compiled
568
572
  // dist/ — package-first migration #2321 (#2337).
@@ -28,6 +28,8 @@ export function generateZfbConfig(_choices) {
28
28
  lines.push(`import { zudoDocPreset } from "@takazudo/zudo-doc/preset";`);
29
29
  lines.push(`import { settings } from "./src/config/settings";`);
30
30
  lines.push(`import { buildDocsSchema } from "./src/config/docs-schema";`);
31
+ lines.push(`import { translations } from "./src/config/i18n";`);
32
+ lines.push(`import { colorSchemes } from "./src/config/color-schemes";`);
31
33
  lines.push(``);
32
34
  // --- Directive vocabulary ---
33
35
  // The seven canonical directives registered in pages/_mdx-components.ts.
@@ -54,7 +56,7 @@ export function generateZfbConfig(_choices) {
54
56
  lines.push(` base: settings.base,`);
55
57
  lines.push(``);
56
58
  lines.push(` // ── Preset-owned fields (content collections, plugins, markdown, …) ────────`);
57
- lines.push(` ...zudoDocPreset({ settings, buildDocsSchema, directiveVocabulary }),`);
59
+ lines.push(` ...zudoDocPreset({ settings, buildDocsSchema, directiveVocabulary, translations, colorSchemes }),`);
58
60
  lines.push(`});`);
59
61
  return lines.join("\n") + "\n";
60
62
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-zudo-doc",
3
- "version": "1.0.2",
3
+ "version": "1.2.0",
4
4
  "description": "Create a new zudo-doc documentation site",
5
5
  "license": "MIT",
6
6
  "author": "Takeshi Takatsudo",
@@ -55,7 +55,7 @@ export function detectLocaleFromPath(path: string): Locale {
55
55
  }
56
56
 
57
57
  /** UI string translations */
58
- const translations: Record<string, Record<string, string>> = {
58
+ export const translations: Record<string, Record<string, string>> = {
59
59
  en: {
60
60
  "nav.gettingStarted": "Getting Started",
61
61
  "nav.learn": "Learn",
@@ -1,90 +0,0 @@
1
- /** @jsxRuntime automatic */
2
- /** @jsxImportSource preact */
3
- // Page module for the default-locale docs route.
4
- //
5
- // Default-locale (EN) catch-all docs route. paths() enumerates every page in
6
- // the "docs" collection plus auto-generated category index pages (for
7
- // categories without an index.mdx). Per-page props carry all pre-computed
8
- // data so the component is a pure renderer with no collection reads.
9
- //
10
- // paths() contract (zfb ADR-004 — synchronous):
11
- // params: { slug: string[] } — e.g. ["getting-started", "intro"]
12
- // props: { entry, autoIndex, breadcrumbs, prev, next }
13
- //
14
- // Route is the OPTIONAL catchall `[[...slug]]` so a bare root index.mdx can
15
- // build at `/docs/` (canonical root URL — #1891). The root entry emits
16
- // `params.slug = []` (zero segments) via `toSlugParams`; a required `[...slug]`
17
- // catchall rejects an empty array and would drop the whole route.
18
- //
19
- // The catchall slug is an array per zfb spec — the component joins it when
20
- // deriving the string form (e.g. for Content lookups, breadcrumbs, etc.).
21
- //
22
- // Locale: defaultLocale (EN). Non-default locales are handled by
23
- // pages/[locale]/docs/[[...slug]].tsx.
24
- //
25
- // Enumeration + per-entry derived data (breadcrumbs, prev/next, headings) are
26
- // built by the shared, memoized buildDocRouteEntries (#2010); rendering by the
27
- // shared renderDocPage. This file owns only the route's nav source and the
28
- // param/prop shapes.
29
-
30
- import { settings } from "@/config/settings";
31
- import { defaultLocale } from "@/config/i18n";
32
- import type { JSX } from "preact";
33
- import { resolveNavSource } from "../lib/_nav-source-docs";
34
- import type { DocPageEntryProps, DocPageAutoIndexProps } from "../lib/doc-page-props";
35
- import { buildDocRouteEntries } from "../lib/_doc-route-entries";
36
- import { renderDocPage } from "../lib/_doc-page-renderer";
37
-
38
- export const frontmatter = { title: "Docs" };
39
-
40
- // ---------------------------------------------------------------------------
41
- // Props contract
42
- // ---------------------------------------------------------------------------
43
-
44
- type DocPageProps = DocPageEntryProps | DocPageAutoIndexProps;
45
-
46
- // ---------------------------------------------------------------------------
47
- // paths() — synchronous route enumeration (ADR-004)
48
- // ---------------------------------------------------------------------------
49
-
50
- /**
51
- * Enumerate all doc routes for the default locale (EN).
52
- *
53
- * Synchronous per ADR-004: getCollection() resolves from the pre-loaded
54
- * ContentSnapshot. All nav-tree and breadcrumb computation is done in the
55
- * shared builder so the component is a pure renderer.
56
- */
57
- export function paths(): Array<{
58
- params: { slug: string[] };
59
- props: DocPageProps;
60
- }> {
61
- const locale = defaultLocale;
62
- // Identity-stable nav source (draft-filtered, unlisted retained). The same
63
- // instances are returned across this route's many per-page paths()
64
- // invocations, so both buildNavTree's identity fast-path and the
65
- // buildDocRouteEntries memo key on them — see pages/lib/_nav-source-docs.ts
66
- // (#1902).
67
- const source = resolveNavSource(locale, undefined);
68
-
69
- return buildDocRouteEntries({
70
- source,
71
- locale,
72
- routeSig: `docs;${locale}`,
73
- }).map((item) => ({
74
- params: { slug: item.slugParams },
75
- props: item.props,
76
- }));
77
- }
78
-
79
- // ---------------------------------------------------------------------------
80
- // Page component
81
- // ---------------------------------------------------------------------------
82
-
83
- type PageArgs = DocPageProps & { params: { slug: string[] } };
84
-
85
- export default function DocsPage(props: PageArgs): JSX.Element {
86
- return renderDocPage(props, {
87
- locale: defaultLocale,
88
- docHistoryContentDir: settings.docsDir,
89
- });
90
- }
@@ -1,134 +0,0 @@
1
- /** @jsxRuntime automatic */
2
- /** @jsxImportSource preact */
3
- // Page module for the locale-prefixed docs route.
4
- //
5
- // Non-default-locale catch-all docs route. paths() emits one route per
6
- // (locale, slug) combination — one locale from settings.locales per each
7
- // doc in that locale's merged collection (locale-first + base fallback).
8
- //
9
- // paths() contract (zfb ADR-004 — synchronous):
10
- // params: { locale: string; slug: string[] }
11
- // props: { entry, autoIndex, contentDir, isFallback, breadcrumbs, prev, next }
12
- //
13
- // Route is the OPTIONAL catchall `[[...slug]]` so a locale root index.mdx can
14
- // build at `/{locale}/docs/` (canonical root URL — #1891). The root entry
15
- // emits `params.slug = []` via `toSlugParams`; a required `[...slug]` catchall
16
- // rejects an empty array and would drop the ENTIRE locale route (the EN-root
17
- // index leaks in via the locale-first EN fallback, so this fires even before a
18
- // locale-specific root index exists — probe-observed page-count collapse).
19
- //
20
- // i18n / locale routing:
21
- // - Default locale (EN) is handled by pages/docs/[[...slug]].tsx
22
- // (prefixDefaultLocale: false).
23
- // - Non-default locales emit /{locale}/docs/{slug}.
24
- // - Locale-first merge: locale docs take priority; base EN docs fill in
25
- // pages not translated yet (shown with a fallback notice).
26
- //
27
- // Enumeration + per-entry derived data are built by the shared, memoized
28
- // buildDocRouteEntries (#2010); rendering by the shared renderDocPage. This
29
- // file owns only the route's nav source and the param/prop shapes.
30
-
31
- import { settings } from "@/config/settings";
32
- import { getLocaleConfig, type Locale } from "@/config/i18n";
33
- import type { JSX } from "preact";
34
- import { resolveNavSource } from "../../lib/_nav-source-docs";
35
- import type { DocPageEntryProps, DocPageAutoIndexProps } from "../../lib/doc-page-props";
36
- import { buildDocRouteEntries } from "../../lib/_doc-route-entries";
37
- import { renderDocPage } from "../../lib/_doc-page-renderer";
38
-
39
- export const frontmatter = { title: "Docs" };
40
-
41
- // ---------------------------------------------------------------------------
42
- // Types
43
- // ---------------------------------------------------------------------------
44
-
45
- /** Route-specific extra fields — present on both branches of the union. */
46
- interface LocaleDocPageExtra {
47
- /** Content directory for the active locale (or base EN for fallbacks). */
48
- contentDir: string;
49
- /** True when this page falls back to the base EN collection. */
50
- isFallback: boolean;
51
- }
52
-
53
- type DocPageProps =
54
- | (DocPageEntryProps & LocaleDocPageExtra)
55
- | (DocPageAutoIndexProps & LocaleDocPageExtra);
56
-
57
- // ---------------------------------------------------------------------------
58
- // paths() — synchronous (ADR-004)
59
- // ---------------------------------------------------------------------------
60
-
61
- /**
62
- * Emit one route per (non-default locale, slug) combination.
63
- *
64
- * Merge strategy:
65
- * 1. Load locale docs (e.g. "docs-ja").
66
- * 2. Load base EN docs ("docs").
67
- * 3. Locale docs take priority; base EN fills in slugs not translated.
68
- * 4. Track fallback slugs for the fallback-notice banner.
69
- * 5. Build nav tree, compute breadcrumbs and prev/next for each entry.
70
- *
71
- * Fallback detection (`isFallback`) comes from the merge's localeSlugSet —
72
- * the component uses it to show the "not yet translated" notice (matching
73
- * the Astro original).
74
- */
75
- export function paths(): Array<{
76
- params: { locale: string; slug: string[] };
77
- props: DocPageProps;
78
- }> {
79
- const result: Array<{
80
- params: { locale: string; slug: string[] };
81
- props: DocPageProps;
82
- }> = [];
83
-
84
- for (const locale of Object.keys(settings.locales) as string[]) {
85
- const localeConfig = getLocaleConfig(locale);
86
- const contentDir = localeConfig?.dir ?? settings.docsDir;
87
-
88
- // Identity-stable, locale-first merge with EN fallback. The same `docs` /
89
- // `navDocs` / `categoryMeta` instances are reused across this route's many
90
- // per-page paths() invocations so both buildNavTree's identity fast-path
91
- // and the buildDocRouteEntries memo key on them — see
92
- // pages/lib/_nav-source-docs.ts (#1902).
93
- const source = resolveNavSource(locale as Locale, undefined, {
94
- applyDefaultLocaleOnlyFilter: true,
95
- keepUnlisted: true,
96
- });
97
-
98
- for (const item of buildDocRouteEntries({
99
- source,
100
- locale: locale as Locale,
101
- routeSig: `locale-docs;${locale}`,
102
- })) {
103
- // isFallback: page came from base docs, not the locale collection.
104
- // Always false for autoIndex items (item.isFallback already is).
105
- const extra: LocaleDocPageExtra = {
106
- contentDir: item.isFallback ? settings.docsDir : contentDir,
107
- isFallback: item.isFallback,
108
- };
109
- result.push({
110
- params: { locale, slug: item.slugParams },
111
- props:
112
- item.props.kind === "entry"
113
- ? { ...item.props, ...extra }
114
- : { ...item.props, ...extra },
115
- });
116
- }
117
- }
118
-
119
- return result;
120
- }
121
-
122
- // ---------------------------------------------------------------------------
123
- // Page component
124
- // ---------------------------------------------------------------------------
125
-
126
- type PageArgs = DocPageProps & { params: { locale: string; slug: string[] } };
127
-
128
- export default function LocaleDocsPage(props: PageArgs): JSX.Element {
129
- return renderDocPage(props, {
130
- locale: props.params.locale as Locale,
131
- isFallback: props.isFallback,
132
- docHistoryContentDir: props.contentDir,
133
- });
134
- }
@@ -1,151 +0,0 @@
1
- /** @jsxRuntime automatic */
2
- /** @jsxImportSource preact */
3
- // Page module for the versioned non-default-locale docs route.
4
- //
5
- // Optional-catchall [[...slug]] so slug=[] (empty) routes to /v/<ver>/<locale>/docs/
6
- // when a versioned locale root index.mdx exists — toSlugParams("") returns [].
7
- //
8
- // Versioned locale docs route. paths() cross-products settings.versions ×
9
- // configured per-version locales with a locale-first merge strategy:
10
- // locale-specific collection (`docs-v-${version.slug}-${locale}`) takes
11
- // priority; the base EN collection (`docs-v-${version.slug}`) fills in
12
- // pages not translated yet (shown with a fallback notice).
13
- //
14
- // If version.locales?.[locale] is not configured, only the base EN collection is used.
15
- //
16
- // paths() contract (zfb ADR-004 — synchronous):
17
- // params: { version: string; locale: string; slug: string[] }
18
- // props: { entry, autoIndex, version, contentDir, isFallback, breadcrumbs, prev, next }
19
- //
20
- // Prev/next hrefs are pre-resolved to the versioned locale URL form
21
- // (e.g. /v/1.0/ja/docs/…) so the component needs no URL computation.
22
- //
23
- // Enumeration + per-entry derived data are built by the shared, memoized
24
- // buildDocRouteEntries (#2010); rendering by the shared renderDocPage. This
25
- // file owns only the route's nav source, its versioned-locale URL closure,
26
- // and the param/prop shapes.
27
-
28
- import { settings } from "@/config/settings";
29
- import type { VersionConfig } from "@/config/settings";
30
- import { type Locale } from "@/config/i18n";
31
- import { versionedDocsUrl } from "@/utils/base";
32
- import type { JSX } from "preact";
33
- import { resolveVersionedLocaleSource } from "../../../../lib/_nav-source-docs";
34
- import type { DocPageEntryProps, DocPageAutoIndexProps } from "../../../../lib/doc-page-props";
35
- import { buildDocRouteEntries } from "../../../../lib/_doc-route-entries";
36
- import { renderDocPage } from "../../../../lib/_doc-page-renderer";
37
-
38
- export const frontmatter = { title: "Docs" };
39
-
40
- // ---------------------------------------------------------------------------
41
- // Types
42
- // ---------------------------------------------------------------------------
43
-
44
- /** Route-specific extra fields — present on both branches of the union. */
45
- interface VersionedLocaleDocPageExtra {
46
- /** The version config for the active version. */
47
- version: VersionConfig;
48
- /** Content directory for this page (locale dir if translated, version docsDir if fallback). */
49
- contentDir: string;
50
- /** True when this page falls back to the base EN collection for this version. */
51
- isFallback: boolean;
52
- }
53
-
54
- type DocPageProps =
55
- | (DocPageEntryProps & VersionedLocaleDocPageExtra)
56
- | (DocPageAutoIndexProps & VersionedLocaleDocPageExtra);
57
-
58
- // ---------------------------------------------------------------------------
59
- // paths() — synchronous (ADR-004)
60
- // ---------------------------------------------------------------------------
61
-
62
- /**
63
- * Emit one route per (version, locale, slug) combination for all non-default locales.
64
- *
65
- * Cross-products settings.versions × Object.keys(settings.locales) (which are
66
- * the non-default locales — default EN is handled by v/[version]/docs/[...slug].tsx).
67
- *
68
- * Merge strategy per (version, locale):
69
- * 1. Load locale docs (e.g. "docs-v-1.0-ja") if version.locales[locale] is set.
70
- * 2. Load base EN docs ("docs-v-1.0").
71
- * 3. Locale docs take priority; base EN fills in slugs not translated.
72
- * 4. Track fallback slugs for the fallback-notice banner.
73
- * 5. Build nav tree with the active locale, compute breadcrumbs and prev/next.
74
- *
75
- * Prev/next hrefs are pre-resolved to the versioned locale URL form.
76
- */
77
- export function paths(): Array<{
78
- params: { version: string; locale: string; slug: string[] };
79
- props: DocPageProps;
80
- }> {
81
- if (!settings.versions) return [];
82
-
83
- const result: Array<{
84
- params: { version: string; locale: string; slug: string[] };
85
- props: DocPageProps;
86
- }> = [];
87
-
88
- for (const version of settings.versions) {
89
- for (const locale of Object.keys(settings.locales) as string[]) {
90
- const localeDir = version.locales?.[locale]?.dir;
91
-
92
- // Identity-stable, locale-first merge over the version's EN base. Reused
93
- // across the route's per-page paths() invocations so buildNavTree's
94
- // identity fast-path and the buildDocRouteEntries memo apply — see
95
- // pages/lib/_nav-source-docs.ts (#1902).
96
- const source = resolveVersionedLocaleSource(
97
- version.slug,
98
- version.docsDir,
99
- locale as Locale,
100
- localeDir,
101
- { applyDefaultLocaleOnlyFilter: true, keepUnlisted: true },
102
- );
103
-
104
- // URL closure for THIS (version, locale) — every versioned-locale href
105
- // (prev/next, breadcrumb crumbs, auto-index cards) is produced by this
106
- // single function bound to the version slug + locale, resolved against
107
- // this route's own tree (#1916).
108
- const urlFor = (s: string): string => versionedDocsUrl(s, version.slug, locale as Locale);
109
-
110
- for (const item of buildDocRouteEntries({
111
- source,
112
- locale: locale as Locale,
113
- routeSig: `v-locale-docs;${version.slug};${locale}`,
114
- urlFor,
115
- })) {
116
- // isFallback: page came from the version's base EN docs, not the
117
- // locale collection. Always false for autoIndex items.
118
- const extra: VersionedLocaleDocPageExtra = {
119
- version,
120
- contentDir: item.isFallback
121
- ? version.docsDir
122
- : (localeDir ?? version.docsDir),
123
- isFallback: item.isFallback,
124
- };
125
- result.push({
126
- params: { version: version.slug, locale, slug: item.slugParams },
127
- props:
128
- item.props.kind === "entry"
129
- ? { ...item.props, ...extra }
130
- : { ...item.props, ...extra },
131
- });
132
- }
133
- }
134
- }
135
-
136
- return result;
137
- }
138
-
139
- // ---------------------------------------------------------------------------
140
- // Page component
141
- // ---------------------------------------------------------------------------
142
-
143
- type PageArgs = DocPageProps & { params: { version: string; locale: string; slug: string[] } };
144
-
145
- export default function VersionedLocaleDocsPage(props: PageArgs): JSX.Element {
146
- return renderDocPage(props, {
147
- locale: props.params.locale as Locale,
148
- version: props.version,
149
- isFallback: props.isFallback,
150
- });
151
- }
@@ -1,123 +0,0 @@
1
- /** @jsxRuntime automatic */
2
- /** @jsxImportSource preact */
3
- // Page module for the versioned EN docs route.
4
- //
5
- // Optional-catchall [[...slug]] so slug=[] (empty) routes to /v/<ver>/docs/
6
- // when a versioned root index.mdx exists — toSlugParams("") returns [].
7
- //
8
- // Versioned EN docs route. paths() enumerates one route per (version, slug)
9
- // combination using the `docs-v-${version.slug}` collection for each version
10
- // configured in settings.versions.
11
- //
12
- // paths() contract (zfb ADR-004 — synchronous):
13
- // params: { version: string; slug: string[] }
14
- // props: { entry, autoIndex, version, breadcrumbs, prev, next }
15
- //
16
- // Each version renders with its own nav tree (from the version's docsDir
17
- // category metadata). Prev/next hrefs are pre-resolved to the versioned URL
18
- // form (e.g. /v/1.0/docs/…) so the component needs no URL computation.
19
- //
20
- // Version banner: if version.banner is set ("unmaintained" | "unreleased"),
21
- // the DocLayoutWithDefaults version-banner prop drives the banner display.
22
- //
23
- // Enumeration + per-entry derived data are built by the shared, memoized
24
- // buildDocRouteEntries (#2010); rendering by the shared renderDocPage. This
25
- // file owns only the route's nav source, its versioned URL closure, and the
26
- // param/prop shapes.
27
-
28
- import { settings } from "@/config/settings";
29
- import type { VersionConfig } from "@/config/settings";
30
- import { versionedDocsUrl } from "@/utils/base";
31
- import type { JSX } from "preact";
32
- import { resolveNavSource } from "../../../lib/_nav-source-docs";
33
- import type { DocPageEntryProps, DocPageAutoIndexProps } from "../../../lib/doc-page-props";
34
- import { buildDocRouteEntries } from "../../../lib/_doc-route-entries";
35
- import { renderDocPage } from "../../../lib/_doc-page-renderer";
36
-
37
- export const frontmatter = { title: "Docs" };
38
-
39
- // ---------------------------------------------------------------------------
40
- // Types
41
- // ---------------------------------------------------------------------------
42
-
43
- /** Route-specific extra fields — present on both branches of the union. */
44
- interface VersionedDocPageExtra {
45
- /** The version config for the active version. */
46
- version: VersionConfig;
47
- }
48
-
49
- type DocPageProps =
50
- | (DocPageEntryProps & VersionedDocPageExtra)
51
- | (DocPageAutoIndexProps & VersionedDocPageExtra);
52
-
53
- // ---------------------------------------------------------------------------
54
- // paths() — synchronous (ADR-004)
55
- // ---------------------------------------------------------------------------
56
-
57
- /**
58
- * Emit one route per (version, slug) combination.
59
- *
60
- * For each version in settings.versions, loads docs from
61
- * `docs-v-${version.slug}` and enumerates all pages plus
62
- * auto-generated category index pages.
63
- *
64
- * Prev/next hrefs are pre-resolved to the versioned form.
65
- */
66
- export function paths(): Array<{
67
- params: { version: string; slug: string[] };
68
- props: DocPageProps;
69
- }> {
70
- if (!settings.versions) return [];
71
-
72
- const result: Array<{
73
- params: { version: string; slug: string[] };
74
- props: DocPageProps;
75
- }> = [];
76
-
77
- for (const version of settings.versions) {
78
- // Identity-stable nav source for this version (EN base, draft-filtered,
79
- // unlisted retained). Reused across the route's per-page paths()
80
- // invocations so buildNavTree's identity fast-path and the
81
- // buildDocRouteEntries memo apply — see pages/lib/_nav-source-docs.ts
82
- // (#1902). Versioned docs always use EN locale for the nav tree.
83
- const source = resolveNavSource("en", version.slug);
84
-
85
- // URL closure for THIS version — every versioned href (prev/next,
86
- // breadcrumb crumbs, auto-index cards) is produced by this single
87
- // function bound to the version slug. Because it is built per-version
88
- // inside this loop, a latest-page pagination override is rewritten
89
- // through the VERSIONED closure for this route only — it can never bleed
90
- // into the latest route, which has no such closure (#1916).
91
- const urlFor = (s: string): string => versionedDocsUrl(s, version.slug);
92
-
93
- for (const item of buildDocRouteEntries({
94
- source,
95
- locale: "en",
96
- routeSig: `v-docs;${version.slug}`,
97
- urlFor,
98
- })) {
99
- result.push({
100
- params: { version: version.slug, slug: item.slugParams },
101
- props:
102
- item.props.kind === "entry"
103
- ? { ...item.props, version }
104
- : { ...item.props, version },
105
- });
106
- }
107
- }
108
-
109
- return result;
110
- }
111
-
112
- // ---------------------------------------------------------------------------
113
- // Page component
114
- // ---------------------------------------------------------------------------
115
-
116
- type PageArgs = DocPageProps & { params: { version: string; slug: string[] } };
117
-
118
- export default function VersionedDocsPage(props: PageArgs): JSX.Element {
119
- return renderDocPage(props, {
120
- locale: "en",
121
- version: props.version,
122
- });
123
- }