create-zudo-doc 0.2.20 → 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 +22 -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 -47
- 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/tauri/files/src-tauri/capabilities/default.json +1 -4
- package/templates/features/tauri/files/src-tauri/tauri.conf.json +1 -1
- package/templates/features/tauriDev/files/src-tauri-dev/capabilities/default.json +1 -1
- 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,263 +1,29 @@
|
|
|
1
1
|
/** @jsxRuntime automatic */
|
|
2
2
|
/** @jsxImportSource preact */
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
// Extracted (#1917) from the near-verbatim render bodies of:
|
|
6
|
-
// pages/docs/[[...slug]].tsx
|
|
7
|
-
// pages/[locale]/docs/[[...slug]].tsx
|
|
8
|
-
// pages/v/[version]/docs/[[...slug]].tsx
|
|
9
|
-
// pages/v/[version]/[locale]/docs/[[...slug]].tsx
|
|
10
|
-
//
|
|
11
|
-
// This module is intentionally version- and i18n-AGNOSTIC: it imports no
|
|
12
|
-
// VersionConfig and no versionedDocsUrl. Everything version/locale-specific
|
|
13
|
-
// is threaded in as plain props or pre-built VNode slots, so the base EN
|
|
14
|
-
// route (which ships in every scaffold, including barebones) can depend on
|
|
15
|
-
// it without dragging in the versioning/i18n feature surface. The feature
|
|
16
|
-
// route templates import this same module via the identical relative path,
|
|
17
|
-
// keeping the create-zudo-doc template copies byte-identical to the host.
|
|
18
|
-
|
|
19
|
-
import type { ComponentChildren, JSX, VNode } from "preact";
|
|
20
|
-
import { Island } from "@takazudo/zfb";
|
|
3
|
+
// Host thin-stub — see @takazudo/zudo-doc/doc-page-shell (epic #2344, S5).
|
|
21
4
|
import { settings } from "@/config/settings";
|
|
22
|
-
import
|
|
23
|
-
import {
|
|
24
|
-
import { Toc, MobileToc } from "@takazudo/zudo-doc/toc";
|
|
5
|
+
import { createDocPageShell } from "@takazudo/zudo-doc/doc-page-shell";
|
|
6
|
+
import { composeMetaTitle } from "./_compose-meta-title";
|
|
25
7
|
import { getTocTitle } from "./_toc-title";
|
|
26
|
-
import { Breadcrumb } from "@takazudo/zudo-doc/breadcrumb";
|
|
27
|
-
import { NavCardGrid } from "@takazudo/zudo-doc/nav-indexing";
|
|
28
8
|
import { HeadWithDefaults } from "./_head-with-defaults";
|
|
29
|
-
import { composeMetaTitle } from "./_compose-meta-title";
|
|
30
9
|
import { SidebarWithDefaults } from "./_sidebar-with-defaults";
|
|
31
10
|
import { HeaderWithDefaults } from "./_header-with-defaults";
|
|
32
11
|
import { FooterWithDefaults } from "./_footer-with-defaults";
|
|
33
12
|
import { SidebarPrepaint } from "./_sidebar-prepaint";
|
|
34
13
|
import { DocBodyEnd } from "./_doc-body-end";
|
|
35
14
|
import { DocPager } from "./_doc-pager";
|
|
36
|
-
import type { BreadcrumbItem } from "@/utils/docs";
|
|
37
|
-
import type { VersionBannerLabels } from "@takazudo/zudo-doc/i18n-version";
|
|
38
|
-
import type { Locale } from "@/config/i18n";
|
|
39
|
-
import type { extractHeadings } from "./_extract-headings";
|
|
40
|
-
|
|
41
|
-
/** Slots and parameters that vary between the 4 doc routes. */
|
|
42
|
-
export interface DocPageShellProps {
|
|
43
|
-
/** Discriminates the body: a real entry vs an auto-generated category index. */
|
|
44
|
-
kind: "entry" | "autoIndex";
|
|
45
|
-
/** Active locale string, e.g. "en", "ja". */
|
|
46
|
-
locale: string;
|
|
47
|
-
/** Canonical route slug for this page (no version/locale prefix). */
|
|
48
|
-
slug: string;
|
|
49
|
-
/** Page title (entry title or auto-index label). */
|
|
50
|
-
title: string;
|
|
51
|
-
/** Page description (may be undefined). */
|
|
52
|
-
description?: string;
|
|
53
|
-
/** Absolute canonical URL, or undefined when siteUrl is unset. */
|
|
54
|
-
canonical?: string;
|
|
55
|
-
/** Pre-resolved breadcrumb trail (hrefs already remapped per route). */
|
|
56
|
-
breadcrumbs: BreadcrumbItem[];
|
|
57
|
-
/** Pre-resolved prev/next nav nodes (hrefs already remapped per route). */
|
|
58
|
-
prev: NavNode | null;
|
|
59
|
-
next: NavNode | null;
|
|
60
|
-
/** Depth-2/3/4 headings for the SSG TOC. */
|
|
61
|
-
headings: ReturnType<typeof extractHeadings>;
|
|
62
|
-
|
|
63
|
-
/** Sidebar/header nav-section key for this slug. */
|
|
64
|
-
navSection: string | undefined;
|
|
65
|
-
/** Per-page sidebar persist key (undefined when the sidebar is hidden). */
|
|
66
|
-
sidebarPersistKey: string | undefined;
|
|
67
|
-
/** Whether to hide the sidebar entirely (entry frontmatter). */
|
|
68
|
-
hideSidebar?: boolean;
|
|
69
|
-
/** Whether to hide the TOC (entry frontmatter). */
|
|
70
|
-
hideToc?: boolean;
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Path of THIS page used by Header/Sidebar to mark the active item.
|
|
74
|
-
* Latest routes pass docsUrl(slug, locale); versioned routes pass
|
|
75
|
-
* versionedDocsUrl(slug, version, locale).
|
|
76
|
-
*/
|
|
77
|
-
currentPath: string;
|
|
78
|
-
/** Version slug for Header/Sidebar active-state, or undefined on latest routes. */
|
|
79
|
-
currentVersion?: string;
|
|
80
|
-
/** Inline version switcher VNode for the breadcrumb right-slot (route-built). */
|
|
81
|
-
versionSwitcher: ComponentChildren;
|
|
82
|
-
|
|
83
|
-
/** Version banner type ("unmaintained" | "unreleased") or undefined on latest. */
|
|
84
|
-
versionBanner?: "unmaintained" | "unreleased";
|
|
85
|
-
/** URL of the latest equivalent page for the version banner link. */
|
|
86
|
-
versionBannerLatestUrl?: string;
|
|
87
|
-
/** Localized version-banner labels. */
|
|
88
|
-
versionBannerLabels?: VersionBannerLabels;
|
|
89
|
-
|
|
90
|
-
/** Auto-index branch: label heading text. */
|
|
91
|
-
autoIndexLabel?: string;
|
|
92
|
-
/** Auto-index branch: pre-filtered + href-remapped child cards. */
|
|
93
|
-
autoIndexChildren?: NavNode[];
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Auto-index branch slot: the build-time date block (DocMetainfoArea), or
|
|
97
|
-
* null to omit it. Threaded in so the shell stays oblivious to which routes
|
|
98
|
-
* render it.
|
|
99
|
-
*/
|
|
100
|
-
metainfoSlot?: VNode | null;
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Entry branch slot: the content header (h1 + meta + tags + description +
|
|
104
|
-
* frontmatter preview), built per route (carries isFallback).
|
|
105
|
-
*/
|
|
106
|
-
contentHeaderSlot?: VNode;
|
|
107
|
-
/** Entry branch slot: the rendered MDX `<Content />`. */
|
|
108
|
-
contentSlot?: VNode;
|
|
109
|
-
/**
|
|
110
|
-
* Entry branch slot: the document-utilities area (DocHistoryArea), or null
|
|
111
|
-
* to omit it. Hidden on versioned pages (#1916 #5).
|
|
112
|
-
*/
|
|
113
|
-
docHistorySlot?: VNode | null;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Render shell shared by all 4 doc-route page components. The caller computes
|
|
118
|
-
* every route-specific value (URLs, version switcher, slots) and passes it in;
|
|
119
|
-
* this component only assembles the DocLayoutWithDefaults call and the two
|
|
120
|
-
* body branches (auto-index vs entry).
|
|
121
|
-
*/
|
|
122
|
-
export function DocPageShell(props: DocPageShellProps): JSX.Element {
|
|
123
|
-
const {
|
|
124
|
-
kind,
|
|
125
|
-
locale,
|
|
126
|
-
title,
|
|
127
|
-
description,
|
|
128
|
-
canonical,
|
|
129
|
-
breadcrumbs,
|
|
130
|
-
prev,
|
|
131
|
-
next,
|
|
132
|
-
headings,
|
|
133
|
-
navSection,
|
|
134
|
-
sidebarPersistKey,
|
|
135
|
-
hideSidebar,
|
|
136
|
-
hideToc,
|
|
137
|
-
currentPath,
|
|
138
|
-
currentVersion,
|
|
139
|
-
versionSwitcher,
|
|
140
|
-
versionBanner,
|
|
141
|
-
versionBannerLatestUrl,
|
|
142
|
-
versionBannerLabels,
|
|
143
|
-
autoIndexLabel,
|
|
144
|
-
autoIndexChildren,
|
|
145
|
-
metainfoSlot,
|
|
146
|
-
contentHeaderSlot,
|
|
147
|
-
contentSlot,
|
|
148
|
-
docHistorySlot,
|
|
149
|
-
} = props;
|
|
150
|
-
|
|
151
|
-
// TOC overrides: mount the package Toc/MobileToc with the host-resolved
|
|
152
|
-
// locale-aware `tocTitle`. The gating mirrors the package's
|
|
153
|
-
// `shouldRenderDefaultToc` exactly (`!hideToc && headings.length > 0`) so an
|
|
154
|
-
// undefined override never silently falls back to the package default with a
|
|
155
|
-
// different title. Each is wrapped in `<Island when="load">` here (the call
|
|
156
|
-
// site), matching how the package wraps its own default. Hydrating these
|
|
157
|
-
// npm-dist "use client" components requires zfb >= 0.1.0-next.39, whose
|
|
158
|
-
// scanner registers node_modules islands (zfb#999/#1001) — the former
|
|
159
|
-
// scanner-visible local shims (#2057) are gone; re-adding them would
|
|
160
|
-
// recreate island marker-name collisions.
|
|
161
|
-
const tocTitle = getTocTitle(locale);
|
|
162
|
-
const shouldRenderToc = !hideToc && headings.length > 0;
|
|
163
|
-
const tocOverride = shouldRenderToc
|
|
164
|
-
? (Island({
|
|
165
|
-
when: "load",
|
|
166
|
-
children: <Toc headings={headings} title={tocTitle} />,
|
|
167
|
-
}) as unknown as VNode)
|
|
168
|
-
: undefined;
|
|
169
|
-
const mobileTocOverride = shouldRenderToc
|
|
170
|
-
? (Island({
|
|
171
|
-
when: "load",
|
|
172
|
-
children: <MobileToc headings={headings} title={tocTitle} />,
|
|
173
|
-
}) as unknown as VNode)
|
|
174
|
-
: undefined;
|
|
175
|
-
|
|
176
|
-
return (
|
|
177
|
-
<DocLayoutWithDefaults
|
|
178
|
-
title={composeMetaTitle(title)}
|
|
179
|
-
// Plain <meta name="description"> is emitted by DocLayout from this prop —
|
|
180
|
-
// gate it here alongside the og:description gate inside HeadWithDefaults (#2078)
|
|
181
|
-
description={settings.metaTags.description ? description : undefined}
|
|
182
|
-
head={<HeadWithDefaults title={title} description={description} canonical={canonical} />}
|
|
183
|
-
lang={locale}
|
|
184
|
-
noindex={settings.noindex}
|
|
185
|
-
hideSidebar={hideSidebar}
|
|
186
|
-
hideToc={hideToc}
|
|
187
|
-
headings={headings}
|
|
188
|
-
canonical={canonical}
|
|
189
|
-
sidebarPersistKey={sidebarPersistKey}
|
|
190
|
-
versionBanner={versionBanner ?? false}
|
|
191
|
-
versionBannerLatestUrl={versionBannerLatestUrl}
|
|
192
|
-
versionBannerLabels={versionBannerLabels}
|
|
193
|
-
headerOverride={
|
|
194
|
-
<HeaderWithDefaults
|
|
195
|
-
lang={locale as Locale}
|
|
196
|
-
currentSlug={props.slug}
|
|
197
|
-
navSection={navSection}
|
|
198
|
-
currentVersion={currentVersion}
|
|
199
|
-
currentPath={currentPath}
|
|
200
|
-
/>
|
|
201
|
-
}
|
|
202
|
-
breadcrumbOverride={
|
|
203
|
-
breadcrumbs.length > 0 ? (
|
|
204
|
-
<Breadcrumb items={breadcrumbs} rightSlot={versionSwitcher} />
|
|
205
|
-
) : undefined
|
|
206
|
-
}
|
|
207
|
-
sidebarOverride={
|
|
208
|
-
<SidebarWithDefaults
|
|
209
|
-
currentSlug={props.slug}
|
|
210
|
-
lang={locale as Locale}
|
|
211
|
-
navSection={navSection}
|
|
212
|
-
currentVersion={currentVersion}
|
|
213
|
-
currentPath={currentPath}
|
|
214
|
-
/>
|
|
215
|
-
}
|
|
216
|
-
tocOverride={tocOverride}
|
|
217
|
-
mobileTocOverride={mobileTocOverride}
|
|
218
|
-
afterSidebar={<SidebarPrepaint />}
|
|
219
|
-
footerOverride={<FooterWithDefaults lang={locale} />}
|
|
220
|
-
bodyEndComponents={<DocBodyEnd />}
|
|
221
|
-
enableClientRouter={settings.dynamicPageTransition}
|
|
222
|
-
>
|
|
223
|
-
{kind === "autoIndex" ? (
|
|
224
|
-
/* Auto-index page: category without an index.mdx.
|
|
225
|
-
Fragment (not <div>) so children become direct children of
|
|
226
|
-
<article class="zd-content">, picking up the flow-space rule
|
|
227
|
-
(.zd-content > :where(* + *) { margin-top: var(--flow-space) }).
|
|
228
|
-
Wrapping in <div> would make h1/description p children-of-children
|
|
229
|
-
and the flow gap (~24px) would never apply — see #1460. */
|
|
230
|
-
<>
|
|
231
|
-
<h1 class="text-heading font-bold mb-vsp-xs">{autoIndexLabel}</h1>
|
|
232
|
-
|
|
233
|
-
{/* Build-time date block — chrome parity (#1461). Threaded in via
|
|
234
|
-
metainfoSlot so each route controls whether it renders. */}
|
|
235
|
-
{metainfoSlot}
|
|
236
|
-
|
|
237
|
-
{description && (
|
|
238
|
-
<p class="mb-vsp-lg text-title text-muted">{description}</p>
|
|
239
|
-
)}
|
|
240
|
-
<NavCardGrid children={autoIndexChildren ?? []} />
|
|
241
|
-
</>
|
|
242
|
-
) : (
|
|
243
|
-
/* Regular doc page. Fragment (not <div>) for the same reason as
|
|
244
|
-
the auto-index branch above — see #1460. */
|
|
245
|
-
<>
|
|
246
|
-
{contentHeaderSlot}
|
|
247
|
-
|
|
248
|
-
{contentSlot}
|
|
249
|
-
|
|
250
|
-
{/* Prev / Next pagination — placed before the document utilities
|
|
251
|
-
section to match the Astro reference order: content → pager →
|
|
252
|
-
view-source / history. Fixes #1535. */}
|
|
253
|
-
<DocPager prev={prev} next={next} locale={locale} />
|
|
254
15
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
16
|
+
export type { DocPageShellProps } from "@takazudo/zudo-doc/doc-page-shell";
|
|
17
|
+
|
|
18
|
+
export const DocPageShell = createDocPageShell({
|
|
19
|
+
settings,
|
|
20
|
+
composeMetaTitle,
|
|
21
|
+
getTocTitle,
|
|
22
|
+
HeadWithDefaults,
|
|
23
|
+
SidebarWithDefaults,
|
|
24
|
+
HeaderWithDefaults,
|
|
25
|
+
FooterWithDefaults,
|
|
26
|
+
SidebarPrepaint,
|
|
27
|
+
DocBodyEnd,
|
|
28
|
+
DocPager,
|
|
29
|
+
});
|
|
@@ -1,79 +1,9 @@
|
|
|
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.
|
|
9
|
-
//
|
|
10
|
-
// Uses ChevronLeft / ChevronRight from the shared icon module
|
|
11
|
-
// (@takazudo/zudo-doc/icons) rather than hand-written SVG paths, absorbing
|
|
12
|
-
// the last inline chevron occurrences in the route files (see #1880 item 4).
|
|
13
|
-
|
|
14
|
-
import type { JSX } from "preact";
|
|
3
|
+
// Host thin-stub — see @takazudo/zudo-doc/doc-pager (epic #2344, S7).
|
|
15
4
|
import { t } from "@/config/i18n";
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
// NavNode is a superset; we only need the fields the pager uses.
|
|
19
|
-
interface PagerNode {
|
|
20
|
-
href?: string;
|
|
21
|
-
label: string;
|
|
22
|
-
}
|
|
5
|
+
import { createDocPager } from "@takazudo/zudo-doc/doc-pager";
|
|
23
6
|
|
|
24
|
-
|
|
25
|
-
/** Previous page node (null = no previous page → renders placeholder). */
|
|
26
|
-
prev: PagerNode | null;
|
|
27
|
-
/** Next page node (null = no next page → renders placeholder). */
|
|
28
|
-
next: PagerNode | null;
|
|
29
|
-
/** Active locale for translated "Previous" / "Next" labels. */
|
|
30
|
-
locale: string;
|
|
31
|
-
}
|
|
7
|
+
export type { DocPagerProps } from "@takazudo/zudo-doc/doc-pager";
|
|
32
8
|
|
|
33
|
-
|
|
34
|
-
* Prev/next pagination nav shared by all four doc-route page components.
|
|
35
|
-
*
|
|
36
|
-
* Renders a two-column grid: prev card on the left, next card on the right.
|
|
37
|
-
* When a node is absent its slot is filled with an empty `<div>` to maintain
|
|
38
|
-
* the two-column layout. Placement: immediately after MDX content, before
|
|
39
|
-
* `DocHistoryArea` (Astro reference order — content → pager → utilities,
|
|
40
|
-
* per #1535).
|
|
41
|
-
*/
|
|
42
|
-
export function DocPager({ prev, next, locale }: DocPagerProps): JSX.Element {
|
|
43
|
-
return (
|
|
44
|
-
<nav class="mt-vsp-2xl grid grid-cols-2 gap-hsp-xl">
|
|
45
|
-
{prev ? (
|
|
46
|
-
<a
|
|
47
|
-
href={prev.href}
|
|
48
|
-
class="group border border-muted rounded-lg p-hsp-lg hover:border-accent"
|
|
49
|
-
>
|
|
50
|
-
<div class="flex items-center gap-hsp-xs text-caption text-muted mb-vsp-2xs">
|
|
51
|
-
<ChevronLeft className="h-[1.125rem] w-[1.125rem]" />
|
|
52
|
-
<span class="no-underline">{t("nav.previous", locale)}</span>
|
|
53
|
-
</div>
|
|
54
|
-
<p class="text-small font-semibold underline group-hover:text-accent">
|
|
55
|
-
{prev.label}
|
|
56
|
-
</p>
|
|
57
|
-
</a>
|
|
58
|
-
) : (
|
|
59
|
-
<div />
|
|
60
|
-
)}
|
|
61
|
-
{next ? (
|
|
62
|
-
<a
|
|
63
|
-
href={next.href}
|
|
64
|
-
class="group border border-muted rounded-lg p-hsp-lg hover:border-accent text-right"
|
|
65
|
-
>
|
|
66
|
-
<div class="flex items-center justify-end gap-hsp-xs text-caption text-muted mb-vsp-2xs">
|
|
67
|
-
<span class="no-underline">{t("nav.next", locale)}</span>
|
|
68
|
-
<ChevronRight className="h-[1.125rem] w-[1.125rem]" />
|
|
69
|
-
</div>
|
|
70
|
-
<p class="text-small font-semibold underline group-hover:text-accent">
|
|
71
|
-
{next.label}
|
|
72
|
-
</p>
|
|
73
|
-
</a>
|
|
74
|
-
) : (
|
|
75
|
-
<div />
|
|
76
|
-
)}
|
|
77
|
-
</nav>
|
|
78
|
-
);
|
|
79
|
-
}
|
|
9
|
+
export const DocPager = createDocPager({ t });
|
|
@@ -1,188 +1,54 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
// a per-route signature), so the expensive per-entry work — extractHeadings,
|
|
14
|
-
// buildBreadcrumbs, prev/next resolution — runs ONCE per entry per build,
|
|
15
|
-
// not once per entry per page (zfb re-invokes paths() once per built page).
|
|
16
|
-
//
|
|
17
|
-
// Versioned-vs-latest behavior is keyed on the presence of `urlFor` (#1916):
|
|
18
|
-
// - `urlFor` set (versioned routes): breadcrumbs resolve against the NAV
|
|
19
|
-
// tree (unlisted excluded) with crumbs remapped to the versioned URL
|
|
20
|
-
// space; prev/next hrefs are rewritten through the closure; auto-index
|
|
21
|
-
// child-card hrefs are ALWAYS remapped to the versioned URL.
|
|
22
|
-
// - `urlFor` unset (latest routes): breadcrumbs resolve against the FULL
|
|
23
|
-
// tree (unlisted included, for accurate crumbs); prev/next and child
|
|
24
|
-
// hrefs keep the latest `docsUrl` already baked into the nav nodes.
|
|
25
|
-
// These two behaviors travel together by construction: only versioned routes
|
|
26
|
-
// own a versioned URL closure (see _doc-route-paths.ts for the #1916
|
|
27
|
-
// rationale on why latest routes must never receive one).
|
|
28
|
-
|
|
1
|
+
// Thin stub — doc-route-entries moved to the package (epic #2344, S6).
|
|
2
|
+
// Calls `createDocRouteEntries(ctx)` from @takazudo/zudo-doc/doc-route-entries
|
|
3
|
+
// with the host utilities injected, then re-exports the resulting builder
|
|
4
|
+
// function so all existing call sites continue to work unchanged.
|
|
5
|
+
|
|
6
|
+
import { createDocRouteEntries } from "@takazudo/zudo-doc/doc-route-entries";
|
|
7
|
+
import type {
|
|
8
|
+
DocPageEntry,
|
|
9
|
+
DocNavNode,
|
|
10
|
+
BreadcrumbItem,
|
|
11
|
+
} from "@takazudo/zudo-doc/doc-route-entries";
|
|
12
|
+
export type { DocRouteEntry, BuildDocRouteEntriesArgs } from "@takazudo/zudo-doc/doc-route-entries";
|
|
29
13
|
import {
|
|
30
14
|
buildNavTree,
|
|
31
15
|
buildBreadcrumbs,
|
|
32
16
|
collectAutoIndexNodes,
|
|
33
17
|
type NavNode,
|
|
18
|
+
type CategoryMeta,
|
|
34
19
|
} from "@/utils/docs";
|
|
35
20
|
import { getNavSectionForSlug, getNavSubtree } from "@/utils/nav-scope";
|
|
36
21
|
import { toRouteSlug, toSlugParams } from "@/utils/slug";
|
|
22
|
+
import type { DocsEntry } from "@/types/docs-entry";
|
|
37
23
|
import type { Locale } from "@/config/i18n";
|
|
38
24
|
import { extractHeadings } from "./_extract-headings";
|
|
39
|
-
import type { AutoIndexNode, DocPageBaseProps } from "./doc-page-props";
|
|
40
|
-
import { memoizeDerived } from "./_nav-source-cache";
|
|
41
|
-
import type { NavSourceDocs } from "./_nav-source-docs";
|
|
42
|
-
import {
|
|
43
|
-
resolveDocPrevNext,
|
|
44
|
-
flattenSubtree,
|
|
45
|
-
rewriteNavHref,
|
|
46
|
-
remapNavChildHrefs,
|
|
47
|
-
} from "./_doc-route-paths";
|
|
48
|
-
|
|
49
|
-
// ---------------------------------------------------------------------------
|
|
50
|
-
// Types
|
|
51
|
-
// ---------------------------------------------------------------------------
|
|
52
|
-
|
|
53
|
-
/** One enumerated doc route: a content entry or an auto-generated category
|
|
54
|
-
* index, with all per-page derived data pre-computed. */
|
|
55
|
-
export interface DocRouteEntry {
|
|
56
|
-
/** Canonical route slug ("" for the docs root index — #1891). */
|
|
57
|
-
slug: string;
|
|
58
|
-
/** Optional-catchall params array — `toSlugParams(slug)` ([] for the root). */
|
|
59
|
-
slugParams: string[];
|
|
60
|
-
/**
|
|
61
|
-
* True when the entry came from the base collection rather than the locale
|
|
62
|
-
* collection (`!localeSlugSet.has(slug)`). Only meaningful on routes whose
|
|
63
|
-
* nav source performs a locale merge — routes without one (default-locale /
|
|
64
|
-
* versioned-EN, where `localeSlugSet` is empty) must ignore this field.
|
|
65
|
-
* Always false for autoIndex items.
|
|
66
|
-
*/
|
|
67
|
-
isFallback: boolean;
|
|
68
|
-
/** Shared page props (kind/entry/autoIndex/breadcrumbs/prev/next/headings). */
|
|
69
|
-
props: DocPageBaseProps;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export interface BuildDocRouteEntriesArgs {
|
|
73
|
-
/** Identity-stable nav source for this route's (locale, version) context —
|
|
74
|
-
* from resolveNavSource / resolveVersionedLocaleSource. The memo is keyed
|
|
75
|
-
* on `source.docs` identity, so the source MUST come from those resolvers
|
|
76
|
-
* (a fresh array defeats the memo — harmless, but recomputes per call). */
|
|
77
|
-
source: NavSourceDocs;
|
|
78
|
-
/** Active locale for nav-tree labels and breadcrumbs. */
|
|
79
|
-
locale: Locale;
|
|
80
|
-
/**
|
|
81
|
-
* Unique memo signature for this route context. Each route file passes its
|
|
82
|
-
* own prefix plus the loop variables (version slug / locale), e.g.
|
|
83
|
-
* "docs;en", "locale-docs;ja", "v-docs;1.0", "v-locale-docs;1.0;ja" —
|
|
84
|
-
* call sites that share a docs array identity must never collide on a key.
|
|
85
|
-
*/
|
|
86
|
-
routeSig: string;
|
|
87
|
-
/** Versioned URL closure bound to the route's version (+ locale). Presence
|
|
88
|
-
* switches the versioned behaviors documented in the module header. */
|
|
89
|
-
urlFor?: (slug: string) => string;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// ---------------------------------------------------------------------------
|
|
93
|
-
// buildDocRouteEntries
|
|
94
|
-
// ---------------------------------------------------------------------------
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Enumerate all doc routes (content entries + auto-index pages) for one
|
|
98
|
-
* (locale, version) context, with per-entry derived data pre-computed.
|
|
99
|
-
*
|
|
100
|
-
* Memoized per build on the identity-stable `source.docs` array (#1902), so
|
|
101
|
-
* repeated paths() invocations across the route's many pages return the SAME
|
|
102
|
-
* array instance without redoing the per-entry work. In the no-snapshot
|
|
103
|
-
* fallback path (unit tests / direct Node runs) `source.docs` is a fresh
|
|
104
|
-
* array per call, so the memo misses and this computes fresh — matching the
|
|
105
|
-
* deliberate no-memo policy in _nav-source-cache.ts.
|
|
106
|
-
*/
|
|
107
|
-
export function buildDocRouteEntries(
|
|
108
|
-
args: BuildDocRouteEntriesArgs,
|
|
109
|
-
): DocRouteEntry[] {
|
|
110
|
-
const { source, locale, routeSig, urlFor } = args;
|
|
111
|
-
|
|
112
|
-
return memoizeDerived([source.docs], `docRouteEntries;${routeSig}`, () => {
|
|
113
|
-
const { docs, navDocs, categoryMeta, localeSlugSet } = source;
|
|
114
|
-
|
|
115
|
-
// Nav docs: exclude unlisted (for sidebar/prev-next) but keep for breadcrumbs
|
|
116
|
-
const tree = buildNavTree(navDocs, locale, categoryMeta);
|
|
117
|
-
// Breadcrumb tree: latest routes use the full tree (including unlisted)
|
|
118
|
-
// for accurate crumbs; versioned routes resolve crumbs against the nav
|
|
119
|
-
// tree itself (#1916 #1).
|
|
120
|
-
const breadcrumbTree = urlFor ? tree : buildNavTree(docs, locale, categoryMeta);
|
|
121
|
-
|
|
122
|
-
const result: DocRouteEntry[] = [];
|
|
123
|
-
|
|
124
|
-
// Regular doc pages
|
|
125
|
-
for (const entry of docs) {
|
|
126
|
-
// A `category_no_page` index.mdx carries category metadata only — keep
|
|
127
|
-
// it in the nav tree (built above, used for breadcrumbs) but emit NO
|
|
128
|
-
// route for it. zfb's walker retains every .mdx as a collection entry,
|
|
129
|
-
// so without this explicit skip the metadata file would silently add a
|
|
130
|
-
// route.
|
|
131
|
-
if (entry.data.category_no_page === true) continue;
|
|
132
|
-
// Canonical route slug via the one shared rule (@/utils/slug) — yields
|
|
133
|
-
// "" for a root index (URL /docs/ — #1891).
|
|
134
|
-
const slug = entry.data.slug ?? toRouteSlug(entry.slug);
|
|
135
|
-
const navSection = getNavSectionForSlug(slug);
|
|
136
|
-
const subtree = getNavSubtree(tree, navSection);
|
|
137
|
-
|
|
138
|
-
// Prev/next + frontmatter pagination overrides resolved against THIS
|
|
139
|
-
// route's own `tree`; versioned routes then rewrite the hrefs through
|
|
140
|
-
// their urlFor closure (latest routes pass it through unchanged).
|
|
141
|
-
const { prev: prevNode, next: nextNode } = resolveDocPrevNext(
|
|
142
|
-
tree,
|
|
143
|
-
flattenSubtree(subtree),
|
|
144
|
-
slug,
|
|
145
|
-
entry.data,
|
|
146
|
-
);
|
|
147
|
-
|
|
148
|
-
result.push({
|
|
149
|
-
slug,
|
|
150
|
-
slugParams: toSlugParams(slug),
|
|
151
|
-
isFallback: !localeSlugSet.has(slug),
|
|
152
|
-
props: {
|
|
153
|
-
kind: "entry",
|
|
154
|
-
entry,
|
|
155
|
-
breadcrumbs: buildBreadcrumbs(breadcrumbTree, slug, locale, urlFor),
|
|
156
|
-
prev: rewriteNavHref(prevNode, urlFor),
|
|
157
|
-
next: rewriteNavHref(nextNode, urlFor),
|
|
158
|
-
headings: extractHeadings(entry.body ?? ""),
|
|
159
|
-
},
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Auto-generated index pages for categories without index.mdx
|
|
164
|
-
for (const node of collectAutoIndexNodes(tree)) {
|
|
165
|
-
result.push({
|
|
166
|
-
slug: node.slug,
|
|
167
|
-
slugParams: toSlugParams(node.slug),
|
|
168
|
-
isFallback: false,
|
|
169
|
-
props: {
|
|
170
|
-
kind: "autoIndex",
|
|
171
|
-
autoIndex: urlFor
|
|
172
|
-
? // #1916 #2: child-card hrefs ALWAYS resolve to the versioned URL.
|
|
173
|
-
({
|
|
174
|
-
...node,
|
|
175
|
-
children: remapNavChildHrefs(node.children, urlFor) as NavNode[],
|
|
176
|
-
} as AutoIndexNode)
|
|
177
|
-
: (node as AutoIndexNode),
|
|
178
|
-
breadcrumbs: buildBreadcrumbs(breadcrumbTree, node.slug, locale, urlFor),
|
|
179
|
-
prev: null,
|
|
180
|
-
next: null,
|
|
181
|
-
headings: [],
|
|
182
|
-
},
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
25
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
26
|
+
export const { buildDocRouteEntries } = createDocRouteEntries({
|
|
27
|
+
// The factory describes its injected nav builders with the package's own
|
|
28
|
+
// structural counterparts (DocPageEntry / DocNavNode / Map<string, unknown>)
|
|
29
|
+
// and a plain `locale: string`. The host's buildNavTree / buildBreadcrumbs
|
|
30
|
+
// are typed against the concrete project types (DocsEntry / NavNode / the
|
|
31
|
+
// Locale union / Map<string, CategoryMeta>). They are runtime-identical, so
|
|
32
|
+
// the stub adapts them with thin wrappers that cast at the injection boundary
|
|
33
|
+
// where the host owns the type knowledge.
|
|
34
|
+
buildNavTree: (docs: DocPageEntry[], locale: string, categoryMeta: Map<string, unknown>) =>
|
|
35
|
+
buildNavTree(
|
|
36
|
+
docs as unknown as DocsEntry[],
|
|
37
|
+
locale as Locale,
|
|
38
|
+
categoryMeta as Map<string, CategoryMeta>,
|
|
39
|
+
) as DocNavNode[],
|
|
40
|
+
buildBreadcrumbs: (
|
|
41
|
+
tree: DocNavNode[],
|
|
42
|
+
slug: string,
|
|
43
|
+
locale: string,
|
|
44
|
+
urlFor?: (slug: string) => string,
|
|
45
|
+
): BreadcrumbItem[] =>
|
|
46
|
+
buildBreadcrumbs(tree as NavNode[], slug, locale as Locale, urlFor),
|
|
47
|
+
collectAutoIndexNodes: (tree: DocNavNode[]) =>
|
|
48
|
+
collectAutoIndexNodes(tree as NavNode[]) as DocNavNode[],
|
|
49
|
+
getNavSectionForSlug,
|
|
50
|
+
getNavSubtree,
|
|
51
|
+
toRouteSlug,
|
|
52
|
+
toSlugParams,
|
|
53
|
+
extractHeadings,
|
|
54
|
+
});
|