create-zudo-doc 0.2.11 → 0.2.12
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/scaffold.js
CHANGED
|
@@ -333,12 +333,16 @@ function generatePackageJson(choices) {
|
|
|
333
333
|
// "@takazudo/zfb" (#972) — plus removal of the no-op linkValidation.allowExternal
|
|
334
334
|
// knob (#925); both are non-breaking for a fresh scaffold. A fresh scaffold
|
|
335
335
|
// sets no explicit codeHighlight.theme so the default still applies. No
|
|
336
|
-
// consumer-facing / CLI breaking change.
|
|
337
|
-
|
|
338
|
-
|
|
336
|
+
// consumer-facing / CLI breaking change. next.52 (current pin): adds the
|
|
337
|
+
// `ClientRouter({ preserveHtmlAttrs })` option (zfb#1104) — consumers can
|
|
338
|
+
// declare runtime `<html>` attribute names to preserve across SPA swaps so
|
|
339
|
+
// e.g. `data-sidebar-hidden` / `data-theme` survive (zudolab/zudo-doc#2200).
|
|
340
|
+
// Additive, non-breaking for a fresh scaffold.
|
|
341
|
+
"@takazudo/zfb": "0.1.0-next.52",
|
|
342
|
+
"@takazudo/zfb-runtime": "0.1.0-next.52",
|
|
339
343
|
// zfb-adapter-cloudflare — required for any route with `prerender = false`.
|
|
340
344
|
// Pinned in lockstep with @takazudo/zfb.
|
|
341
|
-
"@takazudo/zfb-adapter-cloudflare": "0.1.0-next.
|
|
345
|
+
"@takazudo/zfb-adapter-cloudflare": "0.1.0-next.52",
|
|
342
346
|
// @takazudo/zudo-doc — published from this monorepo via
|
|
343
347
|
// .github/workflows/publish-zudo-doc.yml. The pin here is bumped in
|
|
344
348
|
// lockstep by scripts/release-create-zudo-doc.sh whenever zudo-doc's
|
|
@@ -350,7 +354,7 @@ function generatePackageJson(choices) {
|
|
|
350
354
|
// ties this pin to packages/zudo-doc's version, so the lockstep release
|
|
351
355
|
// bumps both together; do not cut a create-zudo-doc release until the
|
|
352
356
|
// matching @takazudo/zudo-doc version (with content.css) is on npm.
|
|
353
|
-
"@takazudo/zudo-doc": "^0.2.
|
|
357
|
+
"@takazudo/zudo-doc": "^0.2.12",
|
|
354
358
|
// zod — used by the generated zfb.config.ts. zfb-config-gen emits
|
|
355
359
|
// `import { z } from "zod"` for the content-collection schema +
|
|
356
360
|
// `z.toJSONSchema(...)` conversion. Without this dep, the consumer
|
|
@@ -373,7 +377,6 @@ function generatePackageJson(choices) {
|
|
|
373
377
|
"preact-render-to-string": "^6.6.6",
|
|
374
378
|
shiki: "^4.0.2",
|
|
375
379
|
"@shikijs/transformers": "^4.0.0",
|
|
376
|
-
clsx: "^2.1.0",
|
|
377
380
|
"gray-matter": "^4.0.0",
|
|
378
381
|
mermaid: "^11.12.3",
|
|
379
382
|
"remark-cjk-friendly": "^2.0.1",
|
|
@@ -405,7 +408,7 @@ function generatePackageJson(choices) {
|
|
|
405
408
|
// @takazudo/zudo-doc/integrations/doc-history which in turn imports
|
|
406
409
|
// @takazudo/zudo-doc-history-server/git-history. Without this dep the
|
|
407
410
|
// plugin host fails at init with ERR_MODULE_NOT_FOUND — W8A (#1739).
|
|
408
|
-
deps["@takazudo/zudo-doc-history-server"] = "^0.2.
|
|
411
|
+
deps["@takazudo/zudo-doc-history-server"] = "^0.2.12";
|
|
409
412
|
// W7A (#1736): doc-history-plugin.mjs spawns `tsx -e <inline-script>` to
|
|
410
413
|
// run the v2 runtime in a TS-aware Node subprocess; without tsx the
|
|
411
414
|
// plugin's preBuild step exits with ENOENT before zfb finishes config
|
package/package.json
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
// packages/zudo-doc/src/theme-toggle/index.tsx. Type references via
|
|
7
7
|
// the global React namespace still resolve via @types/react.
|
|
8
8
|
import { useState, useEffect } from "preact/hooks";
|
|
9
|
-
import clsx from "clsx";
|
|
10
9
|
// After zudolab/zudo-doc#1335 (E2 task 2 half B) the host components
|
|
11
10
|
// pull lifecycle event names from the v2 transitions module rather
|
|
12
11
|
// than hard-coding `astro:*` literals.
|
|
@@ -18,6 +17,9 @@ import type { LocaleLink } from "@/types/locale";
|
|
|
18
17
|
// pulled in by `./sidebar`'s runtime barrel.
|
|
19
18
|
import type { SidebarRootMenuItem } from "@takazudo/zudo-doc/sidebar/types";
|
|
20
19
|
|
|
20
|
+
const cx = (...classes: Array<string | false | null | undefined>) =>
|
|
21
|
+
classes.filter(Boolean).join(" ");
|
|
22
|
+
|
|
21
23
|
// Mobile drawer hosts the SidebarTree directly (rather than receiving it as
|
|
22
24
|
// JSX children) so the tree's data props ride across the SSR → hydrate
|
|
23
25
|
// boundary inside the Island marker's `data-props` attribute. zfb's
|
|
@@ -90,7 +92,7 @@ export default function SidebarToggle({
|
|
|
90
92
|
{/* X icon — visible only when open */}
|
|
91
93
|
<svg
|
|
92
94
|
xmlns="http://www.w3.org/2000/svg"
|
|
93
|
-
className={
|
|
95
|
+
className={cx("h-icon-lg w-icon-lg", !open && "hidden")}
|
|
94
96
|
aria-hidden="true"
|
|
95
97
|
fill="none"
|
|
96
98
|
viewBox="0 0 24 24"
|
|
@@ -106,7 +108,7 @@ export default function SidebarToggle({
|
|
|
106
108
|
{/* Hamburger icon — visible only when closed */}
|
|
107
109
|
<svg
|
|
108
110
|
xmlns="http://www.w3.org/2000/svg"
|
|
109
|
-
className={
|
|
111
|
+
className={cx("h-icon-lg w-icon-lg", open && "hidden")}
|
|
110
112
|
aria-hidden="true"
|
|
111
113
|
fill="none"
|
|
112
114
|
viewBox="0 0 24 24"
|
|
@@ -131,7 +133,7 @@ export default function SidebarToggle({
|
|
|
131
133
|
backdrop (onClick below), so the header hamburger being dimmed under
|
|
132
134
|
it is fine. */}
|
|
133
135
|
<div
|
|
134
|
-
className={
|
|
136
|
+
className={cx("fixed inset-0 z-modal-backdrop bg-overlay/30 lg:hidden", !open && "hidden")}
|
|
135
137
|
aria-hidden={!open}
|
|
136
138
|
onClick={() => setOpen(false)}
|
|
137
139
|
/>
|
|
@@ -717,19 +717,10 @@ pre[class^="syntect-"] .line .highlighted-word {
|
|
|
717
717
|
}
|
|
718
718
|
}
|
|
719
719
|
|
|
720
|
-
/*
|
|
721
|
-
*
|
|
722
|
-
*
|
|
723
|
-
*
|
|
724
|
-
* flash + slide. The island sets data-sidebar-no-transition for the swap
|
|
725
|
-
* window and removes it (double rAF) after restoring the hidden state, so the
|
|
726
|
-
* wipe/restore apply instantly and a later user toggle still animates. */
|
|
727
|
-
html[data-sidebar-no-transition] #desktop-sidebar,
|
|
728
|
-
html[data-sidebar-no-transition] .zd-sidebar-content-wrapper,
|
|
729
|
-
html[data-sidebar-no-transition] .zd-doc-content-band,
|
|
730
|
-
html[data-sidebar-no-transition] .zd-desktop-sidebar-toggle {
|
|
731
|
-
transition: none !important;
|
|
732
|
-
}
|
|
720
|
+
/* The SPA-swap flash guard (`data-sidebar-no-transition`) was removed once
|
|
721
|
+
* doc-layout adopted <ClientRouter preserveHtmlAttrs={["data-sidebar-hidden",
|
|
722
|
+
* ...]} /> (zfb-runtime >= 0.1.0-next.52): the attribute now survives the swap
|
|
723
|
+
* before paint, so no sidebar geometry transition fires mid-swap. */
|
|
733
724
|
|
|
734
725
|
/* ── Find-in-page highlight (W7A: unconditional — Tauri feature gates at runtime) ── */
|
|
735
726
|
.find-match {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { useState, useEffect, useRef } from 'preact/hooks';
|
|
4
|
-
import { BEFORE_NAVIGATE_EVENT, AFTER_NAVIGATE_EVENT } from '@takazudo/zudo-doc/transitions';
|
|
5
4
|
|
|
6
5
|
export const SIDEBAR_STORAGE_KEY = 'zudo-doc-sidebar-visible';
|
|
7
6
|
|
|
@@ -22,93 +21,13 @@ function setDataAttribute(isVisible: boolean) {
|
|
|
22
21
|
}
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
// SPA-navigation guard for the desktop sidebar's hidden-state (#2198).
|
|
26
|
-
//
|
|
27
|
-
// zfb's Strategy-B client router wipes EVERY <html> attribute during the body
|
|
28
|
-
// swap (swapRootAttributes re-adds only NON_OVERRIDABLE_ZFB_ATTRS plus the
|
|
29
|
-
// incoming SSR document's attributes), so the persisted `data-sidebar-hidden`
|
|
30
|
-
// runtime value is lost on every navigation, and the pre-paint inline script
|
|
31
|
-
// does not re-run on SPA hops. Left alone, the freshly-rendered sidebar paints
|
|
32
|
-
// visible and then animates shut when the value is restored — the flash + slide.
|
|
33
|
-
//
|
|
34
|
-
// These listeners MUST live at module scope, NOT in the island's useEffect:
|
|
35
|
-
// zfb-runtime (>= 0.1.0-next.51) calls unmountIslands() BEFORE the swap and
|
|
36
|
-
// before firing AFTER_NAVIGATE_EVENT, so a useEffect-registered listener is torn
|
|
37
|
-
// down (effect cleanup) before the swap and never sees the after-swap event —
|
|
38
|
-
// the restore would never run (#2198 verification). Registering once on
|
|
39
|
-
// `document` at bundle load — the same lifecycle-independent pattern as
|
|
40
|
-
// client-router-bootstrap.tsx — keeps the guard alive across island
|
|
41
|
-
// unmount/remount. SSR-safe: no-ops when `document` is undefined.
|
|
42
|
-
//
|
|
43
|
-
// Strategy: on BEFORE_NAVIGATE_EVENT, record whether the sidebar was hidden and
|
|
44
|
-
// set a transient `data-sidebar-no-transition` marker (global.css zeroes the
|
|
45
|
-
// sidebar/wrapper/band/toggle transitions). The swap then wipes BOTH the marker
|
|
46
|
-
// and data-sidebar-hidden. On AFTER_NAVIGATE_EVENT (swap done → the live <html>
|
|
47
|
-
// is no longer wiped) RE-SET the marker, then re-add data-sidebar-hidden in the
|
|
48
|
-
// same synchronous batch, so the hidden geometry snaps in with transitions
|
|
49
|
-
// suppressed (no slide, no open frame). Remove the marker on a double rAF
|
|
50
|
-
// afterward so a later user toggle still animates.
|
|
51
|
-
let spaNavGuardRegistered = false;
|
|
52
|
-
function registerSidebarSpaNavGuard() {
|
|
53
|
-
if (typeof document === 'undefined' || spaNavGuardRegistered) return;
|
|
54
|
-
spaNavGuardRegistered = true;
|
|
55
|
-
|
|
56
|
-
let wasHidden = false;
|
|
57
|
-
let swapToken = 0;
|
|
58
|
-
// Long enough to outlast the View-Transition swap pipeline on slow
|
|
59
|
-
// machines/CI; short enough that an aborted nav self-heals quickly. Only a
|
|
60
|
-
// safety net for a nav that never reaches `restore` (aborted/superseded).
|
|
61
|
-
const STUCK_MARKER_FALLBACK_MS = 1500;
|
|
62
|
-
|
|
63
|
-
const capture = () => {
|
|
64
|
-
wasHidden = document.documentElement.hasAttribute('data-sidebar-hidden');
|
|
65
|
-
document.documentElement.setAttribute('data-sidebar-no-transition', '');
|
|
66
|
-
const token = ++swapToken;
|
|
67
|
-
window.setTimeout(() => {
|
|
68
|
-
if (token === swapToken) {
|
|
69
|
-
document.documentElement.removeAttribute('data-sidebar-no-transition');
|
|
70
|
-
}
|
|
71
|
-
}, STUCK_MARKER_FALLBACK_MS);
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
const restore = () => {
|
|
75
|
-
// Marker first, then the attribute, in one synchronous batch — so the
|
|
76
|
-
// hidden geometry is restored with transitions off (the swap already wiped
|
|
77
|
-
// the capture-time marker, so re-setting it here on the post-swap <html> is
|
|
78
|
-
// what actually suppresses the animation).
|
|
79
|
-
document.documentElement.setAttribute('data-sidebar-no-transition', '');
|
|
80
|
-
if (wasHidden) {
|
|
81
|
-
document.documentElement.setAttribute('data-sidebar-hidden', '');
|
|
82
|
-
}
|
|
83
|
-
// Drop the marker only after the restored state is committed. A single rAF
|
|
84
|
-
// can coincide with the restore's style recalc and animate it, so defer one
|
|
85
|
-
// extra frame. The token bump no-ops capture's safety-net for this swap.
|
|
86
|
-
const token = ++swapToken;
|
|
87
|
-
requestAnimationFrame(() => {
|
|
88
|
-
requestAnimationFrame(() => {
|
|
89
|
-
if (token === swapToken) {
|
|
90
|
-
document.documentElement.removeAttribute('data-sidebar-no-transition');
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
document.addEventListener(BEFORE_NAVIGATE_EVENT, capture);
|
|
97
|
-
document.addEventListener(AFTER_NAVIGATE_EVENT, restore);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Register at module load (browser-only via the guard) so the listeners exist
|
|
101
|
-
// before the first navigation and survive island unmount/remount.
|
|
102
|
-
registerSidebarSpaNavGuard();
|
|
103
|
-
|
|
104
24
|
export default function DesktopSidebarToggle() {
|
|
105
25
|
// Initial state must match server render (always `true`) to avoid a
|
|
106
26
|
// hydration mismatch when the persisted preference is "hidden". The
|
|
107
27
|
// doc-layout's pre-paint inline script applies `data-sidebar-hidden`
|
|
108
28
|
// to <html> from localStorage *before* this island mounts, so the
|
|
109
29
|
// visual state stays correct; we only need to sync this island's
|
|
110
|
-
// React state to the persisted preference after hydration.
|
|
111
|
-
// pattern as packages/zudo-doc/src/theme-toggle/index.tsx (commit 9aebd8e).
|
|
30
|
+
// React state to the persisted preference after hydration.
|
|
112
31
|
const [visible, setVisible] = useState<boolean>(true);
|
|
113
32
|
// Tracks whether the hydration sync (below) has run. The persistence
|
|
114
33
|
// effect below skips the very first mount so we don't overwrite the
|
|
@@ -145,10 +64,11 @@ export default function DesktopSidebarToggle() {
|
|
|
145
64
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
146
65
|
}, []);
|
|
147
66
|
|
|
148
|
-
// The SPA-navigation flash
|
|
149
|
-
//
|
|
150
|
-
//
|
|
151
|
-
//
|
|
67
|
+
// The SPA-navigation flash (a collapsed sidebar briefly painting open on
|
|
68
|
+
// every soft swap) is handled upstream: doc-layout mounts
|
|
69
|
+
// <ClientRouter preserveHtmlAttrs={["data-sidebar-hidden", ...]} /> so
|
|
70
|
+
// zfb-runtime (>= 0.1.0-next.52) re-applies the runtime attribute across the
|
|
71
|
+
// swap before paint. No host-side capture/restore guard is needed.
|
|
152
72
|
|
|
153
73
|
return (
|
|
154
74
|
<button
|