@takazudo/zudo-doc 0.2.22 → 1.0.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/bin/zudo-doc.mjs +83 -0
- package/dist/eject/index.d.ts +33 -0
- package/dist/eject/index.js +229 -0
- package/dist/plugins/routes.d.ts +2 -0
- package/dist/plugins/routes.js +100 -0
- package/dist/preset.d.ts +47 -1
- package/dist/preset.js +29 -13
- package/dist/routes/404.d.ts +7 -0
- package/dist/routes/404.js +47 -0
- package/dist/routes/_chrome.d.ts +32 -0
- package/dist/routes/_chrome.js +365 -0
- package/dist/routes/_context.d.ts +56 -0
- package/dist/routes/_context.js +222 -0
- package/dist/routes/_docs-helpers.d.ts +43 -0
- package/dist/routes/_docs-helpers.js +173 -0
- package/dist/routes/_virtual.d.js +0 -0
- package/dist/routes/api-ai-chat.d.ts +5 -0
- package/dist/routes/api-ai-chat.js +24 -0
- package/dist/routes/docs-slug.d.ts +21 -0
- package/dist/routes/docs-slug.js +26 -0
- package/dist/routes/docs-tags-index.d.ts +7 -0
- package/dist/routes/docs-tags-index.js +11 -0
- package/dist/routes/docs-tags-tag.d.ts +23 -0
- package/dist/routes/docs-tags-tag.js +19 -0
- package/dist/routes/docs-versions.d.ts +7 -0
- package/dist/routes/docs-versions.js +11 -0
- package/dist/routes/index.d.ts +7 -0
- package/dist/routes/index.js +117 -0
- package/dist/routes/locale-docs-slug.d.ts +27 -0
- package/dist/routes/locale-docs-slug.js +40 -0
- package/dist/routes/locale-docs-tags-index.d.ts +18 -0
- package/dist/routes/locale-docs-tags-index.js +15 -0
- package/dist/routes/locale-docs-tags-tag.d.ts +25 -0
- package/dist/routes/locale-docs-tags-tag.js +22 -0
- package/dist/routes/locale-docs-versions.d.ts +18 -0
- package/dist/routes/locale-docs-versions.js +15 -0
- package/dist/routes/locale-index.d.ts +24 -0
- package/dist/routes/locale-index.js +132 -0
- package/dist/routes/robots.txt.d.ts +3 -0
- package/dist/routes/robots.txt.js +8 -0
- package/dist/routes/sitemap.xml.d.ts +5 -0
- package/dist/routes/sitemap.xml.js +31 -0
- package/dist/routes/v-docs-slug.d.ts +27 -0
- package/dist/routes/v-docs-slug.js +34 -0
- package/dist/routes/v-locale-docs-slug.d.ts +31 -0
- package/dist/routes/v-locale-docs-slug.js +50 -0
- package/dist/safelist.css +1 -1
- package/dist/settings.d.ts +15 -0
- package/eject/breadcrumb/breadcrumb.tsx +194 -0
- package/eject/breadcrumb/find-path.ts +26 -0
- package/eject/breadcrumb/index.ts +4 -0
- package/eject/breadcrumb/types.ts +32 -0
- package/eject/code-group/index.tsx +78 -0
- package/eject/content-admonition/index.tsx +50 -0
- package/eject/details/details.tsx +34 -0
- package/eject/details/index.ts +4 -0
- package/eject/doc-pager/index.tsx +91 -0
- package/eject/footer/footer.tsx +167 -0
- package/eject/footer/index.ts +19 -0
- package/eject/footer/types.ts +60 -0
- package/eject/header/header.tsx +725 -0
- package/eject/header/index.ts +36 -0
- package/eject/header/nav-active.ts +122 -0
- package/eject/header/nav-overflow-script.ts +302 -0
- package/eject/header/right-items.ts +78 -0
- package/eject/header/types.ts +69 -0
- package/eject/page-loading/index.ts +10 -0
- package/eject/page-loading/page-loading-overlay.tsx +103 -0
- package/eject/sidebar/index.ts +27 -0
- package/eject/sidebar/sidebar.tsx +137 -0
- package/eject/sidebar/types.ts +73 -0
- package/eject/tab-item/index.ts +7 -0
- package/eject/tab-item/tab-item.tsx +70 -0
- package/eject/theme-toggle/color-scheme-sync.ts +73 -0
- package/eject/theme-toggle/index.tsx +120 -0
- package/eject/toc/cx.ts +38 -0
- package/eject/toc/index.ts +11 -0
- package/eject/toc/mobile-toc.tsx +133 -0
- package/eject/toc/toc-title.ts +33 -0
- package/eject/toc/toc.tsx +119 -0
- package/eject/toc/types.ts +14 -0
- package/eject/toc/use-active-heading.ts +162 -0
- package/package.json +87 -7
- package/routes-src/404.tsx +49 -0
- package/routes-src/_chrome.tsx +470 -0
- package/routes-src/_context.ts +314 -0
- package/routes-src/_docs-helpers.ts +284 -0
- package/routes-src/_virtual.d.ts +15 -0
- package/routes-src/api-ai-chat.tsx +46 -0
- package/routes-src/docs-slug.tsx +43 -0
- package/routes-src/docs-tags-index.tsx +14 -0
- package/routes-src/docs-tags-tag.tsx +29 -0
- package/routes-src/docs-versions.tsx +15 -0
- package/routes-src/index.tsx +134 -0
- package/routes-src/locale-docs-slug.tsx +69 -0
- package/routes-src/locale-docs-tags-index.tsx +23 -0
- package/routes-src/locale-docs-tags-tag.tsx +39 -0
- package/routes-src/locale-docs-versions.tsx +23 -0
- package/routes-src/locale-index.tsx +150 -0
- package/routes-src/robots.txt.tsx +13 -0
- package/routes-src/sitemap.xml.tsx +48 -0
- package/routes-src/v-docs-slug.tsx +64 -0
- package/routes-src/v-locale-docs-slug.tsx +85 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/** @jsxRuntime automatic */
|
|
2
|
+
/** @jsxImportSource preact */
|
|
3
|
+
|
|
4
|
+
// Footer presentational shell for the documentation layout.
|
|
5
|
+
//
|
|
6
|
+
// The original template mixed data-prep (settings + getDocsCollection
|
|
7
|
+
// + tag-vocabulary lookups + locale overrides) with the presentational
|
|
8
|
+
// footer markup. Because v2 must stay decoupled from host-only helpers,
|
|
9
|
+
// only the presentational shell lives here: callers prepare the
|
|
10
|
+
// already-localized, already-resolved data upstream and feed it in via
|
|
11
|
+
// `linkColumns` / `tagColumns` / `copyright` props.
|
|
12
|
+
//
|
|
13
|
+
// Behaviour parity notes:
|
|
14
|
+
//
|
|
15
|
+
// - The `<footer>` shell is always rendered — even when all three slots
|
|
16
|
+
// are empty — so the contentinfo ARIA landmark is present on every
|
|
17
|
+
// page regardless of whether link columns or copyright are configured.
|
|
18
|
+
// (The original Astro template returned early when `!footer`; that
|
|
19
|
+
// guard lives in the host-side `FooterWithDefaults` wrapper in
|
|
20
|
+
// `pages/lib/footer-with-defaults.tsx` now.)
|
|
21
|
+
//
|
|
22
|
+
// - The link/tag column grid is only emitted when at least one column is
|
|
23
|
+
// present (mirrors the Astro `hasColumns &&` guard).
|
|
24
|
+
//
|
|
25
|
+
// - The copyright block is rendered as-is via `dangerouslySetInnerHTML`
|
|
26
|
+
// because the original template used `<Fragment set:html={copyright} />`
|
|
27
|
+
// to allow inline anchors. Callers are responsible for sanitising
|
|
28
|
+
// the string (the Astro version did the same — it trusted
|
|
29
|
+
// `settings.footer.copyright`).
|
|
30
|
+
//
|
|
31
|
+
// - When both columns and copyright exist, the copyright block is
|
|
32
|
+
// visually separated by a top border + spacing, identical to the
|
|
33
|
+
// `mt-vsp-lg border-t border-muted pt-vsp-md` that the Astro template
|
|
34
|
+
// applied via `class:list` conditional.
|
|
35
|
+
|
|
36
|
+
import type { VNode } from "preact";
|
|
37
|
+
|
|
38
|
+
import type { FooterLinkColumn, FooterTagColumn } from "./types.js";
|
|
39
|
+
|
|
40
|
+
export interface FooterProps {
|
|
41
|
+
/**
|
|
42
|
+
* Already-localized link columns. Each item's href should be
|
|
43
|
+
* base-prefixed and locale-aware; `isExternal` controls the
|
|
44
|
+
* target/rel attributes.
|
|
45
|
+
*/
|
|
46
|
+
linkColumns?: FooterLinkColumn[];
|
|
47
|
+
/**
|
|
48
|
+
* Already-resolved tag columns. Empty array (or omitted) hides the
|
|
49
|
+
* taglist entirely. Each tag's href should already be base-prefixed.
|
|
50
|
+
*/
|
|
51
|
+
tagColumns?: FooterTagColumn[];
|
|
52
|
+
/**
|
|
53
|
+
* Copyright HTML. Rendered via `dangerouslySetInnerHTML` so embedded
|
|
54
|
+
* anchors work. The caller is responsible for the contents.
|
|
55
|
+
*/
|
|
56
|
+
copyright?: string;
|
|
57
|
+
/**
|
|
58
|
+
* When provided, adds `data-zfb-transition-persist` to the `<footer>`
|
|
59
|
+
* element. Use a locale-keyed value (e.g. `footer-en`, `footer-ja`) so
|
|
60
|
+
* cross-locale swaps discard the stale footer while same-locale swaps
|
|
61
|
+
* preserve DOM-node identity. See zudolab/zudo-doc#1546.
|
|
62
|
+
*/
|
|
63
|
+
persistKey?: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Footer shell for the documentation layout.
|
|
68
|
+
*
|
|
69
|
+
* Always renders the `<footer>` shell so the contentinfo ARIA landmark
|
|
70
|
+
* is present on every page — even when no columns or copyright are
|
|
71
|
+
* configured. The inner content (link grid, copyright) is only emitted
|
|
72
|
+
* when the respective slots carry data.
|
|
73
|
+
*/
|
|
74
|
+
export function Footer(props: FooterProps): VNode {
|
|
75
|
+
const linkColumns = props.linkColumns ?? [];
|
|
76
|
+
const tagColumns = props.tagColumns ?? [];
|
|
77
|
+
const copyright = props.copyright ?? "";
|
|
78
|
+
const persistKey = props.persistKey;
|
|
79
|
+
|
|
80
|
+
const hasColumns = linkColumns.length > 0 || tagColumns.length > 0;
|
|
81
|
+
const hasCopyright = copyright.length > 0;
|
|
82
|
+
|
|
83
|
+
const copyrightClass = hasColumns
|
|
84
|
+
? "text-center text-caption text-muted [&_a]:text-accent [&_a]:underline mt-vsp-lg border-t border-muted pt-vsp-md"
|
|
85
|
+
: "text-center text-caption text-muted [&_a]:text-accent [&_a]:underline";
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<footer
|
|
89
|
+
class="border-t border-muted bg-surface"
|
|
90
|
+
// Strategy B: locale-keyed persist (zudolab/zudo-doc#1546).
|
|
91
|
+
// The footer's locale-aware bits (link labels, copyright) are SSR'd
|
|
92
|
+
// per locale; a locale-keyed persist key (`footer-en`, `footer-ja`)
|
|
93
|
+
// guarantees cross-locale swaps re-render the footer while
|
|
94
|
+
// same-locale swaps preserve DOM-node identity (safe — footer
|
|
95
|
+
// content is invariant page-to-page within a locale).
|
|
96
|
+
{...(persistKey
|
|
97
|
+
? { "data-zfb-transition-persist": persistKey }
|
|
98
|
+
: {})}
|
|
99
|
+
>
|
|
100
|
+
<div class="mx-auto max-w-[clamp(50rem,75vw,90rem)] px-hsp-xl py-vsp-xl lg:px-hsp-2xl lg:py-vsp-2xl">
|
|
101
|
+
{hasColumns && (
|
|
102
|
+
<div class="grid grid-cols-1 gap-vsp-lg sm:grid-cols-2 lg:grid-cols-[repeat(auto-fit,minmax(12rem,1fr))]">
|
|
103
|
+
{linkColumns.map((column, i) => (
|
|
104
|
+
<div key={`link-${i}-${column.title}`}>
|
|
105
|
+
<p class="text-small font-semibold text-fg mb-vsp-xs">
|
|
106
|
+
{column.title}
|
|
107
|
+
</p>
|
|
108
|
+
<ul class="list-none p-0">
|
|
109
|
+
{column.items.map((item, j) => (
|
|
110
|
+
<li
|
|
111
|
+
key={`item-${i}-${j}-${item.href}`}
|
|
112
|
+
class="mb-vsp-2xs"
|
|
113
|
+
>
|
|
114
|
+
<a
|
|
115
|
+
href={item.href}
|
|
116
|
+
class="text-caption text-muted hover:text-accent hover:underline focus-visible:underline"
|
|
117
|
+
{...(item.isExternal
|
|
118
|
+
? {
|
|
119
|
+
target: "_blank",
|
|
120
|
+
rel: "noopener noreferrer",
|
|
121
|
+
}
|
|
122
|
+
: {})}
|
|
123
|
+
>
|
|
124
|
+
{item.label}
|
|
125
|
+
</a>
|
|
126
|
+
</li>
|
|
127
|
+
))}
|
|
128
|
+
</ul>
|
|
129
|
+
</div>
|
|
130
|
+
))}
|
|
131
|
+
{tagColumns.map((column, i) => (
|
|
132
|
+
<div
|
|
133
|
+
key={`tag-${i}-${column.group}`}
|
|
134
|
+
data-taglist-group={column.group}
|
|
135
|
+
>
|
|
136
|
+
<h2 class="text-small font-semibold text-fg mb-vsp-xs">
|
|
137
|
+
{column.title}
|
|
138
|
+
</h2>
|
|
139
|
+
<ul class="list-none p-0">
|
|
140
|
+
{column.tags.map(({ tag, count, href }) => (
|
|
141
|
+
<li key={`tag-item-${tag}`} class="mb-vsp-2xs">
|
|
142
|
+
<a
|
|
143
|
+
href={href}
|
|
144
|
+
class="text-caption text-muted hover:text-accent hover:underline focus-visible:underline"
|
|
145
|
+
>
|
|
146
|
+
#{tag}
|
|
147
|
+
<span class="opacity-60" aria-hidden="true">
|
|
148
|
+
({count})
|
|
149
|
+
</span>
|
|
150
|
+
</a>
|
|
151
|
+
</li>
|
|
152
|
+
))}
|
|
153
|
+
</ul>
|
|
154
|
+
</div>
|
|
155
|
+
))}
|
|
156
|
+
</div>
|
|
157
|
+
)}
|
|
158
|
+
{hasCopyright && (
|
|
159
|
+
<div
|
|
160
|
+
class={copyrightClass}
|
|
161
|
+
dangerouslySetInnerHTML={{ __html: copyright }}
|
|
162
|
+
/>
|
|
163
|
+
)}
|
|
164
|
+
</div>
|
|
165
|
+
</footer>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public entry for the framework-agnostic footer shell.
|
|
3
|
+
*
|
|
4
|
+
* Consumers import from `@takazudo/zudo-doc/footer`:
|
|
5
|
+
*
|
|
6
|
+
* import { Footer, type FooterProps } from "@takazudo/zudo-doc/footer";
|
|
7
|
+
*
|
|
8
|
+
* The shell is purely presentational — see `./types.ts` for the data
|
|
9
|
+
* shapes the host project assembles upstream.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export { Footer } from "./footer.js";
|
|
13
|
+
export type { FooterProps } from "./footer.js";
|
|
14
|
+
export type {
|
|
15
|
+
FooterLinkColumn,
|
|
16
|
+
FooterLinkItem,
|
|
17
|
+
FooterTagColumn,
|
|
18
|
+
FooterTagItem,
|
|
19
|
+
} from "./types.js";
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public types for the framework-agnostic footer shell.
|
|
3
|
+
*
|
|
4
|
+
* The original footer template mixed three concerns:
|
|
5
|
+
* 1. Reading `settings.footer` and applying locale overrides.
|
|
6
|
+
* 2. Loading the docs collection + tag vocabulary to build the
|
|
7
|
+
* optional taglist columns.
|
|
8
|
+
* 3. Rendering the footer markup.
|
|
9
|
+
*
|
|
10
|
+
* Concerns (1) and (2) depend on host-side helpers (`@/config/settings`,
|
|
11
|
+
* `@/utils/get-docs-collection`, `tag-vocabulary`, etc.) that v2 must
|
|
12
|
+
* not reach into. So this package only ports concern (3): the
|
|
13
|
+
* presentational shell. Callers prepare the columns upstream and pass
|
|
14
|
+
* already-localized, already-resolved hrefs in.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** A single link rendered inside a {@link FooterLinkColumn}. */
|
|
18
|
+
export interface FooterLinkItem {
|
|
19
|
+
/** Visible label (already locale-resolved by the caller). */
|
|
20
|
+
label: string;
|
|
21
|
+
/** Resolved href (already base-prefixed and locale-aware). */
|
|
22
|
+
href: string;
|
|
23
|
+
/**
|
|
24
|
+
* When true, the rendered anchor adds `target="_blank"` and
|
|
25
|
+
* `rel="noopener noreferrer"`. Callers compute this from their own
|
|
26
|
+
* external-href detector.
|
|
27
|
+
*/
|
|
28
|
+
isExternal?: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** One column in the footer's link grid. */
|
|
32
|
+
export interface FooterLinkColumn {
|
|
33
|
+
/** Visible heading for the column (already locale-resolved). */
|
|
34
|
+
title: string;
|
|
35
|
+
items: FooterLinkItem[];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** A single tag rendered inside a {@link FooterTagColumn}. */
|
|
39
|
+
export interface FooterTagItem {
|
|
40
|
+
/** Canonical tag id (rendered as `#<tag>`). */
|
|
41
|
+
tag: string;
|
|
42
|
+
/** Document count shown next to the tag. */
|
|
43
|
+
count: number;
|
|
44
|
+
/** Resolved href to the tag's index page. */
|
|
45
|
+
href: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** One column in the footer's tag grid. */
|
|
49
|
+
export interface FooterTagColumn {
|
|
50
|
+
/**
|
|
51
|
+
* Group identifier — usually a vocabulary group name like `"topic"`,
|
|
52
|
+
* or the literal `"__flat__"` sentinel for the ungrouped/flat column.
|
|
53
|
+
* Surfaced as `data-taglist-group` on the rendered column wrapper so
|
|
54
|
+
* downstream tests / e2e selectors keep working.
|
|
55
|
+
*/
|
|
56
|
+
group: string;
|
|
57
|
+
/** Visible heading for the column (already locale-resolved). */
|
|
58
|
+
title: string;
|
|
59
|
+
tags: FooterTagItem[];
|
|
60
|
+
}
|