@takazudo/zudo-doc 0.2.0-next.3 → 0.2.0-next.6

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.
@@ -1,5 +1,6 @@
1
1
  import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
2
2
  import { findPath } from "./find-path.js";
3
+ import { ChevronRight } from "../icons/index.js";
3
4
  function buildBreadcrumbItems(tree, currentId, homeHref) {
4
5
  const items = [{ label: "", href: homeHref }];
5
6
  const path = findPath(tree, currentId);
@@ -41,26 +42,7 @@ function isPathLike(text) {
41
42
  return false;
42
43
  }
43
44
  function ChevronIcon() {
44
- return /* @__PURE__ */ jsx(
45
- "svg",
46
- {
47
- xmlns: "http://www.w3.org/2000/svg",
48
- class: "h-icon-xs w-icon-xs text-muted shrink-0",
49
- fill: "none",
50
- viewBox: "0 0 24 24",
51
- stroke: "currentColor",
52
- "stroke-width": "2",
53
- "aria-hidden": "true",
54
- children: /* @__PURE__ */ jsx(
55
- "path",
56
- {
57
- "stroke-linecap": "round",
58
- "stroke-linejoin": "round",
59
- d: "M9 5l7 7-7 7"
60
- }
61
- )
62
- }
63
- );
45
+ return /* @__PURE__ */ jsx(ChevronRight, { className: "h-icon-xs w-icon-xs text-muted shrink-0" });
64
46
  }
65
47
  function HomeIcon() {
66
48
  return /* @__PURE__ */ jsx(
@@ -16,7 +16,7 @@
16
16
  * tests can override the URL — e.g. self-hosted mirrors, version-
17
17
  * locked deployments — without re-templating the whole script.
18
18
  */
19
- declare const MERMAID_CDN_MODULE_URL = "https://esm.sh/mermaid@11.4.1";
19
+ declare const MERMAID_CDN_MODULE_URL = "https://esm.sh/mermaid@11.15.0";
20
20
  /**
21
21
  * Build the inline init script with a caller-supplied module URL.
22
22
  *
@@ -1,5 +1,5 @@
1
1
  import { AFTER_NAVIGATE_EVENT } from "../transitions/page-events.js";
2
- const MERMAID_CDN_MODULE_URL = "https://esm.sh/mermaid@11.4.1";
2
+ const MERMAID_CDN_MODULE_URL = "https://esm.sh/mermaid@11.15.0";
3
3
  function buildMermaidInitScript(cdnUrl) {
4
4
  const safeUrlLiteral = JSON.stringify(cdnUrl).replace(
5
5
  /<\/(script)/gi,
@@ -1,11 +1,9 @@
1
- import * as preact from 'preact';
2
- import { ComponentChildren } from 'preact';
1
+ import { JSX } from 'preact';
3
2
 
4
- type Props = {
5
- children?: ComponentChildren;
6
- className?: string;
7
- [key: string]: any;
8
- };
9
- declare function ContentBlockquote({ children, className, ...rest }: Props): preact.JSX.Element;
3
+ /** @jsxRuntime automatic */
4
+ /** @jsxImportSource preact */
5
+
6
+ type Props = JSX.IntrinsicElements["blockquote"];
7
+ declare function ContentBlockquote({ children, className, ...rest }: Props): JSX.Element;
10
8
 
11
9
  export { ContentBlockquote };
@@ -1,11 +1,9 @@
1
- import * as preact from 'preact';
2
- import { ComponentChildren } from 'preact';
1
+ import { JSX } from 'preact';
3
2
 
4
- type Props = {
5
- children?: ComponentChildren;
6
- className?: string;
7
- [key: string]: any;
8
- };
3
+ /** @jsxRuntime automatic */
4
+ /** @jsxImportSource preact */
5
+
6
+ type Props = JSX.IntrinsicElements["code"];
9
7
  /**
10
8
  * Override for inline `<code>` in MDX. Wraps text-only inline code with
11
9
  * <SmartBreak> so that path/URL-like strings (e.g. `src/foo/bar.ts`) can
@@ -21,6 +19,6 @@ type Props = {
21
19
  * `extractText` unwraps that so the heuristic works regardless of MDX's
22
20
  * internal wrapping.
23
21
  */
24
- declare function ContentCode({ children, className, ...rest }: Props): preact.JSX.Element;
22
+ declare function ContentCode({ children, className, ...rest }: Props): JSX.Element;
25
23
 
26
24
  export { ContentCode };
@@ -1,12 +1,9 @@
1
- import * as preact from 'preact';
2
- import { ComponentChildren } from 'preact';
1
+ import { JSX } from 'preact';
3
2
 
4
- type Props = {
5
- href?: string;
6
- className?: string;
7
- children?: ComponentChildren;
8
- [key: string]: any;
9
- };
10
- declare function ContentLink({ href, className, children, ...rest }: Props): preact.JSX.Element;
3
+ /** @jsxRuntime automatic */
4
+ /** @jsxImportSource preact */
5
+
6
+ type Props = JSX.IntrinsicElements["a"];
7
+ declare function ContentLink({ href, className, children, ...rest }: Props): JSX.Element;
11
8
 
12
9
  export { ContentLink };
@@ -2,7 +2,7 @@ import { jsx } from "preact/jsx-runtime";
2
2
  import { SmartBreak as SmartBreakBase } from "../toc/smart-break.js";
3
3
  const SmartBreak = SmartBreakBase;
4
4
  function ContentLink({ href, className, children, ...rest }) {
5
- const classes = className ? className.split(" ") : [];
5
+ const classes = typeof className === "string" ? className.split(" ") : [];
6
6
  if (classes.includes("block") || classes.includes("hash-link")) {
7
7
  return /* @__PURE__ */ jsx("a", { href, className, ...rest, children });
8
8
  }
@@ -1,11 +1,9 @@
1
- import * as preact from 'preact';
2
- import { ComponentChildren } from 'preact';
1
+ import { JSX } from 'preact';
3
2
 
4
- type Props = {
5
- children?: ComponentChildren;
6
- className?: string;
7
- [key: string]: any;
8
- };
9
- declare function ContentOl({ children, className, ...rest }: Props): preact.JSX.Element;
3
+ /** @jsxRuntime automatic */
4
+ /** @jsxImportSource preact */
5
+
6
+ type Props = JSX.IntrinsicElements["ol"];
7
+ declare function ContentOl({ children, className, ...rest }: Props): JSX.Element;
10
8
 
11
9
  export { ContentOl };
@@ -1,10 +1,9 @@
1
- import * as preact from 'preact';
2
- import { ComponentChildren } from 'preact';
1
+ import { JSX } from 'preact';
3
2
 
4
- type Props = {
5
- children?: ComponentChildren;
6
- [key: string]: any;
7
- };
8
- declare function ContentParagraph({ children, ...rest }: Props): preact.JSX.Element;
3
+ /** @jsxRuntime automatic */
4
+ /** @jsxImportSource preact */
5
+
6
+ type Props = JSX.IntrinsicElements["p"];
7
+ declare function ContentParagraph({ children, ...rest }: Props): JSX.Element;
9
8
 
10
9
  export { ContentParagraph };
@@ -1,11 +1,9 @@
1
- import * as preact from 'preact';
2
- import { ComponentChildren } from 'preact';
1
+ import { JSX } from 'preact';
3
2
 
4
- type Props = {
5
- children?: ComponentChildren;
6
- className?: string;
7
- [key: string]: any;
8
- };
9
- declare function ContentStrong({ children, className, ...rest }: Props): preact.JSX.Element;
3
+ /** @jsxRuntime automatic */
4
+ /** @jsxImportSource preact */
5
+
6
+ type Props = JSX.IntrinsicElements["strong"];
7
+ declare function ContentStrong({ children, className, ...rest }: Props): JSX.Element;
10
8
 
11
9
  export { ContentStrong };
@@ -1,11 +1,9 @@
1
- import * as preact from 'preact';
2
- import { ComponentChildren } from 'preact';
1
+ import { JSX } from 'preact';
3
2
 
4
- type Props = {
5
- children?: ComponentChildren;
6
- className?: string;
7
- [key: string]: any;
8
- };
9
- declare function ContentTable({ children, className, ...rest }: Props): preact.JSX.Element;
3
+ /** @jsxRuntime automatic */
4
+ /** @jsxImportSource preact */
5
+
6
+ type Props = JSX.IntrinsicElements["table"];
7
+ declare function ContentTable({ children, className, ...rest }: Props): JSX.Element;
10
8
 
11
9
  export { ContentTable };
@@ -1,11 +1,9 @@
1
- import * as preact from 'preact';
2
- import { ComponentChildren } from 'preact';
1
+ import { JSX } from 'preact';
3
2
 
4
- type Props = {
5
- children?: ComponentChildren;
6
- className?: string;
7
- [key: string]: any;
8
- };
9
- declare function ContentUl({ children, className, ...rest }: Props): preact.JSX.Element;
3
+ /** @jsxRuntime automatic */
4
+ /** @jsxImportSource preact */
5
+
6
+ type Props = JSX.IntrinsicElements["ul"];
7
+ declare function ContentUl({ children, className, ...rest }: Props): JSX.Element;
10
8
 
11
9
  export { ContentUl };
@@ -1,14 +1,9 @@
1
- import { ComponentChildren, JSX } from 'preact';
1
+ import { JSX } from 'preact';
2
2
 
3
3
  /** @jsxRuntime automatic */
4
4
  /** @jsxImportSource preact */
5
5
 
6
- type Props = {
7
- id?: string;
8
- className?: string;
9
- children?: ComponentChildren;
10
- [key: string]: any;
11
- };
6
+ type Props = JSX.IntrinsicElements["h2"];
12
7
  declare function HeadingH2({ id, children, className, ...rest }: Props): JSX.Element;
13
8
 
14
9
  export { HeadingH2 };
@@ -1,14 +1,9 @@
1
- import { ComponentChildren, JSX } from 'preact';
1
+ import { JSX } from 'preact';
2
2
 
3
3
  /** @jsxRuntime automatic */
4
4
  /** @jsxImportSource preact */
5
5
 
6
- type Props = {
7
- id?: string;
8
- className?: string;
9
- children?: ComponentChildren;
10
- [key: string]: any;
11
- };
6
+ type Props = JSX.IntrinsicElements["h3"];
12
7
  declare function HeadingH3({ id, children, className, ...rest }: Props): JSX.Element;
13
8
 
14
9
  export { HeadingH3 };
@@ -1,14 +1,9 @@
1
- import { ComponentChildren, JSX } from 'preact';
1
+ import { JSX } from 'preact';
2
2
 
3
3
  /** @jsxRuntime automatic */
4
4
  /** @jsxImportSource preact */
5
5
 
6
- type Props = {
7
- id?: string;
8
- className?: string;
9
- children?: ComponentChildren;
10
- [key: string]: any;
11
- };
6
+ type Props = JSX.IntrinsicElements["h4"];
12
7
  declare function HeadingH4({ id, children, className, ...rest }: Props): JSX.Element;
13
8
 
14
9
  export { HeadingH4 };
@@ -5,6 +5,7 @@ import {
5
5
  pathForMatch
6
6
  } from "./nav-active.js";
7
7
  import { NAV_OVERFLOW_SCRIPT } from "./nav-overflow-script.js";
8
+ import { GitHub as GitHubIcon } from "../icons/index.js";
8
9
  function Header(props) {
9
10
  const {
10
11
  lang,
@@ -207,80 +208,95 @@ function renderNavItem(item, activeNavPath, lang, currentVersion, urlHelpers, i1
207
208
  }
208
209
  );
209
210
  }
210
- function renderRightItem(item, index, ctx) {
211
- if (item.type === "trigger" && item.trigger === "design-token-panel") {
212
- const inlineOnclick = {
213
- onclick: "window.dispatchEvent(new CustomEvent('toggle-design-token-panel'))"
214
- };
215
- return /* @__PURE__ */ jsx(
216
- "button",
217
- {
218
- id: "design-token-trigger",
219
- type: "button",
220
- class: "flex items-center justify-center text-muted transition-colors hover:text-fg",
221
- "aria-label": "Toggle design token panel",
222
- ...inlineOnclick,
223
- children: /* @__PURE__ */ jsxs(
224
- "svg",
225
- {
226
- xmlns: "http://www.w3.org/2000/svg",
227
- width: "20",
228
- height: "20",
229
- viewBox: "0 0 24 24",
230
- fill: "none",
231
- stroke: "currentColor",
232
- "stroke-width": "2",
233
- "stroke-linecap": "round",
234
- "stroke-linejoin": "round",
235
- "aria-hidden": "true",
236
- children: [
237
- /* @__PURE__ */ jsx("circle", { cx: "13.5", cy: "6.5", r: "2.5" }),
238
- /* @__PURE__ */ jsx("circle", { cx: "17.5", cy: "10.5", r: "2.5" }),
239
- /* @__PURE__ */ jsx("circle", { cx: "8.5", cy: "7.5", r: "2.5" }),
240
- /* @__PURE__ */ jsx("circle", { cx: "6.5", cy: "12.5", r: "2.5" }),
241
- /* @__PURE__ */ jsx("path", { d: "M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z" })
242
- ]
243
- }
244
- )
245
- },
246
- `right-${index}`
247
- );
248
- }
249
- if (item.type === "trigger" && item.trigger === "ai-chat") {
250
- const inlineOnclick = {
251
- onclick: "window.dispatchEvent(new CustomEvent('toggle-ai-chat'))"
252
- };
253
- return /* @__PURE__ */ jsx(
254
- "button",
255
- {
256
- id: "ai-chat-trigger",
257
- type: "button",
258
- class: "flex items-center justify-center text-muted transition-colors hover:text-fg",
259
- "aria-label": "Open AI assistant",
260
- ...inlineOnclick,
261
- children: /* @__PURE__ */ jsxs(
262
- "svg",
263
- {
264
- xmlns: "http://www.w3.org/2000/svg",
265
- width: "20",
266
- height: "20",
267
- viewBox: "0 0 24 24",
268
- fill: "currentColor",
269
- "aria-hidden": "true",
270
- children: [
271
- /* @__PURE__ */ jsx("path", { d: "M9.5 2.5Q10.5 11.5 18 13Q10.5 14.5 9.5 23.5Q8.5 14.5 1 13Q8.5 11.5 9.5 2.5Z" }),
272
- /* @__PURE__ */ jsx("path", { d: "M19 0.5Q19.5 4 23.5 5Q19.5 6 19 9.5Q18.5 6 14.5 5Q18.5 4 19 0.5Z" })
273
- ]
274
- }
275
- )
276
- },
277
- `right-${index}`
278
- );
279
- }
280
- if (item.type === "component" && item.component === "version-switcher") {
281
- return /* @__PURE__ */ jsx("div", { class: "hidden lg:block", children: ctx.versionSwitcher }, `right-${index}`);
282
- }
283
- if (item.type === "component" && item.component === "github-link" && ctx.githubRepoUrl) {
211
+ function TriggerButton({
212
+ index,
213
+ id,
214
+ ariaLabel,
215
+ event,
216
+ children
217
+ }) {
218
+ const inlineOnclick = {
219
+ onclick: `window.dispatchEvent(new CustomEvent('${event}'))`
220
+ };
221
+ return /* @__PURE__ */ jsx(
222
+ "button",
223
+ {
224
+ id,
225
+ type: "button",
226
+ class: "flex items-center justify-center text-muted transition-colors hover:text-fg",
227
+ "aria-label": ariaLabel,
228
+ ...inlineOnclick,
229
+ children
230
+ },
231
+ `right-${index}`
232
+ );
233
+ }
234
+ function SlotWrapper({
235
+ index,
236
+ className,
237
+ children
238
+ }) {
239
+ return /* @__PURE__ */ jsx("div", { class: className, children }, `right-${index}`);
240
+ }
241
+ const RIGHT_ITEM_DISPATCH = {
242
+ "trigger:design-token-panel": (_item, index) => /* @__PURE__ */ jsx(
243
+ TriggerButton,
244
+ {
245
+ index,
246
+ id: "design-token-trigger",
247
+ ariaLabel: "Toggle design token panel",
248
+ event: "toggle-design-token-panel",
249
+ children: /* @__PURE__ */ jsxs(
250
+ "svg",
251
+ {
252
+ xmlns: "http://www.w3.org/2000/svg",
253
+ width: "20",
254
+ height: "20",
255
+ viewBox: "0 0 24 24",
256
+ fill: "none",
257
+ stroke: "currentColor",
258
+ "stroke-width": "2",
259
+ "stroke-linecap": "round",
260
+ "stroke-linejoin": "round",
261
+ "aria-hidden": "true",
262
+ children: [
263
+ /* @__PURE__ */ jsx("circle", { cx: "13.5", cy: "6.5", r: "2.5" }),
264
+ /* @__PURE__ */ jsx("circle", { cx: "17.5", cy: "10.5", r: "2.5" }),
265
+ /* @__PURE__ */ jsx("circle", { cx: "8.5", cy: "7.5", r: "2.5" }),
266
+ /* @__PURE__ */ jsx("circle", { cx: "6.5", cy: "12.5", r: "2.5" }),
267
+ /* @__PURE__ */ jsx("path", { d: "M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z" })
268
+ ]
269
+ }
270
+ )
271
+ }
272
+ ),
273
+ "trigger:ai-chat": (_item, index) => /* @__PURE__ */ jsx(
274
+ TriggerButton,
275
+ {
276
+ index,
277
+ id: "ai-chat-trigger",
278
+ ariaLabel: "Open AI assistant",
279
+ event: "toggle-ai-chat",
280
+ children: /* @__PURE__ */ jsxs(
281
+ "svg",
282
+ {
283
+ xmlns: "http://www.w3.org/2000/svg",
284
+ width: "20",
285
+ height: "20",
286
+ viewBox: "0 0 24 24",
287
+ fill: "currentColor",
288
+ "aria-hidden": "true",
289
+ children: [
290
+ /* @__PURE__ */ jsx("path", { d: "M9.5 2.5Q10.5 11.5 18 13Q10.5 14.5 9.5 23.5Q8.5 14.5 1 13Q8.5 11.5 9.5 2.5Z" }),
291
+ /* @__PURE__ */ jsx("path", { d: "M19 0.5Q19.5 4 23.5 5Q19.5 6 19 9.5Q18.5 6 14.5 5Q18.5 4 19 0.5Z" })
292
+ ]
293
+ }
294
+ )
295
+ }
296
+ ),
297
+ "component:version-switcher": (_item, index, ctx) => /* @__PURE__ */ jsx(SlotWrapper, { index, className: "hidden lg:block", children: ctx.versionSwitcher }),
298
+ "component:github-link": (_item, index, ctx) => {
299
+ if (!ctx.githubRepoUrl) return null;
284
300
  return /* @__PURE__ */ jsxs(
285
301
  "a",
286
302
  {
@@ -292,35 +308,23 @@ function renderRightItem(item, index, ctx) {
292
308
  title: ctx.githubLabel,
293
309
  children: [
294
310
  /* @__PURE__ */ jsx("span", { class: "sr-only", children: ctx.githubLabel }),
295
- /* @__PURE__ */ jsx(
296
- "svg",
297
- {
298
- xmlns: "http://www.w3.org/2000/svg",
299
- width: "20",
300
- height: "20",
301
- viewBox: "0 0 24 24",
302
- fill: "currentColor",
303
- "aria-hidden": "true",
304
- children: /* @__PURE__ */ jsx("path", { d: "M12 .5C5.649.5.5 5.649.5 12a11.5 11.5 0 0 0 7.86 10.915c.575.106.785-.25.785-.556 0-.274-.01-1-.016-1.962-3.198.695-3.873-1.541-3.873-1.541-.523-1.327-1.277-1.68-1.277-1.68-1.044-.714.079-.699.079-.699 1.154.082 1.761 1.186 1.761 1.186 1.026 1.758 2.692 1.25 3.348.956.104-.743.401-1.25.73-1.537-2.553-.29-5.238-1.276-5.238-5.682 0-1.255.448-2.282 1.182-3.086-.119-.29-.512-1.458.111-3.04 0 0 .964-.309 3.159 1.18A10.98 10.98 0 0 1 12 6.036c.977.005 1.963.132 2.883.387 2.193-1.49 3.155-1.18 3.155-1.18.625 1.582.232 2.75.114 3.04.736.804 1.18 1.831 1.18 3.086 0 4.417-2.689 5.389-5.25 5.673.412.355.779 1.056.779 2.129 0 1.538-.014 2.778-.014 3.156 0 .31.207.668.79.555A11.502 11.502 0 0 0 23.5 12C23.5 5.649 18.351.5 12 .5Z" })
305
- }
306
- )
311
+ /* @__PURE__ */ jsx(GitHubIcon, {})
307
312
  ]
308
313
  },
309
314
  `right-${index}`
310
315
  );
311
- }
312
- if (item.type === "component" && item.component === "theme-toggle") {
316
+ },
317
+ "component:theme-toggle": (_item, index, ctx) => {
313
318
  if (!ctx.colorModeEnabled) return null;
314
- return /* @__PURE__ */ jsx("div", { class: "hidden lg:flex items-center", children: ctx.themeToggle }, `right-${index}`);
315
- }
316
- if (item.type === "component" && item.component === "language-switcher") {
319
+ return /* @__PURE__ */ jsx(SlotWrapper, { index, className: "hidden lg:flex items-center", children: ctx.themeToggle });
320
+ },
321
+ "component:language-switcher": (_item, index, ctx) => {
317
322
  if (!(ctx.lang && ctx.hasLocales)) return null;
318
- return /* @__PURE__ */ jsx("div", { class: "hidden lg:flex items-center", children: ctx.languageSwitcher }, `right-${index}`);
319
- }
320
- if (item.type === "component" && item.component === "search") {
321
- return /* @__PURE__ */ jsx("div", { children: ctx.search }, `right-${index}`);
322
- }
323
- if (item.type === "link") {
323
+ return /* @__PURE__ */ jsx(SlotWrapper, { index, className: "hidden lg:flex items-center", children: ctx.languageSwitcher });
324
+ },
325
+ "component:search": (_item, index, ctx) => /* @__PURE__ */ jsx(SlotWrapper, { index, children: ctx.search }),
326
+ link: (item, index) => {
327
+ if (item.type !== "link") return null;
324
328
  const label = item.label ?? item.ariaLabel;
325
329
  const isExternal = /^https?:\/\//.test(item.href);
326
330
  return /* @__PURE__ */ jsx(
@@ -334,24 +338,14 @@ function renderRightItem(item, index, ctx) {
334
338
  title: label,
335
339
  children: item.icon === "github" ? /* @__PURE__ */ jsxs(Fragment, { children: [
336
340
  label && /* @__PURE__ */ jsx("span", { class: "sr-only", children: label }),
337
- /* @__PURE__ */ jsx(
338
- "svg",
339
- {
340
- xmlns: "http://www.w3.org/2000/svg",
341
- width: "20",
342
- height: "20",
343
- viewBox: "0 0 24 24",
344
- fill: "currentColor",
345
- "aria-hidden": "true",
346
- children: /* @__PURE__ */ jsx("path", { d: "M12 .5C5.649.5.5 5.649.5 12a11.5 11.5 0 0 0 7.86 10.915c.575.106.785-.25.785-.556 0-.274-.01-1-.016-1.962-3.198.695-3.873-1.541-3.873-1.541-.523-1.327-1.277-1.68-1.277-1.68-1.044-.714.079-.699.079-.699 1.154.082 1.761 1.186 1.761 1.186 1.026 1.758 2.692 1.25 3.348.956.104-.743.401-1.25.73-1.537-2.553-.29-5.238-1.276-5.238-5.682 0-1.255.448-2.282 1.182-3.086-.119-.29-.512-1.458.111-3.04 0 0 .964-.309 3.159 1.18A10.98 10.98 0 0 1 12 6.036c.977.005 1.963.132 2.883.387 2.193-1.49 3.155-1.18 3.155-1.18.625 1.582.232 2.75.114 3.04.736.804 1.18 1.831 1.18 3.086 0 4.417-2.689 5.389-5.25 5.673.412.355.779 1.056.779 2.129 0 1.538-.014 2.778-.014 3.156 0 .31.207.668.79.555A11.502 11.502 0 0 0 23.5 12C23.5 5.649 18.351.5 12 .5Z" })
347
- }
348
- )
341
+ /* @__PURE__ */ jsx(GitHubIcon, {})
349
342
  ] }) : label
350
343
  },
351
344
  `right-${index}`
352
345
  );
353
- }
354
- if (item.type === "html") {
346
+ },
347
+ html: (item, index) => {
348
+ if (item.type !== "html") return null;
355
349
  return /* @__PURE__ */ jsx(
356
350
  "span",
357
351
  {
@@ -360,7 +354,11 @@ function renderRightItem(item, index, ctx) {
360
354
  `right-${index}`
361
355
  );
362
356
  }
363
- return null;
357
+ };
358
+ function renderRightItem(item, index, ctx) {
359
+ const key = item.type === "trigger" ? `trigger:${item.trigger}` : item.type === "component" ? `component:${item.component}` : item.type;
360
+ const handler = RIGHT_ITEM_DISPATCH[key];
361
+ return handler ? handler(item, index, ctx) : null;
364
362
  }
365
363
  export {
366
364
  Header
@@ -44,14 +44,52 @@ interface HtmlPreviewWrapperProps {
44
44
  defaultOpen?: boolean;
45
45
  }
46
46
  /**
47
- * HTML preview wrapper component.
47
+ * Bare HTML preview body — the actual island **hydration target**.
48
48
  *
49
- * Merges `settings.htmlPreview` (global config) with per-usage props and
50
- * forwards everything to `<HtmlPreview>`. Wraps it in
51
- * `<Island when="visible">`, mirroring the legacy `client:visible`
52
- * hydration timing the iframe is heavy and not on the critical path,
53
- * so we defer hydration until the preview enters the viewport.
49
+ * Merges global (`settings.htmlPreview`) config with per-usage props and
50
+ * forwards everything to `<HtmlPreview>`. Renders the preview tree
51
+ * **directly**: it does NOT wrap itself in `<Island>`. `HtmlPreviewWrapper`
52
+ * below applies the `<Island when="visible">` wrapper around it.
53
+ *
54
+ * ## Island invariant (read before touching the displayName / Island wiring)
55
+ *
56
+ * The hydration-target export's NAME must equal its `displayName` (which
57
+ * becomes the `data-zfb-island="…"` marker), AND that export must NOT itself
58
+ * render an `<Island>`. The zfb scanner resolves the client hydration
59
+ * component by marker-name → export-name lookup; if the resolved export
60
+ * re-wraps in `Island()`, the client re-emits a second `data-zfb-island`
61
+ * wrapper and Preact reuses the SSR'd children one level off — re-parenting
62
+ * the preview + code sections inside the flex title bar (the broken
63
+ * side-by-side layout). This is the same class of bug fixed for
64
+ * Toc / MobileToc / Sidebar in zudolab/zudo-doc#1355 and was the original
65
+ * defect here (zudolab/zudo-doc#1925, an Astro→zfb migration regression):
66
+ * the inner bare component carried the *outer* wrapper's name
67
+ * (`displayName = "HtmlPreviewWrapper"`) and was not exported, so the marker
68
+ * resolved to the exported self-wrapping `HtmlPreviewWrapper` and the client
69
+ * double-wrapped. Fix: the bare component carries its OWN name
70
+ * (`HtmlPreviewWrapperInner`) and is exported, so the marker resolves to
71
+ * THIS bare component and the bundle hydrates it in-place.
72
+ */
73
+ declare function HtmlPreviewWrapperInner(props: HtmlPreviewWrapperProps): VNode;
74
+ declare namespace HtmlPreviewWrapperInner {
75
+ var displayName: string;
76
+ }
77
+ /**
78
+ * HTML preview wrapper component — the public MDX-registered binding
79
+ * (`HtmlPreview: HtmlPreviewWrapper`).
80
+ *
81
+ * Wraps the bare `HtmlPreviewWrapperInner` in `<Island when="visible">`,
82
+ * mirroring the legacy `client:visible` hydration timing — the iframe is
83
+ * heavy and not on the critical path, so hydration is deferred until the
84
+ * preview enters the viewport. The SSG output emits
85
+ * `data-zfb-island="HtmlPreviewWrapperInner"` around the bare tree, and the
86
+ * client bundle hydrates `HtmlPreviewWrapperInner` against it in-place.
87
+ *
88
+ * The public export name and signature are unchanged from before the
89
+ * zudolab/zudo-doc#1925 fix, so existing consumers that register
90
+ * `HtmlPreview: HtmlPreviewWrapper` keep working (and now hydrate correctly)
91
+ * with no call-site change.
54
92
  */
55
93
  declare function HtmlPreviewWrapper(props: HtmlPreviewWrapperProps): VNode;
56
94
 
57
- export { type HtmlPreviewGlobalConfig, HtmlPreviewWrapper, type HtmlPreviewWrapperProps };
95
+ export { type HtmlPreviewGlobalConfig, HtmlPreviewWrapper, HtmlPreviewWrapperInner, type HtmlPreviewWrapperProps };
@@ -23,7 +23,7 @@ function HtmlPreviewWrapperInner(props) {
23
23
  }
24
24
  );
25
25
  }
26
- HtmlPreviewWrapperInner.displayName = "HtmlPreviewWrapper";
26
+ HtmlPreviewWrapperInner.displayName = "HtmlPreviewWrapperInner";
27
27
  function HtmlPreviewWrapper(props) {
28
28
  const rendered = Island({
29
29
  when: "visible",
@@ -32,5 +32,6 @@ function HtmlPreviewWrapper(props) {
32
32
  return rendered;
33
33
  }
34
34
  export {
35
- HtmlPreviewWrapper
35
+ HtmlPreviewWrapper,
36
+ HtmlPreviewWrapperInner
36
37
  };
@@ -1,4 +1,4 @@
1
- export { HtmlPreviewGlobalConfig, HtmlPreviewWrapper, HtmlPreviewWrapperProps } from './html-preview-wrapper.js';
1
+ export { HtmlPreviewGlobalConfig, HtmlPreviewWrapper, HtmlPreviewWrapperInner, HtmlPreviewWrapperProps } from './html-preview-wrapper.js';
2
2
  export { HtmlPreview, HtmlPreviewProps } from './html-preview.js';
3
3
  export { CodeBlockData, PreviewBase, PreviewBaseProps } from './preview-base.js';
4
4
  export { HighlightedCode, HighlightedCodeProps } from './highlighted-code.js';
@@ -1,5 +1,6 @@
1
1
  import {
2
- HtmlPreviewWrapper
2
+ HtmlPreviewWrapper,
3
+ HtmlPreviewWrapperInner
3
4
  } from "./html-preview-wrapper.js";
4
5
  import { HtmlPreview } from "./html-preview.js";
5
6
  import { PreviewBase } from "./preview-base.js";
@@ -8,5 +9,6 @@ export {
8
9
  HighlightedCode,
9
10
  HtmlPreview,
10
11
  HtmlPreviewWrapper,
12
+ HtmlPreviewWrapperInner,
11
13
  PreviewBase
12
14
  };
@@ -0,0 +1,18 @@
1
+ import { VNode } from 'preact';
2
+
3
+ /** @jsxRuntime automatic */
4
+ /** @jsxImportSource preact */
5
+
6
+ interface IconProps {
7
+ /** CSS class string forwarded to the root `<svg>` element. */
8
+ className?: string;
9
+ }
10
+ declare function ChevronRight({ className }: IconProps): VNode;
11
+ declare function ChevronLeft({ className }: IconProps): VNode;
12
+ declare function Search({ className }: IconProps): VNode;
13
+ declare function History({ className }: IconProps): VNode;
14
+ declare function Close({ className }: IconProps): VNode;
15
+ declare function ArrowLeft({ className }: IconProps): VNode;
16
+ declare function GitHub({ className }: IconProps): VNode;
17
+
18
+ export { ArrowLeft, ChevronLeft, ChevronRight, Close, GitHub, History, type IconProps, Search };
@@ -0,0 +1,124 @@
1
+ import { jsx, jsxs } from "preact/jsx-runtime";
2
+ function ChevronRight({ className }) {
3
+ return /* @__PURE__ */ jsx(
4
+ "svg",
5
+ {
6
+ xmlns: "http://www.w3.org/2000/svg",
7
+ class: className || void 0,
8
+ fill: "none",
9
+ viewBox: "0 0 24 24",
10
+ stroke: "currentColor",
11
+ "stroke-width": "2",
12
+ "aria-hidden": "true",
13
+ children: /* @__PURE__ */ jsx("path", { "stroke-linecap": "round", "stroke-linejoin": "round", d: "M9 5l7 7-7 7" })
14
+ }
15
+ );
16
+ }
17
+ function ChevronLeft({ className }) {
18
+ return /* @__PURE__ */ jsx(
19
+ "svg",
20
+ {
21
+ xmlns: "http://www.w3.org/2000/svg",
22
+ class: className || void 0,
23
+ fill: "none",
24
+ viewBox: "0 0 24 24",
25
+ stroke: "currentColor",
26
+ "stroke-width": "2",
27
+ "aria-hidden": "true",
28
+ children: /* @__PURE__ */ jsx("path", { "stroke-linecap": "round", "stroke-linejoin": "round", d: "M15 19l-7-7 7-7" })
29
+ }
30
+ );
31
+ }
32
+ function Search({ className }) {
33
+ return /* @__PURE__ */ jsx(
34
+ "svg",
35
+ {
36
+ xmlns: "http://www.w3.org/2000/svg",
37
+ class: className || void 0,
38
+ fill: "none",
39
+ viewBox: "0 0 24 24",
40
+ stroke: "currentColor",
41
+ "stroke-width": "2",
42
+ "aria-hidden": "true",
43
+ children: /* @__PURE__ */ jsx("path", { "stroke-linecap": "round", "stroke-linejoin": "round", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" })
44
+ }
45
+ );
46
+ }
47
+ function History({ className }) {
48
+ return /* @__PURE__ */ jsxs(
49
+ "svg",
50
+ {
51
+ xmlns: "http://www.w3.org/2000/svg",
52
+ class: className || void 0,
53
+ viewBox: "0 0 24 24",
54
+ fill: "none",
55
+ stroke: "currentColor",
56
+ "stroke-width": "2",
57
+ "stroke-linecap": "round",
58
+ "stroke-linejoin": "round",
59
+ "aria-hidden": "true",
60
+ children: [
61
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
62
+ /* @__PURE__ */ jsx("polyline", { points: "12 6 12 12 16 14" })
63
+ ]
64
+ }
65
+ );
66
+ }
67
+ function Close({ className }) {
68
+ return /* @__PURE__ */ jsx(
69
+ "svg",
70
+ {
71
+ xmlns: "http://www.w3.org/2000/svg",
72
+ class: className || void 0,
73
+ viewBox: "0 0 24 24",
74
+ fill: "none",
75
+ stroke: "currentColor",
76
+ "stroke-width": "2",
77
+ "stroke-linecap": "round",
78
+ "stroke-linejoin": "round",
79
+ "aria-hidden": "true",
80
+ children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" })
81
+ }
82
+ );
83
+ }
84
+ function ArrowLeft({ className }) {
85
+ return /* @__PURE__ */ jsx(
86
+ "svg",
87
+ {
88
+ xmlns: "http://www.w3.org/2000/svg",
89
+ class: className || void 0,
90
+ viewBox: "0 0 24 24",
91
+ fill: "none",
92
+ stroke: "currentColor",
93
+ "stroke-width": "2",
94
+ "stroke-linecap": "round",
95
+ "stroke-linejoin": "round",
96
+ "aria-hidden": "true",
97
+ children: /* @__PURE__ */ jsx("path", { d: "M19 12H5M12 19l-7-7 7-7" })
98
+ }
99
+ );
100
+ }
101
+ function GitHub({ className }) {
102
+ return /* @__PURE__ */ jsx(
103
+ "svg",
104
+ {
105
+ xmlns: "http://www.w3.org/2000/svg",
106
+ width: "20",
107
+ height: "20",
108
+ viewBox: "0 0 24 24",
109
+ fill: "currentColor",
110
+ class: className || void 0,
111
+ "aria-hidden": "true",
112
+ children: /* @__PURE__ */ jsx("path", { d: "M12 .5C5.649.5.5 5.649.5 12a11.5 11.5 0 0 0 7.86 10.915c.575.106.785-.25.785-.556 0-.274-.01-1-.016-1.962-3.198.695-3.873-1.541-3.873-1.541-.523-1.327-1.277-1.68-1.277-1.68-1.044-.714.079-.699.079-.699 1.154.082 1.761 1.186 1.761 1.186 1.026 1.758 2.692 1.25 3.348.956.104-.743.401-1.25.73-1.537-2.553-.29-5.238-1.276-5.238-5.682 0-1.255.448-2.282 1.182-3.086-.119-.29-.512-1.458.111-3.04 0 0 .964-.309 3.159 1.18A10.98 10.98 0 0 1 12 6.036c.977.005 1.963.132 2.883.387 2.193-1.49 3.155-1.18 3.155-1.18.625 1.582.232 2.75.114 3.04.736.804 1.18 1.831 1.18 3.086 0 4.417-2.689 5.389-5.25 5.673.412.355.779 1.056.779 2.129 0 1.538-.014 2.778-.014 3.156 0 .31.207.668.79.555A11.502 11.502 0 0 0 23.5 12C23.5 5.649 18.351.5 12 .5Z" })
113
+ }
114
+ );
115
+ }
116
+ export {
117
+ ArrowLeft,
118
+ ChevronLeft,
119
+ ChevronRight,
120
+ Close,
121
+ GitHub,
122
+ History,
123
+ Search
124
+ };
@@ -76,31 +76,40 @@ function generateClaudemdDocs(config) {
76
76
  ensureDir(outputDir);
77
77
  const items = [];
78
78
  for (const filePath of files) {
79
- const content = fs.readFileSync(filePath, "utf8");
80
79
  const relPath = path.relative(projectRoot, filePath);
81
80
  const displayPath = `/${relPath}`;
82
81
  const dirPart = path.dirname(relPath);
83
82
  const slug = dirPart === "." ? "root" : dirPart.replace(/\//g, "--");
84
83
  items.push({ displayPath, slug, relPath });
85
- const pos = items.length + 1;
84
+ }
85
+ items.sort((a, b) => {
86
+ if (a.slug === "root") return -1;
87
+ if (b.slug === "root") return 1;
88
+ return a.displayPath.localeCompare(b.displayPath);
89
+ });
90
+ const emittedSlugs = /* @__PURE__ */ new Map();
91
+ items.forEach((item, index) => {
92
+ const previous = emittedSlugs.get(item.slug);
93
+ if (previous !== void 0) {
94
+ throw new Error(
95
+ `claude-resources: slug collision \u2014 "${item.slug}" is produced by both "${previous}" and "${item.relPath}". Rename one of the directories to resolve the conflict.`
96
+ );
97
+ }
98
+ emittedSlugs.set(item.slug, item.relPath);
99
+ const content = fs.readFileSync(path.join(projectRoot, item.relPath), "utf8");
86
100
  const mdx = `---
87
- title: "${escapeTitle(displayPath)}"
88
- description: "CLAUDE.md at ${escapeTitle(displayPath)}"
89
- sidebar_position: ${pos}
90
- sidebar_label: "${escapeTitle(relPath)}"
101
+ title: "${escapeTitle(item.displayPath)}"
102
+ description: "CLAUDE.md at ${escapeTitle(item.displayPath)}"
103
+ sidebar_position: ${index + 1}
104
+ sidebar_label: "${escapeTitle(item.relPath)}"
91
105
  generated: true
92
106
  ---
93
107
 
94
- **Path:** \`${relPath}\`
108
+ **Path:** \`${item.relPath}\`
95
109
 
96
110
  ${escapeForMdx(content.trim())}
97
111
  `;
98
- fs.writeFileSync(path.join(outputDir, `${slug}.mdx`), mdx);
99
- }
100
- items.sort((a, b) => {
101
- if (a.slug === "root") return -1;
102
- if (b.slug === "root") return 1;
103
- return a.displayPath.localeCompare(b.displayPath);
112
+ fs.writeFileSync(path.join(outputDir, `${item.slug}.mdx`), mdx);
104
113
  });
105
114
  writeCategoryMeta(outputDir, "CLAUDE.md", 900, "Project-specific instructions");
106
115
  return items;
@@ -2,9 +2,7 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import {
4
4
  collectContentFiles,
5
- getFileCommits,
6
- getFirstCommit,
7
- getCommitInfo
5
+ getFileCommitsMeta
8
6
  } from "@takazudo/zudo-doc-history-server/git-history";
9
7
  const META_OUT_RELATIVE_DIR = ".zfb";
10
8
  const META_OUT_FILENAME = "doc-history-meta.json";
@@ -33,11 +31,10 @@ async function runDocHistoryMetaStep(options) {
33
31
  for (const [localeKey, contentDir] of dirEntries) {
34
32
  const files = collectContentFiles(contentDir);
35
33
  for (const { filePath, slug } of files) {
36
- const commits = getFileCommits(filePath, 1);
37
- if (commits.length === 0) continue;
38
- const newestInfo = getCommitInfo(commits[0], filePath);
39
- const firstHash = getFirstCommit(filePath);
40
- const oldestInfo = firstHash && firstHash !== commits[0] ? getCommitInfo(firstHash, filePath) : newestInfo;
34
+ const allCommits = getFileCommitsMeta(filePath);
35
+ if (allCommits.length === 0) continue;
36
+ const newestInfo = allCommits[0];
37
+ const oldestInfo = allCommits[allCommits.length - 1] ?? newestInfo;
41
38
  const composedSlug = localeKey ? `${localeKey}/${slug}` : slug;
42
39
  meta[composedSlug] = {
43
40
  // Author comes from the FIRST (oldest) commit.
@@ -17,7 +17,7 @@ function collectMdFiles(dir) {
17
17
  if (entry.name.startsWith("_")) continue;
18
18
  walk(fullPath, baseDir);
19
19
  } else if (/\.mdx?$/.test(entry.name) && !entry.name.startsWith("_")) {
20
- const rel = relative(baseDir, fullPath).replace(/\.mdx?$/, "").replace(/\/index$/, "");
20
+ const rel = relative(baseDir, fullPath).replace(/\.mdx?$/, "").replace(/\/index$/, "").replace(/^index$/, "");
21
21
  results.push({ filePath: fullPath, slug: rel });
22
22
  }
23
23
  }
@@ -19,7 +19,7 @@ function collectMdFiles(dir) {
19
19
  if (entry.name.startsWith("_")) continue;
20
20
  walk(fullPath, baseDir);
21
21
  } else if (/\.mdx?$/.test(entry.name) && !entry.name.startsWith("_")) {
22
- const rel = relative(baseDir, fullPath).replace(/\.mdx?$/, "").replace(/\/index$/, "");
22
+ const rel = relative(baseDir, fullPath).replace(/\.mdx?$/, "").replace(/\/index$/, "").replace(/^index$/, "");
23
23
  results.push({ filePath: fullPath, slug: rel });
24
24
  }
25
25
  }
@@ -1,4 +1,5 @@
1
1
  import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
2
+ import { ChevronRight } from "../icons/index.js";
2
3
  function VersionsPageContent(props) {
3
4
  const { latestHref, versions, labels } = props;
4
5
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -13,25 +14,7 @@ function VersionsPageContent(props) {
13
14
  class: "inline-flex items-center gap-hsp-xs text-small text-accent underline hover:text-accent-hover",
14
15
  children: [
15
16
  labels.latestLink,
16
- /* @__PURE__ */ jsx(
17
- "svg",
18
- {
19
- xmlns: "http://www.w3.org/2000/svg",
20
- class: "h-[0.875rem] w-[0.875rem]",
21
- fill: "none",
22
- viewBox: "0 0 24 24",
23
- stroke: "currentColor",
24
- "stroke-width": "2",
25
- children: /* @__PURE__ */ jsx(
26
- "path",
27
- {
28
- "stroke-linecap": "round",
29
- "stroke-linejoin": "round",
30
- d: "M9 5l7 7-7 7"
31
- }
32
- )
33
- }
34
- )
17
+ /* @__PURE__ */ jsx(ChevronRight, { className: "h-[0.875rem] w-[0.875rem]" })
35
18
  ]
36
19
  }
37
20
  )
@@ -1,4 +1,3 @@
1
- import {} from "@takazudo/zdtp";
2
1
  import {
3
2
  emptyOverrides
4
3
  } from "./design-token-types.js";
@@ -22,6 +22,6 @@ declare function smartBreak(text: string): VNode | string;
22
22
  */
23
23
  declare function SmartBreak({ children }: {
24
24
  children?: unknown;
25
- }): any;
25
+ }): VNode;
26
26
 
27
27
  export { SmartBreak, isPathLike, smartBreak };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takazudo/zudo-doc",
3
- "version": "0.2.0-next.3",
3
+ "version": "0.2.0-next.6",
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",
@@ -146,6 +146,10 @@
146
146
  "./url-normalizer": {
147
147
  "types": "./dist/url-normalizer/index.d.ts",
148
148
  "default": "./dist/url-normalizer/index.js"
149
+ },
150
+ "./icons": {
151
+ "types": "./dist/icons/index.d.ts",
152
+ "default": "./dist/icons/index.js"
149
153
  }
150
154
  },
151
155
  "files": [
@@ -154,13 +158,17 @@
154
158
  ],
155
159
  "peerDependencies": {
156
160
  "preact": "^10.29.1",
157
- "@takazudo/zfb": "^0.1.0-next.28",
158
- "@takazudo/zfb-runtime": "^0.1.0-next.28",
159
- "@takazudo/zudo-doc-history-server": "^0.2.0-next.3"
161
+ "@takazudo/zfb": "^0.1.0-next.31",
162
+ "@takazudo/zfb-runtime": "^0.1.0-next.31",
163
+ "@takazudo/zdtp": "^0.2.0-next.2",
164
+ "@takazudo/zudo-doc-history-server": "^0.2.0-next.6"
160
165
  },
161
166
  "peerDependenciesMeta": {
162
167
  "@takazudo/zudo-doc-history-server": {
163
168
  "optional": true
169
+ },
170
+ "@takazudo/zdtp": {
171
+ "optional": true
164
172
  }
165
173
  },
166
174
  "dependencies": {
@@ -174,8 +182,8 @@
174
182
  "tsup": "^8.0.0",
175
183
  "typescript": "^5.0.0",
176
184
  "vitest": "^3.0.0",
177
- "@takazudo/zfb": "0.1.0-next.28",
178
- "@takazudo/zfb-runtime": "0.1.0-next.28"
185
+ "@takazudo/zfb": "0.1.0-next.31",
186
+ "@takazudo/zfb-runtime": "0.1.0-next.31"
179
187
  },
180
188
  "scripts": {
181
189
  "build": "cross-env NODE_OPTIONS=--max-old-space-size=4096 tsup",