@takazudo/zudo-doc 3.3.0 → 4.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 (423) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/README.md +2 -2
  3. package/bin/tag-cli-config.ts +126 -0
  4. package/bin/tags-audit-runner.ts +60 -76
  5. package/bin/tags-audit.mjs +17 -36
  6. package/bin/tags-suggest-runner.ts +429 -0
  7. package/bin/tags-suggest.mjs +30 -0
  8. package/bin/zudo-doc.mjs +78 -25
  9. package/dist/breadcrumb/breadcrumb.d.ts +4 -4
  10. package/dist/breadcrumb/find-path.d.ts +2 -2
  11. package/dist/breadcrumb/index.d.ts +1 -1
  12. package/dist/breadcrumb/types.d.ts +0 -5
  13. package/dist/chrome/derive.d.ts +16 -10
  14. package/dist/chrome/derive.js +53 -4
  15. package/dist/chrome/index.d.ts +13 -10
  16. package/dist/chrome/index.js +12 -6
  17. package/dist/chrome/primary-slots.d.ts +21 -0
  18. package/dist/chrome/primary-slots.js +59 -0
  19. package/dist/chrome-bindings.d.ts +68 -0
  20. package/dist/code-syntax/code-block-enhancer-script.d.ts +4 -0
  21. package/dist/code-syntax/code-block-enhancer-script.js +7 -4
  22. package/dist/code-syntax/code-block-enhancer.d.ts +2 -2
  23. package/dist/code-syntax/code-block-enhancer.js +1 -3
  24. package/dist/code-syntax/index.d.ts +5 -5
  25. package/dist/code-syntax/index.js +4 -13
  26. package/dist/code-syntax/mermaid-init-script.d.ts +1 -22
  27. package/dist/code-syntax/mermaid-init-script.js +0 -2
  28. package/dist/code-syntax/mermaid-init.d.ts +0 -1
  29. package/dist/code-syntax/mermaid-init.js +3 -4
  30. package/dist/code-syntax/tabs-init.d.ts +0 -1
  31. package/dist/code-syntax/tabs-init.js +1 -3
  32. package/dist/code-syntax/tabs.d.ts +0 -1
  33. package/dist/code-syntax/tabs.js +1 -3
  34. package/dist/color-scheme-utils.d.ts +71 -3
  35. package/dist/color-scheme-utils.js +137 -0
  36. package/dist/color-schemes-defaults/index.js +13 -0
  37. package/dist/config/component-tokens.d.ts +1 -1
  38. package/dist/config/component-tokens.js +104 -5
  39. package/dist/config.d.ts +28 -12
  40. package/dist/config.js +11 -2
  41. package/dist/content/component-map.d.ts +0 -16
  42. package/dist/content/component-map.js +2 -4
  43. package/dist/content/index.d.ts +1 -1
  44. package/dist/content/index.js +2 -3
  45. package/dist/content.css +1 -1
  46. package/dist/design-token-panel-bootstrap.d.ts +45 -40
  47. package/dist/design-token-panel-bootstrap.js +98 -21
  48. package/dist/design-token-panel-config/index.js +1 -4
  49. package/dist/doc-body-end-islands/design-token-panel-island.d.ts +15 -0
  50. package/dist/doc-body-end-islands/design-token-panel-island.js +31 -0
  51. package/dist/doc-body-end-islands/index.d.ts +39 -17
  52. package/dist/doc-body-end-islands/index.js +13 -21
  53. package/dist/doc-body-end-islands/theme-pack-switcher-island.d.ts +37 -0
  54. package/dist/doc-body-end-islands/theme-pack-switcher-island.js +18 -0
  55. package/dist/doc-content-header/index.js +1 -1
  56. package/dist/doc-history-area/index.d.ts +10 -4
  57. package/dist/doc-history-area/index.js +3 -2
  58. package/dist/doc-metainfo-area/index.d.ts +1 -0
  59. package/dist/doc-page-props/index.d.ts +7 -23
  60. package/dist/doc-page-renderer/index.d.ts +1 -0
  61. package/dist/doc-page-renderer/index.js +1 -0
  62. package/dist/doc-page-shell/index.js +19 -12
  63. package/dist/doc-pager/index.js +1 -1
  64. package/dist/doc-route-entries/index.d.ts +2 -2
  65. package/dist/doclayout/doc-layout-with-defaults.js +4 -4
  66. package/dist/doclayout/doc-layout.d.ts +8 -0
  67. package/dist/doclayout/doc-layout.js +10 -1
  68. package/dist/docs-schema/index.js +1 -5
  69. package/dist/eject/index.d.ts +16 -0
  70. package/dist/eject/index.js +122 -28
  71. package/dist/extract-headings/index.d.ts +5 -8
  72. package/dist/extract-headings/index.js +2 -9
  73. package/dist/factory-context/index.d.ts +42 -4
  74. package/dist/features.css +80 -45
  75. package/dist/footer/footer.js +1 -0
  76. package/dist/head-with-defaults/index.d.ts +2 -0
  77. package/dist/head-with-defaults/index.js +16 -0
  78. package/dist/header/header.d.ts +10 -5
  79. package/dist/header/header.js +45 -5
  80. package/dist/header/index.d.ts +1 -1
  81. package/dist/header/types.d.ts +30 -1
  82. package/dist/header-with-defaults/index.js +1 -0
  83. package/dist/home-page/index.d.ts +2 -0
  84. package/dist/home-page/index.js +11 -5
  85. package/dist/home-page/prepare-home-data.js +1 -1
  86. package/dist/locale-merge/index.d.ts +9 -14
  87. package/dist/locale-merge/index.js +6 -4
  88. package/dist/mdx-components/index.js +4 -4
  89. package/dist/plugins/claude-resources.d.ts +1 -0
  90. package/dist/plugins/claude-resources.js +4 -2
  91. package/dist/plugins/doc-history.js +1 -1
  92. package/dist/{integrations → plugins/internal}/claude-resources/index.d.ts +1 -16
  93. package/dist/{integrations → plugins/internal}/claude-resources/index.js +0 -9
  94. package/dist/{integrations → plugins/internal}/doc-history/index.d.ts +0 -17
  95. package/dist/{integrations → plugins/internal}/doc-history/index.js +0 -4
  96. package/dist/{integrations → plugins/internal}/doc-history/pre-build.d.ts +2 -4
  97. package/dist/plugins/internal/llms-txt/index.d.ts +7 -0
  98. package/dist/{integrations → plugins/internal}/llms-txt/load.d.ts +1 -1
  99. package/dist/{integrations → plugins/internal}/llms-txt/load.js +2 -2
  100. package/dist/{integrations → plugins/internal}/llms-txt/strip.d.ts +2 -3
  101. package/dist/{integrations → plugins/internal}/llms-txt/strip.js +1 -1
  102. package/dist/{integrations → plugins/internal}/llms-txt/types.d.ts +13 -22
  103. package/dist/{integrations → plugins/internal}/search-index/collect.js +1 -1
  104. package/dist/plugins/internal/theme-packs/copy.d.ts +32 -0
  105. package/dist/plugins/internal/theme-packs/copy.js +45 -0
  106. package/dist/plugins/internal/theme-packs/dev-middleware.d.ts +22 -0
  107. package/dist/plugins/internal/theme-packs/dev-middleware.js +80 -0
  108. package/dist/plugins/internal/theme-packs/index.d.ts +6 -0
  109. package/dist/plugins/internal/theme-packs/index.js +9 -0
  110. package/dist/plugins/internal/theme-packs/resolve.d.ts +17 -0
  111. package/dist/plugins/internal/theme-packs/resolve.js +17 -0
  112. package/dist/plugins/internal/theme-packs/types.d.ts +22 -0
  113. package/dist/plugins/internal/theme-packs/types.js +0 -0
  114. package/dist/plugins/llms-txt.js +1 -1
  115. package/dist/plugins/routes.js +11 -1
  116. package/dist/plugins/search-index.js +1 -1
  117. package/dist/plugins/theme-packs.d.ts +3 -0
  118. package/dist/plugins/theme-packs.js +40 -0
  119. package/dist/preset.d.ts +19 -14
  120. package/dist/preset.js +24 -9
  121. package/dist/route-context/index.js +4 -6
  122. package/dist/route-enumerators/index.d.ts +6 -18
  123. package/dist/route-enumerators/index.js +8 -6
  124. package/dist/routes/404.js +3 -1
  125. package/dist/routes/_chrome.js +2 -2
  126. package/dist/routes/_context.d.ts +7 -3
  127. package/dist/routes/_context.js +2 -0
  128. package/dist/routes/_docs-helpers.js +9 -21
  129. package/dist/safelist.css +1 -1
  130. package/dist/settings.d.ts +27 -12
  131. package/dist/sidebar-toggle-island/index.js +1 -0
  132. package/dist/sidebar-tree/build-tree.d.ts +3 -4
  133. package/dist/sidebar-tree/build-tree.js +4 -3
  134. package/dist/sidebar-tree/index.d.ts +2 -2
  135. package/dist/sidebar-tree/types.d.ts +6 -17
  136. package/dist/site-tree-nav-island/index.d.ts +3 -1
  137. package/dist/site-tree-nav-island/index.js +17 -5
  138. package/dist/site-tree-nav-island/state.d.ts +4 -0
  139. package/dist/site-tree-nav-island/state.js +10 -0
  140. package/dist/tag-helpers/index.d.ts +6 -13
  141. package/dist/tag-helpers/index.js +5 -23
  142. package/dist/tag-pages/index.d.ts +8 -21
  143. package/dist/tag-pages/index.js +14 -10
  144. package/dist/tags-audit.d.ts +16 -44
  145. package/dist/tags-audit.js +9 -172
  146. package/dist/theme/color-scheme-provider.d.ts +2 -3
  147. package/dist/theme/color-scheme-provider.js +2 -10
  148. package/dist/theme/index.d.ts +1 -4
  149. package/dist/theme/index.js +2 -30
  150. package/dist/theme/theme-pack-provider.d.ts +42 -0
  151. package/dist/theme/theme-pack-provider.js +75 -0
  152. package/dist/theme-cli/apply.d.ts +16 -0
  153. package/dist/theme-cli/apply.js +61 -0
  154. package/dist/theme-cli/config-io.d.ts +15 -0
  155. package/dist/theme-cli/config-io.js +51 -0
  156. package/dist/theme-cli/config-rewriter.d.ts +21 -0
  157. package/dist/theme-cli/config-rewriter.js +141 -0
  158. package/dist/theme-cli/config-scanner.d.ts +63 -0
  159. package/dist/theme-cli/config-scanner.js +288 -0
  160. package/dist/theme-cli/index.d.ts +7 -0
  161. package/dist/theme-cli/index.js +38 -0
  162. package/dist/theme-cli/list.d.ts +27 -0
  163. package/dist/theme-cli/list.js +64 -0
  164. package/dist/theme-cli/provenance.d.ts +17 -0
  165. package/dist/theme-cli/provenance.js +35 -0
  166. package/dist/theme-cli/registry.d.ts +14 -0
  167. package/dist/theme-cli/registry.js +13 -0
  168. package/dist/theme-pack-dialog/dialog-state.d.ts +25 -0
  169. package/dist/theme-pack-dialog/dialog-state.js +40 -0
  170. package/dist/theme-pack-dialog/index.d.ts +5 -0
  171. package/dist/theme-pack-dialog/index.js +152 -0
  172. package/dist/theme-pack-dialog/theme-pack-card.d.ts +25 -0
  173. package/dist/theme-pack-dialog/theme-pack-card.js +72 -0
  174. package/dist/theme-pack-switcher/index.d.ts +49 -0
  175. package/dist/theme-pack-switcher/index.js +205 -0
  176. package/dist/theme-pack-switcher/switcher-state.d.ts +56 -0
  177. package/dist/theme-pack-switcher/switcher-state.js +43 -0
  178. package/dist/theme-pack-switcher/theme-pack-sync.d.ts +85 -0
  179. package/dist/theme-pack-switcher/theme-pack-sync.js +121 -0
  180. package/dist/theme-packs/beacon/fonts/AtkinsonHyperlegible-400-latin.woff2 +0 -0
  181. package/dist/theme-packs/beacon/fonts/AtkinsonHyperlegible-700-latin.woff2 +0 -0
  182. package/dist/theme-packs/beacon/fonts/AtkinsonHyperlegible-italic-400-latin.woff2 +0 -0
  183. package/dist/theme-packs/beacon/fonts/AtkinsonHyperlegible-italic-700-latin.woff2 +0 -0
  184. package/dist/theme-packs/beacon/fonts/AtkinsonHyperlegibleMono-italic-latin.woff2 +0 -0
  185. package/dist/theme-packs/beacon/fonts/AtkinsonHyperlegibleMono-latin.woff2 +0 -0
  186. package/dist/theme-packs/beacon/fonts/OFL.txt +94 -0
  187. package/dist/theme-packs/beacon/meta.json +37 -0
  188. package/dist/theme-packs/beacon/pack.css +442 -0
  189. package/dist/theme-packs/broadsheet/fonts/CourierPrime-400-latin.woff2 +0 -0
  190. package/dist/theme-packs/broadsheet/fonts/CourierPrime-700-latin.woff2 +0 -0
  191. package/dist/theme-packs/broadsheet/fonts/OFL.txt +95 -0
  192. package/dist/theme-packs/broadsheet/fonts/PlayfairDisplay-italic-latin.woff2 +0 -0
  193. package/dist/theme-packs/broadsheet/fonts/PlayfairDisplay-latin.woff2 +0 -0
  194. package/dist/theme-packs/broadsheet/fonts/SourceSerif4-italic-latin.woff2 +0 -0
  195. package/dist/theme-packs/broadsheet/fonts/SourceSerif4-latin.woff2 +0 -0
  196. package/dist/theme-packs/broadsheet/meta.json +38 -0
  197. package/dist/theme-packs/broadsheet/pack.css +448 -0
  198. package/dist/theme-packs/brutalist/fonts/ArchivoBlack-latin.woff2 +0 -0
  199. package/dist/theme-packs/brutalist/fonts/IBMPlexMono-400-latin.woff2 +0 -0
  200. package/dist/theme-packs/brutalist/fonts/IBMPlexMono-500-latin.woff2 +0 -0
  201. package/dist/theme-packs/brutalist/fonts/IBMPlexMono-700-latin.woff2 +0 -0
  202. package/dist/theme-packs/brutalist/fonts/OFL.txt +95 -0
  203. package/dist/theme-packs/brutalist/fonts/SpaceGrotesk-latin.woff2 +0 -0
  204. package/dist/theme-packs/brutalist/meta.json +38 -0
  205. package/dist/theme-packs/brutalist/pack.css +546 -0
  206. package/dist/theme-packs/default/meta.json +37 -0
  207. package/dist/theme-packs/drift/fonts/IBMPlexMono-400-latin-ext.woff2 +0 -0
  208. package/dist/theme-packs/drift/fonts/IBMPlexMono-400-latin.woff2 +0 -0
  209. package/dist/theme-packs/drift/fonts/IBMPlexMono-500-latin-ext.woff2 +0 -0
  210. package/dist/theme-packs/drift/fonts/IBMPlexMono-500-latin.woff2 +0 -0
  211. package/dist/theme-packs/drift/fonts/IBMPlexSans-italic-latin.woff2 +0 -0
  212. package/dist/theme-packs/drift/fonts/IBMPlexSans-latin-ext.woff2 +0 -0
  213. package/dist/theme-packs/drift/fonts/IBMPlexSans-latin.woff2 +0 -0
  214. package/dist/theme-packs/drift/fonts/OFL.txt +93 -0
  215. package/dist/theme-packs/drift/meta.json +37 -0
  216. package/dist/theme-packs/drift/pack.css +478 -0
  217. package/dist/theme-packs/fjord/fonts/Inter-latin-ext.woff2 +0 -0
  218. package/dist/theme-packs/fjord/fonts/Inter-latin.woff2 +0 -0
  219. package/dist/theme-packs/fjord/fonts/JetBrainsMono-latin-ext.woff2 +0 -0
  220. package/dist/theme-packs/fjord/fonts/JetBrainsMono-latin.woff2 +0 -0
  221. package/dist/theme-packs/fjord/fonts/OFL.txt +94 -0
  222. package/dist/theme-packs/fjord/meta.json +37 -0
  223. package/dist/theme-packs/fjord/pack.css +375 -0
  224. package/dist/theme-packs/foundry/fonts/Inter-latin-ext.woff2 +0 -0
  225. package/dist/theme-packs/foundry/fonts/Inter-latin.woff2 +0 -0
  226. package/dist/theme-packs/foundry/fonts/OFL.txt +93 -0
  227. package/dist/theme-packs/foundry/meta.json +37 -0
  228. package/dist/theme-packs/foundry/pack.css +202 -0
  229. package/dist/theme-packs/futura-editorial/fonts/Jost-latin.woff2 +0 -0
  230. package/dist/theme-packs/futura-editorial/fonts/NotoSans-italic-latin.woff2 +0 -0
  231. package/dist/theme-packs/futura-editorial/fonts/NotoSans-latin.woff2 +0 -0
  232. package/dist/theme-packs/futura-editorial/fonts/OFL.txt +95 -0
  233. package/dist/theme-packs/futura-editorial/fonts/SpaceMono-400-latin.woff2 +0 -0
  234. package/dist/theme-packs/futura-editorial/fonts/SpaceMono-700-latin.woff2 +0 -0
  235. package/dist/theme-packs/futura-editorial/meta.json +38 -0
  236. package/dist/theme-packs/futura-editorial/pack.css +313 -0
  237. package/dist/theme-packs/hearth/fonts/Fraunces-italic-latin.woff2 +0 -0
  238. package/dist/theme-packs/hearth/fonts/Fraunces-latin.woff2 +0 -0
  239. package/dist/theme-packs/hearth/fonts/Nunito-latin.woff2 +0 -0
  240. package/dist/theme-packs/hearth/fonts/OFL.txt +95 -0
  241. package/dist/theme-packs/hearth/fonts/SplineSansMono-latin.woff2 +0 -0
  242. package/dist/theme-packs/hearth/meta.json +38 -0
  243. package/dist/theme-packs/hearth/pack.css +385 -0
  244. package/dist/theme-packs/hollow/fonts/OFL.txt +94 -0
  245. package/dist/theme-packs/hollow/fonts/SpaceGrotesk-latin.woff2 +0 -0
  246. package/dist/theme-packs/hollow/fonts/SpaceMono-400-italic-latin.woff2 +0 -0
  247. package/dist/theme-packs/hollow/fonts/SpaceMono-400-latin.woff2 +0 -0
  248. package/dist/theme-packs/hollow/fonts/SpaceMono-700-latin.woff2 +0 -0
  249. package/dist/theme-packs/hollow/meta.json +37 -0
  250. package/dist/theme-packs/hollow/pack.css +428 -0
  251. package/dist/theme-packs/ledger/fonts/CrimsonPro-latin-ext-italic.woff2 +0 -0
  252. package/dist/theme-packs/ledger/fonts/CrimsonPro-latin-ext.woff2 +0 -0
  253. package/dist/theme-packs/ledger/fonts/CrimsonPro-latin-italic.woff2 +0 -0
  254. package/dist/theme-packs/ledger/fonts/CrimsonPro-latin.woff2 +0 -0
  255. package/dist/theme-packs/ledger/fonts/IBMPlexMono-400-latin-ext.woff2 +0 -0
  256. package/dist/theme-packs/ledger/fonts/IBMPlexMono-400-latin.woff2 +0 -0
  257. package/dist/theme-packs/ledger/fonts/IBMPlexMono-500-latin-ext.woff2 +0 -0
  258. package/dist/theme-packs/ledger/fonts/IBMPlexMono-500-latin.woff2 +0 -0
  259. package/dist/theme-packs/ledger/fonts/OFL.txt +94 -0
  260. package/dist/theme-packs/ledger/meta.json +37 -0
  261. package/dist/theme-packs/ledger/pack.css +463 -0
  262. package/dist/theme-packs/manuscript/fonts/CourierPrime-400-latin-ext.woff2 +0 -0
  263. package/dist/theme-packs/manuscript/fonts/CourierPrime-400-latin.woff2 +0 -0
  264. package/dist/theme-packs/manuscript/fonts/CourierPrime-700-latin-ext.woff2 +0 -0
  265. package/dist/theme-packs/manuscript/fonts/CourierPrime-700-latin.woff2 +0 -0
  266. package/dist/theme-packs/manuscript/fonts/EBGaramond-latin-italic.woff2 +0 -0
  267. package/dist/theme-packs/manuscript/fonts/EBGaramond-latin.woff2 +0 -0
  268. package/dist/theme-packs/manuscript/fonts/OFL.txt +94 -0
  269. package/dist/theme-packs/manuscript/meta.json +37 -0
  270. package/dist/theme-packs/manuscript/pack.css +376 -0
  271. package/dist/theme-packs/matcha/fonts/MPLUS1Code-latin.woff2 +0 -0
  272. package/dist/theme-packs/matcha/fonts/OFL.txt +95 -0
  273. package/dist/theme-packs/matcha/fonts/ShipporiMincho-500-latin.woff2 +0 -0
  274. package/dist/theme-packs/matcha/fonts/ShipporiMincho-700-latin.woff2 +0 -0
  275. package/dist/theme-packs/matcha/fonts/ZenKakuGothicNew-400-latin.woff2 +0 -0
  276. package/dist/theme-packs/matcha/fonts/ZenKakuGothicNew-500-latin.woff2 +0 -0
  277. package/dist/theme-packs/matcha/meta.json +38 -0
  278. package/dist/theme-packs/matcha/pack.css +409 -0
  279. package/dist/theme-packs/nocturne/fonts/CormorantGaramond-italic-latin.woff2 +0 -0
  280. package/dist/theme-packs/nocturne/fonts/CormorantGaramond-latin.woff2 +0 -0
  281. package/dist/theme-packs/nocturne/fonts/IBMPlexMono-400-latin.woff2 +0 -0
  282. package/dist/theme-packs/nocturne/fonts/IBMPlexMono-500-latin.woff2 +0 -0
  283. package/dist/theme-packs/nocturne/fonts/IBMPlexMono-italic-latin.woff2 +0 -0
  284. package/dist/theme-packs/nocturne/fonts/Manrope-latin.woff2 +0 -0
  285. package/dist/theme-packs/nocturne/fonts/OFL.txt +95 -0
  286. package/dist/theme-packs/nocturne/meta.json +38 -0
  287. package/dist/theme-packs/nocturne/pack.css +502 -0
  288. package/dist/theme-packs/observatory/fonts/JosefinSans-latin.woff2 +0 -0
  289. package/dist/theme-packs/observatory/fonts/Jost-italic-latin.woff2 +0 -0
  290. package/dist/theme-packs/observatory/fonts/Jost-latin.woff2 +0 -0
  291. package/dist/theme-packs/observatory/fonts/OFL.txt +95 -0
  292. package/dist/theme-packs/observatory/fonts/SpaceMono-400-latin.woff2 +0 -0
  293. package/dist/theme-packs/observatory/fonts/SpaceMono-700-latin.woff2 +0 -0
  294. package/dist/theme-packs/observatory/fonts/SpaceMono-italic-latin.woff2 +0 -0
  295. package/dist/theme-packs/observatory/meta.json +38 -0
  296. package/dist/theme-packs/observatory/pack.css +728 -0
  297. package/dist/theme-packs/onyx/fonts/CormorantGaramond-italic-latin.woff2 +0 -0
  298. package/dist/theme-packs/onyx/fonts/CormorantGaramond-latin.woff2 +0 -0
  299. package/dist/theme-packs/onyx/fonts/IBMPlexMono-400-latin-ext.woff2 +0 -0
  300. package/dist/theme-packs/onyx/fonts/IBMPlexMono-400-latin.woff2 +0 -0
  301. package/dist/theme-packs/onyx/fonts/IBMPlexMono-500-latin-ext.woff2 +0 -0
  302. package/dist/theme-packs/onyx/fonts/IBMPlexMono-500-latin.woff2 +0 -0
  303. package/dist/theme-packs/onyx/fonts/Jost-latin.woff2 +0 -0
  304. package/dist/theme-packs/onyx/fonts/OFL.txt +95 -0
  305. package/dist/theme-packs/onyx/meta.json +38 -0
  306. package/dist/theme-packs/onyx/pack.css +497 -0
  307. package/dist/theme-packs/phosphor/fonts/JetBrainsMono-latin-ext.woff2 +0 -0
  308. package/dist/theme-packs/phosphor/fonts/JetBrainsMono-latin.woff2 +0 -0
  309. package/dist/theme-packs/phosphor/fonts/OFL.txt +94 -0
  310. package/dist/theme-packs/phosphor/fonts/VT323-latin-ext.woff2 +0 -0
  311. package/dist/theme-packs/phosphor/fonts/VT323-latin.woff2 +0 -0
  312. package/dist/theme-packs/phosphor/meta.json +38 -0
  313. package/dist/theme-packs/phosphor/pack.css +493 -0
  314. package/dist/theme-packs/solar/fonts/OFL.txt +94 -0
  315. package/dist/theme-packs/solar/fonts/SourceCodePro-italic-latin.woff2 +0 -0
  316. package/dist/theme-packs/solar/fonts/SourceCodePro-latin.woff2 +0 -0
  317. package/dist/theme-packs/solar/fonts/SourceSans3-italic-latin.woff2 +0 -0
  318. package/dist/theme-packs/solar/fonts/SourceSans3-latin.woff2 +0 -0
  319. package/dist/theme-packs/solar/meta.json +37 -0
  320. package/dist/theme-packs/solar/pack.css +380 -0
  321. package/dist/theme-packs/sumi/fonts/IBMPlexMono-400-latin-ext.woff2 +0 -0
  322. package/dist/theme-packs/sumi/fonts/IBMPlexMono-400-latin.woff2 +0 -0
  323. package/dist/theme-packs/sumi/fonts/IBMPlexMono-500-latin-ext.woff2 +0 -0
  324. package/dist/theme-packs/sumi/fonts/IBMPlexMono-500-latin.woff2 +0 -0
  325. package/dist/theme-packs/sumi/fonts/OFL.txt +95 -0
  326. package/dist/theme-packs/sumi/fonts/ShipporiMinchoB1-600-latin.woff2 +0 -0
  327. package/dist/theme-packs/sumi/fonts/ShipporiMinchoB1-700-latin.woff2 +0 -0
  328. package/dist/theme-packs/sumi/fonts/ShipporiMinchoB1-800-latin.woff2 +0 -0
  329. package/dist/theme-packs/sumi/fonts/ZenKakuGothicNew-400-latin.woff2 +0 -0
  330. package/dist/theme-packs/sumi/fonts/ZenKakuGothicNew-500-latin.woff2 +0 -0
  331. package/dist/theme-packs/sumi/meta.json +38 -0
  332. package/dist/theme-packs/sumi/pack.css +502 -0
  333. package/dist/theme-packs/swissgrid/fonts/IBMPlexMono-400-latin-ext.woff2 +0 -0
  334. package/dist/theme-packs/swissgrid/fonts/IBMPlexMono-400-latin.woff2 +0 -0
  335. package/dist/theme-packs/swissgrid/fonts/IBMPlexMono-600-latin.woff2 +0 -0
  336. package/dist/theme-packs/swissgrid/fonts/Inter-latin-ext.woff2 +0 -0
  337. package/dist/theme-packs/swissgrid/fonts/Inter-latin.woff2 +0 -0
  338. package/dist/theme-packs/swissgrid/fonts/InterTight-latin.woff2 +0 -0
  339. package/dist/theme-packs/swissgrid/fonts/OFL.txt +95 -0
  340. package/dist/theme-packs/swissgrid/meta.json +38 -0
  341. package/dist/theme-packs/swissgrid/pack.css +518 -0
  342. package/dist/theme-packs/washi/fonts/MPlus1Code-400-latin.woff2 +0 -0
  343. package/dist/theme-packs/washi/fonts/MPlus1Code-500-latin.woff2 +0 -0
  344. package/dist/theme-packs/washi/fonts/OFL.txt +95 -0
  345. package/dist/theme-packs/washi/fonts/ShipporiMincho-500-latin.woff2 +0 -0
  346. package/dist/theme-packs/washi/fonts/ShipporiMincho-600-latin.woff2 +0 -0
  347. package/dist/theme-packs/washi/fonts/ShipporiMincho-700-latin.woff2 +0 -0
  348. package/dist/theme-packs/washi/fonts/ZenKakuGothicNew-400-latin.woff2 +0 -0
  349. package/dist/theme-packs/washi/fonts/ZenKakuGothicNew-500-latin.woff2 +0 -0
  350. package/dist/theme-packs/washi/fonts/ZenKakuGothicNew-700-latin.woff2 +0 -0
  351. package/dist/theme-packs/washi/meta.json +38 -0
  352. package/dist/theme-packs/washi/pack.css +479 -0
  353. package/dist/theme-packs-registry/index.d.ts +5 -0
  354. package/dist/theme-packs-registry/index.js +30 -0
  355. package/dist/theme-packs-registry/load-registry.d.ts +23 -0
  356. package/dist/theme-packs-registry/load-registry.js +64 -0
  357. package/dist/theme-packs-registry/meta-schema.d.ts +70 -0
  358. package/dist/theme-packs-registry/meta-schema.js +38 -0
  359. package/dist/theme-packs-registry/resolve-enabled-packs.d.ts +25 -0
  360. package/dist/theme-packs-registry/resolve-enabled-packs.js +43 -0
  361. package/dist/theme-packs-registry/token-manifest.d.ts +19 -0
  362. package/dist/theme-packs-registry/token-manifest.js +57 -0
  363. package/dist/theme-packs-registry/validator.d.ts +35 -0
  364. package/dist/theme-packs-registry/validator.js +284 -0
  365. package/dist/theme-toggle/color-scheme-sync.d.ts +2 -4
  366. package/dist/toc/mobile-toc.js +1 -1
  367. package/dist/versions-page/index.d.ts +2 -2
  368. package/dist/versions-page/index.js +8 -8
  369. package/eject/breadcrumb/breadcrumb.tsx +4 -4
  370. package/eject/breadcrumb/find-path.ts +2 -2
  371. package/eject/breadcrumb/index.ts +1 -1
  372. package/eject/breadcrumb/types.ts +0 -6
  373. package/eject/code-group/index.tsx +2 -2
  374. package/eject/doc-history/index.tsx +1 -1
  375. package/eject/doc-pager/index.tsx +1 -1
  376. package/eject/footer/footer.tsx +1 -0
  377. package/eject/header/header.tsx +86 -21
  378. package/eject/header/index.ts +3 -0
  379. package/eject/header/types.ts +39 -1
  380. package/eject/sidebar-toggle-island/index.tsx +7 -1
  381. package/eject/site-tree-nav-island/index.tsx +15 -3
  382. package/eject/site-tree-nav-island/state.ts +9 -0
  383. package/eject/theme-toggle/color-scheme-sync.ts +2 -4
  384. package/eject/toc/mobile-toc.tsx +9 -1
  385. package/package.json +35 -29
  386. package/routes-src/404.tsx +4 -1
  387. package/routes-src/_chrome.tsx +6 -5
  388. package/routes-src/_context.ts +4 -0
  389. package/routes-src/_docs-helpers.ts +9 -29
  390. package/routes-src/_virtual.d.ts +4 -0
  391. package/virtual-modules.d.ts +4 -0
  392. package/zfb-config-shim.d.ts +40 -18
  393. package/dist/integrations/llms-txt/index.d.ts +0 -33
  394. package/dist/theme/color-tweak-export-modal.d.ts +0 -16
  395. package/dist/theme/color-tweak-export-modal.js +0 -138
  396. package/dist/theme/design-token-serde.d.ts +0 -183
  397. package/dist/theme/design-token-serde.js +0 -346
  398. package/dist/theme/design-token-types.d.ts +0 -13
  399. package/dist/theme/design-token-types.js +0 -6
  400. package/dist/theme/iframe-bridge.d.ts +0 -42
  401. package/dist/theme/iframe-bridge.js +0 -72
  402. /package/dist/{integrations → plugins/internal}/claude-resources/escape-for-mdx.d.ts +0 -0
  403. /package/dist/{integrations → plugins/internal}/claude-resources/escape-for-mdx.js +0 -0
  404. /package/dist/{integrations → plugins/internal}/claude-resources/generate.d.ts +0 -0
  405. /package/dist/{integrations → plugins/internal}/claude-resources/generate.js +0 -0
  406. /package/dist/{integrations → plugins/internal}/doc-history/pre-build.js +0 -0
  407. /package/dist/{integrations → plugins/internal}/llms-txt/dev-middleware.d.ts +0 -0
  408. /package/dist/{integrations → plugins/internal}/llms-txt/dev-middleware.js +0 -0
  409. /package/dist/{integrations → plugins/internal}/llms-txt/emit.d.ts +0 -0
  410. /package/dist/{integrations → plugins/internal}/llms-txt/emit.js +0 -0
  411. /package/dist/{integrations → plugins/internal}/llms-txt/generate.d.ts +0 -0
  412. /package/dist/{integrations → plugins/internal}/llms-txt/generate.js +0 -0
  413. /package/dist/{integrations → plugins/internal}/llms-txt/index.js +0 -0
  414. /package/dist/{integrations → plugins/internal}/llms-txt/types.js +0 -0
  415. /package/dist/{integrations → plugins/internal}/search-index/build-emitter.d.ts +0 -0
  416. /package/dist/{integrations → plugins/internal}/search-index/build-emitter.js +0 -0
  417. /package/dist/{integrations → plugins/internal}/search-index/collect.d.ts +0 -0
  418. /package/dist/{integrations → plugins/internal}/search-index/dev-middleware.d.ts +0 -0
  419. /package/dist/{integrations → plugins/internal}/search-index/dev-middleware.js +0 -0
  420. /package/dist/{integrations → plugins/internal}/search-index/index.d.ts +0 -0
  421. /package/dist/{integrations → plugins/internal}/search-index/index.js +0 -0
  422. /package/dist/{integrations → plugins/internal}/search-index/types.d.ts +0 -0
  423. /package/dist/{integrations → plugins/internal}/search-index/types.js +0 -0
@@ -1,5 +1,6 @@
1
1
  import type { Settings, TagVocabularyEntry } from "../settings.js";
2
2
  import type { ColorScheme } from "../color-scheme-utils.js";
3
+ import type { ThemePackRegistry } from "../theme-packs-registry/index.js";
3
4
  import type { UrlHelpers } from "../url-helpers/index.js";
4
5
  import type { NavSourceDocsAPI } from "../nav-source-docs/index.js";
5
6
  import type { DocRouteEntriesAPI } from "../doc-route-entries/index.js";
@@ -8,6 +9,7 @@ import type { ResolvedTag } from "../tag-helpers/index.js";
8
9
  import type { DocNavNode, DocPageEntry } from "../doc-page-props/index.js";
9
10
  import type { HeadingItem } from "../extract-headings/index.js";
10
11
  import type { CategoryMeta } from "../sidebar-tree/index.js";
12
+ import type { HeaderRightComponentRegistry } from "../header/types.js";
11
13
  /**
12
14
  * The i18n surface a factory may read. Parameterizes what `base.ts` used to read
13
15
  * off the project's `@/config/i18n` singleton directly, so URL/locale logic moves
@@ -103,6 +105,21 @@ export interface RouteContextPayload<S = Settings> {
103
105
  /** Host color-scheme palette map; `null` when the host passed none (chrome
104
106
  * then falls back to a neutral default scheme). */
105
107
  colorSchemes: Record<string, ColorScheme> | null;
108
+ /**
109
+ * Resolved, enabled, ordered theme-pack registry (ADR
110
+ * `docs/adr/theme-packs.md`, Decision 2 "Registry threading to
111
+ * SSR/islands") — settings ∩ the bundled `theme-packs/` directories, in
112
+ * switcher order. `null` (or omitted) renders the whole feature inert (same
113
+ * accepted coupling class as {@link colorSchemes} for a
114
+ * `packageOwnedRoutes: false` host that builds its own payload without
115
+ * threading one).
116
+ *
117
+ * OPTIONAL on purpose: this field was added after the payload shape
118
+ * shipped, so an existing `packageOwnedRoutes: false` host that constructs
119
+ * its own payload predates it. `createRouteContext` normalizes an omitted
120
+ * value to `null` (→ inert) so upgrading such a host does not throw at SSR.
121
+ */
122
+ themePackRegistry?: ThemePackRegistry | null;
106
123
  }
107
124
  /** Aggregated `tag → docs` index entry built by `collectTags`. */
108
125
  export interface TagInfo {
@@ -133,6 +150,9 @@ export interface RouteContext<S = Settings> extends UrlHelpers, NavSourceDocsAPI
133
150
  settings: S;
134
151
  /** Host color-scheme palette map (or `null`); threaded to chrome head CSS. */
135
152
  colorSchemes: Record<string, ColorScheme> | null;
153
+ /** Resolved, enabled, ordered theme-pack registry (or `null`) — see
154
+ * {@link RouteContextPayload.themePackRegistry}. */
155
+ themePackRegistry: ThemePackRegistry | null;
136
156
  /** The reconstructed i18n surface. */
137
157
  i18n: FactoryI18n;
138
158
  /** Default locale code (un-prefixed `/docs/...`). */
@@ -162,14 +182,14 @@ export interface RouteContext<S = Settings> extends UrlHelpers, NavSourceDocsAPI
162
182
  resolveTagBound(raw: string): ResolvedTag;
163
183
  /** Aggregate a `tag → docs` index from a doc collection. */
164
184
  collectTags(entries: ReadonlyArray<{
165
- id: string;
185
+ slug: string;
166
186
  data: {
167
187
  slug?: string;
168
188
  title?: string;
169
189
  description?: string;
170
190
  tags?: string[];
171
191
  };
172
- }>, slugFn: (id: string, data: {
192
+ }>, slugFn: (entrySlug: string, data: {
173
193
  slug?: string;
174
194
  }) => string): Map<string, TagInfo>;
175
195
  /** Build a recursive nav tree from a flat doc collection. */
@@ -188,8 +208,8 @@ export interface RouteContext<S = Settings> extends UrlHelpers, NavSourceDocsAPI
188
208
  isNavVisible(doc: DocPageEntry): boolean;
189
209
  /** The content-bridge handle: identity-stable, draft-filtered docs loader. */
190
210
  stableDocs(collectionName: string): DocPageEntry[];
191
- /** Canonical route slug for a doc id. */
192
- toRouteSlug(id: string): string;
211
+ /** Canonical route slug for a zfb content slug. */
212
+ toRouteSlug(entrySlug: string): string;
193
213
  /** Split a route slug into path params. */
194
214
  toSlugParams(routeSlug: string): string[];
195
215
  }
@@ -202,8 +222,26 @@ export interface RouteContext<S = Settings> extends UrlHelpers, NavSourceDocsAPI
202
222
  * (HOSTCOLLAPSE wave) later passes the real bindings.
203
223
  */
204
224
  export interface ChromeHostBindings {
225
+ /** Primary header chrome. Default: the package HeaderWithDefaults component. */
226
+ Header?: FactoryComponent;
227
+ /** Primary footer chrome. Default: the package FooterWithDefaults component. */
228
+ Footer?: FactoryComponent;
229
+ /** Primary doc sidebar chrome. Default: the package SidebarWithDefaults component. */
230
+ Sidebar?: FactoryComponent;
231
+ /** Primary desktop table of contents. Default: the package Toc component. */
232
+ Toc?: FactoryComponent;
233
+ /** Primary breadcrumb trail. Default: the package Breadcrumb component. */
234
+ Breadcrumb?: FactoryComponent;
235
+ /** Primary previous/next document pager. Default: the package DocPager component. */
236
+ DocPager?: FactoryComponent;
205
237
  /** Header search widget. Default: the package SearchWidget bound to the site base. */
206
238
  SearchWidget?: FactoryComponent;
239
+ /**
240
+ * Project-owned header-right renderers keyed by the serializable component
241
+ * name in `settings.headerRightItems`. Built-in names are reserved and may
242
+ * not be shadowed. Default: `{}`.
243
+ */
244
+ headerRightComponents?: HeaderRightComponentRegistry;
207
245
  /** Per-page git-history meta manifest. Default: `{}` (no Created/Updated block). */
208
246
  docHistoryMeta?: Record<string, unknown>;
209
247
  /** Sidebar section config. Default: `{}` (auto-generated tree only). */
package/dist/features.css CHANGED
@@ -20,6 +20,8 @@
20
20
  * --text-{small,caption}
21
21
  * --leading-relaxed
22
22
  * --zd-fg
23
+ * --zd-code-{bg,fg}
24
+ * --zd-syntax-{comment,string,number,keyword,callable,type,name,inserted,deleted}
23
25
  * --zd-sidebar-w
24
26
  * --zd-header-h
25
27
  * --zd-transition-slow
@@ -46,11 +48,11 @@ header[data-header] {
46
48
  position: relative;
47
49
  }
48
50
 
49
- pre[class^="syntect-"].word-wrap {
51
+ :is(pre.hi-root, .tab-panel pre).word-wrap {
50
52
  overflow-x: hidden;
51
53
  }
52
54
 
53
- pre[class^="syntect-"].word-wrap code {
55
+ :is(pre.hi-root, .tab-panel pre).word-wrap code {
54
56
  white-space: pre-wrap;
55
57
  overflow-wrap: anywhere;
56
58
  }
@@ -139,38 +141,49 @@ pre[class^="syntect-"].word-wrap code {
139
141
  * Code-block syntax-highlight token color rule
140
142
  * ======================================== */
141
143
 
142
- /* Code-block token colors come from CSS custom properties in two cases on this
143
- * site, both resolved here via light-dark():
144
- *
145
- * 1. Build-time — zfb DUAL-theme syntect (codeHighlight.themeLight/themeDark
146
- * in zfb.config.ts). Emits <pre class="syntect-dual"> whose token spans
147
- * carry style="--shiki-light:#X;--shiki-dark:#Y" (no `color` declaration)
148
- * and whose <pre> carries --shiki-{light,dark}-bg. Zero client JS.
149
- *
150
- * 2. Runtime — the HtmlPreview component's Shiki blocks (<pre class="shiki">),
151
- * which emit the same --shiki-* custom properties.
152
- *
153
- * Both resolve through the `color-scheme` property, which ColorSchemeProvider /
154
- * ThemeToggle toggle per active theme — the same mechanism the palette tokens
155
- * use — so code follows the in-page light/dark switch.
156
- *
157
- * Compatibility: SINGLE-theme syntect (the zfb default, NOT used here) instead
158
- * bakes inline style="color:#hex". This rule deliberately uses NO !important so
159
- * that such an inline `color` — a higher-precedence author declaration — still
160
- * wins, leaving single-theme output untouched. The --shiki-* spans have no
161
- * inline `color`, so the rule applies cleanly. Same logic for background-color
162
- * on the <pre>. See zudolab/zudo-doc#1457.
163
- *
164
- * NOTE: the zdtp design-token panel does NOT highlight code — its Shiki
165
- * integration is a no-op stub upstream. Earlier revisions of this comment
166
- * wrongly attributed the --shiki-* vars to a zdtp client-side re-highlight. */
167
- /* Token color + font-style on the spans (and harmlessly on the <pre>/<code>,
168
- * where the per-token --shiki-* vars are undefined so the declaration is
169
- * ignored). */
144
+ /* zfb's default class-mode stylesheet lives in `@layer zfb-hi`. This adapter
145
+ * stays unlayered, so zudo's semantic design tokens win without specificity or
146
+ * import-order coupling. The indirections deliberately stay as var() values:
147
+ * ColorSchemeProvider and the Design Token Panel can replace any --zd-* source
148
+ * live, and existing highlighted DOM recomputes without a renderer pass. */
149
+ :root {
150
+ --zfb-hi-fg: var(--zd-code-fg);
151
+ --zfb-hi-bg: var(--zd-code-bg);
152
+ --zfb-hi-esc: var(--zd-syntax-string);
153
+ --zfb-hi-op: var(--zd-code-fg);
154
+ --zfb-hi-com: var(--zd-syntax-comment);
155
+ --zfb-hi-str: var(--zd-syntax-string);
156
+ --zfb-hi-num: var(--zd-syntax-number);
157
+ --zfb-hi-const: var(--zd-syntax-number);
158
+ --zfb-hi-kw: var(--zd-syntax-keyword);
159
+ --zfb-hi-fn: var(--zd-syntax-callable);
160
+ --zfb-hi-ty: var(--zd-syntax-type);
161
+ --zfb-hi-ns: var(--zd-syntax-type);
162
+ --zfb-hi-prop: var(--zd-syntax-name);
163
+ --zfb-hi-var: var(--zd-syntax-name);
164
+ --zfb-hi-tag: var(--zd-syntax-name);
165
+ --zfb-hi-attr: var(--zd-syntax-name);
166
+ --zfb-hi-punct: var(--zd-code-fg);
167
+ --zfb-hi-ins: var(--zd-syntax-inserted);
168
+ --zfb-hi-ins-bg: color-mix(
169
+ in srgb,
170
+ var(--zd-syntax-inserted) 15%,
171
+ var(--zd-code-bg)
172
+ );
173
+ --zfb-hi-del: var(--zd-syntax-deleted);
174
+ --zfb-hi-del-bg: color-mix(
175
+ in srgb,
176
+ var(--zd-syntax-deleted) 15%,
177
+ var(--zd-code-bg)
178
+ );
179
+ --zfb-hi-hd: var(--zd-syntax-keyword);
180
+ }
181
+
182
+ /* HTML Preview remains on Shiki until #2742. Its dual-theme variables resolve
183
+ * through color-scheme. These selectors intentionally exclude `.hi-root`,
184
+ * whose colors come from the semantic bridge above. */
170
185
  [data-theme] .shiki,
171
- [data-theme] .shiki span,
172
- [data-theme] pre[class^="syntect-"],
173
- [data-theme] pre[class^="syntect-"] span {
186
+ [data-theme] .shiki span {
174
187
  color: light-dark(var(--shiki-light), var(--shiki-dark));
175
188
  font-style: light-dark(
176
189
  var(--shiki-light-font-style, inherit),
@@ -183,8 +196,7 @@ pre[class^="syntect-"].word-wrap code {
183
196
  * painting them per-span would lay an opaque base background over the
184
197
  * translucent line-/word-highlight backgrounds that sit on the enclosing
185
198
  * .line span (see .line.highlighted below). */
186
- [data-theme] .shiki,
187
- [data-theme] pre[class^="syntect-"] {
199
+ [data-theme] .shiki {
188
200
  background-color: light-dark(var(--shiki-light-bg), var(--shiki-dark-bg));
189
201
  }
190
202
 
@@ -212,13 +224,13 @@ pre[class^="syntect-"].word-wrap code {
212
224
  * zfb emits data-line-highlight="true" on the <span class="line"> element
213
225
  * (verified empirically at next.13). The .highlighted class form is kept for
214
226
  * forward-compat in case a future zfb version emits both. */
215
- pre[class^="syntect-"] .line.highlighted,
216
- pre[class^="syntect-"] [data-line-highlight="true"] {
227
+ pre.hi-root .line.highlighted,
228
+ pre.hi-root [data-line-highlight="true"] {
217
229
  background-color: color-mix(in srgb, var(--color-accent) 15%, transparent);
218
230
  }
219
231
 
220
232
  /* Word highlighting via /word/ meta syntax */
221
- pre[class^="syntect-"] .line .highlighted-word {
233
+ pre.hi-root .line .highlighted-word {
222
234
  background-color: color-mix(in srgb, var(--color-accent) 25%, transparent);
223
235
  border-bottom: 1px solid var(--color-accent);
224
236
  }
@@ -242,7 +254,7 @@ pre[class^="syntect-"] .line .highlighted-word {
242
254
  padding: var(--spacing-vsp-2xs) var(--spacing-hsp-lg);
243
255
  }
244
256
 
245
- .code-block-container pre[class^="syntect-"] {
257
+ .code-block-container pre.hi-root {
246
258
  margin-top: 0 !important;
247
259
  border-top-left-radius: 0;
248
260
  border-top-right-radius: 0;
@@ -253,10 +265,10 @@ pre[class^="syntect-"] .line .highlighted-word {
253
265
  *
254
266
  * zfb's :::code-group emits <CodeGroup tabs={[...]}> with one
255
267
  * <pre data-lang="…">{RAW text}</pre> child per fence. These <pre> elements
256
- * are NOT syntect-highlighted (the Rust pipeline doesn't highlight inside
257
- * code-group fences), so they get no `.syntect-*` class. Apply explicit
258
- * code-block visual treatment via tokens to match the syntect-highlighted
259
- * code blocks surrounding them.
268
+ * are NOT syntax-highlighted (the Rust pipeline doesn't highlight inside
269
+ * code-group fences), so they get no `.hi-root` class. Apply explicit
270
+ * code-block visual treatment via tokens to match the highlighted code blocks
271
+ * surrounding them.
260
272
  * ======================================== */
261
273
 
262
274
  .code-group-panel pre[data-lang] {
@@ -934,8 +946,15 @@ dialog.zd-mermaid-dialog::backdrop {
934
946
  *
935
947
  * Single source of truth: `src/config/component-tokens.ts` (tokens with
936
948
  * `surface: "chrome"`). The `gen-component-tokens` generator owns the BEGIN/END
937
- * block below — never hand-edit between the markers. Seeded empty: no chrome
938
- * tokens exist yet (S1, #2458 added only the routing mechanism).
949
+ * block below — never hand-edit between the markers.
950
+ *
951
+ * The `body { font-family }` rule below is the CHROME FONT SEAM (#2887): it is
952
+ * why a theme pack's `--font-sans` reaches the header/sidebar/TOC/footer at all.
953
+ * Those surfaces set no font-family of their own, and preflight's `html, :host`
954
+ * rule compiles to a hardcoded literal stack here (no `--default-font-family` is
955
+ * ever defined), so without this rule the token could only ever reach `.zd-content`
956
+ * prose. It works because this block is UNLAYERED and preflight is imported into
957
+ * `layer(zd-preflight)` — see component-tokens.ts for the full rationale.
939
958
  * ========================================================================== */
940
959
 
941
960
  /* BEGIN --zdc-* chrome component tokens (generated by gen-component-tokens; do not edit by hand) */
@@ -957,4 +976,20 @@ a[data-nav-active] {
957
976
  font-weight: var(--zdc-nav-active-weight, var(--font-weight-medium));
958
977
  }
959
978
 
979
+ body {
980
+ font-family: var(--zdc-chrome-font, var(--font-sans));
981
+ }
982
+
983
+ header[data-header] {
984
+ font-family: var(--zdc-header-font, var(--zdc-chrome-font, var(--font-sans)));
985
+ }
986
+
987
+ #desktop-sidebar, aside[data-zd-mobile-sidebar] {
988
+ font-family: var(--zdc-sidebar-font, var(--zdc-chrome-font, var(--font-sans)));
989
+ }
990
+
991
+ nav[data-zd-toc], div[data-zd-mobile-toc] {
992
+ font-family: var(--zdc-toc-font, var(--zdc-chrome-font, var(--font-sans)));
993
+ }
994
+
960
995
  /* END --zdc-* chrome component tokens */
@@ -11,6 +11,7 @@ function Footer(props) {
11
11
  "footer",
12
12
  {
13
13
  class: "border-t border-muted bg-surface",
14
+ "data-footer": true,
14
15
  ...persistKey ? { "data-zfb-transition-persist": persistKey } : {},
15
16
  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
17
  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: [
@@ -31,6 +31,8 @@ export interface HeadWithDefaultsSettings {
31
31
  siteName: string;
32
32
  colorMode?: ColorSchemeProviderColorMode | null | false;
33
33
  sidebarResizer?: boolean;
34
+ /** Configured theme-pack slug (ADR `docs/adr/theme-packs.md`, #2822). */
35
+ themePack?: string;
34
36
  }
35
37
  /**
36
38
  * Create a `HeadWithDefaults` component from the unified {@link ChromeContext}
@@ -2,6 +2,10 @@ import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
2
2
  import { OgTags, TwitterCard } from "../head/index.js";
3
3
  import { SIDEBAR_RESIZER_RESTORE_SCRIPT } from "../sidebar-resizer/index.js";
4
4
  import ColorSchemeProvider from "../theme/color-scheme-provider.js";
5
+ import ThemePackProvider, {
6
+ themePackVersionMap
7
+ } from "../theme/theme-pack-provider.js";
8
+ import { DEFAULT_THEME_PACK_SLUG } from "../theme-pack-switcher/theme-pack-sync.js";
5
9
  import { deriveComposeMetaTitle, deriveColorSchemeGenerators } from "../chrome/derive.js";
6
10
  import { assertChromeContext } from "../chrome/assert-chrome-context.js";
7
11
  function createHeadWithDefaults(ctx) {
@@ -11,6 +15,10 @@ function createHeadWithDefaults(ctx) {
11
15
  const withBase = ctx.withBase;
12
16
  const absoluteUrl = ctx.absoluteUrl;
13
17
  const { generateCssCustomProperties, generateLightDarkCssProperties } = deriveColorSchemeGenerators(ctx);
18
+ const themePackRegistry = ctx.themePackRegistry;
19
+ const themePackEnabled = themePackRegistry !== null ? themePackVersionMap(themePackRegistry) : null;
20
+ const themePackConfigured = settings.themePack ?? DEFAULT_THEME_PACK_SLUG;
21
+ const themePackBase = withBase("/");
14
22
  function HeadWithDefaults({
15
23
  title,
16
24
  description,
@@ -48,6 +56,14 @@ function createHeadWithDefaults(ctx) {
48
56
  }
49
57
  ),
50
58
  /* @__PURE__ */ jsx(ColorSchemeProvider, { cssText, colorMode }),
59
+ themePackEnabled !== null && /* @__PURE__ */ jsx(
60
+ ThemePackProvider,
61
+ {
62
+ configuredSlug: themePackConfigured,
63
+ enabled: themePackEnabled,
64
+ base: themePackBase
65
+ }
66
+ ),
51
67
  settings.sidebarResizer && /* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: SIDEBAR_RESIZER_RESTORE_SCRIPT } }),
52
68
  /* @__PURE__ */ jsx("link", { rel: "icon", href: withBase("/favicon.ico"), sizes: "any" }),
53
69
  /* @__PURE__ */ jsx("link", { rel: "icon", type: "image/png", sizes: "32x32", href: withBase("/favicon-32x32.png") }),
@@ -1,7 +1,7 @@
1
1
  /** @jsxRuntime automatic */
2
2
  /** @jsxImportSource preact */
3
3
  import type { ComponentChildren, JSX } from "preact";
4
- import type { HeaderNavItem, HeaderRightItem, Locale } from "./types.js";
4
+ import type { HeaderNavItem, HeaderRightComponentRegistry, HeaderRightItem, Locale } from "./types.js";
5
5
  /**
6
6
  * Boundary helpers the host injects into `<Header>`. These are the URL
7
7
  * builders the legacy header.tsx used to import from `@/utils/base` —
@@ -71,10 +71,9 @@ export interface HeaderProps {
71
71
  /** Replacement for the `<Search />` Astro child. */
72
72
  search?: ComponentChildren;
73
73
  /**
74
- * When provided, emits `data-zfb-transition-persist={persistKey}` on the
74
+ * Emits `data-zfb-transition-persist={persistKey}` on the
75
75
  * `<header>` element so zfb's client-router preserves DOM-node identity
76
- * across same-locale View Transition swaps. Omit to disable persist
77
- * (back-compat default — the header is re-rendered on every swap).
76
+ * across same-locale View Transition swaps.
78
77
  *
79
78
  * **Locale keying**: callers MUST key by locale (e.g. `"header-en"`,
80
79
  * `"header-ja"`). Cross-locale swaps must NOT share the same key; a
@@ -90,7 +89,7 @@ export interface HeaderProps {
90
89
  * for consistency, matching the Astro reference implementation
91
90
  * (zudolab/zudo-doc#1546).
92
91
  */
93
- persistKey?: string;
92
+ persistKey: string;
94
93
  /** Site-name string shown in the logo anchor (host `settings.siteName`). */
95
94
  siteName: string;
96
95
  /** Header-nav items in render order (host `settings.headerNav`). */
@@ -105,6 +104,12 @@ export interface HeaderProps {
105
104
  * wrapper, matching prior behaviour.
106
105
  */
107
106
  headerRightItems: HeaderRightItem[];
107
+ /**
108
+ * Host-callable renderers for project-owned component names. The registry is
109
+ * carried through `chromeBindingsModule`; it is never part of the serialized
110
+ * settings payload. Package built-in names are reserved.
111
+ */
112
+ headerRightComponents?: HeaderRightComponentRegistry;
108
113
  /**
109
114
  * Whether the host has a `colorMode` config. Required because the
110
115
  * `theme-toggle` right-item is two-gated: the filter drops it when
@@ -25,6 +25,7 @@ function Header(props) {
25
25
  siteName,
26
26
  headerNav,
27
27
  headerRightItems,
28
+ headerRightComponents,
28
29
  colorModeEnabled,
29
30
  hasLocales,
30
31
  hasVersions,
@@ -37,6 +38,7 @@ function Header(props) {
37
38
  const pathWithoutBase = urlHelpers.stripBase(currentPath);
38
39
  const matchPath = pathForMatch(pathWithoutBase, lang, i18n.defaultLocale);
39
40
  const activeNavPath = computeActiveNavPath(headerNav, matchPath);
41
+ const rightItemDispatch = createRightItemDispatch(headerRightComponents);
40
42
  return /* @__PURE__ */ jsxs(
41
43
  "header",
42
44
  {
@@ -114,7 +116,8 @@ function Header(props) {
114
116
  search,
115
117
  colorModeEnabled,
116
118
  hasLocales
117
- }
119
+ },
120
+ rightItemDispatch
118
121
  ))
119
122
  }
120
123
  ),
@@ -268,7 +271,14 @@ function SlotWrapper({
268
271
  }) {
269
272
  return /* @__PURE__ */ jsx("div", { class: className, children }, `right-${index}`);
270
273
  }
271
- const RIGHT_ITEM_DISPATCH = {
274
+ const BUILTIN_COMPONENT_NAMES = [
275
+ "theme-toggle",
276
+ "language-switcher",
277
+ "version-switcher",
278
+ "github-link",
279
+ "search"
280
+ ];
281
+ const BASE_RIGHT_ITEM_DISPATCH = {
272
282
  "trigger:design-token-panel": (_item, index) => /* @__PURE__ */ jsx(
273
283
  TriggerButton,
274
284
  {
@@ -385,10 +395,40 @@ const RIGHT_ITEM_DISPATCH = {
385
395
  );
386
396
  }
387
397
  };
388
- function renderRightItem(item, index, ctx) {
398
+ function createRightItemDispatch(hostRegistry) {
399
+ const dispatch = new Map(
400
+ Object.entries(BASE_RIGHT_ITEM_DISPATCH)
401
+ );
402
+ if (hostRegistry === void 0) return dispatch;
403
+ for (const [name, component] of Object.entries(hostRegistry)) {
404
+ if (BUILTIN_COMPONENT_NAMES.includes(name)) {
405
+ throw new Error(
406
+ `[zudo-doc] Duplicate header-right component name "${name}" at chromeBindings.headerRightComponents[${JSON.stringify(name)}]: built-in names are reserved and cannot be shadowed. Remove this registry entry or choose a project-owned name.`
407
+ );
408
+ }
409
+ if (typeof component !== "function") {
410
+ throw new TypeError(
411
+ `[zudo-doc] Invalid header-right component "${name}" at chromeBindings.headerRightComponents[${JSON.stringify(name)}]: expected a callable renderer.`
412
+ );
413
+ }
414
+ dispatch.set(`component:${name}`, (item, index, ctx) => {
415
+ if (item.type !== "component") return null;
416
+ const CustomComponent = component;
417
+ return /* @__PURE__ */ jsx(SlotWrapper, { index, children: /* @__PURE__ */ jsx(CustomComponent, { item, index, ...ctx }) });
418
+ });
419
+ }
420
+ return dispatch;
421
+ }
422
+ function renderRightItem(item, index, ctx, dispatch) {
389
423
  const key = item.type === "trigger" ? `trigger:${item.trigger}` : item.type === "component" ? `component:${item.component}` : item.type;
390
- const handler = RIGHT_ITEM_DISPATCH[key];
391
- return handler ? handler(item, index, ctx) : null;
424
+ const handler = dispatch.get(key);
425
+ if (handler) return handler(item, index, ctx);
426
+ if (item.type === "component") {
427
+ throw new Error(
428
+ `[zudo-doc] Unknown header-right component "${item.component}" at Header.headerRightItems[${index}].component. Register a callable renderer as chromeBindings.headerRightComponents["${item.component}"] through settings.chromeBindingsModule, or use a built-in name: ${BUILTIN_COMPONENT_NAMES.join(", ")}.`
429
+ );
430
+ }
431
+ return null;
392
432
  }
393
433
  export {
394
434
  Header
@@ -9,7 +9,7 @@
9
9
  * so downstream tests / custom layouts can reuse them without rebuilding
10
10
  * the `pathForMatch` / `computeActiveNavPath` regex logic.
11
11
  */
12
- export type { Locale, HeaderNavChildItem, HeaderNavItem, HeaderRightComponentItem, HeaderRightComponentName, HeaderRightHtmlItem, HeaderRightItem, HeaderRightLinkItem, HeaderRightTriggerItem, HeaderRightTriggerName, } from "./types.js";
12
+ export type { Locale, HeaderNavChildItem, HeaderNavItem, HeaderRightBuiltinComponentName, HeaderRightComponentItem, HeaderRightComponentName, HeaderRightComponentProps, HeaderRightComponentRegistry, HeaderRightHtmlItem, HeaderRightItem, HeaderRightLinkItem, HeaderRightTriggerItem, HeaderRightTriggerName, } from "./types.js";
13
13
  export { filterHeaderRightItems, type HeaderRightItemFlags, } from "./right-items.js";
14
14
  export { Header, type HeaderProps } from "./header.js";
15
15
  export { computeActiveNavPath, isNavItemActive, pathForMatch, type NavItemLike, } from "./nav-active.js";
@@ -1,3 +1,4 @@
1
+ import type { ComponentChildren } from "preact";
1
2
  /**
2
3
  * Locale code as seen by the header. Widened from the host's literal
3
4
  * union (`"en" | "ja" | …`) to plain `string` at the v2 boundary so the
@@ -14,12 +15,40 @@ export interface HeaderNavChildItem {
14
15
  export interface HeaderNavItem extends HeaderNavChildItem {
15
16
  children?: HeaderNavChildItem[];
16
17
  }
17
- export type HeaderRightComponentName = "theme-toggle" | "language-switcher" | "version-switcher" | "github-link" | "search";
18
+ export type HeaderRightBuiltinComponentName = "theme-toggle" | "language-switcher" | "version-switcher" | "github-link" | "search";
19
+ /**
20
+ * A serializable name resolved against the package built-ins plus the host's
21
+ * `headerRightComponents` chrome-binding registry. The intersection preserves
22
+ * built-in autocomplete while allowing project-owned names.
23
+ */
24
+ export type HeaderRightComponentName = HeaderRightBuiltinComponentName | (string & {});
18
25
  export type HeaderRightTriggerName = "design-token-panel" | "ai-chat";
19
26
  export interface HeaderRightComponentItem {
20
27
  type: "component";
21
28
  component: HeaderRightComponentName;
22
29
  }
30
+ /**
31
+ * Exact props passed to a host `headerRightComponents` renderer. They mirror
32
+ * the existing header-right dispatch context; no callable enters the
33
+ * serialized {@link HeaderRightComponentItem}.
34
+ */
35
+ export interface HeaderRightComponentProps {
36
+ /** The serialized item that selected this renderer. */
37
+ item: HeaderRightComponentItem;
38
+ /** Zero-based position in the rendered `headerRightItems` array. */
39
+ index: number;
40
+ lang: Locale | undefined;
41
+ githubRepoUrl: string | null;
42
+ githubLabel: string;
43
+ themeToggle: ComponentChildren;
44
+ languageSwitcher: ComponentChildren;
45
+ versionSwitcher: ComponentChildren;
46
+ search: ComponentChildren;
47
+ colorModeEnabled: boolean;
48
+ hasLocales: boolean;
49
+ }
50
+ /** A callable-only host registry keyed by serialized component name. */
51
+ export type HeaderRightComponentRegistry = Record<string, (props: HeaderRightComponentProps) => ComponentChildren>;
23
52
  export interface HeaderRightTriggerItem {
24
53
  type: "trigger";
25
54
  trigger: HeaderRightTriggerName;
@@ -149,6 +149,7 @@ function createHeaderWithDefaults(ctx) {
149
149
  siteName: settings.siteName,
150
150
  headerNav: settings.headerNav,
151
151
  headerRightItems,
152
+ headerRightComponents: ctx.hostBindings.headerRightComponents,
152
153
  colorModeEnabled: Boolean(settings.colorMode),
153
154
  hasLocales: locales.length > 1,
154
155
  hasVersions: Boolean(settings.versions),
@@ -30,6 +30,8 @@ export interface HomePageViewProps {
30
30
  tree: DocNavNode[];
31
31
  /** Ordered category prefixes, passed through to `SiteTreeNav`. */
32
32
  categoryOrder: string[];
33
+ /** Root-category slugs that should start collapsed in `SiteTreeNav`. */
34
+ initiallyCollapsedCategorySlugs?: string[];
33
35
  /** Unique tag count for the current locale — gates the "all tags" section
34
36
  * together with `settings.docTags`. */
35
37
  tagCount: number;
@@ -3,9 +3,9 @@ import { Island } from "@takazudo/zfb";
3
3
  import { DocLayoutWithDefaults } from "../doclayout/index.js";
4
4
  import { SiteTreeNav } from "../site-tree-nav-island/index.js";
5
5
  import { createHeadWithDefaults } from "../head-with-defaults/index.js";
6
- import { createHeaderWithDefaults } from "../header-with-defaults/index.js";
7
- import { createFooterWithDefaults } from "../footer-with-defaults/index.js";
6
+ import { resolveThemePackSsrSlug } from "../theme/theme-pack-provider.js";
8
7
  import { deriveComposeMetaTitle, deriveBodyEndIslands } from "../chrome/derive.js";
8
+ import { derivePrimaryChromeSlots } from "../chrome/primary-slots.js";
9
9
  import { assertChromeContext } from "../chrome/assert-chrome-context.js";
10
10
  import { prepareHomeData } from "./prepare-home-data.js";
11
11
  function createHomePageView(ctx) {
@@ -16,15 +16,19 @@ function createHomePageView(ctx) {
16
16
  const defaultLocale = ctx.defaultLocale;
17
17
  const composeMetaTitle = deriveComposeMetaTitle(ctx);
18
18
  const HeadWithDefaults = createHeadWithDefaults(ctx);
19
- const HeaderWithDefaults = createHeaderWithDefaults(ctx);
20
- const FooterWithDefaults = createFooterWithDefaults(ctx);
19
+ const { Header: HeaderWithDefaults, Footer: FooterWithDefaults } = derivePrimaryChromeSlots(ctx);
21
20
  const BodyEndIslands = deriveBodyEndIslands(ctx);
22
21
  const homeExtras = ctx.hostBindings.homeExtras;
22
+ const dataThemePack = resolveThemePackSsrSlug(
23
+ ctx.themePackRegistry,
24
+ ctx.settings
25
+ );
23
26
  function HomePageView({
24
27
  locale,
25
28
  extras,
26
29
  tree,
27
30
  categoryOrder,
31
+ initiallyCollapsedCategorySlugs,
28
32
  tagCount,
29
33
  wide
30
34
  }) {
@@ -39,6 +43,7 @@ function createHomePageView(ctx) {
39
43
  title: composeMetaTitle(settings.siteName),
40
44
  head: /* @__PURE__ */ jsx(HeadWithDefaults, { title: settings.siteName }),
41
45
  lang: locale,
46
+ dataThemePack,
42
47
  noindex: settings.noindex,
43
48
  hideSidebar: true,
44
49
  hideToc: true,
@@ -99,7 +104,8 @@ function createHomePageView(ctx) {
99
104
  {
100
105
  tree,
101
106
  categoryOrder,
102
- categoryIgnore: ["inbox", "develop"]
107
+ categoryIgnore: ["inbox", "develop"],
108
+ initiallyCollapsedCategorySlugs
103
109
  }
104
110
  )
105
111
  }),
@@ -28,7 +28,7 @@ function prepareHomeData(ctx, locale, options) {
28
28
  const grouped = ctx.groupSatelliteNodes(tree, categoryOrder);
29
29
  const tagCount = ctx.collectTags(
30
30
  navDocs.filter((d) => !d.data.category_no_page),
31
- (id, data) => data.slug ?? ctx.toRouteSlug(id)
31
+ (entrySlug, data) => data.slug ?? ctx.toRouteSlug(entrySlug)
32
32
  ).size;
33
33
  return { tree: grouped, categoryOrder, tagCount };
34
34
  }