create-zudo-doc 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +146 -0
  3. package/bin/create-zudo-doc.js +2 -0
  4. package/dist/api.d.ts +20 -0
  5. package/dist/api.js +13 -0
  6. package/dist/claude-md-gen.d.ts +2 -0
  7. package/dist/claude-md-gen.js +113 -0
  8. package/dist/cli.d.ts +39 -0
  9. package/dist/cli.js +157 -0
  10. package/dist/compose.d.ts +95 -0
  11. package/dist/compose.js +206 -0
  12. package/dist/constants.d.ts +20 -0
  13. package/dist/constants.js +224 -0
  14. package/dist/features/body-foot-util.d.ts +10 -0
  15. package/dist/features/body-foot-util.js +12 -0
  16. package/dist/features/claude-resources.d.ts +2 -0
  17. package/dist/features/claude-resources.js +6 -0
  18. package/dist/features/design-token-panel.d.ts +14 -0
  19. package/dist/features/design-token-panel.js +27 -0
  20. package/dist/features/doc-history.d.ts +9 -0
  21. package/dist/features/doc-history.js +11 -0
  22. package/dist/features/doc-tags.d.ts +19 -0
  23. package/dist/features/doc-tags.js +33 -0
  24. package/dist/features/footer-taglist.d.ts +14 -0
  25. package/dist/features/footer-taglist.js +17 -0
  26. package/dist/features/footer.d.ts +8 -0
  27. package/dist/features/footer.js +10 -0
  28. package/dist/features/i18n.d.ts +22 -0
  29. package/dist/features/i18n.js +41 -0
  30. package/dist/features/image-enlarge.d.ts +11 -0
  31. package/dist/features/image-enlarge.js +13 -0
  32. package/dist/features/index.d.ts +15 -0
  33. package/dist/features/index.js +53 -0
  34. package/dist/features/llms-txt.d.ts +11 -0
  35. package/dist/features/llms-txt.js +13 -0
  36. package/dist/features/search.d.ts +9 -0
  37. package/dist/features/search.js +11 -0
  38. package/dist/features/sidebar-resizer.d.ts +14 -0
  39. package/dist/features/sidebar-resizer.js +16 -0
  40. package/dist/features/sidebar-toggle.d.ts +13 -0
  41. package/dist/features/sidebar-toggle.js +15 -0
  42. package/dist/features/tag-governance.d.ts +14 -0
  43. package/dist/features/tag-governance.js +16 -0
  44. package/dist/features/tauri-dev.d.ts +2 -0
  45. package/dist/features/tauri-dev.js +25 -0
  46. package/dist/features/tauri.d.ts +11 -0
  47. package/dist/features/tauri.js +52 -0
  48. package/dist/features/versioning.d.ts +27 -0
  49. package/dist/features/versioning.js +43 -0
  50. package/dist/index.d.ts +1 -0
  51. package/dist/index.js +150 -0
  52. package/dist/preset.d.ts +37 -0
  53. package/dist/preset.js +156 -0
  54. package/dist/prompts.d.ts +32 -0
  55. package/dist/prompts.js +248 -0
  56. package/dist/scaffold.d.ts +4 -0
  57. package/dist/scaffold.js +344 -0
  58. package/dist/settings-gen.d.ts +2 -0
  59. package/dist/settings-gen.js +237 -0
  60. package/dist/utils.d.ts +8 -0
  61. package/dist/utils.js +34 -0
  62. package/dist/zfb-config-gen.d.ts +19 -0
  63. package/dist/zfb-config-gen.js +222 -0
  64. package/package.json +65 -0
  65. package/templates/base/.htmlvalidate.json +5 -0
  66. package/templates/base/.zfb/doc-history-meta.json +1 -0
  67. package/templates/base/pages/404.tsx +55 -0
  68. package/templates/base/pages/_data.ts +179 -0
  69. package/templates/base/pages/_mdx-components.ts +249 -0
  70. package/templates/base/pages/docs/[...slug].tsx +448 -0
  71. package/templates/base/pages/index.tsx +158 -0
  72. package/templates/base/pages/lib/_body-end-islands.tsx +201 -0
  73. package/templates/base/pages/lib/_category-nav.tsx +148 -0
  74. package/templates/base/pages/lib/_category-tree-nav.tsx +104 -0
  75. package/templates/base/pages/lib/_compose-meta-title.ts +29 -0
  76. package/templates/base/pages/lib/_details.tsx +30 -0
  77. package/templates/base/pages/lib/_doc-history-area.tsx +178 -0
  78. package/templates/base/pages/lib/_doc-metainfo-area.tsx +100 -0
  79. package/templates/base/pages/lib/_doc-tags-area.tsx +89 -0
  80. package/templates/base/pages/lib/_extract-headings.ts +81 -0
  81. package/templates/base/pages/lib/_footer-with-defaults.tsx +234 -0
  82. package/templates/base/pages/lib/_frontmatter-preview-data.ts +53 -0
  83. package/templates/base/pages/lib/_head-with-defaults.tsx +113 -0
  84. package/templates/base/pages/lib/_header-with-defaults.tsx +386 -0
  85. package/templates/base/pages/lib/_inline-version-switcher.tsx +84 -0
  86. package/templates/base/pages/lib/_math-block.tsx +63 -0
  87. package/templates/base/pages/lib/_nav-source-docs.ts +68 -0
  88. package/templates/base/pages/lib/_preset-generator.tsx +81 -0
  89. package/templates/base/pages/lib/_search-widget-script.ts +388 -0
  90. package/templates/base/pages/lib/_search-widget.tsx +196 -0
  91. package/templates/base/pages/lib/_sidebar-with-defaults.tsx +176 -0
  92. package/templates/base/pages/lib/_site-tree-nav.tsx +128 -0
  93. package/templates/base/pages/lib/locale-merge.ts +58 -0
  94. package/templates/base/pages/lib/route-enumerators.ts +302 -0
  95. package/templates/base/pages/sitemap.xml.tsx +51 -0
  96. package/templates/base/plugins/connect-adapter.mjs +144 -0
  97. package/templates/base/plugins/copy-public-plugin.mjs +50 -0
  98. package/templates/base/plugins/search-index-plugin.mjs +54 -0
  99. package/templates/base/scripts/run-b4push.sh +102 -0
  100. package/templates/base/src/components/ai-chat-modal.tsx +15 -0
  101. package/templates/base/src/components/client-router-bootstrap.tsx +14 -0
  102. package/templates/base/src/components/content/component-map.ts +25 -0
  103. package/templates/base/src/components/content/content-blockquote.tsx +16 -0
  104. package/templates/base/src/components/content/content-code.tsx +117 -0
  105. package/templates/base/src/components/content/content-link.tsx +83 -0
  106. package/templates/base/src/components/content/content-ol.tsx +19 -0
  107. package/templates/base/src/components/content/content-paragraph.tsx +10 -0
  108. package/templates/base/src/components/content/content-strong.tsx +16 -0
  109. package/templates/base/src/components/content/content-table.tsx +18 -0
  110. package/templates/base/src/components/content/content-ul.tsx +18 -0
  111. package/templates/base/src/components/content/heading-h2.tsx +26 -0
  112. package/templates/base/src/components/content/heading-h3.tsx +26 -0
  113. package/templates/base/src/components/content/heading-h4.tsx +26 -0
  114. package/templates/base/src/components/design-token-panel-bootstrap.tsx +15 -0
  115. package/templates/base/src/components/desktop-sidebar-toggle.tsx +15 -0
  116. package/templates/base/src/components/doc-history.tsx +18 -0
  117. package/templates/base/src/components/html-preview/highlighted-code.tsx +74 -0
  118. package/templates/base/src/components/html-preview/html-preview.tsx +108 -0
  119. package/templates/base/src/components/html-preview/preflight.ts +112 -0
  120. package/templates/base/src/components/html-preview/preview-base.tsx +159 -0
  121. package/templates/base/src/components/image-enlarge.tsx +19 -0
  122. package/templates/base/src/components/mobile-toc.tsx +94 -0
  123. package/templates/base/src/components/preset-generator.tsx +14 -0
  124. package/templates/base/src/components/sidebar-toggle.tsx +98 -0
  125. package/templates/base/src/components/sidebar-tree.tsx +543 -0
  126. package/templates/base/src/components/site-tree-nav.tsx +233 -0
  127. package/templates/base/src/components/theme-toggle.tsx +93 -0
  128. package/templates/base/src/components/toc.tsx +63 -0
  129. package/templates/base/src/components/tree-nav-shared.tsx +71 -0
  130. package/templates/base/src/config/color-scheme-utils.ts +182 -0
  131. package/templates/base/src/config/color-schemes.ts +128 -0
  132. package/templates/base/src/config/frontmatter-preview-defaults.ts +24 -0
  133. package/templates/base/src/config/frontmatter-preview-renderers.tsx +46 -0
  134. package/templates/base/src/config/i18n.ts +225 -0
  135. package/templates/base/src/config/settings-types.ts +162 -0
  136. package/templates/base/src/config/sidebars.ts +66 -0
  137. package/templates/base/src/config/tag-vocabulary-types.ts +39 -0
  138. package/templates/base/src/config/tag-vocabulary.ts +20 -0
  139. package/templates/base/src/hooks/use-active-heading.ts +133 -0
  140. package/templates/base/src/plugins/docs-source-map.ts +103 -0
  141. package/templates/base/src/plugins/hast-utils.ts +10 -0
  142. package/templates/base/src/plugins/rehype-code-title.ts +50 -0
  143. package/templates/base/src/plugins/rehype-heading-links.ts +53 -0
  144. package/templates/base/src/plugins/rehype-image-enlarge.ts +113 -0
  145. package/templates/base/src/plugins/rehype-mermaid.ts +41 -0
  146. package/templates/base/src/plugins/rehype-strip-md-extension.ts +58 -0
  147. package/templates/base/src/plugins/remark-admonitions.ts +99 -0
  148. package/templates/base/src/plugins/remark-resolve-markdown-links.ts +127 -0
  149. package/templates/base/src/plugins/url-utils.ts +4 -0
  150. package/templates/base/src/styles/global.css +1066 -0
  151. package/templates/base/src/types/docs-entry.ts +39 -0
  152. package/templates/base/src/types/heading.ts +5 -0
  153. package/templates/base/src/types/locale.ts +10 -0
  154. package/templates/base/src/utils/base.ts +139 -0
  155. package/templates/base/src/utils/content-files.ts +106 -0
  156. package/templates/base/src/utils/dedent.ts +24 -0
  157. package/templates/base/src/utils/docs.ts +335 -0
  158. package/templates/base/src/utils/git-info.ts +70 -0
  159. package/templates/base/src/utils/github.ts +19 -0
  160. package/templates/base/src/utils/header-right-items.ts +38 -0
  161. package/templates/base/src/utils/nav-scope.ts +63 -0
  162. package/templates/base/src/utils/sidebar.ts +104 -0
  163. package/templates/base/src/utils/slug.ts +10 -0
  164. package/templates/base/src/utils/smart-break.tsx +126 -0
  165. package/templates/base/src/utils/tags.ts +126 -0
  166. package/templates/base/tsconfig.json +36 -0
  167. package/templates/features/bodyFootUtil/files/src/utils/github.ts +19 -0
  168. package/templates/features/claudeResources/files/plugins/claude-resources-plugin.mjs +137 -0
  169. package/templates/features/claudeResources/files/src/integrations/claude-resources/__tests__/escape-for-mdx.test.ts +34 -0
  170. package/templates/features/claudeResources/files/src/integrations/claude-resources/__tests__/generate.test.ts +376 -0
  171. package/templates/features/claudeResources/files/src/integrations/claude-resources/escape-for-mdx.ts +93 -0
  172. package/templates/features/claudeResources/files/src/integrations/claude-resources/generate.ts +586 -0
  173. package/templates/features/designTokenPanel/files/src/components/design-token-panel-bootstrap.tsx +15 -0
  174. package/templates/features/designTokenPanel/files/src/config/design-token-panel-config.ts +99 -0
  175. package/templates/features/designTokenPanel/files/src/config/design-tokens-manifest.ts +177 -0
  176. package/templates/features/designTokenPanel/files/src/lib/design-token-panel-bootstrap.ts +50 -0
  177. package/templates/features/docHistory/files/plugins/doc-history-plugin.mjs +99 -0
  178. package/templates/features/docHistory/files/src/components/doc-history.tsx +598 -0
  179. package/templates/features/docHistory/files/src/types/doc-history.ts +23 -0
  180. package/templates/features/docHistory/files/src/utils/doc-history.ts +180 -0
  181. package/templates/features/docTags/files/pages/[locale]/docs/tags/[tag].tsx +116 -0
  182. package/templates/features/docTags/files/pages/[locale]/docs/tags/index.tsx +99 -0
  183. package/templates/features/docTags/files/pages/docs/tags/[tag].tsx +101 -0
  184. package/templates/features/docTags/files/pages/docs/tags/index.tsx +86 -0
  185. package/templates/features/i18n/files/pages/[locale]/docs/[...slug].tsx +467 -0
  186. package/templates/features/i18n/files/pages/[locale]/index.tsx +213 -0
  187. package/templates/features/imageEnlarge/files/src/components/image-enlarge.tsx +248 -0
  188. package/templates/features/llmsTxt/files/plugins/llms-txt-plugin.mjs +74 -0
  189. package/templates/features/sidebarResizer/files/src/scripts/sidebar-resizer.ts +185 -0
  190. package/templates/features/sidebarToggle/files/src/components/desktop-sidebar-toggle.tsx +126 -0
  191. package/templates/features/tagGovernance/files/scripts/tags-audit.ts +576 -0
  192. package/templates/features/tagGovernance/files/scripts/tags-suggest.ts +428 -0
  193. package/templates/features/tauri/files/src/components/find-bar.tsx +122 -0
  194. package/templates/features/tauri/files/src/components/find-in-page-init.tsx +53 -0
  195. package/templates/features/tauri/files/src/utils/find-in-page.ts +175 -0
  196. package/templates/features/tauri/files/src-tauri/Cargo.toml +14 -0
  197. package/templates/features/tauri/files/src-tauri/build.rs +3 -0
  198. package/templates/features/tauri/files/src-tauri/capabilities/default.json +11 -0
  199. package/templates/features/tauri/files/src-tauri/src/main.rs +250 -0
  200. package/templates/features/tauri/files/src-tauri/tauri.conf.json +25 -0
  201. package/templates/features/tauriDev/files/src-tauri-dev/Cargo.toml +15 -0
  202. package/templates/features/tauriDev/files/src-tauri-dev/build.rs +3 -0
  203. package/templates/features/tauriDev/files/src-tauri-dev/capabilities/default.json +7 -0
  204. package/templates/features/tauriDev/files/src-tauri-dev/frontend/index.html +187 -0
  205. package/templates/features/tauriDev/files/src-tauri-dev/icons/icon.png +0 -0
  206. package/templates/features/tauriDev/files/src-tauri-dev/src/main.rs +995 -0
  207. package/templates/features/tauriDev/files/src-tauri-dev/tauri.conf.json +22 -0
  208. package/templates/features/tauriDev/files/src-tauri-dev/test-launch.sh +65 -0
  209. package/templates/features/versioning/files/pages/[locale]/docs/versions.tsx +100 -0
  210. package/templates/features/versioning/files/pages/docs/versions.tsx +78 -0
  211. package/templates/features/versioning/files/pages/v/[version]/docs/[...slug].tsx +451 -0
  212. package/templates/features/versioning/files/pages/v/[version]/ja/docs/[...slug].tsx +490 -0
@@ -0,0 +1,249 @@
1
+ // Shared MDX-component bag used by every doc-route page that renders
2
+ // `<entry.Content components={...} />`.
3
+ //
4
+ // ## Why a shared helper
5
+ //
6
+ // Pre-S4e the page-side `components` map only carried `htmlOverrides` plus
7
+ // `HtmlPreview`, because the zfb content bridge wasn't installed and every
8
+ // `<entry.Content>` call took the raw-markdown `<pre data-zfb-content-fallback>`
9
+ // path. Now that the bridge IS installed (zudo-doc#506), the compiled
10
+ // MDXContent functions fire for every entry — and the MDX emitter wraps
11
+ // every named-tag access with:
12
+ //
13
+ // const CategoryNav2 = _components.CategoryNav ?? components.CategoryNav;
14
+ // if (!CategoryNav2) throw new Error("MDX requires `CategoryNav` to be passed via the `components` prop");
15
+ //
16
+ // So any tag the MDX corpus uses but the page omits → 500 at render time.
17
+ //
18
+ // ## Strategy
19
+ //
20
+ // This module ships stub bindings for tags not yet ported to `@takazudo/zudo-doc`
21
+ // (render nothing), and real Preact bindings for tags whose ports are complete.
22
+ // As real components land, they replace their stub here and propagate to every page automatically.
23
+ //
24
+ // `htmlOverrides` (basic typography — h2/h3/h4/p/a/ul/ol/blockquote/strong/table)
25
+ // and `HtmlPreview: HtmlPreviewWrapper` (Island wrapper) stay in their
26
+ // non-stub form because their Preact bindings already exist.
27
+ //
28
+ // ## Locale-aware bindings (createMdxComponents factory)
29
+ //
30
+ // CategoryNav, CategoryTreeNav, SiteTreeNav, and SiteTreeNavDemo resolve nav
31
+ // tree data at render time. Since the same MDX content is rendered for both
32
+ // default-locale and non-default-locale pages, these components need to know
33
+ // which locale to use when building the nav tree.
34
+ //
35
+ // The `createMdxComponents(lang)` factory returns a components map with
36
+ // locale-bound wrappers for these nav components. Page modules should call it
37
+ // with the active locale instead of using the static `mdxComponents` export.
38
+ // The static export still exists for backward compatibility (using defaultLocale).
39
+
40
+ import type { ComponentChildren } from "preact";
41
+ import { htmlOverrides } from "@takazudo/zudo-doc/content";
42
+ import { HtmlPreviewWrapper } from "@takazudo/zudo-doc/html-preview-wrapper";
43
+ import { Tabs } from "@takazudo/zudo-doc/code-syntax";
44
+ import { TabItem } from "@takazudo/zudo-doc/tab-item";
45
+ import { defaultLocale, type Locale } from "@/config/i18n";
46
+ import { withBase } from "@/utils/base";
47
+ import { CategoryNavWrapper } from "./lib/_category-nav";
48
+ import { CategoryTreeNavWrapper } from "./lib/_category-tree-nav";
49
+ import { SiteTreeNavWrapper } from "./lib/_site-tree-nav";
50
+ import { DetailsWrapper } from "./lib/_details";
51
+ import { PresetGeneratorFallback } from "./lib/_preset-generator";
52
+ import { MathBlock } from "./lib/_math-block";
53
+
54
+ /**
55
+ * MDX `<img>` override — rewrites root-relative src attributes to include the
56
+ * configured site base path (settings.base). Without this, an MDX image like
57
+ * `![alt](/img/foo.webp)` emits `src="/img/foo.webp"` which 404s when the
58
+ * site is deployed under a sub-path prefix (e.g. /my-docs/).
59
+ *
60
+ * Only root-relative paths (starting with "/") are rewritten; external URLs,
61
+ * protocol-relative URLs ("//…"), and data URIs pass through unchanged. The
62
+ * withBase() call is generic — it reads settings.base at build time and applies
63
+ * whatever prefix is configured.
64
+ *
65
+ * Note: `srcset` attributes are NOT rewritten here because the current MDX
66
+ * corpus does not use srcset (standard markdown `![alt](src)` syntax produces
67
+ * only `src`). If srcset with root-relative URLs is ever introduced, extend
68
+ * this override to rewrite each srcset candidate URL as well.
69
+ */
70
+ function ContentImg(props: Record<string, unknown>) {
71
+ const src = props.src;
72
+ const rewrittenSrc =
73
+ typeof src === "string" && src.startsWith("/") && !src.startsWith("//")
74
+ ? withBase(src)
75
+ : src;
76
+ return { type: "img", props: { ...props, src: rewrittenSrc }, key: null, constructor: undefined };
77
+ }
78
+
79
+ /**
80
+ * MDX-tag stub: renders nothing. Returning `null` keeps the rendered
81
+ * tree intact (Preact's null-vnode path) without leaking placeholder
82
+ * markup into the SSR output.
83
+ */
84
+ const MdxStub = (_props: unknown) => null;
85
+
86
+ /**
87
+ * SSR-pass-through wrapper for `<Island when="load|idle|visible">`.
88
+ *
89
+ * In the zfb build the zfb `<Island>` component is unavailable, so the
90
+ * MDX corpus tags resolve to this binding instead. Rendering the
91
+ * children directly ensures that any server-renderable content nested
92
+ * inside `<Island>` (headings, paragraphs, etc.) appears in the SSR
93
+ * HTML. Client-only inner components that are themselves wrapped in an
94
+ * SSR-skip placeholder will emit their own placeholder markup; this
95
+ * wrapper does not suppress them.
96
+ *
97
+ * The `when` prop is intentionally ignored at render time — it is only
98
+ * meaningful to the zfb hydration runtime on the client, which reads
99
+ * the `data-when` attribute on the inner SSR-skip placeholder div (if
100
+ * present) rather than on this wrapper.
101
+ */
102
+ function IslandWrapper(props: {
103
+ when?: "load" | "idle" | "visible" | "media";
104
+ children?: ComponentChildren;
105
+ }): ComponentChildren {
106
+ return props.children ?? null;
107
+ }
108
+
109
+ /**
110
+ * Build an admonition stub for the given variant — renders the
111
+ * children inside `<div class="admonition admonition-<variant>">`
112
+ * so the body text stays visible until the proper Preact bindings
113
+ * land. Matches the `admonition` class hook the design system already
114
+ * targets for the Astro-era components.
115
+ *
116
+ * The title row is ALWAYS rendered (defaulting to the capitalized
117
+ * variant name when no `title` prop is given). The icon emoji is
118
+ * supplied by `.admonition-title::before` in `global.css` keyed off
119
+ * `data-admonition`, so the stub stays variant-agnostic. This mirrors
120
+ * the Astro reference theme's structure (zudolab/zudo-doc#1456).
121
+ *
122
+ * Untyped (`unknown` props) on purpose: the stubs go away once the
123
+ * proper bindings ship, so investing in a typed prop bag here would
124
+ * just be deleted later.
125
+ */
126
+ function makeAdmonitionStub(variant: string) {
127
+ // Default title — capitalized variant name (e.g. "note" → "Note"),
128
+ // matching the Astro reference where every admonition shows a title row
129
+ // regardless of whether the author provided one in MDX.
130
+ const defaultTitle = variant.charAt(0).toUpperCase() + variant.slice(1);
131
+ // The tag name is passed through `h` indirectly by the MDX runtime
132
+ // (Preact's `h(tag, props, ...children)`), so we build a plain
133
+ // VNode-shaped object here. Returning a real Preact vnode via
134
+ // `h("div", ...)` would require pulling in `preact` at the call
135
+ // site; the literal-shape is what htmlOverrides downstream emit
136
+ // and it round-trips through `preact-render-to-string` cleanly.
137
+ return function AdmonitionStub(props: { title?: string; children?: unknown }): unknown {
138
+ const title = props.title && props.title.length > 0 ? props.title : defaultTitle;
139
+ return {
140
+ type: "div",
141
+ props: {
142
+ // `data-admonition` is the structural hook the smoke spec relies on
143
+ // (independent of styling classes); the design-system class hooks
144
+ // are kept too so existing CSS continues to apply.
145
+ "data-admonition": variant,
146
+ class: `admonition admonition-${variant}`,
147
+ children: [
148
+ { type: "p", props: { class: "admonition-title", children: title }, key: null, constructor: undefined },
149
+ { type: "div", props: { class: "admonition-body", children: props.children }, key: null, constructor: undefined },
150
+ ],
151
+ },
152
+ key: null,
153
+ constructor: undefined,
154
+ };
155
+ };
156
+ }
157
+
158
+ /**
159
+ * Build a locale-aware MDX components map for the given locale.
160
+ *
161
+ * Nav components (CategoryNav, CategoryTreeNav, SiteTreeNav, SiteTreeNavDemo)
162
+ * resolve nav tree data at render time and need the active locale so they
163
+ * query the right collection. The factory closes over `lang` and returns
164
+ * locale-bound wrapper functions.
165
+ *
166
+ * Page modules should call createMdxComponents(locale) instead of importing
167
+ * the static mdxComponents export.
168
+ *
169
+ * Components map includes:
170
+ * - `htmlOverrides` — element-level overrides for native tags (h2..h4,
171
+ * p, a, ul/ol, blockquote, strong, table). Defined in
172
+ * `@takazudo/zudo-doc/content`.
173
+ * - `HtmlPreview` — Island-wrapped preview component.
174
+ * - Real Preact wrappers for CategoryNav, CategoryTreeNav, SiteTreeNav,
175
+ * SiteTreeNavDemo, and Details.
176
+ * - `Island` — SSR pass-through wrapper so children render server-side.
177
+ * - `PresetGenerator` — SSR fallback shell that renders the 8 h3 sections;
178
+ * interactive form hydrates client-side via SSR-skip placeholder.
179
+ * - Stub bindings for every other custom tag the MDX corpus references.
180
+ *
181
+ * Keep this list in sync with the corpus when new MDX tags appear.
182
+ * `pnpm exec grep -rohE '<[A-Z][a-zA-Z]+' src/content/` enumerates them.
183
+ */
184
+ export function createMdxComponents(lang: Locale | string = defaultLocale) {
185
+ // Locale-bound wrappers — close over `lang` so each wrapper queries
186
+ // the correct collection without needing a prop.
187
+ const CategoryNavBound = (props: Record<string, unknown>) =>
188
+ CategoryNavWrapper({ ...(props as Parameters<typeof CategoryNavWrapper>[0]), lang });
189
+ const CategoryTreeNavBound = (props: Record<string, unknown>) =>
190
+ CategoryTreeNavWrapper({ ...(props as Parameters<typeof CategoryTreeNavWrapper>[0]), lang });
191
+ const SiteTreeNavBound = (props: Record<string, unknown>) =>
192
+ SiteTreeNavWrapper({ ...(props as Parameters<typeof SiteTreeNavWrapper>[0]), lang });
193
+
194
+ return {
195
+ ...htmlOverrides,
196
+ // img override: rewrites root-relative src to include the site base path.
197
+ // Required when settings.base is a sub-path (e.g. /my-docs/) so that
198
+ // MDX images like ![alt](/img/foo.webp) resolve correctly on the deployed
199
+ // site. withBase() is generic — any configured base value works.
200
+ img: ContentImg,
201
+ HtmlPreview: HtmlPreviewWrapper,
202
+ // Admonitions — proper bindings land in the doc-content-components
203
+ // topic. Until then, render the children inside a
204
+ // `<div class="admonition admonition-<variant>">` so the body text
205
+ // stays visible (and the design system's existing `.admonition` CSS
206
+ // hook still targets it).
207
+ Note: makeAdmonitionStub("note"),
208
+ Tip: makeAdmonitionStub("tip"),
209
+ Info: makeAdmonitionStub("info"),
210
+ Warning: makeAdmonitionStub("warning"),
211
+ Danger: makeAdmonitionStub("danger"),
212
+ // Showcase / nav helpers — real Preact wrappers replacing MdxStub.
213
+ CategoryNav: CategoryNavBound,
214
+ CategoryTreeNav: CategoryTreeNavBound,
215
+ SiteTreeNav: SiteTreeNavBound,
216
+ SiteTreeNavDemo: SiteTreeNavBound,
217
+ Details: DetailsWrapper,
218
+ Tabs,
219
+ TabItem,
220
+ // Math rendering — KaTeX via server-side katex.renderToString().
221
+ // The math-equations.mdx content files write <MathBlock> JSX directly
222
+ // (instead of $$…$$) because the zfb Rust emitter does not yet support
223
+ // remark-math math nodes (zudo-front-builder #93).
224
+ MathBlock,
225
+ SmartBreak: MdxStub,
226
+ // Island: pass children through so server-renderable content nested
227
+ // inside <Island> appears in SSR HTML. See IslandWrapper comment above.
228
+ Island: IslandWrapper,
229
+ // PresetGenerator: render the 8 section headings as static SSR HTML for
230
+ // a11y/SEO section structure and no-JS layout stability. The interactive
231
+ // form loads client-side via the SSR-skip placeholder inside
232
+ // PresetGeneratorFallback (see pages/lib/_preset-generator.tsx).
233
+ PresetGenerator: PresetGeneratorFallback,
234
+ // Pure showcase placeholders (Avatar/Button/Card/MyComponent/PageLayout
235
+ // appear only inside MDX prose as illustrative examples — never
236
+ // implemented as real components).
237
+ Avatar: MdxStub,
238
+ Button: MdxStub,
239
+ Card: MdxStub,
240
+ MyComponent: MdxStub,
241
+ PageLayout: MdxStub,
242
+ };
243
+ }
244
+
245
+ /**
246
+ * Static default-locale components map for backward compatibility.
247
+ * New page modules should call createMdxComponents(locale) instead.
248
+ */
249
+ export const mdxComponents = createMdxComponents(defaultLocale);