create-zudo-doc 0.2.8 → 0.2.10
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/compose.d.ts +6 -0
- package/dist/compose.js +7 -0
- package/dist/features/design-token-panel.d.ts +8 -6
- package/dist/features/design-token-panel.js +81 -6
- package/dist/features/image-enlarge.d.ts +1 -1
- package/dist/features/image-enlarge.js +6 -4
- package/dist/scaffold.js +58 -12
- package/dist/settings-gen.js +10 -3
- package/package.json +1 -1
- package/templates/base/pages/lib/_body-end-islands.tsx +28 -68
- package/templates/base/src/components/mermaid-enlarge.tsx +490 -0
- package/templates/base/src/config/color-schemes.ts +6 -5
- package/templates/base/src/config/settings-types.ts +3 -1
- package/templates/base/src/styles/global.css +152 -425
- package/templates/base/src/components/design-token-panel-bootstrap.tsx +0 -15
- package/templates/base/src/utils/header-right-items.ts +0 -38
package/dist/compose.d.ts
CHANGED
|
@@ -80,6 +80,12 @@ export declare function validateDependencies(features: FeatureDefinition[], allS
|
|
|
80
80
|
* `p:` map entry) when imageEnlarge is enabled.
|
|
81
81
|
* - `pages/lib/_body-end-islands.tsx` — tauri.ts injects the FindInPageInit
|
|
82
82
|
* island (import, displayName, Island mount) when tauri is enabled.
|
|
83
|
+
* design-token-panel.ts injects the DesignTokenPanelBootstrap island
|
|
84
|
+
* (import, displayName, Island mount + toggle shim) when designTokenPanel
|
|
85
|
+
* is enabled.
|
|
86
|
+
* - `src/config/settings-types.ts` — design-token-panel.ts injects the
|
|
87
|
+
* `"design-token-panel"` member into `HeaderRightTriggerName` when the
|
|
88
|
+
* feature is enabled (replace-range between the :start/:end anchors).
|
|
83
89
|
*/
|
|
84
90
|
export declare const ANCHOR_FILES: string[];
|
|
85
91
|
/**
|
package/dist/compose.js
CHANGED
|
@@ -166,11 +166,18 @@ export function validateDependencies(features, allSelectedNames) {
|
|
|
166
166
|
* `p:` map entry) when imageEnlarge is enabled.
|
|
167
167
|
* - `pages/lib/_body-end-islands.tsx` — tauri.ts injects the FindInPageInit
|
|
168
168
|
* island (import, displayName, Island mount) when tauri is enabled.
|
|
169
|
+
* design-token-panel.ts injects the DesignTokenPanelBootstrap island
|
|
170
|
+
* (import, displayName, Island mount + toggle shim) when designTokenPanel
|
|
171
|
+
* is enabled.
|
|
172
|
+
* - `src/config/settings-types.ts` — design-token-panel.ts injects the
|
|
173
|
+
* `"design-token-panel"` member into `HeaderRightTriggerName` when the
|
|
174
|
+
* feature is enabled (replace-range between the :start/:end anchors).
|
|
169
175
|
*/
|
|
170
176
|
export const ANCHOR_FILES = [
|
|
171
177
|
"src/styles/global.css",
|
|
172
178
|
"pages/_mdx-components.ts",
|
|
173
179
|
"pages/lib/_body-end-islands.tsx",
|
|
180
|
+
"src/config/settings-types.ts",
|
|
174
181
|
];
|
|
175
182
|
/**
|
|
176
183
|
* Main composition entry point. Orchestrates the full feature composition
|
|
@@ -2,11 +2,13 @@ import type { FeatureModule } from "../compose.js";
|
|
|
2
2
|
/**
|
|
3
3
|
* Design-token-panel (zdtp) feature.
|
|
4
4
|
*
|
|
5
|
-
* Injects
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
5
|
+
* Injects:
|
|
6
|
+
* 1. The zdtp CSS @import at `@slot:global-css:feature-styles` in
|
|
7
|
+
* `src/styles/global.css`.
|
|
8
|
+
* 2. The DesignTokenPanelBootstrap import, displayName, and Island mount
|
|
9
|
+
* (with pre-hydration toggle shim) into
|
|
10
|
+
* `pages/lib/_body-end-islands.tsx` via the three @slot: anchors
|
|
11
|
+
* (imports / display-names / extra-islands). Mirrors the tauri feature
|
|
12
|
+
* injection shape (zudolab/zudo-doc#2162).
|
|
11
13
|
*/
|
|
12
14
|
export declare const designTokenPanelFeature: FeatureModule;
|
|
@@ -1,12 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-hydration toggle shim for the zdtp panel (inline, minified).
|
|
3
|
+
*
|
|
4
|
+
* Emitted as a <script dangerouslySetInnerHTML> alongside the
|
|
5
|
+
* DesignTokenPanelBootstrap Island so the header palette button is
|
|
6
|
+
* responsive before the island hydrates. Records the first click as a
|
|
7
|
+
* boolean flag and exposes window.__zdtpReadyClicks so the bootstrap
|
|
8
|
+
* module can drain and re-dispatch once the real zdtp listener is live.
|
|
9
|
+
* Guards against double-installation across SPA body swaps via
|
|
10
|
+
* __zdtpToggleShimInstalled. Mirrors the host's ZDTP_TOGGLE_SHIM_SRC
|
|
11
|
+
* constant (pages/lib/_body-end-islands.tsx, zudolab/zudo-doc#1627 Part B).
|
|
12
|
+
*/
|
|
13
|
+
const ZDTP_TOGGLE_SHIM_SRC = `(function(){
|
|
14
|
+
if(window.__zdtpToggleShimInstalled)return;
|
|
15
|
+
window.__zdtpToggleShimInstalled=true;
|
|
16
|
+
var pending=false;
|
|
17
|
+
function shim(){pending=true;}
|
|
18
|
+
window.addEventListener('toggle-design-token-panel',shim);
|
|
19
|
+
window.__zdtpReadyClicks=function(){
|
|
20
|
+
window.removeEventListener('toggle-design-token-panel',shim);
|
|
21
|
+
delete window.__zdtpReadyClicks;
|
|
22
|
+
if(pending){pending=false;window.dispatchEvent(new CustomEvent('toggle-design-token-panel'));}
|
|
23
|
+
};
|
|
24
|
+
})();`;
|
|
1
25
|
/**
|
|
2
26
|
* Design-token-panel (zdtp) feature.
|
|
3
27
|
*
|
|
4
|
-
* Injects
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
28
|
+
* Injects:
|
|
29
|
+
* 1. The zdtp CSS @import at `@slot:global-css:feature-styles` in
|
|
30
|
+
* `src/styles/global.css`.
|
|
31
|
+
* 2. The DesignTokenPanelBootstrap import, displayName, and Island mount
|
|
32
|
+
* (with pre-hydration toggle shim) into
|
|
33
|
+
* `pages/lib/_body-end-islands.tsx` via the three @slot: anchors
|
|
34
|
+
* (imports / display-names / extra-islands). Mirrors the tauri feature
|
|
35
|
+
* injection shape (zudolab/zudo-doc#2162).
|
|
10
36
|
*/
|
|
11
37
|
export const designTokenPanelFeature = () => ({
|
|
12
38
|
name: "designTokenPanel",
|
|
@@ -21,5 +47,54 @@ export const designTokenPanelFeature = () => ({
|
|
|
21
47
|
anchor: "/* @slot:global-css:feature-styles */",
|
|
22
48
|
content: `@import "@takazudo/zdtp/styles.css";`,
|
|
23
49
|
},
|
|
50
|
+
// 1. Import the island entry. Inserted AFTER the
|
|
51
|
+
// `// @slot:body-end-islands:imports` anchor.
|
|
52
|
+
{
|
|
53
|
+
file: "pages/lib/_body-end-islands.tsx",
|
|
54
|
+
anchor: "// @slot:body-end-islands:imports",
|
|
55
|
+
position: "after",
|
|
56
|
+
content: `import DesignTokenPanelBootstrap from "@/components/design-token-panel-bootstrap";`,
|
|
57
|
+
},
|
|
58
|
+
// 2. Stable island marker name (belt-and-braces guard matching the
|
|
59
|
+
// sibling islands in the file). Inserted AFTER the
|
|
60
|
+
// `// @slot:body-end-islands:display-names` anchor.
|
|
61
|
+
{
|
|
62
|
+
file: "pages/lib/_body-end-islands.tsx",
|
|
63
|
+
anchor: "// @slot:body-end-islands:display-names",
|
|
64
|
+
position: "after",
|
|
65
|
+
content: `(DesignTokenPanelBootstrap as { displayName?: string }).displayName = "DesignTokenPanelBootstrap";`,
|
|
66
|
+
},
|
|
67
|
+
// 4. Extend HeaderRightTriggerName with "design-token-panel". Uses
|
|
68
|
+
// replace-range between the :start/:end anchors in settings-types.ts
|
|
69
|
+
// so the base template emits only "ai-chat" and this injection adds
|
|
70
|
+
// the zdtp trigger only when the feature is on (zudolab/zudo-doc#2162).
|
|
71
|
+
{
|
|
72
|
+
file: "src/config/settings-types.ts",
|
|
73
|
+
anchor: "// @slot:settings-types:trigger-names:start",
|
|
74
|
+
position: "replace",
|
|
75
|
+
content: `export type HeaderRightTriggerName = "design-token-panel" | "ai-chat";`,
|
|
76
|
+
},
|
|
77
|
+
// 3. Island mount + pre-hydration toggle shim. Inserted AFTER the
|
|
78
|
+
// `{/* @slot:body-end-islands:extra-islands */}` anchor.
|
|
79
|
+
// when="load" (not "idle"): the bootstrap module registers the
|
|
80
|
+
// `toggle-design-token-panel` window listener as a side effect of
|
|
81
|
+
// its import, so it must hydrate as early as possible (zudolab/zudo-doc#1623).
|
|
82
|
+
// The inline <script> is the pre-hydration shim (zudolab/zudo-doc#1627 Part B).
|
|
83
|
+
{
|
|
84
|
+
file: "pages/lib/_body-end-islands.tsx",
|
|
85
|
+
anchor: "{/* @slot:body-end-islands:extra-islands */}",
|
|
86
|
+
position: "after",
|
|
87
|
+
content: ` {/* zdtp panel bootstrap: hydrates on load so configurePanel() runs early
|
|
88
|
+
and the toggle-design-token-panel listener is live before the user
|
|
89
|
+
clicks the header trigger. The inline script is the pre-hydration
|
|
90
|
+
shim that queues the first click (zudolab/zudo-doc#1627 Part B). */}
|
|
91
|
+
<script
|
|
92
|
+
dangerouslySetInnerHTML={{ __html: ${JSON.stringify(ZDTP_TOGGLE_SHIM_SRC)} }}
|
|
93
|
+
/>
|
|
94
|
+
{Island({
|
|
95
|
+
when: "load",
|
|
96
|
+
children: <DesignTokenPanelBootstrap />,
|
|
97
|
+
}) as unknown as VNode}`,
|
|
98
|
+
},
|
|
24
99
|
],
|
|
25
100
|
});
|
|
@@ -12,7 +12,7 @@ import type { FeatureModule } from "../compose.js";
|
|
|
12
12
|
* feature, the server-side figure/button emission is re-implemented via an
|
|
13
13
|
* MDX paragraph (p) component override in pages/_mdx-components.ts. When
|
|
14
14
|
* imageEnlarge is enabled, three injections into the template file install:
|
|
15
|
-
* 1. Additional imports: toChildArray + VNode from preact
|
|
15
|
+
* 1. Additional imports: toChildArray + VNode from preact.
|
|
16
16
|
* 2. ENLARGE_SVG const + EnlargeableParagraph function definition.
|
|
17
17
|
* 3. `p: EnlargeableParagraph` entry in the createMdxComponents return map.
|
|
18
18
|
* When imageEnlarge is OFF, none of these are injected, so the override is
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* feature, the server-side figure/button emission is re-implemented via an
|
|
12
12
|
* MDX paragraph (p) component override in pages/_mdx-components.ts. When
|
|
13
13
|
* imageEnlarge is enabled, three injections into the template file install:
|
|
14
|
-
* 1. Additional imports: toChildArray + VNode from preact
|
|
14
|
+
* 1. Additional imports: toChildArray + VNode from preact.
|
|
15
15
|
* 2. ENLARGE_SVG const + EnlargeableParagraph function definition.
|
|
16
16
|
* 3. `p: EnlargeableParagraph` entry in the createMdxComponents return map.
|
|
17
17
|
* When imageEnlarge is OFF, none of these are injected, so the override is
|
|
@@ -21,15 +21,17 @@
|
|
|
21
21
|
export const imageEnlargeFeature = () => ({
|
|
22
22
|
name: "imageEnlarge",
|
|
23
23
|
injections: [
|
|
24
|
-
// 1. Import additions: toChildArray + VNode from preact
|
|
24
|
+
// 1. Import additions: toChildArray + VNode from preact.
|
|
25
25
|
// Inserted AFTER the `// @slot:mdx-components:enlarge-imports` anchor.
|
|
26
|
+
// NOTE: `settings` is NOT injected here — the base template already
|
|
27
|
+
// imports it (#2172); injecting it again caused a duplicate ES-module
|
|
28
|
+
// lexical binding.
|
|
26
29
|
{
|
|
27
30
|
file: "pages/_mdx-components.ts",
|
|
28
31
|
anchor: "// @slot:mdx-components:enlarge-imports",
|
|
29
32
|
position: "after",
|
|
30
33
|
content: `import { toChildArray } from "preact";
|
|
31
|
-
import type { VNode } from "preact"
|
|
32
|
-
import { settings } from "@/config/settings";`,
|
|
34
|
+
import type { VNode } from "preact";`,
|
|
33
35
|
},
|
|
34
36
|
// 2. ENLARGE_SVG const + EnlargeableParagraph function.
|
|
35
37
|
// Inserted AFTER the `// @slot:mdx-components:enlarge-defs` anchor
|
package/dist/scaffold.js
CHANGED
|
@@ -178,7 +178,7 @@ export async function scaffold(choices) {
|
|
|
178
178
|
await fs.outputFile(path.join(targetDir, "zfb.config.ts"), zfbConfigContent);
|
|
179
179
|
const pkg = generatePackageJson(choices);
|
|
180
180
|
await fs.outputFile(path.join(targetDir, "package.json"), JSON.stringify(pkg, null, 2) + "\n");
|
|
181
|
-
|
|
181
|
+
const gitignoreLines = [
|
|
182
182
|
"# Build output",
|
|
183
183
|
"node_modules",
|
|
184
184
|
"dist",
|
|
@@ -201,7 +201,34 @@ export async function scaffold(choices) {
|
|
|
201
201
|
"# Cloudflare Wrangler",
|
|
202
202
|
".wrangler/",
|
|
203
203
|
"",
|
|
204
|
-
]
|
|
204
|
+
];
|
|
205
|
+
// The doc-lookup skill is only generated when skillSymlinker is selected
|
|
206
|
+
// (the setup-doc-skill.sh script and `setup:doc-skill` npm script are gated
|
|
207
|
+
// on the same feature above), so only emit its ignore entries then —
|
|
208
|
+
// otherwise they would be dead rules that could silently hide an unrelated
|
|
209
|
+
// skill a user later installs under a matching name. The skill name is
|
|
210
|
+
// deterministic (always `<projectName>-wisdom`, matching DEFAULT_SKILL_NAME
|
|
211
|
+
// in scripts/setup-doc-skill.sh and the package name), so these entries match
|
|
212
|
+
// the directory the script creates. The docs-ja symlink only exists for i18n
|
|
213
|
+
// projects (the script creates it conditionally), so gate that line on i18n.
|
|
214
|
+
if (choices.features.includes("skillSymlinker")) {
|
|
215
|
+
gitignoreLines.push("# Generated doc-lookup skill", `.claude/skills/${choices.projectName}-wisdom/SKILL.md`, `.claude/skills/${choices.projectName}-wisdom/docs`);
|
|
216
|
+
if (choices.features.includes("i18n")) {
|
|
217
|
+
gitignoreLines.push(`.claude/skills/${choices.projectName}-wisdom/docs-ja`);
|
|
218
|
+
}
|
|
219
|
+
gitignoreLines.push("");
|
|
220
|
+
}
|
|
221
|
+
await fs.outputFile(path.join(targetDir, ".gitignore"), gitignoreLines.join("\n"));
|
|
222
|
+
// Emit an .npmrc exempting undici-types from pnpm's trust-downgrade policy.
|
|
223
|
+
// External pnpm supply-chain quirk (pnpm >= 10.21, https://github.com/pnpm/pnpm/issues/8889):
|
|
224
|
+
// when a consumer enables `trust-policy=no-downgrade` (off by default, but a
|
|
225
|
+
// common hardened posture), `pnpm install` aborts with ERR_PNPM_TRUST_DOWNGRADE
|
|
226
|
+
// on undici-types@6.21.0 — a transitive dep of @types/node@^22 whose earlier
|
|
227
|
+
// releases carried provenance attestation that 6.21.0 dropped. The package is a
|
|
228
|
+
// type-only stub and safe; this narrow exclusion lets a fresh scaffold install
|
|
229
|
+
// under a strict trust policy without disabling the guard wholesale. Pinned to
|
|
230
|
+
// the exact known-safe version so a future undici-types bump is re-reviewed.
|
|
231
|
+
await fs.outputFile(path.join(targetDir, ".npmrc"), "trust-policy-exclude[]=undici-types@6.21.0\n");
|
|
205
232
|
const claudeContent = generateCLAUDEFile(choices);
|
|
206
233
|
await fs.outputFile(path.join(targetDir, "CLAUDE.md"), claudeContent);
|
|
207
234
|
// 4. Compose features (copy feature files + inject into shared files)
|
|
@@ -290,21 +317,40 @@ function generatePackageJson(choices) {
|
|
|
290
317
|
// extraWatchPaths rebuilds, and TS-config-loader path canonicalization
|
|
291
318
|
// (Takazudo/zudo-front-builder#1036–#1043). next.45: docs-only. next.46:
|
|
292
319
|
// opt-in dev boot-lazy mode (#1057) + client-router timer lifecycle fixes —
|
|
293
|
-
// dev-server-only. next.47
|
|
294
|
-
//
|
|
295
|
-
//
|
|
296
|
-
//
|
|
297
|
-
//
|
|
298
|
-
|
|
299
|
-
|
|
320
|
+
// dev-server-only. next.47: dual light/dark syntect themes (themeLight/
|
|
321
|
+
// themeDark on CodeHighlightConfig, --shiki-light/--shiki-dark, #1067) plus
|
|
322
|
+
// stricter build-start validation that rejects unknown theme names. next.48:
|
|
323
|
+
// re-export @takazudo/zfb/config from the zfb-shim.d.ts type shim — type-only
|
|
324
|
+
// fix, additive. next.49: client-router WebKit bfcache fix —
|
|
325
|
+
// re-sync the history index + originalLocation on a bfcache restore so
|
|
326
|
+
// browser Back after an SPA navigation returns to the previous page instead
|
|
327
|
+
// of skipping an entry — runtime-only bug fix, additive. next.50 (current
|
|
328
|
+
// pin): client-router fix to commit the SPA history entry BEFORE the View
|
|
329
|
+
// Transition, so on WebKit/iOS a single browser Back after an SPA navigation
|
|
330
|
+
// creates a distinct history entry instead of falling off the site —
|
|
331
|
+
// runtime-only bug fix, additive. next.51 (current pin): additive public-API
|
|
332
|
+
// surface — VNode/VNodeArray/VNodeObject are now exported from
|
|
333
|
+
// "@takazudo/zfb" (#972) — plus removal of the no-op linkValidation.allowExternal
|
|
334
|
+
// knob (#925); both are non-breaking for a fresh scaffold. A fresh scaffold
|
|
335
|
+
// sets no explicit codeHighlight.theme so the default still applies. No
|
|
336
|
+
// consumer-facing / CLI breaking change.
|
|
337
|
+
"@takazudo/zfb": "0.1.0-next.51",
|
|
338
|
+
"@takazudo/zfb-runtime": "0.1.0-next.51",
|
|
300
339
|
// zfb-adapter-cloudflare — required for any route with `prerender = false`.
|
|
301
340
|
// Pinned in lockstep with @takazudo/zfb.
|
|
302
|
-
"@takazudo/zfb-adapter-cloudflare": "0.1.0-next.
|
|
341
|
+
"@takazudo/zfb-adapter-cloudflare": "0.1.0-next.51",
|
|
303
342
|
// @takazudo/zudo-doc — published from this monorepo via
|
|
304
343
|
// .github/workflows/publish-zudo-doc.yml. The pin here is bumped in
|
|
305
344
|
// lockstep by scripts/release-create-zudo-doc.sh whenever zudo-doc's
|
|
306
345
|
// version moves, so a fresh scaffold pulls the version we just published.
|
|
307
|
-
|
|
346
|
+
// RELEASE DEPENDENCY (zudolab/zudo-doc#2188): the base template's
|
|
347
|
+
// global.css now `@import`s `@takazudo/zudo-doc/content.css`, an export
|
|
348
|
+
// added alongside this pin. The pinned range MUST resolve to a PUBLISHED
|
|
349
|
+
// version that ships that export — published 0.2.9 does NOT. check-pin-parity
|
|
350
|
+
// ties this pin to packages/zudo-doc's version, so the lockstep release
|
|
351
|
+
// bumps both together; do not cut a create-zudo-doc release until the
|
|
352
|
+
// matching @takazudo/zudo-doc version (with content.css) is on npm.
|
|
353
|
+
"@takazudo/zudo-doc": "^0.2.10",
|
|
308
354
|
// zod — used by the generated zfb.config.ts. zfb-config-gen emits
|
|
309
355
|
// `import { z } from "zod"` for the content-collection schema +
|
|
310
356
|
// `z.toJSONSchema(...)` conversion. Without this dep, the consumer
|
|
@@ -359,7 +405,7 @@ function generatePackageJson(choices) {
|
|
|
359
405
|
// @takazudo/zudo-doc/integrations/doc-history which in turn imports
|
|
360
406
|
// @takazudo/zudo-doc-history-server/git-history. Without this dep the
|
|
361
407
|
// plugin host fails at init with ERR_MODULE_NOT_FOUND — W8A (#1739).
|
|
362
|
-
deps["@takazudo/zudo-doc-history-server"] = "^0.2.
|
|
408
|
+
deps["@takazudo/zudo-doc-history-server"] = "^0.2.10";
|
|
363
409
|
// W7A (#1736): doc-history-plugin.mjs spawns `tsx -e <inline-script>` to
|
|
364
410
|
// run the v2 runtime in a TS-aware Node subprocess; without tsx the
|
|
365
411
|
// plugin's preBuild step exits with ENOENT before zfb finishes config
|
package/dist/settings-gen.js
CHANGED
|
@@ -259,10 +259,17 @@ export function generateSettingsFile(choices) {
|
|
|
259
259
|
if (choices.headerRightItems !== undefined) {
|
|
260
260
|
// User-supplied override (including empty array): emit each entry verbatim,
|
|
261
261
|
// in the chosen order. An empty array means "no header-right items" — honor it.
|
|
262
|
-
//
|
|
263
|
-
//
|
|
264
|
-
//
|
|
262
|
+
// DEFENSIVE STRIP: drop any "design-token-panel" trigger when the
|
|
263
|
+
// designTokenPanel feature is off — the type "design-token-panel" is absent
|
|
264
|
+
// from HeaderRightTriggerName in a feature-off scaffold (gated via
|
|
265
|
+
// @slot:settings-types:trigger-names), so emitting it would cause a TS error
|
|
266
|
+
// (zudolab/zudo-doc#2162).
|
|
265
267
|
for (const item of choices.headerRightItems) {
|
|
268
|
+
if (item.type === "trigger" &&
|
|
269
|
+
item.trigger === "design-token-panel" &&
|
|
270
|
+
!choices.features.includes("designTokenPanel")) {
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
266
273
|
if (item.type === "trigger") {
|
|
267
274
|
lines.push(` { type: "trigger", trigger: ${JSON.stringify(item.trigger)} },`);
|
|
268
275
|
}
|
package/package.json
CHANGED
|
@@ -34,8 +34,8 @@ import { settings } from "@/config/settings";
|
|
|
34
34
|
|
|
35
35
|
import AiChatModal from "@/components/ai-chat-modal";
|
|
36
36
|
import ClientRouterBootstrap from "@/components/client-router-bootstrap";
|
|
37
|
-
import DesignTokenPanelBootstrap from "@/components/design-token-panel-bootstrap";
|
|
38
37
|
import ImageEnlarge, { ImageEnlargeSsrFallback } from "@/components/image-enlarge";
|
|
38
|
+
import MermaidEnlarge, { MermaidEnlargeSsrFallback } from "@/components/mermaid-enlarge";
|
|
39
39
|
import { PageLoadingOverlay } from "@takazudo/zudo-doc/page-loading";
|
|
40
40
|
// @slot:body-end-islands:imports
|
|
41
41
|
|
|
@@ -49,9 +49,8 @@ import { PageLoadingOverlay } from "@takazudo/zudo-doc/page-loading";
|
|
|
49
49
|
(AiChatModal as { displayName?: string }).displayName = "AiChatModal";
|
|
50
50
|
(ClientRouterBootstrap as { displayName?: string }).displayName =
|
|
51
51
|
"ClientRouterBootstrap";
|
|
52
|
-
(DesignTokenPanelBootstrap as { displayName?: string }).displayName =
|
|
53
|
-
"DesignTokenPanelBootstrap";
|
|
54
52
|
(ImageEnlarge as { displayName?: string }).displayName = "ImageEnlarge";
|
|
53
|
+
(MermaidEnlarge as { displayName?: string }).displayName = "MermaidEnlarge";
|
|
55
54
|
// @slot:body-end-islands:display-names
|
|
56
55
|
|
|
57
56
|
/**
|
|
@@ -64,37 +63,6 @@ import { PageLoadingOverlay } from "@takazudo/zudo-doc/page-loading";
|
|
|
64
63
|
*/
|
|
65
64
|
const DEFAULT_AI_CHAT_BODY_LABEL = "Ask a question about the documentation.";
|
|
66
65
|
|
|
67
|
-
/**
|
|
68
|
-
* SSR-emitted inline script that acts as a pre-hydration shim for the
|
|
69
|
-
* `toggle-design-token-panel` window event. Because the
|
|
70
|
-
* DesignTokenPanelBootstrap Island is deferred, zdtp's real
|
|
71
|
-
* `toggle-design-token-panel` listener (registered in index.tsx at
|
|
72
|
-
* module init) is not yet installed when the user clicks the header
|
|
73
|
-
* palette button. This shim:
|
|
74
|
-
*
|
|
75
|
-
* 1. Records the first (and only meaningful) click as a boolean flag.
|
|
76
|
-
* 2. Exposes `window.__zdtpReadyClicks` so the bootstrap Island can
|
|
77
|
-
* drain the queue and re-dispatch a single event once the real
|
|
78
|
-
* listener is live.
|
|
79
|
-
* 3. Guards against double-installation across any re-evaluation path
|
|
80
|
-
* (SPA body swap, HMR, etc.) via `__zdtpToggleShimInstalled`.
|
|
81
|
-
*
|
|
82
|
-
* A single boolean (not an array) is used because the panel is a toggle —
|
|
83
|
-
* any number of pre-hydration clicks should result in at most one open.
|
|
84
|
-
*/
|
|
85
|
-
const ZDTP_TOGGLE_SHIM_SRC = `(function(){
|
|
86
|
-
if(window.__zdtpToggleShimInstalled)return;
|
|
87
|
-
window.__zdtpToggleShimInstalled=true;
|
|
88
|
-
var pending=false;
|
|
89
|
-
function shim(){pending=true;}
|
|
90
|
-
window.addEventListener('toggle-design-token-panel',shim);
|
|
91
|
-
window.__zdtpReadyClicks=function(){
|
|
92
|
-
window.removeEventListener('toggle-design-token-panel',shim);
|
|
93
|
-
delete window.__zdtpReadyClicks;
|
|
94
|
-
if(pending){pending=false;window.dispatchEvent(new CustomEvent('toggle-design-token-panel'));}
|
|
95
|
-
};
|
|
96
|
-
})();`;
|
|
97
|
-
|
|
98
66
|
/** Props for {@link BodyEndIslands}. */
|
|
99
67
|
export interface BodyEndIslandsProps {
|
|
100
68
|
/** Base path the AI chat modal uses to construct API URLs. */
|
|
@@ -109,15 +77,18 @@ export interface BodyEndIslandsProps {
|
|
|
109
77
|
}
|
|
110
78
|
|
|
111
79
|
/**
|
|
112
|
-
* The default body-end islands a doc page may mount: the
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
* `settings.
|
|
117
|
-
* landmark heading) on `settings.aiAssistant`, and image-enlarge on
|
|
118
|
-
* `settings.imageEnlarge` — so a feature-off consumer ships neither the
|
|
80
|
+
* The default body-end islands a doc page may mount: the AI chat modal
|
|
81
|
+
* (`<dialog>` overlay) and the image-enlarge dialog (mounted lazily based
|
|
82
|
+
* on viewport scan). Each is feature-gated — the AI chat modal (and its
|
|
83
|
+
* sr-only landmark heading) on `settings.aiAssistant`, and image-enlarge
|
|
84
|
+
* on `settings.imageEnlarge` — so a feature-off consumer ships neither the
|
|
119
85
|
* island marker nor a misleading landmark (zudolab/zudo-doc#2058).
|
|
120
86
|
*
|
|
87
|
+
* Optional feature islands (e.g. the design token panel bootstrap) are not
|
|
88
|
+
* listed here: they are injected at the body-end-islands composition
|
|
89
|
+
* anchors only when their feature is selected, so a feature-off scaffold
|
|
90
|
+
* carries no trace of them.
|
|
91
|
+
*
|
|
121
92
|
* Each island is wrapped in `<Island ssrFallback>` so the heavy
|
|
122
93
|
* component is NOT evaluated server-side — they depend on
|
|
123
94
|
* `dialog.showModal()`, `localStorage`, `ResizeObserver`, runtime
|
|
@@ -143,37 +114,12 @@ export function BodyEndIslands({
|
|
|
143
114
|
children: <ClientRouterBootstrap />,
|
|
144
115
|
}) as unknown as VNode;
|
|
145
116
|
|
|
146
|
-
// Hydrates on load so configurePanel() runs as early as possible and
|
|
147
|
-
// the `toggle-design-token-panel` window listener is registered before
|
|
148
|
-
// the user can click the header trigger. Renders nothing visually —
|
|
149
|
-
// the zdtp panel self-mounts as a side-effect (zudolab/zudo-doc#1623).
|
|
150
|
-
//
|
|
151
|
-
// The inline <script> emitted alongside the Island is the pre-hydration
|
|
152
|
-
// toggle shim (zudolab/zudo-doc#1627 Part B). It captures the first
|
|
153
|
-
// click as a boolean flag and exposes window.__zdtpReadyClicks so the
|
|
154
|
-
// bootstrap module can drain and re-dispatch once the real zdtp listener
|
|
155
|
-
// is registered. Mirrors the PageLoadingOverlay SSR-script pattern.
|
|
156
|
-
const designTokenPanelBootstrap =
|
|
157
|
-
settings.designTokenPanel
|
|
158
|
-
? (
|
|
159
|
-
<>
|
|
160
|
-
<script
|
|
161
|
-
dangerouslySetInnerHTML={{ __html: ZDTP_TOGGLE_SHIM_SRC }}
|
|
162
|
-
/>
|
|
163
|
-
{Island({
|
|
164
|
-
when: "load",
|
|
165
|
-
children: <DesignTokenPanelBootstrap />,
|
|
166
|
-
}) as unknown as VNode}
|
|
167
|
-
</>
|
|
168
|
-
)
|
|
169
|
-
: null;
|
|
170
|
-
|
|
171
117
|
// Gated on `settings.aiAssistant` (zudolab/zudo-doc#2058): when the AI
|
|
172
118
|
// assistant feature is off, neither the AiChatModal island marker nor the
|
|
173
119
|
// sr-only "AI Assistant" landmark heading should reach the SSG output —
|
|
174
120
|
// otherwise feature-off consumers ship a dead island marker plus a
|
|
175
121
|
// misleading screen-reader landmark for a section that never hydrates.
|
|
176
|
-
//
|
|
122
|
+
// Same feature-gating pattern as the other optional body-end islands.
|
|
177
123
|
//
|
|
178
124
|
// KNOWN CAVEAT: zfb's island scanner walks the static `"use client"`
|
|
179
125
|
// import chain, so gating this JSX removes the SSR marker and heading but
|
|
@@ -215,6 +161,20 @@ export function BodyEndIslands({
|
|
|
215
161
|
}) as unknown as VNode)
|
|
216
162
|
: null;
|
|
217
163
|
|
|
164
|
+
// Gated on `settings.mermaid`. Mirrors the imageEnlarge block: the SSR
|
|
165
|
+
// fallback is an empty, closed `<dialog class="zd-mermaid-dialog ...">` so
|
|
166
|
+
// the dist HTML carries one dialog from the start and hydration (when="idle")
|
|
167
|
+
// swaps in the real component. Unlike images (SSR-wrapped by the MDX paragraph
|
|
168
|
+
// override), mermaid renders client-side, so this island injects the enlarge
|
|
169
|
+
// button into each rendered diagram container itself.
|
|
170
|
+
const mermaidEnlarge = settings.mermaid
|
|
171
|
+
? (Island({
|
|
172
|
+
when: "idle",
|
|
173
|
+
ssrFallback: <MermaidEnlargeSsrFallback />,
|
|
174
|
+
children: <MermaidEnlarge />,
|
|
175
|
+
}) as unknown as VNode)
|
|
176
|
+
: null;
|
|
177
|
+
|
|
218
178
|
return (
|
|
219
179
|
<>
|
|
220
180
|
{/* Pure SSR — no Island wrap. The component emits its overlay div,
|
|
@@ -222,9 +182,9 @@ export function BodyEndIslands({
|
|
|
222
182
|
zfb:before-preparation / zfb:after-swap listeners at runtime. */}
|
|
223
183
|
<PageLoadingOverlay />
|
|
224
184
|
{clientRouterBootstrap}
|
|
225
|
-
{designTokenPanelBootstrap}
|
|
226
185
|
{aiAssistant}
|
|
227
186
|
{imageEnlarge}
|
|
187
|
+
{mermaidEnlarge}
|
|
228
188
|
{/* @slot:body-end-islands:extra-islands */}
|
|
229
189
|
</>
|
|
230
190
|
);
|