@takazudo/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/bin/gen-z-index.mjs +164 -0
- package/bin/tags-audit-runner.ts +126 -0
- package/bin/tags-audit.mjs +64 -0
- package/dist/ai-chat-modal/index.d.ts +8 -0
- package/dist/ai-chat-modal/index.js +243 -0
- package/dist/body-foot-util/body-foot-util-area.d.ts +4 -8
- package/dist/body-foot-util/edit-link.d.ts +4 -8
- package/dist/body-foot-util/index.d.ts +4 -3
- package/dist/breadcrumb/breadcrumb.d.ts +5 -9
- package/dist/breadcrumb/find-path.d.ts +2 -5
- package/dist/breadcrumb/index.d.ts +4 -4
- package/dist/breadcrumb/types.d.ts +3 -5
- package/dist/category-nav/index.d.ts +86 -0
- package/dist/category-nav/index.js +44 -0
- package/dist/category-tree-nav/index.d.ts +65 -0
- package/dist/category-tree-nav/index.js +24 -0
- package/dist/code-group/index.d.ts +10 -0
- package/dist/code-group/index.js +37 -0
- package/dist/code-syntax/code-block-enhancer-script.d.ts +1 -3
- package/dist/code-syntax/code-block-enhancer.d.ts +3 -6
- package/dist/code-syntax/index.d.ts +9 -8
- package/dist/code-syntax/mermaid-init-script.d.ts +3 -5
- package/dist/code-syntax/mermaid-init.d.ts +4 -7
- package/dist/code-syntax/tabs-init-script.d.ts +1 -3
- package/dist/code-syntax/tabs-init.d.ts +3 -6
- package/dist/code-syntax/tabs.d.ts +4 -7
- package/dist/color-scheme-utils.d.ts +125 -0
- package/dist/color-scheme-utils.js +151 -0
- package/dist/compose-meta-title/index.d.ts +7 -0
- package/dist/compose-meta-title/index.js +10 -0
- package/dist/content/component-map.d.ts +13 -17
- package/dist/content/content-blockquote.d.ts +3 -6
- package/dist/content/content-code.d.ts +3 -6
- package/dist/content/content-code.js +1 -1
- package/dist/content/content-link.d.ts +3 -6
- package/dist/content/content-link.js +1 -1
- package/dist/content/content-ol.d.ts +3 -6
- package/dist/content/content-paragraph.d.ts +3 -6
- package/dist/content/content-strong.d.ts +3 -6
- package/dist/content/content-table.d.ts +3 -6
- package/dist/content/content-ul.d.ts +3 -6
- package/dist/content/heading-h2.d.ts +3 -6
- package/dist/content/heading-h3.d.ts +3 -6
- package/dist/content/heading-h4.d.ts +3 -6
- package/dist/content/index.d.ts +29 -13
- package/dist/content-admonition/index.d.ts +15 -0
- package/dist/content-admonition/index.js +14 -0
- package/dist/design-token-panel-bootstrap.d.ts +38 -0
- package/dist/design-token-panel-bootstrap.js +29 -0
- package/dist/desktop-sidebar-toggle-island/index.d.ts +5 -0
- package/dist/desktop-sidebar-toggle-island/index.js +62 -0
- package/dist/details/details.d.ts +3 -7
- package/dist/details/index.d.ts +2 -2
- package/dist/doc-body-end/index.d.ts +21 -0
- package/dist/doc-body-end/index.js +15 -0
- package/dist/doc-content-header/index.d.ts +69 -0
- package/dist/doc-content-header/index.js +49 -0
- package/dist/doc-history/index.d.ts +10 -0
- package/dist/doc-history/index.js +407 -0
- package/dist/doc-history-area/index.d.ts +84 -0
- package/dist/doc-history-area/index.js +76 -0
- package/dist/doc-metainfo-area/index.d.ts +46 -0
- package/dist/doc-metainfo-area/index.js +41 -0
- package/dist/doc-page-props/index.d.ts +93 -0
- package/dist/doc-page-props/index.js +0 -0
- package/dist/doc-page-renderer/index.d.ts +128 -0
- package/dist/doc-page-renderer/index.js +103 -0
- package/dist/doc-page-shell/index.d.ts +136 -0
- package/dist/doc-page-shell/index.js +127 -0
- package/dist/doc-pager/index.d.ts +25 -0
- package/dist/doc-pager/index.js +41 -0
- package/dist/doc-route-entries/index.d.ts +125 -0
- package/dist/doc-route-entries/index.js +76 -0
- package/dist/doc-route-paths/index.d.ts +54 -0
- package/dist/doc-route-paths/index.js +61 -0
- package/dist/doc-tags-area/index.d.ts +38 -0
- package/dist/doc-tags-area/index.js +30 -0
- package/dist/doclayout/anchors.d.ts +7 -9
- package/dist/doclayout/doc-layout-with-defaults.d.ts +16 -12
- package/dist/doclayout/doc-layout.d.ts +5 -9
- package/dist/doclayout/index.d.ts +6 -6
- package/dist/extract-headings/index.d.ts +43 -0
- package/dist/extract-headings/index.js +111 -0
- package/dist/factory-context/index.d.ts +80 -0
- package/dist/factory-context/index.js +0 -0
- package/dist/features.css +882 -0
- package/dist/footer/footer.d.ts +4 -8
- package/dist/footer/index.d.ts +13 -3
- package/dist/footer/types.d.ts +4 -6
- package/dist/footer-with-defaults/index.d.ts +63 -0
- package/dist/footer-with-defaults/index.js +128 -0
- package/dist/frontmatter-preview-data/index.d.ts +26 -0
- package/dist/frontmatter-preview-data/index.js +23 -0
- package/dist/github-helpers/index.d.ts +17 -0
- package/dist/github-helpers/index.js +16 -0
- package/dist/head/doc-head.d.ts +3 -6
- package/dist/head/index.d.ts +9 -5
- package/dist/head/og-tags.d.ts +4 -7
- package/dist/head/twitter-card.d.ts +3 -6
- package/dist/head/types.d.ts +1 -3
- package/dist/head-with-defaults/index.d.ts +49 -0
- package/dist/head-with-defaults/index.js +62 -0
- package/dist/header/header.d.ts +6 -10
- package/dist/header/index.d.ts +16 -6
- package/dist/header/nav-active.d.ts +5 -7
- package/dist/header/nav-overflow-script.d.ts +1 -3
- package/dist/header/right-items.d.ts +3 -6
- package/dist/header/types.d.ts +10 -12
- package/dist/header-with-defaults/index.d.ts +77 -0
- package/dist/header-with-defaults/index.js +163 -0
- package/dist/html-preview-wrapper/dedent.d.ts +1 -3
- package/dist/html-preview-wrapper/highlighted-code.d.ts +3 -7
- package/dist/html-preview-wrapper/html-preview-wrapper.d.ts +6 -10
- package/dist/html-preview-wrapper/html-preview.d.ts +5 -9
- package/dist/html-preview-wrapper/index.d.ts +8 -5
- package/dist/html-preview-wrapper/preflight.d.ts +1 -3
- package/dist/html-preview-wrapper/preview-base.d.ts +4 -8
- package/dist/i18n-version/index.d.ts +7 -5
- package/dist/i18n-version/language-switcher.d.ts +5 -8
- package/dist/i18n-version/types.d.ts +3 -5
- package/dist/i18n-version/version-banner.d.ts +4 -8
- package/dist/i18n-version/version-switcher.d.ts +7 -10
- package/dist/icons/index.d.ts +9 -13
- package/dist/image-enlarge/index.d.ts +13 -0
- package/dist/image-enlarge/index.js +176 -0
- package/dist/index.d.ts +26 -2
- package/dist/inline-version-switcher/index.d.ts +31 -0
- package/dist/inline-version-switcher/index.js +44 -0
- package/dist/integrations/claude-resources/escape-for-mdx.d.ts +1 -3
- package/dist/integrations/claude-resources/generate.d.ts +2 -4
- package/dist/integrations/claude-resources/index.d.ts +7 -10
- package/dist/integrations/doc-history/index.d.ts +21 -24
- package/dist/integrations/doc-history/pre-build.d.ts +7 -9
- package/dist/integrations/llms-txt/dev-middleware.d.ts +7 -11
- package/dist/integrations/llms-txt/emit.d.ts +2 -7
- package/dist/integrations/llms-txt/generate.d.ts +3 -8
- package/dist/integrations/llms-txt/index.d.ts +33 -8
- package/dist/integrations/llms-txt/load.d.ts +3 -7
- package/dist/integrations/llms-txt/strip.d.ts +2 -6
- package/dist/integrations/llms-txt/types.d.ts +9 -13
- package/dist/integrations/search-index/build-emitter.d.ts +4 -7
- package/dist/integrations/search-index/collect.d.ts +2 -5
- package/dist/integrations/search-index/dev-middleware.d.ts +5 -8
- package/dist/integrations/search-index/index.d.ts +7 -5
- package/dist/integrations/search-index/types.d.ts +5 -7
- package/dist/island-types/index.d.ts +44 -0
- package/dist/island-types/index.js +12 -0
- package/dist/locale-merge/index.d.ts +114 -0
- package/dist/locale-merge/index.js +27 -0
- package/dist/math-block/index.d.ts +18 -0
- package/dist/math-block/index.js +29 -0
- package/dist/md-utils/index.d.ts +6 -8
- package/dist/md-utils/index.js +2 -1
- package/dist/mdx-components/index.d.ts +46 -0
- package/dist/mdx-components/index.js +161 -0
- package/dist/mermaid-enlarge/index.d.ts +11 -0
- package/dist/mermaid-enlarge/index.js +290 -0
- package/dist/metainfo/doc-metainfo.d.ts +5 -9
- package/dist/metainfo/doc-tags.d.ts +7 -11
- package/dist/metainfo/frontmatter-preview.d.ts +8 -12
- package/dist/metainfo/index.d.ts +6 -4
- package/dist/nav-data-prep/index.d.ts +72 -0
- package/dist/nav-data-prep/index.js +34 -0
- package/dist/nav-indexing/category-nav.d.ts +4 -8
- package/dist/nav-indexing/category-tree-nav.d.ts +4 -8
- package/dist/nav-indexing/doc-card-grid.d.ts +4 -8
- package/dist/nav-indexing/docs-sitemap.d.ts +4 -8
- package/dist/nav-indexing/index.d.ts +37 -10
- package/dist/nav-indexing/nav-card-grid.d.ts +4 -8
- package/dist/nav-indexing/site-tree-nav-demo.d.ts +4 -8
- package/dist/nav-indexing/tag-nav.d.ts +6 -10
- package/dist/nav-indexing/types.d.ts +6 -8
- package/dist/nav-indexing/versions-page-content.d.ts +4 -8
- package/dist/nav-scope/index.d.ts +41 -0
- package/dist/nav-scope/index.js +41 -0
- package/dist/nav-source-cache/index.d.ts +13 -0
- package/dist/nav-source-cache/index.js +28 -0
- package/dist/nav-source-docs/index.d.ts +169 -0
- package/dist/nav-source-docs/index.js +123 -0
- package/dist/page-loading/index.d.ts +1 -2
- package/dist/page-loading/page-loading-overlay.d.ts +4 -8
- package/dist/plugins/claude-resources.d.ts +3 -0
- package/dist/plugins/claude-resources.js +27 -0
- package/dist/plugins/connect-adapter.d.ts +31 -0
- package/dist/plugins/connect-adapter.js +78 -0
- package/dist/plugins/doc-history.d.ts +3 -0
- package/dist/plugins/doc-history.js +54 -0
- package/dist/plugins/llms-txt.d.ts +3 -0
- package/dist/plugins/llms-txt.js +48 -0
- package/dist/plugins/plugin-utils.d.ts +17 -0
- package/dist/plugins/plugin-utils.js +11 -0
- package/dist/plugins/search-index.d.ts +3 -0
- package/dist/plugins/search-index.js +24 -0
- package/dist/preset.d.ts +152 -0
- package/dist/preset.js +169 -0
- package/dist/render-markdown/index.d.ts +5 -0
- package/dist/render-markdown/index.js +115 -0
- package/dist/robots.d.ts +36 -0
- package/dist/robots.js +17 -0
- package/dist/route-enumerators/index.d.ts +204 -0
- package/dist/route-enumerators/index.js +156 -0
- package/dist/safelist.css +1 -1
- package/dist/search-widget/index.d.ts +38 -0
- package/dist/search-widget/index.js +169 -0
- package/dist/search-widget-script/index.d.ts +18 -0
- package/dist/search-widget-script/index.js +465 -0
- package/dist/settings.d.ts +255 -0
- package/dist/settings.js +0 -0
- package/dist/sidebar/index.d.ts +21 -3
- package/dist/sidebar/sidebar.d.ts +5 -9
- package/dist/sidebar/types.d.ts +4 -6
- package/dist/sidebar-prepaint/index.d.ts +21 -0
- package/dist/sidebar-prepaint/index.js +23 -0
- package/dist/sidebar-resizer/index.d.ts +2 -6
- package/dist/sidebar-resizer/sidebar-resizer-init.d.ts +6 -10
- package/dist/sidebar-toggle-island/index.d.ts +13 -0
- package/dist/sidebar-toggle-island/index.js +122 -0
- package/dist/sidebar-tree/build-tree.d.ts +4 -8
- package/dist/sidebar-tree/category-meta.d.ts +3 -6
- package/dist/sidebar-tree/index.d.ts +18 -3
- package/dist/sidebar-tree/types.d.ts +6 -8
- package/dist/sidebar-tree-island/index.d.ts +13 -0
- package/dist/sidebar-tree-island/index.js +454 -0
- package/dist/sidebar-utils/index.d.ts +64 -0
- package/dist/sidebar-utils/index.js +88 -0
- package/dist/sidebar-with-defaults/index.d.ts +38 -0
- package/dist/sidebar-with-defaults/index.js +45 -0
- package/dist/site-tree-nav/index.d.ts +71 -0
- package/dist/site-tree-nav/index.js +36 -0
- package/dist/site-tree-nav-island/index.d.ts +11 -0
- package/dist/site-tree-nav-island/index.js +176 -0
- package/dist/slug/index.d.ts +4 -0
- package/dist/slug/index.js +19 -0
- package/dist/smart-break/index.d.ts +55 -0
- package/dist/{toc/smart-break.js → smart-break/index.js} +30 -3
- package/dist/tab-item/index.d.ts +2 -2
- package/dist/tab-item/tab-item.d.ts +6 -7
- package/dist/tag-helpers/index.d.ts +40 -0
- package/dist/tag-helpers/index.js +54 -0
- package/dist/tag-pages/index.d.ts +114 -0
- package/dist/tag-pages/index.js +146 -0
- package/dist/tags-audit.d.ts +107 -0
- package/dist/tags-audit.js +321 -0
- package/dist/theme/color-scheme-provider.d.ts +4 -8
- package/dist/theme/color-tweak-export-modal.d.ts +4 -7
- package/dist/theme/design-token-serde.d.ts +14 -17
- package/dist/theme/design-token-types.d.ts +4 -6
- package/dist/theme/iframe-bridge.d.ts +12 -14
- package/dist/theme/index.d.ts +7 -9
- package/dist/theme/theme-toggle.d.ts +3 -8
- package/dist/theme-toggle/color-scheme-sync.d.ts +5 -7
- package/dist/theme-toggle/index.d.ts +4 -8
- package/dist/toc/cx.d.ts +2 -3
- package/dist/toc/index.d.ts +8 -6
- package/dist/toc/mobile-toc.d.ts +5 -9
- package/dist/toc/mobile-toc.js +1 -1
- package/dist/toc/toc-title.d.ts +1 -3
- package/dist/toc/toc.d.ts +5 -9
- package/dist/toc/toc.js +1 -1
- package/dist/toc/types.d.ts +1 -3
- package/dist/toc/use-active-heading.d.ts +4 -7
- package/dist/transitions/index.d.ts +1 -1
- package/dist/transitions/page-events.d.ts +4 -6
- package/dist/tree-nav-shared/index.d.ts +22 -0
- package/dist/tree-nav-shared/index.js +66 -0
- package/dist/url-helpers/index.d.ts +37 -0
- package/dist/url-helpers/index.js +106 -0
- package/dist/url-normalizer/index.d.ts +39 -1
- package/dist/url-normalizer/normalize.d.ts +3 -5
- package/dist/use-modal-dialog/index.d.ts +70 -0
- package/dist/use-modal-dialog/index.js +73 -0
- package/dist/versions-page/index.d.ts +55 -0
- package/dist/versions-page/index.js +73 -0
- package/package.json +290 -10
- package/dist/toc/smart-break.d.ts +0 -27
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Frontmatter fields the builder reads off of each entry's `data` object.
|
|
10
10
|
* Callers are free to extend this; unrecognised fields are ignored.
|
|
11
11
|
*/
|
|
12
|
-
interface SidebarFrontmatter {
|
|
12
|
+
export interface SidebarFrontmatter {
|
|
13
13
|
title: string;
|
|
14
14
|
description?: string;
|
|
15
15
|
sidebar_position?: number;
|
|
@@ -47,7 +47,7 @@ interface SidebarFrontmatter {
|
|
|
47
47
|
* structural superset of both Astro's `CollectionEntry` and zfb's
|
|
48
48
|
* `CollectionEntry<T>` so callers can pass either through unchanged.
|
|
49
49
|
*/
|
|
50
|
-
interface CollectionEntryLike<T extends SidebarFrontmatter = SidebarFrontmatter> {
|
|
50
|
+
export interface CollectionEntryLike<T extends SidebarFrontmatter = SidebarFrontmatter> {
|
|
51
51
|
/**
|
|
52
52
|
* Stable identifier. For Astro entries this is the file path without the
|
|
53
53
|
* extension (e.g. `getting-started/index`). For zfb entries the project
|
|
@@ -69,7 +69,7 @@ interface CollectionEntryLike<T extends SidebarFrontmatter = SidebarFrontmatter>
|
|
|
69
69
|
/**
|
|
70
70
|
* Metadata supplied by a directory's `_category_.json` file.
|
|
71
71
|
*/
|
|
72
|
-
interface CategoryMeta {
|
|
72
|
+
export interface CategoryMeta {
|
|
73
73
|
label?: string;
|
|
74
74
|
position?: number;
|
|
75
75
|
description?: string;
|
|
@@ -87,7 +87,7 @@ interface CategoryMeta {
|
|
|
87
87
|
* because downstream consumers (sidebar config layer, breadcrumb builder)
|
|
88
88
|
* need them. They are all optional from a caller's perspective.
|
|
89
89
|
*/
|
|
90
|
-
interface SidebarNode {
|
|
90
|
+
export interface SidebarNode {
|
|
91
91
|
type: "doc" | "category";
|
|
92
92
|
/** Path-style slug, e.g. `getting-started/introduction`. */
|
|
93
93
|
id: string;
|
|
@@ -106,8 +106,8 @@ interface SidebarNode {
|
|
|
106
106
|
* for non-default locales and `/docs/<slug>/` otherwise — but most projects
|
|
107
107
|
* will inject their own to honour `base`, `trailingSlash`, etc.
|
|
108
108
|
*/
|
|
109
|
-
type BuildHref = (slug: string, locale: string) => string;
|
|
110
|
-
interface BuildSidebarTreeOptions {
|
|
109
|
+
export type BuildHref = (slug: string, locale: string) => string;
|
|
110
|
+
export interface BuildSidebarTreeOptions {
|
|
111
111
|
/**
|
|
112
112
|
* Map keyed by slash-joined directory path → category meta. Typically
|
|
113
113
|
* produced by {@link CategoryMetaLoader}.
|
|
@@ -130,5 +130,3 @@ interface BuildSidebarTreeOptions {
|
|
|
130
130
|
*/
|
|
131
131
|
isNavVisible?: (entry: CollectionEntryLike<SidebarFrontmatter>) => boolean;
|
|
132
132
|
}
|
|
133
|
-
|
|
134
|
-
export type { BuildHref, BuildSidebarTreeOptions, CategoryMeta, CollectionEntryLike, SidebarFrontmatter, SidebarNode };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SidebarNavNode, SidebarRootMenuItem, SidebarLocaleLink } from "../sidebar/types.js";
|
|
2
|
+
export interface SidebarTreeProps {
|
|
3
|
+
nodes: SidebarNavNode[];
|
|
4
|
+
currentSlug?: string;
|
|
5
|
+
rootMenuItems?: SidebarRootMenuItem[];
|
|
6
|
+
backToMenuLabel?: string;
|
|
7
|
+
localeLinks?: SidebarLocaleLink[];
|
|
8
|
+
themeDefaultMode?: "light" | "dark";
|
|
9
|
+
}
|
|
10
|
+
export declare function SidebarTree({ nodes, currentSlug, rootMenuItems, backToMenuLabel, localeLinks, themeDefaultMode }: SidebarTreeProps): import("preact").JSX.Element;
|
|
11
|
+
export declare namespace SidebarTree {
|
|
12
|
+
var displayName: string;
|
|
13
|
+
}
|
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
|
|
3
|
+
import { useState, useCallback, useEffect, useMemo, useRef } from "preact/hooks";
|
|
4
|
+
import { memo } from "preact/compat";
|
|
5
|
+
import { INDENT, BASE_PAD, connectorLeft, ConnectorLines, CategoryLinkIcon } from "../tree-nav-shared/index.js";
|
|
6
|
+
import { ChevronRight, ChevronLeft, Search } from "../icons/index.js";
|
|
7
|
+
import { ThemeToggle } from "../theme-toggle/index.js";
|
|
8
|
+
import { smartBreakToHtml } from "../smart-break/index.js";
|
|
9
|
+
import { AFTER_NAVIGATE_EVENT, BEFORE_NAVIGATE_EVENT } from "../transitions/index.js";
|
|
10
|
+
function ToggleChevron({ isExpanded, className }) {
|
|
11
|
+
return /* @__PURE__ */ jsx(
|
|
12
|
+
ChevronRight,
|
|
13
|
+
{
|
|
14
|
+
className: `h-[0.625rem] w-[0.625rem] shrink-0 transition-transform duration-150 ${isExpanded ? "rotate-90" : ""} ${className ?? ""}`
|
|
15
|
+
}
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
const STORAGE_KEY = "zd-sidebar-open";
|
|
19
|
+
function padLeft(depth, forCategory) {
|
|
20
|
+
if (depth === 0) return `calc(${BASE_PAD} + ${forCategory ? "0.15rem" : "0rem"})`;
|
|
21
|
+
return `calc(${depth} * ${INDENT} + 1.25rem + 5px)`;
|
|
22
|
+
}
|
|
23
|
+
function getOpenSet() {
|
|
24
|
+
try {
|
|
25
|
+
const raw = sessionStorage.getItem(STORAGE_KEY);
|
|
26
|
+
if (!raw) return /* @__PURE__ */ new Set();
|
|
27
|
+
const parsed = JSON.parse(raw);
|
|
28
|
+
return Array.isArray(parsed) ? new Set(parsed.filter((v) => typeof v === "string")) : /* @__PURE__ */ new Set();
|
|
29
|
+
} catch {
|
|
30
|
+
return /* @__PURE__ */ new Set();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function saveOpenSet(set) {
|
|
34
|
+
try {
|
|
35
|
+
sessionStorage.setItem(STORAGE_KEY, JSON.stringify([...set]));
|
|
36
|
+
} catch {
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function normalizePath(p) {
|
|
40
|
+
return p.replace(/\/$/, "") || "/";
|
|
41
|
+
}
|
|
42
|
+
function findActiveSlug(nodes, pathname) {
|
|
43
|
+
for (const node of nodes) {
|
|
44
|
+
if (node.href && normalizePath(node.href) === pathname) return node.slug;
|
|
45
|
+
const found = findActiveSlug(node.children, pathname);
|
|
46
|
+
if (found !== void 0) return found;
|
|
47
|
+
}
|
|
48
|
+
return void 0;
|
|
49
|
+
}
|
|
50
|
+
function deriveActiveSlugFromUrl(nodes) {
|
|
51
|
+
if (typeof window === "undefined") return void 0;
|
|
52
|
+
const pathname = normalizePath(window.location.pathname);
|
|
53
|
+
return findActiveSlug(nodes, pathname);
|
|
54
|
+
}
|
|
55
|
+
function useActiveSlug(nodes, initial) {
|
|
56
|
+
const [slug, setSlug] = useState(
|
|
57
|
+
() => initial !== void 0 ? initial : deriveActiveSlugFromUrl(nodes)
|
|
58
|
+
);
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
const update = () => {
|
|
61
|
+
const found = deriveActiveSlugFromUrl(nodes);
|
|
62
|
+
if (found !== void 0) setSlug(found);
|
|
63
|
+
};
|
|
64
|
+
update();
|
|
65
|
+
document.addEventListener(AFTER_NAVIGATE_EVENT, update);
|
|
66
|
+
return () => document.removeEventListener(AFTER_NAVIGATE_EVENT, update);
|
|
67
|
+
}, [nodes]);
|
|
68
|
+
return slug;
|
|
69
|
+
}
|
|
70
|
+
function useSidebarScrollPreserve() {
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
let savedScrollTop = 0;
|
|
73
|
+
let restoreTimer;
|
|
74
|
+
const onBefore = () => {
|
|
75
|
+
if (restoreTimer !== void 0) {
|
|
76
|
+
clearTimeout(restoreTimer);
|
|
77
|
+
restoreTimer = void 0;
|
|
78
|
+
}
|
|
79
|
+
const aside = document.querySelector("#desktop-sidebar");
|
|
80
|
+
if (aside) savedScrollTop = aside.scrollTop;
|
|
81
|
+
};
|
|
82
|
+
const onAfter = () => {
|
|
83
|
+
const aside = document.querySelector("#desktop-sidebar");
|
|
84
|
+
if (!aside) return;
|
|
85
|
+
restoreTimer = setTimeout(() => {
|
|
86
|
+
restoreTimer = void 0;
|
|
87
|
+
aside.scrollTop = savedScrollTop;
|
|
88
|
+
}, 50);
|
|
89
|
+
};
|
|
90
|
+
document.addEventListener(BEFORE_NAVIGATE_EVENT, onBefore);
|
|
91
|
+
document.addEventListener(AFTER_NAVIGATE_EVENT, onAfter);
|
|
92
|
+
return () => {
|
|
93
|
+
document.removeEventListener(BEFORE_NAVIGATE_EVENT, onBefore);
|
|
94
|
+
document.removeEventListener(AFTER_NAVIGATE_EVENT, onAfter);
|
|
95
|
+
if (restoreTimer !== void 0) clearTimeout(restoreTimer);
|
|
96
|
+
};
|
|
97
|
+
}, []);
|
|
98
|
+
}
|
|
99
|
+
function filterTree(nodes, query) {
|
|
100
|
+
return nodes.reduce((acc, node) => {
|
|
101
|
+
const matchesLabel = node.label.toLowerCase().includes(query.toLowerCase());
|
|
102
|
+
const filteredChildren = node.children.length > 0 ? filterTree(node.children, query) : [];
|
|
103
|
+
if (matchesLabel || filteredChildren.length > 0) {
|
|
104
|
+
acc.push({
|
|
105
|
+
...node,
|
|
106
|
+
children: matchesLabel ? node.children : filteredChildren
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return acc;
|
|
110
|
+
}, []);
|
|
111
|
+
}
|
|
112
|
+
function RootMenuItemEntry({ item }) {
|
|
113
|
+
const [expanded, setExpanded] = useState(false);
|
|
114
|
+
const hasChildren = item.children && item.children.length > 0;
|
|
115
|
+
return /* @__PURE__ */ jsxs("div", { className: "border-t border-muted", children: [
|
|
116
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
117
|
+
/* @__PURE__ */ jsxs(
|
|
118
|
+
"a",
|
|
119
|
+
{
|
|
120
|
+
href: item.href,
|
|
121
|
+
className: "flex flex-1 items-center gap-hsp-xs px-hsp-sm py-vsp-xs text-small font-semibold text-fg hover:text-accent hover:underline break-words",
|
|
122
|
+
children: [
|
|
123
|
+
/* @__PURE__ */ jsx(CategoryLinkIcon, { className: "w-[14px]" }),
|
|
124
|
+
/* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: smartBreakToHtml(item.label) } })
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
),
|
|
128
|
+
hasChildren && /* @__PURE__ */ jsx(
|
|
129
|
+
"button",
|
|
130
|
+
{
|
|
131
|
+
type: "button",
|
|
132
|
+
onClick: () => setExpanded((prev) => !prev),
|
|
133
|
+
className: "flex items-center justify-center px-hsp-sm py-vsp-xs text-muted hover:text-fg",
|
|
134
|
+
"aria-expanded": expanded,
|
|
135
|
+
"aria-label": expanded ? `Collapse ${item.label}` : `Expand ${item.label}`,
|
|
136
|
+
children: /* @__PURE__ */ jsx(ToggleChevron, { isExpanded: expanded, className: "text-muted" })
|
|
137
|
+
}
|
|
138
|
+
)
|
|
139
|
+
] }),
|
|
140
|
+
hasChildren && expanded && /* @__PURE__ */ jsx("div", { className: "pb-vsp-xs", children: item.children.map((child) => /* @__PURE__ */ jsx(
|
|
141
|
+
"a",
|
|
142
|
+
{
|
|
143
|
+
href: child.href,
|
|
144
|
+
className: "block pl-hsp-xl pr-hsp-sm py-vsp-2xs text-small text-muted hover:text-accent hover:underline break-words",
|
|
145
|
+
children: /* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: smartBreakToHtml(child.label) } })
|
|
146
|
+
},
|
|
147
|
+
child.href
|
|
148
|
+
)) })
|
|
149
|
+
] });
|
|
150
|
+
}
|
|
151
|
+
function SidebarFooter({ links, themeDefaultMode }) {
|
|
152
|
+
if (!links && !themeDefaultMode) return null;
|
|
153
|
+
return (
|
|
154
|
+
// pb-[50vh] provides scroll room so the footer doesn't sit at the very bottom of the viewport
|
|
155
|
+
/* @__PURE__ */ jsxs("div", { className: "lg:hidden flex items-center gap-hsp-md border-t border-muted px-hsp-sm py-vsp-xs pb-[50vh] text-small", children: [
|
|
156
|
+
themeDefaultMode && /* @__PURE__ */ jsx(ThemeToggle, { defaultMode: themeDefaultMode }),
|
|
157
|
+
links && links.map((link, i) => /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-hsp-xs", children: [
|
|
158
|
+
i > 0 && /* @__PURE__ */ jsx("span", { className: "text-muted", children: "/" }),
|
|
159
|
+
link.active ? /* @__PURE__ */ jsx("span", { "aria-current": "true", className: "font-medium text-fg", children: link.label }) : /* @__PURE__ */ jsx("a", { href: link.href, lang: link.code, className: "text-muted hover:text-fg", children: link.label })
|
|
160
|
+
] }, link.href))
|
|
161
|
+
] })
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
function SidebarTree({ nodes, currentSlug, rootMenuItems, backToMenuLabel, localeLinks, themeDefaultMode }) {
|
|
165
|
+
const activeSlug = useActiveSlug(nodes, currentSlug);
|
|
166
|
+
useSidebarScrollPreserve();
|
|
167
|
+
const [query, setQuery] = useState("");
|
|
168
|
+
const [showingRootMenu, setShowingRootMenu] = useState(false);
|
|
169
|
+
const filterRef = useRef(null);
|
|
170
|
+
const [filterPlaceholder, setFilterPlaceholder] = useState("Filter...");
|
|
171
|
+
useEffect(() => {
|
|
172
|
+
const platform = navigator.userAgentData?.platform ?? navigator.platform;
|
|
173
|
+
const isMac = /mac/i.test(platform);
|
|
174
|
+
setFilterPlaceholder(isMac ? "Filter... (\u2318 + /)" : "Filter... (Ctrl + /)");
|
|
175
|
+
}, []);
|
|
176
|
+
useEffect(() => {
|
|
177
|
+
function handleKeyDown(e) {
|
|
178
|
+
if (e.isComposing) return;
|
|
179
|
+
if (e.key === "/" && (e.metaKey || e.ctrlKey)) {
|
|
180
|
+
const el = filterRef.current;
|
|
181
|
+
if (!el || el.offsetParent === null) return;
|
|
182
|
+
e.preventDefault();
|
|
183
|
+
el.focus();
|
|
184
|
+
el.select();
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
188
|
+
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
189
|
+
}, []);
|
|
190
|
+
const filteredNodes = useMemo(
|
|
191
|
+
() => query ? filterTree(nodes, query) : nodes,
|
|
192
|
+
[nodes, query]
|
|
193
|
+
);
|
|
194
|
+
const footer = useMemo(
|
|
195
|
+
() => localeLinks || themeDefaultMode ? /* @__PURE__ */ jsx(SidebarFooter, { links: localeLinks, themeDefaultMode }) : null,
|
|
196
|
+
[localeLinks, themeDefaultMode]
|
|
197
|
+
);
|
|
198
|
+
if (showingRootMenu && rootMenuItems) {
|
|
199
|
+
return /* @__PURE__ */ jsxs("nav", { children: [
|
|
200
|
+
/* @__PURE__ */ jsxs(
|
|
201
|
+
"button",
|
|
202
|
+
{
|
|
203
|
+
type: "button",
|
|
204
|
+
onClick: () => setShowingRootMenu(false),
|
|
205
|
+
className: "flex w-full items-center gap-hsp-xs px-hsp-sm py-vsp-xs text-left text-small text-muted hover:text-fg border-b border-muted",
|
|
206
|
+
children: [
|
|
207
|
+
/* @__PURE__ */ jsx(ChevronRight, { className: "h-icon-sm w-icon-sm shrink-0" }),
|
|
208
|
+
backToMenuLabel ?? "Back to main menu"
|
|
209
|
+
]
|
|
210
|
+
}
|
|
211
|
+
),
|
|
212
|
+
rootMenuItems.map((item) => /* @__PURE__ */ jsx(RootMenuItemEntry, { item }, item.href)),
|
|
213
|
+
footer
|
|
214
|
+
] });
|
|
215
|
+
}
|
|
216
|
+
if (activeSlug === void 0 && rootMenuItems) {
|
|
217
|
+
return /* @__PURE__ */ jsxs("nav", { children: [
|
|
218
|
+
rootMenuItems.map((item) => /* @__PURE__ */ jsx(RootMenuItemEntry, { item }, item.href)),
|
|
219
|
+
footer
|
|
220
|
+
] });
|
|
221
|
+
}
|
|
222
|
+
return /* @__PURE__ */ jsxs("nav", { children: [
|
|
223
|
+
rootMenuItems && /* @__PURE__ */ jsxs(
|
|
224
|
+
"button",
|
|
225
|
+
{
|
|
226
|
+
type: "button",
|
|
227
|
+
onClick: () => setShowingRootMenu(true),
|
|
228
|
+
className: "lg:hidden flex w-full items-center gap-hsp-xs px-hsp-sm py-vsp-xs text-left text-small text-muted hover:text-fg border-b border-muted",
|
|
229
|
+
children: [
|
|
230
|
+
/* @__PURE__ */ jsx(ChevronLeft, { className: "h-icon-sm w-icon-sm shrink-0" }),
|
|
231
|
+
backToMenuLabel ?? "Back to main menu"
|
|
232
|
+
]
|
|
233
|
+
}
|
|
234
|
+
),
|
|
235
|
+
/* @__PURE__ */ jsx("div", { className: "px-hsp-sm py-vsp-xs", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-hsp-xs bg-surface rounded px-hsp-sm py-vsp-2xs", children: [
|
|
236
|
+
/* @__PURE__ */ jsx(Search, { className: "h-[14px] w-[14px] text-muted shrink-0" }),
|
|
237
|
+
/* @__PURE__ */ jsx(
|
|
238
|
+
"input",
|
|
239
|
+
{
|
|
240
|
+
ref: filterRef,
|
|
241
|
+
type: "text",
|
|
242
|
+
"aria-label": "Filter navigation",
|
|
243
|
+
placeholder: filterPlaceholder,
|
|
244
|
+
value: query,
|
|
245
|
+
onInput: (e) => setQuery(e.currentTarget.value),
|
|
246
|
+
className: "bg-transparent text-small outline-none w-full text-fg placeholder:text-muted"
|
|
247
|
+
}
|
|
248
|
+
)
|
|
249
|
+
] }) }),
|
|
250
|
+
/* @__PURE__ */ jsx(
|
|
251
|
+
NodeList,
|
|
252
|
+
{
|
|
253
|
+
nodes: filteredNodes,
|
|
254
|
+
currentSlug: activeSlug,
|
|
255
|
+
depth: 0,
|
|
256
|
+
forceOpen: !!query
|
|
257
|
+
}
|
|
258
|
+
),
|
|
259
|
+
footer
|
|
260
|
+
] });
|
|
261
|
+
}
|
|
262
|
+
SidebarTree.displayName = "SidebarTree";
|
|
263
|
+
const NodeList = memo(function NodeList2({
|
|
264
|
+
nodes,
|
|
265
|
+
currentSlug,
|
|
266
|
+
depth,
|
|
267
|
+
forceOpen
|
|
268
|
+
}) {
|
|
269
|
+
return /* @__PURE__ */ jsx(Fragment, { children: nodes.map((node, index) => {
|
|
270
|
+
const isLast = index === nodes.length - 1;
|
|
271
|
+
return node.children.length > 0 ? /* @__PURE__ */ jsx(
|
|
272
|
+
CategoryNode,
|
|
273
|
+
{
|
|
274
|
+
node,
|
|
275
|
+
currentSlug,
|
|
276
|
+
depth,
|
|
277
|
+
isLast,
|
|
278
|
+
forceOpen
|
|
279
|
+
},
|
|
280
|
+
node.slug
|
|
281
|
+
) : /* @__PURE__ */ jsx(
|
|
282
|
+
LeafNode,
|
|
283
|
+
{
|
|
284
|
+
node,
|
|
285
|
+
currentSlug,
|
|
286
|
+
depth,
|
|
287
|
+
isLast
|
|
288
|
+
},
|
|
289
|
+
node.slug
|
|
290
|
+
);
|
|
291
|
+
}) });
|
|
292
|
+
});
|
|
293
|
+
function subtreeContainsSlug(node, slug) {
|
|
294
|
+
if (!slug) return false;
|
|
295
|
+
if (node.slug === slug) return true;
|
|
296
|
+
return node.children.some((child) => subtreeContainsSlug(child, slug));
|
|
297
|
+
}
|
|
298
|
+
const CategoryNode = memo(function CategoryNode2({
|
|
299
|
+
node,
|
|
300
|
+
currentSlug,
|
|
301
|
+
depth,
|
|
302
|
+
isLast,
|
|
303
|
+
forceOpen
|
|
304
|
+
}) {
|
|
305
|
+
const containsCurrent = useMemo(
|
|
306
|
+
() => subtreeContainsSlug(node, currentSlug),
|
|
307
|
+
[node, currentSlug]
|
|
308
|
+
);
|
|
309
|
+
const isActive = node.slug === currentSlug;
|
|
310
|
+
const labelHtml = useMemo(() => smartBreakToHtml(node.label), [node.label]);
|
|
311
|
+
const [open, setOpen] = useState(containsCurrent ? true : !node.collapsed);
|
|
312
|
+
useEffect(() => {
|
|
313
|
+
const stored = getOpenSet();
|
|
314
|
+
if (stored.has(node.slug) && !open) {
|
|
315
|
+
setOpen(true);
|
|
316
|
+
}
|
|
317
|
+
}, []);
|
|
318
|
+
useEffect(() => {
|
|
319
|
+
if (subtreeContainsSlug(node, currentSlug) && !open) {
|
|
320
|
+
setOpen(true);
|
|
321
|
+
const stored = getOpenSet();
|
|
322
|
+
stored.add(node.slug);
|
|
323
|
+
saveOpenSet(stored);
|
|
324
|
+
}
|
|
325
|
+
}, [currentSlug]);
|
|
326
|
+
useEffect(() => {
|
|
327
|
+
if (open) {
|
|
328
|
+
const stored = getOpenSet();
|
|
329
|
+
if (!stored.has(node.slug)) {
|
|
330
|
+
stored.add(node.slug);
|
|
331
|
+
saveOpenSet(stored);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}, [open, node.slug]);
|
|
335
|
+
const toggle = useCallback(() => {
|
|
336
|
+
setOpen((prev) => {
|
|
337
|
+
const next = !prev;
|
|
338
|
+
const stored = getOpenSet();
|
|
339
|
+
if (next) {
|
|
340
|
+
stored.add(node.slug);
|
|
341
|
+
} else {
|
|
342
|
+
stored.delete(node.slug);
|
|
343
|
+
}
|
|
344
|
+
saveOpenSet(stored);
|
|
345
|
+
return next;
|
|
346
|
+
});
|
|
347
|
+
}, [node.slug]);
|
|
348
|
+
const isExpanded = forceOpen || open;
|
|
349
|
+
const paddingLeft = padLeft(depth, true);
|
|
350
|
+
return /* @__PURE__ */ jsxs("div", { className: `${depth === 0 ? "border-t border-muted" : ""} ${depth >= 1 && !isLast ? "relative" : ""}`, children: [
|
|
351
|
+
depth >= 1 && !isLast && isExpanded && /* @__PURE__ */ jsx(
|
|
352
|
+
"div",
|
|
353
|
+
{
|
|
354
|
+
className: "absolute border-l border-solid border-muted z-local-1",
|
|
355
|
+
style: {
|
|
356
|
+
left: connectorLeft(depth),
|
|
357
|
+
top: 0,
|
|
358
|
+
bottom: 0
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
),
|
|
362
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
363
|
+
/* @__PURE__ */ jsx(ConnectorLines, { depth, isLast, topPad: "calc(0.15rem + var(--spacing-vsp-xs))" }),
|
|
364
|
+
node.href ? /* @__PURE__ */ jsxs(
|
|
365
|
+
"div",
|
|
366
|
+
{
|
|
367
|
+
className: `flex w-full items-center text-small font-semibold pt-[0.15rem] ${isActive ? "bg-fg text-bg" : "text-fg"}`,
|
|
368
|
+
children: [
|
|
369
|
+
/* @__PURE__ */ jsxs(
|
|
370
|
+
"a",
|
|
371
|
+
{
|
|
372
|
+
href: node.href,
|
|
373
|
+
"aria-current": isActive ? "page" : void 0,
|
|
374
|
+
className: `flex-1 flex items-start gap-hsp-xs py-vsp-xs hover:underline focus:underline break-words ${isActive ? "text-bg" : "text-fg"}`,
|
|
375
|
+
style: { paddingLeft },
|
|
376
|
+
children: [
|
|
377
|
+
depth === 0 && /* @__PURE__ */ jsx("span", { className: "flex h-[1lh] items-center", children: /* @__PURE__ */ jsx(CategoryLinkIcon, { className: `w-[14px] ${isActive ? "text-bg" : ""}` }) }),
|
|
378
|
+
/* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: labelHtml } })
|
|
379
|
+
]
|
|
380
|
+
}
|
|
381
|
+
),
|
|
382
|
+
/* @__PURE__ */ jsx(
|
|
383
|
+
"button",
|
|
384
|
+
{
|
|
385
|
+
type: "button",
|
|
386
|
+
onClick: toggle,
|
|
387
|
+
className: `aspect-square flex items-center justify-center w-[1.5rem] border-y border-l hover:underline focus:underline ${isActive ? "border-bg/30" : "border-muted"}`,
|
|
388
|
+
"aria-expanded": isExpanded,
|
|
389
|
+
"aria-label": isExpanded ? `Collapse ${node.label}` : `Expand ${node.label}`,
|
|
390
|
+
children: /* @__PURE__ */ jsx(ToggleChevron, { isExpanded, className: isActive ? "text-bg" : "text-muted" })
|
|
391
|
+
}
|
|
392
|
+
)
|
|
393
|
+
]
|
|
394
|
+
}
|
|
395
|
+
) : /* @__PURE__ */ jsxs(
|
|
396
|
+
"button",
|
|
397
|
+
{
|
|
398
|
+
type: "button",
|
|
399
|
+
onClick: toggle,
|
|
400
|
+
className: `flex w-full items-center gap-hsp-md text-left text-small font-semibold py-vsp-xs text-fg hover:underline focus:underline break-words`,
|
|
401
|
+
style: { paddingLeft },
|
|
402
|
+
"aria-expanded": isExpanded,
|
|
403
|
+
"aria-label": isExpanded ? `Collapse ${node.label}` : `Expand ${node.label}`,
|
|
404
|
+
children: [
|
|
405
|
+
/* @__PURE__ */ jsx("span", { className: "aspect-square flex items-center justify-center w-[1.5rem] shrink-0 border border-muted", children: /* @__PURE__ */ jsx(ToggleChevron, { isExpanded, className: "text-muted" }) }),
|
|
406
|
+
/* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: labelHtml } })
|
|
407
|
+
]
|
|
408
|
+
}
|
|
409
|
+
)
|
|
410
|
+
] }),
|
|
411
|
+
isExpanded && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
|
|
412
|
+
NodeList,
|
|
413
|
+
{
|
|
414
|
+
nodes: node.children,
|
|
415
|
+
currentSlug,
|
|
416
|
+
depth: depth + 1,
|
|
417
|
+
forceOpen
|
|
418
|
+
}
|
|
419
|
+
) })
|
|
420
|
+
] });
|
|
421
|
+
});
|
|
422
|
+
const LeafNode = memo(function LeafNode2({
|
|
423
|
+
node,
|
|
424
|
+
currentSlug,
|
|
425
|
+
depth,
|
|
426
|
+
isLast
|
|
427
|
+
}) {
|
|
428
|
+
const labelHtml = useMemo(() => smartBreakToHtml(node.label), [node.label]);
|
|
429
|
+
if (!node.href) return null;
|
|
430
|
+
const isActive = node.slug === currentSlug;
|
|
431
|
+
const isRoot = depth === 0;
|
|
432
|
+
const paddingLeft = padLeft(depth, isRoot);
|
|
433
|
+
const outerClass = isRoot ? "border-t border-muted" : !isRoot && isLast ? "pb-vsp-md" : "";
|
|
434
|
+
const topPad = isRoot ? "calc(var(--spacing-vsp-xs) + 0.15rem)" : "var(--spacing-vsp-2xs)";
|
|
435
|
+
return /* @__PURE__ */ jsx("div", { className: outerClass, children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
436
|
+
/* @__PURE__ */ jsx(ConnectorLines, { depth, isLast, topPad }),
|
|
437
|
+
/* @__PURE__ */ jsxs(
|
|
438
|
+
"a",
|
|
439
|
+
{
|
|
440
|
+
href: node.href,
|
|
441
|
+
"aria-current": isActive ? "page" : void 0,
|
|
442
|
+
className: isRoot ? `flex items-start gap-hsp-xs py-[calc(var(--spacing-vsp-xs)+0.15rem)] pr-[4px] text-small font-semibold break-words ${isActive ? "bg-fg text-bg" : "text-fg hover:underline focus:underline"}` : `block py-vsp-2xs pr-[4px] text-small break-words ${isActive ? "bg-fg font-medium text-bg" : "text-muted hover:underline focus:underline"}`,
|
|
443
|
+
style: { paddingLeft },
|
|
444
|
+
children: [
|
|
445
|
+
isRoot && /* @__PURE__ */ jsx("span", { className: "flex h-[1lh] items-center", children: /* @__PURE__ */ jsx(CategoryLinkIcon, { className: `w-[14px] ${isActive ? "text-bg" : ""}` }) }),
|
|
446
|
+
/* @__PURE__ */ jsx("span", { dangerouslySetInnerHTML: { __html: labelHtml } })
|
|
447
|
+
]
|
|
448
|
+
}
|
|
449
|
+
)
|
|
450
|
+
] }) });
|
|
451
|
+
});
|
|
452
|
+
export {
|
|
453
|
+
SidebarTree
|
|
454
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export interface SidebarLink {
|
|
2
|
+
type: "link";
|
|
3
|
+
label: string;
|
|
4
|
+
href: string;
|
|
5
|
+
}
|
|
6
|
+
export interface SidebarDoc {
|
|
7
|
+
type: "doc";
|
|
8
|
+
/** Doc slug, e.g. "getting-started/introduction" */
|
|
9
|
+
id: string;
|
|
10
|
+
/** Override the doc's title in sidebar */
|
|
11
|
+
label?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface SidebarCategory {
|
|
14
|
+
type: "category";
|
|
15
|
+
label: string;
|
|
16
|
+
items: SidebarItem[];
|
|
17
|
+
collapsed?: boolean;
|
|
18
|
+
sortOrder?: "asc" | "desc";
|
|
19
|
+
}
|
|
20
|
+
export interface SidebarAutogenerated {
|
|
21
|
+
type: "autogenerated";
|
|
22
|
+
dirName?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A sidebar item — string shorthand is equivalent to `{ type: "doc", id: slug }`.
|
|
26
|
+
*/
|
|
27
|
+
export type SidebarItem = SidebarDoc | SidebarLink | SidebarCategory | SidebarAutogenerated | string;
|
|
28
|
+
/** Sidebar config keyed by section (categoryMatch value). */
|
|
29
|
+
export type SidebarsConfig = {
|
|
30
|
+
[sectionKey: string]: SidebarItem[] | undefined;
|
|
31
|
+
};
|
|
32
|
+
/** Minimal nav node shape required by sidebar-utils functions. */
|
|
33
|
+
export interface SidebarNavNode {
|
|
34
|
+
slug: string;
|
|
35
|
+
label: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
position: number;
|
|
38
|
+
href?: string;
|
|
39
|
+
hasPage: boolean;
|
|
40
|
+
children: SidebarNavNode[];
|
|
41
|
+
sortOrder?: "asc" | "desc";
|
|
42
|
+
collapsed?: boolean;
|
|
43
|
+
}
|
|
44
|
+
/** Category metadata shape (mirrors host's CategoryMeta). */
|
|
45
|
+
export interface SidebarCategoryMeta {
|
|
46
|
+
label?: string;
|
|
47
|
+
position?: number;
|
|
48
|
+
collapsed?: boolean;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Build sidebar nodes for a given nav section.
|
|
52
|
+
*
|
|
53
|
+
* If sidebar config exists for this section, use it. Otherwise fall back to
|
|
54
|
+
* the auto-generated tree filtered to the section's categoryMatch.
|
|
55
|
+
*
|
|
56
|
+
* Parameterized version of the host's `buildSidebarForSection` from
|
|
57
|
+
* `src/utils/sidebar.ts` — receives `sidebars`, `buildNavTree`, and
|
|
58
|
+
* `explicitCategoryPrefixes` as arguments instead of importing from
|
|
59
|
+
* `@/config/sidebars`, `@/utils/docs`, `@/utils/nav-scope`.
|
|
60
|
+
*
|
|
61
|
+
* `explicitCategoryPrefixes` is the pre-computed list of non-`"!"` categoryMatch
|
|
62
|
+
* values from headerNav, used for the `"!"` fallback category filter.
|
|
63
|
+
*/
|
|
64
|
+
export declare function buildSidebarForSection(docs: unknown[], lang: string, categoryMatch: string | undefined, categoryMeta: Map<string, SidebarCategoryMeta> | undefined, sidebars: SidebarsConfig, buildNavTree: (docs: unknown[], lang: string, categoryMeta?: Map<string, SidebarCategoryMeta>) => SidebarNavNode[], explicitCategoryPrefixes: string[]): SidebarNavNode[];
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
function findNode(tree, slug) {
|
|
2
|
+
for (const node of tree) {
|
|
3
|
+
if (node.slug === slug) return node;
|
|
4
|
+
if (node.children.length > 0) {
|
|
5
|
+
const found = findNode(node.children, slug);
|
|
6
|
+
if (found) return found;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return void 0;
|
|
10
|
+
}
|
|
11
|
+
function resolveItems(items, tree, lang) {
|
|
12
|
+
return items.flatMap((item) => resolveItem(item, tree, lang));
|
|
13
|
+
}
|
|
14
|
+
function resolveItem(item, tree, lang) {
|
|
15
|
+
if (typeof item === "string") {
|
|
16
|
+
const node = findNode(tree, item);
|
|
17
|
+
return node ? [{ ...node, children: [] }] : [];
|
|
18
|
+
}
|
|
19
|
+
switch (item.type) {
|
|
20
|
+
case "doc": {
|
|
21
|
+
const node = findNode(tree, item.id);
|
|
22
|
+
if (!node) return [];
|
|
23
|
+
return [{ ...node, children: [], ...item.label ? { label: item.label } : {} }];
|
|
24
|
+
}
|
|
25
|
+
case "link": {
|
|
26
|
+
return [
|
|
27
|
+
{
|
|
28
|
+
slug: `__link__${item.href}`,
|
|
29
|
+
label: item.label,
|
|
30
|
+
href: item.href,
|
|
31
|
+
position: 0,
|
|
32
|
+
hasPage: false,
|
|
33
|
+
children: []
|
|
34
|
+
}
|
|
35
|
+
];
|
|
36
|
+
}
|
|
37
|
+
case "category": {
|
|
38
|
+
const children = resolveItems(item.items, tree, lang);
|
|
39
|
+
if (item.sortOrder === "desc") {
|
|
40
|
+
children.reverse();
|
|
41
|
+
}
|
|
42
|
+
return [
|
|
43
|
+
{
|
|
44
|
+
slug: `__category__${item.label}`,
|
|
45
|
+
label: item.label,
|
|
46
|
+
position: 0,
|
|
47
|
+
hasPage: false,
|
|
48
|
+
href: void 0,
|
|
49
|
+
children,
|
|
50
|
+
sortOrder: item.sortOrder,
|
|
51
|
+
collapsed: item.collapsed
|
|
52
|
+
}
|
|
53
|
+
];
|
|
54
|
+
}
|
|
55
|
+
case "autogenerated": {
|
|
56
|
+
if (item.dirName) {
|
|
57
|
+
const node = findNode(tree, item.dirName);
|
|
58
|
+
return node ? node.children : [];
|
|
59
|
+
}
|
|
60
|
+
return tree;
|
|
61
|
+
}
|
|
62
|
+
default: {
|
|
63
|
+
const _exhaustive = item;
|
|
64
|
+
throw new Error(`Unhandled sidebar item type: ${JSON.stringify(_exhaustive)}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function filterByCategory(tree, categoryMatch, explicitPrefixes) {
|
|
69
|
+
if (!categoryMatch) return tree;
|
|
70
|
+
if (categoryMatch === "!") {
|
|
71
|
+
return tree.filter(
|
|
72
|
+
(node) => !explicitPrefixes.some((prefix) => node.slug.startsWith(prefix))
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
return tree.filter((node) => node.slug.startsWith(categoryMatch));
|
|
76
|
+
}
|
|
77
|
+
function buildSidebarForSection(docs, lang, categoryMatch, categoryMeta, sidebars, buildNavTree, explicitCategoryPrefixes) {
|
|
78
|
+
const tree = buildNavTree(docs, lang, categoryMeta);
|
|
79
|
+
const sectionKey = categoryMatch ?? "default";
|
|
80
|
+
const config = sidebars[sectionKey];
|
|
81
|
+
if (!config || config.length === 0) {
|
|
82
|
+
return filterByCategory(tree, categoryMatch, explicitCategoryPrefixes);
|
|
83
|
+
}
|
|
84
|
+
return resolveItems(config, tree, lang);
|
|
85
|
+
}
|
|
86
|
+
export {
|
|
87
|
+
buildSidebarForSection
|
|
88
|
+
};
|