create-zudo-doc 0.2.21 → 0.2.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/features/image-enlarge.d.ts +10 -2
  2. package/dist/features/image-enlarge.js +10 -2
  3. package/dist/scaffold.js +20 -22
  4. package/dist/zfb-config-gen.d.ts +16 -10
  5. package/dist/zfb-config-gen.js +34 -239
  6. package/package.json +1 -1
  7. package/templates/base/pages/lib/_body-end-islands.tsx +6 -13
  8. package/templates/base/pages/lib/_category-nav.tsx +30 -115
  9. package/templates/base/pages/lib/_category-tree-nav.tsx +38 -65
  10. package/templates/base/pages/lib/_compose-meta-title.ts +2 -6
  11. package/templates/base/pages/lib/_doc-body-end.tsx +3 -35
  12. package/templates/base/pages/lib/_doc-content-header.tsx +10 -111
  13. package/templates/base/pages/lib/_doc-history-area.tsx +19 -211
  14. package/templates/base/pages/lib/_doc-metainfo-area.tsx +10 -113
  15. package/templates/base/pages/lib/_doc-page-renderer.tsx +22 -183
  16. package/templates/base/pages/lib/_doc-page-shell.tsx +17 -251
  17. package/templates/base/pages/lib/_doc-pager.tsx +4 -74
  18. package/templates/base/pages/lib/_doc-route-entries.ts +43 -177
  19. package/templates/base/pages/lib/_doc-route-paths.ts +16 -101
  20. package/templates/base/pages/lib/_doc-tags-area.tsx +14 -77
  21. package/templates/base/pages/lib/_footer-with-defaults.tsx +37 -225
  22. package/templates/base/pages/lib/_frontmatter-preview-data.ts +5 -31
  23. package/templates/base/pages/lib/_head-with-defaults.tsx +13 -138
  24. package/templates/base/pages/lib/_header-with-defaults.tsx +24 -324
  25. package/templates/base/pages/lib/_inline-version-switcher.tsx +16 -78
  26. package/templates/base/pages/lib/_nav-data-prep.ts +32 -51
  27. package/templates/base/pages/lib/_nav-source-cache.ts +12 -57
  28. package/templates/base/pages/lib/_nav-source-docs.ts +33 -233
  29. package/templates/base/pages/lib/_search-widget-script.ts +2 -470
  30. package/templates/base/pages/lib/_search-widget.tsx +9 -195
  31. package/templates/base/pages/lib/_sidebar-prepaint.tsx +6 -59
  32. package/templates/base/pages/lib/_sidebar-with-defaults.tsx +16 -118
  33. package/templates/base/pages/lib/_site-tree-nav.tsx +29 -80
  34. package/templates/base/pages/lib/doc-page-props.ts +26 -44
  35. package/templates/base/pages/lib/locale-merge.ts +32 -145
  36. package/templates/base/pages/lib/route-enumerators.ts +52 -286
  37. package/templates/base/pages/robots.txt.tsx +2 -26
  38. package/templates/base/src/components/ai-chat-modal.tsx +9 -8
  39. package/templates/base/src/components/doc-history.tsx +9 -8
  40. package/templates/base/src/components/image-enlarge.tsx +11 -8
  41. package/templates/base/src/components/sidebar-toggle.tsx +6 -170
  42. package/templates/base/src/components/sidebar-tree.tsx +6 -548
  43. package/templates/base/src/components/site-tree-nav.tsx +6 -220
  44. package/templates/base/src/config/color-scheme-utils.ts +34 -158
  45. package/templates/base/src/config/i18n.ts +9 -0
  46. package/templates/base/src/config/z-index-tokens.ts +5 -4
  47. package/templates/base/src/styles/global.css +5 -579
  48. package/templates/base/src/utils/base.ts +1 -1
  49. package/templates/base/src/utils/docs.ts +47 -16
  50. package/templates/base/src/utils/github.ts +12 -9
  51. package/templates/base/src/utils/nav-scope.ts +13 -42
  52. package/templates/base/src/utils/sidebar.ts +18 -86
  53. package/templates/base/src/utils/slug.ts +10 -53
  54. package/templates/base/src/utils/smart-break.tsx +12 -120
  55. package/templates/base/src/utils/tags.ts +25 -68
  56. package/templates/features/bodyFootUtil/files/src/utils/github.ts +12 -9
  57. package/templates/features/designTokenPanel/files/src/lib/design-token-panel-bootstrap.ts +13 -39
  58. package/templates/features/docHistory/files/src/components/doc-history.tsx +8 -636
  59. package/templates/features/docHistory/files/src/types/doc-history.ts +7 -23
  60. package/templates/features/docTags/files/pages/lib/_tag-pages.tsx +35 -201
  61. package/templates/features/imageEnlarge/files/src/components/image-enlarge.tsx +8 -269
  62. package/templates/features/sidebarToggle/files/src/components/desktop-sidebar-toggle.tsx +6 -99
  63. package/templates/features/tagGovernance/files/scripts/tags-audit.ts +67 -515
  64. package/templates/features/versioning/files/pages/lib/_versions-page.tsx +21 -73
  65. package/templates/base/plugins/connect-adapter.mjs +0 -169
  66. package/templates/base/plugins/search-index-plugin.mjs +0 -66
  67. package/templates/base/scripts/gen-z-index.mjs +0 -157
  68. package/templates/base/src/components/mermaid-enlarge.tsx +0 -490
  69. package/templates/features/claudeResources/files/plugins/claude-resources-plugin.mjs +0 -47
  70. package/templates/features/docHistory/files/plugins/doc-history-plugin.mjs +0 -111
  71. package/templates/features/llmsTxt/files/plugins/llms-txt-plugin.mjs +0 -93
@@ -1,35 +1,15 @@
1
1
  /** @jsxRuntime automatic */
2
2
  /** @jsxImportSource preact */
3
- // Locale-aware DocHistory area wrapper for the zfb doc pages.
3
+ // Host thin-stub see @takazudo/zudo-doc/doc-history-area (epic #2344, S7).
4
4
  //
5
- // Mirrors the Phase B-1 pattern used by _footer-with-defaults.tsx: this
6
- // wrapper lives in pages/lib/ with a leading underscore so the zfb router
7
- // skips it as a page module, while the two doc-page modules
8
- // (docs/[...slug].tsx and [locale]/docs/[...slug].tsx) import it directly.
9
- // It gates on settings.docHistory, resolves the correct locale prop
10
- // (omitted for the default locale, matching the doc-history fetch-path
11
- // branch in src/components/doc-history.tsx), and passes the assembled
12
- // island into BodyFootUtilArea — restoring the
13
- // `<section aria-label="Document utilities">` landmark and its Revision
14
- // History heading in the SSG output for all zfb doc routes.
15
- //
16
- // Wave 8 (Path A — super-epic #1333 / child epic #1355): the doc-history
17
- // island is now built right here using zfb's native `<Island ssrFallback>`
18
- // API with the real DocHistory component imported from
19
- // `@/components/doc-history`. Previously this file passed
20
- // DocHistoryIslandProps to BodyFootUtilArea, which fed an SSR-skip
21
- // wrapper that did not import the real component — the orphan-component
22
- // bug that left the marker un-bundled. The host-side import here is the
23
- // page → real-component chain zfb's island scanner walks.
24
-
25
- import type { VNode } from "preact";
26
- import { Island } from "@takazudo/zfb";
5
+ // The DocHistory import is kept here so zfb's island scanner walks the chain:
6
+ // page stub DocHistory. The factory receives the constructor via deps.
27
7
  import { settings } from "@/config/settings";
28
8
  import { defaultLocale, t } from "@/config/i18n";
29
- import { BodyFootUtilArea } from "@takazudo/zudo-doc/body-foot-util";
30
- import { buildGitHubSourceUrl } from "@/utils/github";
31
- import { DocHistory } from "@/components/doc-history";
32
9
  import { toHistorySlug } from "@/utils/slug";
10
+ import { buildGitHubSourceUrl as _buildGitHubSourceUrl } from "@/utils/github";
11
+ import { createDocHistoryArea } from "@takazudo/zudo-doc/doc-history-area";
12
+ import { DocHistory } from "@takazudo/zudo-doc/doc-history";
33
13
  // SSR author + date metadata comes from `.zfb/doc-history-meta.json`, a
34
14
  // build-time manifest emitted by `scripts/zfb-prebuild.mjs` (step 2:
35
15
  // doc-history-meta) before `zfb build` runs. esbuild inlines the JSON
@@ -39,188 +19,16 @@ import { toHistorySlug } from "@/utils/slug";
39
19
  // because the zfb bundler builds pages from a shadow tree; relative paths
40
20
  // across the shadow boundary would resolve to the wrong location.
41
21
  import docHistoryMeta from "#doc-history-meta";
42
-
43
- // Set explicit `displayName` on the named-export DocHistory so zfb's
44
- // `captureComponentName` produces a stable marker even after the SSR
45
- // pipeline runs the component through a function-name-rewriting layer.
46
- // (DocHistory is `export function DocHistory(...)` — `name` is already
47
- // "DocHistory" but the explicit assignment is a guard for production
48
- // minification regressions, mirroring the BodyEndIslands helper.)
49
- (DocHistory as { displayName?: string }).displayName = "DocHistory";
50
-
51
- interface DocHistoryAreaProps {
52
- /** Page slug, e.g. "getting-started/intro". */
53
- slug: string;
54
- /** Active locale string, e.g. "en", "ja". */
55
- locale: string;
56
- /**
57
- * Raw zfb entry slug (relative path without extension), e.g.
58
- * "getting-started/intro" or "getting-started/index". Appended with
59
- * the source extension from the build-time manifest (".mdx" fallback)
60
- * to form the file path passed to buildGitHubSourceUrl.
61
- * Omit for auto-index pages (no underlying MDX file) — sourceUrl
62
- * will be suppressed automatically.
63
- */
64
- entrySlug?: string;
65
- /**
66
- * Content directory for the active locale, e.g. "src/content/docs"
67
- * or "src/content/docs-ja". Combined with entrySlug to build the
68
- * view-source GitHub URL. Omit to suppress the view-source link.
69
- */
70
- contentDir?: string;
71
- /**
72
- * True when this locale page falls back to the base EN collection
73
- * (i.e. the slug has no translation for the active locale). When true,
74
- * the history data-path derivations use defaultLocale so the island
75
- * fetches the correct bare-slug JSON and the SSR manifest lookup hits
76
- * the bare key — both of which only exist for EN-origin files.
77
- * Display labels (t() calls) still use the active locale so JA users
78
- * see JA labels on fallback pages. Omit (or false) for translated pages
79
- * and all other call sites (EN route, tag pages) — behavior unchanged.
80
- */
81
- isFallback?: boolean;
82
- }
83
-
84
- /**
85
- * Renders the `<BodyFootUtilArea>` shell with a doc-history island when
86
- * `settings.docHistory` is enabled. Returns null otherwise so no empty
87
- * landmark appears on pages where history is disabled.
88
- *
89
- * The locale prop is forwarded to the real DocHistory component only for
90
- * non-default locales — the history JSON server stores default-locale
91
- * files without a locale path segment (matching the fetch-path branch in
92
- * doc-history.tsx).
93
- *
94
- * When entrySlug + contentDir are both provided and settings.bodyFootUtilArea
95
- * has viewSourceLink enabled, computes sourceUrl via buildGitHubSourceUrl and
96
- * resolves the i18n label for the active locale — keeping the v2 component
97
- * oblivious to project settings (host-side computation, B-8-2).
98
- *
99
- * The SSR fallback for the doc-history island is built from git metadata
100
- * (author name, created/updated dates) so that static HTML contains the
101
- * author marker before JS hydration, visible to screen readers and crawlers.
102
- */
103
- export function DocHistoryArea({
104
- slug,
105
- locale,
106
- entrySlug,
107
- contentDir,
108
- isFallback,
109
- }: DocHistoryAreaProps): VNode | null {
110
- if (!settings.docHistory) return null;
111
-
112
- // Doc-history storage sentinel ("" -> "index"): a root index page has the
113
- // canonical route slug "" (→ /docs/), but doc-history JSON and the meta
114
- // manifest store/serve the root entry under "index" (an empty path segment
115
- // is unroutable — the server regex and the prebuild key composition both
116
- // reject ""). Apply the sentinel to the slug segment BEFORE locale
117
- // composition so root pages resolve to e.g. /doc-history/index.json and the
118
- // meta key "ja/index". See @/utils/slug `toHistorySlug` and the
119
- // collectContentFiles walk in packages/doc-history-server. (#1891)
120
- const historySlug = toHistorySlug(slug);
121
-
122
- // On EN-fallback locale pages the history data exists only at the bare
123
- // (non-locale-prefixed) path — the prebuild/server writes locale-prefixed
124
- // keys/paths only for files physically present in the locale collection.
125
- // Use defaultLocale for data lookups when isFallback is true; keep locale
126
- // for all display label calls (t()) so JA users see JA labels.
127
- const effectiveHistoryLocale = isFallback ? defaultLocale : locale;
128
-
129
- // Look up the build-time manifest entry for this page. The composedSlug
130
- // matches the key written by the prebuild step: bare slug for the default
131
- // locale, "<localeKey>/<slug>" for non-default locales.
132
- const composedSlug =
133
- effectiveHistoryLocale === defaultLocale ? historySlug : `${effectiveHistoryLocale}/${historySlug}`;
134
- type MetaEntry = {
135
- author: string;
136
- createdDate: string;
137
- updatedDate: string;
138
- /** Source file extension (".mdx" | ".md") — optional in older manifests. */
139
- ext?: string;
140
- };
141
- const meta = (docHistoryMeta as Record<string, MetaEntry>)[composedSlug];
142
-
143
- // Locale-aware labels for the SSR fallback.
144
- const createdLabel = t("doc.created", locale);
145
- const updatedLabel = t("doc.updated", locale);
146
- const historyLabel = t("doc.history", locale);
147
-
148
- // Real-component props — locale omitted for the default locale.
149
- // Use effectiveHistoryLocale so fallback pages fetch the bare (non-ja/) path.
150
- const docHistoryLocale = effectiveHistoryLocale === defaultLocale ? undefined : effectiveHistoryLocale;
151
- const docHistoryBasePath = settings.base ?? "/";
152
-
153
- // Build the SSR fallback with only the sr-only metadata block so the
154
- // author marker and Created/Updated labels are present in SSG output
155
- // before JS hydration, discoverable by screen readers and crawlers.
156
- // The visible "History" trigger button is NOT included here — DocHistory
157
- // renders its own trigger after hydration, and including one in the
158
- // ssrFallback as well caused a duplicate button in the DOM because
159
- // Preact's render() does not reliably remove static ssrFallback HTML
160
- // before mounting the new component output (same wrapper-self-Island
161
- // pattern fixed for Toc/Sidebar in commit 4014cdc).
162
- const author = meta?.author;
163
- const createdDate = meta?.createdDate;
164
- const updatedDate = meta?.updatedDate;
165
-
166
- // Explicit type annotation omitted: inferred JSX return is structurally
167
- // compatible with zfb's VNode (the ssrFallback prop target). Preact's
168
- // VNode<{}> generic form is not directly assignable to zfb's VNode at the
169
- // type level even though the runtime shapes are identical.
170
- const fallback = (
171
- <div class="sr-only">
172
- {author && <span>{author}</span>}
173
- <span>
174
- {createdLabel}
175
- {createdDate ? `: ${createdDate}` : ""}
176
- </span>
177
- <span>
178
- {updatedLabel}
179
- {updatedDate ? `: ${updatedDate}` : ""}
180
- </span>
181
- </div>
182
- );
183
-
184
- // Compose the SSR-skip island with zfb's native `<Island ssrFallback>` API.
185
- // The page → this file → real DocHistory import chain is what the scanner
186
- // walks; the marker emitted is "DocHistory" via captureComponentName.
187
- const docHistoryIsland = Island({
188
- when: "idle",
189
- ssrFallback: fallback,
190
- children: (
191
- <DocHistory
192
- slug={historySlug}
193
- locale={docHistoryLocale}
194
- basePath={docHistoryBasePath}
195
- />
196
- ),
197
- }) as unknown as VNode;
198
-
199
- // Compute the view-source GitHub URL host-side so the v2 BodyFootUtilArea
200
- // component stays oblivious to project settings. Gate on
201
- // bodyFootUtilArea.viewSourceLink, and require both entrySlug and contentDir
202
- // (auto-index pages pass neither). The real source extension comes from the
203
- // build-time manifest (`ext`, written by pre-build.ts) — the content walkers
204
- // accept both .mdx and .md, so hardcoding ".mdx" produced broken view-source
205
- // URLs for .md pages. ".mdx" remains the fallback for entries without a
206
- // manifest record (untracked files, SKIP_DOC_HISTORY=1, stale manifests).
207
- const utilSettings = settings.bodyFootUtilArea;
208
- const sourceExt = meta?.ext ?? ".mdx";
209
- const sourceUrl =
210
- utilSettings && utilSettings.viewSourceLink && entrySlug && contentDir
211
- ? buildGitHubSourceUrl(contentDir, entrySlug + sourceExt)
212
- : null;
213
-
214
- // Resolve the i18n label host-side; pass the result so the v2 component
215
- // stays framework-agnostic. Falls back to the EN default when locale has
216
- // no translation (see DEFAULT_VIEW_SOURCE_LABEL in the v2 package).
217
- const viewSourceLabel = t("doc.viewSource", locale);
218
-
219
- return (
220
- <BodyFootUtilArea
221
- docHistoryIsland={docHistoryIsland}
222
- sourceUrl={sourceUrl}
223
- viewSourceLabel={viewSourceLabel}
224
- />
225
- );
226
- }
22
+ import type { DocHistoryAreaProps } from "@takazudo/zudo-doc/doc-history-area";
23
+
24
+ export type { DocHistoryAreaProps };
25
+
26
+ export const DocHistoryArea = createDocHistoryArea({
27
+ settings,
28
+ defaultLocale,
29
+ docHistoryMeta: docHistoryMeta as Record<string, { author: string; createdDate: string; updatedDate: string; ext?: string }>,
30
+ t,
31
+ toHistorySlug,
32
+ buildGitHubSourceUrl: (contentDir: string, entryId: string) => _buildGitHubSourceUrl(contentDir, entryId),
33
+ DocHistory,
34
+ });
@@ -1,31 +1,10 @@
1
1
  /** @jsxRuntime automatic */
2
2
  /** @jsxImportSource preact */
3
- // Locale-aware DocMetainfo area wrapper for the zfb doc pages.
4
- //
5
- // Renders the visible date block (created / updated dates + author)
6
- // between the article <h1> and the description paragraph (doc-metainfo
7
- // placement — between <h1> and description).
8
- //
9
- // Data source: `.zfb/doc-history-meta.json`, a build-time manifest
10
- // emitted by `scripts/zfb-prebuild.mjs` before `zfb build` runs.
11
- // esbuild inlines the JSON statically so no Node.js `fs` code reaches
12
- // the client bundle — the same approach used by `_doc-history-area.tsx`
13
- // (b11-2 pattern).
14
- //
15
- // Date formatting uses Intl.DateTimeFormat (browser-safe). We do NOT
16
- // import the old `formatDate` from `src/utils/git-info.ts` — that module
17
- // carried top-level Node.js imports (`execFileSync`, `existsSync`) that
18
- // would be dragged into the client bundle (the B-11 lesson). That file
19
- // was removed in S1 cleanup (#1928); the mirror below is the canonical copy.
20
- //
21
- // Labels are resolved from the project's i18n table so non-default
22
- // locales (e.g. /ja/) get translated "作成" / "更新" strings.
23
-
24
- import type { VNode } from "preact";
3
+ // Host thin-stub see @takazudo/zudo-doc/doc-metainfo-area (epic #2344, S7).
25
4
  import { settings } from "@/config/settings";
26
5
  import { defaultLocale, t } from "@/config/i18n";
27
- import { DocMetainfo } from "@takazudo/zudo-doc/metainfo";
28
6
  import { toHistorySlug } from "@/utils/slug";
7
+ import { createDocMetainfoArea } from "@takazudo/zudo-doc/doc-metainfo-area";
29
8
  // SSR author + date metadata comes from `.zfb/doc-history-meta.json`, a
30
9
  // build-time manifest emitted by `scripts/zfb-prebuild.mjs` (step 2:
31
10
  // doc-history-meta) before `zfb build` runs. esbuild inlines the JSON
@@ -36,94 +15,12 @@ import { toHistorySlug } from "@/utils/slug";
36
15
  // across the shadow boundary would resolve to the wrong location.
37
16
  import docHistoryMeta from "#doc-history-meta";
38
17
 
39
- // BCP-47 locale tag mapping used by Intl.DateTimeFormat.
40
- // Originally mirrored from `src/utils/git-info.ts` (removed in S1 #1928).
41
- // The formatDate function below is the stable copy; kept in sync manually.
42
- const LOCALE_TO_BCP47: Record<string, string> = {
43
- en: "en-US",
44
- ja: "ja-JP",
45
- de: "de-DE",
46
- };
47
-
48
- /** Format an ISO date string for display, respecting the active locale. */
49
- function formatDate(isoDate: string, locale: string): string {
50
- const d = new Date(isoDate);
51
- if (isNaN(d.getTime())) return isoDate;
52
- return d.toLocaleDateString(LOCALE_TO_BCP47[locale] ?? "en-US", {
53
- year: "numeric",
54
- month: "short",
55
- day: "numeric",
56
- });
57
- }
58
-
59
- interface DocMetainfoAreaProps {
60
- /** Page slug, e.g. "getting-started/intro". */
61
- slug: string;
62
- /** Active locale string, e.g. "en", "ja". */
63
- locale: string;
64
- /**
65
- * True when this locale page falls back to the base EN collection
66
- * (i.e. the slug has no translation for the active locale). When true,
67
- * the manifest lookup uses defaultLocale so the visible block resolves
68
- * the bare-slug key — the only key that exists for EN-origin files —
69
- * matching the dropdown's `effectiveHistoryLocale` derivation in
70
- * _doc-history-area.tsx. Display formatting (dates + labels) still uses
71
- * the active locale so JA users see JA formatting on fallback pages.
72
- */
73
- isFallback?: boolean;
74
- }
75
-
76
- /**
77
- * Renders the visible date block (Created / Updated / Author) when
78
- * `settings.docMetainfo` is enabled and the build-time manifest has an
79
- * entry for the active page.
80
- *
81
- * Returns null when `docMetainfo` is disabled, the page is untracked
82
- * (no manifest entry), or the manifest was generated in a shallow clone
83
- * (`SKIP_DOC_HISTORY=1` → empty JSON).
84
- *
85
- * The component is intentionally server-render-only: it emits static
86
- * HTML from build-time data and has no client JS footprint. It sits
87
- * between `<h1>` and the description `<p>` (doc-metainfo placement).
88
- */
89
- export function DocMetainfoArea({ slug, locale, isFallback }: DocMetainfoAreaProps): VNode | null {
90
- if (!settings.docMetainfo) return null;
91
-
92
- // Doc-history storage sentinel ("" -> "index"): a root index page has the
93
- // canonical route slug "" (→ /docs/), but the prebuild keys the root entry
94
- // under "index" (collectContentFiles keeps the bare root; an empty path
95
- // segment is unroutable). Apply the sentinel BEFORE locale composition so
96
- // the visible Created/Updated/Author block resolves for a root page — see
97
- // @/utils/slug `toHistorySlug` and _doc-history-area.tsx. (#1891)
98
- const historySlug = toHistorySlug(slug);
99
-
100
- // On EN-fallback locale pages the manifest only has the bare
101
- // (non-locale-prefixed) key — the prebuild writes locale-prefixed keys
102
- // only for files physically present in the locale collection. Use
103
- // defaultLocale for the data lookup when isFallback is true, mirroring
104
- // `effectiveHistoryLocale` in _doc-history-area.tsx so the visible block
105
- // and the dropdown agree. Display formatting keeps the active locale.
106
- const effectiveHistoryLocale = isFallback ? defaultLocale : locale;
107
-
108
- // Key format: bare slug for default locale, "<locale>/<slug>" for others.
109
- // Matches the prebuild step's composedSlug logic (pre-build.ts).
110
- const composedSlug =
111
- effectiveHistoryLocale === defaultLocale
112
- ? historySlug
113
- : `${effectiveHistoryLocale}/${historySlug}`;
114
-
115
- type MetaEntry = { author: string; createdDate: string; updatedDate: string };
116
- const meta = (docHistoryMeta as Record<string, MetaEntry>)[composedSlug];
117
-
118
- if (!meta) return null;
18
+ export type { DocMetainfoAreaProps } from "@takazudo/zudo-doc/doc-metainfo-area";
119
19
 
120
- return (
121
- <DocMetainfo
122
- createdAt={meta.createdDate ? formatDate(meta.createdDate, locale) : null}
123
- updatedAt={meta.updatedDate ? formatDate(meta.updatedDate, locale) : null}
124
- author={meta.author || null}
125
- createdLabel={t("doc.created", locale)}
126
- updatedLabel={t("doc.updated", locale)}
127
- />
128
- );
129
- }
20
+ export const DocMetainfoArea = createDocMetainfoArea({
21
+ settings,
22
+ defaultLocale,
23
+ docHistoryMeta: docHistoryMeta as Record<string, { author: string; createdDate: string; updatedDate: string }>,
24
+ t,
25
+ toHistorySlug,
26
+ });
@@ -1,192 +1,31 @@
1
1
  /** @jsxRuntime automatic */
2
2
  /** @jsxImportSource preact */
3
- // Shared page renderer for the 4 doc catch-all routes.
4
- //
5
- // Extracted (#2010) from the near-identical default components of:
6
- // pages/docs/[[...slug]].tsx
7
- // pages/[locale]/docs/[[...slug]].tsx
8
- // pages/v/[version]/docs/[[...slug]].tsx
9
- // pages/v/[version]/[locale]/docs/[[...slug]].tsx
10
- //
11
- // Each route's default export stays a thin adapter that reads its params /
12
- // route-specific props (locale, version, contentDir, isFallback) and
13
- // delegates here. Route-specific behavior is parameterized:
14
- // - `version` present → versioned chrome: versioned canonical URL, version
15
- // banner, version-aware switcher, auto-index child hrefs kept as the
16
- // pre-remapped versioned hrefs from paths() (#1916 #2), and doc history
17
- // hidden until versioned history is supported (#1916 #5).
18
- // - `version` absent → latest chrome: docsUrl canonical, child hrefs fall
19
- // back to the nav node's own docsUrl, doc history rendered for listed
20
- // entries via `docHistoryContentDir`.
21
-
22
- import { settings } from "@/config/settings";
23
- import type { VersionConfig } from "@/config/settings";
24
- import { t, type Locale } from "@/config/i18n";
3
+ // Host thin-stub see @takazudo/zudo-doc/doc-page-renderer (epic #2344, S7).
4
+ import { t } from "@/config/i18n";
25
5
  import { docsUrl, versionedDocsUrl, absoluteUrl } from "@/utils/base";
26
- import type { NavNode } from "@/utils/docs";
27
6
  import { getNavSectionForSlug } from "@/utils/nav-scope";
28
7
  import { toRouteSlug } from "@/utils/slug";
29
- import type { JSX } from "preact";
30
- // Shared MDX-tag → Preact-component bag. Includes htmlOverrides
31
- // (native typography), HtmlPreviewWrapper (Island), and stub bindings
32
- // for every other custom tag the MDX corpus references — see
33
- // `pages/_mdx-components.ts` for the full list and rationale.
34
8
  import { createMdxComponents } from "../_mdx-components";
35
- import type { DocPageBaseProps } from "./doc-page-props";
36
- import { DocHistoryArea } from "./_doc-history-area";
37
- import { DocMetainfoArea } from "./_doc-metainfo-area";
9
+ import { createRenderDocPage } from "@takazudo/zudo-doc/doc-page-renderer";
38
10
  import { buildInlineVersionSwitcher } from "./_inline-version-switcher";
39
- import { DocContentHeader } from "./_doc-content-header";
40
11
  import { DocPageShell } from "./_doc-page-shell";
12
+ import { DocContentHeader } from "./_doc-content-header";
13
+ import { DocMetainfoArea } from "./_doc-metainfo-area";
14
+ import { DocHistoryArea } from "./_doc-history-area";
41
15
 
42
- export interface RenderDocPageOptions {
43
- /** Active locale — drives nav wrappers, labels, and URL building. */
44
- locale: Locale;
45
- /** Version config when rendering a versioned route; undefined = latest. */
46
- version?: VersionConfig;
47
- /** True when this page falls back to the base EN collection (locale
48
- * routes). Drives the fallback notice + history-area hint. */
49
- isFallback?: boolean;
50
- /**
51
- * Content directory for the doc-history view-source link (e.g. the active
52
- * locale's dir, or the base docsDir for EN/fallback pages). Latest routes
53
- * pass it; versioned routes omit it — doc history is hidden on versioned
54
- * pages regardless (#1916 #5).
55
- */
56
- docHistoryContentDir?: string;
57
- }
58
-
59
- export function renderDocPage(
60
- props: DocPageBaseProps,
61
- opts: RenderDocPageOptions,
62
- ): JSX.Element {
63
- const { breadcrumbs, prev, next, headings } = props;
64
- const { locale, version, isFallback } = opts;
65
-
66
- const slug = props.kind === "autoIndex"
67
- ? props.autoIndex.slug
68
- : (props.entry.data.slug ?? toRouteSlug(props.entry.slug));
69
-
70
- const title = props.kind === "autoIndex" ? props.autoIndex.label : props.entry.data.title;
71
- const description = props.kind === "autoIndex" ? props.autoIndex.description : props.entry.data.description;
72
-
73
- // Locale-aware components bag — creates nav wrappers bound to the active
74
- // locale so CategoryNav/CategoryTreeNav/SiteTreeNav query the right collection.
75
- const components = createMdxComponents(locale);
76
-
77
- // Resolve child hrefs for auto-index pages. Versioned routes: child cards
78
- // already carry versioned hrefs from paths() (#1916 #2) — just filter to
79
- // renderable nodes. Latest routes: keep the nav node's own docsUrl href
80
- // (fallback for a noPage parent without an href).
81
- const autoIndexChildren = props.kind === "autoIndex"
82
- ? version
83
- ? props.autoIndex.children.filter((c: NavNode) => c.hasPage || c.children.length > 0)
84
- : props.autoIndex.children
85
- .filter((c: NavNode) => c.hasPage || c.children.length > 0)
86
- .map((c: NavNode) => ({
87
- ...c,
88
- href: c.href ?? docsUrl(c.slug, locale),
89
- }))
90
- : [];
91
-
92
- // Version banner: drives the `<VersionBanner>` element inside
93
- // DocLayoutWithDefaults when `version.banner` is "unmaintained" or
94
- // "unreleased". The banner links out to the latest version of the
95
- // current page (slug-preserving — strips the /v/{version}/ prefix,
96
- // keeps the /{locale}/ locale prefix).
97
- const versionBannerType = version?.banner ? version.banner : undefined;
98
- const versionBannerLatestUrl = versionBannerType
99
- ? docsUrl(slug, locale)
100
- : undefined;
101
- const versionBannerLabels = versionBannerType
102
- ? {
103
- message:
104
- versionBannerType === "unmaintained"
105
- ? t("version.banner.unmaintained", locale)
106
- : t("version.banner.unreleased", locale),
107
- latestLink: t("version.banner.latestLink", locale),
108
- }
109
- : undefined;
110
-
111
- // Canonical URL — base-prefixed page path, absolutized against siteUrl.
112
- // Versioned pages use the versioned URL as canonical.
113
- const currentPath = version
114
- ? versionedDocsUrl(slug, version.slug, locale)
115
- : docsUrl(slug, locale);
116
- const canonical = absoluteUrl(currentPath);
117
-
118
- // Persist key: locale + nav-section so the sidebar DOM node is reused
119
- // across same-locale + same-section navigations only. No sanitizer needed —
120
- // both lang (BCP-47 locale string) and navSection (filesystem-derived
121
- // kebab-case slug) come from controlled, trusted sources.
122
- const navSection = getNavSectionForSlug(slug);
123
- const hideSidebar = props.kind === "entry" ? props.entry.data.hide_sidebar : undefined;
124
- const sidebarPersistKey = hideSidebar
125
- ? undefined
126
- : `sidebar-${locale}-${navSection ?? "default"}`;
127
-
128
- return (
129
- <DocPageShell
130
- kind={props.kind}
131
- locale={locale}
132
- slug={slug}
133
- title={title}
134
- description={description}
135
- canonical={canonical}
136
- breadcrumbs={breadcrumbs}
137
- prev={prev}
138
- next={next}
139
- headings={headings}
140
- navSection={navSection}
141
- sidebarPersistKey={sidebarPersistKey}
142
- hideSidebar={hideSidebar}
143
- hideToc={props.kind === "entry" ? props.entry.data.hide_toc : undefined}
144
- currentPath={currentPath}
145
- currentVersion={version?.slug}
146
- versionSwitcher={buildInlineVersionSwitcher(slug, locale, version?.slug)}
147
- versionBanner={versionBannerType}
148
- versionBannerLatestUrl={versionBannerLatestUrl}
149
- versionBannerLabels={versionBannerLabels}
150
- autoIndexLabel={props.kind === "autoIndex" ? props.autoIndex.label : undefined}
151
- autoIndexChildren={autoIndexChildren}
152
- metainfoSlot={
153
- // Versioned gate mirrors DocContentHeader: the doc-history-meta
154
- // manifest is built from latest dirs only, so a bare versioned slug
155
- // would surface the LATEST page's Created/Updated/Author.
156
- !version && props.kind === "autoIndex" ? (
157
- <DocMetainfoArea slug={slug} locale={locale} isFallback={isFallback} />
158
- ) : null
159
- }
160
- contentHeaderSlot={
161
- props.kind === "entry" ? (
162
- <DocContentHeader
163
- entry={props.entry}
164
- slug={slug}
165
- locale={locale}
166
- isFallback={isFallback}
167
- version={version?.slug}
168
- />
169
- ) : undefined
170
- }
171
- contentSlot={
172
- props.kind === "entry" ? <props.entry.Content components={components} /> : undefined
173
- }
174
- docHistorySlot={
175
- // #1916 #5: doc-history hidden on versioned pages until versioned
176
- // history is supported.
177
- !version &&
178
- opts.docHistoryContentDir !== undefined &&
179
- props.kind === "entry" &&
180
- !props.entry.data.unlisted ? (
181
- <DocHistoryArea
182
- slug={slug}
183
- locale={locale}
184
- entrySlug={props.entry.slug}
185
- contentDir={opts.docHistoryContentDir}
186
- isFallback={isFallback}
187
- />
188
- ) : null
189
- }
190
- />
191
- );
192
- }
16
+ export type { RenderDocPageOptions } from "@takazudo/zudo-doc/doc-page-renderer";
17
+
18
+ export const renderDocPage = createRenderDocPage({
19
+ docsUrl,
20
+ versionedDocsUrl,
21
+ absoluteUrl,
22
+ getNavSectionForSlug,
23
+ toRouteSlug,
24
+ createMdxComponents,
25
+ t,
26
+ buildInlineVersionSwitcher,
27
+ DocPageShell,
28
+ DocContentHeader,
29
+ DocMetainfoArea,
30
+ DocHistoryArea,
31
+ });