blume 2.0.3 → 2.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 (455) hide show
  1. package/AGENTS.md +1 -0
  2. package/CHANGELOG.md +48 -0
  3. package/README.md +1 -1
  4. package/dist/cli/{chunk-1d7ve1dm.js → chunk-0gz36akr.js} +18 -2
  5. package/dist/cli/{chunk-1d7ve1dm.js.map → chunk-0gz36akr.js.map} +3 -3
  6. package/dist/cli/{chunk-2eytanqx.js → chunk-1n228xqb.js} +2 -2
  7. package/dist/cli/{chunk-yfyb25rh.js → chunk-2f3ndkpw.js} +24 -8
  8. package/dist/cli/chunk-2f3ndkpw.js.map +14 -0
  9. package/dist/cli/{chunk-r20tn01b.js → chunk-2f7n4qzt.js} +8 -2
  10. package/dist/cli/{chunk-r20tn01b.js.map → chunk-2f7n4qzt.js.map} +3 -3
  11. package/dist/cli/{chunk-35d4wj9f.js → chunk-2n4ps1b3.js} +7 -7
  12. package/dist/cli/{chunk-j85vccga.js → chunk-43zcf4gz.js} +97 -57
  13. package/dist/cli/{chunk-j85vccga.js.map → chunk-43zcf4gz.js.map} +6 -6
  14. package/dist/cli/{chunk-e04dxsz1.js → chunk-4ejxbzee.js} +1 -1
  15. package/dist/cli/{chunk-5m5nmvyq.js → chunk-4h8z9vv5.js} +233 -39
  16. package/dist/cli/chunk-4h8z9vv5.js.map +16 -0
  17. package/dist/cli/{chunk-5f86nr5m.js → chunk-5cg2rzgf.js} +18 -16
  18. package/dist/cli/{chunk-5f86nr5m.js.map → chunk-5cg2rzgf.js.map} +2 -2
  19. package/dist/cli/{chunk-tzmab476.js → chunk-5ffywsmb.js} +4 -4
  20. package/dist/cli/{chunk-2z928egk.js → chunk-5wj2qwn2.js} +5 -5
  21. package/dist/cli/chunk-6bm0xpgd.js +18 -0
  22. package/dist/cli/chunk-6bm0xpgd.js.map +10 -0
  23. package/dist/cli/{chunk-vg9r4eb9.js → chunk-713mngdq.js} +12 -5
  24. package/dist/cli/{chunk-vg9r4eb9.js.map → chunk-713mngdq.js.map} +3 -3
  25. package/dist/cli/{chunk-5xvm6tfj.js → chunk-9geymqns.js} +17 -15
  26. package/dist/cli/{chunk-5xvm6tfj.js.map → chunk-9geymqns.js.map} +2 -2
  27. package/dist/cli/{chunk-q58y5e6a.js → chunk-9xr4dgee.js} +26 -17
  28. package/dist/cli/chunk-9xr4dgee.js.map +10 -0
  29. package/dist/cli/{chunk-b07cmahc.js → chunk-amrb6hgh.js} +2 -2
  30. package/dist/cli/chunk-cm89scdv.js +443 -0
  31. package/dist/cli/chunk-cm89scdv.js.map +11 -0
  32. package/dist/cli/{chunk-akbpwfxc.js → chunk-cmtcnh9f.js} +2 -2
  33. package/dist/cli/chunk-cy5bm0j0.js +104 -0
  34. package/dist/cli/chunk-cy5bm0j0.js.map +11 -0
  35. package/dist/cli/{chunk-crgn1q09.js → chunk-e7vvk5ya.js} +4 -4
  36. package/dist/cli/{chunk-pehfxfta.js → chunk-g2z9x01v.js} +6 -98
  37. package/dist/cli/chunk-g2z9x01v.js.map +10 -0
  38. package/dist/cli/{chunk-tkacnehg.js → chunk-gp84za0h.js} +2 -2
  39. package/dist/cli/{chunk-wrr3j9w9.js → chunk-h2a48yhd.js} +186 -63
  40. package/dist/cli/chunk-h2a48yhd.js.map +36 -0
  41. package/dist/cli/{chunk-hm3vjy5s.js → chunk-jnwj5kjj.js} +14 -9
  42. package/dist/cli/{chunk-hm3vjy5s.js.map → chunk-jnwj5kjj.js.map} +4 -4
  43. package/dist/cli/chunk-kwrg63tm.js +31 -0
  44. package/dist/cli/chunk-kwrg63tm.js.map +10 -0
  45. package/dist/cli/{chunk-2hsdwb9n.js → chunk-nd1821sk.js} +18 -16
  46. package/dist/cli/{chunk-2hsdwb9n.js.map → chunk-nd1821sk.js.map} +2 -2
  47. package/dist/cli/{chunk-6dsbexzp.js → chunk-ntv4qrt7.js} +17 -15
  48. package/dist/cli/{chunk-6dsbexzp.js.map → chunk-ntv4qrt7.js.map} +2 -2
  49. package/dist/cli/{chunk-r9rcc4w7.js → chunk-p804f3pe.js} +7 -7
  50. package/dist/cli/{chunk-ey84smr6.js → chunk-py62fewh.js} +6 -6
  51. package/dist/cli/{chunk-ey84smr6.js.map → chunk-py62fewh.js.map} +1 -1
  52. package/dist/cli/chunk-q3wxxq39.js +126 -0
  53. package/dist/cli/chunk-q3wxxq39.js.map +11 -0
  54. package/dist/cli/{chunk-9t7a85s3.js → chunk-rekqz4qg.js} +23 -13
  55. package/dist/cli/chunk-rekqz4qg.js.map +10 -0
  56. package/dist/cli/{chunk-8ktnccpt.js → chunk-ta27feev.js} +1 -1
  57. package/dist/cli/{chunk-pv29h0wf.js → chunk-xkz5xbtv.js} +3476 -822
  58. package/dist/cli/chunk-xkz5xbtv.js.map +213 -0
  59. package/dist/cli/{chunk-a58773jm.js → chunk-y4ykbark.js} +2 -2
  60. package/dist/cli/{chunk-p3v96n38.js → chunk-y5h4r2y0.js} +4 -4
  61. package/dist/cli/{chunk-acanzt5p.js → chunk-yj17vs39.js} +6 -6
  62. package/dist/cli/{chunk-p73c0m7w.js → chunk-yxmk4pec.js} +16 -14
  63. package/dist/cli/{chunk-p73c0m7w.js.map → chunk-yxmk4pec.js.map} +2 -2
  64. package/dist/cli/{chunk-3em5wd2y.js → chunk-zccbjcj0.js} +4 -3
  65. package/dist/cli/{chunk-3em5wd2y.js.map → chunk-zccbjcj0.js.map} +2 -2
  66. package/dist/cli/{chunk-c8chx29p.js → chunk-zf748avv.js} +384 -207
  67. package/dist/cli/chunk-zf748avv.js.map +37 -0
  68. package/dist/cli/{chunk-g4hq16wv.js → chunk-zhvd6adm.js} +16 -14
  69. package/dist/cli/{chunk-g4hq16wv.js.map → chunk-zhvd6adm.js.map} +2 -2
  70. package/dist/cli/index.js +26 -20
  71. package/dist/cli/index.js.map +5 -5
  72. package/dist/types/ai/agent-surface.d.ts +8 -7
  73. package/dist/types/ai/ai-catalog.d.ts +7 -0
  74. package/dist/types/ai/ask-context.d.ts +22 -0
  75. package/dist/types/ai/ask.d.ts +271 -58
  76. package/dist/types/ai/index.d.ts +2 -2
  77. package/dist/types/ai/site-skill.d.ts +26 -0
  78. package/dist/types/ai/skills.d.ts +16 -0
  79. package/dist/types/astro/integration.d.ts +8 -0
  80. package/dist/types/captcha/hcaptcha.d.ts +27 -0
  81. package/dist/types/captcha/index.d.ts +28 -0
  82. package/dist/types/captcha/schema.d.ts +29 -0
  83. package/dist/types/captcha/turnstile.d.ts +28 -0
  84. package/dist/types/components/content/api-field.d.ts +59 -0
  85. package/dist/types/components/content/api-page.d.ts +95 -0
  86. package/dist/types/components/layout/nav-utils.d.ts +26 -0
  87. package/dist/types/components/openapi/helpers.d.ts +137 -0
  88. package/dist/types/components/openapi/security.d.ts +85 -0
  89. package/dist/types/consent/ethyca.d.ts +48 -0
  90. package/dist/types/consent/index.d.ts +37 -0
  91. package/dist/types/consent/native.d.ts +28 -0
  92. package/dist/types/consent/osano.d.ts +42 -0
  93. package/dist/types/consent/schema.d.ts +110 -0
  94. package/dist/types/core/config-input.d.ts +187 -20
  95. package/dist/types/core/data.d.ts +49 -4
  96. package/dist/types/core/footer.d.ts +8 -0
  97. package/dist/types/core/i18n-ui.d.ts +86 -0
  98. package/dist/types/core/includes.d.ts +8 -2
  99. package/dist/types/core/localizable.d.ts +7 -0
  100. package/dist/types/core/page-modes.d.ts +29 -0
  101. package/dist/types/core/redirect-patterns.d.ts +144 -0
  102. package/dist/types/core/related.d.ts +40 -0
  103. package/dist/types/core/schema.d.ts +551 -56
  104. package/dist/types/core/sources/read.d.ts +5 -0
  105. package/dist/types/core/types.d.ts +1 -1
  106. package/dist/types/core/variables.d.ts +42 -0
  107. package/dist/types/deploy/node-headers.d.ts +13 -2
  108. package/dist/types/deploy/platforms/cloudflare.d.ts +5 -0
  109. package/dist/types/deploy/platforms/netlify.d.ts +7 -0
  110. package/dist/types/deploy/platforms/vercel.d.ts +6 -0
  111. package/dist/types/deploy/redirects.d.ts +39 -11
  112. package/dist/types/deploy/vercel-negotiation.d.ts +9 -0
  113. package/dist/types/markdown/code-title.d.ts +17 -0
  114. package/dist/types/markdown/features.d.ts +3 -2
  115. package/dist/types/narration/build.d.ts +70 -0
  116. package/dist/types/narration/provider.d.ts +26 -0
  117. package/dist/types/narration/script.d.ts +154 -0
  118. package/dist/types/openapi/model.d.ts +12 -6
  119. package/dist/types/openapi/overlay.d.ts +54 -0
  120. package/dist/types/openapi/parse.d.ts +13 -0
  121. package/dist/types/openapi/references.d.ts +14 -4
  122. package/dist/types/ratelimit/cloudflare.d.ts +39 -0
  123. package/dist/types/ratelimit/index.d.ts +27 -0
  124. package/dist/types/ratelimit/memory.d.ts +36 -0
  125. package/dist/types/ratelimit/schema.d.ts +111 -0
  126. package/dist/types/ratelimit/upstash.d.ts +21 -0
  127. package/dist/types/ratelimit/wrangler.d.ts +23 -0
  128. package/dist/types/reference/asyncapi.d.ts +10 -10
  129. package/dist/types/reference/graphql.d.ts +13 -10
  130. package/dist/types/reference/openapi.d.ts +33 -12
  131. package/dist/types/reference/options.d.ts +45 -5
  132. package/dist/types/reference/scalar.d.ts +13 -0
  133. package/dist/types/reference/schema.d.ts +60 -36
  134. package/dist/types/search/documents.d.ts +12 -1
  135. package/dist/types/search/orama-index.d.ts +4 -0
  136. package/dist/types/seo/metatags.d.ts +20 -0
  137. package/docs/02-deployment.mdx +41 -5
  138. package/docs/03-upgrading.mdx +4 -4
  139. package/docs/04-migrating.mdx +1 -1
  140. package/docs/advanced/changelog.mdx +2 -2
  141. package/docs/advanced/skills.mdx +14 -0
  142. package/docs/cli/audit.mdx +21 -1
  143. package/docs/cli/index.mdx +1 -0
  144. package/docs/configuration/analytics.mdx +3 -1
  145. package/docs/configuration/assistant.mdx +188 -36
  146. package/docs/configuration/consent.mdx +100 -0
  147. package/docs/configuration/customization.mdx +4 -4
  148. package/docs/configuration/index.mdx +63 -5
  149. package/docs/configuration/meta.ts +3 -0
  150. package/docs/configuration/narration.mdx +119 -0
  151. package/docs/configuration/rate-limiting.mdx +69 -0
  152. package/docs/configuration/search.mdx +29 -1
  153. package/docs/configuration/theming.mdx +3 -1
  154. package/docs/content/components.mdx +106 -0
  155. package/docs/content/frontmatter.mdx +76 -0
  156. package/docs/content/i18n.mdx +38 -3
  157. package/docs/content/includes.mdx +16 -0
  158. package/docs/content/meta.mdx +1 -0
  159. package/docs/content/meta.ts +1 -0
  160. package/docs/content/navigation.mdx +28 -6
  161. package/docs/content/sources/contentful.mdx +32 -0
  162. package/docs/content/sources/custom.mdx +39 -0
  163. package/docs/content/sources/github-releases.mdx +31 -0
  164. package/docs/content/sources/index.mdx +91 -0
  165. package/docs/content/sources/meta.ts +16 -0
  166. package/docs/content/sources/notion.mdx +32 -0
  167. package/docs/content/sources/obsidian.mdx +37 -0
  168. package/docs/content/sources/payload.mdx +30 -0
  169. package/docs/content/sources/remote-mdx.mdx +40 -0
  170. package/docs/content/sources/sanity.mdx +29 -0
  171. package/docs/content/sources/strapi.mdx +31 -0
  172. package/docs/content/syntax.mdx +67 -2
  173. package/docs/content/variables.mdx +41 -0
  174. package/docs/discoverability/agent-discovery.mdx +29 -2
  175. package/docs/discoverability/index.mdx +1 -1
  176. package/docs/discoverability/llms-txt.mdx +1 -1
  177. package/docs/discoverability/metadata.mdx +17 -0
  178. package/docs/references/api-pages.mdx +74 -0
  179. package/docs/references/asyncapi.mdx +1 -1
  180. package/docs/references/graphql.mdx +2 -2
  181. package/docs/references/meta.ts +1 -1
  182. package/docs/references/openapi.mdx +102 -3
  183. package/docs/references/scalar.mdx +3 -1
  184. package/package.json +36 -1
  185. package/skills/blume/SKILL.md +3 -0
  186. package/skills/blume-migrate/SKILL.md +5 -5
  187. package/skills/blume-migrate/references/docusaurus.md +3 -3
  188. package/skills/blume-migrate/references/mintlify.md +37 -19
  189. package/skills/blume-migrate/references/nextra.md +2 -2
  190. package/skills/blume-migrate/references/starlight.md +2 -1
  191. package/skills/blume-migrate/scripts/mintlify-codemod.mjs +60 -14
  192. package/skills/blume-write-skill/SKILL.md +82 -0
  193. package/src/ai/agent-readability.ts +2 -1
  194. package/src/ai/agent-surface.ts +9 -7
  195. package/src/ai/ai-catalog.ts +6 -3
  196. package/src/ai/ask-context.ts +73 -20
  197. package/src/ai/ask-data.ts +6 -0
  198. package/src/ai/ask-tools.ts +142 -0
  199. package/src/ai/ask.ts +354 -76
  200. package/src/ai/component-markdown.ts +75 -0
  201. package/src/ai/cors.ts +2 -0
  202. package/src/ai/index.ts +12 -0
  203. package/src/ai/llms.ts +6 -2
  204. package/src/ai/markdown.ts +2 -1
  205. package/src/ai/mcp/data.ts +6 -0
  206. package/src/ai/openapi-components.ts +9 -3
  207. package/src/ai/site-skill.ts +274 -0
  208. package/src/ai/skills.ts +35 -2
  209. package/src/ai/write-skill.ts +97 -0
  210. package/src/astro/generate.ts +132 -18
  211. package/src/astro/index.ts +1 -0
  212. package/src/astro/integration.ts +35 -0
  213. package/src/astro/module-types.ts +6 -0
  214. package/src/astro/templates.ts +283 -30
  215. package/src/astro/variables.ts +31 -0
  216. package/src/audit/catalog.ts +19 -0
  217. package/src/audit/checks/contrast.ts +183 -0
  218. package/src/audit/checks/i18n.ts +2 -3
  219. package/src/audit/checks/indexability.ts +2 -3
  220. package/src/audit/checks/links.ts +5 -12
  221. package/src/audit/checks/sitemap.ts +2 -3
  222. package/src/audit/redirects.ts +46 -15
  223. package/src/audit/run.ts +2 -0
  224. package/src/audit/types.ts +2 -1
  225. package/src/blume-modules.d.ts +7 -0
  226. package/src/captcha/client.ts +152 -0
  227. package/src/captcha/hcaptcha.ts +36 -0
  228. package/src/captcha/index.ts +28 -0
  229. package/src/captcha/schema.ts +32 -0
  230. package/src/captcha/turnstile.ts +38 -0
  231. package/src/captcha/verify.ts +71 -0
  232. package/src/cli/command-meta.ts +5 -0
  233. package/src/cli/commands/doctor.ts +22 -16
  234. package/src/cli/commands/skill.ts +96 -0
  235. package/src/cli/index.ts +5 -0
  236. package/src/cli/required-secrets.ts +71 -29
  237. package/src/components/BlumePage.astro +2 -0
  238. package/src/components/content/ApiEndpoint.astro +18 -0
  239. package/src/components/content/ApiField.astro +79 -0
  240. package/src/components/content/ApiPlayground.astro +62 -0
  241. package/src/components/content/ApiRail.astro +19 -0
  242. package/src/components/content/Color.astro +1 -0
  243. package/src/components/content/FileTree.astro +1 -0
  244. package/src/components/content/GithubInfo.astro +1 -0
  245. package/src/components/content/Panel.astro +1 -0
  246. package/src/components/content/ParamField.astro +25 -0
  247. package/src/components/content/RequestExample.astro +17 -0
  248. package/src/components/content/ResponseExample.astro +17 -0
  249. package/src/components/content/ResponseField.astro +32 -0
  250. package/src/components/content/Step.astro +1 -0
  251. package/src/components/content/Tile.astro +1 -0
  252. package/src/components/content/Tooltip.astro +1 -0
  253. package/src/components/content/Tree.astro +1 -0
  254. package/src/components/content/TypeTable.astro +4 -1
  255. package/src/components/content/View.astro +21 -0
  256. package/src/components/content/ViewSwitcher.astro +168 -0
  257. package/src/components/content/api-field.ts +100 -0
  258. package/src/components/content/api-page.ts +224 -0
  259. package/src/components/content/view-switcher.ts +71 -0
  260. package/src/components/index.ts +2 -0
  261. package/src/components/islands/Assistant.astro +10 -1
  262. package/src/components/islands/assistant.tsx +104 -14
  263. package/src/components/islands/code-question.ts +62 -0
  264. package/src/components/islands/hooks.ts +110 -21
  265. package/src/components/islands/support-link.ts +68 -0
  266. package/src/components/layout/Analytics.astro +11 -2
  267. package/src/components/layout/Banner.astro +14 -10
  268. package/src/components/layout/Breadcrumbs.astro +6 -2
  269. package/src/components/layout/ConsentBanner.astro +62 -0
  270. package/src/components/layout/ConsentHead.astro +38 -0
  271. package/src/components/layout/Directory.astro +94 -0
  272. package/src/components/layout/DrawerSwitchers.astro +51 -0
  273. package/src/components/layout/Empty.astro +2 -2
  274. package/src/components/layout/Header.astro +122 -80
  275. package/src/components/layout/LanguageSwitcher.astro +48 -15
  276. package/src/components/layout/NarrationPlayer.astro +1085 -0
  277. package/src/components/layout/NavSelector.astro +33 -7
  278. package/src/components/layout/PageFeedback.astro +54 -49
  279. package/src/components/layout/PageLayout.astro +71 -3
  280. package/src/components/layout/ReferenceLayout.astro +17 -6
  281. package/src/components/layout/RelatedPages.astro +42 -0
  282. package/src/components/layout/RootLayout.astro +308 -45
  283. package/src/components/layout/Search.astro +31 -17
  284. package/src/components/layout/SiteFooter.astro +124 -0
  285. package/src/components/layout/SiteMetatags.astro +16 -0
  286. package/src/components/layout/consent/native.ts +79 -0
  287. package/src/components/layout/consent/types.ts +37 -0
  288. package/src/components/layout/footer-links.ts +53 -0
  289. package/src/components/layout/footer-socials.ts +87 -0
  290. package/src/components/layout/locale-redirect.ts +107 -0
  291. package/src/components/layout/nav-utils.ts +83 -0
  292. package/src/components/layout/page-feedback.ts +96 -0
  293. package/src/components/layout/search/analytics.ts +98 -0
  294. package/src/components/layout/search/flexsearch.ts +17 -5
  295. package/src/components/layout/search/orama-cloud.ts +26 -14
  296. package/src/components/layout/search/types.ts +20 -0
  297. package/src/components/layout/search/typesense.ts +5 -1
  298. package/src/components/openapi/Operation.astro +161 -13
  299. package/src/components/openapi/RequestBody.astro +6 -4
  300. package/src/components/openapi/RequestPanel.astro +59 -7
  301. package/src/components/openapi/Responses.astro +6 -4
  302. package/src/components/openapi/async-snippets.ts +4 -4
  303. package/src/components/openapi/code-samples.ts +97 -0
  304. package/src/components/openapi/security.ts +6 -3
  305. package/src/components/openapi/snippets.ts +869 -8
  306. package/src/components/props.ts +6 -0
  307. package/src/consent/client.ts +95 -0
  308. package/src/consent/clients.ts +19 -0
  309. package/src/consent/ethyca.ts +71 -0
  310. package/src/consent/head.ts +24 -0
  311. package/src/consent/index.ts +37 -0
  312. package/src/consent/init.ts +29 -0
  313. package/src/consent/native.ts +36 -0
  314. package/src/consent/osano.ts +59 -0
  315. package/src/consent/schema.ts +30 -0
  316. package/src/core/builtin-tags.ts +5 -0
  317. package/src/core/client-address.ts +19 -0
  318. package/src/core/config-input.ts +194 -20
  319. package/src/core/data.ts +44 -4
  320. package/src/core/diagnostics.ts +3 -2
  321. package/src/core/footer.ts +26 -0
  322. package/src/core/graph.ts +39 -36
  323. package/src/core/i18n-ui.ts +82 -2
  324. package/src/core/includes.ts +20 -3
  325. package/src/core/links.ts +16 -2
  326. package/src/core/localizable.ts +26 -0
  327. package/src/core/navigation.ts +43 -12
  328. package/src/core/page-modes.ts +56 -0
  329. package/src/core/project-graph.ts +111 -5
  330. package/src/core/redirect-patterns.ts +491 -0
  331. package/src/core/related.ts +131 -0
  332. package/src/core/schema.ts +318 -64
  333. package/src/core/sources/normalize.ts +2 -1
  334. package/src/core/sources/read.ts +8 -3
  335. package/src/core/types.ts +1 -1
  336. package/src/core/ui-packs/ar.ts +43 -0
  337. package/src/core/ui-packs/bg.ts +45 -0
  338. package/src/core/ui-packs/bn.ts +43 -0
  339. package/src/core/ui-packs/ca.ts +46 -0
  340. package/src/core/ui-packs/cs.ts +44 -0
  341. package/src/core/ui-packs/da.ts +45 -0
  342. package/src/core/ui-packs/de.ts +46 -0
  343. package/src/core/ui-packs/el.ts +45 -0
  344. package/src/core/ui-packs/es.ts +46 -0
  345. package/src/core/ui-packs/fa.ts +45 -0
  346. package/src/core/ui-packs/fi.ts +45 -0
  347. package/src/core/ui-packs/fr.ts +46 -0
  348. package/src/core/ui-packs/he.ts +43 -0
  349. package/src/core/ui-packs/hi.ts +44 -0
  350. package/src/core/ui-packs/hr.ts +45 -0
  351. package/src/core/ui-packs/hu.ts +44 -0
  352. package/src/core/ui-packs/id.ts +45 -0
  353. package/src/core/ui-packs/it.ts +45 -0
  354. package/src/core/ui-packs/ja.ts +45 -0
  355. package/src/core/ui-packs/ko.ts +44 -0
  356. package/src/core/ui-packs/nl.ts +46 -0
  357. package/src/core/ui-packs/no.ts +44 -0
  358. package/src/core/ui-packs/pl.ts +45 -0
  359. package/src/core/ui-packs/pt-br.ts +46 -0
  360. package/src/core/ui-packs/pt.ts +45 -0
  361. package/src/core/ui-packs/ro.ts +45 -0
  362. package/src/core/ui-packs/ru.ts +45 -0
  363. package/src/core/ui-packs/sk.ts +44 -0
  364. package/src/core/ui-packs/sr.ts +45 -0
  365. package/src/core/ui-packs/sv.ts +44 -0
  366. package/src/core/ui-packs/th.ts +43 -0
  367. package/src/core/ui-packs/tr.ts +45 -0
  368. package/src/core/ui-packs/uk.ts +45 -0
  369. package/src/core/ui-packs/vi.ts +45 -0
  370. package/src/core/ui-packs/zh-tw.ts +43 -0
  371. package/src/core/ui-packs/zh.ts +43 -0
  372. package/src/core/variables.ts +103 -0
  373. package/src/deploy/artifacts.ts +77 -8
  374. package/src/deploy/cloudflare-negotiation.ts +35 -5
  375. package/src/deploy/headers.ts +2 -1
  376. package/src/deploy/node-headers.ts +63 -9
  377. package/src/deploy/platforms/cloudflare.ts +32 -0
  378. package/src/deploy/platforms/netlify.ts +33 -1
  379. package/src/deploy/platforms/vercel.ts +37 -2
  380. package/src/deploy/redirects.ts +91 -24
  381. package/src/deploy/vercel-negotiation.ts +36 -0
  382. package/src/markdown/api-rail.ts +259 -0
  383. package/src/markdown/code-title.ts +35 -9
  384. package/src/markdown/features.ts +3 -2
  385. package/src/markdown/fence-meta.ts +2 -0
  386. package/src/markdown/include.ts +11 -1
  387. package/src/markdown/index.ts +28 -5
  388. package/src/markdown/math.ts +4 -4
  389. package/src/markdown/variables.ts +56 -0
  390. package/src/markdown/views.ts +82 -0
  391. package/src/narration/build.ts +412 -0
  392. package/src/narration/player.ts +249 -0
  393. package/src/narration/provider.ts +29 -0
  394. package/src/narration/script.ts +592 -0
  395. package/src/og/card.ts +7 -6
  396. package/src/openapi/model.ts +57 -24
  397. package/src/openapi/overlay.ts +256 -0
  398. package/src/openapi/parse.ts +55 -2
  399. package/src/openapi/references.ts +21 -5
  400. package/src/openapi/render-mdx.ts +5 -1
  401. package/src/openapi/scalar.ts +40 -6
  402. package/src/openapi/source.ts +1 -1
  403. package/src/ratelimit/cloudflare.ts +54 -0
  404. package/src/ratelimit/index.ts +30 -0
  405. package/src/ratelimit/memory.ts +45 -0
  406. package/src/ratelimit/runtime.ts +229 -0
  407. package/src/ratelimit/schema.ts +28 -0
  408. package/src/ratelimit/upstash.ts +30 -0
  409. package/src/ratelimit/wrangler.ts +70 -0
  410. package/src/reference/asyncapi.ts +2 -2
  411. package/src/reference/graphql.ts +5 -2
  412. package/src/reference/openapi.ts +21 -7
  413. package/src/reference/options.ts +51 -7
  414. package/src/reference/scalar.ts +33 -8
  415. package/src/registry/eject.ts +20 -4
  416. package/src/registry/registry.ts +7 -0
  417. package/src/search/documents.ts +26 -2
  418. package/src/search/orama-index.ts +28 -3
  419. package/src/search/pagefind-ranking.ts +39 -0
  420. package/src/search/sync/algolia.ts +15 -4
  421. package/src/search/sync/orama-cloud.ts +3 -0
  422. package/src/search/sync/typesense.ts +5 -0
  423. package/src/seo/metatags.ts +67 -0
  424. package/src/theme/chrome-icons.ts +1 -0
  425. package/src/theme/color.ts +500 -0
  426. package/src/theme/entry.ts +56 -3
  427. package/src/theme/palette.ts +121 -45
  428. package/src/translate/prompts.ts +1 -0
  429. package/src/translate/validate.ts +8 -2
  430. package/src/upgrade/upgrade.ts +4 -171
  431. package/dist/cli/chunk-364znk6q.js +0 -75
  432. package/dist/cli/chunk-364znk6q.js.map +0 -11
  433. package/dist/cli/chunk-5m5nmvyq.js.map +0 -13
  434. package/dist/cli/chunk-9t7a85s3.js.map +0 -10
  435. package/dist/cli/chunk-c8chx29p.js.map +0 -36
  436. package/dist/cli/chunk-pehfxfta.js.map +0 -10
  437. package/dist/cli/chunk-pv29h0wf.js.map +0 -190
  438. package/dist/cli/chunk-q58y5e6a.js.map +0 -10
  439. package/dist/cli/chunk-wrr3j9w9.js.map +0 -35
  440. package/dist/cli/chunk-yfyb25rh.js.map +0 -14
  441. package/docs/content/sources.mdx +0 -334
  442. /package/dist/cli/{chunk-2eytanqx.js.map → chunk-1n228xqb.js.map} +0 -0
  443. /package/dist/cli/{chunk-35d4wj9f.js.map → chunk-2n4ps1b3.js.map} +0 -0
  444. /package/dist/cli/{chunk-e04dxsz1.js.map → chunk-4ejxbzee.js.map} +0 -0
  445. /package/dist/cli/{chunk-tzmab476.js.map → chunk-5ffywsmb.js.map} +0 -0
  446. /package/dist/cli/{chunk-2z928egk.js.map → chunk-5wj2qwn2.js.map} +0 -0
  447. /package/dist/cli/{chunk-b07cmahc.js.map → chunk-amrb6hgh.js.map} +0 -0
  448. /package/dist/cli/{chunk-akbpwfxc.js.map → chunk-cmtcnh9f.js.map} +0 -0
  449. /package/dist/cli/{chunk-crgn1q09.js.map → chunk-e7vvk5ya.js.map} +0 -0
  450. /package/dist/cli/{chunk-tkacnehg.js.map → chunk-gp84za0h.js.map} +0 -0
  451. /package/dist/cli/{chunk-r9rcc4w7.js.map → chunk-p804f3pe.js.map} +0 -0
  452. /package/dist/cli/{chunk-8ktnccpt.js.map → chunk-ta27feev.js.map} +0 -0
  453. /package/dist/cli/{chunk-a58773jm.js.map → chunk-y4ykbark.js.map} +0 -0
  454. /package/dist/cli/{chunk-p3v96n38.js.map → chunk-y5h4r2y0.js.map} +0 -0
  455. /package/dist/cli/{chunk-acanzt5p.js.map → chunk-yj17vs39.js.map} +0 -0
@@ -2,7 +2,7 @@
2
2
  import Ask from "blume:ask";
3
3
  import data from "blume:data";
4
4
  import { withBase, withMountedBase } from "../islands/base-path.ts";
5
- import { NEW_TAB_ATTRS, newTabAttrs } from "../../core/new-tab.ts";
5
+ import { newTabAttrs } from "../../core/new-tab.ts";
6
6
  import type { ComponentOverride } from "../../core/define-components.ts";
7
7
  import { EN_UI } from "../../core/i18n-ui.ts";
8
8
  import type { UIStrings } from "../../core/i18n-ui.ts";
@@ -11,7 +11,6 @@ import type {
11
11
  Navigation,
12
12
  NavSelector as NavSelectorConfig,
13
13
  } from "../../core/types.ts";
14
- import { GITHUB_MARK } from "../github-mark.ts";
15
14
  import Icon from "../Icon.astro";
16
15
  import LanguageSwitcher from "./LanguageSwitcher.astro";
17
16
  import Logo from "./Logo.astro";
@@ -129,11 +128,19 @@ const activeTab = currentTabForRoute(navigation.tabs, route, navigation.root);
129
128
  // mobile nav below `lg`, so the inline tabs wait until `lg` to avoid duplicating
130
129
  // the drawer's links between `md` and `lg`.
131
130
  const tabsNavClass = hasSidebar
132
- ? "hidden gap-1 md:flex"
133
- : "hidden gap-1 lg:flex";
131
+ ? "hidden shrink-0 gap-1 md:flex"
132
+ : "hidden shrink-0 gap-1 lg:flex";
134
133
 
135
134
  const iconButton =
136
- "inline-flex size-9 cursor-pointer items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-muted hover:text-foreground";
135
+ "inline-flex size-9 shrink-0 cursor-pointer items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-muted hover:text-foreground";
136
+
137
+ // Below `lg`, where the sidebar is a drawer, the selectors, version selector,
138
+ // and language switcher move into a row at the top of it (see
139
+ // DrawerSwitchers.astro): they scope what the sidebar lists, and beside the
140
+ // logo, tabs, search, and icon buttons they'd overflow a phone or tablet
141
+ // header. With no drawer to open they have nowhere else to go, so they stay.
142
+ // Nothing in the header shrinks except the logo, whose title truncates.
143
+ const switcherClass = showNavToggle ? "hidden shrink-0 lg:block" : "shrink-0";
137
144
 
138
145
  // Header links: plain actions are secondary and hide below `sm`, where the
139
146
  // header has room for the logo and the drawer toggle and nothing else. The one
@@ -186,37 +193,44 @@ const clickScript = `(()=>{const dr=()=>{const h=document.querySelector("[data-b
186
193
  ---
187
194
 
188
195
  <header
189
- class="sticky top-0 z-40 flex h-16 items-center gap-3 bg-background/90 px-4 backdrop-blur md:px-6"
196
+ class="sticky top-0 z-40 flex h-16 items-center gap-2 bg-background/90 px-4 backdrop-blur sm:gap-3 md:px-6 lg:grid lg:grid-cols-[minmax(0,1fr)_auto_minmax(max-content,1fr)]"
190
197
  data-blume-header
191
198
  data-blume-header-transparent={transparent ? "" : undefined}
192
199
  >
193
- {
194
- showNavToggle && (
195
- <button
196
- aria-controls="blume-nav-drawer"
197
- aria-expanded="false"
198
- aria-label={n.toggleNavigation}
199
- class={`${iconButton} lg:hidden`}
200
- data-blume-nav-toggle
201
- type="button"
202
- >
203
- <Icon name="menu" size={20} />
204
- </button>
205
- )
206
- }
207
- <LogoSlot locale={locale} logo={logo} site={site} />
208
- {
209
- navigation.selectors.length > 0 && (
210
- <div class="flex items-center gap-1.5">
211
- {navigation.selectors.map((selector) => (
212
- <NavSelector route={route} selector={selector} />
213
- ))}
214
- </div>
215
- )
216
- }
200
+ {/* From `lg` the header is three columns, so the tabs sit at its center:
201
+ the logo side and the controls side share the rest equally. The logo
202
+ side may shrink to nothing (its title truncates, as on phones); the
203
+ controls never shrink, so when they need more than half, the tabs move
204
+ over rather than overlap. Below `lg` it's one row, tabs after the logo. */}
205
+ <div class="flex min-w-0 items-center gap-2 sm:gap-3 lg:col-start-1">
206
+ {
207
+ showNavToggle && (
208
+ <button
209
+ aria-controls="blume-nav-drawer"
210
+ aria-expanded="false"
211
+ aria-label={n.toggleNavigation}
212
+ class={`${iconButton} lg:hidden`}
213
+ data-blume-nav-toggle
214
+ type="button"
215
+ >
216
+ <Icon name="menu" size={20} />
217
+ </button>
218
+ )
219
+ }
220
+ <LogoSlot locale={locale} logo={logo} site={site} />
221
+ {
222
+ navigation.selectors.length > 0 && (
223
+ <div class:list={["flex items-center gap-1.5", switcherClass]}>
224
+ {navigation.selectors.map((selector) => (
225
+ <NavSelector route={route} selector={selector} />
226
+ ))}
227
+ </div>
228
+ )
229
+ }
230
+ </div>
217
231
  {
218
232
  navigation.tabs.length > 0 && (
219
- <nav aria-label={n.sections} class={tabsNavClass}>
233
+ <nav aria-label={n.sections} class:list={[tabsNavClass, "lg:col-start-2"]}>
220
234
  {navigation.tabs.map((tab) =>
221
235
  tab.items && tab.items.length > 0 ? (
222
236
  <NavTabMenu
@@ -241,38 +255,31 @@ const clickScript = `(()=>{const dr=()=>{const h=document.querySelector("[data-b
241
255
  </nav>
242
256
  )
243
257
  }
244
- <div class="flex-1"></div>
245
- {
246
- /* Right-aligned next to the language switcher: the spacer absorbs its
247
- width, so pages without a version selector (blog, generated references)
248
- keep the logo, tabs, and the rest of this cluster in place — no layout
249
- shift when crossing into the docs. */
250
- versionSelector && (
251
- <NavSelector align="end" route={route} selector={versionSelector} />
252
- )
253
- }
254
- {
255
- localeSwitch && localeSwitch.length > 1 && (
256
- <LanguageSwitcher
257
- label={switcherStrings?.label ?? "Language"}
258
- options={localeSwitch}
259
- untranslatedLabel={switcherStrings?.untranslated ?? "Not translated"}
260
- />
261
- )
262
- }
263
- {
264
- searchEnabled && (
265
- <SearchSlot
266
- assistantEnabled={assistantEnabled}
267
- locale={searchLocale}
268
- navigation={navigation}
269
- popularPages={data.config.search.popular}
270
- strings={searchStrings}
271
- version={searchVersion}
272
- />
273
- )
274
- }
275
- <div class="flex items-center gap-2">
258
+ <div class="flex-1 lg:hidden"></div>
259
+ {/* Everything on the right sits in one group with a tight gap: the version
260
+ and language pickers, the header links, and the icon buttons. Below `lg`
261
+ the spacer absorbs its width, so pages without a version selector (blog,
262
+ generated references) keep the logo and tabs in place — no layout shift
263
+ when crossing into the docs. */}
264
+ <div class="flex shrink-0 items-center gap-1 lg:col-start-3 lg:justify-self-end">
265
+ {
266
+ versionSelector && (
267
+ <div class={switcherClass}>
268
+ <NavSelector align="end" route={route} selector={versionSelector} />
269
+ </div>
270
+ )
271
+ }
272
+ {
273
+ localeSwitch && localeSwitch.length > 1 && (
274
+ <div class={switcherClass}>
275
+ <LanguageSwitcher
276
+ label={switcherStrings?.label ?? "Language"}
277
+ options={localeSwitch}
278
+ untranslatedLabel={switcherStrings?.untranslated ?? "Not translated"}
279
+ />
280
+ </div>
281
+ )
282
+ }
276
283
  {
277
284
  /* Plain links first, then the one filled button: the reader's eye lands
278
285
  on the button because nothing beside it competes. */
@@ -299,29 +306,24 @@ const clickScript = `(()=>{const dr=()=>{const h=document.querySelector("[data-b
299
306
  )
300
307
  }
301
308
  {
302
- navigation.repoUrl && (
303
- <a
304
- aria-label={n.githubRepository}
305
- class={iconButton}
306
- href={navigation.repoUrl}
307
- {...NEW_TAB_ATTRS}
308
- >
309
- <svg
310
- aria-hidden="true"
311
- fill="currentColor"
312
- height="18"
313
- set:html={GITHUB_MARK}
314
- viewBox="0 0 16 16"
315
- width="18"
316
- xmlns="http://www.w3.org/2000/svg"
317
- />
318
- </a>
309
+ /* The icon buttons, each named by a tooltip. The site's repository and
310
+ social profiles live in the footer. */
311
+ searchEnabled && (
312
+ <SearchSlot
313
+ assistantEnabled={assistantEnabled}
314
+ locale={searchLocale}
315
+ navigation={navigation}
316
+ popularPages={data.config.search.popular}
317
+ strings={searchStrings}
318
+ version={searchVersion}
319
+ />
319
320
  )
320
321
  }
321
322
  <button
322
323
  aria-label={n.toggleTheme}
323
324
  class={iconButton}
324
325
  data-blume-theme-toggle
326
+ data-blume-tooltip={n.toggleTheme}
325
327
  type="button"
326
328
  >
327
329
  <span class="inline-flex dark:hidden"><Icon name="sun" size={18} /></span>
@@ -334,6 +336,46 @@ const clickScript = `(()=>{const dr=()=>{const h=document.querySelector("[data-b
334
336
  {transparent && <script is:inline set:html={transparentScript} />}
335
337
 
336
338
  <style is:global>
339
+ /* The header's icon buttons are named by a tooltip below them, shown on hover
340
+ (where there is one) and on keyboard focus. It hangs from the button's end
341
+ edge, so the last button's tooltip never runs past the viewport, and it
342
+ keeps the page's own colors under a transparent header. */
343
+ [data-blume-tooltip] {
344
+ position: relative;
345
+ }
346
+ [data-blume-tooltip]::after {
347
+ content: attr(data-blume-tooltip);
348
+ position: absolute;
349
+ top: calc(100% + 0.375rem);
350
+ inset-inline-end: 0;
351
+ z-index: 50;
352
+ padding: 0.25rem 0.5rem;
353
+ border-radius: 0.375rem;
354
+ background-color: var(--blume-header-foreground);
355
+ color: var(--blume-header-background);
356
+ font-size: 0.75rem;
357
+ font-weight: 500;
358
+ line-height: 1rem;
359
+ white-space: nowrap;
360
+ pointer-events: none;
361
+ opacity: 0;
362
+ visibility: hidden;
363
+ transition:
364
+ opacity 120ms ease,
365
+ visibility 0s linear 120ms;
366
+ }
367
+ [data-blume-tooltip]:focus-visible::after {
368
+ opacity: 1;
369
+ visibility: visible;
370
+ transition: opacity 120ms ease;
371
+ }
372
+ @media (hover: hover) {
373
+ [data-blume-tooltip]:hover::after {
374
+ opacity: 1;
375
+ visibility: visible;
376
+ transition: opacity 120ms ease 400ms;
377
+ }
378
+ }
337
379
  /* Transparent header (PageLayout `transparentHeader`): at the top of the
338
380
  page the bar has no background and its chrome renders in white so it can
339
381
  sit over a dark hero; once scrolled it is the frosted bar again. The color
@@ -7,52 +7,82 @@ interface Props {
7
7
  options: LocaleSwitchOption[];
8
8
  label: string;
9
9
  untranslatedLabel: string;
10
+ /**
11
+ * `bar` (the default) for the header; `drawer` for the top of the nav
12
+ * drawer, where the trigger spans the drawer and opens a panel as wide as
13
+ * itself, so nothing reaches past the drawer edge.
14
+ */
15
+ variant?: "bar" | "drawer";
10
16
  }
11
17
 
12
- const { options, label, untranslatedLabel } = Astro.props;
18
+ const { options, label, untranslatedLabel, variant = "bar" } = Astro.props;
13
19
  const current = options.find((option) => option.current);
14
20
  // The accessible name carries the visible language name too (WCAG 2.5.3,
15
21
  // label in name), so a voice-control user can say "English" to open it.
16
22
  const summaryLabel = current ? `${label}: ${current.label}` : label;
17
23
 
18
- const iconButton =
19
- "inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-full border border-border bg-background px-3 text-muted-foreground text-sm transition-colors hover:border-foreground hover:text-foreground";
24
+ // In the header the trigger is styled like the icon buttons beside it: no
25
+ // border, a background on hover and while open. The drawer's spans the
26
+ // drawer, where the border marks it as a control.
27
+ const triggerClass =
28
+ variant === "bar"
29
+ ? "inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-full px-3 text-muted-foreground text-sm transition-colors hover:bg-muted hover:text-foreground group-open:bg-muted group-open:text-foreground"
30
+ : "inline-flex h-9 w-full cursor-pointer items-center gap-1.5 rounded-full border border-border bg-background px-3 text-muted-foreground text-sm transition-colors hover:border-foreground hover:text-foreground";
20
31
  const menuRowClass =
21
- "flex w-full items-center gap-2.5 rounded-md px-2 py-1.5 text-start text-muted-foreground text-sm transition-colors hover:bg-muted hover:text-foreground aria-[current=true]:text-foreground";
32
+ "flex w-full items-center gap-4 rounded-md px-2 py-1.5 text-start text-muted-foreground text-sm transition-colors hover:bg-muted hover:text-foreground aria-[current=true]:text-foreground";
22
33
  ---
23
34
 
24
35
  {
25
36
  options.length > 1 && (
26
- <details class="group relative" data-blume-dropdown>
37
+ <details
38
+ class:list={["group relative", variant === "drawer" && "w-full"]}
39
+ data-blume-dropdown
40
+ >
27
41
  <summary
28
42
  aria-label={summaryLabel}
29
- class={`${iconButton} list-none [&::-webkit-details-marker]:hidden`}
43
+ class:list={[triggerClass, "list-none [&::-webkit-details-marker]:hidden"]}
30
44
  >
31
- <Icon name="globe" size={16} />
32
- {/* Collapses to the globe icon below `lg`, matching the search field. */}
33
- <span class="max-lg:hidden">{current?.label ?? label}</span>
45
+ <span class:list={[variant === "drawer" && "flex-1 text-start"]}>
46
+ {current?.label ?? label}
47
+ </span>
34
48
  <Icon
35
49
  class="transition-transform group-open:rotate-180"
36
50
  name="chevron-down"
37
51
  size={14}
38
52
  />
39
53
  </summary>
40
- <div class="absolute end-0 z-50 mt-2 min-w-44 rounded-blume border border-border bg-background p-1 shadow-xl">
54
+ <div
55
+ class:list={[
56
+ "absolute z-50 mt-2 rounded-blume border border-border bg-background p-1 shadow-xl",
57
+ // As wide as its longest row: the panel hangs from a narrow trigger,
58
+ // so it wouldn't otherwise grow past its minimum.
59
+ variant === "bar"
60
+ ? "end-0 w-max min-w-44 max-w-[calc(100vw-1rem)]"
61
+ : "inset-x-0",
62
+ ]}
63
+ >
41
64
  {options.map((option) => (
42
65
  <a
43
66
  aria-current={option.current ? "true" : undefined}
44
67
  class={menuRowClass}
68
+ data-blume-locale-choice
45
69
  href={withMountedBase(option.href)}
46
70
  hreflang={option.code}
47
71
  lang={option.code}
48
72
  >
49
- <span class="flex-1">{option.label}</span>
50
- {option.untranslated && (
51
- <span class="text-muted-foreground text-xs italic">
52
- {untranslatedLabel}
73
+ {/* The name keeps its full width, so the panel grows to fit the
74
+ longest row; the note and check sit at the far end. */}
75
+ <span>{option.label}</span>
76
+ {(option.untranslated || option.current) && (
77
+ <span class="ms-auto flex items-center gap-2.5">
78
+ {option.untranslated && (
79
+ <span class="text-muted-foreground text-xs italic">
80
+ {untranslatedLabel}
81
+ </span>
82
+ )}
83
+ {option.current && <Icon name="check" size={14} />}
53
84
  </span>
54
85
  )}
55
- {option.current && <Icon name="check" size={14} />}
56
86
  </a>
57
87
  ))}
58
88
  </div>
@@ -62,8 +92,11 @@ const menuRowClass =
62
92
 
63
93
  <script>
64
94
  import { installDropdownDismiss } from "../dropdown-dismiss.ts";
95
+ import { rememberLocaleChoice } from "./locale-redirect.ts";
65
96
 
66
97
  // Outside-click / Escape / focus-out dismissal, shared with the nav
67
98
  // selectors and the page actions.
68
99
  installDropdownDismiss();
100
+ // A language picked here stops routing by browser language.
101
+ rememberLocaleChoice(document);
69
102
  </script>