@takazudo/zudo-doc 0.1.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.
Files changed (255) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +18 -0
  3. package/dist/body-foot-util/body-foot-util-area.d.ts +55 -0
  4. package/dist/body-foot-util/body-foot-util-area.js +71 -0
  5. package/dist/body-foot-util/edit-link.d.ts +45 -0
  6. package/dist/body-foot-util/edit-link.js +42 -0
  7. package/dist/body-foot-util/index.d.ts +3 -0
  8. package/dist/body-foot-util/index.js +11 -0
  9. package/dist/breadcrumb/breadcrumb.d.ts +57 -0
  10. package/dist/breadcrumb/breadcrumb.js +113 -0
  11. package/dist/breadcrumb/find-path.d.ts +16 -0
  12. package/dist/breadcrumb/find-path.js +13 -0
  13. package/dist/breadcrumb/index.d.ts +4 -0
  14. package/dist/breadcrumb/index.js +7 -0
  15. package/dist/breadcrumb/types.d.ts +32 -0
  16. package/dist/breadcrumb/types.js +0 -0
  17. package/dist/code-syntax/code-block-enhancer-script.d.ts +3 -0
  18. package/dist/code-syntax/code-block-enhancer-script.js +165 -0
  19. package/dist/code-syntax/code-block-enhancer.d.ts +22 -0
  20. package/dist/code-syntax/code-block-enhancer.js +13 -0
  21. package/dist/code-syntax/index.d.ts +8 -0
  22. package/dist/code-syntax/index.js +29 -0
  23. package/dist/code-syntax/mermaid-init-script.d.ts +51 -0
  24. package/dist/code-syntax/mermaid-init-script.js +225 -0
  25. package/dist/code-syntax/mermaid-init.d.ts +48 -0
  26. package/dist/code-syntax/mermaid-init.js +14 -0
  27. package/dist/code-syntax/tabs-init-script.d.ts +3 -0
  28. package/dist/code-syntax/tabs-init-script.js +106 -0
  29. package/dist/code-syntax/tabs-init.d.ts +24 -0
  30. package/dist/code-syntax/tabs-init.js +10 -0
  31. package/dist/code-syntax/tabs.d.ts +36 -0
  32. package/dist/code-syntax/tabs.js +62 -0
  33. package/dist/content/component-map.d.ts +51 -0
  34. package/dist/content/component-map.js +29 -0
  35. package/dist/content/content-blockquote.d.ts +11 -0
  36. package/dist/content/content-blockquote.js +14 -0
  37. package/dist/content/content-code.d.ts +26 -0
  38. package/dist/content/content-code.js +39 -0
  39. package/dist/content/content-link.d.ts +12 -0
  40. package/dist/content/content-link.js +43 -0
  41. package/dist/content/content-ol.d.ts +11 -0
  42. package/dist/content/content-ol.js +15 -0
  43. package/dist/content/content-paragraph.d.ts +10 -0
  44. package/dist/content/content-paragraph.js +7 -0
  45. package/dist/content/content-strong.d.ts +11 -0
  46. package/dist/content/content-strong.js +14 -0
  47. package/dist/content/content-table.d.ts +11 -0
  48. package/dist/content/content-table.js +14 -0
  49. package/dist/content/content-ul.d.ts +11 -0
  50. package/dist/content/content-ul.js +15 -0
  51. package/dist/content/heading-h2.d.ts +14 -0
  52. package/dist/content/heading-h2.js +18 -0
  53. package/dist/content/heading-h3.d.ts +14 -0
  54. package/dist/content/heading-h3.js +18 -0
  55. package/dist/content/heading-h4.d.ts +14 -0
  56. package/dist/content/heading-h4.js +18 -0
  57. package/dist/content/index.d.ts +13 -0
  58. package/dist/content/index.js +27 -0
  59. package/dist/details/details.d.ts +26 -0
  60. package/dist/details/details.js +10 -0
  61. package/dist/details/index.d.ts +2 -0
  62. package/dist/details/index.js +4 -0
  63. package/dist/doclayout/anchors.d.ts +55 -0
  64. package/dist/doclayout/anchors.js +42 -0
  65. package/dist/doclayout/doc-layout-with-defaults.d.ts +83 -0
  66. package/dist/doclayout/doc-layout-with-defaults.js +159 -0
  67. package/dist/doclayout/doc-layout.d.ts +121 -0
  68. package/dist/doclayout/doc-layout.js +89 -0
  69. package/dist/doclayout/index.d.ts +6 -0
  70. package/dist/doclayout/index.js +17 -0
  71. package/dist/footer/footer.d.ts +42 -0
  72. package/dist/footer/footer.js +79 -0
  73. package/dist/footer/index.d.ts +3 -0
  74. package/dist/footer/index.js +4 -0
  75. package/dist/footer/types.d.ts +58 -0
  76. package/dist/footer/types.js +0 -0
  77. package/dist/head/doc-head.d.ts +33 -0
  78. package/dist/head/doc-head.js +90 -0
  79. package/dist/head/index.d.ts +5 -0
  80. package/dist/head/index.js +8 -0
  81. package/dist/head/og-tags.d.ts +25 -0
  82. package/dist/head/og-tags.js +16 -0
  83. package/dist/head/twitter-card.d.ts +21 -0
  84. package/dist/head/twitter-card.js +14 -0
  85. package/dist/head/types.d.ts +83 -0
  86. package/dist/head/types.js +0 -0
  87. package/dist/header/header.d.ts +158 -0
  88. package/dist/header/header.js +367 -0
  89. package/dist/header/index.d.ts +6 -0
  90. package/dist/header/index.js +18 -0
  91. package/dist/header/nav-active.d.ts +39 -0
  92. package/dist/header/nav-active.js +24 -0
  93. package/dist/header/nav-overflow-script.d.ts +3 -0
  94. package/dist/header/nav-overflow-script.js +169 -0
  95. package/dist/header/right-items.d.ts +38 -0
  96. package/dist/header/right-items.js +30 -0
  97. package/dist/header/types.d.ts +40 -0
  98. package/dist/header/types.js +0 -0
  99. package/dist/html-preview-wrapper/dedent.d.ts +10 -0
  100. package/dist/html-preview-wrapper/dedent.js +16 -0
  101. package/dist/html-preview-wrapper/highlighted-code.d.ts +18 -0
  102. package/dist/html-preview-wrapper/highlighted-code.js +53 -0
  103. package/dist/html-preview-wrapper/html-preview-wrapper.d.ts +60 -0
  104. package/dist/html-preview-wrapper/html-preview-wrapper.js +36 -0
  105. package/dist/html-preview-wrapper/html-preview.d.ts +35 -0
  106. package/dist/html-preview-wrapper/html-preview.js +75 -0
  107. package/dist/html-preview-wrapper/index.d.ts +5 -0
  108. package/dist/html-preview-wrapper/index.js +12 -0
  109. package/dist/html-preview-wrapper/preflight.d.ts +13 -0
  110. package/dist/html-preview-wrapper/preflight.js +108 -0
  111. package/dist/html-preview-wrapper/preview-base.d.ts +29 -0
  112. package/dist/html-preview-wrapper/preview-base.js +127 -0
  113. package/dist/i18n-version/index.d.ts +5 -0
  114. package/dist/i18n-version/index.js +14 -0
  115. package/dist/i18n-version/language-switcher.d.ts +24 -0
  116. package/dist/i18n-version/language-switcher.js +25 -0
  117. package/dist/i18n-version/types.d.ts +43 -0
  118. package/dist/i18n-version/types.js +0 -0
  119. package/dist/i18n-version/version-banner.d.ts +30 -0
  120. package/dist/i18n-version/version-banner.js +21 -0
  121. package/dist/i18n-version/version-switcher.d.ts +112 -0
  122. package/dist/i18n-version/version-switcher.js +157 -0
  123. package/dist/index.d.ts +2 -0
  124. package/dist/index.js +0 -0
  125. package/dist/integrations/claude-resources/escape-for-mdx.d.ts +8 -0
  126. package/dist/integrations/claude-resources/escape-for-mdx.js +131 -0
  127. package/dist/integrations/claude-resources/generate.d.ts +13 -0
  128. package/dist/integrations/claude-resources/generate.js +404 -0
  129. package/dist/integrations/claude-resources/index.d.ts +46 -0
  130. package/dist/integrations/claude-resources/index.js +24 -0
  131. package/dist/integrations/doc-history/index.d.ts +137 -0
  132. package/dist/integrations/doc-history/index.js +138 -0
  133. package/dist/integrations/doc-history/pre-build.d.ts +58 -0
  134. package/dist/integrations/doc-history/pre-build.js +67 -0
  135. package/dist/integrations/llms-txt/dev-middleware.d.ts +40 -0
  136. package/dist/integrations/llms-txt/dev-middleware.js +76 -0
  137. package/dist/integrations/llms-txt/emit.d.ts +22 -0
  138. package/dist/integrations/llms-txt/emit.js +55 -0
  139. package/dist/integrations/llms-txt/generate.d.ts +26 -0
  140. package/dist/integrations/llms-txt/generate.js +36 -0
  141. package/dist/integrations/llms-txt/index.d.ts +7 -0
  142. package/dist/integrations/llms-txt/index.js +27 -0
  143. package/dist/integrations/llms-txt/load.d.ts +51 -0
  144. package/dist/integrations/llms-txt/load.js +83 -0
  145. package/dist/integrations/llms-txt/strip.d.ts +22 -0
  146. package/dist/integrations/llms-txt/strip.js +10 -0
  147. package/dist/integrations/llms-txt/types.d.ts +145 -0
  148. package/dist/integrations/llms-txt/types.js +0 -0
  149. package/dist/integrations/search-index/build-emitter.d.ts +30 -0
  150. package/dist/integrations/search-index/build-emitter.js +15 -0
  151. package/dist/integrations/search-index/collect.d.ts +12 -0
  152. package/dist/integrations/search-index/collect.js +48 -0
  153. package/dist/integrations/search-index/content-files.d.ts +32 -0
  154. package/dist/integrations/search-index/content-files.js +50 -0
  155. package/dist/integrations/search-index/dev-middleware.d.ts +16 -0
  156. package/dist/integrations/search-index/dev-middleware.js +30 -0
  157. package/dist/integrations/search-index/index.d.ts +5 -0
  158. package/dist/integrations/search-index/index.js +14 -0
  159. package/dist/integrations/search-index/types.d.ts +38 -0
  160. package/dist/integrations/search-index/types.js +6 -0
  161. package/dist/metainfo/doc-metainfo.d.ts +50 -0
  162. package/dist/metainfo/doc-metainfo.js +107 -0
  163. package/dist/metainfo/doc-tags.d.ts +66 -0
  164. package/dist/metainfo/doc-tags.js +53 -0
  165. package/dist/metainfo/frontmatter-preview.d.ts +95 -0
  166. package/dist/metainfo/frontmatter-preview.js +55 -0
  167. package/dist/metainfo/index.d.ts +4 -0
  168. package/dist/metainfo/index.js +28 -0
  169. package/dist/nav-indexing/category-nav.d.ts +28 -0
  170. package/dist/nav-indexing/category-nav.js +41 -0
  171. package/dist/nav-indexing/category-tree-nav.d.ts +27 -0
  172. package/dist/nav-indexing/category-tree-nav.js +49 -0
  173. package/dist/nav-indexing/doc-card-grid.d.ts +38 -0
  174. package/dist/nav-indexing/doc-card-grid.js +40 -0
  175. package/dist/nav-indexing/docs-sitemap.d.ts +25 -0
  176. package/dist/nav-indexing/docs-sitemap.js +40 -0
  177. package/dist/nav-indexing/index.d.ts +10 -0
  178. package/dist/nav-indexing/index.js +18 -0
  179. package/dist/nav-indexing/nav-card-grid.d.ts +31 -0
  180. package/dist/nav-indexing/nav-card-grid.js +43 -0
  181. package/dist/nav-indexing/site-tree-nav-demo.d.ts +39 -0
  182. package/dist/nav-indexing/site-tree-nav-demo.js +65 -0
  183. package/dist/nav-indexing/tag-nav.d.ts +38 -0
  184. package/dist/nav-indexing/tag-nav.js +96 -0
  185. package/dist/nav-indexing/types.d.ts +95 -0
  186. package/dist/nav-indexing/types.js +0 -0
  187. package/dist/nav-indexing/versions-page-content.d.ts +29 -0
  188. package/dist/nav-indexing/versions-page-content.js +76 -0
  189. package/dist/page-loading/index.d.ts +2 -0
  190. package/dist/page-loading/index.js +10 -0
  191. package/dist/page-loading/page-loading-overlay.d.ts +35 -0
  192. package/dist/page-loading/page-loading-overlay.js +50 -0
  193. package/dist/sidebar/index.d.ts +3 -0
  194. package/dist/sidebar/index.js +4 -0
  195. package/dist/sidebar/sidebar.d.ts +54 -0
  196. package/dist/sidebar/sidebar.js +35 -0
  197. package/dist/sidebar/types.d.ts +71 -0
  198. package/dist/sidebar/types.js +0 -0
  199. package/dist/sidebar-resizer/index.d.ts +14 -0
  200. package/dist/sidebar-resizer/index.js +165 -0
  201. package/dist/sidebar-resizer/sidebar-resizer-init.d.ts +20 -0
  202. package/dist/sidebar-resizer/sidebar-resizer-init.js +119 -0
  203. package/dist/sidebar-tree/build-tree.d.ts +43 -0
  204. package/dist/sidebar-tree/build-tree.js +127 -0
  205. package/dist/sidebar-tree/category-meta.d.ts +19 -0
  206. package/dist/sidebar-tree/category-meta.js +63 -0
  207. package/dist/sidebar-tree/index.d.ts +3 -0
  208. package/dist/sidebar-tree/index.js +13 -0
  209. package/dist/sidebar-tree/types.d.ts +120 -0
  210. package/dist/sidebar-tree/types.js +0 -0
  211. package/dist/tab-item/index.d.ts +2 -0
  212. package/dist/tab-item/index.js +5 -0
  213. package/dist/tab-item/tab-item.d.ts +38 -0
  214. package/dist/tab-item/tab-item.js +25 -0
  215. package/dist/theme/color-scheme-provider.d.ts +32 -0
  216. package/dist/theme/color-scheme-provider.js +43 -0
  217. package/dist/theme/color-tweak-export-modal.d.ts +20 -0
  218. package/dist/theme/color-tweak-export-modal.js +138 -0
  219. package/dist/theme/design-token-serde.d.ts +136 -0
  220. package/dist/theme/design-token-serde.js +254 -0
  221. package/dist/theme/design-token-tweak-panel.d.ts +11 -0
  222. package/dist/theme/design-token-tweak-panel.js +10 -0
  223. package/dist/theme/design-token-types.d.ts +19 -0
  224. package/dist/theme/design-token-types.js +6 -0
  225. package/dist/theme/iframe-bridge.d.ts +44 -0
  226. package/dist/theme/iframe-bridge.js +70 -0
  227. package/dist/theme/index.d.ts +9 -0
  228. package/dist/theme/index.js +42 -0
  229. package/dist/theme/theme-toggle.d.ts +17 -0
  230. package/dist/theme/theme-toggle.js +91 -0
  231. package/dist/toc/cx.d.ts +16 -0
  232. package/dist/toc/cx.js +22 -0
  233. package/dist/toc/index.d.ts +5 -0
  234. package/dist/toc/index.js +9 -0
  235. package/dist/toc/mobile-toc.d.ts +46 -0
  236. package/dist/toc/mobile-toc.js +88 -0
  237. package/dist/toc/smart-break.d.ts +27 -0
  238. package/dist/toc/smart-break.js +36 -0
  239. package/dist/toc/toc-title.d.ts +10 -0
  240. package/dist/toc/toc-title.js +14 -0
  241. package/dist/toc/toc.d.ts +60 -0
  242. package/dist/toc/toc.js +56 -0
  243. package/dist/toc/types.d.ts +23 -0
  244. package/dist/toc/types.js +0 -0
  245. package/dist/toc/use-active-heading.d.ts +30 -0
  246. package/dist/toc/use-active-heading.js +106 -0
  247. package/dist/transitions/index.d.ts +1 -0
  248. package/dist/transitions/index.js +12 -0
  249. package/dist/transitions/page-events.d.ts +41 -0
  250. package/dist/transitions/page-events.js +20 -0
  251. package/dist/url-normalizer/index.d.ts +1 -0
  252. package/dist/url-normalizer/index.js +6 -0
  253. package/dist/url-normalizer/normalize.d.ts +104 -0
  254. package/dist/url-normalizer/normalize.js +22 -0
  255. package/package.json +186 -0
@@ -0,0 +1,89 @@
1
+ import { jsx, jsxs } from "preact/jsx-runtime";
2
+ import { ClientRouter } from "@takazudo/zfb-runtime";
3
+ const DESKTOP_SIDEBAR_ID = "desktop-sidebar";
4
+ function DocLayout(props) {
5
+ const {
6
+ title,
7
+ description,
8
+ noindex,
9
+ lang = "en",
10
+ dataTheme,
11
+ htmlStyle,
12
+ head,
13
+ header,
14
+ sidebar,
15
+ hideSidebar = false,
16
+ sidebarPersistKey,
17
+ afterSidebar,
18
+ breadcrumb,
19
+ afterBreadcrumb,
20
+ mobileToc,
21
+ main,
22
+ afterContent,
23
+ toc,
24
+ hideToc = false,
25
+ footer,
26
+ bodyEndComponents,
27
+ bodyEndScripts
28
+ } = props;
29
+ const hasSidebar = sidebar !== void 0;
30
+ const showSidebar = !hideSidebar && hasSidebar;
31
+ const showToc = !hideToc && toc !== void 0;
32
+ const htmlAttrs = { lang };
33
+ if (dataTheme !== void 0) {
34
+ htmlAttrs["data-theme"] = dataTheme;
35
+ }
36
+ if (htmlStyle !== void 0) {
37
+ htmlAttrs.style = htmlStyle;
38
+ }
39
+ return /* @__PURE__ */ jsxs("html", { ...htmlAttrs, children: [
40
+ /* @__PURE__ */ jsxs("head", { children: [
41
+ /* @__PURE__ */ jsx("meta", { charSet: "utf-8" }),
42
+ /* @__PURE__ */ jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }),
43
+ /* @__PURE__ */ jsx("title", { children: title }),
44
+ description !== void 0 && /* @__PURE__ */ jsx("meta", { name: "description", content: description }),
45
+ noindex && /* @__PURE__ */ jsx("meta", { name: "robots", content: "noindex, nofollow" }),
46
+ ClientRouter(),
47
+ head
48
+ ] }),
49
+ /* @__PURE__ */ jsxs("body", { class: "min-h-screen antialiased", children: [
50
+ header,
51
+ hasSidebar && /* @__PURE__ */ jsx(
52
+ "aside",
53
+ {
54
+ id: DESKTOP_SIDEBAR_ID,
55
+ "aria-label": "Documentation sidebar",
56
+ class: showSidebar ? "hidden lg:block fixed top-[3.5rem] left-0 z-30 w-[var(--zd-sidebar-w)] h-[calc(100vh-3.5rem)] overflow-y-auto bg-bg border-r border-muted pb-vsp-xl" : "sr-only",
57
+ ...sidebarPersistKey !== void 0 ? { "data-zfb-transition-persist": sidebarPersistKey } : {},
58
+ children: sidebar
59
+ }
60
+ ),
61
+ afterSidebar,
62
+ /* @__PURE__ */ jsxs("div", { class: showSidebar ? "lg:ml-[var(--zd-sidebar-w)]" : void 0, children: [
63
+ /* @__PURE__ */ jsx("div", { class: "flex min-h-[calc(100vh-3.5rem)] justify-center", children: /* @__PURE__ */ jsxs(
64
+ "div",
65
+ {
66
+ class: `flex w-full gap-[clamp(1.5rem,3vw,4rem)] ${showSidebar ? "max-w-[clamp(50rem,75vw,90rem)]" : "max-w-[80rem]"}`,
67
+ children: [
68
+ /* @__PURE__ */ jsxs("main", { class: "flex-1 min-w-0 px-hsp-xl py-vsp-xl lg:px-hsp-2xl lg:py-vsp-2xl", children: [
69
+ breadcrumb,
70
+ afterBreadcrumb,
71
+ !hideToc && mobileToc,
72
+ /* @__PURE__ */ jsx("article", { class: "zd-content max-w-none", children: main }),
73
+ afterContent
74
+ ] }),
75
+ showToc && toc
76
+ ]
77
+ }
78
+ ) }),
79
+ footer
80
+ ] }),
81
+ bodyEndComponents,
82
+ bodyEndScripts
83
+ ] })
84
+ ] });
85
+ }
86
+ export {
87
+ DESKTOP_SIDEBAR_ID,
88
+ DocLayout
89
+ };
@@ -0,0 +1,6 @@
1
+ export { DESKTOP_SIDEBAR_ID, DocLayout, DocLayoutHtmlAttrs, DocLayoutProps } from './doc-layout.js';
2
+ export { DocLayoutWithDefaults, DocLayoutWithDefaultsProps } from './doc-layout-with-defaults.js';
3
+ export { DOC_LAYOUT_ANCHORS, DOC_LAYOUT_ANCHOR_IDS, DocLayoutAnchor, DocLayoutAnchorId, DocLayoutAnchorKind, allAnchorComments, anchorComment } from './anchors.js';
4
+ import 'preact';
5
+ import '../toc/types.js';
6
+ import '../i18n-version/version-banner.js';
@@ -0,0 +1,17 @@
1
+ import { DocLayout, DESKTOP_SIDEBAR_ID } from "./doc-layout.js";
2
+ import { DocLayoutWithDefaults } from "./doc-layout-with-defaults.js";
3
+ import {
4
+ DOC_LAYOUT_ANCHORS,
5
+ DOC_LAYOUT_ANCHOR_IDS,
6
+ allAnchorComments,
7
+ anchorComment
8
+ } from "./anchors.js";
9
+ export {
10
+ DESKTOP_SIDEBAR_ID,
11
+ DOC_LAYOUT_ANCHORS,
12
+ DOC_LAYOUT_ANCHOR_IDS,
13
+ DocLayout,
14
+ DocLayoutWithDefaults,
15
+ allAnchorComments,
16
+ anchorComment
17
+ };
@@ -0,0 +1,42 @@
1
+ import { VNode } from 'preact';
2
+ import { FooterLinkColumn, FooterTagColumn } from './types.js';
3
+
4
+ /** @jsxRuntime automatic */
5
+ /** @jsxImportSource preact */
6
+
7
+ interface FooterProps {
8
+ /**
9
+ * Already-localized link columns. Each item's href should be
10
+ * base-prefixed and locale-aware; `isExternal` controls the
11
+ * target/rel attributes.
12
+ */
13
+ linkColumns?: FooterLinkColumn[];
14
+ /**
15
+ * Already-resolved tag columns. Empty array (or omitted) hides the
16
+ * taglist entirely. Each tag's href should already be base-prefixed.
17
+ */
18
+ tagColumns?: FooterTagColumn[];
19
+ /**
20
+ * Copyright HTML. Rendered via `dangerouslySetInnerHTML` so embedded
21
+ * anchors work. The caller is responsible for the contents.
22
+ */
23
+ copyright?: string;
24
+ /**
25
+ * When provided, adds `data-zfb-transition-persist` to the `<footer>`
26
+ * element. Use a locale-keyed value (e.g. `footer-en`, `footer-ja`) so
27
+ * cross-locale swaps discard the stale footer while same-locale swaps
28
+ * preserve DOM-node identity. See zudolab/zudo-doc#1546.
29
+ */
30
+ persistKey?: string;
31
+ }
32
+ /**
33
+ * Footer shell for the documentation layout.
34
+ *
35
+ * Always renders the `<footer>` shell so the contentinfo ARIA landmark
36
+ * is present on every page — even when no columns or copyright are
37
+ * configured. The inner content (link grid, copyright) is only emitted
38
+ * when the respective slots carry data.
39
+ */
40
+ declare function Footer(props: FooterProps): VNode;
41
+
42
+ export { Footer, type FooterProps };
@@ -0,0 +1,79 @@
1
+ import { jsx, jsxs } from "preact/jsx-runtime";
2
+ function Footer(props) {
3
+ const linkColumns = props.linkColumns ?? [];
4
+ const tagColumns = props.tagColumns ?? [];
5
+ const copyright = props.copyright ?? "";
6
+ const persistKey = props.persistKey;
7
+ const hasColumns = linkColumns.length > 0 || tagColumns.length > 0;
8
+ const hasCopyright = copyright.length > 0;
9
+ const copyrightClass = hasColumns ? "text-center text-caption text-muted [&_a]:text-accent [&_a]:underline mt-vsp-lg border-t border-muted pt-vsp-md" : "text-center text-caption text-muted [&_a]:text-accent [&_a]:underline";
10
+ return /* @__PURE__ */ jsx(
11
+ "footer",
12
+ {
13
+ class: "border-t border-muted bg-surface",
14
+ ...persistKey ? { "data-zfb-transition-persist": persistKey } : {},
15
+ children: /* @__PURE__ */ jsxs("div", { class: "mx-auto max-w-[clamp(50rem,75vw,90rem)] px-hsp-xl py-vsp-xl lg:px-hsp-2xl lg:py-vsp-2xl", children: [
16
+ hasColumns && /* @__PURE__ */ jsxs("div", { class: "grid grid-cols-1 gap-vsp-lg sm:grid-cols-2 lg:grid-cols-[repeat(auto-fit,minmax(12rem,1fr))]", children: [
17
+ linkColumns.map((column, i) => /* @__PURE__ */ jsxs("div", { children: [
18
+ /* @__PURE__ */ jsx("p", { class: "text-small font-semibold text-fg mb-vsp-xs", children: column.title }),
19
+ /* @__PURE__ */ jsx("ul", { class: "list-none p-0", children: column.items.map((item, j) => /* @__PURE__ */ jsx(
20
+ "li",
21
+ {
22
+ class: "mb-vsp-2xs",
23
+ children: /* @__PURE__ */ jsx(
24
+ "a",
25
+ {
26
+ href: item.href,
27
+ class: "text-caption text-muted hover:text-accent hover:underline focus-visible:underline",
28
+ ...item.isExternal ? {
29
+ target: "_blank",
30
+ rel: "noopener noreferrer"
31
+ } : {},
32
+ children: item.label
33
+ }
34
+ )
35
+ },
36
+ `item-${i}-${j}-${item.href}`
37
+ )) })
38
+ ] }, `link-${i}-${column.title}`)),
39
+ tagColumns.map((column, i) => /* @__PURE__ */ jsxs(
40
+ "div",
41
+ {
42
+ "data-taglist-group": column.group,
43
+ children: [
44
+ /* @__PURE__ */ jsx("h2", { class: "text-small font-semibold text-fg mb-vsp-xs", children: column.title }),
45
+ /* @__PURE__ */ jsx("ul", { class: "list-none p-0", children: column.tags.map(({ tag, count, href }) => /* @__PURE__ */ jsx("li", { class: "mb-vsp-2xs", children: /* @__PURE__ */ jsxs(
46
+ "a",
47
+ {
48
+ href,
49
+ class: "text-caption text-muted hover:text-accent hover:underline focus-visible:underline",
50
+ children: [
51
+ "#",
52
+ tag,
53
+ /* @__PURE__ */ jsxs("span", { class: "opacity-60", "aria-hidden": "true", children: [
54
+ "\xA0(",
55
+ count,
56
+ ")"
57
+ ] })
58
+ ]
59
+ }
60
+ ) }, `tag-item-${tag}`)) })
61
+ ]
62
+ },
63
+ `tag-${i}-${column.group}`
64
+ ))
65
+ ] }),
66
+ hasCopyright && /* @__PURE__ */ jsx(
67
+ "div",
68
+ {
69
+ class: copyrightClass,
70
+ dangerouslySetInnerHTML: { __html: copyright }
71
+ }
72
+ )
73
+ ] })
74
+ }
75
+ );
76
+ }
77
+ export {
78
+ Footer
79
+ };
@@ -0,0 +1,3 @@
1
+ export { Footer, FooterProps } from './footer.js';
2
+ export { FooterLinkColumn, FooterLinkItem, FooterTagColumn, FooterTagItem } from './types.js';
3
+ import 'preact';
@@ -0,0 +1,4 @@
1
+ import { Footer } from "./footer.js";
2
+ export {
3
+ Footer
4
+ };
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Public types for the framework-agnostic footer shell.
3
+ *
4
+ * The original Astro `footer.astro` mixed three concerns:
5
+ * 1. Reading `settings.footer` and applying locale overrides.
6
+ * 2. Loading the docs collection + tag vocabulary to build the
7
+ * optional taglist columns.
8
+ * 3. Rendering the footer markup.
9
+ *
10
+ * Concerns (1) and (2) depend on host-side helpers (`@/config/settings`,
11
+ * `@/utils/get-docs-collection`, `tag-vocabulary`, etc.) that v2 must
12
+ * not reach into. So this package only ports concern (3): the
13
+ * presentational shell. Callers prepare the columns upstream and pass
14
+ * already-localized, already-resolved hrefs in.
15
+ */
16
+ /** A single link rendered inside a {@link FooterLinkColumn}. */
17
+ interface FooterLinkItem {
18
+ /** Visible label (already locale-resolved by the caller). */
19
+ label: string;
20
+ /** Resolved href (already base-prefixed and locale-aware). */
21
+ href: string;
22
+ /**
23
+ * When true, the rendered anchor adds `target="_blank"` and
24
+ * `rel="noopener noreferrer"`. Callers compute this from their own
25
+ * external-href detector.
26
+ */
27
+ isExternal?: boolean;
28
+ }
29
+ /** One column in the footer's link grid. */
30
+ interface FooterLinkColumn {
31
+ /** Visible heading for the column (already locale-resolved). */
32
+ title: string;
33
+ items: FooterLinkItem[];
34
+ }
35
+ /** A single tag rendered inside a {@link FooterTagColumn}. */
36
+ interface FooterTagItem {
37
+ /** Canonical tag id (rendered as `#<tag>`). */
38
+ tag: string;
39
+ /** Document count shown next to the tag. */
40
+ count: number;
41
+ /** Resolved href to the tag's index page. */
42
+ href: string;
43
+ }
44
+ /** One column in the footer's tag grid. */
45
+ interface FooterTagColumn {
46
+ /**
47
+ * Group identifier — usually a vocabulary group name like `"topic"`,
48
+ * or the literal `"__flat__"` sentinel for the ungrouped/flat column.
49
+ * Surfaced as `data-taglist-group` on the rendered column wrapper so
50
+ * downstream tests / e2e selectors keep working.
51
+ */
52
+ group: string;
53
+ /** Visible heading for the column (already locale-resolved). */
54
+ title: string;
55
+ tags: FooterTagItem[];
56
+ }
57
+
58
+ export type { FooterLinkColumn, FooterLinkItem, FooterTagColumn, FooterTagItem };
File without changes
@@ -0,0 +1,33 @@
1
+ import { JSX } from 'preact';
2
+ import { HeadProps } from './types.js';
3
+
4
+ /**
5
+ * Framework head tag emission. Renders only the meta-tag layer of <head>;
6
+ * provider components such as ColorSchemeProvider or astro:transitions'
7
+ * ClientRouter and any inline boot scripts (sidebar toggle, design token
8
+ * panel, etc.) are owned by other topic folders and composed by the host
9
+ * layout alongside this primitive.
10
+ *
11
+ * Output order is fixed and matches the existing src/layouts/doc-layout.astro
12
+ * emission so head HTML stays byte-identical (modulo asset hashes) to the
13
+ * pre-migration build for any fixture page:
14
+ *
15
+ * 1. <meta charset>
16
+ * 2. <meta name="viewport">
17
+ * 3. <title>
18
+ * 4. <meta name="description"> (if description)
19
+ * 5. <meta name="robots"> (noindex sitewide OR unlisted page)
20
+ * 6. <link rel="canonical"> (if canonical)
21
+ * 7. <meta name="theme-color"> (if themeColor)
22
+ * 8. og:* tags (og:title always; rest conditional)
23
+ * 9. twitter:* tags (only when twitterCard set)
24
+ * 10. <link rel="stylesheet"> ... (in supplied order — e.g. KaTeX)
25
+ * 11. <link rel="alternate"> ... (in supplied order — e.g. llms.txt)
26
+ * 12. <link rel="preload"> ... (in supplied order)
27
+ *
28
+ * Never reorder existing slots; append new tag families at the end so
29
+ * downstream byte-diffs remain stable.
30
+ */
31
+ declare function DocHead(props: HeadProps): JSX.Element;
32
+
33
+ export { DocHead };
@@ -0,0 +1,90 @@
1
+ import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
2
+ import { OgTags } from "./og-tags.js";
3
+ import { TwitterCard } from "./twitter-card.js";
4
+ function DocHead(props) {
5
+ const {
6
+ title,
7
+ description,
8
+ noindex,
9
+ unlisted,
10
+ canonical,
11
+ themeColor,
12
+ twitterCard,
13
+ twitterSite,
14
+ twitterCreator,
15
+ twitterTitle,
16
+ twitterDescription,
17
+ twitterImage,
18
+ stylesheets,
19
+ alternateLinks,
20
+ preload
21
+ } = props;
22
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
23
+ /* @__PURE__ */ jsx("meta", { charset: "utf-8" }),
24
+ /* @__PURE__ */ jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }),
25
+ /* @__PURE__ */ jsx("title", { children: title }),
26
+ description !== void 0 && /* @__PURE__ */ jsx("meta", { name: "description", content: description }),
27
+ noindex && /* @__PURE__ */ jsx("meta", { name: "robots", content: "noindex, nofollow" }),
28
+ !noindex && unlisted && /* @__PURE__ */ jsx("meta", { name: "robots", content: "noindex" }),
29
+ canonical !== void 0 && /* @__PURE__ */ jsx("link", { rel: "canonical", href: canonical }),
30
+ themeColor !== void 0 && /* @__PURE__ */ jsx("meta", { name: "theme-color", content: themeColor }),
31
+ /* @__PURE__ */ jsx(
32
+ OgTags,
33
+ {
34
+ title,
35
+ description,
36
+ ogTitle: props.ogTitle,
37
+ ogDescription: props.ogDescription,
38
+ ogType: props.ogType,
39
+ ogUrl: props.ogUrl,
40
+ ogImage: props.ogImage,
41
+ ogSiteName: props.ogSiteName
42
+ }
43
+ ),
44
+ twitterCard !== void 0 && /* @__PURE__ */ jsx(
45
+ TwitterCard,
46
+ {
47
+ card: twitterCard,
48
+ site: twitterSite,
49
+ creator: twitterCreator,
50
+ title: twitterTitle,
51
+ description: twitterDescription,
52
+ image: twitterImage
53
+ }
54
+ ),
55
+ stylesheets?.map((s) => /* @__PURE__ */ jsx(
56
+ "link",
57
+ {
58
+ rel: "stylesheet",
59
+ href: s.href,
60
+ ...s.integrity !== void 0 ? { integrity: s.integrity } : {},
61
+ ...s.crossorigin !== void 0 ? { crossorigin: s.crossorigin } : {}
62
+ },
63
+ `stylesheet:${s.href}`
64
+ )),
65
+ alternateLinks?.map((l) => /* @__PURE__ */ jsx(
66
+ "link",
67
+ {
68
+ rel: l.rel,
69
+ ...l.type !== void 0 ? { type: l.type } : {},
70
+ href: l.href,
71
+ ...l.title !== void 0 ? { title: l.title } : {}
72
+ },
73
+ `${l.rel}:${l.type ?? ""}:${l.href}`
74
+ )),
75
+ preload?.map((p) => /* @__PURE__ */ jsx(
76
+ "link",
77
+ {
78
+ rel: "preload",
79
+ as: p.as,
80
+ href: p.href,
81
+ ...p.type !== void 0 ? { type: p.type } : {},
82
+ ...p.crossorigin !== void 0 ? { crossorigin: p.crossorigin } : {}
83
+ },
84
+ `preload:${p.as}:${p.href}`
85
+ ))
86
+ ] });
87
+ }
88
+ export {
89
+ DocHead
90
+ };
@@ -0,0 +1,5 @@
1
+ export { DocHead } from './doc-head.js';
2
+ export { OgTags } from './og-tags.js';
3
+ export { TwitterCard } from './twitter-card.js';
4
+ export { HeadProps } from './types.js';
5
+ import 'preact';
@@ -0,0 +1,8 @@
1
+ import { DocHead } from "./doc-head.js";
2
+ import { OgTags } from "./og-tags.js";
3
+ import { TwitterCard } from "./twitter-card.js";
4
+ export {
5
+ DocHead,
6
+ OgTags,
7
+ TwitterCard
8
+ };
@@ -0,0 +1,25 @@
1
+ import { JSX } from 'preact';
2
+ import { HeadProps } from './types.js';
3
+
4
+ /**
5
+ * Open Graph meta tags. Emits og:title (always — defaults to `title`) plus
6
+ * any other og:* fields the caller has supplied.
7
+ *
8
+ * Output order matches the order in src/layouts/doc-layout.astro for byte
9
+ * parity: og:title → og:description → og:type → og:url → og:image →
10
+ * og:site_name. New og:* tags should be appended at the end of the list,
11
+ * never reordered, to keep snapshot diffs minimal.
12
+ */
13
+ declare function OgTags(props: {
14
+ title: string;
15
+ description?: string;
16
+ ogTitle?: string;
17
+ ogDescription?: string;
18
+ ogType?: string;
19
+ ogUrl?: string;
20
+ ogImage?: string;
21
+ ogSiteName?: string;
22
+ }): JSX.Element;
23
+ type OgInputs = Pick<HeadProps, "ogTitle" | "ogDescription" | "ogType" | "ogUrl" | "ogImage" | "ogSiteName">;
24
+
25
+ export { type OgInputs, OgTags };
@@ -0,0 +1,16 @@
1
+ import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
2
+ function OgTags(props) {
3
+ const ogTitle = props.ogTitle ?? props.title;
4
+ const ogDescription = props.ogDescription ?? props.description;
5
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
6
+ /* @__PURE__ */ jsx("meta", { property: "og:title", content: ogTitle }),
7
+ ogDescription !== void 0 && /* @__PURE__ */ jsx("meta", { property: "og:description", content: ogDescription }),
8
+ props.ogType !== void 0 && /* @__PURE__ */ jsx("meta", { property: "og:type", content: props.ogType }),
9
+ props.ogUrl !== void 0 && /* @__PURE__ */ jsx("meta", { property: "og:url", content: props.ogUrl }),
10
+ props.ogImage !== void 0 && /* @__PURE__ */ jsx("meta", { property: "og:image", content: props.ogImage }),
11
+ props.ogSiteName !== void 0 && /* @__PURE__ */ jsx("meta", { property: "og:site_name", content: props.ogSiteName })
12
+ ] });
13
+ }
14
+ export {
15
+ OgTags
16
+ };
@@ -0,0 +1,21 @@
1
+ import { JSX } from 'preact';
2
+ import { HeadProps } from './types.js';
3
+
4
+ /**
5
+ * Twitter card meta tags. The host renders this only when a card type is
6
+ * configured; this component itself assumes `card` is set and emits twitter:card
7
+ * plus whichever other twitter:* fields the caller has supplied.
8
+ *
9
+ * Field order: card → site → creator → title → description → image. Preserve
10
+ * this order to keep snapshot diffs predictable.
11
+ */
12
+ declare function TwitterCard(props: {
13
+ card: NonNullable<HeadProps["twitterCard"]>;
14
+ site?: string;
15
+ creator?: string;
16
+ title?: string;
17
+ description?: string;
18
+ image?: string;
19
+ }): JSX.Element;
20
+
21
+ export { TwitterCard };
@@ -0,0 +1,14 @@
1
+ import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
2
+ function TwitterCard(props) {
3
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
4
+ /* @__PURE__ */ jsx("meta", { name: "twitter:card", content: props.card }),
5
+ props.site !== void 0 && /* @__PURE__ */ jsx("meta", { name: "twitter:site", content: props.site }),
6
+ props.creator !== void 0 && /* @__PURE__ */ jsx("meta", { name: "twitter:creator", content: props.creator }),
7
+ props.title !== void 0 && /* @__PURE__ */ jsx("meta", { name: "twitter:title", content: props.title }),
8
+ props.description !== void 0 && /* @__PURE__ */ jsx("meta", { name: "twitter:description", content: props.description }),
9
+ props.image !== void 0 && /* @__PURE__ */ jsx("meta", { name: "twitter:image", content: props.image })
10
+ ] });
11
+ }
12
+ export {
13
+ TwitterCard
14
+ };
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Input props for {@link DocHead}.
3
+ *
4
+ * The framework component is intentionally free of project-specific globals
5
+ * (settings.ts, i18n helpers, base path). Callers build a HeadProps object
6
+ * from their own config and pass it in. This keeps the head primitive
7
+ * portable across Astro and zfb hosts and lets us assert byte-parity in
8
+ * unit tests without bootstrapping a full runtime.
9
+ */
10
+ interface HeadProps {
11
+ /**
12
+ * Full title string. The caller is responsible for composing
13
+ * "{Page Title} | {Site Name}" — DocHead does not append the site name.
14
+ */
15
+ title: string;
16
+ /** Page description; emitted as <meta name="description"> and og:description. */
17
+ description?: string;
18
+ /**
19
+ * Apply <meta name="robots" content="noindex, nofollow"> sitewide.
20
+ * When true, takes precedence over `unlisted`.
21
+ */
22
+ noindex?: boolean;
23
+ /**
24
+ * Mark this individual page as unlisted. When `noindex` is false and
25
+ * `unlisted` is true, emits <meta name="robots" content="noindex">.
26
+ */
27
+ unlisted?: boolean;
28
+ /** Override og:title. Defaults to `title`. */
29
+ ogTitle?: string;
30
+ /** Override og:description. Defaults to `description`. */
31
+ ogDescription?: string;
32
+ /** og:type, e.g. "website" or "article". Omitted if undefined. */
33
+ ogType?: string;
34
+ /** og:url. Omitted if undefined. */
35
+ ogUrl?: string;
36
+ /** og:image. Omitted if undefined. */
37
+ ogImage?: string;
38
+ /** og:site_name. Omitted if undefined. */
39
+ ogSiteName?: string;
40
+ /**
41
+ * When set, emits twitter:card and any of the other twitter:* fields that
42
+ * are also supplied. When undefined, no twitter:* tags are emitted.
43
+ */
44
+ twitterCard?: "summary" | "summary_large_image" | "app" | "player";
45
+ twitterSite?: string;
46
+ twitterCreator?: string;
47
+ twitterTitle?: string;
48
+ twitterDescription?: string;
49
+ twitterImage?: string;
50
+ /** Canonical URL emitted as <link rel="canonical">. */
51
+ canonical?: string;
52
+ /** theme-color meta value (e.g. "#ffffff"). */
53
+ themeColor?: string;
54
+ /** Generic stylesheet links (e.g. KaTeX). Emitted in order. */
55
+ stylesheets?: ReadonlyArray<{
56
+ href: string;
57
+ integrity?: string;
58
+ crossorigin?: "anonymous" | "use-credentials";
59
+ }>;
60
+ /**
61
+ * Generic alternate / RSS / sitemap links emitted as
62
+ * <link rel={rel} type={type} href={href} title={title}>.
63
+ * Used for llms.txt, RSS feed discovery, sitemap discovery, etc.
64
+ */
65
+ alternateLinks?: ReadonlyArray<{
66
+ rel: string;
67
+ href: string;
68
+ type?: string;
69
+ title?: string;
70
+ }>;
71
+ /**
72
+ * Generic preload hints emitted as
73
+ * <link rel="preload" as={as} href={href} type={type} crossorigin={crossorigin}>.
74
+ */
75
+ preload?: ReadonlyArray<{
76
+ href: string;
77
+ as: string;
78
+ type?: string;
79
+ crossorigin?: "anonymous" | "use-credentials";
80
+ }>;
81
+ }
82
+
83
+ export type { HeadProps };
File without changes