create-zudo-doc 0.2.21 → 0.2.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/features/image-enlarge.d.ts +10 -2
- package/dist/features/image-enlarge.js +10 -2
- package/dist/scaffold.js +20 -22
- 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/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/_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/_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/pages/robots.txt.tsx +2 -26
- package/templates/base/src/components/ai-chat-modal.tsx +9 -8
- 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/components/site-tree-nav.tsx +6 -220
- 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/z-index-tokens.ts +5 -4
- package/templates/base/src/styles/global.css +5 -579
- 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/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/plugins/connect-adapter.mjs +0 -169
- 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/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/llmsTxt/files/plugins/llms-txt-plugin.mjs +0 -93
|
@@ -1,64 +1,11 @@
|
|
|
1
1
|
/** @jsxRuntime automatic */
|
|
2
2
|
/** @jsxImportSource preact */
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
// Extracted from the four doc-route render bodies (pages/docs/[...slug].tsx,
|
|
6
|
-
// pages/[locale]/docs/[...slug].tsx, pages/v/[version]/docs/[...slug].tsx,
|
|
7
|
-
// pages/v/[version]/[locale]/docs/[...slug].tsx) where the block was
|
|
8
|
-
// duplicated verbatim across all four routes.
|
|
9
|
-
//
|
|
10
|
-
// Contains:
|
|
11
|
-
// 1. A pre-paint inline <script> that restores the persisted sidebar
|
|
12
|
-
// visibility flag from localStorage before first paint (avoids flash).
|
|
13
|
-
// 2. A `DesktopSidebarToggle` Island that mounts on "load".
|
|
14
|
-
//
|
|
15
|
-
// Pattern mirrors `_body-end-islands.tsx`: the file imports the real
|
|
16
|
-
// component so zfb's island scanner walks page → helper → DesktopSidebarToggle
|
|
17
|
-
// and registers the constructor in the manifest. The Island call's return type
|
|
18
|
-
// is widened to `unknown` (JSX shim gap) so call-sites cast through
|
|
19
|
-
// `as unknown as VNode` at the boundary.
|
|
20
|
-
|
|
21
|
-
import type { VNode, JSX } from "preact";
|
|
22
|
-
import { Island } from "@takazudo/zfb";
|
|
3
|
+
// Host thin-stub — see @takazudo/zudo-doc/sidebar-prepaint (epic #2344, S5).
|
|
23
4
|
import { settings } from "@/config/settings";
|
|
24
|
-
import
|
|
25
|
-
|
|
26
|
-
/** Props for {@link SidebarPrepaint}. */
|
|
27
|
-
export interface SidebarPrepaintProps {
|
|
28
|
-
/**
|
|
29
|
-
* Mirrors the page's `hide_sidebar: true` frontmatter. When true the desktop
|
|
30
|
-
* toggle is skipped — there is no visible sidebar for it to collapse.
|
|
31
|
-
*/
|
|
32
|
-
hideSidebar?: boolean;
|
|
33
|
-
}
|
|
5
|
+
import { createSidebarPrepaint } from "@takazudo/zudo-doc/sidebar-prepaint";
|
|
34
6
|
|
|
35
|
-
|
|
36
|
-
* The `afterSidebar` slot content shared by all four doc-route page components.
|
|
37
|
-
*
|
|
38
|
-
* Returns the pre-paint localStorage script + `DesktopSidebarToggle` Island
|
|
39
|
-
* when `settings.sidebarToggle` is enabled AND the page actually shows a
|
|
40
|
-
* sidebar; returns `undefined` when the toggle is disabled or the page hides
|
|
41
|
-
* the sidebar (matching the conditional the route files used inline).
|
|
42
|
-
*/
|
|
43
|
-
export function SidebarPrepaint({
|
|
44
|
-
hideSidebar,
|
|
45
|
-
}: SidebarPrepaintProps): JSX.Element | undefined {
|
|
46
|
-
if (!settings.sidebarToggle || hideSidebar) return undefined;
|
|
7
|
+
export type { SidebarPrepaintProps } from "@takazudo/zudo-doc/sidebar-prepaint";
|
|
47
8
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
<html data-sidebar-hidden> before first paint to avoid flash.
|
|
52
|
-
Rendered only when the toggle is enabled and the page shows a
|
|
53
|
-
sidebar; the attribute is only set when localStorage says "false"
|
|
54
|
-
so the default (visible) needs no attribute and causes no layout shift. */}
|
|
55
|
-
<script dangerouslySetInnerHTML={{
|
|
56
|
-
__html: `(function(){try{if(localStorage.getItem('zudo-doc-sidebar-visible')==='false'){document.documentElement.setAttribute('data-sidebar-hidden','');}}catch(e){}})();`,
|
|
57
|
-
}} />
|
|
58
|
-
{Island({
|
|
59
|
-
when: "load",
|
|
60
|
-
children: <DesktopSidebarToggle />,
|
|
61
|
-
}) as unknown as VNode}
|
|
62
|
-
</>
|
|
63
|
-
);
|
|
64
|
-
}
|
|
9
|
+
export const SidebarPrepaint = createSidebarPrepaint({
|
|
10
|
+
sidebarToggle: Boolean(settings.sidebarToggle),
|
|
11
|
+
});
|
|
@@ -1,41 +1,8 @@
|
|
|
1
1
|
/** @jsxRuntime automatic */
|
|
2
2
|
/** @jsxImportSource preact */
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
// Sidebar data-prep utilities — builds root-menu items from
|
|
6
|
-
// settings.headerNav, loads the locale's docs collection (with EN
|
|
7
|
-
// fallback for non-default locales), builds the nav tree for the active
|
|
8
|
-
// section, optionally remaps hrefs for versioned routes, and feeds the
|
|
9
|
-
// result into the host's <SidebarTree> Preact island.
|
|
10
|
-
//
|
|
11
|
-
// Why this wrapper exists: the data prep is host-only (it imports
|
|
12
|
-
// @/config/* and @/utils/*), so it cannot live in the published v2
|
|
13
|
-
// package. Without this wrapper the zfb doc pages fall through to a
|
|
14
|
-
// <SidebarTree nodes={[]} /> default and the SSG output emits an empty
|
|
15
|
-
// `<div data-zfb-island="SidebarTree" data-when="load"></div>` marker.
|
|
16
|
-
|
|
17
|
-
import type { JSX } from "preact";
|
|
18
|
-
// `<Island>` wraps `<SidebarTree>` directly here (rather than going through
|
|
19
|
-
// the v2 `<Sidebar>` shell with `treeComponent`) so the zfb island bundle's
|
|
20
|
-
// hydrate pass targets the actual stateful tree component. Mirrors the
|
|
21
|
-
// mobile `<SidebarToggle>` shape in `pages/lib/_header-with-defaults.tsx`:
|
|
22
|
-
// the hydration target owns its own data props directly so they ride the
|
|
23
|
-
// SSR → hydrate boundary inside the Island marker's `data-props` attribute.
|
|
24
|
-
//
|
|
25
|
-
// Background: zfb's `Island.captureSerializableProps` runs `JSON.stringify`
|
|
26
|
-
// on the wrapped component's own props bag, which silently drops function
|
|
27
|
-
// values. With the previous `<Sidebar treeComponent={SidebarTree} ...>`
|
|
28
|
-
// shape the `treeComponent` function was dropped during serialisation, so
|
|
29
|
-
// at hydration the v2 Sidebar shell mounted with `treeComponent=undefined`,
|
|
30
|
-
// returned `null`, and Preact's `hydrate(null, element)` left the SSR-
|
|
31
|
-
// rendered tree DOM in place WITHOUT attaching the input's `onChange`
|
|
32
|
-
// handler — typing into the filter input had no DOM effect.
|
|
33
|
-
// zudolab/zudo-doc#1459 (Wave 1 #1445 wired the input but not the wiring
|
|
34
|
-
// path; this wave routes the hydration target so the wiring actually
|
|
35
|
-
// reaches the rendered tree).
|
|
36
|
-
import { Island } from "@takazudo/zfb";
|
|
37
|
-
import SidebarTree from "@/components/sidebar-tree";
|
|
3
|
+
// Host thin-stub — see @takazudo/zudo-doc/sidebar-with-defaults (epic #2344, S5).
|
|
38
4
|
import { defaultLocale, locales, t, type Locale } from "@/config/i18n";
|
|
5
|
+
import { createSidebarWithDefaults } from "@takazudo/zudo-doc/sidebar-with-defaults";
|
|
39
6
|
import {
|
|
40
7
|
buildRootMenuItems,
|
|
41
8
|
buildLocaleLinksForNav,
|
|
@@ -43,86 +10,17 @@ import {
|
|
|
43
10
|
getThemeDefaultMode,
|
|
44
11
|
} from "./_nav-data-prep";
|
|
45
12
|
|
|
46
|
-
export
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
currentPath?: string;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Default-bearing host wrapper that performs sidebar data prep, then wraps
|
|
65
|
-
* the project's `<SidebarTree>`
|
|
66
|
-
* Preact island in `<Island when="load">` so the SSG output ships a
|
|
67
|
-
* populated `<div data-zfb-island="SidebarTree" data-when="load">…tree…
|
|
68
|
-
* </div>` marker for the hydration runtime to pick up.
|
|
69
|
-
*
|
|
70
|
-
* The v2 `<Sidebar>` shell is intentionally NOT used as the hydration
|
|
71
|
-
* target here. Its `treeComponent` prop is a function, and zfb's
|
|
72
|
-
* `Island.captureSerializableProps` drops function values during
|
|
73
|
-
* `JSON.stringify`, so a `<Sidebar treeComponent={SidebarTree} ...>`
|
|
74
|
-
* island would hydrate with `treeComponent=undefined` and the shell
|
|
75
|
-
* would return `null`, silently breaking the filter input's hydration
|
|
76
|
-
* (zudolab/zudo-doc#1459). Wrapping `<SidebarTree>` directly mirrors the
|
|
77
|
-
* mobile `<SidebarToggle>` shape (see `_header-with-defaults.tsx`) and
|
|
78
|
-
* keeps all data props serializable.
|
|
79
|
-
*/
|
|
80
|
-
export function SidebarWithDefaults(
|
|
81
|
-
props: SidebarWithDefaultsProps,
|
|
82
|
-
): JSX.Element {
|
|
83
|
-
const {
|
|
84
|
-
currentSlug,
|
|
85
|
-
lang = defaultLocale,
|
|
86
|
-
navSection,
|
|
87
|
-
currentVersion,
|
|
88
|
-
currentPath = "",
|
|
89
|
-
} = props;
|
|
90
|
-
|
|
91
|
-
// Root-menu items, sidebar nodes, locale links, and theme mode — all
|
|
92
|
-
// delegated to the shared _nav-data-prep helpers so header and sidebar
|
|
93
|
-
// wrappers stay in sync without duplicating the logic.
|
|
94
|
-
const rootMenuItems = buildRootMenuItems(lang, currentVersion);
|
|
95
|
-
|
|
96
|
-
const backToMenuLabel = navSection ? t("nav.backToMenu", lang) : undefined;
|
|
97
|
-
|
|
98
|
-
// emptyWhenUnsectioned=false: the desktop sidebar falls back to the FULL
|
|
99
|
-
// tree for pages whose slug matches no headerNav categoryMatch (legacy
|
|
100
|
-
// behavior) — only the header's mobile drawer collapses to root menu.
|
|
101
|
-
const nodes = buildSidebarNodes(lang, navSection, currentVersion, false);
|
|
102
|
-
|
|
103
|
-
// Locale-switcher links are only meaningful when more than one locale is
|
|
104
|
-
// configured — matches the Astro template's guard.
|
|
105
|
-
const localeLinks = buildLocaleLinksForNav(currentPath, lang, locales.length);
|
|
106
|
-
|
|
107
|
-
// Wrap <SidebarTree> directly in <Island when="load">. SSR emits the
|
|
108
|
-
// `data-zfb-island="SidebarTree"` marker around the rendered tree, with
|
|
109
|
-
// all data props serialised into `data-props` (every prop is plain data:
|
|
110
|
-
// arrays of objects + strings). At hydration the runtime finds the
|
|
111
|
-
// marker, looks up "SidebarTree" in the islands manifest (registered via
|
|
112
|
-
// the host's `"use client"` directive on `src/components/sidebar-tree.tsx`),
|
|
113
|
-
// and mounts the real component in-place — re-attaching the filter
|
|
114
|
-
// input's `onChange` handler to the existing SSR DOM.
|
|
115
|
-
return Island({
|
|
116
|
-
when: "load",
|
|
117
|
-
children: (
|
|
118
|
-
<SidebarTree
|
|
119
|
-
nodes={nodes}
|
|
120
|
-
currentSlug={currentSlug}
|
|
121
|
-
rootMenuItems={rootMenuItems}
|
|
122
|
-
backToMenuLabel={backToMenuLabel}
|
|
123
|
-
localeLinks={localeLinks}
|
|
124
|
-
themeDefaultMode={getThemeDefaultMode()}
|
|
125
|
-
/>
|
|
126
|
-
),
|
|
127
|
-
}) as unknown as JSX.Element;
|
|
128
|
-
}
|
|
13
|
+
export type { SidebarWithDefaultsProps } from "@takazudo/zudo-doc/sidebar-with-defaults";
|
|
14
|
+
|
|
15
|
+
export const SidebarWithDefaults = createSidebarWithDefaults({
|
|
16
|
+
defaultLocale,
|
|
17
|
+
localeCount: locales.length,
|
|
18
|
+
buildRootMenuItems: (lang, currentVersion) =>
|
|
19
|
+
buildRootMenuItems(lang as Locale, currentVersion),
|
|
20
|
+
buildLocaleLinksForNav: (currentPath, lang, localeCount) =>
|
|
21
|
+
buildLocaleLinksForNav(currentPath, lang as Locale, localeCount),
|
|
22
|
+
buildSidebarNodes: (lang, navSection, currentVersion, emptyWhenUnsectioned) =>
|
|
23
|
+
buildSidebarNodes(lang as Locale, navSection, currentVersion, emptyWhenUnsectioned),
|
|
24
|
+
getThemeDefaultMode,
|
|
25
|
+
t: (key, lang) => t(key as Parameters<typeof t>[0], lang as Locale),
|
|
26
|
+
});
|
|
@@ -1,88 +1,37 @@
|
|
|
1
1
|
/** @jsxRuntime automatic */
|
|
2
2
|
/** @jsxImportSource preact */
|
|
3
|
-
//
|
|
3
|
+
// Thin stub — site-tree-nav moved to the package (epic #2344, S8).
|
|
4
|
+
// Calls `createSiteTreeNavWrapper(deps)` from @takazudo/zudo-doc/site-tree-nav
|
|
5
|
+
// with host singletons injected, then re-exports the resulting component so
|
|
6
|
+
// all existing call sites continue to work unchanged.
|
|
4
7
|
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// SiteTreeNav island (refs #1453):
|
|
8
|
-
//
|
|
9
|
-
// 1. Load the full docs collection for the active locale.
|
|
10
|
-
// 2. Build nav tree via buildNavTree().
|
|
11
|
-
// 3. Group satellite nodes via groupSatelliteNodes().
|
|
12
|
-
// 4. Wrap the interactive SiteTreeNav in Island({when:"idle"}) so the MDX
|
|
13
|
-
// page gets the collapsible grid rendered at
|
|
14
|
-
// /docs/components/site-tree-nav/ (refs #1453/#1442).
|
|
15
|
-
//
|
|
16
|
-
// All data access is synchronous (ADR-004 zfb content snapshot contract).
|
|
17
|
-
// The `lang` prop is injected by createMdxComponents() in
|
|
18
|
-
// pages/_mdx-components.ts so locale routes get locale-aware nav data.
|
|
19
|
-
//
|
|
20
|
-
// categoryIgnore defaults to ["inbox", "develop"] — matching the index page
|
|
21
|
-
// and SiteTreeNavDemo defaults.
|
|
8
|
+
// IMPORTANT: Island({when:"idle"}) is PRESERVED in the package factory —
|
|
9
|
+
// the island mounts after the page is idle for performance (refs #1453).
|
|
22
10
|
|
|
23
|
-
import
|
|
24
|
-
import {
|
|
25
|
-
import
|
|
26
|
-
import {
|
|
27
|
-
buildNavTree,
|
|
28
|
-
groupSatelliteNodes,
|
|
29
|
-
} from "@/utils/docs";
|
|
30
|
-
import { defaultLocale, type Locale } from "@/config/i18n";
|
|
11
|
+
import { createSiteTreeNavWrapper } from "@takazudo/zudo-doc/site-tree-nav";
|
|
12
|
+
import type { SidebarNavNode } from "@takazudo/zudo-doc/sidebar/types";
|
|
13
|
+
import { buildNavTree, groupSatelliteNodes } from "@/utils/docs";
|
|
14
|
+
import { defaultLocale } from "@/config/i18n";
|
|
31
15
|
import { getCategoryOrder } from "@/utils/nav-scope";
|
|
32
16
|
import { resolveNavSource } from "./_nav-source-docs";
|
|
33
17
|
|
|
34
|
-
export
|
|
35
|
-
/**
|
|
36
|
-
* Active locale. Injected via createMdxComponents() closure.
|
|
37
|
-
* Defaults to defaultLocale when not provided.
|
|
38
|
-
*/
|
|
39
|
-
lang?: Locale | string;
|
|
40
|
-
/**
|
|
41
|
-
* Optional aria-label for the wrapping <nav> element.
|
|
42
|
-
* Forwarded to the v2 SiteTreeNavDemo component.
|
|
43
|
-
*/
|
|
44
|
-
ariaLabel?: string;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* MDX wrapper shared by both <SiteTreeNav> and <SiteTreeNavDemo> tags.
|
|
49
|
-
*
|
|
50
|
-
* Builds the full site nav tree and renders it via the interactive SiteTreeNav
|
|
51
|
-
* island (wrapped in Island({when:"idle"})) — restoring byte-parity with the
|
|
52
|
-
* Astro reference at /docs/components/site-tree-nav/ (refs #1453/#1442).
|
|
53
|
-
*
|
|
54
|
-
* The island renders the collapsible multi-column grid the reference shows.
|
|
55
|
-
* SiteTreeNavDemo (static <details> list) is no longer used for MDX content.
|
|
56
|
-
*
|
|
57
|
-
* Returns null when the tree is empty after filtering.
|
|
58
|
-
*/
|
|
59
|
-
export function SiteTreeNavWrapper({
|
|
60
|
-
lang = defaultLocale,
|
|
61
|
-
ariaLabel,
|
|
62
|
-
}: SiteTreeNavWrapperProps): JSX.Element | null {
|
|
63
|
-
const locale = lang as Locale;
|
|
64
|
-
|
|
65
|
-
// SiteTreeNav mirrors the route nav: applies the defaultLocaleOnly filter for
|
|
66
|
-
// non-default locales (same options the sidebar/route enumeration use).
|
|
67
|
-
const { navDocs, categoryMeta } = resolveNavSource(locale, undefined, {
|
|
68
|
-
applyDefaultLocaleOnlyFilter: true,
|
|
69
|
-
keepUnlisted: true,
|
|
70
|
-
});
|
|
71
|
-
const tree = buildNavTree(navDocs, locale, categoryMeta);
|
|
72
|
-
const categoryOrder = getCategoryOrder();
|
|
73
|
-
const groupedTree = groupSatelliteNodes(tree, categoryOrder);
|
|
74
|
-
|
|
75
|
-
if (groupedTree.length === 0) return null;
|
|
18
|
+
export type { SiteTreeNavWrapperProps } from "@takazudo/zudo-doc/site-tree-nav";
|
|
76
19
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
20
|
+
export const SiteTreeNavWrapper = createSiteTreeNavWrapper({
|
|
21
|
+
defaultLocale,
|
|
22
|
+
resolveNavSource: resolveNavSource as (
|
|
23
|
+
lang: string,
|
|
24
|
+
currentVersion: string | undefined,
|
|
25
|
+
options?: { applyDefaultLocaleOnlyFilter?: boolean; keepUnlisted?: boolean },
|
|
26
|
+
) => import("@takazudo/zudo-doc/site-tree-nav").SiteTreeNavSource,
|
|
27
|
+
buildNavTree: buildNavTree as (
|
|
28
|
+
docs: unknown[],
|
|
29
|
+
locale: string,
|
|
30
|
+
categoryMeta: Map<string, unknown>,
|
|
31
|
+
) => SidebarNavNode[],
|
|
32
|
+
groupSatelliteNodes: groupSatelliteNodes as (
|
|
33
|
+
tree: SidebarNavNode[],
|
|
34
|
+
prefixes: string[],
|
|
35
|
+
) => SidebarNavNode[],
|
|
36
|
+
getCategoryOrder,
|
|
37
|
+
});
|
|
@@ -1,48 +1,30 @@
|
|
|
1
|
-
//
|
|
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.
|
|
2
4
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
// non-null inside each branch — eliminating all `entry!` assertions.
|
|
5
|
+
// S5 and downstream (S7) consumers import `DocPageBaseProps`, `DocPageEntry`,
|
|
6
|
+
// `AutoIndexNode`, `DocPageEntryProps`, `DocPageAutoIndexProps` from this path
|
|
7
|
+
// unchanged — all are re-exported below.
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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";
|
|
12
19
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
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";
|
|
19
25
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
interface DocPagePropsBase {
|
|
26
|
-
breadcrumbs: BreadcrumbItem[];
|
|
27
|
-
prev: NavNode | null;
|
|
28
|
-
next: NavNode | null;
|
|
29
|
-
/** Depth-2/3/4 headings extracted from the MDX body, for SSG TOC links. */
|
|
30
|
-
headings: ReturnType<typeof extractHeadings>;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/** Branch: a real content entry. `autoIndex` is absent. */
|
|
34
|
-
export interface DocPageEntryProps extends DocPagePropsBase {
|
|
35
|
-
kind: "entry";
|
|
36
|
-
entry: DocPageEntry;
|
|
37
|
-
autoIndex?: undefined;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/** Branch: an auto-generated category index. `entry` is absent. */
|
|
41
|
-
export interface DocPageAutoIndexProps extends DocPagePropsBase {
|
|
42
|
-
kind: "autoIndex";
|
|
43
|
-
autoIndex: AutoIndexNode;
|
|
44
|
-
entry?: undefined;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/** Discriminated union for the `kind` prop. Narrow via `props.kind === "entry"`. */
|
|
48
|
-
export type DocPageBaseProps = DocPageEntryProps | DocPageAutoIndexProps;
|
|
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,159 +1,46 @@
|
|
|
1
|
-
//
|
|
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.
|
|
2
4
|
//
|
|
3
|
-
//
|
|
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.
|
|
5
10
|
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
//
|
|
19
|
-
// This is a zfb-only module (synchronous, uses pre-loaded collections).
|
|
20
|
-
|
|
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";
|
|
21
23
|
import { isDefaultLocaleOnlyPath } from "@/utils/base";
|
|
22
|
-
import
|
|
23
|
-
|
|
24
|
-
// ---------------------------------------------------------------------------
|
|
25
|
-
// mergeLocaleDocs
|
|
26
|
-
// ---------------------------------------------------------------------------
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Options for mergeLocaleDocs.
|
|
30
|
-
*
|
|
31
|
-
* The generic parameter `T` allows callers to pass arrays of a DocsEntry
|
|
32
|
-
* subtype (e.g. `DocPageEntry[]`) and get back results of the same subtype,
|
|
33
|
-
* eliminating the need for `as unknown as` casts at call sites.
|
|
34
|
-
*/
|
|
35
|
-
export interface MergeLocaleDocsOptions<T extends DocsEntry = DocsEntry> {
|
|
36
|
-
/** Pre-loaded base (EN/default-locale) docs array, already draft-filtered. */
|
|
37
|
-
baseDocs: T[];
|
|
38
|
-
/** Pre-loaded locale-specific docs array, already draft-filtered. */
|
|
39
|
-
localeDocs: T[];
|
|
40
|
-
/**
|
|
41
|
-
* When true, base docs whose path matches a `defaultLocaleOnlyPrefixes`
|
|
42
|
-
* entry are excluded from the merge result. This matches the behavior of the
|
|
43
|
-
* inline copies in route-enumerators, nav helpers, and page paths() sections.
|
|
44
|
-
*
|
|
45
|
-
* Pass true for any call site that enumerates routes or builds nav trees for
|
|
46
|
-
* non-default locales (where showing a default-locale-only page to a locale
|
|
47
|
-
* user would be incorrect). Pass false (or omit) for call sites where the
|
|
48
|
-
* filtered paths are harmless — e.g. category nav cards, taglist columns.
|
|
49
|
-
*
|
|
50
|
-
* @default false
|
|
51
|
-
*/
|
|
52
|
-
applyDefaultLocaleOnlyFilter?: boolean;
|
|
53
|
-
/**
|
|
54
|
-
* Controls whether `unlisted: true` docs survive the merge.
|
|
55
|
-
*
|
|
56
|
-
* - `true` — unlisted docs are RETAINED (locale + base). Route/sitemap
|
|
57
|
-
* enumeration uses this: unlisted pages have real HTML files, so
|
|
58
|
-
* they must be built; nav callers rely on `isNavVisible`
|
|
59
|
-
* downstream to hide them from the tree.
|
|
60
|
-
* - `false` (default) — unlisted docs are DROPPED from both locale and base.
|
|
61
|
-
* Tag aggregation uses this so hidden pages don't contribute tags.
|
|
62
|
-
*
|
|
63
|
-
* @default false
|
|
64
|
-
*/
|
|
65
|
-
keepUnlisted?: boolean;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Result of mergeLocaleDocs.
|
|
70
|
-
*
|
|
71
|
-
* **Array identity:** Each call returns a fresh array — no module-level
|
|
72
|
-
* memoization is applied. If a caller keys a cache on the docs array identity
|
|
73
|
-
* (e.g. a nav-tree cache), it should memoize the result itself rather than
|
|
74
|
-
* relying on reference stability from this helper.
|
|
75
|
-
*
|
|
76
|
-
* This contract is intentionally unchanged. The identity-stable layer for
|
|
77
|
-
* nav-source arrays lives ABOVE this helper: `pages/lib/_nav-source-docs.ts`
|
|
78
|
-
* (`resolveNavSource` / `resolveVersionedLocaleSource`) memoizes the merge
|
|
79
|
-
* result on the snapshot-anchored input arrays + option signature (see
|
|
80
|
-
* `pages/lib/_nav-source-cache.ts`), so `mergeLocaleDocs` itself stays a pure,
|
|
81
|
-
* memo-free function (#1902).
|
|
82
|
-
*
|
|
83
|
-
* The generic `T` mirrors the parameter on {@link MergeLocaleDocsOptions} so
|
|
84
|
-
* the returned `docs` array preserves the subtype of the input arrays.
|
|
85
|
-
*/
|
|
86
|
-
export interface MergeLocaleDocsResult<T extends DocsEntry = DocsEntry> {
|
|
87
|
-
/**
|
|
88
|
-
* Merged doc array: locale docs first, followed by base docs for slugs not
|
|
89
|
-
* present in the locale collection (and not excluded by filter options).
|
|
90
|
-
*/
|
|
91
|
-
docs: T[];
|
|
92
|
-
/**
|
|
93
|
-
* Set of slugs that came from the locale collection.
|
|
94
|
-
* Useful for callers that need to determine whether a page is a fallback
|
|
95
|
-
* (i.e. `isFallback = !localeSlugSet.has(slug)`).
|
|
96
|
-
*/
|
|
97
|
-
localeSlugSet: ReadonlySet<string>;
|
|
98
|
-
}
|
|
24
|
+
import { loadCategoryMeta } from "@/utils/docs";
|
|
25
|
+
import type { CategoryMeta } from "@/utils/docs";
|
|
99
26
|
|
|
100
27
|
/**
|
|
101
28
|
* Merge locale docs with base-locale fallbacks.
|
|
102
29
|
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
* already strips the `/index` suffix (via `stripIndexSuffix` in `_data.ts`),
|
|
108
|
-
* this key is consistent across all call sites regardless of whether they
|
|
109
|
-
* loaded docs via `loadDocs` or `bridgeEntries`.
|
|
110
|
-
*
|
|
111
|
-
* **Array identity**: returns a fresh array on each call — see
|
|
112
|
-
* {@link MergeLocaleDocsResult} for caching guidance.
|
|
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.
|
|
113
34
|
*/
|
|
114
|
-
export function mergeLocaleDocs<T extends
|
|
115
|
-
options: MergeLocaleDocsOptions<T>,
|
|
35
|
+
export function mergeLocaleDocs<T extends MergeDocsEntry = MergeDocsEntry>(
|
|
36
|
+
options: Omit<MergeLocaleDocsOptions<T>, "isDefaultLocaleOnlyPath">,
|
|
116
37
|
): MergeLocaleDocsResult<T> {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
keepUnlisted = false,
|
|
122
|
-
} = options;
|
|
123
|
-
|
|
124
|
-
const filteredLocale = keepUnlisted
|
|
125
|
-
? localeDocs
|
|
126
|
-
: localeDocs.filter((d) => !d.data.unlisted);
|
|
127
|
-
|
|
128
|
-
const filteredBase = keepUnlisted
|
|
129
|
-
? baseDocs
|
|
130
|
-
: baseDocs.filter((d) => !d.data.unlisted);
|
|
131
|
-
|
|
132
|
-
const localeSlugSet = new Set(filteredLocale.map((d) => d.data.slug ?? d.id));
|
|
133
|
-
|
|
134
|
-
let fallbackDocs = filteredBase.filter(
|
|
135
|
-
(d) => !localeSlugSet.has(d.data.slug ?? d.id),
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
if (applyDefaultLocaleOnlyFilter) {
|
|
139
|
-
fallbackDocs = fallbackDocs.filter(
|
|
140
|
-
(d) => !isDefaultLocaleOnlyPath(`/docs/${d.data.slug ?? d.id}`),
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return {
|
|
145
|
-
docs: [...filteredLocale, ...fallbackDocs],
|
|
146
|
-
localeSlugSet,
|
|
147
|
-
};
|
|
38
|
+
return _mergeLocaleDocs({
|
|
39
|
+
...options,
|
|
40
|
+
isDefaultLocaleOnlyPath,
|
|
41
|
+
});
|
|
148
42
|
}
|
|
149
43
|
|
|
150
|
-
// ---------------------------------------------------------------------------
|
|
151
|
-
// mergeCategoryMeta
|
|
152
|
-
// ---------------------------------------------------------------------------
|
|
153
|
-
|
|
154
|
-
import { loadCategoryMeta } from "@/utils/docs";
|
|
155
|
-
import type { CategoryMeta } from "@/utils/docs";
|
|
156
|
-
|
|
157
44
|
/**
|
|
158
45
|
* Merge category metadata for a locale: base metadata first, locale overrides
|
|
159
46
|
* win on overlapping keys.
|