create-zudo-doc 3.2.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 (122) 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/scaffold.d.ts +13 -6
  41. package/dist/scaffold.js +64 -45
  42. package/dist/utils.d.ts +10 -0
  43. package/dist/utils.js +14 -0
  44. package/dist/zfb-config-gen.d.ts +32 -20
  45. package/dist/zfb-config-gen.js +400 -53
  46. package/package.json +2 -2
  47. package/templates/base/pages/docs/[[...slug]].tsx +59 -0
  48. package/templates/base/pages/index.tsx +6 -41
  49. package/templates/base/src/styles/global.css +15 -340
  50. package/templates/base/tsconfig.json +3 -26
  51. package/templates/features/i18n/files/pages/[locale]/docs/[[...slug]].tsx +88 -0
  52. package/templates/features/tagGovernance/files/scripts/tags-suggest.ts +3 -1
  53. package/dist/settings-gen.d.ts +0 -2
  54. package/dist/settings-gen.js +0 -320
  55. package/templates/base/.htmlvalidate.json +0 -5
  56. package/templates/base/.zfb/doc-history-meta.json +0 -1
  57. package/templates/base/pages/_data.ts +0 -160
  58. package/templates/base/pages/lib/_body-end-islands.tsx +0 -165
  59. package/templates/base/pages/lib/_chrome.ts +0 -167
  60. package/templates/base/pages/lib/_details.tsx +0 -29
  61. package/templates/base/pages/lib/_doc-route-entries.ts +0 -10
  62. package/templates/base/pages/lib/_extract-headings.ts +0 -37
  63. package/templates/base/pages/lib/_frontmatter-preview-data.ts +0 -27
  64. package/templates/base/pages/lib/_nav-source-cache.ts +0 -100
  65. package/templates/base/pages/lib/_nav-source-docs.ts +0 -17
  66. package/templates/base/pages/lib/_preset-generator.tsx +0 -81
  67. package/templates/base/pages/lib/_route-context.ts +0 -32
  68. package/templates/base/pages/lib/_search-widget.tsx +0 -17
  69. package/templates/base/pages/lib/doc-page-props.ts +0 -30
  70. package/templates/base/pages/lib/locale-merge.ts +0 -59
  71. package/templates/base/scripts/run-b4push.sh +0 -102
  72. package/templates/base/src/components/ai-chat-modal.tsx +0 -18
  73. package/templates/base/src/components/content/code-group.tsx +0 -3
  74. package/templates/base/src/components/content/content-admonition.tsx +0 -4
  75. package/templates/base/src/components/desktop-sidebar-toggle.tsx +0 -15
  76. package/templates/base/src/components/doc-history.tsx +0 -21
  77. package/templates/base/src/components/image-enlarge.tsx +0 -24
  78. package/templates/base/src/components/preset-generator.tsx +0 -14
  79. package/templates/base/src/components/sidebar-toggle.tsx +0 -6
  80. package/templates/base/src/components/sidebar-tree.tsx +0 -6
  81. package/templates/base/src/config/color-scheme-utils.ts +0 -69
  82. package/templates/base/src/config/color-schemes.ts +0 -165
  83. package/templates/base/src/config/docs-schema.ts +0 -95
  84. package/templates/base/src/config/frontmatter-preview-defaults.ts +0 -27
  85. package/templates/base/src/config/frontmatter-preview-renderers.tsx +0 -46
  86. package/templates/base/src/config/i18n.ts +0 -239
  87. package/templates/base/src/config/settings-types.ts +0 -45
  88. package/templates/base/src/config/sidebars.ts +0 -66
  89. package/templates/base/src/config/tag-vocabulary-types.ts +0 -4
  90. package/templates/base/src/config/tag-vocabulary.ts +0 -20
  91. package/templates/base/src/config/z-index-tokens.ts +0 -128
  92. package/templates/base/src/types/docs-entry.ts +0 -28
  93. package/templates/base/src/types/heading.ts +0 -5
  94. package/templates/base/src/types/locale.ts +0 -10
  95. package/templates/base/src/utils/base.ts +0 -164
  96. package/templates/base/src/utils/docs.ts +0 -446
  97. package/templates/base/src/utils/git-info.ts +0 -70
  98. package/templates/base/src/utils/github.ts +0 -22
  99. package/templates/base/src/utils/nav-scope.ts +0 -34
  100. package/templates/base/src/utils/sidebar.ts +0 -36
  101. package/templates/base/src/utils/slug.ts +0 -10
  102. package/templates/base/src/utils/smart-break.tsx +0 -12
  103. package/templates/base/src/utils/tags.ts +0 -83
  104. package/templates/base/zfb-shim.d.ts +0 -183
  105. package/templates/features/bodyFootUtil/files/src/utils/github.ts +0 -22
  106. package/templates/features/claudeResources/files/src/integrations/claude-resources/__tests__/escape-for-mdx.test.ts +0 -42
  107. package/templates/features/claudeResources/files/src/integrations/claude-resources/__tests__/generate.test.ts +0 -752
  108. package/templates/features/claudeResources/files/src/integrations/claude-resources/escape-for-mdx.ts +0 -97
  109. package/templates/features/claudeResources/files/src/integrations/claude-resources/generate.ts +0 -735
  110. package/templates/features/designTokenPanel/files/src/components/design-token-panel-bootstrap.tsx +0 -15
  111. package/templates/features/designTokenPanel/files/src/config/design-token-panel-config.ts +0 -435
  112. package/templates/features/designTokenPanel/files/src/config/design-tokens-manifest.ts +0 -174
  113. package/templates/features/designTokenPanel/files/src/lib/design-token-panel-bootstrap.ts +0 -30
  114. package/templates/features/docHistory/files/src/components/doc-history.tsx +0 -10
  115. package/templates/features/docHistory/files/src/types/doc-history.ts +0 -7
  116. package/templates/features/dynamicPageTransition/files/src/components/client-router-bootstrap.tsx +0 -72
  117. package/templates/features/i18n/files/pages/[locale]/index.tsx +0 -72
  118. package/templates/features/imageEnlarge/files/src/components/image-enlarge.tsx +0 -11
  119. package/templates/features/sidebarToggle/files/src/components/desktop-sidebar-toggle.tsx +0 -6
  120. package/templates/features/tauri/files/src/components/find-bar.tsx +0 -122
  121. package/templates/features/tauri/files/src/components/find-in-page-init.tsx +0 -59
  122. package/templates/features/tauri/files/src/utils/find-in-page.ts +0 -175
@@ -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
- }
@@ -1,32 +0,0 @@
1
- // Host route context — the reconstructed RouteContext (settings + i18n + URL
2
- // helpers + nav/slug helpers + identity-stable nav-source resolvers + doc-route
3
- // + route enumerators), built ONCE via the public `createRouteContext`
4
- // (epic Collapse Wiring Shells #2420, FACTORIES #2424).
5
- //
6
- // Kept SEPARATE from `_chrome.ts` so the data shells (`_nav-source-docs`
7
- // / `_doc-route-entries` / `route-enumerators`) — and the unit tests that import
8
- // them — depend ONLY on this lightweight module, NOT on the chrome host bindings
9
- // (which pull the build-time `#doc-history-meta` alias + island components that
10
- // don't resolve under vitest).
11
- //
12
- // The host content bridge (`stableDocs`) is injected so the docs read + nav
13
- // enumeration match the project's existing `pages/*` paths() exactly (host
14
- // `bridgeDocsEntries` over the `zfb/content` snapshot), not the package default.
15
-
16
- import { createRouteContext } from "@takazudo/zudo-doc/route-context";
17
- import type { ColorScheme } from "@takazudo/zudo-doc/color-scheme-utils";
18
- import { settings } from "@/config/settings";
19
- import { translations } from "@/config/i18n";
20
- import { tagVocabulary } from "@/config/tag-vocabulary";
21
- import { colorSchemes } from "@/config/color-schemes";
22
- import { stableDocs } from "./_nav-source-cache";
23
-
24
- export const routeContext = createRouteContext(
25
- {
26
- settings,
27
- translations,
28
- tagVocabulary,
29
- colorSchemes: colorSchemes as unknown as Record<string, ColorScheme>,
30
- },
31
- { stableDocs },
32
- );
@@ -1,17 +0,0 @@
1
- /** @jsxRuntime automatic */
2
- /** @jsxImportSource preact */
3
- // Host thin-stub — see @takazudo/zudo-doc/search-widget (epic #2344, S5).
4
- // Injects the host's base path and re-exports the package SearchWidget.
5
- import type { JSX } from "preact";
6
- import {
7
- SearchWidget as PackageSearchWidget,
8
- type SearchWidgetProps as PackageSearchWidgetProps,
9
- } from "@takazudo/zudo-doc/search-widget";
10
- import { withBase } from "@/utils/base";
11
-
12
- export type SearchWidgetProps = Omit<PackageSearchWidgetProps, "base">;
13
-
14
- /** Locale-aware search widget — thin host stub that injects the base path. */
15
- export function SearchWidget(props: SearchWidgetProps): JSX.Element {
16
- return <PackageSearchWidget {...props} base={withBase("/")} />;
17
- }
@@ -1,30 +0,0 @@
1
- // Thin stub — types moved to the package (epic #2344, S6).
2
- // Re-exports the shared discriminated-union props types for all 4 doc-route
3
- // pages from @takazudo/zudo-doc/doc-page-props.
4
- //
5
- // S5 and downstream (S7) consumers import `DocPageBaseProps`, `DocPageEntry`,
6
- // `AutoIndexNode`, `DocPageEntryProps`, `DocPageAutoIndexProps` from this path
7
- // unchanged — all are re-exported below.
8
-
9
- export type {
10
- DocNavNode,
11
- DocPageEntry,
12
- DocPageFrontmatter,
13
- AutoIndexNode,
14
- DocPageEntryProps,
15
- DocPageAutoIndexProps,
16
- DocPageBaseProps,
17
- HeadingItem,
18
- } from "@takazudo/zudo-doc/doc-page-props";
19
-
20
- // Backward-compatible alias: downstream callers that import `NavNode` from
21
- // this path (e.g. _doc-route-entries.ts, route-enumerators.ts) continue to
22
- // resolve. `DocNavNode` is structurally identical to the host's `NavNode` from
23
- // src/utils/docs.ts (same required fields, same optional fields).
24
- export type { DocNavNode as NavNode } from "@takazudo/zudo-doc/doc-page-props";
25
-
26
- // Backward-compatible alias: `BreadcrumbItem` was previously imported from
27
- // @/utils/docs in some files. The package's `DocPageBaseProps` uses
28
- // `BreadcrumbItem` from @takazudo/zudo-doc/breadcrumb/types — re-export it
29
- // here so callers importing from this path still resolve.
30
- export type { BreadcrumbItem } from "@takazudo/zudo-doc/breadcrumb";
@@ -1,59 +0,0 @@
1
- // Thin stub — locale-merge moved to the package (epic #2344, S6).
2
- // Re-exports the pure merge functions from @takazudo/zudo-doc/locale-merge
3
- // and provides backward-compatible wrappers that inject the host singletons.
4
- //
5
- // `mergeLocaleDocs` is the main export: now the package function accepts an
6
- // optional `isDefaultLocaleOnlyPath` injection in its options object. The host
7
- // wrapper below injects the host's `isDefaultLocaleOnlyPath` automatically
8
- // so all existing call sites — which pass `applyDefaultLocaleOnlyFilter: true`
9
- // without explicitly passing the predicate — continue to work unchanged.
10
- //
11
- // `mergeCategoryMeta` is kept as a host-only helper (it wraps `loadCategoryMeta`
12
- // from @/utils/docs which is a host import). The package's `nav-source-docs`
13
- // factory now owns the merged-category-meta caching; this re-export is kept
14
- // for any remaining host call sites.
15
-
16
- export type {
17
- MergeDocsEntry,
18
- MergeLocaleDocsOptions,
19
- MergeLocaleDocsResult,
20
- } from "@takazudo/zudo-doc/locale-merge";
21
- import { mergeLocaleDocs as _mergeLocaleDocs } from "@takazudo/zudo-doc/locale-merge";
22
- import type { MergeLocaleDocsOptions, MergeLocaleDocsResult, MergeDocsEntry } from "@takazudo/zudo-doc/locale-merge";
23
- import { isDefaultLocaleOnlyPath } from "@/utils/base";
24
- import { loadCategoryMeta } from "@/utils/docs";
25
- import type { CategoryMeta } from "@/utils/docs";
26
-
27
- /**
28
- * Merge locale docs with base-locale fallbacks.
29
- *
30
- * Thin host wrapper around the package's `mergeLocaleDocs` that injects
31
- * `isDefaultLocaleOnlyPath` from `@/utils/base` automatically. Existing call
32
- * sites that pass `applyDefaultLocaleOnlyFilter: true` continue to work
33
- * without change — the predicate is now injected rather than module-imported.
34
- */
35
- export function mergeLocaleDocs<T extends MergeDocsEntry = MergeDocsEntry>(
36
- options: Omit<MergeLocaleDocsOptions<T>, "isDefaultLocaleOnlyPath">,
37
- ): MergeLocaleDocsResult<T> {
38
- return _mergeLocaleDocs({
39
- ...options,
40
- isDefaultLocaleOnlyPath,
41
- });
42
- }
43
-
44
- /**
45
- * Merge category metadata for a locale: base metadata first, locale overrides
46
- * win on overlapping keys.
47
- *
48
- * This matches the category-meta merge order used in route enumerators,
49
- * nav helpers, and page paths() sections.
50
- */
51
- export function mergeCategoryMeta(
52
- baseDir: string,
53
- localeDir: string,
54
- ): Map<string, CategoryMeta> {
55
- return new Map<string, CategoryMeta>([
56
- ...loadCategoryMeta(baseDir),
57
- ...loadCategoryMeta(localeDir),
58
- ]);
59
- }