@takazudo/zudo-doc 1.1.0 → 1.2.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/dist/doc-body-end-islands/index.d.ts +32 -0
- package/dist/doc-body-end-islands/index.js +40 -0
- package/dist/doc-page-renderer/index.js +5 -2
- package/dist/plugins/routes.js +3 -1
- package/dist/preset.d.ts +24 -8
- package/dist/preset.js +33 -8
- package/dist/routes/404.js +2 -2
- package/dist/routes/_chrome.d.ts +7 -7
- package/dist/routes/_chrome.js +25 -10
- package/dist/routes/_context.d.ts +5 -0
- package/dist/routes/_context.js +2 -0
- package/dist/routes/index.js +2 -2
- package/dist/routes/locale-index.js +2 -2
- package/dist/safelist.css +1 -1
- package/dist/settings.d.ts +12 -10
- package/package.json +10 -6
- package/routes-src/404.tsx +2 -2
- package/routes-src/_chrome.tsx +41 -14
- package/routes-src/_context.ts +5 -0
- package/routes-src/_virtual.d.ts +6 -2
- package/routes-src/index.tsx +2 -2
- package/routes-src/locale-index.tsx +2 -2
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** @jsxRuntime automatic */
|
|
2
|
+
/** @jsxImportSource preact */
|
|
3
|
+
import type { JSX } from "preact";
|
|
4
|
+
/** The `settings` subset this factory reads — the three package-island flags.
|
|
5
|
+
* A structural subset so the host can pass its full `Settings` object. */
|
|
6
|
+
export interface BodyEndIslandsSettings {
|
|
7
|
+
aiAssistant: boolean;
|
|
8
|
+
imageEnlarge: boolean;
|
|
9
|
+
mermaid: boolean;
|
|
10
|
+
}
|
|
11
|
+
/** Dependencies injected by `_chrome.tsx` (carries the virtual-module settings). */
|
|
12
|
+
export interface BodyEndIslandsDeps {
|
|
13
|
+
settings: BodyEndIslandsSettings;
|
|
14
|
+
}
|
|
15
|
+
/** Props for the produced `BodyEndIslands` component. */
|
|
16
|
+
export interface BodyEndIslandsProps {
|
|
17
|
+
/** Base path the AI chat modal uses to construct API URLs. */
|
|
18
|
+
basePath: string;
|
|
19
|
+
/**
|
|
20
|
+
* Sr-only label rendered as the AiChatModal SSR fallback. Defaults to the
|
|
21
|
+
* English string; pass a locale-translated string for non-default locales so
|
|
22
|
+
* screen readers announce the chat entrypoint correctly before hydration.
|
|
23
|
+
*/
|
|
24
|
+
aiChatBodyLabel?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Build the package-default `BodyEndIslands` component bound to the host's
|
|
28
|
+
* serializable `settings` flags. The produced component matches the
|
|
29
|
+
* `createDocBodyEnd` `BodyEndIslands` slot contract
|
|
30
|
+
* (`(props: { basePath: string }) => JSX.Element`).
|
|
31
|
+
*/
|
|
32
|
+
export declare function createBodyEndIslands(deps: BodyEndIslandsDeps): (props: BodyEndIslandsProps) => JSX.Element;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
|
|
2
|
+
import { Island } from "@takazudo/zfb";
|
|
3
|
+
import { AiChatModal } from "../ai-chat-modal/index.js";
|
|
4
|
+
import { ImageEnlarge, ImageEnlargeSsrFallback } from "../image-enlarge/index.js";
|
|
5
|
+
import { MermaidEnlarge, MermaidEnlargeSsrFallback } from "../mermaid-enlarge/index.js";
|
|
6
|
+
const DEFAULT_AI_CHAT_BODY_LABEL = "Ask a question about the documentation.";
|
|
7
|
+
function createBodyEndIslands(deps) {
|
|
8
|
+
const { settings } = deps;
|
|
9
|
+
function BodyEndIslands({
|
|
10
|
+
basePath,
|
|
11
|
+
aiChatBodyLabel = DEFAULT_AI_CHAT_BODY_LABEL
|
|
12
|
+
}) {
|
|
13
|
+
const aiAssistant = settings.aiAssistant ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
14
|
+
/* @__PURE__ */ jsx("h2", { class: "sr-only", children: "AI Assistant" }),
|
|
15
|
+
Island({
|
|
16
|
+
ssrFallback: /* @__PURE__ */ jsx("p", { class: "sr-only", children: aiChatBodyLabel }),
|
|
17
|
+
children: /* @__PURE__ */ jsx(AiChatModal, { basePath })
|
|
18
|
+
})
|
|
19
|
+
] }) : null;
|
|
20
|
+
const imageEnlarge = settings.imageEnlarge ? Island({
|
|
21
|
+
when: "idle",
|
|
22
|
+
ssrFallback: /* @__PURE__ */ jsx(ImageEnlargeSsrFallback, {}),
|
|
23
|
+
children: /* @__PURE__ */ jsx(ImageEnlarge, {})
|
|
24
|
+
}) : null;
|
|
25
|
+
const mermaidEnlarge = settings.mermaid ? Island({
|
|
26
|
+
when: "idle",
|
|
27
|
+
ssrFallback: /* @__PURE__ */ jsx(MermaidEnlargeSsrFallback, {}),
|
|
28
|
+
children: /* @__PURE__ */ jsx(MermaidEnlarge, {})
|
|
29
|
+
}) : null;
|
|
30
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
31
|
+
aiAssistant,
|
|
32
|
+
imageEnlarge,
|
|
33
|
+
mermaidEnlarge
|
|
34
|
+
] });
|
|
35
|
+
}
|
|
36
|
+
return BodyEndIslands;
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
createBodyEndIslands
|
|
40
|
+
};
|
|
@@ -34,7 +34,10 @@ function createRenderDocPage(deps) {
|
|
|
34
34
|
const currentPath = version ? versionedDocsUrl(slug, version.slug, locale) : docsUrl(slug, locale);
|
|
35
35
|
const canonical = absoluteUrl(currentPath);
|
|
36
36
|
const navSection = getNavSectionForSlug(slug);
|
|
37
|
-
const
|
|
37
|
+
const entryData = props.kind === "entry" ? props.entry.data : void 0;
|
|
38
|
+
const standalone = entryData?.standalone;
|
|
39
|
+
const hideSidebar = entryData ? entryData.hide_sidebar || standalone : void 0;
|
|
40
|
+
const hideToc = entryData ? entryData.hide_toc || standalone : void 0;
|
|
38
41
|
const sidebarPersistKey = hideSidebar ? void 0 : `sidebar-${locale}-${navSection ?? "default"}`;
|
|
39
42
|
const ContentComponent = props.kind === "entry" ? props.entry.Content : null;
|
|
40
43
|
return /* @__PURE__ */ jsx(
|
|
@@ -53,7 +56,7 @@ function createRenderDocPage(deps) {
|
|
|
53
56
|
navSection,
|
|
54
57
|
sidebarPersistKey,
|
|
55
58
|
hideSidebar,
|
|
56
|
-
hideToc
|
|
59
|
+
hideToc,
|
|
57
60
|
currentPath,
|
|
58
61
|
currentVersion: version?.slug,
|
|
59
62
|
versionSwitcher: buildInlineVersionSwitcher(slug, locale, version?.slug),
|
package/dist/plugins/routes.js
CHANGED
|
@@ -48,12 +48,14 @@ const plugin = definePlugin({
|
|
|
48
48
|
const settings = options.settings ?? {};
|
|
49
49
|
const translations = options.translations ?? {};
|
|
50
50
|
const tagVocabulary = options.tagVocabulary ?? [];
|
|
51
|
+
const colorSchemes = options.colorSchemes ?? null;
|
|
51
52
|
ctx.addVirtualModule(
|
|
52
53
|
"virtual:zudo-doc-route-context",
|
|
53
54
|
() => `export const routeContext = ${JSON.stringify({
|
|
54
55
|
settings,
|
|
55
56
|
translations,
|
|
56
|
-
tagVocabulary
|
|
57
|
+
tagVocabulary,
|
|
58
|
+
colorSchemes
|
|
57
59
|
})};
|
|
58
60
|
`
|
|
59
61
|
);
|
package/dist/preset.d.ts
CHANGED
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
* bundles cleanly under `--platform=neutral` (verified: zero `node:*`).
|
|
34
34
|
*/
|
|
35
35
|
import { z } from "zod";
|
|
36
|
+
import type { ColorScheme } from "./color-scheme-utils.js";
|
|
36
37
|
/** A single locale's content directory (`settings.locales[code]`). */
|
|
37
38
|
export interface PresetLocaleConfig {
|
|
38
39
|
dir: string;
|
|
@@ -72,13 +73,15 @@ export interface PresetSettings {
|
|
|
72
73
|
claudeResources?: PresetClaudeResourcesConfig | false;
|
|
73
74
|
/** "owner/repo" — when set, enables `#123` / SHA autolinks in markdown. Omit to disable entirely. */
|
|
74
75
|
githubAutolinksRepo?: string;
|
|
75
|
-
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
76
|
+
/**
|
|
77
|
+
* When `true` (the **default** when omitted — #2404), the preset adds the
|
|
78
|
+
* package-owned route-injection plugin (`@takazudo/zudo-doc/plugins/routes`).
|
|
79
|
+
* Set explicitly to `false` to opt out — only needed for projects shipping
|
|
80
|
+
* their own `pages/*.tsx` stubs for every doc route. When `false` AND doc
|
|
81
|
+
* content is configured (`docsDir` non-empty and/or locales/versions set),
|
|
82
|
+
* a single `console.warn` is emitted per build as a heads-up (the build
|
|
83
|
+
* succeeds). See `docs/adr/route-injection-seam.md`. (#2404)
|
|
84
|
+
*/
|
|
82
85
|
packageOwnedRoutes?: boolean;
|
|
83
86
|
/** Gate for the `/docs/tags` + `/docs/tags/[tag]` injected routes. */
|
|
84
87
|
docTags?: boolean;
|
|
@@ -146,6 +149,19 @@ export interface ZudoDocPresetArgs {
|
|
|
146
149
|
* `settings.packageOwnedRoutes` is true. Optional — defaults to `[]`.
|
|
147
150
|
*/
|
|
148
151
|
tagVocabulary?: readonly PresetTagVocabularyEntry[];
|
|
152
|
+
/**
|
|
153
|
+
* The host's color-scheme palette map (`src/config/color-schemes.ts`
|
|
154
|
+
* `colorSchemes`). Only consumed when `settings.packageOwnedRoutes` is true
|
|
155
|
+
* — rides into the route-context virtual module so the package-owned routes
|
|
156
|
+
* (incl. `/404`) can emit the correct `--zd-*` CSS custom properties.
|
|
157
|
+
*
|
|
158
|
+
* Serializable JSON (ColorScheme has no function-valued fields), so it
|
|
159
|
+
* round-trips through `JSON.stringify` losslessly.
|
|
160
|
+
*
|
|
161
|
+
* Optional — when absent, package-owned routes fall back to `DEFAULT_SCHEME`
|
|
162
|
+
* (a neutral grey ramp). See `routes/_chrome.tsx`.
|
|
163
|
+
*/
|
|
164
|
+
colorSchemes?: Record<string, ColorScheme>;
|
|
149
165
|
}
|
|
150
166
|
export interface PresetCollection {
|
|
151
167
|
name: string;
|
|
@@ -199,4 +215,4 @@ export interface ZudoDocPresetResult {
|
|
|
199
215
|
* });
|
|
200
216
|
* ```
|
|
201
217
|
*/
|
|
202
|
-
export declare function zudoDocPreset({ settings, buildDocsSchema, directiveVocabulary, translations, tagVocabulary, }: ZudoDocPresetArgs): ZudoDocPresetResult;
|
|
218
|
+
export declare function zudoDocPreset({ settings, buildDocsSchema, directiveVocabulary, translations, tagVocabulary, colorSchemes, }: ZudoDocPresetArgs): ZudoDocPresetResult;
|
package/dist/preset.js
CHANGED
|
@@ -4,12 +4,13 @@ function zudoDocPreset({
|
|
|
4
4
|
buildDocsSchema,
|
|
5
5
|
directiveVocabulary,
|
|
6
6
|
translations,
|
|
7
|
-
tagVocabulary
|
|
7
|
+
tagVocabulary,
|
|
8
|
+
colorSchemes
|
|
8
9
|
}) {
|
|
9
10
|
const docsSchemaJson = z.toJSONSchema(buildDocsSchema());
|
|
10
11
|
return {
|
|
11
12
|
collections: buildCollections(settings, docsSchemaJson),
|
|
12
|
-
plugins: buildPlugins(settings, { translations, tagVocabulary }),
|
|
13
|
+
plugins: buildPlugins(settings, { translations, tagVocabulary, colorSchemes }),
|
|
13
14
|
markdown: {
|
|
14
15
|
features: buildMarkdownFeatures(settings, directiveVocabulary),
|
|
15
16
|
...settings.cjkFriendly !== void 0 ? { cjkFriendly: settings.cjkFriendly } : {}
|
|
@@ -116,18 +117,41 @@ function buildPlugins(settings, routeContext) {
|
|
|
116
117
|
const localeRecord = Object.fromEntries(
|
|
117
118
|
Object.entries(settings.locales).map(([code, locale]) => [code, { dir: locale.dir }])
|
|
118
119
|
);
|
|
120
|
+
const effectivePackageOwnedRoutes = settings.packageOwnedRoutes ?? true;
|
|
121
|
+
if (effectivePackageOwnedRoutes) {
|
|
122
|
+
const contentConfiguredForWarn = typeof settings.docsDir === "string" && settings.docsDir.length > 0 || Object.keys(settings.locales).length > 0 || Array.isArray(settings.versions) && settings.versions.length > 0;
|
|
123
|
+
const translationsMissing = !routeContext.translations || Object.keys(routeContext.translations).length === 0;
|
|
124
|
+
const colorSchemesMissing = !routeContext.colorSchemes;
|
|
125
|
+
if (contentConfiguredForWarn && (translationsMissing || colorSchemesMissing)) {
|
|
126
|
+
const missing = [
|
|
127
|
+
...translationsMissing ? ["translations"] : [],
|
|
128
|
+
...colorSchemesMissing ? ["colorSchemes"] : []
|
|
129
|
+
].join(" and/or ");
|
|
130
|
+
console.warn(
|
|
131
|
+
`zudo-doc: packageOwnedRoutes is on but ${missing} were not passed to zudoDocPreset \u2014 package-owned routes (incl. /404) will render with fallback i18n/theme. Pass them to inherit host bindings.`
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
if (!effectivePackageOwnedRoutes) {
|
|
136
|
+
const contentConfigured = typeof settings.docsDir === "string" && settings.docsDir.length > 0 || Object.keys(settings.locales).length > 0 || Array.isArray(settings.versions) && settings.versions.length > 0;
|
|
137
|
+
if (contentConfigured) {
|
|
138
|
+
console.warn(
|
|
139
|
+
"zudo-doc: packageOwnedRoutes is off but doc content is configured \u2014 no doc routes will be injected; the build will produce only host pages/. Set packageOwnedRoutes: true in settings."
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
119
143
|
return [
|
|
120
|
-
// Package-owned route injection —
|
|
121
|
-
//
|
|
122
|
-
//
|
|
123
|
-
//
|
|
144
|
+
// Package-owned route injection — default-on (#2404). The descriptor is a
|
|
145
|
+
// BARE SPECIFIER, never an imported plugin function: the preset's node-free
|
|
146
|
+
// eval-graph guard (preset.test.ts) bundles this module under
|
|
147
|
+
// --platform=neutral, and importing the plugin would drag its
|
|
124
148
|
// `injectRoute`/`node:*` graph into the config eval. The plugin's `setup`
|
|
125
149
|
// hook reads `options` to (a) emit the route-context virtual module
|
|
126
150
|
// (serializable settings/translations/tagVocabulary only) and (b) derive
|
|
127
151
|
// the route catalog from `settings.locales` / `settings.versions`. Listed
|
|
128
152
|
// FIRST so an injected route is registered before the other plugins'
|
|
129
153
|
// preBuild work runs (ordering is cosmetic — injection happens in `setup`).
|
|
130
|
-
...
|
|
154
|
+
...effectivePackageOwnedRoutes ? [
|
|
131
155
|
{
|
|
132
156
|
name: "@takazudo/zudo-doc/plugins/routes",
|
|
133
157
|
options: {
|
|
@@ -136,7 +160,8 @@ function buildPlugins(settings, routeContext) {
|
|
|
136
160
|
// src/config/settings.ts), so it round-trips losslessly.
|
|
137
161
|
settings,
|
|
138
162
|
translations: routeContext.translations ?? {},
|
|
139
|
-
tagVocabulary: routeContext.tagVocabulary ?? []
|
|
163
|
+
tagVocabulary: routeContext.tagVocabulary ?? [],
|
|
164
|
+
colorSchemes: routeContext.colorSchemes ?? null
|
|
140
165
|
}
|
|
141
166
|
}
|
|
142
167
|
] : [],
|
package/dist/routes/404.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
HeadWithDefaults,
|
|
6
6
|
HeaderWithDefaults,
|
|
7
7
|
FooterWithDefaults,
|
|
8
|
-
|
|
8
|
+
BodyEndIslands,
|
|
9
9
|
composeMetaTitle
|
|
10
10
|
} from "./_chrome.js";
|
|
11
11
|
const frontmatter = { title: "404" };
|
|
@@ -24,7 +24,7 @@ function NotFoundPage() {
|
|
|
24
24
|
sidebarOverride: /* @__PURE__ */ jsx(Fragment, {}),
|
|
25
25
|
headerOverride: /* @__PURE__ */ jsx(HeaderWithDefaults, { lang: locale }),
|
|
26
26
|
footerOverride: /* @__PURE__ */ jsx(FooterWithDefaults, { lang: locale }),
|
|
27
|
-
bodyEndComponents: /* @__PURE__ */ jsx(
|
|
27
|
+
bodyEndComponents: /* @__PURE__ */ jsx(BodyEndIslands, { basePath: settings.base ?? "/" }),
|
|
28
28
|
enableClientRouter: settings.dynamicPageTransition,
|
|
29
29
|
children: /* @__PURE__ */ jsxs("div", { class: "min-h-[60vh] flex flex-col items-center justify-center px-hsp-2xl py-vsp-xl", children: [
|
|
30
30
|
/* @__PURE__ */ jsx("h1", { class: "text-display font-bold mb-vsp-md", children: "404" }),
|
package/dist/routes/_chrome.d.ts
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
/** @jsxImportSource preact */
|
|
3
3
|
import type { JSX, VNode, ComponentChildren } from "preact";
|
|
4
4
|
import type { DocNavNode } from "./_docs-helpers.js";
|
|
5
|
-
/** Package
|
|
6
|
-
*
|
|
7
|
-
* the
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
/** Package-default body-end islands — the package-island subset of the host's
|
|
6
|
+
* `BodyEndIslands` (AiChatModal / ImageEnlarge / MermaidEnlarge), reconstructed
|
|
7
|
+
* from the serializable virtual-module `settings` flags (#2406 / #2401(c)).
|
|
8
|
+
* The host-owned bootstraps (client-router / design-token-panel) cannot live
|
|
9
|
+
* in the package, so they are NOT included here — A2/S4 re-homes those. */
|
|
10
|
+
declare const BodyEndIslands: (props: import("../doc-body-end-islands/index.js").BodyEndIslandsProps) => JSX.Element;
|
|
11
11
|
export declare const composeMetaTitle: (title: string) => string;
|
|
12
12
|
export declare const HeadWithDefaults: (props: import("../head-with-defaults/index.js").HeadWithDefaultsProps) => JSX.Element;
|
|
13
13
|
export declare const HeaderWithDefaults: (props: import("../header-with-defaults/index.js").HeaderWithDefaultsProps) => JSX.Element;
|
|
@@ -27,6 +27,6 @@ export declare const collectTagMapForLocale: (locale: string) => Map<string, imp
|
|
|
27
27
|
locale: string;
|
|
28
28
|
children?: ComponentChildren;
|
|
29
29
|
}) => JSX.Element;
|
|
30
|
-
export { SiteTreeNavWrapper,
|
|
30
|
+
export { SiteTreeNavWrapper, BodyEndIslands };
|
|
31
31
|
export { buildDocRouteEntries, } from "./_context.js";
|
|
32
32
|
export type { DocNavNode };
|
package/dist/routes/_chrome.js
CHANGED
|
@@ -22,7 +22,8 @@ import {
|
|
|
22
22
|
findNode,
|
|
23
23
|
firstRoutedHref,
|
|
24
24
|
collectTags,
|
|
25
|
-
stableDocs
|
|
25
|
+
stableDocs,
|
|
26
|
+
colorSchemes
|
|
26
27
|
} from "./_context.js";
|
|
27
28
|
import { createComposeMetaTitle } from "../compose-meta-title/index.js";
|
|
28
29
|
import {
|
|
@@ -35,6 +36,7 @@ import { createFooterWithDefaults } from "../footer-with-defaults/index.js";
|
|
|
35
36
|
import { createSidebarWithDefaults } from "../sidebar-with-defaults/index.js";
|
|
36
37
|
import { createSidebarPrepaint } from "../sidebar-prepaint/index.js";
|
|
37
38
|
import { createDocBodyEnd } from "../doc-body-end/index.js";
|
|
39
|
+
import { createBodyEndIslands } from "../doc-body-end-islands/index.js";
|
|
38
40
|
import { createDocPager } from "../doc-pager/index.js";
|
|
39
41
|
import { createDocPageShell } from "../doc-page-shell/index.js";
|
|
40
42
|
import { createDocContentHeader } from "../doc-content-header/index.js";
|
|
@@ -92,9 +94,7 @@ const DEFAULT_SCHEME = {
|
|
|
92
94
|
};
|
|
93
95
|
const docHistoryMeta = {};
|
|
94
96
|
const sidebarsConfig = {};
|
|
95
|
-
|
|
96
|
-
return /* @__PURE__ */ jsx(Fragment, {});
|
|
97
|
-
}
|
|
97
|
+
const BodyEndIslands = createBodyEndIslands({ settings });
|
|
98
98
|
function DocHistoryStub(_props) {
|
|
99
99
|
return /* @__PURE__ */ jsx(Fragment, {});
|
|
100
100
|
}
|
|
@@ -102,13 +102,28 @@ function SearchWidgetBound(props) {
|
|
|
102
102
|
return SearchWidget({ ...props, base: withBase("/") });
|
|
103
103
|
}
|
|
104
104
|
const composeMetaTitle = createComposeMetaTitle(settings.siteName);
|
|
105
|
+
function resolveHostScheme(key) {
|
|
106
|
+
if (!colorSchemes) return DEFAULT_SCHEME;
|
|
107
|
+
return colorSchemes[key] ?? DEFAULT_SCHEME;
|
|
108
|
+
}
|
|
105
109
|
const HeadWithDefaults = createHeadWithDefaults({
|
|
106
110
|
settings,
|
|
107
111
|
composeMetaTitle,
|
|
108
112
|
withBase,
|
|
109
113
|
absoluteUrl,
|
|
110
|
-
|
|
111
|
-
|
|
114
|
+
// Called only in single-scheme mode (colorMode false): resolve via settings.colorScheme.
|
|
115
|
+
generateCssCustomProperties: () => generateCssCustomProperties(resolveHostScheme(settings.colorScheme)),
|
|
116
|
+
// Called only in light/dark mode (colorMode truthy): resolve the pair.
|
|
117
|
+
generateLightDarkCssProperties: () => {
|
|
118
|
+
const cm = settings.colorMode;
|
|
119
|
+
if (cm) {
|
|
120
|
+
return generateLightDarkCssProperties(
|
|
121
|
+
resolveHostScheme(cm.lightScheme),
|
|
122
|
+
resolveHostScheme(cm.darkScheme)
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
return generateLightDarkCssProperties(DEFAULT_SCHEME, DEFAULT_SCHEME);
|
|
126
|
+
}
|
|
112
127
|
});
|
|
113
128
|
function buildRootMenuItems(lang, currentVersion) {
|
|
114
129
|
return buildRootMenuItemsBase(
|
|
@@ -193,7 +208,7 @@ const SidebarWithDefaults = createSidebarWithDefaults({
|
|
|
193
208
|
t
|
|
194
209
|
});
|
|
195
210
|
const SidebarPrepaint = createSidebarPrepaint({ sidebarToggle: settings.sidebarToggle });
|
|
196
|
-
const DocBodyEnd = createDocBodyEnd({ settings, BodyEndIslands
|
|
211
|
+
const DocBodyEnd = createDocBodyEnd({ settings, BodyEndIslands });
|
|
197
212
|
const DocPager = createDocPager({ t });
|
|
198
213
|
const DocMetainfoArea = createDocMetainfoArea({
|
|
199
214
|
settings,
|
|
@@ -348,7 +363,7 @@ const VersionsPageView = createVersionsPageView({
|
|
|
348
363
|
HeadWithDefaults,
|
|
349
364
|
HeaderWithDefaults,
|
|
350
365
|
FooterWithDefaults,
|
|
351
|
-
BodyEndIslands
|
|
366
|
+
BodyEndIslands
|
|
352
367
|
}
|
|
353
368
|
});
|
|
354
369
|
const tagPages = createTagPages({
|
|
@@ -365,7 +380,7 @@ const tagPages = createTagPages({
|
|
|
365
380
|
HeadWithDefaults,
|
|
366
381
|
HeaderWithDefaults,
|
|
367
382
|
FooterWithDefaults,
|
|
368
|
-
BodyEndIslands
|
|
383
|
+
BodyEndIslands,
|
|
369
384
|
DocHistoryArea
|
|
370
385
|
}
|
|
371
386
|
});
|
|
@@ -374,7 +389,7 @@ import {
|
|
|
374
389
|
buildDocRouteEntries
|
|
375
390
|
} from "./_context.js";
|
|
376
391
|
export {
|
|
377
|
-
|
|
392
|
+
BodyEndIslands,
|
|
378
393
|
FooterWithDefaults,
|
|
379
394
|
HeadWithDefaults,
|
|
380
395
|
HeaderWithDefaults,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Settings } from "../settings.js";
|
|
2
|
+
import type { ColorScheme } from "../color-scheme-utils.js";
|
|
2
3
|
import type { FactoryI18n } from "../factory-context/index.js";
|
|
3
4
|
import { type UrlHelpers } from "../url-helpers/index.js";
|
|
4
5
|
import { toRouteSlug, toSlugParams } from "../slug/index.js";
|
|
@@ -10,10 +11,14 @@ export interface RouteContextPayload {
|
|
|
10
11
|
settings: Settings;
|
|
11
12
|
translations: Record<string, Record<string, string>>;
|
|
12
13
|
tagVocabulary: readonly TagVocabularyEntry[];
|
|
14
|
+
colorSchemes: Record<string, ColorScheme> | null;
|
|
13
15
|
}
|
|
14
16
|
/** The serializable route-context (from the virtual module). */
|
|
15
17
|
export declare const ctx: RouteContextPayload;
|
|
16
18
|
export declare const settings: Settings;
|
|
19
|
+
/** Host color-scheme palette map. `null` when not supplied — `_chrome.tsx`
|
|
20
|
+
* falls back to `DEFAULT_SCHEME` in that case. */
|
|
21
|
+
export declare const colorSchemes: Record<string, ColorScheme> | null;
|
|
17
22
|
export declare const defaultLocale: string;
|
|
18
23
|
export declare const locales: readonly string[];
|
|
19
24
|
export declare function getLocaleConfig(locale: string): {
|
package/dist/routes/_context.js
CHANGED
|
@@ -35,6 +35,7 @@ const ctx = routeContext;
|
|
|
35
35
|
const settings = ctx.settings;
|
|
36
36
|
const translations = ctx.translations;
|
|
37
37
|
const tagVocabulary = ctx.tagVocabulary;
|
|
38
|
+
const colorSchemes = ctx.colorSchemes;
|
|
38
39
|
const defaultLocale = settings.defaultLocale;
|
|
39
40
|
const locales = [
|
|
40
41
|
defaultLocale,
|
|
@@ -183,6 +184,7 @@ export {
|
|
|
183
184
|
buildNavTree,
|
|
184
185
|
collectAutoIndexNodes,
|
|
185
186
|
collectTags,
|
|
187
|
+
colorSchemes,
|
|
186
188
|
ctx,
|
|
187
189
|
defaultLocale,
|
|
188
190
|
docsUrl,
|
package/dist/routes/index.js
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
HeadWithDefaults,
|
|
20
20
|
HeaderWithDefaults,
|
|
21
21
|
FooterWithDefaults,
|
|
22
|
-
|
|
22
|
+
BodyEndIslands,
|
|
23
23
|
composeMetaTitle
|
|
24
24
|
} from "./_chrome.js";
|
|
25
25
|
const frontmatter = { title: "Home" };
|
|
@@ -53,7 +53,7 @@ function IndexPage() {
|
|
|
53
53
|
sidebarOverride: /* @__PURE__ */ jsx(Fragment, {}),
|
|
54
54
|
headerOverride: /* @__PURE__ */ jsx(HeaderWithDefaults, { lang: locale, currentPath: withBase("/") }),
|
|
55
55
|
footerOverride: /* @__PURE__ */ jsx(FooterWithDefaults, { lang: locale }),
|
|
56
|
-
bodyEndComponents: /* @__PURE__ */ jsx(
|
|
56
|
+
bodyEndComponents: /* @__PURE__ */ jsx(BodyEndIslands, { basePath: settings.base ?? "/" }),
|
|
57
57
|
enableClientRouter: settings.dynamicPageTransition,
|
|
58
58
|
children: [
|
|
59
59
|
/* @__PURE__ */ jsx("div", { class: "flex justify-center mb-vsp-xl", children: /* @__PURE__ */ jsxs("div", { class: "flex flex-col items-center text-center gap-hsp-md lg:flex-row lg:text-left lg:gap-hsp-xl", children: [
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
HeadWithDefaults,
|
|
21
21
|
HeaderWithDefaults,
|
|
22
22
|
FooterWithDefaults,
|
|
23
|
-
|
|
23
|
+
BodyEndIslands,
|
|
24
24
|
composeMetaTitle
|
|
25
25
|
} from "./_chrome.js";
|
|
26
26
|
const frontmatter = { title: "Home" };
|
|
@@ -63,7 +63,7 @@ function LocaleIndexPage({ params }) {
|
|
|
63
63
|
sidebarOverride: /* @__PURE__ */ jsx(Fragment, {}),
|
|
64
64
|
headerOverride: /* @__PURE__ */ jsx(HeaderWithDefaults, { lang: locale, currentPath: withBase(`/${locale}/`) }),
|
|
65
65
|
footerOverride: /* @__PURE__ */ jsx(FooterWithDefaults, { lang: locale }),
|
|
66
|
-
bodyEndComponents: /* @__PURE__ */ jsx(
|
|
66
|
+
bodyEndComponents: /* @__PURE__ */ jsx(BodyEndIslands, { basePath: settings.base ?? "/" }),
|
|
67
67
|
enableClientRouter: settings.dynamicPageTransition,
|
|
68
68
|
children: [
|
|
69
69
|
/* @__PURE__ */ jsx("div", { class: "flex justify-center mb-vsp-xl", children: /* @__PURE__ */ jsxs("div", { class: "flex flex-col items-center text-center gap-hsp-md lg:flex-row lg:text-left lg:gap-hsp-xl", children: [
|
package/dist/safelist.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/* generated by gen-safelist.mjs — do not edit by hand */
|
|
2
|
-
@source inline("-mb-px -ml-hsp-sm -translate-x-full 2xl:w-[24px] [&::-webkit-details-marker]:hidden [&_a]:text-accent [&_a]:underline [&_nav]:mb-0 [data-kbd-shortcut] [doc-history-meta] [doc-history] [doc-layout] [llms-txt] a a2 abbr about above absent absolute across activated active actual added admonition admonition- admonition-body admonition-title after after-breadcrumb after-content after-navigate after-sidebar after-title against agent agents ai-chat ai-chat-md ai-chat-trigger alert align-top all allow-same-origin allow-scripts alone already already-executed an anchor anchored and animate-spin announce antialiased any application/json application/xml applies apply-css-vars approach are area arg aria-atomic aria-busy aria-controls aria-current aria-disabled aria-expanded aria-haspopup aria-hidden aria-label aria-live aria-orientation aria-pressed aria-selected aria-valuemax aria-valuemin aria-valuenow arrive arrows article as asc aside aspect-[1200/630] aspect-square assets assigning assistant async at attach attribute attributes auto autogenerated available avoid await away b back backdrop:bg-bg/30 backdrop:bg-bg/80 backdrop:bg-overlay/60 backdrop:z-modal-backdrop background backtick backticks baked banner bare base base64 based batch be because before below best between bg bg-[#fff] bg-accent bg-bg bg-chat-assistant-bg bg-chat-user-bg bg-code-bg bg-fg bg-info/10 bg-info/5 bg-muted bg-overlay/30 bg-surface bg-transparent bg-warning/10 bg-warning/5 bi bigint bin blank blanks blob block blockquote blocks blur body body-end-components body-end-scripts boolean bootstrap border border-accent border-b border-b-2 border-b-[5px] border-bg/30 border-collapse border-danger border-dashed border-fg border-info/30 border-l border-l-0 border-l-[3px] border-muted border-none border-r border-solid border-t border-t-[2px] border-t-[3px] border-transparent border-warning/30 border-y both bottom-vsp-xl box-border br breadcrumb:end breadcrumb:start break-words browser browsers btn bug bundler but button buttons by bypassed cached call caller can cancellation cannot canonical caption carry cases cat-nav- catch category catppuccin-latte caught caution center center/contain change changed changes checkbox child ci circle cite class class-less claude claude-agents claude-commands claude-md claude-skills cleaned clear clear-css-vars clearing click client client-router client-side clip clobbering close closed closing code code-block-sr-announce code-group code-group-panel col col-resize colgroup collision color color-scheme color-scheme-changed color-scheme-provider color-tweak colorization colors command commands commit compare component component:github-link component:language-switcher component:search component:theme-toggle component:version-switcher compute computed concrete configuration configure configured connect const consumer consumes container containers containing content content-admonition content-type content-wrapper:end content-wrapper:start contents context controller controls converts copy correct correctly corrupt count covered covers cp crashes created cross-component crumb- cs css cur current cursor cursor-not-allowed cursor-pointer custom danger dark data data-active data-admonition data-base data-close-search data-group-id data-header data-header-logo data-header-nav data-header-right data-kbd-shortcut data-loading-index data-mermaid-enlarge-ready data-mermaid-rendered data-mermaid-src data-nav-item data-nav-item-dropdown data-nav-more data-nav-more-menu data-nav-more-toggle data-no-results data-open-search data-pan-active data-processed data-result-count-template data-search-count data-search-count-narrow data-search-dialog data-search-input data-search-placeholder data-search-results data-search-unavailable data-sidebar-hidden data-sidebar-resizer data-site-nav data-tab-btn data-tab-default data-tab-label data-tab-value data-tabs data-taglist-group data-testid data-theme data-theme/style data-variant data-version-banner data-version-menu data-version-switcher data-version-toggle data-zfb-transition-persist dd debounced decimal declare decoration-muted default defaults del delegated desc description design design-token-panel design-token-trigger desktop desktop-sidebar desktop-sidebar-toggle desktop-sidebar-toggle-island destructive detach detached details deterministic develop dfn diagram diagrams dialog dieser diff diff-line-added diff-line-content diff-line-empty diff-line-num diff-line-removed diff-row dir directly directories directory disabled disabled:opacity-50 disc display:none dist div dl do doc doc-card- doc-history doc-history-generate doc-history-panel doc-history-trigger doc-pager docs docs- docs-v- document document-level does double-registration drag draggable drop dropdown dropdown-child dropdown-parent dropdowns dt duration-150 duration-200 during dynamically e e2e each earlier ease-in-out edge eject ejected el element elements els else em emit emitting empty empty/undefined en enable end enlarged entire entities entries entry error escape escaped even eventually every exactly excerpt existing exists exit expected export extends failed fall fallback fallbacks falls false fast feature feed fg fields fieldset figcaption figure file fill fills finally find fire fires first fixed fixtures flag flash flat flex flex-1 flex-col flex-wrap flip flipping flips focus focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2 focus-visible:underline focus:border-accent focus:outline-none focus:underline font font-bold font-medium font-mono font-semibold footer footer- for form found free fresh from frontmatter frontmatter-preview frozen fs-extra full fully function further g gap-[0.3em] gap-[clamp(1.5rem,3vw,4rem)] gap-hsp-2xs gap-hsp-md gap-hsp-sm gap-hsp-xl gap-hsp-xs gap-vsp-2xs gap-vsp-lg gap-vsp-md gap-vsp-xs gap-x-hsp-2xs gap-x-hsp-lg gap-x-hsp-md gap-x-hsp-sm gap-x-hsp-xs gap-y-vsp-2xs gap-y-vsp-lg gap-y-vsp-md gap-y-vsp-xs gaps gate generate generation genuine geometry get github github-link go got graph gray-matter grid grid-cols-1 grid-cols-2 group group-focus-visible:text-accent group-focus-visible:underline group-focus-within:block group-hover:bg-fg group-hover:block group-hover:text-accent group-hover:text-bg group-hover:underline group-open:rotate-90 guard h-[0.5rem] h-[0.625rem] h-[0.875rem] h-[1.125rem] h-[1.25rem] h-[1.575rem] h-[14px] h-[1lh] h-[2rem] h-[3.5rem] h-[3rem] h-[90vh] h-[calc(100%-3rem)] h-[calc(100vh-3.5rem)] h-dvh h-full h-icon-lg h-icon-md h-icon-sm h-icon-xs h1 h2 h3 h4 h5 h6 half hand handle handled handler handlers has hash-link have head head-links head-scripts header header- header-call:end header-call:start height here hex hidden highlight highlighter history hit horizontal host hover:bg-[color-mix(in_srgb,var(--color-surface)_80%,var(--color-fg)_20%)] hover:bg-accent-hover hover:bg-accent/10 hover:bg-surface hover:border-accent hover:border-accent-hover hover:border-fg hover:text-accent hover:text-accent-hover hover:text-fg hover:underline hr href hrefs html i i2 i3 i4 icon identical idle idx if iframe image image-enlarge image/png img import important imports in inactive inbox includes index index-load info inherit initial initialised injected inline inline-block inline-flex input input-clear ins inset-0 inside install instance instanceof instead instructions intended intent into invalid inverse invoke is issues it italic item item- items items-baseline items-center items-start its itself javascript justify-between justify-center justify-end justify-start katex kbd keep keeps kept keyboard keyboard-shortcut keydown keystroke keywords khroma label landing language-switcher last:border-b-0 later launch leading-relaxed leading-snug leading-tight leaf- leak leaves leaving left left-0 left:calc legend legitimate lg lg:block lg:border lg:border-fg lg:border-solid lg:flex lg:flex-col lg:flex-row lg:gap-hsp-xl lg:grid-cols-[repeat(auto-fit,minmax(12rem,1fr))] lg:h-[90vh] lg:hidden lg:justify-start lg:m-auto lg:max-h-[90vh] lg:max-w-[52.5rem] lg:ml-[var(--zd-sidebar-w)] lg:pt-vsp-2xl lg:px-hsp-2xl lg:py-vsp-2xl lg:text-left lg:w-[90vw] lg:w-[clamp(16rem,25%,22rem)] li li2 light like likely line linger link link- links list-disc list-none listener literal literals lives llms llms-txt load local locale locales log longest-match look lostpointercapture lower lowercased luminance m m-0 m21 m6 main make malformed malicious maps mark marks matches matching math math-display math-inline max max-h-[80vh] max-h-[85vh] max-h-[90vh] max-h-full max-h-none max-w-[46rem] max-w-[80rem] max-w-[85%] max-w-[85vw] max-w-[90vw] max-w-[clamp(50rem,75vw,90rem)] max-w-full max-w-none may mb-0 mb-vsp-2xs mb-vsp-lg mb-vsp-md mb-vsp-sm mb-vsp-xl mb-vsp-xs measures measuring mechanism menu merged mermaid message messages meta metadata min-h-[60vh] min-h-[calc(100vh-3.5rem)] min-h-screen min-w-0 min-w-[10rem] min-w-[8rem] mirror mirrors missing ml-auto ml-hsp-2xl ml-hsp-lg ml-hsp-sm ml-hsp-xl mod mode mounted mouseenter mouseleave mr-hsp-sm mt-0 mt-vsp-2xl mt-vsp-2xs mt-vsp-3xs mt-vsp-lg mt-vsp-md mt-vsp-sm mt-vsp-xl must mutates mutation mutations mx-auto my-vsp-lg my-vsp-md name named native nav nav-card- navigating navigation navigations near needs new newly-swapped next no no-enlarge no-op no-repeat no-underline node node:buffer node:fs node:fs/promises node:module node:path nodes nofollow noindex non-empty non-persisted non-string none noopener noreferrer normal not not-object note now null number numeric object object-contain observe observer occurred of off og:description og:image og:image:alt og:image:height og:image:width og:title og:type og:url ol old older on once one only opacity-60 open open/close option or original other others out outline-none over overflow overflow-auto overflow-hidden overflow-x-auto overflow-y-auto overflow-y:auto overwrite own p p-0 p-hsp-lg p-hsp-md p-hsp-sm p-hsp-xl package packages padding page page-loading page-loading-overlay page-loading-spinner page-navigate-end pages paint pan panel panels parent parse parsed pass path paths pattern pb-[50vh] pb-vsp-md pb-vsp-xl pb-vsp-xs per per-call per-link permanently persisted pi pick picked picks picocolors pins pipelines pl-[1.25rem] pl-hsp-lg pl-hsp-sm pl-hsp-xl place placeholder placeholder:text-muted plain plural plus pnpm pointer-events-none pointercancel pointerdown pointermove pointerup polite polygon polyline populates port position position:fixed pr-[4px] pr-hsp-lg pr-hsp-md pr-hsp-sm pr-hsp-xl pre pre-lowercased preact preact/compat preact/hooks preact/jsx-runtime preload pres preserved produced produces production project propagating properties property props provided proxy pt-[0.15rem] pt-[2px] pt-vsp-3xs pt-vsp-md pt-vsp-sm pt-vsp-xl pt-vsp-xs ptag- public purely px px-hsp-2xl px-hsp-2xs px-hsp-lg px-hsp-md px-hsp-sm px-hsp-xl px-hsp-xs py-0 py-[2px] py-[calc(var(--spacing-vsp-xs)+0.15rem)] py-hsp-2xs py-hsp-sm py-hsp-xs py-vsp-2xs py-vsp-3xs py-vsp-lg py-vsp-md py-vsp-sm py-vsp-xl py-vsp-xs q query question r raw re-encode/decode re-lowercase re-querying re-render re-renders re-run re-running re-selects reach reached reaches read reading reads ready real real-value recorded recovers references refetch refreshes regenerate regenerates reinit reinits relative reload remains remove removed render rendered renders reorder repaint repeated repeating replaced replaces repopulate requires reserved resize resize-x resolve resolved resolves response restore restores result result-click results results-area retry return returns revision revisions rewrite right- right-0 ro robots role root rotate-180 rotate-90 round round-trip rounded rounded-[0.75rem] rounded-bl-[0.25rem] rounded-bl-[1rem] rounded-br-[0.25rem] rounded-br-[1rem] rounded-full rounded-lg rounded-t-[1rem] route router routes-src running runs runtime s safe safer same same-locale samp scanned schema-mismatch schema-missing scheme score scored script script-eval script-evaluation script-injection scripts scroll scrollbar scrolled scrollend search search-index searched section section- see sel-bg sel-fg select select-none self self-start sentinel separator server server-rendered set sets setup shadow-[0_1px_3px_color-mix(in_srgb,var(--color-fg)_8%,transparent)] shadow-lg shared shiki ship ships short shortcut should show shown shrink-0 sidebar sidebar- sidebar-toggle-island sidebar-tree-island signal similarity single singular site-search site-tree-nav-island sitemap- sites size skill skills skipping skips slash slug sm:border sm:border-muted sm:flex-row sm:grid-cols-2 sm:h-auto sm:items-center sm:justify-between sm:max-h-[80vh] sm:max-w-[52rem] sm:mx-auto sm:my-[10vh] sm:rounded-lg small smooth snapshot snapshots so soft soft-nav solid some somehow source sources space-y-vsp-2xs spacing span spans spec specifier specifiers sr-only src stale start state status stay sticky still stop stored stray string strings strip stroke-linecap stroke-linejoin stroke-width strong style style-attribute styles stylesheet sub subagents subsequent success successful summary sup support survives svg swap swapped swaps synchronous synchronously syntactically syntect t tab tab-item tab-panel tabindex table tablist tabpanel tabs tabs-container tabs-content tabs-nav tag tag- tag-item- tags tags:audit tbody td temp temp-element template temporary temporary-element terminal terms test-results text text-accent text-bg text-body text-caption text-center text-chat-assistant-text text-chat-user-text text-code-fg text-danger text-display text-fg text-heading text-info text-left text-micro text-muted text-muted/50 text-right text-small text-title text-warning text/plain textarea tfoot th that the thead their them theme theme-color theme-toggle theme/token then there these they this through throw time tip title to toggle toggle-ai-chat toggle-design-token-panel toggles token tokens tolerates too toolbar top-0 top-[3.5rem] top-full top-level total touches tp tr tracked tracking-wider trade-off transition transition-[background,color,border-color] transition-[left,color] transition-colors transition-transform translate-x-0 transparent treats tree tree-child- tree-item- tree-top- trick trigger trigger:ai-chat trigger:design-token-panel triggers true truncate truncated try turn twitter:card twitter:creator twitter:description twitter:image twitter:site twitter:title two type u ul unavailable unchanged undefined under underline understand unknown unmaintained unobserve unreadable unrelated unreleased unreliable unset unsupported up uppercase usage use used user uses utf-8 utf8 utilities v v2 val value value-reader values var variable version version- version-menu version-switcher vertical via video viewport virtual:zudo-doc-route-context visible vitesse-dark vocabulary w w-1/2 w-[0.5rem] w-[0.625rem] w-[0.875rem] w-[1.125rem] w-[1.575rem] w-[1.5rem] w-[1.75rem] w-[14px] w-[16px] w-[16rem] w-[18px] w-[280px] w-[2rem] w-[320px] w-[90vw] w-[var(--zd-sidebar-w)] w-dvw w-full w-icon-lg w-icon-md w-icon-sm w-icon-xs want warning was watching wbr wbr- we website went what when where whereas whether which while whitespace-nowrap whitespace-pre whole will with without word working worktrees would wrap wrapper wrappers written wrong wrote xl:flex xl:hidden y-scrollbar yet you your z-dropdown z-local-1 z-modal z-modal-backdrop z-sidebar z-toolbar zd-content zd-desktop-sidebar-toggle zd-doc-content-band zd-enlarge-btn zd-enlarge-dialog zd-enlarge-dialog-close zd-enlargeable zd-html-preview-code zd-mermaid-dialog zd-mermaid-enlargeable zd-mermaid-tool-btn zd-mermaid-toolbar zd-mermaid-transform zd-mermaid-viewport zd-sidebar-content-wrapper zd-sidebar-open zfb zfb:after-swap zfb:before-preparation zod zoom zudo-doc-design-tokens/v1 zudo-doc-sidebar-visible zudo-doc-sidebar-width zudo-doc-theme zudo-doc-theme-bridge");
|
|
2
|
+
@source inline("-mb-px -ml-hsp-sm -translate-x-full 2xl:w-[24px] [&::-webkit-details-marker]:hidden [&_a]:text-accent [&_a]:underline [&_nav]:mb-0 [data-kbd-shortcut] [doc-history-meta] [doc-history] [doc-layout] [llms-txt] a a2 abbr about above absent absolute across activated active actual added admonition admonition- admonition-body admonition-title after after-breadcrumb after-content after-navigate after-sidebar after-title against agent agents ai-chat ai-chat-md ai-chat-trigger alert align-top all allow-same-origin allow-scripts alone already already-executed an anchor anchored and and/or animate-spin announce antialiased any application/json application/xml applies apply-css-vars approach are area arg aria-atomic aria-busy aria-controls aria-current aria-disabled aria-expanded aria-haspopup aria-hidden aria-label aria-live aria-orientation aria-pressed aria-selected aria-valuemax aria-valuemin aria-valuenow arrive arrows article as asc aside aspect-[1200/630] aspect-square assets assigning assistant async at attach attribute attributes auto autogenerated available avoid await away b back backdrop:bg-bg/30 backdrop:bg-bg/80 backdrop:bg-overlay/60 backdrop:z-modal-backdrop background backtick backticks baked banner bare base base64 based batch be because before below best between bg bg-[#fff] bg-accent bg-bg bg-chat-assistant-bg bg-chat-user-bg bg-code-bg bg-fg bg-info/10 bg-info/5 bg-muted bg-overlay/30 bg-surface bg-transparent bg-warning/10 bg-warning/5 bi bigint bin blank blanks blob block blockquote blocks blur body body-end-components body-end-scripts boolean bootstrap border border-accent border-b border-b-2 border-b-[5px] border-bg/30 border-collapse border-danger border-dashed border-fg border-info/30 border-l border-l-0 border-l-[3px] border-muted border-none border-r border-solid border-t border-t-[2px] border-t-[3px] border-transparent border-warning/30 border-y both bottom-vsp-xl box-border br breadcrumb:end breadcrumb:start break-words browser browsers btn bug build bundler but button buttons by bypassed cached call caller can cancellation cannot canonical caption carry cases cat-nav- catch category catppuccin-latte caught caution center center/contain change changed changes checkbox child ci circle cite class class-less claude claude-agents claude-commands claude-md claude-skills cleaned clear clear-css-vars clearing click client client-router client-side clip clobbering close closed closing code code-block-sr-announce code-group code-group-panel col col-resize colgroup collision color color-scheme color-scheme-changed color-scheme-provider color-tweak colorization colors command commands commit compare component component:github-link component:language-switcher component:search component:theme-toggle component:version-switcher compute computed concrete configuration configure configured connect const consumer consumes container containers containing content content-admonition content-type content-wrapper:end content-wrapper:start contents context controller controls converts copy correct correctly corrupt count covered covers cp crashes created cross-component crumb- cs css cur current cursor cursor-not-allowed cursor-pointer custom danger dark data data-active data-admonition data-base data-close-search data-group-id data-header data-header-logo data-header-nav data-header-right data-kbd-shortcut data-loading-index data-mermaid-enlarge-ready data-mermaid-rendered data-mermaid-src data-nav-item data-nav-item-dropdown data-nav-more data-nav-more-menu data-nav-more-toggle data-no-results data-open-search data-pan-active data-processed data-result-count-template data-search-count data-search-count-narrow data-search-dialog data-search-input data-search-placeholder data-search-results data-search-unavailable data-sidebar-hidden data-sidebar-resizer data-site-nav data-tab-btn data-tab-default data-tab-label data-tab-value data-tabs data-taglist-group data-testid data-theme data-theme/style data-variant data-version-banner data-version-menu data-version-switcher data-version-toggle data-zfb-transition-persist dd debounced decimal declare decoration-muted default defaults del delegated desc description design design-token-panel design-token-trigger desktop desktop-sidebar desktop-sidebar-toggle desktop-sidebar-toggle-island destructive detach detached details deterministic develop dfn diagram diagrams dialog dieser diff diff-line-added diff-line-content diff-line-empty diff-line-num diff-line-removed diff-row dir directly directories directory disabled disabled:opacity-50 disc display:none dist div dl do doc doc-card- doc-history doc-history-generate doc-history-panel doc-history-trigger doc-pager docs docs- docs-v- document document-level does double-registration drag draggable drop dropdown dropdown-child dropdown-parent dropdowns dt duration-150 duration-200 during dynamically e e2e each earlier ease-in-out edge eject ejected el element elements els else em emit emitting empty empty/undefined en enable end enlarged entire entities entries entry error escape escaped even eventually every exactly excerpt existing exists exit expected export extends failed fall fallback fallbacks falls false fast feature feed fg fields fieldset figcaption figure file fill fills finally find fire fires first fixed fixtures flag flash flat flex flex-1 flex-col flex-wrap flip flipping flips focus focus-visible:outline-2 focus-visible:outline-accent focus-visible:outline-offset-2 focus-visible:underline focus:border-accent focus:outline-none focus:underline font font-bold font-medium font-mono font-semibold footer footer- for form found free fresh from frontmatter frontmatter-preview frozen fs-extra full fully function further g gap-[0.3em] gap-[clamp(1.5rem,3vw,4rem)] gap-hsp-2xs gap-hsp-md gap-hsp-sm gap-hsp-xl gap-hsp-xs gap-vsp-2xs gap-vsp-lg gap-vsp-md gap-vsp-xs gap-x-hsp-2xs gap-x-hsp-lg gap-x-hsp-md gap-x-hsp-sm gap-x-hsp-xs gap-y-vsp-2xs gap-y-vsp-lg gap-y-vsp-md gap-y-vsp-xs gaps gate generate generation genuine geometry get github github-link go got graph gray-matter grid grid-cols-1 grid-cols-2 group group-focus-visible:text-accent group-focus-visible:underline group-focus-within:block group-hover:bg-fg group-hover:block group-hover:text-accent group-hover:text-bg group-hover:underline group-open:rotate-90 guard h-[0.5rem] h-[0.625rem] h-[0.875rem] h-[1.125rem] h-[1.25rem] h-[1.575rem] h-[14px] h-[1lh] h-[2rem] h-[3.5rem] h-[3rem] h-[90vh] h-[calc(100%-3rem)] h-[calc(100vh-3.5rem)] h-dvh h-full h-icon-lg h-icon-md h-icon-sm h-icon-xs h1 h2 h3 h4 h5 h6 half hand handle handled handler handlers has hash-link have head head-links head-scripts header header- header-call:end header-call:start height here hex hidden highlight highlighter history hit horizontal host hover:bg-[color-mix(in_srgb,var(--color-surface)_80%,var(--color-fg)_20%)] hover:bg-accent-hover hover:bg-accent/10 hover:bg-surface hover:border-accent hover:border-accent-hover hover:border-fg hover:text-accent hover:text-accent-hover hover:text-fg hover:underline hr href hrefs html i i18n/theme. i2 i3 i4 icon identical idle idx if iframe image image-enlarge image/png img import important imports in inactive inbox includes index index-load info inherit initial initialised injected inline inline-block inline-flex input input-clear ins inset-0 inside install instance instanceof instead instructions intended intent into invalid inverse invoke is issues it italic item item- items items-baseline items-center items-start its itself javascript justify-between justify-center justify-end justify-start katex kbd keep keeps kept keyboard keyboard-shortcut keydown keystroke keywords khroma label landing language-switcher last:border-b-0 later launch leading-relaxed leading-snug leading-tight leaf- leak leaves leaving left left-0 left:calc legend legitimate lg lg:block lg:border lg:border-fg lg:border-solid lg:flex lg:flex-col lg:flex-row lg:gap-hsp-xl lg:grid-cols-[repeat(auto-fit,minmax(12rem,1fr))] lg:h-[90vh] lg:hidden lg:justify-start lg:m-auto lg:max-h-[90vh] lg:max-w-[52.5rem] lg:ml-[var(--zd-sidebar-w)] lg:pt-vsp-2xl lg:px-hsp-2xl lg:py-vsp-2xl lg:text-left lg:w-[90vw] lg:w-[clamp(16rem,25%,22rem)] li li2 light like likely line linger link link- links list-disc list-none listener literal literals lives llms llms-txt load local locale locales log longest-match look lostpointercapture lower lowercased luminance m m-0 m21 m6 main make malformed malicious maps mark marks matches matching math math-display math-inline max max-h-[80vh] max-h-[85vh] max-h-[90vh] max-h-full max-h-none max-w-[46rem] max-w-[80rem] max-w-[85%] max-w-[85vw] max-w-[90vw] max-w-[clamp(50rem,75vw,90rem)] max-w-full max-w-none may mb-0 mb-vsp-2xs mb-vsp-lg mb-vsp-md mb-vsp-sm mb-vsp-xl mb-vsp-xs measures measuring mechanism menu merged mermaid message messages meta metadata min-h-[60vh] min-h-[calc(100vh-3.5rem)] min-h-screen min-w-0 min-w-[10rem] min-w-[8rem] mirror mirrors missing ml-auto ml-hsp-2xl ml-hsp-lg ml-hsp-sm ml-hsp-xl mod mode mounted mouseenter mouseleave mr-hsp-sm mt-0 mt-vsp-2xl mt-vsp-2xs mt-vsp-3xs mt-vsp-lg mt-vsp-md mt-vsp-sm mt-vsp-xl must mutates mutation mutations mx-auto my-vsp-lg my-vsp-md name named native nav nav-card- navigating navigation navigations near needs new newly-swapped next no no-enlarge no-op no-repeat no-underline node node:buffer node:fs node:fs/promises node:module node:path nodes nofollow noindex non-empty non-persisted non-string none noopener noreferrer normal not not-object note now null number numeric object object-contain observe observer occurred of off og:description og:image og:image:alt og:image:height og:image:width og:title og:type og:url ol old older on once one only opacity-60 open open/close option or original other others out outline-none over overflow overflow-auto overflow-hidden overflow-x-auto overflow-y-auto overflow-y:auto overwrite own p p-0 p-hsp-lg p-hsp-md p-hsp-sm p-hsp-xl package package-owned packages padding page page-loading page-loading-overlay page-loading-spinner page-navigate-end pages pages/. paint pan panel panels parent parse parsed pass passed path paths pattern pb-[50vh] pb-vsp-md pb-vsp-xl pb-vsp-xs per per-call per-link permanently persisted pi pick picked picks picocolors pins pipelines pl-[1.25rem] pl-hsp-lg pl-hsp-sm pl-hsp-xl place placeholder placeholder:text-muted plain plural plus pnpm pointer-events-none pointercancel pointerdown pointermove pointerup polite polygon polyline populates port position position:fixed pr-[4px] pr-hsp-lg pr-hsp-md pr-hsp-sm pr-hsp-xl pre pre-lowercased preact preact/compat preact/hooks preact/jsx-runtime preload pres preserved produce produced produces production project propagating properties property props provided proxy pt-[0.15rem] pt-[2px] pt-vsp-3xs pt-vsp-md pt-vsp-sm pt-vsp-xl pt-vsp-xs ptag- public purely px px-hsp-2xl px-hsp-2xs px-hsp-lg px-hsp-md px-hsp-sm px-hsp-xl px-hsp-xs py-0 py-[2px] py-[calc(var(--spacing-vsp-xs)+0.15rem)] py-hsp-2xs py-hsp-sm py-hsp-xs py-vsp-2xs py-vsp-3xs py-vsp-lg py-vsp-md py-vsp-sm py-vsp-xl py-vsp-xs q query question r raw re-encode/decode re-lowercase re-querying re-render re-renders re-run re-running re-selects reach reached reaches read reading reads ready real real-value recorded recovers references refetch refreshes regenerate regenerates reinit reinits relative reload remains remove removed render rendered renders reorder repaint repeated repeating replaced replaces repopulate requires reserved resize resize-x resolve resolved resolves response restore restores result result-click results results-area retry return returns revision revisions rewrite right- right-0 ro robots role root rotate-180 rotate-90 round round-trip rounded rounded-[0.75rem] rounded-bl-[0.25rem] rounded-bl-[1rem] rounded-br-[0.25rem] rounded-br-[1rem] rounded-full rounded-lg rounded-t-[1rem] route router routes routes-src running runs runtime s safe safer same same-locale samp scanned schema-mismatch schema-missing scheme score scored script script-eval script-evaluation script-injection scripts scroll scrollbar scrolled scrollend search search-index searched section section- see sel-bg sel-fg select select-none self self-start sentinel separator server server-rendered set sets setup shadow-[0_1px_3px_color-mix(in_srgb,var(--color-fg)_8%,transparent)] shadow-lg shared shiki ship ships short shortcut should show shown shrink-0 sidebar sidebar- sidebar-toggle-island sidebar-tree-island signal similarity single singular site-search site-tree-nav-island sitemap- sites size skill skills skipping skips slash slug sm:border sm:border-muted sm:flex-row sm:grid-cols-2 sm:h-auto sm:items-center sm:justify-between sm:max-h-[80vh] sm:max-w-[52rem] sm:mx-auto sm:my-[10vh] sm:rounded-lg small smooth snapshot snapshots so soft soft-nav solid some somehow source sources space-y-vsp-2xs spacing span spans spec specifier specifiers sr-only src stale start state status stay sticky still stop stored stray string strings strip stroke-linecap stroke-linejoin stroke-width strong style style-attribute styles stylesheet sub subagents subsequent success successful summary sup support survives svg swap swapped swaps synchronous synchronously syntactically syntect t tab tab-item tab-panel tabindex table tablist tabpanel tabs tabs-container tabs-content tabs-nav tag tag- tag-item- tags tags:audit tbody td temp temp-element template temporary temporary-element terminal terms test-results text text-accent text-bg text-body text-caption text-center text-chat-assistant-text text-chat-user-text text-code-fg text-danger text-display text-fg text-heading text-info text-left text-micro text-muted text-muted/50 text-right text-small text-title text-warning text/plain textarea tfoot th that the thead their them theme theme-color theme-toggle theme/token then there these they this through throw time tip title to toggle toggle-ai-chat toggle-design-token-panel toggles token tokens tolerates too toolbar top-0 top-[3.5rem] top-full top-level total touches tp tr tracked tracking-wider trade-off transition transition-[background,color,border-color] transition-[left,color] transition-colors transition-transform translate-x-0 translations transparent treats tree tree-child- tree-item- tree-top- trick trigger trigger:ai-chat trigger:design-token-panel triggers true truncate truncated try turn twitter:card twitter:creator twitter:description twitter:image twitter:site twitter:title two type u ul unavailable unchanged undefined under underline understand unknown unmaintained unobserve unreadable unrelated unreleased unreliable unset unsupported up uppercase usage use used user uses utf-8 utf8 utilities v v2 val value value-reader values var variable version version- version-menu version-switcher vertical via video viewport virtual:zudo-doc-route-context visible vitesse-dark vocabulary w w-1/2 w-[0.5rem] w-[0.625rem] w-[0.875rem] w-[1.125rem] w-[1.575rem] w-[1.5rem] w-[1.75rem] w-[14px] w-[16px] w-[16rem] w-[18px] w-[280px] w-[2rem] w-[320px] w-[90vw] w-[var(--zd-sidebar-w)] w-dvw w-full w-icon-lg w-icon-md w-icon-sm w-icon-xs want warning was watching wbr wbr- we website went were what when where whereas whether which while whitespace-nowrap whitespace-pre whole will with without word working worktrees would wrap wrapper wrappers written wrong wrote xl:flex xl:hidden y-scrollbar yet you your z-dropdown z-local-1 z-modal z-modal-backdrop z-sidebar z-toolbar zd-content zd-desktop-sidebar-toggle zd-doc-content-band zd-enlarge-btn zd-enlarge-dialog zd-enlarge-dialog-close zd-enlargeable zd-html-preview-code zd-mermaid-dialog zd-mermaid-enlargeable zd-mermaid-tool-btn zd-mermaid-toolbar zd-mermaid-transform zd-mermaid-viewport zd-sidebar-content-wrapper zd-sidebar-open zfb zfb:after-swap zfb:before-preparation zod zoom zudo-doc-design-tokens/v1 zudo-doc-sidebar-visible zudo-doc-sidebar-width zudo-doc-theme zudo-doc-theme-bridge");
|
package/dist/settings.d.ts
CHANGED
|
@@ -254,17 +254,19 @@ export interface Settings {
|
|
|
254
254
|
headerRightItems: HeaderRightItem[];
|
|
255
255
|
/**
|
|
256
256
|
* Build-time package-owned route injection (epic Package-First Finale #2356,
|
|
257
|
-
* ADR `docs/adr/route-injection-seam.md`). When `true
|
|
258
|
-
* `@takazudo/zudo-doc/plugins/routes`
|
|
259
|
-
* from the package instead of requiring
|
|
257
|
+
* ADR `docs/adr/route-injection-seam.md`). When `true` (the **default** when
|
|
258
|
+
* omitted — #2404), the preset adds the `@takazudo/zudo-doc/plugins/routes`
|
|
259
|
+
* plugin, which injects the doc routes from the package instead of requiring
|
|
260
|
+
* project-shipped `pages/*.tsx` stubs.
|
|
260
261
|
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
* `
|
|
267
|
-
*
|
|
262
|
+
* Set explicitly to `false` only if your project ships its own `pages/*.tsx`
|
|
263
|
+
* stubs for every doc route. Any injected route whose URL shape collides with
|
|
264
|
+
* a kept `pages/` stub is silently dropped (user `pages/` wins), so existing
|
|
265
|
+
* stubs are a harmless no-op if you later re-enable this.
|
|
266
|
+
*
|
|
267
|
+
* When `false` AND doc content is configured (`docsDir` non-empty and/or
|
|
268
|
+
* locales/versions set), a single `console.warn` is emitted per build to
|
|
269
|
+
* flag a potentially-empty build (#2404). No throw — the build succeeds.
|
|
268
270
|
*/
|
|
269
271
|
packageOwnedRoutes?: boolean;
|
|
270
272
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@takazudo/zudo-doc",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "zudo-doc framework primitives layer that sits on top of zfb's engine — sidebar, theme, TOC, breadcrumb, layouts, head injection, View Transitions, SSR-skip wrappers (per ADR-003).",
|
|
6
6
|
"license": "MIT",
|
|
@@ -392,6 +392,10 @@
|
|
|
392
392
|
"types": "./dist/doc-body-end/index.d.ts",
|
|
393
393
|
"default": "./dist/doc-body-end/index.js"
|
|
394
394
|
},
|
|
395
|
+
"./doc-body-end-islands": {
|
|
396
|
+
"types": "./dist/doc-body-end-islands/index.d.ts",
|
|
397
|
+
"default": "./dist/doc-body-end-islands/index.js"
|
|
398
|
+
},
|
|
395
399
|
"./doc-history-area": {
|
|
396
400
|
"types": "./dist/doc-history-area/index.d.ts",
|
|
397
401
|
"default": "./dist/doc-history-area/index.js"
|
|
@@ -511,9 +515,9 @@
|
|
|
511
515
|
],
|
|
512
516
|
"peerDependencies": {
|
|
513
517
|
"preact": "^10.29.1",
|
|
514
|
-
"@takazudo/zfb": "^0.1.0-next.
|
|
515
|
-
"@takazudo/zfb-runtime": "^0.1.0-next.
|
|
516
|
-
"@takazudo/zudo-doc-history-server": "^1.0
|
|
518
|
+
"@takazudo/zfb": "^0.1.0-next.69",
|
|
519
|
+
"@takazudo/zfb-runtime": "^0.1.0-next.69",
|
|
520
|
+
"@takazudo/zudo-doc-history-server": "^1.1.0",
|
|
517
521
|
"@takazudo/zdtp": "^0.3.3",
|
|
518
522
|
"shiki": "^4.0.2",
|
|
519
523
|
"zod": "^4.3.6",
|
|
@@ -555,8 +559,8 @@
|
|
|
555
559
|
"typescript": "^5.0.0",
|
|
556
560
|
"vitest": "^4.1.0",
|
|
557
561
|
"zod": "^4.3.6",
|
|
558
|
-
"@takazudo/zfb": "0.1.0-next.
|
|
559
|
-
"@takazudo/zfb-runtime": "0.1.0-next.
|
|
562
|
+
"@takazudo/zfb": "0.1.0-next.69",
|
|
563
|
+
"@takazudo/zfb-runtime": "0.1.0-next.69"
|
|
560
564
|
},
|
|
561
565
|
"scripts": {
|
|
562
566
|
"build": "tsup && tsc -p tsconfig.build.json",
|
package/routes-src/404.tsx
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
HeadWithDefaults,
|
|
11
11
|
HeaderWithDefaults,
|
|
12
12
|
FooterWithDefaults,
|
|
13
|
-
|
|
13
|
+
BodyEndIslands,
|
|
14
14
|
composeMetaTitle,
|
|
15
15
|
} from "./_chrome.js";
|
|
16
16
|
|
|
@@ -31,7 +31,7 @@ export default function NotFoundPage(): JSX.Element {
|
|
|
31
31
|
sidebarOverride={<></>}
|
|
32
32
|
headerOverride={<HeaderWithDefaults lang={locale} />}
|
|
33
33
|
footerOverride={<FooterWithDefaults lang={locale} />}
|
|
34
|
-
bodyEndComponents={<
|
|
34
|
+
bodyEndComponents={<BodyEndIslands basePath={settings.base ?? "/"} />}
|
|
35
35
|
enableClientRouter={settings.dynamicPageTransition}
|
|
36
36
|
>
|
|
37
37
|
<div class="min-h-[60vh] flex flex-col items-center justify-center px-hsp-2xl py-vsp-xl">
|
package/routes-src/_chrome.tsx
CHANGED
|
@@ -52,6 +52,7 @@ import {
|
|
|
52
52
|
firstRoutedHref,
|
|
53
53
|
collectTags,
|
|
54
54
|
stableDocs,
|
|
55
|
+
colorSchemes,
|
|
55
56
|
} from "./_context.js";
|
|
56
57
|
import type { CategoryMeta, DocNavNode } from "./_docs-helpers.js";
|
|
57
58
|
|
|
@@ -67,6 +68,7 @@ import { createFooterWithDefaults } from "@takazudo/zudo-doc/footer-with-default
|
|
|
67
68
|
import { createSidebarWithDefaults } from "@takazudo/zudo-doc/sidebar-with-defaults";
|
|
68
69
|
import { createSidebarPrepaint } from "@takazudo/zudo-doc/sidebar-prepaint";
|
|
69
70
|
import { createDocBodyEnd } from "@takazudo/zudo-doc/doc-body-end";
|
|
71
|
+
import { createBodyEndIslands } from "@takazudo/zudo-doc/doc-body-end-islands";
|
|
70
72
|
import { createDocPager } from "@takazudo/zudo-doc/doc-pager";
|
|
71
73
|
import { createDocPageShell } from "@takazudo/zudo-doc/doc-page-shell";
|
|
72
74
|
import { createDocContentHeader } from "@takazudo/zudo-doc/doc-content-header";
|
|
@@ -128,12 +130,12 @@ const docHistoryMeta: Record<string, never> = {};
|
|
|
128
130
|
* tree. The project `sidebars` config is host-bound (A2). */
|
|
129
131
|
const sidebarsConfig: Record<string, never> = {};
|
|
130
132
|
|
|
131
|
-
/** Package
|
|
132
|
-
*
|
|
133
|
-
* the
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
133
|
+
/** Package-default body-end islands — the package-island subset of the host's
|
|
134
|
+
* `BodyEndIslands` (AiChatModal / ImageEnlarge / MermaidEnlarge), reconstructed
|
|
135
|
+
* from the serializable virtual-module `settings` flags (#2406 / #2401(c)).
|
|
136
|
+
* The host-owned bootstraps (client-router / design-token-panel) cannot live
|
|
137
|
+
* in the package, so they are NOT included here — A2/S4 re-homes those. */
|
|
138
|
+
const BodyEndIslands = createBodyEndIslands({ settings });
|
|
137
139
|
|
|
138
140
|
/** Package no-op DocHistory island stub — renders an empty fragment (the
|
|
139
141
|
* `DocHistoryComponent` contract requires a VNode, not null). */
|
|
@@ -162,14 +164,38 @@ function SearchWidgetBound(props: {
|
|
|
162
164
|
|
|
163
165
|
export const composeMetaTitle = createComposeMetaTitle(settings.siteName);
|
|
164
166
|
|
|
167
|
+
// Scheme-selection: resolve the active color scheme(s) from the host
|
|
168
|
+
// `colorSchemes` map supplied via the virtual module. Falls back to
|
|
169
|
+
// `DEFAULT_SCHEME` for any missing key or when `colorSchemes` is absent.
|
|
170
|
+
// `generateCssCustomProperties` is called in single-scheme mode
|
|
171
|
+
// (`settings.colorMode` is false); `generateLightDarkCssProperties` in
|
|
172
|
+
// light/dark mode. Both delegate to DEFAULT_SCHEME when `colorSchemes` is null.
|
|
173
|
+
function resolveHostScheme(key: string): ColorScheme {
|
|
174
|
+
if (!colorSchemes) return DEFAULT_SCHEME;
|
|
175
|
+
return colorSchemes[key] ?? DEFAULT_SCHEME;
|
|
176
|
+
}
|
|
177
|
+
|
|
165
178
|
export const HeadWithDefaults = createHeadWithDefaults({
|
|
166
179
|
settings,
|
|
167
180
|
composeMetaTitle,
|
|
168
181
|
withBase,
|
|
169
182
|
absoluteUrl,
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
183
|
+
// Called only in single-scheme mode (colorMode false): resolve via settings.colorScheme.
|
|
184
|
+
generateCssCustomProperties: () =>
|
|
185
|
+
generateCssCustomProperties(resolveHostScheme(settings.colorScheme)),
|
|
186
|
+
// Called only in light/dark mode (colorMode truthy): resolve the pair.
|
|
187
|
+
generateLightDarkCssProperties: () => {
|
|
188
|
+
const cm = settings.colorMode;
|
|
189
|
+
if (cm) {
|
|
190
|
+
return generateLightDarkCssProperties(
|
|
191
|
+
resolveHostScheme(cm.lightScheme),
|
|
192
|
+
resolveHostScheme(cm.darkScheme),
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
// Should not be reached (head-with-defaults only calls this when colorMode
|
|
196
|
+
// is truthy), but guard the contract by falling back to DEFAULT_SCHEME.
|
|
197
|
+
return generateLightDarkCssProperties(DEFAULT_SCHEME, DEFAULT_SCHEME);
|
|
198
|
+
},
|
|
173
199
|
});
|
|
174
200
|
|
|
175
201
|
// ---------------------------------------------------------------------------
|
|
@@ -272,7 +298,7 @@ export const SidebarWithDefaults = createSidebarWithDefaults({
|
|
|
272
298
|
});
|
|
273
299
|
|
|
274
300
|
const SidebarPrepaint = createSidebarPrepaint({ sidebarToggle: settings.sidebarToggle });
|
|
275
|
-
const DocBodyEnd = createDocBodyEnd({ settings, BodyEndIslands
|
|
301
|
+
const DocBodyEnd = createDocBodyEnd({ settings, BodyEndIslands });
|
|
276
302
|
const DocPager = createDocPager({ t });
|
|
277
303
|
|
|
278
304
|
// ---------------------------------------------------------------------------
|
|
@@ -495,7 +521,7 @@ export const VersionsPageView = createVersionsPageView({
|
|
|
495
521
|
HeadWithDefaults,
|
|
496
522
|
HeaderWithDefaults,
|
|
497
523
|
FooterWithDefaults,
|
|
498
|
-
BodyEndIslands
|
|
524
|
+
BodyEndIslands,
|
|
499
525
|
},
|
|
500
526
|
});
|
|
501
527
|
|
|
@@ -513,15 +539,16 @@ const tagPages = createTagPages({
|
|
|
513
539
|
HeadWithDefaults,
|
|
514
540
|
HeaderWithDefaults,
|
|
515
541
|
FooterWithDefaults,
|
|
516
|
-
BodyEndIslands
|
|
542
|
+
BodyEndIslands,
|
|
517
543
|
DocHistoryArea: DocHistoryArea as never,
|
|
518
544
|
},
|
|
519
545
|
});
|
|
520
546
|
|
|
521
547
|
export const { collectTagMapForLocale, TagDetailPageView, TagsIndexPageView } = tagPages;
|
|
522
548
|
|
|
523
|
-
// Re-export the locale-aware site-tree wrapper
|
|
524
|
-
|
|
549
|
+
// Re-export the locale-aware site-tree wrapper + the package-default body-end
|
|
550
|
+
// islands for the index entrypoints.
|
|
551
|
+
export { SiteTreeNavWrapper, BodyEndIslands };
|
|
525
552
|
|
|
526
553
|
// Bring the doc-route-entries builder + types into the chrome surface so the
|
|
527
554
|
// doc entrypoints import a single module.
|
package/routes-src/_context.ts
CHANGED
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
import { routeContext } from "virtual:zudo-doc-route-context";
|
|
35
35
|
|
|
36
36
|
import type { Settings } from "@takazudo/zudo-doc/settings";
|
|
37
|
+
import type { ColorScheme } from "@takazudo/zudo-doc/color-scheme-utils";
|
|
37
38
|
import type { FactoryI18n } from "@takazudo/zudo-doc/factory-context";
|
|
38
39
|
import { makeUrlHelpers, type UrlHelpers } from "@takazudo/zudo-doc/url-helpers";
|
|
39
40
|
import {
|
|
@@ -84,6 +85,7 @@ export interface RouteContextPayload {
|
|
|
84
85
|
settings: Settings;
|
|
85
86
|
translations: Record<string, Record<string, string>>;
|
|
86
87
|
tagVocabulary: readonly TagVocabularyEntry[];
|
|
88
|
+
colorSchemes: Record<string, ColorScheme> | null;
|
|
87
89
|
}
|
|
88
90
|
|
|
89
91
|
/** The serializable route-context (from the virtual module). */
|
|
@@ -91,6 +93,9 @@ export const ctx = routeContext as unknown as RouteContextPayload;
|
|
|
91
93
|
export const settings: Settings = ctx.settings;
|
|
92
94
|
const translations = ctx.translations;
|
|
93
95
|
const tagVocabulary = ctx.tagVocabulary;
|
|
96
|
+
/** Host color-scheme palette map. `null` when not supplied — `_chrome.tsx`
|
|
97
|
+
* falls back to `DEFAULT_SCHEME` in that case. */
|
|
98
|
+
export const colorSchemes: Record<string, ColorScheme> | null = ctx.colorSchemes;
|
|
94
99
|
|
|
95
100
|
// ---------------------------------------------------------------------------
|
|
96
101
|
// i18n — reconstruct a FactoryI18n from settings + translations (Decision 1).
|
package/routes-src/_virtual.d.ts
CHANGED
|
@@ -4,12 +4,16 @@
|
|
|
4
4
|
// — so this declaration gives the package route entrypoints a typed import.
|
|
5
5
|
//
|
|
6
6
|
// The payload is SERIALIZABLE DATA ONLY (ADR Decision 1): `settings`,
|
|
7
|
-
// `translations`, `tagVocabulary`. `_context.ts` narrows it
|
|
8
|
-
// `RouteContextPayload` at the seam.
|
|
7
|
+
// `translations`, `tagVocabulary`, `colorSchemes`. `_context.ts` narrows it
|
|
8
|
+
// to the concrete `RouteContextPayload` at the seam.
|
|
9
9
|
declare module "virtual:zudo-doc-route-context" {
|
|
10
10
|
export const routeContext: {
|
|
11
11
|
settings: unknown;
|
|
12
12
|
translations: Record<string, Record<string, string>>;
|
|
13
13
|
tagVocabulary: ReadonlyArray<Record<string, unknown>>;
|
|
14
|
+
/** Host color-scheme palette map. `null` when the caller did not pass
|
|
15
|
+
* `colorSchemes` to `zudoDocPreset` — `_chrome.tsx` falls back to
|
|
16
|
+
* `DEFAULT_SCHEME` in that case. */
|
|
17
|
+
colorSchemes: Record<string, unknown> | null;
|
|
14
18
|
};
|
|
15
19
|
}
|
package/routes-src/index.tsx
CHANGED
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
HeadWithDefaults,
|
|
29
29
|
HeaderWithDefaults,
|
|
30
30
|
FooterWithDefaults,
|
|
31
|
-
|
|
31
|
+
BodyEndIslands,
|
|
32
32
|
composeMetaTitle,
|
|
33
33
|
} from "./_chrome.js";
|
|
34
34
|
|
|
@@ -67,7 +67,7 @@ export default function IndexPage(): JSX.Element {
|
|
|
67
67
|
sidebarOverride={<></>}
|
|
68
68
|
headerOverride={<HeaderWithDefaults lang={locale} currentPath={withBase("/")} />}
|
|
69
69
|
footerOverride={<FooterWithDefaults lang={locale} />}
|
|
70
|
-
bodyEndComponents={<
|
|
70
|
+
bodyEndComponents={<BodyEndIslands basePath={settings.base ?? "/"} />}
|
|
71
71
|
enableClientRouter={settings.dynamicPageTransition}
|
|
72
72
|
>
|
|
73
73
|
<div class="flex justify-center mb-vsp-xl">
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
HeadWithDefaults,
|
|
29
29
|
HeaderWithDefaults,
|
|
30
30
|
FooterWithDefaults,
|
|
31
|
-
|
|
31
|
+
BodyEndIslands,
|
|
32
32
|
composeMetaTitle,
|
|
33
33
|
} from "./_chrome.js";
|
|
34
34
|
|
|
@@ -83,7 +83,7 @@ export default function LocaleIndexPage({ params }: PageArgs): JSX.Element {
|
|
|
83
83
|
sidebarOverride={<></>}
|
|
84
84
|
headerOverride={<HeaderWithDefaults lang={locale} currentPath={withBase(`/${locale}/`)} />}
|
|
85
85
|
footerOverride={<FooterWithDefaults lang={locale} />}
|
|
86
|
-
bodyEndComponents={<
|
|
86
|
+
bodyEndComponents={<BodyEndIslands basePath={settings.base ?? "/"} />}
|
|
87
87
|
enableClientRouter={settings.dynamicPageTransition}
|
|
88
88
|
>
|
|
89
89
|
<div class="flex justify-center mb-vsp-xl">
|