create-zudo-doc 3.1.0 → 3.3.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 (127) hide show
  1. package/dist/claude-md-gen.d.ts +8 -0
  2. package/dist/claude-md-gen.js +43 -26
  3. package/dist/compose.d.ts +14 -20
  4. package/dist/compose.js +15 -25
  5. package/dist/features/body-foot-util.d.ts +8 -4
  6. package/dist/features/body-foot-util.js +8 -4
  7. package/dist/features/claude-resources.d.ts +12 -0
  8. package/dist/features/claude-resources.js +13 -6
  9. package/dist/features/design-token-panel.d.ts +0 -12
  10. package/dist/features/design-token-panel.js +32 -93
  11. package/dist/features/doc-history.d.ts +18 -3
  12. package/dist/features/doc-history.js +45 -60
  13. package/dist/features/doc-tags.d.ts +9 -13
  14. package/dist/features/doc-tags.js +10 -26
  15. package/dist/features/dynamic-page-transition.d.ts +19 -30
  16. package/dist/features/dynamic-page-transition.js +21 -209
  17. package/dist/features/footer-taglist.d.ts +1 -1
  18. package/dist/features/footer-taglist.js +1 -1
  19. package/dist/features/footer.d.ts +3 -2
  20. package/dist/features/footer.js +3 -2
  21. package/dist/features/i18n.d.ts +13 -8
  22. package/dist/features/i18n.js +14 -9
  23. package/dist/features/image-enlarge.d.ts +7 -26
  24. package/dist/features/image-enlarge.js +7 -26
  25. package/dist/features/llms-txt.d.ts +3 -5
  26. package/dist/features/llms-txt.js +3 -5
  27. package/dist/features/search.d.ts +7 -3
  28. package/dist/features/search.js +7 -3
  29. package/dist/features/sidebar-resizer.d.ts +4 -8
  30. package/dist/features/sidebar-resizer.js +4 -8
  31. package/dist/features/sidebar-toggle.d.ts +7 -7
  32. package/dist/features/sidebar-toggle.js +7 -7
  33. package/dist/features/tag-governance.d.ts +14 -7
  34. package/dist/features/tag-governance.js +52 -8
  35. package/dist/features/tauri.d.ts +13 -10
  36. package/dist/features/tauri.js +16 -52
  37. package/dist/features/versioning.d.ts +12 -24
  38. package/dist/features/versioning.js +13 -39
  39. package/dist/index.js +2 -3
  40. package/dist/preset.d.ts +1 -0
  41. package/dist/preset.js +5 -0
  42. package/dist/prompts.d.ts +2 -0
  43. package/dist/prompts.js +1 -0
  44. package/dist/scaffold.d.ts +13 -6
  45. package/dist/scaffold.js +78 -59
  46. package/dist/utils.d.ts +10 -0
  47. package/dist/utils.js +14 -0
  48. package/dist/zfb-config-gen.d.ts +32 -20
  49. package/dist/zfb-config-gen.js +400 -53
  50. package/package.json +2 -2
  51. package/templates/base/pages/docs/[[...slug]].tsx +59 -0
  52. package/templates/base/pages/index.tsx +6 -41
  53. package/templates/base/scripts/setup-doc-skill.sh +261 -0
  54. package/templates/base/src/styles/global.css +15 -340
  55. package/templates/base/tsconfig.json +3 -26
  56. package/templates/features/i18n/files/pages/[locale]/docs/[[...slug]].tsx +88 -0
  57. package/templates/features/tagGovernance/files/scripts/tags-suggest.ts +3 -1
  58. package/dist/settings-gen.d.ts +0 -2
  59. package/dist/settings-gen.js +0 -319
  60. package/templates/base/.htmlvalidate.json +0 -5
  61. package/templates/base/.zfb/doc-history-meta.json +0 -1
  62. package/templates/base/pages/_data.ts +0 -160
  63. package/templates/base/pages/lib/_body-end-islands.tsx +0 -165
  64. package/templates/base/pages/lib/_chrome.ts +0 -167
  65. package/templates/base/pages/lib/_details.tsx +0 -29
  66. package/templates/base/pages/lib/_doc-route-entries.ts +0 -10
  67. package/templates/base/pages/lib/_extract-headings.ts +0 -37
  68. package/templates/base/pages/lib/_frontmatter-preview-data.ts +0 -27
  69. package/templates/base/pages/lib/_nav-source-cache.ts +0 -100
  70. package/templates/base/pages/lib/_nav-source-docs.ts +0 -17
  71. package/templates/base/pages/lib/_preset-generator.tsx +0 -81
  72. package/templates/base/pages/lib/_route-context.ts +0 -32
  73. package/templates/base/pages/lib/_search-widget.tsx +0 -17
  74. package/templates/base/pages/lib/doc-page-props.ts +0 -30
  75. package/templates/base/pages/lib/locale-merge.ts +0 -59
  76. package/templates/base/scripts/run-b4push.sh +0 -102
  77. package/templates/base/src/components/ai-chat-modal.tsx +0 -18
  78. package/templates/base/src/components/content/code-group.tsx +0 -3
  79. package/templates/base/src/components/content/content-admonition.tsx +0 -4
  80. package/templates/base/src/components/desktop-sidebar-toggle.tsx +0 -15
  81. package/templates/base/src/components/doc-history.tsx +0 -21
  82. package/templates/base/src/components/image-enlarge.tsx +0 -24
  83. package/templates/base/src/components/preset-generator.tsx +0 -14
  84. package/templates/base/src/components/sidebar-toggle.tsx +0 -6
  85. package/templates/base/src/components/sidebar-tree.tsx +0 -6
  86. package/templates/base/src/config/color-scheme-utils.ts +0 -69
  87. package/templates/base/src/config/color-schemes.ts +0 -165
  88. package/templates/base/src/config/docs-schema.ts +0 -95
  89. package/templates/base/src/config/frontmatter-preview-defaults.ts +0 -27
  90. package/templates/base/src/config/frontmatter-preview-renderers.tsx +0 -46
  91. package/templates/base/src/config/i18n.ts +0 -239
  92. package/templates/base/src/config/settings-types.ts +0 -45
  93. package/templates/base/src/config/sidebars.ts +0 -66
  94. package/templates/base/src/config/tag-vocabulary-types.ts +0 -4
  95. package/templates/base/src/config/tag-vocabulary.ts +0 -20
  96. package/templates/base/src/config/z-index-tokens.ts +0 -128
  97. package/templates/base/src/types/docs-entry.ts +0 -28
  98. package/templates/base/src/types/heading.ts +0 -5
  99. package/templates/base/src/types/locale.ts +0 -10
  100. package/templates/base/src/utils/base.ts +0 -164
  101. package/templates/base/src/utils/docs.ts +0 -446
  102. package/templates/base/src/utils/git-info.ts +0 -70
  103. package/templates/base/src/utils/github.ts +0 -22
  104. package/templates/base/src/utils/nav-scope.ts +0 -34
  105. package/templates/base/src/utils/sidebar.ts +0 -36
  106. package/templates/base/src/utils/slug.ts +0 -10
  107. package/templates/base/src/utils/smart-break.tsx +0 -12
  108. package/templates/base/src/utils/tags.ts +0 -83
  109. package/templates/base/zfb-shim.d.ts +0 -178
  110. package/templates/features/bodyFootUtil/files/src/utils/github.ts +0 -22
  111. package/templates/features/claudeResources/files/src/integrations/claude-resources/__tests__/escape-for-mdx.test.ts +0 -42
  112. package/templates/features/claudeResources/files/src/integrations/claude-resources/__tests__/generate.test.ts +0 -752
  113. package/templates/features/claudeResources/files/src/integrations/claude-resources/escape-for-mdx.ts +0 -97
  114. package/templates/features/claudeResources/files/src/integrations/claude-resources/generate.ts +0 -735
  115. package/templates/features/designTokenPanel/files/src/components/design-token-panel-bootstrap.tsx +0 -15
  116. package/templates/features/designTokenPanel/files/src/config/design-token-panel-config.ts +0 -435
  117. package/templates/features/designTokenPanel/files/src/config/design-tokens-manifest.ts +0 -174
  118. package/templates/features/designTokenPanel/files/src/lib/design-token-panel-bootstrap.ts +0 -30
  119. package/templates/features/docHistory/files/src/components/doc-history.tsx +0 -10
  120. package/templates/features/docHistory/files/src/types/doc-history.ts +0 -7
  121. package/templates/features/dynamicPageTransition/files/src/components/client-router-bootstrap.tsx +0 -72
  122. package/templates/features/i18n/files/pages/[locale]/index.tsx +0 -72
  123. package/templates/features/imageEnlarge/files/src/components/image-enlarge.tsx +0 -11
  124. package/templates/features/sidebarToggle/files/src/components/desktop-sidebar-toggle.tsx +0 -6
  125. package/templates/features/tauri/files/src/components/find-bar.tsx +0 -122
  126. package/templates/features/tauri/files/src/components/find-in-page-init.tsx +0 -59
  127. package/templates/features/tauri/files/src/utils/find-in-page.ts +0 -175
@@ -1,165 +0,0 @@
1
- /** @jsxRuntime automatic */
2
- /** @jsxImportSource preact */
3
- // Host-side body-end islands helper.
4
- //
5
- // Wave 8 (Path A — super-epic #1333 / child epic #1355) drops the local
6
- // SSR-skip wrapper functions in `@takazudo/zudo-doc/ssr-skip` and uses
7
- // zfb's native `<Island ssrFallback={...}>` API directly with the real
8
- // component constructors imported by the host.
9
- //
10
- // The previous indirection (page → wrapper → placeholder div) created an
11
- // orphan-component bug: the real components were `"use client"` modules
12
- // that no page module ever imported transitively, so zfb's island scanner
13
- // never walked page → real-component, the manifest never bound the marker
14
- // to the real constructor, and the bundle never contained the real
15
- // component body. PR #150 to zfb fixed the marker-name alignment but the
16
- // orphan problem stayed — see issue zudolab/zudo-doc#1355 Wave 7 report.
17
- //
18
- // This helper is the page → real-component import chain the scanner
19
- // needs. Each island below is composed with zfb's `<Island>` wrapper,
20
- // which emits `<div data-zfb-island-skip-ssr="<ComponentName>">…</div>`
21
- // at SSR (zfb's `captureComponentName` derives the marker from
22
- // `child.displayName ?? child.name`). Because the page imports this
23
- // file, and this file imports the real components, the scanner walks
24
- // page → helper → real component and registers the constructor under
25
- // the SSR marker name.
26
- //
27
- // Pattern mirrors `_header-with-defaults.tsx`: the JSX-shim widens
28
- // `Island`'s return type to `unknown`, so call-sites cast through
29
- // `as unknown as VNode` at the boundary.
30
-
31
- import type { VNode, JSX } from "preact";
32
- import { Island } from "@takazudo/zfb";
33
- import { settings } from "@/config/settings";
34
-
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
- // @slot:body-end-islands:imports
39
-
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.
43
- // @slot:body-end-islands:display-names
44
-
45
- /**
46
- * Default sr-only label rendered as the AiChatModal SSR fallback. This
47
- * mirrors the body-label string the deleted `AiChatModalIsland` wrapper
48
- * produced verbatim so assistive tech can discover the chat entrypoint
49
- * in the static HTML before JS hydration. English-only for now — the
50
- * previous default was also English-only; pass `aiChatBodyLabel` to
51
- * localise.
52
- */
53
- const DEFAULT_AI_CHAT_BODY_LABEL = "Ask a question about the documentation.";
54
-
55
- /** Props for {@link BodyEndIslands}. */
56
- export interface BodyEndIslandsProps {
57
- /** Base path the AI chat modal uses to construct API URLs. */
58
- basePath: string;
59
- /**
60
- * Sr-only label rendered as the AiChatModal SSR fallback. Defaults to
61
- * the English string. Pass a locale-translated string for non-default
62
- * locales so screen readers announce the chat entrypoint correctly
63
- * before hydration.
64
- */
65
- aiChatBodyLabel?: string;
66
- }
67
-
68
- /**
69
- * The default body-end islands a doc page may mount: the AI chat modal
70
- * (`<dialog>` overlay) and the image-enlarge dialog (mounted lazily based
71
- * on viewport scan). Each is feature-gated — the AI chat modal (and its
72
- * sr-only landmark heading) on `settings.aiAssistant`, and image-enlarge
73
- * on `settings.imageEnlarge` — so a feature-off consumer ships neither the
74
- * island marker nor a misleading landmark (zudolab/zudo-doc#2058).
75
- *
76
- * Optional feature islands (e.g. the design token panel bootstrap) are not
77
- * listed here: they are injected at the body-end-islands composition
78
- * anchors only when their feature is selected, so a feature-off scaffold
79
- * carries no trace of them.
80
- *
81
- * Each island is wrapped in `<Island ssrFallback>` so the heavy
82
- * component is NOT evaluated server-side — they depend on
83
- * `dialog.showModal()`, `localStorage`, `ResizeObserver`, runtime
84
- * fetch, etc. The hydration runtime swaps each placeholder on the
85
- * client.
86
- *
87
- * When `settings.aiAssistant` is enabled, the
88
- * `<h2 class="sr-only">AI Assistant</h2>` heading is emitted in the SSG
89
- * output so screen readers and crawlers can discover the chat section
90
- * landmark before JS hydration.
91
- */
92
- export function BodyEndIslands({
93
- basePath,
94
- aiChatBodyLabel = DEFAULT_AI_CHAT_BODY_LABEL,
95
- }: BodyEndIslandsProps): JSX.Element {
96
- // Gated on `settings.aiAssistant` (zudolab/zudo-doc#2058): when the AI
97
- // assistant feature is off, neither the AiChatModal island marker nor the
98
- // sr-only "AI Assistant" landmark heading should reach the SSG output —
99
- // otherwise feature-off consumers ship a dead island marker plus a
100
- // misleading screen-reader landmark for a section that never hydrates.
101
- // Same feature-gating pattern as the other optional body-end islands.
102
- //
103
- // KNOWN CAVEAT: zfb's island scanner walks the static `"use client"`
104
- // import chain, so gating this JSX removes the SSR marker and heading but
105
- // may NOT strip the AiChatModal bundle from the build output. Marker
106
- // removal is the agreed first fix (#2058); bundle stripping is out of scope.
107
- //
108
- // The sr-only <p> fallback keeps the body label in static HTML for screen
109
- // readers before JS hydration; sr-only keeps it invisible to sighted users.
110
- const aiAssistant = settings.aiAssistant ? (
111
- <>
112
- {/* Emits the "AI Assistant" heading in the SSG output so screen
113
- readers can discover the chat section landmark before JS
114
- hydration. */}
115
- <h2 class="sr-only">AI Assistant</h2>
116
- {
117
- Island({
118
- ssrFallback: <p class="sr-only">{aiChatBodyLabel}</p>,
119
- children: <AiChatModal basePath={basePath} />,
120
- }) as unknown as VNode
121
- }
122
- </>
123
- ) : null;
124
-
125
- // Gated on `settings.imageEnlarge` (zudolab/zudo-doc#2058). Same caveat as
126
- // the AI assistant gating: removing this JSX drops the SSR dialog shell and
127
- // island marker, but the bundle may persist via the static import scan.
128
- //
129
- // Wave 11 (zudolab/zudo-doc#1355): the SSR fallback is the empty, closed
130
- // `<dialog class="zd-enlarge-dialog ...">` shell so the dist HTML carries
131
- // one dialog from the start. Without this the smoke "exactly one
132
- // zd-enlarge-dialog element" assertion sees zero (skip-ssr placeholders are
133
- // empty divs) and the no-JS path has no dialog at all. Hydration replaces
134
- // this shell with the real ImageEnlarge component when the page goes idle.
135
- const imageEnlarge = settings.imageEnlarge
136
- ? (Island({
137
- when: "idle",
138
- ssrFallback: <ImageEnlargeSsrFallback />,
139
- children: <ImageEnlarge />,
140
- }) as unknown as VNode)
141
- : null;
142
-
143
- // Gated on `settings.mermaid`. Mirrors the imageEnlarge block: the SSR
144
- // fallback is an empty, closed `<dialog class="zd-mermaid-dialog ...">` so
145
- // the dist HTML carries one dialog from the start and hydration (when="idle")
146
- // swaps in the real component. Unlike images (SSR-wrapped by the MDX paragraph
147
- // override), mermaid renders client-side, so this island injects the enlarge
148
- // button into each rendered diagram container itself.
149
- const mermaidEnlarge = settings.mermaid
150
- ? (Island({
151
- when: "idle",
152
- ssrFallback: <MermaidEnlargeSsrFallback />,
153
- children: <MermaidEnlarge />,
154
- }) as unknown as VNode)
155
- : null;
156
-
157
- return (
158
- <>
159
- {aiAssistant}
160
- {imageEnlarge}
161
- {mermaidEnlarge}
162
- {/* @slot:body-end-islands:extra-islands */}
163
- </>
164
- );
165
- }
@@ -1,167 +0,0 @@
1
- /** @jsxRuntime automatic */
2
- /** @jsxImportSource preact */
3
- // Host chrome adapter — THE single host adapter for the page-chrome surface
4
- // (epic Collapse Wiring Shells #2420; HOSTCOLLAPSE #2427 collapsed the former
5
- // per-component `pages/lib/_*` chrome shells into this one module).
6
- //
7
- // It builds the host's REAL bindings ONCE and threads them through the public
8
- // `createChrome(routeContext, hostBindings)` builder, then re-exports the wired
9
- // page-chrome barrel (renderDocPage, HeaderWithDefaults, FooterWithDefaults,
10
- // HeadWithDefaults, composeMetaTitle, …). Every doc route + homepage chrome
11
- // import resolves here.
12
- //
13
- // - the reconstructed route context comes from the retained, vitest-safe
14
- // `./_route-context` seam (settings + i18n + URL/nav/slug helpers +
15
- // nav-source resolvers + route enumerators), fed the host content bridge
16
- // (`stableDocs`) so the content read + nav enumeration stay byte-identical;
17
- // - the genuinely host-bound slots (`hostBindings`): the real SearchWidget,
18
- // git-history manifest, sidebars config, frontmatter renderers/builder,
19
- // footer tag loader + vocabulary, body-end islands, DocHistory island, and
20
- // the showcase MDX content overrides (`mdxExtras`).
21
- //
22
- // Island-scanner contract (load-bearing): this module MUST keep the STATIC
23
- // imports of DocHistory (`@takazudo/zudo-doc/doc-history`), BodyEndIslands
24
- // (`./_body-end-islands`) and PresetGeneratorFallback (`./_preset-generator`).
25
- // After the collapse the only page→island import chain is
26
- // `pages/docs/*.tsx → _chrome.ts → {DocHistory, BodyEndIslands, PresetGenerator}`;
27
- // if any of these became a type-only or dynamic import the zfb island scanner
28
- // would stop walking it and the marker/bundle would silently drop.
29
-
30
- import type { ComponentChildren } from "preact";
31
- import type { ChromeHostBindings } from "@takazudo/zudo-doc/factory-context";
32
-
33
- import { createChrome } from "@takazudo/zudo-doc/chrome";
34
-
35
- import { settings } from "@/config/settings";
36
- import { defaultLocale } from "@/config/i18n";
37
- import { tagVocabulary } from "@/config/tag-vocabulary";
38
- import sidebars from "@/config/sidebars";
39
- import { frontmatterRenderers } from "@/config/frontmatter-preview-renderers";
40
- import { collectTags } from "@/utils/tags";
41
- import { toRouteSlug } from "@/utils/slug";
42
- import type { DocsEntry } from "@/types/docs-entry";
43
-
44
- import { routeContext } from "./_route-context";
45
- import { stableDocs, memoizeDerived } from "./_nav-source-cache";
46
- import { mergeLocaleDocs } from "./locale-merge";
47
- import { SearchWidget } from "./_search-widget";
48
- import { BodyEndIslands as BodyEndIslandsSeam } from "./_body-end-islands";
49
- import { buildFrontmatterPreviewEntries } from "./_frontmatter-preview-data";
50
- import { DetailsWrapper } from "./_details";
51
- import { PresetGeneratorFallback } from "./_preset-generator";
52
- import { DocHistory } from "@takazudo/zudo-doc/doc-history";
53
- import { HtmlPreviewWrapper, type HtmlPreviewWrapperProps } from "@takazudo/zudo-doc/html-preview-wrapper";
54
- // SSR author + date metadata — `#doc-history-meta` is the build-time manifest
55
- // alias (esbuild-inlined, no fs). Static import is load-bearing for the island
56
- // scanner chain noted above.
57
- import docHistoryMeta from "#doc-history-meta";
58
-
59
- // ---------------------------------------------------------------------------
60
- // Footer tag loader (host-side; moved verbatim from the former
61
- // _footer-with-defaults.tsx). Reads collections via
62
- // stableDocs / memoizeDerived and aggregates tags per locale. Threaded as
63
- // hostBindings.loadTagsForLocale.
64
- // ---------------------------------------------------------------------------
65
-
66
- function loadTagsForLocale(lang: string) {
67
- if (lang === defaultLocale) {
68
- const baseDocs = stableDocs("docs");
69
- return memoizeDerived([baseDocs], "footerTaglist;default", () => {
70
- const docs: DocsEntry[] = baseDocs.filter(
71
- (d) => !d.data.draft && !d.data.unlisted && !d.data.category_no_page,
72
- );
73
- const tagMap = collectTags(docs, (id, data) => data.slug ?? toRouteSlug(id));
74
- return [...tagMap.values()].sort((a, b) => a.tag.localeCompare(b.tag, lang));
75
- });
76
- }
77
- const baseDocs = stableDocs("docs");
78
- const localeDocs = stableDocs(`docs-${lang}`);
79
- return memoizeDerived([baseDocs, localeDocs], `footerTaglist;${lang}`, () => {
80
- const result = mergeLocaleDocs({
81
- baseDocs: baseDocs.filter((d) => !d.data.draft),
82
- localeDocs: localeDocs.filter((d) => !d.data.draft),
83
- applyDefaultLocaleOnlyFilter: true,
84
- });
85
- const docs: DocsEntry[] = result.docs.filter((d) => !d.data.category_no_page);
86
- const tagMap = collectTags(docs, (id, data) => data.slug ?? toRouteSlug(id));
87
- return [...tagMap.values()].sort((a, b) => a.tag.localeCompare(b.tag, lang));
88
- });
89
- }
90
-
91
- // ---------------------------------------------------------------------------
92
- // Showcase MDX content overrides (host-bound; identical to the former
93
- // pages/_mdx-components.ts `extras` block — kept in lockstep). Threaded via
94
- // hostBindings.mdxExtras; the package factory merges them over its defaults.
95
- // ---------------------------------------------------------------------------
96
-
97
- /** MDX-tag stub: renders nothing (Preact null-vnode path). */
98
- const MdxStub = (_props: unknown) => null;
99
-
100
- /** SSR pass-through for `<Island when=…>` — renders children, ignores `when`. */
101
- function IslandWrapper(props: {
102
- when?: "load" | "idle" | "visible" | "media";
103
- children?: ComponentChildren;
104
- }): ComponentChildren {
105
- return props.children ?? null;
106
- }
107
-
108
- const HtmlPreviewWithGlobalConfig = (props: HtmlPreviewWrapperProps) =>
109
- HtmlPreviewWrapper({ globalConfig: settings.htmlPreview ?? null, ...props });
110
-
111
- const mdxExtras = {
112
- HtmlPreview: HtmlPreviewWithGlobalConfig,
113
- Details: DetailsWrapper,
114
- SmartBreak: MdxStub,
115
- Island: IslandWrapper,
116
- PresetGenerator: PresetGeneratorFallback,
117
- Avatar: MdxStub,
118
- Button: MdxStub,
119
- Card: MdxStub,
120
- MyComponent: MdxStub,
121
- PageLayout: MdxStub,
122
- } as unknown as Record<string, (props: Record<string, unknown>) => unknown>;
123
-
124
- // ---------------------------------------------------------------------------
125
- // The host's real bindings (the 10 ChromeHostBindings slots).
126
- // ---------------------------------------------------------------------------
127
-
128
- const hostBindings: ChromeHostBindings = {
129
- SearchWidget: SearchWidget as ChromeHostBindings["SearchWidget"],
130
- docHistoryMeta: docHistoryMeta as Record<string, unknown>,
131
- sidebarsConfig: sidebars as unknown as Record<string, unknown>,
132
- frontmatterRenderers: frontmatterRenderers as unknown as ChromeHostBindings["frontmatterRenderers"],
133
- buildFrontmatterPreviewEntries:
134
- buildFrontmatterPreviewEntries as unknown as ChromeHostBindings["buildFrontmatterPreviewEntries"],
135
- loadTagsForLocale: loadTagsForLocale as unknown as ChromeHostBindings["loadTagsForLocale"],
136
- tagVocabulary,
137
- BodyEndIslands: BodyEndIslandsSeam as unknown as ChromeHostBindings["BodyEndIslands"],
138
- DocHistory: DocHistory as unknown as ChromeHostBindings["DocHistory"],
139
- mdxExtras: mdxExtras as ChromeHostBindings["mdxExtras"],
140
- };
141
-
142
- // ---------------------------------------------------------------------------
143
- // Build the wired page-chrome surface ONCE from the route context + real host
144
- // bindings, and re-export the barrel. Every omitted slot falls back to the
145
- // package stub (byte-identical to the injected package-routes path); each REAL
146
- // slot above overrides it.
147
- // ---------------------------------------------------------------------------
148
-
149
- const chrome = createChrome(routeContext, hostBindings);
150
-
151
- export type { RenderDocPageOptions } from "@takazudo/zudo-doc/doc-page-renderer";
152
-
153
- export const {
154
- composeMetaTitle,
155
- HeadWithDefaults,
156
- HeaderWithDefaults,
157
- FooterWithDefaults,
158
- SidebarWithDefaults,
159
- renderDocPage,
160
- VersionsPageView,
161
- collectTagMapForLocale,
162
- TagDetailPageView,
163
- TagsIndexPageView,
164
- SiteTreeNavWrapper,
165
- BodyEndIslands,
166
- HomePageView,
167
- } = chrome;
@@ -1,29 +0,0 @@
1
- /** @jsxRuntime automatic */
2
- /** @jsxImportSource preact */
3
- // Host-side MDX wrapper for <Details> — trivial passthrough to the v2
4
- // Details component.
5
- //
6
- // The v2 Details component accepts standard Preact children. MDX passes slot
7
- // content as `children`, so the mapping is direct. The title prop (default
8
- // "Details") is forwarded unchanged.
9
-
10
- import type { ComponentChildren, VNode } from "preact";
11
- import { Details as DetailsV2 } from "@takazudo/zudo-doc/details";
12
-
13
- export interface DetailsWrapperProps {
14
- /** Summary label shown in the <summary> element. Defaults to "Details". */
15
- title?: string;
16
- /** MDX slot content rendered inside the collapsed body. */
17
- children?: ComponentChildren;
18
- }
19
-
20
- /**
21
- * Passthrough wrapper for the v2 Details component.
22
- *
23
- * Used in pages/_mdx-components.ts as the Details binding so that MDX
24
- * content using `<Details title="...">...</Details>` renders correctly
25
- * on zfb routes.
26
- */
27
- export function DetailsWrapper({ title, children }: DetailsWrapperProps): VNode {
28
- return <DetailsV2 title={title}>{children}</DetailsV2>;
29
- }
@@ -1,10 +0,0 @@
1
- // Thin shim — the memoized doc-route-entry builder rides on the unified
2
- // ChromeContext now (epic Collapse Wiring Shells #2420, FACTORIES #2424).
3
- // `createRouteContext` (in _route-context.ts) assembles `buildDocRouteEntries`
4
- // as part of the route context; this module just re-exports it so the doc-route
5
- // page files keep importing it from here unchanged.
6
-
7
- export type { DocRouteEntry, BuildDocRouteEntriesArgs } from "@takazudo/zudo-doc/doc-route-entries";
8
- import { routeContext } from "./_route-context";
9
-
10
- export const { buildDocRouteEntries } = routeContext;
@@ -1,37 +0,0 @@
1
- // Thin showcase wrapper around @takazudo/zudo-doc/extract-headings.
2
- // The package-side extractHeadings takes settings as explicit params (no
3
- // project singleton import). This wrapper re-reads the project settings and
4
- // passes them through so call sites in _doc-route-entries.ts continue to
5
- // call extractHeadings(body) without change.
6
- //
7
- // Moved to the package as part of the package-first migration (#2321, S4 #2327).
8
-
9
- import { settings } from "../../src/config/settings";
10
- export type { HeadingIdStrategy, HeadingItem } from "@takazudo/zudo-doc/extract-headings";
11
- export { slugify } from "@takazudo/zudo-doc/extract-headings";
12
- import { extractHeadings as _extractHeadings } from "@takazudo/zudo-doc/extract-headings";
13
- import type { HeadingItem, HeadingIdStrategy } from "@takazudo/zudo-doc/extract-headings";
14
-
15
- /**
16
- * Extract TOC headings from a raw MDX/markdown body, using the project's
17
- * configured `tocMinDepth`, `tocMaxDepth`, and `headingIdStrategy` from
18
- * `src/config/settings`.
19
- *
20
- * Accepts the same optional `opts` overrides as the underlying package
21
- * function (for tests that want to override the depth window or strategy
22
- * without touching the global settings).
23
- */
24
- export function extractHeadings(
25
- body: string,
26
- opts?: {
27
- tocMinDepth?: number;
28
- tocMaxDepth?: number;
29
- strategy?: HeadingIdStrategy;
30
- },
31
- ): HeadingItem[] {
32
- return _extractHeadings(body, {
33
- tocMinDepth: opts?.tocMinDepth ?? settings.tocMinDepth,
34
- tocMaxDepth: opts?.tocMaxDepth ?? settings.tocMaxDepth,
35
- strategy: opts?.strategy ?? settings.headingIdStrategy,
36
- });
37
- }
@@ -1,27 +0,0 @@
1
- // Host-side filter helper that turns a doc entry's `data` (frontmatter)
2
- // into the `entries` array expected by `<FrontmatterPreview>`.
3
- //
4
- // The v2 component (packages/zudo-doc/src/metainfo/frontmatter-preview.tsx)
5
- // is a pure renderer — the caller is responsible for:
6
- //
7
- // 1. Honouring `settings.frontmatterPreview === false` (block hidden everywhere).
8
- // 2. Removing schema-managed system keys (DEFAULT_FRONTMATTER_IGNORE_KEYS).
9
- // 3. Applying the host's `ignoreKeys` (replaces the default list) or
10
- // `extraIgnoreKeys` (adds to the default).
11
- // 4. Skipping null/undefined values.
12
- //
13
- // Returning an empty array suppresses the block — the v2 component
14
- // short-circuits with `null` when `entries` is empty.
15
- //
16
- // Custom per-key renderers (from `src/config/frontmatter-preview-renderers.tsx`)
17
- // are wired by the page template directly on the `<FrontmatterPreview>` call site
18
- // via the `renderers` prop. This helper only produces the filtered entries array.
19
-
20
- import { createBuildFrontmatterPreviewEntries } from "@takazudo/zudo-doc/frontmatter-preview-data";
21
- import { settings } from "@/config/settings";
22
- import { DEFAULT_FRONTMATTER_IGNORE_KEYS } from "@/config/frontmatter-preview-defaults";
23
-
24
- export const buildFrontmatterPreviewEntries = createBuildFrontmatterPreviewEntries({
25
- frontmatterPreview: settings.frontmatterPreview,
26
- defaultIgnoreKeys: DEFAULT_FRONTMATTER_IGNORE_KEYS,
27
- });
@@ -1,100 +0,0 @@
1
- // Snapshot-anchored memoization for nav-source arrays.
2
- //
3
- // WHY THIS EXISTS — build-time array-identity stabilization
4
- // --------------------------------------------------------
5
- // zfb's `getCollection(name)` returns a FRESH array of FRESH entry objects on
6
- // every call (it `.map()`s over the underlying snapshot — see
7
- // `node_modules/@takazudo/zfb/dist/content.js`). The doc-route `paths()`
8
- // functions are re-invoked once per built page (e.g. ~123× for the EN docs
9
- // route), and the per-page sidebar + header each re-derive their nav source
10
- // independently. The net effect: `buildNavTree` is called ~2× the page count
11
- // (~900 calls for 251 pages), and every call recomputed an O(n log n)
12
- // stringify+sort cache key over the entire docs collection.
13
- //
14
- // The fix anchors identity on the ONE thing stable across the whole build:
15
- // `getContentSnapshot().collections[name]` — the readonly snapshot array zfb
16
- // installs once at worker boot (verified INSTALLED during `pnpm build`,
17
- // collections `[docs, docs-ja, docs-v-*]`). We memoize the bridged +
18
- // draft-filtered arrays on that anchor (WeakMap) so every repeat caller
19
- // receives the SAME array instance. `buildNavTree`'s WeakMap fast-path
20
- // (`src/utils/docs.ts`) then short-circuits the key computation on identity,
21
- // collapsing ~900 key computations to the handful of distinct
22
- // (snapshot, locale, version, options) inputs.
23
- //
24
- // FALLBACK (no snapshot): unit tests and direct Node invocations run the
25
- // filesystem path with no installed snapshot. There is no stable anchor array
26
- // to key on, AND the underlying `getCollection(name)` result can legitimately
27
- // change between calls in that mode (e.g. a test swapping its mock for the same
28
- // collection name). So we DELIBERATELY do not memoize the no-snapshot path —
29
- // it computes fresh each call. The perf win targets the real build, where the
30
- // snapshot is always installed; correctness wins in the fallback path.
31
- //
32
- // HMR intent preserved: a content edit produces a NEW snapshot object (new
33
- // `collections[name]` array identity), so every memo here misses and
34
- // recomputes — matching the old content-keyed cache's change detection.
35
- //
36
- // PACKAGE SPLIT (epic #2344, S6):
37
- // `memoizeDerived` — the generic two-level WeakMap memo — is now in the
38
- // package at @takazudo/zudo-doc/nav-source-cache (no zfb imports needed).
39
- // `stableDocs` stays here because it imports `getCollection` /
40
- // `getContentSnapshot` from "zfb/content", which is a virtual module
41
- // provided by the zfb SSG build system at compile time — not an npm package.
42
-
43
- import { getCollection, getContentSnapshot } from "zfb/content";
44
- import { bridgeDocsEntries, type ZfbDocsData } from "../_data";
45
- import type { DocPageEntry } from "./doc-page-props";
46
-
47
- // Re-export memoizeDerived from the package (pure, no zfb dep).
48
- export { memoizeDerived } from "@takazudo/zudo-doc/nav-source-cache";
49
-
50
- // ---------------------------------------------------------------------------
51
- // Snapshot anchor → stable bridged arrays
52
- // ---------------------------------------------------------------------------
53
-
54
- /**
55
- * The stable per-build anchor array for a collection: the raw readonly
56
- * snapshot array zfb installed once. Returns `undefined` when no snapshot is
57
- * installed (filesystem-fallback path) so callers take the fresh, unmemoized
58
- * branch.
59
- */
60
- function snapshotAnchor(name: string): readonly unknown[] | undefined {
61
- return getContentSnapshot()?.collections[name];
62
- }
63
-
64
- // Per-anchor-array memo of the bridged + draft-filtered entries. Keyed on the
65
- // snapshot array identity so a new build snapshot invalidates automatically.
66
- const bridgedByAnchor = new WeakMap<object, DocPageEntry[]>();
67
-
68
- function buildBridged(collectionName: string): DocPageEntry[] {
69
- const raw = getCollection<ZfbDocsData>(collectionName);
70
- return bridgeDocsEntries(raw, collectionName).filter(
71
- (d) => !d.data.draft,
72
- );
73
- }
74
-
75
- /**
76
- * Identity-stable, draft-filtered `DocPageEntry[]` for a collection.
77
- *
78
- * Returns the SAME array instance on every call within one build (anchored on
79
- * the snapshot array), so downstream derived arrays — and ultimately
80
- * `buildNavTree` — can rely on reference equality. The entries carry the full
81
- * `DocPageEntry` shape (Content, body, module_specifier, id, collection) the
82
- * route `paths()` props need.
83
- *
84
- * Passed as `stableDocs` to `createNavSourceDocs` in `_nav-source-docs.ts`.
85
- */
86
- export function stableDocs(collectionName: string): DocPageEntry[] {
87
- const anchor = snapshotAnchor(collectionName);
88
-
89
- // No snapshot (fs-fallback / unit tests): compute fresh, do not memoize —
90
- // see the no-snapshot rationale in the module header.
91
- if (anchor === undefined) {
92
- return buildBridged(collectionName);
93
- }
94
-
95
- const cached = bridgedByAnchor.get(anchor);
96
- if (cached) return cached;
97
- const built = buildBridged(collectionName);
98
- bridgedByAnchor.set(anchor, built);
99
- return built;
100
- }
@@ -1,17 +0,0 @@
1
- // Thin shim — nav-source resolvers ride on the unified ChromeContext now
2
- // (epic Collapse Wiring Shells #2420, FACTORIES #2424). The reconstructed
3
- // `createRouteContext` (in _route-context.ts) builds the identity-stable
4
- // nav-source API as part of the route context; this module just re-exports the
5
- // bindings so the existing call sites (route files, nav wrappers, _nav-data-prep,
6
- // route-enumerators) keep importing them from here unchanged.
7
-
8
- export type { NavSourceDocs, NavSourceOptions } from "@takazudo/zudo-doc/nav-source-docs";
9
- import { routeContext } from "./_route-context";
10
-
11
- export const {
12
- resolveNavSource,
13
- resolveVersionedLocaleSource,
14
- loadNavSourceDocs,
15
- stableMergeCategoryMeta,
16
- stableNavDocs,
17
- } = routeContext;
@@ -1,81 +0,0 @@
1
- /** @jsxRuntime automatic */
2
- /** @jsxImportSource preact */
3
- // SSR fallback shell for the <PresetGenerator> interactive form.
4
- //
5
- // The real component (src/components/preset-generator.tsx) is a large
6
- // client-only island. This file is imported transitively from page modules
7
- // (pages/docs/[...slug].tsx → _mdx-components.ts → here), so zfb's island
8
- // scanner walks the static import chain and registers PresetGenerator in the
9
- // manifest. Without this import, the scanner never finds the component and
10
- // client-side hydration never fires (orphan-component problem; same root
11
- // cause fixed for body-end islands in _body-end-islands.tsx).
12
- //
13
- // The fallback renders all 8 section headings as static SSR HTML so:
14
- // 1. Screen readers and search engines see the section structure (a11y/SEO).
15
- // 2. Layout does not collapse to nothing while JS loads (no-JS layout).
16
- // 3. The scanner traces this file → preset-generator.tsx via the Island child
17
- // and registers PresetGenerator in the manifest for client-side mounting.
18
- //
19
- // Uses the canonical `<Island ssrFallback>` API (zfb) so the scanner can
20
- // connect the import to the manifest entry and the hydration runtime can
21
- // mount the real form into the skip-ssr placeholder on the client.
22
-
23
- import type { VNode } from "preact";
24
- import { HeadingH3 } from "@takazudo/zudo-doc/content";
25
- import { Island } from "@takazudo/zfb";
26
- import PresetGenerator from "@/components/preset-generator";
27
-
28
- // Pin displayName so zfb's captureComponentName produces a stable marker
29
- // name even after the SSR pipeline runs through a function-name-rewriting
30
- // layer. Matches the data-zfb-island-skip-ssr attribute value the runtime
31
- // queries. Mirrors the pattern in _body-end-islands.tsx.
32
- (PresetGenerator as { displayName?: string }).displayName = "PresetGenerator";
33
-
34
- // Heading text for each of the 8 sections — must match the original
35
- // SectionHeading calls in src/components/preset-generator.tsx exactly
36
- // so the SSR fallback and the real component render the same section labels.
37
- // Order must mirror the JSX source order in preset-generator.tsx — do NOT
38
- // sort alphabetically. The array drives the SSR fallback heading sequence
39
- // shown to screen readers and visible before JS hydration.
40
- const SECTION_HEADINGS = [
41
- "Project Name",
42
- "Default Language",
43
- "Color Scheme Mode",
44
- "Color Scheme",
45
- "Features",
46
- "Header right items",
47
- "Markdown Options",
48
- "Package Manager",
49
- ] as const;
50
-
51
- /**
52
- * Static SSR fallback for the interactive PresetGenerator form.
53
- *
54
- * Renders all 8 section headings as static HTML for a11y/SEO and no-JS
55
- * layout stability. Uses Island with ssrFallback so the zfb scanner traces
56
- * this file → preset-generator.tsx and registers the real component in the
57
- * island manifest for client-side mounting.
58
- */
59
- export function PresetGeneratorFallback(): VNode {
60
- const fallback = (
61
- <div class="zd-preset-gen-fallback">
62
- {SECTION_HEADINGS.map((heading) => (
63
- <section key={heading}>
64
- <HeadingH3>{heading}</HeadingH3>
65
- </section>
66
- ))}
67
- </div>
68
- );
69
-
70
- // Island with ssrFallback:
71
- // - SSR emits the section headings as static HTML inside the skip-ssr div.
72
- // - The scanner reads children.type = PresetGenerator → registers it in
73
- // the manifest under "PresetGenerator".
74
- // - The hydration runtime mounts the real interactive form into the
75
- // skip-ssr placeholder on the client after load.
76
- return Island({
77
- when: "load",
78
- ssrFallback: fallback,
79
- children: <PresetGenerator />,
80
- }) as unknown as VNode;
81
- }