create-zudo-doc 0.2.21 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/compose.d.ts +6 -3
- package/dist/compose.js +6 -4
- package/dist/features/image-enlarge.d.ts +22 -12
- package/dist/features/image-enlarge.js +23 -191
- package/dist/scaffold.d.ts +11 -0
- package/dist/scaffold.js +51 -24
- package/dist/settings-gen.js +4 -0
- package/dist/zfb-config-gen.d.ts +16 -10
- package/dist/zfb-config-gen.js +34 -239
- package/package.json +1 -1
- package/templates/base/pages/_mdx-components.ts +64 -185
- package/templates/base/pages/index.tsx +1 -1
- package/templates/base/pages/lib/_body-end-islands.tsx +6 -13
- package/templates/base/pages/lib/_category-nav.tsx +30 -115
- package/templates/base/pages/lib/_category-tree-nav.tsx +38 -65
- package/templates/base/pages/lib/_compose-meta-title.ts +2 -6
- package/templates/base/pages/lib/_doc-body-end.tsx +3 -35
- package/templates/base/pages/lib/_doc-content-header.tsx +10 -111
- package/templates/base/pages/lib/_doc-history-area.tsx +19 -211
- package/templates/base/pages/lib/_doc-metainfo-area.tsx +10 -113
- package/templates/base/pages/lib/_doc-page-renderer.tsx +22 -183
- package/templates/base/pages/lib/_doc-page-shell.tsx +17 -251
- package/templates/base/pages/lib/_doc-pager.tsx +4 -74
- package/templates/base/pages/lib/_doc-route-entries.ts +43 -177
- package/templates/base/pages/lib/_doc-route-paths.ts +16 -101
- package/templates/base/pages/lib/_doc-tags-area.tsx +14 -77
- package/templates/base/pages/lib/_extract-headings.ts +21 -295
- package/templates/base/pages/lib/_footer-with-defaults.tsx +37 -225
- package/templates/base/pages/lib/_frontmatter-preview-data.ts +5 -31
- package/templates/base/pages/lib/_head-with-defaults.tsx +13 -138
- package/templates/base/pages/lib/_header-with-defaults.tsx +24 -324
- package/templates/base/pages/lib/_inline-version-switcher.tsx +16 -78
- package/templates/base/pages/lib/_math-block.tsx +4 -63
- package/templates/base/pages/lib/_nav-data-prep.ts +32 -51
- package/templates/base/pages/lib/_nav-source-cache.ts +12 -57
- package/templates/base/pages/lib/_nav-source-docs.ts +33 -233
- package/templates/base/pages/lib/_search-widget-script.ts +2 -470
- package/templates/base/pages/lib/_search-widget.tsx +9 -195
- package/templates/base/pages/lib/_sidebar-prepaint.tsx +6 -59
- package/templates/base/pages/lib/_sidebar-with-defaults.tsx +16 -118
- package/templates/base/pages/lib/_site-tree-nav.tsx +29 -80
- package/templates/base/pages/lib/doc-page-props.ts +26 -44
- package/templates/base/pages/lib/locale-merge.ts +32 -145
- package/templates/base/pages/lib/route-enumerators.ts +52 -286
- package/templates/base/src/components/ai-chat-modal.tsx +9 -8
- package/templates/base/src/components/content/code-group.tsx +3 -76
- package/templates/base/src/components/content/content-admonition.tsx +4 -56
- package/templates/base/src/components/doc-history.tsx +9 -8
- package/templates/base/src/components/image-enlarge.tsx +11 -8
- package/templates/base/src/components/sidebar-toggle.tsx +6 -170
- package/templates/base/src/components/sidebar-tree.tsx +6 -548
- package/templates/base/src/config/color-scheme-utils.ts +34 -158
- package/templates/base/src/config/i18n.ts +9 -0
- package/templates/base/src/config/settings-types.ts +34 -172
- package/templates/base/src/config/z-index-tokens.ts +5 -4
- package/templates/base/src/styles/global.css +40 -587
- package/templates/base/src/utils/base.ts +1 -1
- package/templates/base/src/utils/docs.ts +47 -16
- package/templates/base/src/utils/github.ts +12 -9
- package/templates/base/src/utils/nav-scope.ts +13 -42
- package/templates/base/src/utils/sidebar.ts +18 -86
- package/templates/base/src/utils/slug.ts +10 -53
- package/templates/base/src/utils/smart-break.tsx +12 -120
- package/templates/base/src/utils/tags.ts +25 -68
- package/templates/features/bodyFootUtil/files/src/utils/github.ts +12 -9
- package/templates/features/designTokenPanel/files/src/lib/design-token-panel-bootstrap.ts +13 -39
- package/templates/features/docHistory/files/src/components/doc-history.tsx +8 -636
- package/templates/features/docHistory/files/src/types/doc-history.ts +7 -23
- package/templates/features/docTags/files/pages/lib/_tag-pages.tsx +35 -201
- package/templates/features/i18n/files/pages/[locale]/index.tsx +1 -1
- package/templates/features/imageEnlarge/files/src/components/image-enlarge.tsx +8 -269
- package/templates/features/sidebarToggle/files/src/components/desktop-sidebar-toggle.tsx +6 -99
- package/templates/features/tagGovernance/files/scripts/tags-audit.ts +67 -515
- package/templates/features/versioning/files/pages/lib/_versions-page.tsx +21 -73
- package/templates/base/pages/404.tsx +0 -61
- package/templates/base/pages/robots.txt.tsx +0 -29
- package/templates/base/pages/sitemap.xml.tsx +0 -59
- package/templates/base/plugins/connect-adapter.mjs +0 -169
- package/templates/base/plugins/copy-public-plugin.mjs +0 -58
- package/templates/base/plugins/search-index-plugin.mjs +0 -66
- package/templates/base/scripts/gen-z-index.mjs +0 -157
- package/templates/base/src/components/mermaid-enlarge.tsx +0 -490
- package/templates/base/src/components/site-tree-nav.tsx +0 -220
- package/templates/features/claudeResources/files/plugins/claude-resources-plugin.mjs +0 -47
- package/templates/features/docHistory/files/plugins/doc-history-plugin.mjs +0 -111
- package/templates/features/docTags/files/pages/[locale]/docs/tags/[tag].tsx +0 -59
- package/templates/features/docTags/files/pages/[locale]/docs/tags/index.tsx +0 -39
- package/templates/features/docTags/files/pages/docs/tags/[tag].tsx +0 -43
- package/templates/features/docTags/files/pages/docs/tags/index.tsx +0 -20
- package/templates/features/llmsTxt/files/plugins/llms-txt-plugin.mjs +0 -93
- package/templates/features/versioning/files/pages/[locale]/docs/versions.tsx +0 -48
- package/templates/features/versioning/files/pages/docs/versions.tsx +0 -20
package/dist/zfb-config-gen.js
CHANGED
|
@@ -1,265 +1,60 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Programmatically generate zfb.config.ts from user choices.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* `
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* templates under `plugins/<plugin>.mjs` and `templates/features/<feature>/
|
|
12
|
-
* files/plugins/<plugin>.mjs`.
|
|
4
|
+
* S5b (#2329): collapsed to the thin preset-based shape that mirrors the
|
|
5
|
+
* showcase `zfb.config.ts` after S5a. All collection wiring, plugin
|
|
6
|
+
* descriptors, markdown features, codeHighlight, resolveMarkdownLinks, and
|
|
7
|
+
* trailingSlash are now owned by `zudoDocPreset()` in
|
|
8
|
+
* `@takazudo/zudo-doc/preset`. The generated config spreads the preset
|
|
9
|
+
* result into `defineConfig` and keeps only the project-owned shell fields
|
|
10
|
+
* (`framework`, `port`, `tailwind`, `base`).
|
|
13
11
|
*
|
|
14
12
|
* Replaces the former astro-config-gen.ts + content-config-gen.ts pair.
|
|
15
13
|
* In the zfb world, content-collection schemas live inside zfb.config.ts
|
|
16
14
|
* itself — there is no separate content.config.ts.
|
|
15
|
+
*
|
|
16
|
+
* `_choices` is intentionally unused: post-S5b the emitted config is a
|
|
17
|
+
* CONSTANT. All feature variation is driven by `settings.*` (read at
|
|
18
|
+
* zfb-load time inside `zudoDocPreset()`), so the generated file is byte
|
|
19
|
+
* identical for every feature combination. The parameter is retained only
|
|
20
|
+
* for call-site compatibility (`scaffold.ts` passes `choices`). Do NOT add
|
|
21
|
+
* feature-gated branches here — wire new feature behaviour into
|
|
22
|
+
* `packages/zudo-doc/src/preset.ts` and the project's `settings.ts` instead.
|
|
17
23
|
*/
|
|
18
|
-
export function generateZfbConfig(
|
|
19
|
-
const hasDocHistory = choices.features.includes("docHistory");
|
|
20
|
-
const hasLlmsTxt = choices.features.includes("llmsTxt");
|
|
21
|
-
const hasClaudeResources = choices.features.includes("claudeResources");
|
|
24
|
+
export function generateZfbConfig(_choices) {
|
|
22
25
|
const lines = [];
|
|
23
26
|
// --- Imports ---
|
|
24
|
-
lines.push(`import { z } from "zod";`);
|
|
25
27
|
lines.push(`import { defineConfig } from "zfb/config";`);
|
|
28
|
+
lines.push(`import { zudoDocPreset } from "@takazudo/zudo-doc/preset";`);
|
|
26
29
|
lines.push(`import { settings } from "./src/config/settings";`);
|
|
27
30
|
lines.push(`import { buildDocsSchema } from "./src/config/docs-schema";`);
|
|
28
31
|
lines.push(``);
|
|
29
|
-
// ---
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
lines.push(`
|
|
36
|
-
lines.push(
|
|
37
|
-
lines.push(`
|
|
38
|
-
lines.push(
|
|
39
|
-
|
|
40
|
-
lines.push(`
|
|
41
|
-
lines.push(` name: string;`);
|
|
42
|
-
lines.push(` path: string;`);
|
|
43
|
-
lines.push(` schema: Record<string, unknown>;`);
|
|
44
|
-
lines.push(`}`);
|
|
45
|
-
lines.push(``);
|
|
46
|
-
// --- Collections array ---
|
|
47
|
-
lines.push(`const collections: CollectionEntryShape[] = [];`);
|
|
48
|
-
lines.push(``);
|
|
49
|
-
lines.push(`collections.push({ name: "docs", path: settings.docsDir, schema: docsSchemaJson });`);
|
|
50
|
-
lines.push(``);
|
|
51
|
-
// Locale collections — empty loop when locales is {} (i18n disabled).
|
|
52
|
-
lines.push(`for (const [code, config] of Object.entries(settings.locales)) {`);
|
|
53
|
-
lines.push(` collections.push({ name: \`docs-\${code}\`, path: config.dir, schema: docsSchemaJson });`);
|
|
54
|
-
lines.push(`}`);
|
|
55
|
-
lines.push(``);
|
|
56
|
-
// Version collections — outer `if` short-circuits when versions is false.
|
|
57
|
-
lines.push(`if (settings.versions) {`);
|
|
58
|
-
lines.push(` for (const version of settings.versions) {`);
|
|
59
|
-
lines.push(` collections.push({`);
|
|
60
|
-
lines.push(` name: \`docs-v-\${version.slug}\`,`);
|
|
61
|
-
lines.push(` path: version.docsDir,`);
|
|
62
|
-
lines.push(` schema: docsSchemaJson,`);
|
|
63
|
-
lines.push(` });`);
|
|
64
|
-
lines.push(` if (version.locales) {`);
|
|
65
|
-
lines.push(` for (const [code, config] of Object.entries(version.locales)) {`);
|
|
66
|
-
lines.push(` collections.push({`);
|
|
67
|
-
lines.push(` name: \`docs-v-\${version.slug}-\${code}\`,`);
|
|
68
|
-
lines.push(` path: config.dir,`);
|
|
69
|
-
lines.push(` schema: docsSchemaJson,`);
|
|
70
|
-
lines.push(` });`);
|
|
71
|
-
lines.push(` }`);
|
|
72
|
-
lines.push(` }`);
|
|
73
|
-
lines.push(` }`);
|
|
74
|
-
lines.push(`}`);
|
|
75
|
-
lines.push(``);
|
|
76
|
-
// --- Locale helpers used by integrationPlugins (always emitted because
|
|
77
|
-
// search-index + copy-public are always-on; locale-shaped data is
|
|
78
|
-
// consumed by search-index even when there's only the default locale).
|
|
79
|
-
lines.push(`const localeArray = Object.entries(settings.locales).map(([code, locale]) => ({`);
|
|
80
|
-
lines.push(` code,`);
|
|
81
|
-
lines.push(` dir: locale.dir,`);
|
|
82
|
-
lines.push(`}));`);
|
|
83
|
-
lines.push(`const localeRecord = Object.fromEntries(`);
|
|
84
|
-
lines.push(` Object.entries(settings.locales).map(([code, locale]) => [code, { dir: locale.dir }]),`);
|
|
85
|
-
lines.push(`);`);
|
|
86
|
-
lines.push(``);
|
|
87
|
-
// --- Plugins — inline-object shape matches host. Each entry's `name`
|
|
88
|
-
// is a relative path to a `.mjs` plugin module shipped by the
|
|
89
|
-
// base/feature templates. zfb's plugin runtime resolves the module
|
|
90
|
-
// and dispatches lifecycle hooks (preBuild / postBuild / devMiddleware)
|
|
91
|
-
// on its default export. ---
|
|
92
|
-
lines.push(`const integrationPlugins = [`);
|
|
93
|
-
if (hasClaudeResources) {
|
|
94
|
-
lines.push(` ...(settings.claudeResources`);
|
|
95
|
-
lines.push(` ? [`);
|
|
96
|
-
lines.push(` {`);
|
|
97
|
-
lines.push(` name: "./plugins/claude-resources-plugin.mjs",`);
|
|
98
|
-
lines.push(` options: {`);
|
|
99
|
-
lines.push(` claudeDir: settings.claudeResources.claudeDir,`);
|
|
100
|
-
lines.push(` projectRoot: settings.claudeResources.projectRoot,`);
|
|
101
|
-
lines.push(` docsDir: settings.docsDir,`);
|
|
102
|
-
lines.push(` },`);
|
|
103
|
-
lines.push(` },`);
|
|
104
|
-
lines.push(` ]`);
|
|
105
|
-
lines.push(` : []),`);
|
|
106
|
-
}
|
|
107
|
-
if (hasDocHistory) {
|
|
108
|
-
lines.push(` ...(settings.docHistory`);
|
|
109
|
-
lines.push(` ? [`);
|
|
110
|
-
lines.push(` {`);
|
|
111
|
-
lines.push(` name: "./plugins/doc-history-plugin.mjs",`);
|
|
112
|
-
lines.push(` options: {`);
|
|
113
|
-
lines.push(` docsDir: settings.docsDir,`);
|
|
114
|
-
lines.push(` locales: localeRecord,`);
|
|
115
|
-
lines.push(` base: settings.base,`);
|
|
116
|
-
lines.push(` },`);
|
|
117
|
-
lines.push(` },`);
|
|
118
|
-
lines.push(` ]`);
|
|
119
|
-
lines.push(` : []),`);
|
|
120
|
-
}
|
|
121
|
-
// search-index is always-on (matches host) — emits dist/search-index.json
|
|
122
|
-
// even when no <Search /> widget mounts; ~few-KB cost is acceptable and
|
|
123
|
-
// keeps the dev-middleware route registered for the always-mounted
|
|
124
|
-
// search widget in pages/lib/_header-with-defaults.tsx.
|
|
125
|
-
lines.push(` {`);
|
|
126
|
-
lines.push(` name: "./plugins/search-index-plugin.mjs",`);
|
|
127
|
-
lines.push(` options: {`);
|
|
128
|
-
lines.push(` docsDir: settings.docsDir,`);
|
|
129
|
-
lines.push(` locales: localeRecord,`);
|
|
130
|
-
lines.push(` base: settings.base,`);
|
|
131
|
-
lines.push(` },`);
|
|
132
|
-
lines.push(` },`);
|
|
133
|
-
if (hasLlmsTxt) {
|
|
134
|
-
lines.push(` ...(settings.llmsTxt`);
|
|
135
|
-
lines.push(` ? [`);
|
|
136
|
-
lines.push(` {`);
|
|
137
|
-
lines.push(` name: "./plugins/llms-txt-plugin.mjs",`);
|
|
138
|
-
lines.push(` options: {`);
|
|
139
|
-
lines.push(` siteName: settings.siteName,`);
|
|
140
|
-
lines.push(` siteDescription: settings.siteDescription,`);
|
|
141
|
-
lines.push(` base: settings.base,`);
|
|
142
|
-
lines.push(` siteUrl: settings.siteUrl,`);
|
|
143
|
-
lines.push(` defaultLocaleDir: settings.docsDir,`);
|
|
144
|
-
lines.push(` locales: localeArray,`);
|
|
145
|
-
lines.push(` },`);
|
|
146
|
-
lines.push(` },`);
|
|
147
|
-
lines.push(` ]`);
|
|
148
|
-
lines.push(` : []),`);
|
|
149
|
-
}
|
|
150
|
-
// copy-public is always-on (matches host) — workaround for upstream zfb
|
|
151
|
-
// gap where `zfb build` does not copy `public/` to dist/. Empty/missing
|
|
152
|
-
// public/ is a no-op, so the cost to projects without public/ is zero.
|
|
153
|
-
lines.push(` {`);
|
|
154
|
-
lines.push(` name: "./plugins/copy-public-plugin.mjs",`);
|
|
155
|
-
lines.push(` options: {`);
|
|
156
|
-
lines.push(` publicDir: "public",`);
|
|
157
|
-
lines.push(` },`);
|
|
158
|
-
lines.push(` },`);
|
|
159
|
-
lines.push(`];`);
|
|
32
|
+
// --- Directive vocabulary ---
|
|
33
|
+
// The seven canonical directives registered in pages/_mdx-components.ts.
|
|
34
|
+
// "details" routes to DetailsWrapper — a collapsible, NOT an admonition.
|
|
35
|
+
lines.push(`const directiveVocabulary = {`);
|
|
36
|
+
lines.push(` note: "Note",`);
|
|
37
|
+
lines.push(` tip: "Tip",`);
|
|
38
|
+
lines.push(` info: "Info",`);
|
|
39
|
+
lines.push(` warning: "Warning",`);
|
|
40
|
+
lines.push(` danger: "Danger",`);
|
|
41
|
+
lines.push(` caution: "Caution",`);
|
|
42
|
+
lines.push(` details: "Details",`);
|
|
43
|
+
lines.push(`};`);
|
|
160
44
|
lines.push(``);
|
|
161
45
|
// --- Export ---
|
|
162
46
|
lines.push(`export default defineConfig({`);
|
|
47
|
+
lines.push(` // ── Host-owned shell fields ──────────────────────────────────────────────`);
|
|
163
48
|
lines.push(` framework: "preact",`);
|
|
164
49
|
lines.push(` // Pin the dev/preview port — zfb defaults to 3000, but the generated`);
|
|
165
50
|
lines.push(` // CLAUDE.md and the Tauri dev wrappers assume 4321.`);
|
|
166
51
|
lines.push(` port: 4321,`);
|
|
167
52
|
lines.push(` tailwind: { enabled: true },`);
|
|
168
|
-
lines.push(`
|
|
169
|
-
lines.push(` stripMdExt: true,`);
|
|
170
|
-
lines.push(` resolveMarkdownLinks: {`);
|
|
171
|
-
lines.push(` enabled: true,`);
|
|
172
|
-
lines.push(` dirs: [`);
|
|
173
|
-
lines.push(` { dir: settings.docsDir, routePrefix: "/docs/" },`);
|
|
174
|
-
lines.push(` ...Object.entries(settings.locales).map(([code, locale]) => ({`);
|
|
175
|
-
lines.push(` dir: locale.dir,`);
|
|
176
|
-
lines.push(` routePrefix: \`/\${code}/docs/\`,`);
|
|
177
|
-
lines.push(` })),`);
|
|
178
|
-
lines.push(` // Versioned collections: each version's EN dir + per-locale dirs.`);
|
|
179
|
-
lines.push(` ...(settings.versions`);
|
|
180
|
-
lines.push(` ? settings.versions.flatMap((version) => [`);
|
|
181
|
-
lines.push(` { dir: version.docsDir, routePrefix: \`/v/\${version.slug}/docs/\` },`);
|
|
182
|
-
lines.push(` ...Object.entries(version.locales ?? {}).map(([code, locale]) => ({`);
|
|
183
|
-
lines.push(` dir: locale.dir,`);
|
|
184
|
-
lines.push(` routePrefix: \`/v/\${version.slug}/\${code}/docs/\`,`);
|
|
185
|
-
lines.push(` })),`);
|
|
186
|
-
lines.push(` ])`);
|
|
187
|
-
lines.push(` : []),`);
|
|
188
|
-
lines.push(` ],`);
|
|
189
|
-
lines.push(` onBrokenLinks: "warn",`);
|
|
190
|
-
lines.push(` },`);
|
|
53
|
+
lines.push(` // Public URL prefix for <link rel="stylesheet"> and <script> tags.`);
|
|
191
54
|
lines.push(` base: settings.base,`);
|
|
192
|
-
lines.push(
|
|
193
|
-
//
|
|
194
|
-
|
|
195
|
-
// the active light/dark toggle with no client JS. Theme names are syntect
|
|
196
|
-
// built-ins shipped with zfb (not Shiki names). Matches the host config.
|
|
197
|
-
lines.push(` codeHighlight: {`);
|
|
198
|
-
lines.push(` themeLight: "base16-ocean.light",`);
|
|
199
|
-
lines.push(` themeDark: "base16-ocean.dark",`);
|
|
200
|
-
lines.push(` },`);
|
|
201
|
-
// markdown.features block — mirrors the zfb next.13 opt-in model.
|
|
202
|
-
//
|
|
203
|
-
// Value-shape rule (empirically verified against the next.13 Rust loader):
|
|
204
|
-
// object-typed features (githubAutolinks, codeEnrichment, imageDimensions,
|
|
205
|
-
// linkValidation) REJECT the `true` shorthand and must be given an options
|
|
206
|
-
// object (`{}` or fields). Boolean-OR-object features (githubAlerts,
|
|
207
|
-
// readingTime, codeTabs, mermaid, headingMarkerToc) accept `true`.
|
|
208
|
-
// (directives is object-typed — it takes a `name → component` map, not `true`.)
|
|
209
|
-
// Note: imageEnlarge was formerly a Boolean-OR-object feature here, but
|
|
210
|
-
// next.18 hard-removed it from the Rust config schema — it is now
|
|
211
|
-
// re-implemented in userland via an MDX p-override in pages/_mdx-components.ts
|
|
212
|
-
// (gated on settings.imageEnlarge). Do NOT add imageEnlarge back here.
|
|
213
|
-
//
|
|
214
|
-
// Intentionally omitted features (known-blocked at zfb next.13):
|
|
215
|
-
// - tocExport: injects indented `export const toc = [...]` that MDX
|
|
216
|
-
// parses as content, breaking esbuild with "Expected }" across the
|
|
217
|
-
// whole corpus. Re-enable when the upstream Rust pass emits the
|
|
218
|
-
// export at column 0. (Filed as zudolab/zudo-doc#1814.)
|
|
219
|
-
// - ruby: the `^{...}` annotation syntax 500s the SSR render at next.13.
|
|
220
|
-
// A registered stub cannot fix it — the error is inside zfb's Rust
|
|
221
|
-
// ruby pass. Re-enable when the upstream crate is fixed. (#1815.)
|
|
222
|
-
// - transclude: `:::include{file="..."}` 500s SSR (no registered
|
|
223
|
-
// <include> renderer); `![[...]]` wikilink form is a no-op.
|
|
224
|
-
// Re-enable when a transclude renderer is wired.
|
|
225
|
-
//
|
|
226
|
-
// githubAutolinks is omitted intentionally: the showcase hardcodes
|
|
227
|
-
// `repo: "zudolab/zudo-doc"` but a scaffolded project belongs to a
|
|
228
|
-
// different repo. Users can add `githubAutolinks: { repo: "owner/repo" }`
|
|
229
|
-
// to their zfb.config.ts after scaffolding.
|
|
230
|
-
lines.push(` markdown: {`);
|
|
231
|
-
lines.push(` features: {`);
|
|
232
|
-
lines.push(` // Former-Core features (were always-on before zfb next.12).`);
|
|
233
|
-
lines.push(` // imageEnlarge was a former-Core feature but was hard-removed in zfb`);
|
|
234
|
-
lines.push(` // next.18 — it is now re-implemented via an MDX p-override.`);
|
|
235
|
-
lines.push(` // Admonitions recipe: register the :::name directive vocabulary`);
|
|
236
|
-
lines.push(` // (note/tip/info/warning/danger/caution/details) → components.`);
|
|
237
|
-
lines.push(` directives: {`);
|
|
238
|
-
lines.push(` note: "Note",`);
|
|
239
|
-
lines.push(` tip: "Tip",`);
|
|
240
|
-
lines.push(` info: "Info",`);
|
|
241
|
-
lines.push(` warning: "Warning",`);
|
|
242
|
-
lines.push(` danger: "Danger",`);
|
|
243
|
-
lines.push(` caution: "Caution",`);
|
|
244
|
-
lines.push(` details: "Details", // collapsible — routes to DetailsWrapper`);
|
|
245
|
-
lines.push(` },`);
|
|
246
|
-
lines.push(` mermaid: true,`);
|
|
247
|
-
lines.push(` headingMarkerToc: true,`);
|
|
248
|
-
lines.push(` // Safe opt-in features.`);
|
|
249
|
-
lines.push(` githubAlerts: true,`);
|
|
250
|
-
lines.push(` readingTime: true,`);
|
|
251
|
-
lines.push(` codeEnrichment: {},`);
|
|
252
|
-
lines.push(` codeTabs: true,`);
|
|
253
|
-
lines.push(` imageDimensions: {},`);
|
|
254
|
-
lines.push(` // warn-only link validation — failOnBroken: false never fails the build.`);
|
|
255
|
-
lines.push(` linkValidation: { failOnBroken: false },`);
|
|
256
|
-
lines.push(` // Heading-ID (anchor) strategy — single source of truth in`);
|
|
257
|
-
lines.push(` // settings.headingIdStrategy, also mirrored by the host TOC builder`);
|
|
258
|
-
lines.push(` // (pages/lib/_extract-headings.ts) so TOC anchors match rendered ids.`);
|
|
259
|
-
lines.push(` headingIds: { strategy: settings.headingIdStrategy },`);
|
|
260
|
-
lines.push(` },`);
|
|
261
|
-
lines.push(` },`);
|
|
262
|
-
lines.push(` plugins: integrationPlugins,`);
|
|
55
|
+
lines.push(``);
|
|
56
|
+
lines.push(` // ── Preset-owned fields (content collections, plugins, markdown, …) ────────`);
|
|
57
|
+
lines.push(` ...zudoDocPreset({ settings, buildDocsSchema, directiveVocabulary }),`);
|
|
263
58
|
lines.push(`});`);
|
|
264
59
|
return lines.join("\n") + "\n";
|
|
265
60
|
}
|
package/package.json
CHANGED
|
@@ -1,117 +1,52 @@
|
|
|
1
|
-
//
|
|
2
|
-
// `<entry.Content components={...} />`.
|
|
1
|
+
// Project MDX-components assembly — thin wrapper over the package factory.
|
|
3
2
|
//
|
|
4
|
-
//
|
|
3
|
+
// The bulk of the components bag (htmlOverrides, admonitions, CodeGroup,
|
|
4
|
+
// Tabs/TabItem, MathBlock, the img base-rewrite, the enlargeable-`p` override)
|
|
5
|
+
// now ships from `@takazudo/zudo-doc/mdx-components` (package-first migration,
|
|
6
|
+
// epic #2321, S8 #2332). This file keeps ONLY what is genuinely project-bound:
|
|
5
7
|
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
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).
|
|
8
|
+
// - the 4 locale-bound nav wrappers (CategoryNav / CategoryTreeNav /
|
|
9
|
+
// SiteTreeNav / SiteTreeNavDemo) — they depend on the project's content
|
|
10
|
+
// collections + nav-tree utilities, so they cannot live in the package.
|
|
11
|
+
// They are passed into the factory as `navData`; the factory injects the
|
|
12
|
+
// active `locale` so `/ja` resolves the JA collection (the load-bearing
|
|
13
|
+
// locale thread — a static global mdx-components slot would render the EN
|
|
14
|
+
// tree on every `/ja` page, which is why this stays a per-call factory).
|
|
15
|
+
// - project `extras` spread last: HtmlPreview (with the host's global
|
|
16
|
+
// config), Details, the Island SSR pass-through, the PresetGenerator SSR
|
|
17
|
+
// shell, and the pure-showcase stubs (Avatar/Button/Card/MyComponent/
|
|
18
|
+
// PageLayout) that appear only as illustrative MDX prose.
|
|
39
19
|
|
|
40
20
|
import type { ComponentChildren } from "preact";
|
|
41
|
-
|
|
42
|
-
import { htmlOverrides } from "@takazudo/zudo-doc/content";
|
|
21
|
+
import { createMdxComponents as createMdxComponentsBase } from "@takazudo/zudo-doc/mdx-components";
|
|
43
22
|
import { HtmlPreviewWrapper, type HtmlPreviewWrapperProps } from "@takazudo/zudo-doc/html-preview-wrapper";
|
|
44
|
-
import { Tabs } from "@takazudo/zudo-doc/code-syntax";
|
|
45
|
-
import { TabItem } from "@takazudo/zudo-doc/tab-item";
|
|
46
23
|
import { defaultLocale, type Locale } from "@/config/i18n";
|
|
47
24
|
import { settings } from "@/config/settings";
|
|
48
|
-
import { withBase } from "@/utils/base";
|
|
49
25
|
import { CategoryNavWrapper } from "./lib/_category-nav";
|
|
50
26
|
import { CategoryTreeNavWrapper } from "./lib/_category-tree-nav";
|
|
51
27
|
import { SiteTreeNavWrapper } from "./lib/_site-tree-nav";
|
|
52
28
|
import { DetailsWrapper } from "./lib/_details";
|
|
53
29
|
import { PresetGeneratorFallback } from "./lib/_preset-generator";
|
|
54
|
-
import { MathBlock } from "./lib/_math-block";
|
|
55
|
-
import { CodeGroup } from "@/components/content/code-group";
|
|
56
|
-
import { makeAdmonition } from "@/components/content/content-admonition";
|
|
57
30
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
* configured site base path (settings.base). Without this, an MDX image like
|
|
61
|
-
* `` emits `src="/img/foo.webp"` which 404s when the
|
|
62
|
-
* site is deployed under a sub-path prefix (e.g. /my-docs/).
|
|
63
|
-
*
|
|
64
|
-
* Only root-relative paths (starting with "/") are rewritten; external URLs,
|
|
65
|
-
* protocol-relative URLs ("//…"), and data URIs pass through unchanged. The
|
|
66
|
-
* withBase() call is generic — it reads settings.base at build time and applies
|
|
67
|
-
* whatever prefix is configured.
|
|
68
|
-
*
|
|
69
|
-
* Note: `srcset` attributes are NOT rewritten here because the current MDX
|
|
70
|
-
* corpus does not use srcset (standard markdown `` syntax produces
|
|
71
|
-
* only `src`). If srcset with root-relative URLs is ever introduced, extend
|
|
72
|
-
* this override to rewrite each srcset candidate URL as well.
|
|
73
|
-
*/
|
|
74
|
-
function ContentImg(props: Record<string, unknown>) {
|
|
75
|
-
const src = props.src;
|
|
76
|
-
const rewrittenSrc =
|
|
77
|
-
typeof src === "string" && src.startsWith("/") && !src.startsWith("//")
|
|
78
|
-
? withBase(src)
|
|
79
|
-
: src;
|
|
80
|
-
// Strip the "no-enlarge" sentinel from the rendered DOM — it is read by the
|
|
81
|
-
// p-override before ContentImg is called (the VNode is still unlaunched at
|
|
82
|
-
// that point), so we must delete it here to avoid leaking the sentinel into
|
|
83
|
-
// the img title attribute.
|
|
84
|
-
const { title, ...restProps } = props;
|
|
85
|
-
const finalTitle = title === "no-enlarge" ? undefined : title;
|
|
86
|
-
const mergedProps: Record<string, unknown> = { ...restProps, src: rewrittenSrc };
|
|
87
|
-
if (finalTitle !== undefined) {
|
|
88
|
-
mergedProps.title = finalTitle;
|
|
89
|
-
}
|
|
90
|
-
return { type: "img", props: mergedProps, key: null, constructor: undefined };
|
|
91
|
-
}
|
|
31
|
+
const HtmlPreviewWithGlobalConfig = (props: HtmlPreviewWrapperProps) =>
|
|
32
|
+
HtmlPreviewWrapper({ globalConfig: settings.htmlPreview ?? null, ...props });
|
|
92
33
|
|
|
93
34
|
/**
|
|
94
|
-
* MDX-tag stub: renders nothing. Returning `null` keeps the rendered
|
|
95
|
-
*
|
|
96
|
-
*
|
|
35
|
+
* MDX-tag stub: renders nothing. Returning `null` keeps the rendered tree
|
|
36
|
+
* intact (Preact's null-vnode path) without leaking placeholder markup into
|
|
37
|
+
* the SSR output.
|
|
97
38
|
*/
|
|
98
39
|
const MdxStub = (_props: unknown) => null;
|
|
99
40
|
|
|
100
41
|
/**
|
|
101
42
|
* SSR-pass-through wrapper for `<Island when="load|idle|visible">`.
|
|
102
43
|
*
|
|
103
|
-
* In the zfb build the zfb `<Island>` component is unavailable, so the
|
|
104
|
-
* MDX corpus
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* wrapper does not suppress them.
|
|
110
|
-
*
|
|
111
|
-
* The `when` prop is intentionally ignored at render time — it is only
|
|
112
|
-
* meaningful to the zfb hydration runtime on the client, which reads
|
|
113
|
-
* the `data-when` attribute on the inner SSR-skip placeholder div (if
|
|
114
|
-
* present) rather than on this wrapper.
|
|
44
|
+
* In the zfb build the zfb `<Island>` component is unavailable here, so the
|
|
45
|
+
* MDX corpus tag resolves to this binding instead. Rendering the children
|
|
46
|
+
* directly ensures server-renderable content nested inside `<Island>`
|
|
47
|
+
* (headings, paragraphs, etc.) appears in the SSR HTML. The `when` prop is
|
|
48
|
+
* ignored at render time — it is only meaningful to the zfb hydration runtime
|
|
49
|
+
* on the client, which reads `data-when` on the inner SSR-skip placeholder.
|
|
115
50
|
*/
|
|
116
51
|
function IslandWrapper(props: {
|
|
117
52
|
when?: "load" | "idle" | "visible" | "media";
|
|
@@ -120,104 +55,48 @@ function IslandWrapper(props: {
|
|
|
120
55
|
return props.children ?? null;
|
|
121
56
|
}
|
|
122
57
|
|
|
123
|
-
// @slot:mdx-components:enlarge-defs
|
|
124
|
-
const HtmlPreviewWithGlobalConfig = (props: HtmlPreviewWrapperProps) =>
|
|
125
|
-
HtmlPreviewWrapper({ globalConfig: settings.htmlPreview ?? null, ...props });
|
|
126
|
-
|
|
127
58
|
/**
|
|
128
59
|
* Build a locale-aware MDX components map for the given locale.
|
|
129
60
|
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
* Page modules should call createMdxComponents(locale) instead of importing
|
|
136
|
-
* the static mdxComponents export.
|
|
61
|
+
* Delegates the package-resident components to the `@takazudo/zudo-doc`
|
|
62
|
+
* factory and supplies the project-bound pieces:
|
|
63
|
+
* - `navData`: the 4 locale-aware nav wrappers (the factory injects `lang`).
|
|
64
|
+
* - `extras`: HtmlPreview (host-configured), Details, Island pass-through,
|
|
65
|
+
* PresetGenerator SSR shell, and the showcase stubs.
|
|
137
66
|
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
* p, a, ul/ol, blockquote, strong, table). Defined in
|
|
141
|
-
* `@takazudo/zudo-doc/content`.
|
|
142
|
-
* - `HtmlPreview` — Island-wrapped preview component.
|
|
143
|
-
* - Real Preact wrappers for CategoryNav, CategoryTreeNav, SiteTreeNav,
|
|
144
|
-
* SiteTreeNavDemo, and Details.
|
|
145
|
-
* - `Island` — SSR pass-through wrapper so children render server-side.
|
|
146
|
-
* - `PresetGenerator` — SSR fallback shell that renders the 8 h3 sections;
|
|
147
|
-
* interactive form hydrates client-side via SSR-skip placeholder.
|
|
148
|
-
* - Stub bindings for every other custom tag the MDX corpus references.
|
|
149
|
-
*
|
|
150
|
-
* Keep this list in sync with the corpus when new MDX tags appear.
|
|
151
|
-
* `pnpm exec grep -rohE '<[A-Z][a-zA-Z]+' src/content/` enumerates them.
|
|
67
|
+
* Page modules should call createMdxComponents(locale) — not the static
|
|
68
|
+
* mdxComponents export — so each render gets the locale-correct map.
|
|
152
69
|
*/
|
|
153
70
|
export function createMdxComponents(lang: Locale | string = defaultLocale) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
// Without these bindings, those two alert variants 500 the SSR render.
|
|
184
|
-
Important: makeAdmonition("important"),
|
|
185
|
-
Caution: makeAdmonition("caution"),
|
|
186
|
-
// codeTabs Option A: zfb emits <CodeGroup tabs={[...]}> for :::code-group.
|
|
187
|
-
// The framework does not ship this component; we implement it here and map
|
|
188
|
-
// the tabs[] + <pre data-lang> children to the existing Tabs/TabItem UI.
|
|
189
|
-
CodeGroup: CodeGroup as unknown as (props: Record<string, unknown>) => unknown,
|
|
190
|
-
// Showcase / nav helpers — real Preact wrappers replacing MdxStub.
|
|
191
|
-
CategoryNav: CategoryNavBound,
|
|
192
|
-
CategoryTreeNav: CategoryTreeNavBound,
|
|
193
|
-
SiteTreeNav: SiteTreeNavBound,
|
|
194
|
-
SiteTreeNavDemo: SiteTreeNavBound,
|
|
195
|
-
Details: DetailsWrapper,
|
|
196
|
-
Tabs,
|
|
197
|
-
TabItem,
|
|
198
|
-
// Math rendering — KaTeX via server-side katex.renderToString().
|
|
199
|
-
// The math-equations.mdx content files write <MathBlock> JSX directly
|
|
200
|
-
// (instead of $$…$$) because the zfb Rust emitter does not yet support
|
|
201
|
-
// remark-math math nodes (zudo-front-builder #93).
|
|
202
|
-
MathBlock,
|
|
203
|
-
SmartBreak: MdxStub,
|
|
204
|
-
// Island: pass children through so server-renderable content nested
|
|
205
|
-
// inside <Island> appears in SSR HTML. See IslandWrapper comment above.
|
|
206
|
-
Island: IslandWrapper,
|
|
207
|
-
// PresetGenerator: render the 8 section headings as static SSR HTML for
|
|
208
|
-
// a11y/SEO section structure and no-JS layout stability. The interactive
|
|
209
|
-
// form loads client-side via the SSR-skip placeholder inside
|
|
210
|
-
// PresetGeneratorFallback (see pages/lib/_preset-generator.tsx).
|
|
211
|
-
PresetGenerator: PresetGeneratorFallback,
|
|
212
|
-
// Pure showcase placeholders (Avatar/Button/Card/MyComponent/PageLayout
|
|
213
|
-
// appear only inside MDX prose as illustrative examples — never
|
|
214
|
-
// implemented as real components).
|
|
215
|
-
Avatar: MdxStub,
|
|
216
|
-
Button: MdxStub,
|
|
217
|
-
Card: MdxStub,
|
|
218
|
-
MyComponent: MdxStub,
|
|
219
|
-
PageLayout: MdxStub,
|
|
220
|
-
};
|
|
71
|
+
return createMdxComponentsBase({
|
|
72
|
+
settings,
|
|
73
|
+
locale: lang,
|
|
74
|
+
navData: {
|
|
75
|
+
CategoryNav: CategoryNavWrapper as unknown as (props: Record<string, unknown>) => unknown,
|
|
76
|
+
CategoryTreeNav: CategoryTreeNavWrapper as unknown as (props: Record<string, unknown>) => unknown,
|
|
77
|
+
SiteTreeNav: SiteTreeNavWrapper as unknown as (props: Record<string, unknown>) => unknown,
|
|
78
|
+
},
|
|
79
|
+
extras: {
|
|
80
|
+
HtmlPreview: HtmlPreviewWithGlobalConfig,
|
|
81
|
+
Details: DetailsWrapper,
|
|
82
|
+
// SmartBreak: corpus tag with no visual rendering — render nothing.
|
|
83
|
+
SmartBreak: MdxStub,
|
|
84
|
+
// Island: pass children through so server-renderable content nested
|
|
85
|
+
// inside <Island> appears in SSR HTML. See IslandWrapper comment above.
|
|
86
|
+
Island: IslandWrapper,
|
|
87
|
+
// PresetGenerator: SSR fallback shell that renders the 8 section headings;
|
|
88
|
+
// the interactive form hydrates client-side via the SSR-skip placeholder
|
|
89
|
+
// inside PresetGeneratorFallback (see pages/lib/_preset-generator.tsx).
|
|
90
|
+
PresetGenerator: PresetGeneratorFallback,
|
|
91
|
+
// Pure showcase placeholders — appear only inside MDX prose as
|
|
92
|
+
// illustrative examples, never implemented as real components.
|
|
93
|
+
Avatar: MdxStub,
|
|
94
|
+
Button: MdxStub,
|
|
95
|
+
Card: MdxStub,
|
|
96
|
+
MyComponent: MdxStub,
|
|
97
|
+
PageLayout: MdxStub,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
221
100
|
}
|
|
222
101
|
|
|
223
102
|
/**
|
|
@@ -27,7 +27,7 @@ import { DocLayoutWithDefaults } from "@takazudo/zudo-doc/doclayout";
|
|
|
27
27
|
import type { JSX } from "preact";
|
|
28
28
|
import type { VNode } from "preact";
|
|
29
29
|
import { Island } from "@takazudo/zfb";
|
|
30
|
-
import SiteTreeNav from "
|
|
30
|
+
import { SiteTreeNav } from "@takazudo/zudo-doc/site-tree-nav-island";
|
|
31
31
|
import { FooterWithDefaults } from "./lib/_footer-with-defaults";
|
|
32
32
|
import { HeaderWithDefaults } from "./lib/_header-with-defaults";
|
|
33
33
|
import { HeadWithDefaults } from "./lib/_head-with-defaults";
|
|
@@ -32,21 +32,14 @@ import type { VNode, JSX } from "preact";
|
|
|
32
32
|
import { Island } from "@takazudo/zfb";
|
|
33
33
|
import { settings } from "@/config/settings";
|
|
34
34
|
|
|
35
|
-
import AiChatModal from "
|
|
36
|
-
import ImageEnlarge,
|
|
37
|
-
import MermaidEnlarge,
|
|
35
|
+
import { AiChatModal } from "@takazudo/zudo-doc/ai-chat-modal";
|
|
36
|
+
import { ImageEnlarge, ImageEnlargeSsrFallback } from "@takazudo/zudo-doc/image-enlarge";
|
|
37
|
+
import { MermaidEnlarge, MermaidEnlargeSsrFallback } from "@takazudo/zudo-doc/mermaid-enlarge";
|
|
38
38
|
// @slot:body-end-islands:imports
|
|
39
39
|
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
// The marker must match the third-arg literal that zfb's scanner records
|
|
44
|
-
// for the same source-level identifier (zfb PR #150). esbuild preserves
|
|
45
|
-
// function names by default, but the explicit assignment is a
|
|
46
|
-
// belt-and-braces guard for production minification regressions.
|
|
47
|
-
(AiChatModal as { displayName?: string }).displayName = "AiChatModal";
|
|
48
|
-
(ImageEnlarge as { displayName?: string }).displayName = "ImageEnlarge";
|
|
49
|
-
(MermaidEnlarge as { displayName?: string }).displayName = "MermaidEnlarge";
|
|
40
|
+
// AiChatModal, ImageEnlarge, MermaidEnlarge pin displayName internally in the
|
|
41
|
+
// package. Optional feature islands that still need explicit call-site pinning
|
|
42
|
+
// inject their displayName assignment at the slot below only when selected.
|
|
50
43
|
// @slot:body-end-islands:display-names
|
|
51
44
|
|
|
52
45
|
/**
|