create-zudo-doc 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +146 -0
- package/bin/create-zudo-doc.js +2 -0
- package/dist/api.d.ts +20 -0
- package/dist/api.js +13 -0
- package/dist/claude-md-gen.d.ts +2 -0
- package/dist/claude-md-gen.js +113 -0
- package/dist/cli.d.ts +39 -0
- package/dist/cli.js +157 -0
- package/dist/compose.d.ts +95 -0
- package/dist/compose.js +206 -0
- package/dist/constants.d.ts +20 -0
- package/dist/constants.js +224 -0
- package/dist/features/body-foot-util.d.ts +10 -0
- package/dist/features/body-foot-util.js +12 -0
- package/dist/features/claude-resources.d.ts +2 -0
- package/dist/features/claude-resources.js +6 -0
- package/dist/features/design-token-panel.d.ts +14 -0
- package/dist/features/design-token-panel.js +27 -0
- package/dist/features/doc-history.d.ts +9 -0
- package/dist/features/doc-history.js +11 -0
- package/dist/features/doc-tags.d.ts +19 -0
- package/dist/features/doc-tags.js +33 -0
- package/dist/features/footer-taglist.d.ts +14 -0
- package/dist/features/footer-taglist.js +17 -0
- package/dist/features/footer.d.ts +8 -0
- package/dist/features/footer.js +10 -0
- package/dist/features/i18n.d.ts +22 -0
- package/dist/features/i18n.js +41 -0
- package/dist/features/image-enlarge.d.ts +11 -0
- package/dist/features/image-enlarge.js +13 -0
- package/dist/features/index.d.ts +15 -0
- package/dist/features/index.js +53 -0
- package/dist/features/llms-txt.d.ts +11 -0
- package/dist/features/llms-txt.js +13 -0
- package/dist/features/search.d.ts +9 -0
- package/dist/features/search.js +11 -0
- package/dist/features/sidebar-resizer.d.ts +14 -0
- package/dist/features/sidebar-resizer.js +16 -0
- package/dist/features/sidebar-toggle.d.ts +13 -0
- package/dist/features/sidebar-toggle.js +15 -0
- package/dist/features/tag-governance.d.ts +14 -0
- package/dist/features/tag-governance.js +16 -0
- package/dist/features/tauri-dev.d.ts +2 -0
- package/dist/features/tauri-dev.js +25 -0
- package/dist/features/tauri.d.ts +11 -0
- package/dist/features/tauri.js +52 -0
- package/dist/features/versioning.d.ts +27 -0
- package/dist/features/versioning.js +43 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +150 -0
- package/dist/preset.d.ts +37 -0
- package/dist/preset.js +156 -0
- package/dist/prompts.d.ts +32 -0
- package/dist/prompts.js +248 -0
- package/dist/scaffold.d.ts +4 -0
- package/dist/scaffold.js +344 -0
- package/dist/settings-gen.d.ts +2 -0
- package/dist/settings-gen.js +237 -0
- package/dist/utils.d.ts +8 -0
- package/dist/utils.js +34 -0
- package/dist/zfb-config-gen.d.ts +19 -0
- package/dist/zfb-config-gen.js +222 -0
- package/package.json +65 -0
- package/templates/base/.htmlvalidate.json +5 -0
- package/templates/base/.zfb/doc-history-meta.json +1 -0
- package/templates/base/pages/404.tsx +55 -0
- package/templates/base/pages/_data.ts +179 -0
- package/templates/base/pages/_mdx-components.ts +249 -0
- package/templates/base/pages/docs/[...slug].tsx +448 -0
- package/templates/base/pages/index.tsx +158 -0
- package/templates/base/pages/lib/_body-end-islands.tsx +201 -0
- package/templates/base/pages/lib/_category-nav.tsx +148 -0
- package/templates/base/pages/lib/_category-tree-nav.tsx +104 -0
- package/templates/base/pages/lib/_compose-meta-title.ts +29 -0
- package/templates/base/pages/lib/_details.tsx +30 -0
- package/templates/base/pages/lib/_doc-history-area.tsx +178 -0
- package/templates/base/pages/lib/_doc-metainfo-area.tsx +100 -0
- package/templates/base/pages/lib/_doc-tags-area.tsx +89 -0
- package/templates/base/pages/lib/_extract-headings.ts +81 -0
- package/templates/base/pages/lib/_footer-with-defaults.tsx +234 -0
- package/templates/base/pages/lib/_frontmatter-preview-data.ts +53 -0
- package/templates/base/pages/lib/_head-with-defaults.tsx +113 -0
- package/templates/base/pages/lib/_header-with-defaults.tsx +386 -0
- package/templates/base/pages/lib/_inline-version-switcher.tsx +84 -0
- package/templates/base/pages/lib/_math-block.tsx +63 -0
- package/templates/base/pages/lib/_nav-source-docs.ts +68 -0
- package/templates/base/pages/lib/_preset-generator.tsx +81 -0
- package/templates/base/pages/lib/_search-widget-script.ts +388 -0
- package/templates/base/pages/lib/_search-widget.tsx +196 -0
- package/templates/base/pages/lib/_sidebar-with-defaults.tsx +176 -0
- package/templates/base/pages/lib/_site-tree-nav.tsx +128 -0
- package/templates/base/pages/lib/locale-merge.ts +58 -0
- package/templates/base/pages/lib/route-enumerators.ts +302 -0
- package/templates/base/pages/sitemap.xml.tsx +51 -0
- package/templates/base/plugins/connect-adapter.mjs +144 -0
- package/templates/base/plugins/copy-public-plugin.mjs +50 -0
- package/templates/base/plugins/search-index-plugin.mjs +54 -0
- package/templates/base/scripts/run-b4push.sh +102 -0
- package/templates/base/src/components/ai-chat-modal.tsx +15 -0
- package/templates/base/src/components/client-router-bootstrap.tsx +14 -0
- package/templates/base/src/components/content/component-map.ts +25 -0
- package/templates/base/src/components/content/content-blockquote.tsx +16 -0
- package/templates/base/src/components/content/content-code.tsx +117 -0
- package/templates/base/src/components/content/content-link.tsx +83 -0
- package/templates/base/src/components/content/content-ol.tsx +19 -0
- package/templates/base/src/components/content/content-paragraph.tsx +10 -0
- package/templates/base/src/components/content/content-strong.tsx +16 -0
- package/templates/base/src/components/content/content-table.tsx +18 -0
- package/templates/base/src/components/content/content-ul.tsx +18 -0
- package/templates/base/src/components/content/heading-h2.tsx +26 -0
- package/templates/base/src/components/content/heading-h3.tsx +26 -0
- package/templates/base/src/components/content/heading-h4.tsx +26 -0
- package/templates/base/src/components/design-token-panel-bootstrap.tsx +15 -0
- package/templates/base/src/components/desktop-sidebar-toggle.tsx +15 -0
- package/templates/base/src/components/doc-history.tsx +18 -0
- package/templates/base/src/components/html-preview/highlighted-code.tsx +74 -0
- package/templates/base/src/components/html-preview/html-preview.tsx +108 -0
- package/templates/base/src/components/html-preview/preflight.ts +112 -0
- package/templates/base/src/components/html-preview/preview-base.tsx +159 -0
- package/templates/base/src/components/image-enlarge.tsx +19 -0
- package/templates/base/src/components/mobile-toc.tsx +94 -0
- package/templates/base/src/components/preset-generator.tsx +14 -0
- package/templates/base/src/components/sidebar-toggle.tsx +98 -0
- package/templates/base/src/components/sidebar-tree.tsx +543 -0
- package/templates/base/src/components/site-tree-nav.tsx +233 -0
- package/templates/base/src/components/theme-toggle.tsx +93 -0
- package/templates/base/src/components/toc.tsx +63 -0
- package/templates/base/src/components/tree-nav-shared.tsx +71 -0
- package/templates/base/src/config/color-scheme-utils.ts +182 -0
- package/templates/base/src/config/color-schemes.ts +128 -0
- package/templates/base/src/config/frontmatter-preview-defaults.ts +24 -0
- package/templates/base/src/config/frontmatter-preview-renderers.tsx +46 -0
- package/templates/base/src/config/i18n.ts +225 -0
- package/templates/base/src/config/settings-types.ts +162 -0
- package/templates/base/src/config/sidebars.ts +66 -0
- package/templates/base/src/config/tag-vocabulary-types.ts +39 -0
- package/templates/base/src/config/tag-vocabulary.ts +20 -0
- package/templates/base/src/hooks/use-active-heading.ts +133 -0
- package/templates/base/src/plugins/docs-source-map.ts +103 -0
- package/templates/base/src/plugins/hast-utils.ts +10 -0
- package/templates/base/src/plugins/rehype-code-title.ts +50 -0
- package/templates/base/src/plugins/rehype-heading-links.ts +53 -0
- package/templates/base/src/plugins/rehype-image-enlarge.ts +113 -0
- package/templates/base/src/plugins/rehype-mermaid.ts +41 -0
- package/templates/base/src/plugins/rehype-strip-md-extension.ts +58 -0
- package/templates/base/src/plugins/remark-admonitions.ts +99 -0
- package/templates/base/src/plugins/remark-resolve-markdown-links.ts +127 -0
- package/templates/base/src/plugins/url-utils.ts +4 -0
- package/templates/base/src/styles/global.css +1066 -0
- package/templates/base/src/types/docs-entry.ts +39 -0
- package/templates/base/src/types/heading.ts +5 -0
- package/templates/base/src/types/locale.ts +10 -0
- package/templates/base/src/utils/base.ts +139 -0
- package/templates/base/src/utils/content-files.ts +106 -0
- package/templates/base/src/utils/dedent.ts +24 -0
- package/templates/base/src/utils/docs.ts +335 -0
- package/templates/base/src/utils/git-info.ts +70 -0
- package/templates/base/src/utils/github.ts +19 -0
- package/templates/base/src/utils/header-right-items.ts +38 -0
- package/templates/base/src/utils/nav-scope.ts +63 -0
- package/templates/base/src/utils/sidebar.ts +104 -0
- package/templates/base/src/utils/slug.ts +10 -0
- package/templates/base/src/utils/smart-break.tsx +126 -0
- package/templates/base/src/utils/tags.ts +126 -0
- package/templates/base/tsconfig.json +36 -0
- package/templates/features/bodyFootUtil/files/src/utils/github.ts +19 -0
- package/templates/features/claudeResources/files/plugins/claude-resources-plugin.mjs +137 -0
- package/templates/features/claudeResources/files/src/integrations/claude-resources/__tests__/escape-for-mdx.test.ts +34 -0
- package/templates/features/claudeResources/files/src/integrations/claude-resources/__tests__/generate.test.ts +376 -0
- package/templates/features/claudeResources/files/src/integrations/claude-resources/escape-for-mdx.ts +93 -0
- package/templates/features/claudeResources/files/src/integrations/claude-resources/generate.ts +586 -0
- package/templates/features/designTokenPanel/files/src/components/design-token-panel-bootstrap.tsx +15 -0
- package/templates/features/designTokenPanel/files/src/config/design-token-panel-config.ts +99 -0
- package/templates/features/designTokenPanel/files/src/config/design-tokens-manifest.ts +177 -0
- package/templates/features/designTokenPanel/files/src/lib/design-token-panel-bootstrap.ts +50 -0
- package/templates/features/docHistory/files/plugins/doc-history-plugin.mjs +99 -0
- package/templates/features/docHistory/files/src/components/doc-history.tsx +598 -0
- package/templates/features/docHistory/files/src/types/doc-history.ts +23 -0
- package/templates/features/docHistory/files/src/utils/doc-history.ts +180 -0
- package/templates/features/docTags/files/pages/[locale]/docs/tags/[tag].tsx +116 -0
- package/templates/features/docTags/files/pages/[locale]/docs/tags/index.tsx +99 -0
- package/templates/features/docTags/files/pages/docs/tags/[tag].tsx +101 -0
- package/templates/features/docTags/files/pages/docs/tags/index.tsx +86 -0
- package/templates/features/i18n/files/pages/[locale]/docs/[...slug].tsx +467 -0
- package/templates/features/i18n/files/pages/[locale]/index.tsx +213 -0
- package/templates/features/imageEnlarge/files/src/components/image-enlarge.tsx +248 -0
- package/templates/features/llmsTxt/files/plugins/llms-txt-plugin.mjs +74 -0
- package/templates/features/sidebarResizer/files/src/scripts/sidebar-resizer.ts +185 -0
- package/templates/features/sidebarToggle/files/src/components/desktop-sidebar-toggle.tsx +126 -0
- package/templates/features/tagGovernance/files/scripts/tags-audit.ts +576 -0
- package/templates/features/tagGovernance/files/scripts/tags-suggest.ts +428 -0
- package/templates/features/tauri/files/src/components/find-bar.tsx +122 -0
- package/templates/features/tauri/files/src/components/find-in-page-init.tsx +53 -0
- package/templates/features/tauri/files/src/utils/find-in-page.ts +175 -0
- package/templates/features/tauri/files/src-tauri/Cargo.toml +14 -0
- package/templates/features/tauri/files/src-tauri/build.rs +3 -0
- package/templates/features/tauri/files/src-tauri/capabilities/default.json +11 -0
- package/templates/features/tauri/files/src-tauri/src/main.rs +250 -0
- package/templates/features/tauri/files/src-tauri/tauri.conf.json +25 -0
- package/templates/features/tauriDev/files/src-tauri-dev/Cargo.toml +15 -0
- package/templates/features/tauriDev/files/src-tauri-dev/build.rs +3 -0
- package/templates/features/tauriDev/files/src-tauri-dev/capabilities/default.json +7 -0
- package/templates/features/tauriDev/files/src-tauri-dev/frontend/index.html +187 -0
- package/templates/features/tauriDev/files/src-tauri-dev/icons/icon.png +0 -0
- package/templates/features/tauriDev/files/src-tauri-dev/src/main.rs +995 -0
- package/templates/features/tauriDev/files/src-tauri-dev/tauri.conf.json +22 -0
- package/templates/features/tauriDev/files/src-tauri-dev/test-launch.sh +65 -0
- package/templates/features/versioning/files/pages/[locale]/docs/versions.tsx +100 -0
- package/templates/features/versioning/files/pages/docs/versions.tsx +78 -0
- package/templates/features/versioning/files/pages/v/[version]/docs/[...slug].tsx +451 -0
- package/templates/features/versioning/files/pages/v/[version]/ja/docs/[...slug].tsx +490 -0
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
/** @jsxRuntime automatic */
|
|
2
|
+
/** @jsxImportSource preact */
|
|
3
|
+
// Port of src/pages/docs/[...slug].astro → zfb page module.
|
|
4
|
+
//
|
|
5
|
+
// Default-locale (EN) catch-all docs route. paths() enumerates every page in
|
|
6
|
+
// the "docs" collection plus auto-generated category index pages (for
|
|
7
|
+
// categories without an index.mdx). Per-page props carry all pre-computed
|
|
8
|
+
// data so the component is a pure renderer with no collection reads.
|
|
9
|
+
//
|
|
10
|
+
// paths() contract (zfb ADR-004 — synchronous):
|
|
11
|
+
// params: { slug: string[] } — e.g. ["getting-started", "intro"]
|
|
12
|
+
// props: { entry, autoIndex, breadcrumbs, prev, next }
|
|
13
|
+
//
|
|
14
|
+
// The catchall slug is an array per zfb spec — the component joins it when
|
|
15
|
+
// deriving the string form (e.g. for Content lookups, breadcrumbs, etc.).
|
|
16
|
+
//
|
|
17
|
+
// Locale: defaultLocale (EN). Non-default locales are handled by
|
|
18
|
+
// pages/[locale]/docs/[...slug].tsx.
|
|
19
|
+
|
|
20
|
+
import { getCollection } from "zfb/content";
|
|
21
|
+
import type { CollectionEntry } from "zfb/content";
|
|
22
|
+
import type { DocsEntry } from "@/types/docs-entry";
|
|
23
|
+
import { settings } from "@/config/settings";
|
|
24
|
+
import { defaultLocale, t } from "@/config/i18n";
|
|
25
|
+
import { docsUrl } from "@/utils/base";
|
|
26
|
+
import {
|
|
27
|
+
buildNavTree,
|
|
28
|
+
buildBreadcrumbs,
|
|
29
|
+
flattenTree,
|
|
30
|
+
findNode,
|
|
31
|
+
loadCategoryMeta,
|
|
32
|
+
collectAutoIndexNodes,
|
|
33
|
+
isNavVisible,
|
|
34
|
+
type NavNode,
|
|
35
|
+
type BreadcrumbItem,
|
|
36
|
+
} from "@/utils/docs";
|
|
37
|
+
import { getNavSectionForSlug, getNavSubtree } from "@/utils/nav-scope";
|
|
38
|
+
import { toRouteSlug } from "@/utils/slug";
|
|
39
|
+
import { DocLayoutWithDefaults } from "@takazudo/zudo-doc/doclayout";
|
|
40
|
+
import { Breadcrumb } from "@takazudo/zudo-doc/breadcrumb";
|
|
41
|
+
import { NavCardGrid } from "@takazudo/zudo-doc/nav-indexing";
|
|
42
|
+
import { FrontmatterPreview } from "@takazudo/zudo-doc/metainfo";
|
|
43
|
+
import { frontmatterRenderers } from "@/config/frontmatter-preview-renderers";
|
|
44
|
+
// Shared MDX-tag → Preact-component bag. Includes htmlOverrides
|
|
45
|
+
// (native typography), HtmlPreviewWrapper (Island), and stub bindings
|
|
46
|
+
// for every other custom tag the MDX corpus references — see
|
|
47
|
+
// `pages/_mdx-components.ts` for the full list and rationale.
|
|
48
|
+
import { createMdxComponents } from "../_mdx-components";
|
|
49
|
+
import { FooterWithDefaults } from "../lib/_footer-with-defaults";
|
|
50
|
+
import { DocHistoryArea } from "../lib/_doc-history-area";
|
|
51
|
+
import { DocMetainfoArea } from "../lib/_doc-metainfo-area";
|
|
52
|
+
import { DocTagsArea } from "../lib/_doc-tags-area";
|
|
53
|
+
import { BodyEndIslands } from "../lib/_body-end-islands";
|
|
54
|
+
import { SidebarWithDefaults } from "../lib/_sidebar-with-defaults";
|
|
55
|
+
import { HeaderWithDefaults } from "../lib/_header-with-defaults";
|
|
56
|
+
import { HeadWithDefaults } from "../lib/_head-with-defaults";
|
|
57
|
+
import { buildFrontmatterPreviewEntries } from "../lib/_frontmatter-preview-data";
|
|
58
|
+
import { composeMetaTitle } from "../lib/_compose-meta-title";
|
|
59
|
+
import { buildInlineVersionSwitcher } from "../lib/_inline-version-switcher";
|
|
60
|
+
import type { JSX } from "preact";
|
|
61
|
+
import { bridgeEntries } from "../_data";
|
|
62
|
+
import { extractHeadings } from "../lib/_extract-headings";
|
|
63
|
+
import DesktopSidebarToggle from "@/components/desktop-sidebar-toggle";
|
|
64
|
+
import { SidebarResizerInit } from "@takazudo/zudo-doc/sidebar-resizer";
|
|
65
|
+
import type { VNode } from "preact";
|
|
66
|
+
import { Island } from "@takazudo/zfb";
|
|
67
|
+
|
|
68
|
+
export const frontmatter = { title: "Docs" };
|
|
69
|
+
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
// Props contract
|
|
72
|
+
// ---------------------------------------------------------------------------
|
|
73
|
+
|
|
74
|
+
interface DocPageEntry extends DocsEntry {
|
|
75
|
+
/** zfb content renderer. */
|
|
76
|
+
Content: CollectionEntry<unknown>["Content"];
|
|
77
|
+
/** zfb module specifier (for Content bridge). */
|
|
78
|
+
module_specifier: string;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
interface AutoIndexNode extends NavNode {
|
|
82
|
+
children: NavNode[];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
interface DocPageProps {
|
|
86
|
+
/** The docs entry to render, or null for auto-index pages. */
|
|
87
|
+
entry: DocPageEntry | null;
|
|
88
|
+
/** Pre-built auto-index node (categories without index.mdx). */
|
|
89
|
+
autoIndex?: AutoIndexNode;
|
|
90
|
+
/** Breadcrumb trail, first item is home. */
|
|
91
|
+
breadcrumbs: BreadcrumbItem[];
|
|
92
|
+
/** Preceding page in the nav tree. */
|
|
93
|
+
prev: NavNode | null;
|
|
94
|
+
/** Following page in the nav tree. */
|
|
95
|
+
next: NavNode | null;
|
|
96
|
+
/** Depth-2/3/4 headings extracted from the MDX body, for SSG TOC links. */
|
|
97
|
+
headings: ReturnType<typeof extractHeadings>;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
// paths() — synchronous route enumeration (ADR-004)
|
|
102
|
+
// ---------------------------------------------------------------------------
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Enumerate all doc routes for the default locale (EN).
|
|
106
|
+
*
|
|
107
|
+
* Synchronous per ADR-004: getCollection() resolves from the pre-loaded
|
|
108
|
+
* ContentSnapshot. All nav-tree and breadcrumb computation is done here
|
|
109
|
+
* so the component is a pure renderer.
|
|
110
|
+
*/
|
|
111
|
+
export function paths(): Array<{
|
|
112
|
+
params: { slug: string[] };
|
|
113
|
+
props: DocPageProps;
|
|
114
|
+
}> {
|
|
115
|
+
const locale = defaultLocale;
|
|
116
|
+
const allDocs = (bridgeEntries(getCollection("docs"), "docs") as unknown as DocPageEntry[]);
|
|
117
|
+
// In static builds, always exclude drafts.
|
|
118
|
+
const docs = allDocs.filter((doc) => !doc.data.draft);
|
|
119
|
+
const categoryMeta = loadCategoryMeta(settings.docsDir);
|
|
120
|
+
|
|
121
|
+
// Nav docs: exclude unlisted (for sidebar/prev-next) but keep for breadcrumbs
|
|
122
|
+
const navDocs = docs.filter(isNavVisible);
|
|
123
|
+
const tree = buildNavTree(navDocs as unknown as DocsEntry[], locale, categoryMeta);
|
|
124
|
+
// Full tree (including unlisted) for accurate breadcrumbs
|
|
125
|
+
const fullTree = buildNavTree(docs as unknown as DocsEntry[], locale, categoryMeta);
|
|
126
|
+
|
|
127
|
+
const result: Array<{ params: { slug: string[] }; props: DocPageProps }> = [];
|
|
128
|
+
|
|
129
|
+
// Regular doc pages
|
|
130
|
+
for (const entry of docs) {
|
|
131
|
+
const slug = entry.data.slug ?? toRouteSlug(entry.slug);
|
|
132
|
+
const navSection = getNavSectionForSlug(slug);
|
|
133
|
+
const subtree = getNavSubtree(tree, navSection);
|
|
134
|
+
const flat = flattenTree(subtree);
|
|
135
|
+
const idx = flat.findIndex((n) => n.slug === slug);
|
|
136
|
+
|
|
137
|
+
let prevNode = idx > 0 ? flat[idx - 1] ?? null : null;
|
|
138
|
+
let nextNode = idx >= 0 && idx < flat.length - 1 ? flat[idx + 1] ?? null : null;
|
|
139
|
+
|
|
140
|
+
// Frontmatter pagination overrides
|
|
141
|
+
if (entry.data.pagination_prev !== undefined) {
|
|
142
|
+
if (entry.data.pagination_prev === null) {
|
|
143
|
+
prevNode = null;
|
|
144
|
+
} else {
|
|
145
|
+
const found = findNode(tree, entry.data.pagination_prev);
|
|
146
|
+
prevNode = found ?? prevNode;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (entry.data.pagination_next !== undefined) {
|
|
150
|
+
if (entry.data.pagination_next === null) {
|
|
151
|
+
nextNode = null;
|
|
152
|
+
} else {
|
|
153
|
+
const found = findNode(tree, entry.data.pagination_next);
|
|
154
|
+
nextNode = found ?? nextNode;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
result.push({
|
|
159
|
+
params: { slug: slug.split("/") },
|
|
160
|
+
props: {
|
|
161
|
+
entry,
|
|
162
|
+
breadcrumbs: buildBreadcrumbs(fullTree, slug, locale),
|
|
163
|
+
prev: prevNode,
|
|
164
|
+
next: nextNode,
|
|
165
|
+
headings: extractHeadings(entry.body ?? ""),
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Auto-generated index pages for categories without index.mdx
|
|
171
|
+
for (const node of collectAutoIndexNodes(tree)) {
|
|
172
|
+
result.push({
|
|
173
|
+
params: { slug: node.slug.split("/") },
|
|
174
|
+
props: {
|
|
175
|
+
entry: null,
|
|
176
|
+
autoIndex: node as AutoIndexNode,
|
|
177
|
+
breadcrumbs: buildBreadcrumbs(fullTree, node.slug, locale),
|
|
178
|
+
prev: null,
|
|
179
|
+
next: null,
|
|
180
|
+
headings: [],
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return result;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ---------------------------------------------------------------------------
|
|
189
|
+
// Page component
|
|
190
|
+
// ---------------------------------------------------------------------------
|
|
191
|
+
|
|
192
|
+
interface PageArgs {
|
|
193
|
+
params: { slug: string[] };
|
|
194
|
+
entry: DocPageProps["entry"];
|
|
195
|
+
autoIndex?: DocPageProps["autoIndex"];
|
|
196
|
+
breadcrumbs: DocPageProps["breadcrumbs"];
|
|
197
|
+
prev: DocPageProps["prev"];
|
|
198
|
+
next: DocPageProps["next"];
|
|
199
|
+
headings: DocPageProps["headings"];
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export default function DocsPage({ entry, autoIndex, breadcrumbs, prev, next, headings }: PageArgs): JSX.Element {
|
|
203
|
+
const locale = defaultLocale;
|
|
204
|
+
|
|
205
|
+
const slug = autoIndex
|
|
206
|
+
? autoIndex.slug
|
|
207
|
+
: (entry!.data.slug ?? toRouteSlug(entry!.slug));
|
|
208
|
+
|
|
209
|
+
const title = autoIndex ? autoIndex.label : entry!.data.title;
|
|
210
|
+
const description = autoIndex ? autoIndex.description : entry!.data.description;
|
|
211
|
+
|
|
212
|
+
// Locale-aware components bag — creates nav wrappers bound to the active
|
|
213
|
+
// locale so CategoryNav/CategoryTreeNav/SiteTreeNav query the right collection.
|
|
214
|
+
const components = createMdxComponents(locale);
|
|
215
|
+
|
|
216
|
+
// Resolve child hrefs for auto-index pages
|
|
217
|
+
const autoIndexChildren = autoIndex
|
|
218
|
+
? autoIndex.children
|
|
219
|
+
.filter((c: NavNode) => c.hasPage || c.children.length > 0)
|
|
220
|
+
.map((c: NavNode) => ({
|
|
221
|
+
...c,
|
|
222
|
+
href: c.href ?? docsUrl(c.slug, locale),
|
|
223
|
+
}))
|
|
224
|
+
: [];
|
|
225
|
+
|
|
226
|
+
// Canonical URL — only when siteUrl is configured. pageUrl is the
|
|
227
|
+
// base-prefixed path for this page without the siteUrl origin.
|
|
228
|
+
const pageUrl = docsUrl(slug, locale);
|
|
229
|
+
const canonical = settings.siteUrl
|
|
230
|
+
? settings.siteUrl.replace(/\/$/, "") + pageUrl
|
|
231
|
+
: undefined;
|
|
232
|
+
|
|
233
|
+
// Persist key: locale + nav-section so the sidebar DOM node is reused
|
|
234
|
+
// across same-locale + same-section navigations only. No sanitizer needed —
|
|
235
|
+
// both lang (BCP-47 locale string) and navSection (filesystem-derived
|
|
236
|
+
// kebab-case slug) come from controlled, trusted sources.
|
|
237
|
+
const navSection = getNavSectionForSlug(slug);
|
|
238
|
+
const hideSidebar = entry?.data?.hide_sidebar;
|
|
239
|
+
const sidebarPersistKey = hideSidebar
|
|
240
|
+
? undefined
|
|
241
|
+
: `sidebar-${locale}-${navSection ?? "default"}`;
|
|
242
|
+
|
|
243
|
+
return (
|
|
244
|
+
<DocLayoutWithDefaults
|
|
245
|
+
title={composeMetaTitle(title)}
|
|
246
|
+
description={description}
|
|
247
|
+
head={<HeadWithDefaults title={title} description={description} canonical={canonical} />}
|
|
248
|
+
lang={locale}
|
|
249
|
+
noindex={settings.noindex}
|
|
250
|
+
hideSidebar={hideSidebar}
|
|
251
|
+
hideToc={entry?.data?.hide_toc}
|
|
252
|
+
headings={headings}
|
|
253
|
+
canonical={canonical}
|
|
254
|
+
sidebarPersistKey={sidebarPersistKey}
|
|
255
|
+
headerOverride={
|
|
256
|
+
<HeaderWithDefaults
|
|
257
|
+
lang={locale}
|
|
258
|
+
currentSlug={slug}
|
|
259
|
+
navSection={getNavSectionForSlug(slug)}
|
|
260
|
+
currentPath={docsUrl(slug, locale)}
|
|
261
|
+
/>
|
|
262
|
+
}
|
|
263
|
+
breadcrumbOverride={
|
|
264
|
+
breadcrumbs.length > 0 ? (
|
|
265
|
+
<Breadcrumb
|
|
266
|
+
items={breadcrumbs}
|
|
267
|
+
rightSlot={buildInlineVersionSwitcher(slug, locale)}
|
|
268
|
+
/>
|
|
269
|
+
) : undefined
|
|
270
|
+
}
|
|
271
|
+
sidebarOverride={
|
|
272
|
+
<SidebarWithDefaults
|
|
273
|
+
currentSlug={slug}
|
|
274
|
+
lang={locale}
|
|
275
|
+
navSection={getNavSectionForSlug(slug)}
|
|
276
|
+
currentPath={docsUrl(slug, locale)}
|
|
277
|
+
/>
|
|
278
|
+
}
|
|
279
|
+
afterSidebar={
|
|
280
|
+
// Pre-paint inline script: restore persisted sidebar visibility to
|
|
281
|
+
// <html data-sidebar-hidden> before first paint to avoid flash.
|
|
282
|
+
// Runs unconditionally when sidebarToggle is enabled; the attribute
|
|
283
|
+
// is only set when localStorage says "false" so the default (visible)
|
|
284
|
+
// needs no attribute and causes no layout shift.
|
|
285
|
+
settings.sidebarToggle ? (
|
|
286
|
+
<>
|
|
287
|
+
<script dangerouslySetInnerHTML={{
|
|
288
|
+
__html: `(function(){try{if(localStorage.getItem('zudo-doc-sidebar-visible')==='false'){document.documentElement.setAttribute('data-sidebar-hidden','');}}catch(e){}})();`,
|
|
289
|
+
}} />
|
|
290
|
+
{Island({
|
|
291
|
+
when: "load",
|
|
292
|
+
children: <DesktopSidebarToggle />,
|
|
293
|
+
}) as unknown as VNode}
|
|
294
|
+
</>
|
|
295
|
+
) : undefined
|
|
296
|
+
}
|
|
297
|
+
footerOverride={<FooterWithDefaults lang={locale} />}
|
|
298
|
+
bodyEndComponents={
|
|
299
|
+
<>
|
|
300
|
+
<BodyEndIslands basePath={settings.base ?? "/"} />
|
|
301
|
+
{/* SidebarResizerInit: attach drag handle to #desktop-sidebar on load
|
|
302
|
+
and on AFTER_NAVIGATE_EVENT (zfb:after-swap under the Strategy B
|
|
303
|
+
SPA navigation model). Idempotent — safe on every page. */}
|
|
304
|
+
{settings.sidebarResizer && <SidebarResizerInit />}
|
|
305
|
+
</>
|
|
306
|
+
}
|
|
307
|
+
>
|
|
308
|
+
{autoIndex ? (
|
|
309
|
+
/* Auto-index page: category without an index.mdx.
|
|
310
|
+
Fragment (not <div>) so children become direct children of
|
|
311
|
+
<article class="zd-content">, picking up the flow-space rule
|
|
312
|
+
(.zd-content > :where(* + *) { margin-top: var(--flow-space) }).
|
|
313
|
+
Wrapping in <div> would make h1/description p children-of-children
|
|
314
|
+
and the flow gap (~24px) would never apply — see #1460. */
|
|
315
|
+
<>
|
|
316
|
+
<h1 class="text-heading font-bold mb-vsp-xs">{autoIndex.label}</h1>
|
|
317
|
+
|
|
318
|
+
{/* Build-time date block — chrome parity (#1461). Auto-index pages
|
|
319
|
+
previously rendered without doc-meta; reference site shows it on
|
|
320
|
+
every docs page. The component returns null when no manifest
|
|
321
|
+
entry exists for this slug. */}
|
|
322
|
+
<DocMetainfoArea slug={slug} locale={locale} />
|
|
323
|
+
|
|
324
|
+
{autoIndex.description && (
|
|
325
|
+
<p class="mb-vsp-lg text-title text-muted">
|
|
326
|
+
{autoIndex.description}
|
|
327
|
+
</p>
|
|
328
|
+
)}
|
|
329
|
+
<NavCardGrid children={autoIndexChildren} />
|
|
330
|
+
</>
|
|
331
|
+
) : (
|
|
332
|
+
/* Regular doc page. Fragment (not <div>) for the same reason as
|
|
333
|
+
the auto-index branch above — see #1460. */
|
|
334
|
+
<>
|
|
335
|
+
<h1 class="text-heading font-bold mb-vsp-xs">{entry!.data.title}</h1>
|
|
336
|
+
|
|
337
|
+
{/* Build-time date block (Created / Updated / Author). Mirrors the
|
|
338
|
+
Astro `doc-metainfo.astro` placement — between <h1> and description.
|
|
339
|
+
Data from `.zfb/doc-history-meta.json` (esbuild-inlined, no fs). */}
|
|
340
|
+
<DocMetainfoArea slug={slug} locale={locale} />
|
|
341
|
+
|
|
342
|
+
{/* Page-level tag chips — mirroring doc-tags.astro placement (#1658). */}
|
|
343
|
+
<DocTagsArea slug={slug} locale={locale} tags={entry!.data.tags} />
|
|
344
|
+
|
|
345
|
+
{entry!.data.description && (
|
|
346
|
+
<p class="mb-vsp-lg text-title text-muted">
|
|
347
|
+
{entry!.data.description}
|
|
348
|
+
</p>
|
|
349
|
+
)}
|
|
350
|
+
|
|
351
|
+
{/* Frontmatter preview — non-system, custom keys only. Returns
|
|
352
|
+
null when the entries array is empty, so pages without
|
|
353
|
+
custom frontmatter emit nothing. Custom per-key renderers
|
|
354
|
+
from frontmatter-preview-renderers.tsx produce styled cells
|
|
355
|
+
(pills, badges, etc.) instead of plain text. */}
|
|
356
|
+
<FrontmatterPreview
|
|
357
|
+
entries={buildFrontmatterPreviewEntries(entry!.data)}
|
|
358
|
+
title={t("frontmatter.preview.title", locale)}
|
|
359
|
+
keyColLabel={t("frontmatter.preview.keyCol", locale)}
|
|
360
|
+
valueColLabel={t("frontmatter.preview.valueCol", locale)}
|
|
361
|
+
renderers={frontmatterRenderers}
|
|
362
|
+
data={entry!.data as Record<string, unknown>}
|
|
363
|
+
locale={locale}
|
|
364
|
+
/>
|
|
365
|
+
|
|
366
|
+
{/* MDX content rendered via zfb's Content bridge */}
|
|
367
|
+
{entry && <entry.Content components={components} />}
|
|
368
|
+
|
|
369
|
+
{/* Prev / Next pagination — placed before the document utilities
|
|
370
|
+
section to match the Astro reference order: content → pager →
|
|
371
|
+
view-source / history. In the Astro layout, BodyFootUtilArea was
|
|
372
|
+
rendered by the doc-layout wrapper after the <slot /> content,
|
|
373
|
+
so the pager (inside the slot) came first. Fixes #1535. */}
|
|
374
|
+
<nav class="mt-vsp-2xl grid grid-cols-2 gap-hsp-xl">
|
|
375
|
+
{prev ? (
|
|
376
|
+
<a
|
|
377
|
+
href={prev.href}
|
|
378
|
+
class="group border border-muted rounded-lg p-hsp-lg hover:border-accent"
|
|
379
|
+
>
|
|
380
|
+
<div class="flex items-center gap-hsp-xs text-caption text-muted mb-vsp-2xs">
|
|
381
|
+
<svg
|
|
382
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
383
|
+
class="h-[1.125rem] w-[1.125rem]"
|
|
384
|
+
fill="none"
|
|
385
|
+
viewBox="0 0 24 24"
|
|
386
|
+
stroke="currentColor"
|
|
387
|
+
stroke-width="2"
|
|
388
|
+
>
|
|
389
|
+
<path
|
|
390
|
+
stroke-linecap="round"
|
|
391
|
+
stroke-linejoin="round"
|
|
392
|
+
d="M15 19l-7-7 7-7"
|
|
393
|
+
/>
|
|
394
|
+
</svg>
|
|
395
|
+
<span class="no-underline">{t("nav.previous", locale)}</span>
|
|
396
|
+
</div>
|
|
397
|
+
<p class="text-small font-semibold underline group-hover:text-accent">
|
|
398
|
+
{prev.label}
|
|
399
|
+
</p>
|
|
400
|
+
</a>
|
|
401
|
+
) : (
|
|
402
|
+
<div />
|
|
403
|
+
)}
|
|
404
|
+
{next ? (
|
|
405
|
+
<a
|
|
406
|
+
href={next.href}
|
|
407
|
+
class="group border border-muted rounded-lg p-hsp-lg hover:border-accent text-right"
|
|
408
|
+
>
|
|
409
|
+
<div class="flex items-center justify-end gap-hsp-xs text-caption text-muted mb-vsp-2xs">
|
|
410
|
+
<span class="no-underline">{t("nav.next", locale)}</span>
|
|
411
|
+
<svg
|
|
412
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
413
|
+
class="h-[1.125rem] w-[1.125rem]"
|
|
414
|
+
fill="none"
|
|
415
|
+
viewBox="0 0 24 24"
|
|
416
|
+
stroke="currentColor"
|
|
417
|
+
stroke-width="2"
|
|
418
|
+
>
|
|
419
|
+
<path
|
|
420
|
+
stroke-linecap="round"
|
|
421
|
+
stroke-linejoin="round"
|
|
422
|
+
d="M9 5l7 7-7 7"
|
|
423
|
+
/>
|
|
424
|
+
</svg>
|
|
425
|
+
</div>
|
|
426
|
+
<p class="text-small font-semibold underline group-hover:text-accent">
|
|
427
|
+
{next.label}
|
|
428
|
+
</p>
|
|
429
|
+
</a>
|
|
430
|
+
) : (
|
|
431
|
+
<div />
|
|
432
|
+
)}
|
|
433
|
+
</nav>
|
|
434
|
+
|
|
435
|
+
{/* Document utilities (revision history + view-source link) — skipped for unlisted pages */}
|
|
436
|
+
{!entry!.data.unlisted && (
|
|
437
|
+
<DocHistoryArea
|
|
438
|
+
slug={slug}
|
|
439
|
+
locale={locale}
|
|
440
|
+
entrySlug={entry!.slug}
|
|
441
|
+
contentDir={settings.docsDir}
|
|
442
|
+
/>
|
|
443
|
+
)}
|
|
444
|
+
</>
|
|
445
|
+
)}
|
|
446
|
+
</DocLayoutWithDefaults>
|
|
447
|
+
);
|
|
448
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/** @jsxRuntime automatic */
|
|
2
|
+
/** @jsxImportSource preact */
|
|
3
|
+
// Port of src/pages/index.astro → zfb page module.
|
|
4
|
+
//
|
|
5
|
+
// Default-locale (EN) site index. Static route — no paths() export needed.
|
|
6
|
+
// Collects the EN docs tree and renders the site-map grid plus optional
|
|
7
|
+
// tag count.
|
|
8
|
+
//
|
|
9
|
+
// Data flow:
|
|
10
|
+
// getCollection("docs") [sync, zfb ADR-004]
|
|
11
|
+
// → buildNavTree() builds the nav tree for the sitemap grid
|
|
12
|
+
// → collectTags() counts unique tags for the tag section header
|
|
13
|
+
// → DocLayoutWithDefaults renders the page with no sidebar/TOC
|
|
14
|
+
|
|
15
|
+
import { loadDocs } from "./_data";
|
|
16
|
+
import { settings } from "@/config/settings";
|
|
17
|
+
import { defaultLocale, t } from "@/config/i18n";
|
|
18
|
+
import { withBase } from "@/utils/base";
|
|
19
|
+
import {
|
|
20
|
+
buildNavTree,
|
|
21
|
+
groupSatelliteNodes,
|
|
22
|
+
isNavVisible,
|
|
23
|
+
} from "@/utils/docs";
|
|
24
|
+
import { loadCategoryMeta } from "@/utils/docs";
|
|
25
|
+
import { getCategoryOrder } from "@/utils/nav-scope";
|
|
26
|
+
import { collectTags } from "@/utils/tags";
|
|
27
|
+
import { toRouteSlug } from "@/utils/slug";
|
|
28
|
+
import { DocLayoutWithDefaults } from "@takazudo/zudo-doc/doclayout";
|
|
29
|
+
import type { JSX } from "preact";
|
|
30
|
+
import type { VNode } from "preact";
|
|
31
|
+
import { Island } from "@takazudo/zfb";
|
|
32
|
+
import SiteTreeNav from "@/components/site-tree-nav";
|
|
33
|
+
import { FooterWithDefaults } from "./lib/_footer-with-defaults";
|
|
34
|
+
import { HeaderWithDefaults } from "./lib/_header-with-defaults";
|
|
35
|
+
import { HeadWithDefaults } from "./lib/_head-with-defaults";
|
|
36
|
+
import { composeMetaTitle } from "./lib/_compose-meta-title";
|
|
37
|
+
import { BodyEndIslands } from "./lib/_body-end-islands";
|
|
38
|
+
|
|
39
|
+
export const frontmatter = { title: "Home" };
|
|
40
|
+
|
|
41
|
+
export default function IndexPage(): JSX.Element {
|
|
42
|
+
const locale = defaultLocale;
|
|
43
|
+
|
|
44
|
+
// `loadDocs` bridges zfb's CollectionEntry → Astro-style DocsEntry
|
|
45
|
+
// (adds `id`/`collection`) so `@/utils/docs` helpers see the shape
|
|
46
|
+
// they expect.
|
|
47
|
+
const allDocs = loadDocs("docs");
|
|
48
|
+
const docs = allDocs.filter((doc) => !doc.data.draft);
|
|
49
|
+
const categoryMeta = loadCategoryMeta(settings.docsDir);
|
|
50
|
+
const navDocs = docs.filter(isNavVisible);
|
|
51
|
+
const tree = buildNavTree(navDocs, locale, categoryMeta);
|
|
52
|
+
const categoryOrder = getCategoryOrder();
|
|
53
|
+
const groupedTree = groupSatelliteNodes(tree, categoryOrder);
|
|
54
|
+
|
|
55
|
+
const tagDocs = docs.filter(isNavVisible);
|
|
56
|
+
const tagCount = collectTags(
|
|
57
|
+
tagDocs,
|
|
58
|
+
(id, data) => data.slug ?? toRouteSlug(id),
|
|
59
|
+
).size;
|
|
60
|
+
|
|
61
|
+
const ctaNav = settings.headerNav[0] ?? null;
|
|
62
|
+
const overview = ctaNav ? withBase(ctaNav.path) : null;
|
|
63
|
+
const logoUrl = withBase("/img/logo.svg");
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<DocLayoutWithDefaults
|
|
67
|
+
title={composeMetaTitle(settings.siteName)}
|
|
68
|
+
head={<HeadWithDefaults title={settings.siteName} />}
|
|
69
|
+
lang={locale}
|
|
70
|
+
noindex={settings.noindex}
|
|
71
|
+
hideSidebar={true}
|
|
72
|
+
hideToc={true}
|
|
73
|
+
headerOverride={<HeaderWithDefaults lang={locale} currentPath={withBase("/")} />}
|
|
74
|
+
footerOverride={<FooterWithDefaults lang={locale} />}
|
|
75
|
+
bodyEndComponents={<BodyEndIslands basePath={settings.base ?? "/"} />}
|
|
76
|
+
>
|
|
77
|
+
{/* Hero: logo left, title+desc+links right, block centered */}
|
|
78
|
+
<div class="flex justify-center mb-vsp-xl">
|
|
79
|
+
<div class="flex flex-col items-center text-center gap-hsp-md lg:flex-row lg:text-left lg:gap-hsp-xl">
|
|
80
|
+
<img
|
|
81
|
+
src={logoUrl}
|
|
82
|
+
alt={settings.siteName}
|
|
83
|
+
class="w-[320px] max-w-full aspect-[1200/630] shrink-0"
|
|
84
|
+
/>
|
|
85
|
+
<div>
|
|
86
|
+
<h1 class="text-heading font-bold mb-vsp-2xs">{settings.siteName}</h1>
|
|
87
|
+
<p class="text-muted text-small mb-vsp-sm">{settings.siteDescription}</p>
|
|
88
|
+
<div class="flex items-center justify-center lg:justify-start gap-hsp-md text-small">
|
|
89
|
+
{overview && (
|
|
90
|
+
<>
|
|
91
|
+
<a href={overview} class="text-fg underline hover:text-accent">
|
|
92
|
+
{t("nav.overview", locale)}
|
|
93
|
+
</a>
|
|
94
|
+
<span class="text-muted">/</span>
|
|
95
|
+
</>
|
|
96
|
+
)}
|
|
97
|
+
{settings.githubUrl && (
|
|
98
|
+
<>
|
|
99
|
+
<a
|
|
100
|
+
href={settings.githubUrl as string}
|
|
101
|
+
class="inline-flex items-center gap-[0.3em] text-fg underline hover:text-accent"
|
|
102
|
+
target="_blank"
|
|
103
|
+
rel="noopener noreferrer"
|
|
104
|
+
>
|
|
105
|
+
<svg viewBox="0 0 16 16" aria-hidden="true" class="w-[1em] h-[1em] shrink-0">
|
|
106
|
+
<path
|
|
107
|
+
fill="currentColor"
|
|
108
|
+
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"
|
|
109
|
+
/>
|
|
110
|
+
</svg>
|
|
111
|
+
GitHub
|
|
112
|
+
</a>
|
|
113
|
+
<span class="text-muted">/</span>
|
|
114
|
+
</>
|
|
115
|
+
)}
|
|
116
|
+
{/* @Takazudo link — present in the original Astro index.astro (refs #1453).
|
|
117
|
+
The deploy was missing this trailing item, leaving a dangling "/" separator. */}
|
|
118
|
+
<a
|
|
119
|
+
href="https://x.com/Takazudo"
|
|
120
|
+
class="text-fg underline hover:text-accent"
|
|
121
|
+
target="_blank"
|
|
122
|
+
rel="noopener noreferrer"
|
|
123
|
+
>
|
|
124
|
+
@Takazudo
|
|
125
|
+
</a>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
|
|
131
|
+
{/* Sitemap grid — restored to the original SiteTreeNav island (refs #1453).
|
|
132
|
+
The Astro reference used <Island when="idle"><SiteTreeNav ...></Island>.
|
|
133
|
+
DocsSitemap (vertical <details> list) was incorrect; SiteTreeNav gives
|
|
134
|
+
the responsive multi-column grid the reference renders. */}
|
|
135
|
+
{Island({
|
|
136
|
+
when: "idle",
|
|
137
|
+
children: (
|
|
138
|
+
<SiteTreeNav
|
|
139
|
+
tree={groupedTree}
|
|
140
|
+
categoryOrder={categoryOrder}
|
|
141
|
+
categoryIgnore={["inbox", "develop"]}
|
|
142
|
+
/>
|
|
143
|
+
),
|
|
144
|
+
}) as unknown as VNode}
|
|
145
|
+
|
|
146
|
+
{settings.docTags && tagCount > 0 && (
|
|
147
|
+
<section class="mt-vsp-xl">
|
|
148
|
+
<h2 class="text-title font-bold mb-vsp-md">
|
|
149
|
+
{t("doc.allTags", locale)}
|
|
150
|
+
</h2>
|
|
151
|
+
<a href={withBase("/docs/tags")} class="text-accent underline hover:text-accent-hover">
|
|
152
|
+
{t("doc.allTags", locale)}
|
|
153
|
+
</a>
|
|
154
|
+
</section>
|
|
155
|
+
)}
|
|
156
|
+
</DocLayoutWithDefaults>
|
|
157
|
+
);
|
|
158
|
+
}
|