blume 2.1.3 → 2.2.1

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 (397) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +134 -0
  3. package/README.md +4 -4
  4. package/dist/cli/{chunk-y4msrwm9.js → chunk-080mfch6.js} +15 -15
  5. package/dist/cli/{chunk-gfc5fqvf.js → chunk-1ch3ct3r.js} +18 -18
  6. package/dist/cli/{chunk-gfc5fqvf.js.map → chunk-1ch3ct3r.js.map} +1 -1
  7. package/dist/cli/{chunk-32khwcb6.js → chunk-2ssh60qh.js} +42 -69
  8. package/dist/cli/{chunk-32khwcb6.js.map → chunk-2ssh60qh.js.map} +9 -10
  9. package/dist/cli/{chunk-9qzgg6mj.js → chunk-34wap3ed.js} +3 -3
  10. package/dist/cli/{chunk-k3gr1nm9.js → chunk-40vk8kgf.js} +13 -16
  11. package/dist/cli/{chunk-k3gr1nm9.js.map → chunk-40vk8kgf.js.map} +3 -3
  12. package/dist/cli/chunk-487b95qy.js +329 -0
  13. package/dist/cli/chunk-487b95qy.js.map +13 -0
  14. package/dist/cli/chunk-4zxh25hc.js +157 -0
  15. package/dist/cli/chunk-4zxh25hc.js.map +10 -0
  16. package/dist/cli/chunk-69rjf786.js +146 -0
  17. package/dist/cli/chunk-69rjf786.js.map +11 -0
  18. package/dist/cli/{chunk-dqhg54mr.js → chunk-9h8mh2tk.js} +3 -3
  19. package/dist/cli/{chunk-dqhg54mr.js.map → chunk-9h8mh2tk.js.map} +2 -2
  20. package/dist/cli/{chunk-bqxaqn5p.js → chunk-9jqmq5hv.js} +8 -8
  21. package/dist/cli/{chunk-bqxaqn5p.js.map → chunk-9jqmq5hv.js.map} +1 -1
  22. package/dist/cli/{chunk-dv2z0rzf.js → chunk-aafhwx74.js} +38 -13
  23. package/dist/cli/{chunk-dv2z0rzf.js.map → chunk-aafhwx74.js.map} +5 -4
  24. package/dist/cli/{chunk-desvm72z.js → chunk-b680sv30.js} +22 -26
  25. package/dist/cli/chunk-b680sv30.js.map +13 -0
  26. package/dist/cli/{chunk-0w6hs479.js → chunk-beb0z983.js} +30 -18
  27. package/dist/cli/chunk-beb0z983.js.map +10 -0
  28. package/dist/cli/{chunk-1f882900.js → chunk-c5bjxq8v.js} +2 -2
  29. package/dist/cli/chunk-e1n41w9m.js +155 -0
  30. package/dist/cli/chunk-e1n41w9m.js.map +11 -0
  31. package/dist/cli/{chunk-sc93apfs.js → chunk-etckvbrh.js} +17 -17
  32. package/dist/cli/{chunk-sc93apfs.js.map → chunk-etckvbrh.js.map} +2 -2
  33. package/dist/cli/{chunk-bxwhtvw8.js → chunk-f260jdrn.js} +5 -5
  34. package/dist/cli/{chunk-74wfhv79.js → chunk-fnxgtjeq.js} +1 -1
  35. package/dist/cli/{chunk-ms9z66nz.js → chunk-gwy55cx3.js} +2 -2
  36. package/dist/cli/{chunk-ms9z66nz.js.map → chunk-gwy55cx3.js.map} +2 -2
  37. package/dist/cli/{chunk-dhwtqnnd.js → chunk-gxhcf2hs.js} +2 -2
  38. package/dist/cli/{chunk-tfycddbt.js → chunk-h0qwdbem.js} +2 -2
  39. package/dist/cli/{chunk-nbyvgnnm.js → chunk-hktq4j5r.js} +109 -49
  40. package/dist/cli/chunk-hktq4j5r.js.map +36 -0
  41. package/dist/cli/{chunk-twy7psdz.js → chunk-hn3g2b89.js} +14 -10
  42. package/dist/cli/chunk-hn3g2b89.js.map +10 -0
  43. package/dist/cli/{chunk-j1x92mx9.js → chunk-j4nfgn2j.js} +1 -1
  44. package/dist/cli/{chunk-dpy8qdjf.js → chunk-k45sq16q.js} +74 -183
  45. package/dist/cli/chunk-k45sq16q.js.map +18 -0
  46. package/dist/cli/{chunk-5cmts6dv.js → chunk-kmswjxj9.js} +7 -7
  47. package/dist/cli/{chunk-5cmts6dv.js.map → chunk-kmswjxj9.js.map} +1 -1
  48. package/dist/cli/{chunk-36bxs9c7.js → chunk-nqna8dzp.js} +27 -23
  49. package/dist/cli/chunk-nqna8dzp.js.map +10 -0
  50. package/dist/cli/{chunk-a57yh0h9.js → chunk-p834rkcn.js} +7 -7
  51. package/dist/cli/{chunk-a57yh0h9.js.map → chunk-p834rkcn.js.map} +1 -1
  52. package/dist/cli/{chunk-60hz265r.js → chunk-ppa6mg4d.js} +24 -11
  53. package/dist/cli/chunk-ppa6mg4d.js.map +10 -0
  54. package/dist/cli/{chunk-s0bdnc7v.js → chunk-q1wwrxzw.js} +5 -4
  55. package/dist/cli/chunk-q1wwrxzw.js.map +10 -0
  56. package/dist/cli/{chunk-ave1wcbr.js → chunk-qcyxkj44.js} +1 -1
  57. package/dist/cli/{chunk-124fvmzq.js → chunk-r5nm9w0c.js} +11183 -8806
  58. package/dist/cli/{chunk-124fvmzq.js.map → chunk-r5nm9w0c.js.map} +82 -66
  59. package/dist/cli/{chunk-ckrcm08h.js → chunk-rtvgmg2j.js} +48 -62
  60. package/dist/cli/{chunk-ckrcm08h.js.map → chunk-rtvgmg2j.js.map} +4 -5
  61. package/dist/cli/{chunk-297ajdcv.js → chunk-t2h8pwy1.js} +6 -6
  62. package/dist/cli/{chunk-297ajdcv.js.map → chunk-t2h8pwy1.js.map} +3 -3
  63. package/dist/cli/{chunk-gxtg6ed2.js → chunk-x60e15st.js} +21 -21
  64. package/dist/cli/{chunk-gxtg6ed2.js.map → chunk-x60e15st.js.map} +3 -3
  65. package/dist/cli/{chunk-58bt3hag.js → chunk-x7bh6d9j.js} +4 -4
  66. package/dist/cli/{chunk-hvcxng5f.js → chunk-ydqzkhjn.js} +6 -6
  67. package/dist/cli/{chunk-kdpzw38a.js → chunk-yg8ckc3g.js} +95 -7
  68. package/dist/cli/chunk-yg8ckc3g.js.map +11 -0
  69. package/dist/cli/{chunk-0pmb4tr4.js → chunk-zxd5jrgx.js} +1205 -222
  70. package/dist/cli/chunk-zxd5jrgx.js.map +44 -0
  71. package/dist/cli/index.js +78 -42
  72. package/dist/cli/index.js.map +7 -6
  73. package/dist/types/ai/changelog-components.d.ts +18 -0
  74. package/dist/types/ai/changelog-markdown.d.ts +12 -0
  75. package/dist/types/ai/openapi-components.d.ts +7 -7
  76. package/dist/types/ai/operation-details.d.ts +39 -0
  77. package/dist/types/ai/relative-links.d.ts +3 -1
  78. package/dist/types/ai/serializers.d.ts +6 -4
  79. package/dist/types/analytics/head.d.ts +4 -2
  80. package/dist/types/analytics/script.d.ts +8 -2
  81. package/dist/types/components/content/youtube.d.ts +20 -0
  82. package/dist/types/components/layout/nav-utils.d.ts +8 -0
  83. package/dist/types/components/openapi/example-panels.d.ts +33 -0
  84. package/dist/types/components/openapi/helpers.d.ts +53 -11
  85. package/dist/types/components/openapi/snippets.d.ts +7 -1
  86. package/dist/types/core/alert-diagnostics.d.ts +10 -0
  87. package/dist/types/core/builtin-tags.d.ts +16 -0
  88. package/dist/types/core/changelog-list.d.ts +48 -0
  89. package/dist/types/core/closest-match.d.ts +6 -0
  90. package/dist/types/core/code-fence-diagnostics.d.ts +18 -0
  91. package/dist/types/core/code-fences.d.ts +8 -1
  92. package/dist/types/core/config-input.d.ts +38 -6
  93. package/dist/types/core/content-assets.d.ts +16 -18
  94. package/dist/types/core/data.d.ts +6 -2
  95. package/dist/types/core/diagnostics.d.ts +14 -0
  96. package/dist/types/core/directive-diagnostics.d.ts +22 -8
  97. package/dist/types/core/former-routes.d.ts +14 -0
  98. package/dist/types/core/github.d.ts +5 -4
  99. package/dist/types/core/heading-markers.d.ts +65 -2
  100. package/dist/types/core/hidden-pages.d.ts +3 -0
  101. package/dist/types/core/includes.d.ts +23 -0
  102. package/dist/types/core/last-modified.d.ts +18 -6
  103. package/dist/types/core/links.d.ts +42 -2
  104. package/dist/types/core/load-module.d.ts +19 -4
  105. package/dist/types/core/manifest.d.ts +14 -1
  106. package/dist/types/core/markdown-mirrors.d.ts +22 -0
  107. package/dist/types/core/mcp-clients.d.ts +47 -0
  108. package/dist/types/core/mdx-elements.d.ts +32 -0
  109. package/dist/types/core/mdx-syntax.d.ts +100 -0
  110. package/dist/types/core/meta-diagnostics.d.ts +7 -0
  111. package/dist/types/core/meta.d.ts +32 -5
  112. package/dist/types/core/nav-diagnostics.d.ts +16 -2
  113. package/dist/types/core/navigation.d.ts +13 -0
  114. package/dist/types/core/ordering-prefix.d.ts +6 -0
  115. package/dist/types/core/pinned-ids.d.ts +23 -0
  116. package/dist/types/core/project-graph.d.ts +9 -1
  117. package/dist/types/core/redirect-patterns.d.ts +18 -0
  118. package/dist/types/core/relative-files.d.ts +31 -0
  119. package/dist/types/core/schema.d.ts +322 -11
  120. package/dist/types/core/sources/normalize.d.ts +101 -9
  121. package/dist/types/core/sources/types.d.ts +16 -0
  122. package/dist/types/core/static-files.d.ts +10 -0
  123. package/dist/types/core/static-host.d.ts +42 -0
  124. package/dist/types/core/svg-images.d.ts +26 -0
  125. package/dist/types/core/syntax-diagnostics.d.ts +14 -0
  126. package/dist/types/core/types.d.ts +42 -1
  127. package/dist/types/deploy/generated-files.d.ts +41 -0
  128. package/dist/types/deploy/redirects.d.ts +21 -7
  129. package/dist/types/markdown/code-title.d.ts +9 -5
  130. package/dist/types/markdown/directives.d.ts +8 -0
  131. package/dist/types/markdown/fence-language.d.ts +51 -0
  132. package/dist/types/markdown/fence-meta.d.ts +5 -0
  133. package/dist/types/markdown/github-alerts.d.ts +35 -0
  134. package/dist/types/openapi/asyncapi.d.ts +6 -5
  135. package/dist/types/openapi/checks.d.ts +10 -5
  136. package/dist/types/openapi/model.d.ts +55 -8
  137. package/dist/types/openapi/parse.d.ts +4 -1
  138. package/dist/types/ratelimit/index.d.ts +2 -0
  139. package/dist/types/ratelimit/memory.d.ts +1 -1
  140. package/dist/types/ratelimit/schema.d.ts +40 -0
  141. package/dist/types/ratelimit/unkey.d.ts +48 -0
  142. package/dist/types/sources/filesystem.d.ts +14 -4
  143. package/dist/types/sources/mdx-remote.d.ts +6 -3
  144. package/dist/types/sources/registry.d.ts +3 -3
  145. package/dist/types/theme/color.d.ts +33 -0
  146. package/dist/types/theme/palette.d.ts +122 -0
  147. package/docs/01-quickstart.mdx +1 -1
  148. package/docs/02-deployment.mdx +24 -8
  149. package/docs/04-migrating.mdx +16 -4
  150. package/docs/advanced/changelog.mdx +27 -1
  151. package/docs/advanced/skills.mdx +1 -1
  152. package/docs/cli/audit.mdx +1 -1
  153. package/docs/cli/doctor.mdx +2 -2
  154. package/docs/cli/evals.mdx +1 -1
  155. package/docs/cli/index.mdx +4 -2
  156. package/docs/cli/validate.mdx +10 -7
  157. package/docs/configuration/analytics.mdx +2 -0
  158. package/docs/configuration/customization.mdx +3 -1
  159. package/docs/configuration/index.mdx +7 -6
  160. package/docs/configuration/rate-limiting.mdx +20 -1
  161. package/docs/configuration/theming.mdx +5 -1
  162. package/docs/content/components.mdx +26 -6
  163. package/docs/content/frontmatter.mdx +1 -1
  164. package/docs/content/i18n.mdx +1 -1
  165. package/docs/content/includes.mdx +6 -2
  166. package/docs/content/index.mdx +11 -1
  167. package/docs/content/islands.mdx +2 -0
  168. package/docs/content/meta.mdx +9 -3
  169. package/docs/content/navigation.mdx +14 -6
  170. package/docs/content/sources/obsidian.mdx +1 -1
  171. package/docs/content/sources/remote-mdx.mdx +3 -1
  172. package/docs/content/syntax.mdx +76 -8
  173. package/docs/content/variables.mdx +3 -1
  174. package/docs/discoverability/agent-discovery.mdx +1 -1
  175. package/docs/discoverability/json-api.mdx +1 -1
  176. package/docs/discoverability/llms-txt.mdx +1 -1
  177. package/docs/discoverability/markdown.mdx +2 -2
  178. package/docs/discoverability/mcp.mdx +40 -8
  179. package/docs/discoverability/open-graph.mdx +1 -1
  180. package/docs/discoverability/sitemap-and-robots.mdx +1 -1
  181. package/docs/references/graphql.mdx +2 -0
  182. package/docs/references/openapi.mdx +45 -7
  183. package/package.json +4 -4
  184. package/skills/blume/SKILL.md +2 -2
  185. package/skills/blume-migrate/SKILL.md +51 -29
  186. package/skills/blume-migrate/references/docsify.md +262 -0
  187. package/skills/blume-migrate/references/docus.md +298 -0
  188. package/skills/blume-migrate/references/docusaurus.md +5 -5
  189. package/skills/blume-migrate/references/fern.md +327 -0
  190. package/skills/blume-migrate/references/fumadocs.md +1 -1
  191. package/skills/blume-migrate/references/gitbook.md +267 -0
  192. package/skills/blume-migrate/references/github-wiki.md +259 -0
  193. package/skills/blume-migrate/references/jekyll.md +253 -0
  194. package/skills/blume-migrate/references/mdbook.md +256 -0
  195. package/skills/blume-migrate/references/mintlify.md +5 -5
  196. package/skills/blume-migrate/references/mkdocs.md +236 -0
  197. package/skills/blume-migrate/references/monorepo.md +20 -8
  198. package/skills/blume-migrate/references/nextra.md +5 -5
  199. package/skills/blume-migrate/references/readme.md +257 -0
  200. package/skills/blume-migrate/references/redocly.md +198 -0
  201. package/skills/blume-migrate/references/starlight.md +3 -3
  202. package/skills/blume-migrate/references/vitepress.md +204 -0
  203. package/skills/blume-migrate/references/vuepress.md +271 -0
  204. package/skills/blume-migrate/scripts/docsify-codemod.mjs +2387 -0
  205. package/skills/blume-migrate/scripts/docus-codemod.mjs +2542 -0
  206. package/skills/blume-migrate/scripts/fern-codemod.mjs +2633 -0
  207. package/skills/blume-migrate/scripts/github-wiki-codemod.mjs +2808 -0
  208. package/skills/blume-migrate/scripts/include-excerpts.mjs +649 -0
  209. package/skills/blume-migrate/scripts/jekyll-codemod.mjs +3649 -0
  210. package/skills/blume-migrate/scripts/mintlify-codemod.mjs +17 -13
  211. package/skills/blume-migrate/scripts/mkdocs-codemod.mjs +2526 -0
  212. package/skills/blume-migrate/scripts/operation-routes.mjs +508 -0
  213. package/skills/blume-migrate/scripts/pin-heading-ids.mjs +1049 -0
  214. package/skills/blume-migrate/scripts/readme-codemod.mjs +4139 -0
  215. package/skills/blume-migrate/scripts/vitepress-codemod.mjs +1511 -0
  216. package/src/ai/changelog-components.ts +24 -0
  217. package/src/ai/changelog-markdown.ts +45 -41
  218. package/src/ai/component-markdown.ts +22 -9
  219. package/src/ai/llms.ts +36 -5
  220. package/src/ai/markdown.ts +2 -2
  221. package/src/ai/openapi-components.ts +25 -9
  222. package/src/ai/operation-details.ts +208 -0
  223. package/src/ai/relative-links.ts +48 -8
  224. package/src/ai/serializers.ts +7 -6
  225. package/src/ai/site-skill.ts +6 -2
  226. package/src/analytics/head.ts +11 -5
  227. package/src/analytics/script.ts +13 -3
  228. package/src/astro/generate.ts +47 -11
  229. package/src/astro/index.ts +1 -0
  230. package/src/astro/integration.ts +27 -1
  231. package/src/astro/mdx-source-errors.ts +46 -0
  232. package/src/astro/templates.ts +93 -189
  233. package/src/audit/checks/redirects.ts +5 -1
  234. package/src/audit/redirects.ts +36 -19
  235. package/src/audit/report.ts +22 -9
  236. package/src/audit/run.ts +12 -28
  237. package/src/audit/terms.ts +23 -0
  238. package/src/audit/url.ts +2 -2
  239. package/src/cli/build-failure.ts +256 -7
  240. package/src/cli/command-meta.ts +1 -1
  241. package/src/cli/commands/audit.ts +1 -1
  242. package/src/cli/commands/build.ts +12 -3
  243. package/src/cli/commands/check.ts +13 -2
  244. package/src/cli/commands/dev.ts +1 -1
  245. package/src/cli/commands/doctor.ts +4 -2
  246. package/src/cli/commands/init.ts +3 -3
  247. package/src/cli/commands/preview.ts +17 -1
  248. package/src/cli/commands/validate.ts +22 -10
  249. package/src/cli/prepare.ts +1 -1
  250. package/src/cli/preview-pages.ts +161 -0
  251. package/src/cli/required-secrets.ts +0 -1
  252. package/src/cli/unknown-flags.ts +1 -42
  253. package/src/components/code-copy.ts +51 -0
  254. package/src/components/code-language.ts +75 -0
  255. package/src/components/content/AccordionItem.astro +16 -1
  256. package/src/components/content/Callout.astro +11 -1
  257. package/src/components/content/Changelog.astro +189 -0
  258. package/src/components/content/CodeBlock.astro +8 -11
  259. package/src/components/content/Tabs.astro +16 -2
  260. package/src/components/content/YouTube.astro +6 -4
  261. package/src/components/content/code-block.ts +33 -0
  262. package/src/components/content/content-strings.ts +5 -1
  263. package/src/components/content/inline-markdown.ts +35 -8
  264. package/src/components/content/youtube.ts +49 -7
  265. package/src/components/layout/Analytics.astro +5 -1
  266. package/src/components/layout/NavTree.astro +8 -3
  267. package/src/components/layout/PageActions.astro +81 -23
  268. package/src/components/layout/RootLayout.astro +35 -32
  269. package/src/components/layout/SiteFooter.astro +31 -8
  270. package/src/components/layout/nav-utils.ts +14 -0
  271. package/src/components/layout/search/pagefind.ts +2 -1
  272. package/src/components/openapi/Operation.astro +4 -0
  273. package/src/components/openapi/PanelTabs.astro +9 -3
  274. package/src/components/openapi/RequestBody.astro +42 -8
  275. package/src/components/openapi/RequestPanel.astro +34 -53
  276. package/src/components/openapi/example-panels.ts +110 -0
  277. package/src/components/openapi/helpers.ts +195 -20
  278. package/src/components/openapi/operation-model.ts +63 -26
  279. package/src/components/openapi/request.ts +13 -0
  280. package/src/components/openapi/snippets.ts +14 -2
  281. package/src/core/alert-diagnostics.ts +89 -0
  282. package/src/core/builtin-tags.ts +76 -0
  283. package/src/core/changelog-list.ts +87 -0
  284. package/src/core/closest-match.ts +41 -0
  285. package/src/core/code-fence-diagnostics.ts +267 -0
  286. package/src/core/code-fences.ts +43 -7
  287. package/src/core/component-diagnostics.ts +65 -12
  288. package/src/core/config-input.ts +39 -5
  289. package/src/core/config.ts +46 -1
  290. package/src/core/content-assets.ts +64 -144
  291. package/src/core/data.ts +10 -3
  292. package/src/core/diagnostics.ts +36 -3
  293. package/src/core/directive-diagnostics.ts +265 -47
  294. package/src/core/former-routes.ts +46 -0
  295. package/src/core/git-ignored.ts +53 -0
  296. package/src/core/github.ts +5 -4
  297. package/src/core/heading-markers.ts +156 -2
  298. package/src/core/hidden-pages.ts +64 -0
  299. package/src/core/includes.ts +181 -41
  300. package/src/core/last-modified.ts +47 -10
  301. package/src/core/links.ts +438 -83
  302. package/src/core/load-module.ts +98 -9
  303. package/src/core/manifest.ts +12 -9
  304. package/src/core/markdown-mirrors.ts +52 -0
  305. package/src/core/mcp-clients.ts +87 -0
  306. package/src/core/mdx-elements.ts +153 -0
  307. package/src/core/mdx-syntax.ts +377 -0
  308. package/src/core/meta-diagnostics.ts +134 -0
  309. package/src/core/meta.ts +154 -55
  310. package/src/core/nav-diagnostics.ts +41 -4
  311. package/src/core/navigation.ts +70 -10
  312. package/src/core/ordering-prefix.ts +22 -2
  313. package/src/core/pinned-ids.ts +141 -0
  314. package/src/core/project-graph.ts +221 -29
  315. package/src/core/redirect-patterns.ts +41 -0
  316. package/src/core/relative-files.ts +145 -0
  317. package/src/core/schema.ts +110 -6
  318. package/src/core/sources/mdx-remote.ts +75 -14
  319. package/src/core/sources/normalize.ts +885 -179
  320. package/src/core/sources/notion.ts +5 -4
  321. package/src/core/sources/obsidian.ts +2 -5
  322. package/src/core/sources/types.ts +17 -0
  323. package/src/core/static-files.ts +40 -0
  324. package/src/core/static-host.ts +125 -0
  325. package/src/core/svg-images.ts +98 -0
  326. package/src/core/syntax-diagnostics.ts +491 -0
  327. package/src/core/types.ts +43 -1
  328. package/src/deploy/artifacts.ts +2 -28
  329. package/src/deploy/generated-files.ts +128 -0
  330. package/src/deploy/platforms/vercel.ts +25 -1
  331. package/src/deploy/redirects.ts +43 -16
  332. package/src/deploy/sitemap.ts +2 -1
  333. package/src/markdown/base-links.ts +87 -6
  334. package/src/markdown/code-title.ts +29 -13
  335. package/src/markdown/content-assets.ts +210 -0
  336. package/src/markdown/directives.ts +69 -5
  337. package/src/markdown/fence-language.ts +106 -0
  338. package/src/markdown/fence-meta.ts +42 -0
  339. package/src/markdown/github-alerts.ts +172 -0
  340. package/src/markdown/heading-anchors.ts +265 -56
  341. package/src/markdown/include.ts +30 -3
  342. package/src/markdown/index.ts +145 -40
  343. package/src/markdown/prompt-text.ts +95 -0
  344. package/src/markdown/relative-links.ts +37 -2
  345. package/src/markdown/route-snapshot.ts +22 -12
  346. package/src/markdown/svg-fallback.ts +51 -0
  347. package/src/markdown/title-heading.ts +134 -0
  348. package/src/migrate/migrate.ts +127 -2
  349. package/src/og/card.ts +14 -4
  350. package/src/openapi/asyncapi.ts +14 -6
  351. package/src/openapi/checks.ts +160 -15
  352. package/src/openapi/model.ts +172 -33
  353. package/src/openapi/parse.ts +13 -4
  354. package/src/openapi/render-mdx.ts +55 -9
  355. package/src/openapi/source.ts +87 -6
  356. package/src/ratelimit/index.ts +2 -0
  357. package/src/ratelimit/memory.ts +1 -1
  358. package/src/ratelimit/runtime.ts +81 -0
  359. package/src/ratelimit/schema.ts +2 -0
  360. package/src/ratelimit/unkey.ts +61 -0
  361. package/src/registry/eject.ts +0 -1
  362. package/src/registry/registry.ts +1 -1
  363. package/src/search/documents.ts +10 -2
  364. package/src/sources/filesystem.ts +28 -3
  365. package/src/sources/mdx-remote.ts +7 -15
  366. package/src/theme/color.ts +14 -0
  367. package/src/theme/entry.ts +22 -1
  368. package/src/theme/palette.ts +74 -1
  369. package/dist/cli/chunk-0pmb4tr4.js.map +0 -35
  370. package/dist/cli/chunk-0w6hs479.js.map +0 -10
  371. package/dist/cli/chunk-150jk7km.js +0 -52
  372. package/dist/cli/chunk-150jk7km.js.map +0 -10
  373. package/dist/cli/chunk-36bxs9c7.js.map +0 -10
  374. package/dist/cli/chunk-53jqw8z0.js +0 -89
  375. package/dist/cli/chunk-53jqw8z0.js.map +0 -10
  376. package/dist/cli/chunk-60hz265r.js.map +0 -10
  377. package/dist/cli/chunk-desvm72z.js.map +0 -14
  378. package/dist/cli/chunk-dpy8qdjf.js.map +0 -17
  379. package/dist/cli/chunk-es8h0v3j.js +0 -441
  380. package/dist/cli/chunk-es8h0v3j.js.map +0 -11
  381. package/dist/cli/chunk-kdpzw38a.js.map +0 -11
  382. package/dist/cli/chunk-nbyvgnnm.js.map +0 -36
  383. package/dist/cli/chunk-s0bdnc7v.js.map +0 -10
  384. package/dist/cli/chunk-twy7psdz.js.map +0 -10
  385. package/dist/cli/chunk-ydp3065p.js +0 -64
  386. package/dist/cli/chunk-ydp3065p.js.map +0 -10
  387. /package/dist/cli/{chunk-y4msrwm9.js.map → chunk-080mfch6.js.map} +0 -0
  388. /package/dist/cli/{chunk-9qzgg6mj.js.map → chunk-34wap3ed.js.map} +0 -0
  389. /package/dist/cli/{chunk-1f882900.js.map → chunk-c5bjxq8v.js.map} +0 -0
  390. /package/dist/cli/{chunk-bxwhtvw8.js.map → chunk-f260jdrn.js.map} +0 -0
  391. /package/dist/cli/{chunk-74wfhv79.js.map → chunk-fnxgtjeq.js.map} +0 -0
  392. /package/dist/cli/{chunk-dhwtqnnd.js.map → chunk-gxhcf2hs.js.map} +0 -0
  393. /package/dist/cli/{chunk-tfycddbt.js.map → chunk-h0qwdbem.js.map} +0 -0
  394. /package/dist/cli/{chunk-j1x92mx9.js.map → chunk-j4nfgn2j.js.map} +0 -0
  395. /package/dist/cli/{chunk-ave1wcbr.js.map → chunk-qcyxkj44.js.map} +0 -0
  396. /package/dist/cli/{chunk-58bt3hag.js.map → chunk-x7bh6d9j.js.map} +0 -0
  397. /package/dist/cli/{chunk-hvcxng5f.js.map → chunk-ydqzkhjn.js.map} +0 -0
@@ -4,11 +4,11 @@ import {
4
4
  discoverIslands,
5
5
  discoverExamples,
6
6
  missingDependencyDiagnostic
7
- } from "./chunk-ckrcm08h.js";
7
+ } from "./chunk-rtvgmg2j.js";
8
8
  import {
9
9
  discoverPages,
10
10
  navTargetRoutes
11
- } from "./chunk-124fvmzq.js";
11
+ } from "./chunk-r5nm9w0c.js";
12
12
  import {
13
13
  packageRoot,
14
14
  commandMeta,
@@ -23,20 +23,24 @@ import {
23
23
  import {
24
24
  ComponentOverridesError,
25
25
  analyzeComponentOverrides
26
- } from "./chunk-j1x92mx9.js";
26
+ } from "./chunk-j4nfgn2j.js";
27
27
  import {
28
28
  validateNavTargets,
29
29
  scanProject
30
- } from "./chunk-0pmb4tr4.js";
30
+ } from "./chunk-zxd5jrgx.js";
31
31
  import"./chunk-zccbjcj0.js";
32
32
  import"./chunk-jq5n4avg.js";
33
33
  import {
34
34
  unregisteredSnapshotDiagnostics
35
- } from "./chunk-5cmts6dv.js";
35
+ } from "./chunk-kmswjxj9.js";
36
+ import {
37
+ servedFiles
38
+ } from "./chunk-487b95qy.js";
36
39
  import {
37
40
  serverFeatures,
38
41
  checkRequiredSecrets
39
- } from "./chunk-ms9z66nz.js";
42
+ } from "./chunk-gwy55cx3.js";
43
+ import"./chunk-q1wwrxzw.js";
40
44
 
41
45
  // src/cli/commands/doctor.ts
42
46
  import { readFileSync } from "node:fs";
@@ -44,7 +48,7 @@ import { readFile } from "node:fs/promises";
44
48
  import { defineCommand } from "citty";
45
49
  import { join } from "pathe";
46
50
  import { satisfies } from "semver";
47
- var FALLBACK_NODE_RANGE = ">=22.12.0";
51
+ var FALLBACK_NODE_RANGE = ">=22.19.0";
48
52
  var componentsDiagnostics = async (componentsFile) => {
49
53
  if (!componentsFile) {
50
54
  return { issues: [], mdx: [] };
@@ -110,7 +114,7 @@ var doctorCommand = defineCommand({
110
114
  mode: "build"
111
115
  });
112
116
  const userPages = project.context.pagesRoot ? await discoverPages(project.context.pagesRoot) : [];
113
- diagnostics.push(...project.diagnostics, ...unregisteredSnapshotDiagnostics(project), ...validateNavTargets(project.graph.navigation, navTargetRoutes(project, userPages)));
117
+ diagnostics.push(...project.diagnostics, ...unregisteredSnapshotDiagnostics(project), ...validateNavTargets(project.graph.navigation, navTargetRoutes(project, userPages), servedFiles(project)));
114
118
  const { config } = project;
115
119
  const { islands } = await discoverIslands(root);
116
120
  const dependencies = await missingDependencyDiagnostic(config, root, "error", islands.map((island) => island.framework));
@@ -166,5 +170,5 @@ export {
166
170
  doctorCommand
167
171
  };
168
172
 
169
- //# debugId=A6107CD821E0AA4B64756E2164756E21
170
- //# sourceMappingURL=chunk-twy7psdz.js.map
173
+ //# debugId=A4A339755430C21A64756E2164756E21
174
+ //# sourceMappingURL=chunk-hn3g2b89.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/cli/commands/doctor.ts"],
4
+ "sourcesContent": [
5
+ "import { readFileSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\n\nimport { defineCommand } from \"citty\";\nimport { join } from \"pathe\";\nimport { satisfies } from \"semver\";\n\nimport { discoverExamples } from \"../../astro/examples.ts\";\nimport { discoverIslands } from \"../../astro/islands.ts\";\nimport { discoverPages, navTargetRoutes } from \"../../astro/pages.ts\";\nimport { missingDependencyDiagnostic } from \"../../astro/runtime-deps.ts\";\nimport { missingExampleDiagnostics } from \"../../core/component-diagnostics.ts\";\nimport {\n analyzeComponentOverrides,\n ComponentOverridesError,\n} from \"../../core/component-overrides.ts\";\nimport { BlumeError } from \"../../core/diagnostics.ts\";\nimport { validateNavTargets } from \"../../core/nav-diagnostics.ts\";\nimport { packageRoot } from \"../../core/package-root.ts\";\nimport { scanProject } from \"../../core/project-graph.ts\";\nimport type { ResolvedConfig } from \"../../core/schema.ts\";\nimport { serverFeatures } from \"../../core/server-features.ts\";\nimport type { Diagnostic } from \"../../core/types.ts\";\nimport { unregisteredSnapshotDiagnostics } from \"../../core/version-cut.ts\";\nimport { servedFiles } from \"../../deploy/generated-files.ts\";\nimport { commandMeta } from \"../command-meta.ts\";\nimport { loadEnvFiles } from \"../env.ts\";\nimport { reportInternalError } from \"../internal-error.ts\";\nimport {\n flushStdout,\n logger,\n reportDiagnostics,\n reportDiagnosticsJson,\n} from \"../log.ts\";\nimport { checkRequiredSecrets } from \"../required-secrets.ts\";\n\nconst FALLBACK_NODE_RANGE = \">=22.19.0\";\n\n/**\n * Plan `components.ts` the way `blume dev`/`build` do, reporting each override\n * that can't be planned — a non-static form, or an import of a file that\n * doesn't exist — with its own line. The scan alone never reads the file, so\n * without this doctor would pass a project whose build fails. Also returns\n * the MDX tags the file overrides.\n */\nconst componentsDiagnostics = async (\n componentsFile: string | null\n): Promise<{ issues: Diagnostic[]; mdx: string[] }> => {\n if (!componentsFile) {\n return { issues: [], mdx: [] };\n }\n try {\n const { mdx } = analyzeComponentOverrides(\n await readFile(componentsFile, \"utf-8\"),\n componentsFile\n );\n return { issues: [], mdx: mdx.map((entry) => entry.key) };\n } catch (error) {\n if (error instanceof ComponentOverridesError) {\n return { issues: error.issues, mdx: [] };\n }\n throw error;\n }\n};\n\n/** The supported Node range, read from the package's own `engines` field so\n * doctor can never drift from what the package actually declares. */\nconst supportedNodeRange = (): string => {\n try {\n // SAFETY: this parses blume's own package.json; the optional fields cover\n // an `engines` block going missing, and a bad read falls to the catch.\n const pkg = JSON.parse(\n readFileSync(join(packageRoot(), \"package.json\"), \"utf-8\")\n ) as { engines?: { node?: string } };\n return pkg.engines?.node || FALLBACK_NODE_RANGE;\n } catch {\n return FALLBACK_NODE_RANGE;\n }\n};\n\n/** The adapters a project runs, one line per kind, for the doctor summary. */\nconst integrationSummary = (config: ResolvedConfig): string[] => {\n const { assistant } = config.ai;\n let assistantSummary = \"off\";\n if (assistant?.enabled) {\n assistantSummary = assistant.endpoint\n ? \"external endpoint\"\n : assistant.provider.kind;\n }\n return [\n `References: ${config.reference.map((adapter) => adapter.kind).join(\", \") || \"none\"}`,\n `Analytics: ${config.analytics.map((adapter) => adapter.kind).join(\", \") || \"none\"}`,\n `Consent: ${config.consent?.kind ?? \"none\"}`,\n `Rate limiting: ${config.rateLimit?.kind ?? \"off\"}`,\n `Sources: ${config.content.sources.map((source) => source.kind).join(\", \")}`,\n `Assistant: ${assistantSummary}`,\n ];\n};\n\nexport const doctorCommand = defineCommand({\n args: {\n json: {\n description: \"Emit diagnostics as JSON on stdout (for CI/editors).\",\n type: \"boolean\",\n },\n },\n meta: commandMeta.doctor,\n async run({ args }) {\n const root = process.cwd();\n const diagnostics: Diagnostic[] = [];\n\n const nodeRange = supportedNodeRange();\n if (!satisfies(process.versions.node, nodeRange)) {\n diagnostics.push({\n code: \"BLUME_NODE_VERSION\",\n message: `Node ${process.versions.node} is outside the supported range (${nodeRange}).`,\n severity: \"warning\",\n });\n }\n\n // Read `.env` files first, as `blume dev`/`build` do: remote sources read\n // their tokens during the scan, and the secrets check below reads them too.\n loadEnvFiles(root);\n\n try {\n const project = await scanProject(root, {\n // A missing secret fails at the first request. Checked before the\n // sources fetch, so it's still reported when one of them fails the\n // scan for want of it.\n beforeSources: (config) => {\n diagnostics.push(...checkRequiredSecrets(config));\n },\n mode: \"build\",\n });\n // Tabs, selector items, and featured links can point at custom pages\n // and generated routes too, so they're checked against every route\n // the site serves, as `blume dev`/`build` check them.\n const userPages = project.context.pagesRoot\n ? await discoverPages(project.context.pagesRoot)\n : [];\n diagnostics.push(\n ...project.diagnostics,\n ...unregisteredSnapshotDiagnostics(project),\n ...validateNavTargets(\n project.graph.navigation,\n navTargetRoutes(project, userPages),\n servedFiles(project)\n )\n );\n\n const { config } = project;\n // The packages a build would need: an adapter's missing SDK fails the\n // build.\n const { islands } = await discoverIslands(root);\n const dependencies = await missingDependencyDiagnostic(\n config,\n root,\n \"error\",\n islands.map((island) => island.framework)\n );\n if (dependencies) {\n diagnostics.push(dependencies);\n }\n const overrides = await componentsDiagnostics(\n project.context.componentsFile\n );\n diagnostics.push(\n ...overrides.issues,\n // A `<Component path>` naming no example renders a \"No example\n // found\" box, which dev and build warn about too.\n ...missingExampleDiagnostics(\n project.graph.pages,\n await discoverExamples(root, config.examples.source),\n root,\n new Set([...islands.map((island) => island.name), ...overrides.mdx])\n )\n );\n const features = serverFeatures(config);\n if (\n features.length > 0 &&\n config.deployment.options.output === \"static\"\n ) {\n // A host adapter already names the target, so only its\n // `output: \"static\"` stands in the way; otherwise name one.\n const { kind } = config.deployment;\n diagnostics.push({\n code: \"BLUME_SERVER_FEATURE_REQUIRED\",\n message: `${features.join(\", \")} ${features.length === 1 ? \"requires\" : \"require\"} server output.`,\n severity: \"error\",\n suggestion:\n kind === \"static\"\n ? 'Set deployment to a host adapter from \"blume/deploy\" (e.g. `deployment: vercel()`).'\n : `Drop \\`output: \"static\"\\` from \\`deployment: ${kind}()\\` to build for the server.`,\n });\n }\n\n if (!args.json) {\n logger.info(`Pages: ${project.graph.pages.length}`);\n logger.info(`Output: ${config.deployment.options.output}`);\n logger.info(`Adapter: ${config.deployment.kind}`);\n logger.info(`Search: ${config.search.provider.kind}`);\n for (const line of integrationSummary(config)) {\n logger.info(line);\n }\n }\n } catch (error) {\n if (error instanceof BlumeError) {\n diagnostics.push(error.diagnostic);\n } else {\n reportInternalError(error);\n process.exit(1);\n }\n }\n\n if (args.json) {\n // Drain stdout before exiting non-zero: `process.exit` would otherwise\n // truncate the JSON payload mid-write when stdout is a pipe — exactly how\n // `--json` is consumed in CI/editors.\n if (reportDiagnosticsJson(diagnostics, root)) {\n await flushStdout();\n process.exit(1);\n }\n return;\n }\n\n const hadErrors = reportDiagnostics(diagnostics, root);\n if (diagnostics.length === 0) {\n logger.success(\"No problems found.\");\n }\n if (hadErrors) {\n // Set the code and return rather than `process.exit`, which doesn't wait\n // for a piped stderr: a long diagnostic list would be cut off.\n process.exitCode = 1;\n }\n },\n});\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "A4A339755430C21A64756E2164756E21",
9
+ "names": []
10
+ }
@@ -390,4 +390,4 @@ var analyzeComponentOverrides = (source, filePath) => {
390
390
  export { emptyComponentOverrides, ComponentOverridesError, analyzeComponentOverrides };
391
391
 
392
392
  //# debugId=59653B23465A56F364756E2164756E21
393
- //# sourceMappingURL=chunk-j1x92mx9.js.map
393
+ //# sourceMappingURL=chunk-j4nfgn2j.js.map
@@ -3,6 +3,7 @@ import {
3
3
  buildHomeLinkHeader,
4
4
  resolveDocsCollection,
5
5
  TOC_HIDDEN_KEY,
6
+ TOC_TEXT_KEY,
6
7
  deployPassthrough,
7
8
  RATE_LIMIT_BINDING,
8
9
  fontLocaleCodes,
@@ -12,15 +13,19 @@ import {
12
13
  hasVariables,
13
14
  SVG_ASSET_HEADERS,
14
15
  applyBaseToAstroRedirects,
16
+ isPageIndexFile,
15
17
  withMirrorRedirects,
16
18
  distDir,
17
19
  adapterRoot,
18
20
  deployPlatform
19
- } from "./chunk-124fvmzq.js";
21
+ } from "./chunk-r5nm9w0c.js";
20
22
  import {
21
23
  trimChar,
22
24
  normalizeBasePath
23
25
  } from "./chunk-zccbjcj0.js";
26
+ import {
27
+ getBlumeVersion
28
+ } from "./index.js";
24
29
  import {
25
30
  BLUME_IGNORE_DIRS
26
31
  } from "./chunk-kwrg63tm.js";
@@ -232,6 +237,10 @@ var CONSENT_CLIENT_MODULES = new Map([
232
237
  // src/markdown/api-rail.ts
233
238
  var API_RAIL_KEY = "blumeApiRail";
234
239
 
240
+ // src/markdown/title-heading.ts
241
+ var TITLE_ID_KEY = "blumeTitleId";
242
+ var seen = new WeakSet;
243
+
235
244
  // src/markdown/views.ts
236
245
  var VIEWS_KEY = "blumeViews";
237
246
 
@@ -496,7 +505,8 @@ var astroConfigTemplate = (options) => {
496
505
  })},` : "";
497
506
  const redirectPages = new Set(contentRoutes);
498
507
  const basedRedirects = withMirrorRedirects(applyBaseToAstroRedirects(config.redirects, config.basePath, deployment.options.base ?? "", redirectPages), redirectPages, { from: "", to: normalizeBasePath(deployment.options.base) });
499
- const exactRedirects = basedRedirects.filter((redirect) => !isPatternPath(redirect.from));
508
+ const staticOutput = deployment.options.output === "static";
509
+ const exactRedirects = basedRedirects.filter((redirect) => !(isPatternPath(redirect.from) || staticOutput && isPageIndexFile(redirect.from, redirectPages)));
500
510
  const redirectsOption = exactRedirects.length > 0 ? `
501
511
  redirects: ${JSON.stringify(Object.fromEntries(exactRedirects.map((redirect) => [
502
512
  redirect.from,
@@ -533,6 +543,7 @@ var astroConfigTemplate = (options) => {
533
543
  const blumeImports = [
534
544
  "blumeIntegration",
535
545
  "includeHmrPlugin",
546
+ "mdxSourceErrorsPlugin",
536
547
  "prerenderDepsPlugin",
537
548
  ...runtimeModuleImports,
538
549
  ...adapterOption.includes("withAdapterRoot") ? ["withAdapterRoot"] : [],
@@ -607,10 +618,10 @@ ${userConfigSetup}export default defineConfig({
607
618
  devToolbar: { enabled: false },
608
619
  // One canonical URL per page: canonicals, the sitemap, and hreflang all use
609
620
  // the slashless form, so the slashed spelling is not a second address. Astro
610
- // applies this itself — its dev server answers a slashed URL with a 404 that
611
- // names the setting, an on-demand route redirects — and the Vercel adapter
612
- // turns it into the platform's 308 route, so the Build Output config needs
613
- // no hand-spliced redirect (see deploy/vercel-negotiation.ts). Static hosts
621
+ // applies this itself — an on-demand route redirects, and the integration
622
+ // has the dev server redirect too, ahead of Astro's own 404 — and the Vercel
623
+ // adapter turns it into the platform's 308 route, so the Build Output config
624
+ // needs no hand-spliced redirect (see deploy/vercel-negotiation.ts). Static hosts
614
625
  // serve the \`index.html\` directory layout as they always did.
615
626
  trailingSlash: "never",
616
627
  // The layouts render Astro's <ClientRouter />, and its in-place swaps read
@@ -625,7 +636,7 @@ ${userConfigSetup}export default defineConfig({
625
636
  // the overlap only adds memory.
626
637
  build: { concurrency: Math.min(8, availableParallelism()) },
627
638
  vite: {${viteCacheOption}
628
- plugins: [${runtimeModulesPluginEntry}${variablesPluginEntry}tailwindcss(), includeHmrPlugin(${configPath(`${context.outDir}/src/generated/includes.json`, ejected)}), prerenderDepsPlugin()],
639
+ plugins: [${runtimeModulesPluginEntry}${variablesPluginEntry}tailwindcss(), includeHmrPlugin(${configPath(`${context.outDir}/src/generated/includes.json`, ejected)}), mdxSourceErrorsPlugin(), prerenderDepsPlugin()],
629
640
  build: {${features.mermaid ? MERMAID_CHUNK_LIMIT : ""}
630
641
  rolldownOptions: {
631
642
  ${ROLLDOWN_ON_LOG},
@@ -704,6 +715,8 @@ var runtimeDirWithin = (base, outDir) => {
704
715
  return rel && !rel.startsWith("..") && !isAbsolute2(rel) ? rel : null;
705
716
  };
706
717
  var astroGlobBase = (base) => isAbsolute2(base) ? pathToFileURL(base).href : base;
718
+ var GLOB_SYNTAX = /[!()*+?@[\\\]{|}]/gu;
719
+ var escapeGlob = (path) => path.replaceAll(GLOB_SYNTAX, String.raw`\$&`);
707
720
  var contentConfigTemplate = (options) => {
708
721
  const { context, config } = options;
709
722
  const stagedBase = options.stagedBase ?? stagedContentDir(context.outDir);
@@ -718,7 +731,11 @@ var contentConfigTemplate = (options) => {
718
731
  ...includeGlobs,
719
732
  ...(excludeGlobs ?? []).map((pattern) => `!${pattern}`),
720
733
  ...BLUME_IGNORE_DIRS.flatMap((dir) => dir === ".blume" ? [] : [`!**/${dir}/**`]),
721
- ...outDirIgnore
734
+ ...outDirIgnore,
735
+ ...(options.unparsable ?? []).flatMap((file) => {
736
+ const rel = relative2(collectionBase, file);
737
+ return rel.startsWith("..") || isAbsolute2(rel) ? [] : [`!${escapeGlob(rel)}`];
738
+ })
722
739
  ] : [];
723
740
  const stagedBlock = options.staged ? `
724
741
  const staged = defineCollection({
@@ -743,6 +760,10 @@ import { pageCollectionSchema } from "blume/core/schema.ts";
743
760
  // pageCollectionSchema is the scan's page front-matter schema, so entry.data
744
761
  // is typed and normalized the same way; it passes custom keys through and
745
762
  // falls back to defaults for a page the scan already dropped as invalid.
763
+ //
764
+ // Astro's content store re-parses an entry only when its file or this config
765
+ // changes, so naming the Blume version (${getBlumeVersion()}) here re-parses
766
+ // every entry after an upgrade: none keeps what an older schema produced.
746
767
  const docs = defineCollection({
747
768
  loader: withIncludeRefresh(glob({
748
769
  pattern: ${JSON.stringify(docsPattern)},
@@ -777,7 +798,7 @@ var rateLimitTemplate = (adapter, scope) => {
777
798
  'import { createLimiter, rateLimited } from "blume/ratelimit/runtime.ts";'
778
799
  ];
779
800
  let runtime = "";
780
- if (adapter.kind === "upstash") {
801
+ if (adapter.requiredSecrets.length > 0) {
781
802
  imports.push('import { getSecret } from "astro:env/server";');
782
803
  runtime = ", { secret: getSecret }";
783
804
  } else if (adapter.kind === "cloudflare") {
@@ -1214,11 +1235,25 @@ const TYPES: Record<string, string> = {
1214
1235
  ".webp": "image/webp",
1215
1236
  };
1216
1237
 
1238
+ // The other files a page's links name beside it, typed so the dev server
1239
+ // opens them the way a static host would. Anything else downloads.
1240
+ const FILE_TYPES: Record<string, string> = {
1241
+ ".csv": "text/csv; charset=utf-8",
1242
+ ".json": "application/json",
1243
+ ".mp3": "audio/mpeg",
1244
+ ".pdf": "application/pdf",
1245
+ ".txt": "text/plain; charset=utf-8",
1246
+ ".wav": "audio/wav",
1247
+ ".zip": "application/zip",
1248
+ };
1249
+
1217
1250
  const extensionOf = (path: string): string =>
1218
1251
  path.slice(path.lastIndexOf(".")).toLowerCase();
1219
1252
 
1220
1253
  const contentType = (path: string): string =>
1221
- TYPES[extensionOf(path)] ?? "application/octet-stream";
1254
+ TYPES[extensionOf(path)] ??
1255
+ FILE_TYPES[extensionOf(path)] ??
1256
+ "application/octet-stream";
1222
1257
 
1223
1258
  // A source downloads only images and videos; anything else in the staged
1224
1259
  // directory (a page an older build saved under its URL's extension) is never
@@ -1567,6 +1602,7 @@ import Badge from "blume/components/content/Badge.astro";
1567
1602
  import Callout from "blume/components/content/Callout.astro";
1568
1603
  import Card from "blume/components/content/Card.astro";
1569
1604
  import CardGroup from "blume/components/content/CardGroup.astro";
1605
+ import Changelog from "blume/components/content/Changelog.astro";
1570
1606
  import CodeBlock from "blume/components/content/CodeBlock.astro";
1571
1607
  import CodeGroup from "blume/components/content/CodeGroup.astro";
1572
1608
  import ColorRoot from "blume/components/content/Color.astro";
@@ -1620,6 +1656,7 @@ ${mathImport}import { mdxComponents as userMdx, layoutOverrides } from "../gener
1620
1656
  Callout,
1621
1657
  Card,
1622
1658
  CardGroup,
1659
+ Changelog,
1623
1660
  CodeBlock,
1624
1661
  CodeGroup,
1625
1662
  Color,
@@ -1723,10 +1760,25 @@ const views = Array.isArray(viewsRaw)
1723
1760
  : [];
1724
1761
  const tocHiddenRaw = remarkPluginFrontmatter?.${TOC_HIDDEN_KEY};
1725
1762
  const tocHidden = new Set(Array.isArray(tocHiddenRaw) ? tocHiddenRaw : []);
1726
- const headings =
1763
+ // A heading holding a \`<Badge>\` lists without the badge's text, which the
1764
+ // heading plugin reports by slug the same way.
1765
+ const tocTextRaw = remarkPluginFrontmatter?.${TOC_TEXT_KEY};
1766
+ const tocText = tocTextRaw && typeof tocTextRaw === "object" ? tocTextRaw : {};
1767
+ const headings = (
1727
1768
  tocHidden.size > 0
1728
1769
  ? allHeadings.filter((heading) => !tocHidden.has(heading.slug))
1729
- : allHeadings;
1770
+ : allHeadings
1771
+ ).map((heading) =>
1772
+ typeof tocText[heading.slug] === "string"
1773
+ ? { ...heading, text: tocText[heading.slug] }
1774
+ : heading
1775
+ );
1776
+ // An untitled page's opening \`# Heading\` is its title, so the title-heading
1777
+ // plugin drops it from the body and reports its id here: the title \`<h1>\`
1778
+ // below takes it, so links to the heading's anchor still land (see
1779
+ // markdown/title-heading.ts).
1780
+ const titleIdRaw = remarkPluginFrontmatter?.${TITLE_ID_KEY};
1781
+ const titleId = typeof titleIdRaw === "string" ? titleIdRaw : undefined;
1730
1782
  const frontmatter = entry.data;
1731
1783
 
1732
1784
  const seo = frontmatter.seo;
@@ -2015,7 +2067,7 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
2015
2067
  noindex={effectiveNoindex}
2016
2068
  structuredDataEnabled={data.config.structuredData}
2017
2069
  >
2018
- {pageChrome && <h1>{title}</h1>}
2070
+ {pageChrome && <h1 id={titleId}>{title}</h1>}
2019
2071
  {pageChrome && frontmatter.description && <p class="text-lg text-muted-foreground">{frontmatter.description}</p>}
2020
2072
  {narration && (
2021
2073
  <NarrationPlayer
@@ -2036,32 +2088,17 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
2036
2088
  var changelogIndexTemplate = (options) => {
2037
2089
  const clientData = options.needsReact ? `
2038
2090
  clientData={{ config: data.config, navigation: data.navigation, page: { route: "/changelog", title: pageTitle } }}` : "";
2039
- const stagedSpread = options.staged ? `
2040
- ...(await getCollection("staged")),` : "";
2041
2091
  return `---
2042
2092
  // Generated by Blume. Do not edit.
2043
- import { getCollection } from "astro:content";
2044
2093
  import RootLayout from "blume/components/layout/RootLayout.astro";
2094
+ import Changelog from "blume/components/content/Changelog.astro";
2045
2095
  import { withMountedBase } from "blume/components/islands/base-path.ts";
2046
2096
  import { resolveSlot } from "blume/components/layout/overrides.ts";
2047
- import { resolveDateFormatOptions } from "blume/core/date-format.ts";
2048
2097
  import { layoutOverrides } from "../generated/components.ts";
2049
2098
  import data from "blume:data";
2050
2099
 
2051
2100
  export const prerender = true;
2052
2101
 
2053
- const entryDate = (entry: {
2054
- data: { date?: string | null; changelog?: { date?: string | null } | null };
2055
- }) => entry.data.date ?? entry.data.changelog?.date ?? null;
2056
-
2057
- const parseDate = (value: string | null | undefined) => {
2058
- if (!value) {
2059
- return null;
2060
- }
2061
- const date = new Date(value);
2062
- return Number.isNaN(date.getTime()) ? null : date;
2063
- };
2064
-
2065
2102
  // The changelog is an unlocalized route, so its chrome renders in the default
2066
2103
  // locale's dictionary and direction (\`data.ui\` is the default locale's resolved
2067
2104
  // dictionary), mirroring the catch-all's locale wiring.
@@ -2072,109 +2109,6 @@ const localeMeta = i18n
2072
2109
  const dir = localeMeta?.dir ?? "ltr";
2073
2110
  const htmlLang = i18n ? i18n.defaultLocale : "en";
2074
2111
 
2075
- // Formatted in the same locale as the chrome, and with the configured
2076
- // \`dateFormat\` (UTC by default), to match the per-page "last updated" stamp.
2077
- // The year heads each group, so a row shows the rest of the date: a preset
2078
- // style keeps its month wording, a component format simply drops the year.
2079
- const dateFormatOptions = resolveDateFormatOptions(data.config.dateFormat);
2080
- const { dateStyle, year: _year, ...dateComponents } = dateFormatOptions;
2081
- const rowDateFormat: Intl.DateTimeFormatOptions = dateStyle
2082
- ? {
2083
- ...dateComponents,
2084
- day: "numeric",
2085
- month: dateStyle === "medium" ? "short" : "long",
2086
- }
2087
- : dateComponents;
2088
- const formatRowDate = (date: Date) =>
2089
- new Intl.DateTimeFormat(htmlLang, rowDateFormat).format(date);
2090
- const formatYear = (date: Date) =>
2091
- new Intl.DateTimeFormat(htmlLang, {
2092
- timeZone: dateFormatOptions.timeZone,
2093
- year: "numeric",
2094
- }).format(date);
2095
-
2096
- const slugify = (text: string) =>
2097
- text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") ||
2098
- "update";
2099
-
2100
- // Map each entry to its own generated page so the row can link to it. The
2101
- // collection entry id matches the route manifest's \`entryId\` — and under
2102
- // i18n every locale serves a page for it (its translations plus fallback
2103
- // copies of an untranslated one), all sharing that id, so a map over every
2104
- // route would keep whichever locale came last: a Portuguese permalink on an
2105
- // unlocalized index. Only the default locale's routes are kept, and an entry
2106
- // is listed only when it has one, so a translated changelog file (a distinct
2107
- // entry that lives under its own locale) does not add a second row for the
2108
- // same release.
2109
- const defaultLocale = i18n ? i18n.defaultLocale : null;
2110
- const routeByEntry = new Map<string, string>();
2111
- for (const route of data.routes) {
2112
- if (defaultLocale === null || route.locale === defaultLocale) {
2113
- routeByEntry.set(route.entryId, route.path);
2114
- }
2115
- }
2116
-
2117
- const changelogEntries = [
2118
- ...(await getCollection("docs")),${stagedSpread}
2119
- ]
2120
- .filter(
2121
- (entry) =>
2122
- entry.data.type === "changelog" &&
2123
- !entry.data.draft &&
2124
- !entry.data.sidebar?.hidden &&
2125
- (defaultLocale === null || routeByEntry.has(entry.id))
2126
- )
2127
- .toSorted(
2128
- (a, b) =>
2129
- (parseDate(entryDate(b))?.getTime() ?? 0) -
2130
- (parseDate(entryDate(a))?.getTime() ?? 0)
2131
- );
2132
-
2133
- const items = changelogEntries.map((entry) => {
2134
- const label =
2135
- entry.data.title ??
2136
- (entry.data.changelog?.version
2137
- ? "v" + entry.data.changelog.version
2138
- : "Update");
2139
- const date = parseDate(entryDate(entry));
2140
- const route = routeByEntry.get(entry.id);
2141
- return {
2142
- date: date ? formatRowDate(date) : null,
2143
- dateTime: date ? date.toISOString().slice(0, 10) : null,
2144
- href: route ? withMountedBase(route) : null,
2145
- id: slugify(label),
2146
- label,
2147
- tag: entry.data.changelog?.category ?? null,
2148
- year: date ? formatYear(date) : null,
2149
- };
2150
- });
2151
-
2152
- // Repeated labels slug to the same id (e.g. two entries with neither a title
2153
- // nor a version both falling back to "update"); suffix the later ones -2, -3,
2154
- // ... so every row keeps its own hash anchor. The first keeps the plain slug.
2155
- const seenIds = new Set();
2156
- for (const item of items) {
2157
- let uniqueId = item.id;
2158
- for (let n = 2; seenIds.has(uniqueId); n += 1) {
2159
- uniqueId = item.id + "-" + n;
2160
- }
2161
- seenIds.add(uniqueId);
2162
- item.id = uniqueId;
2163
- }
2164
-
2165
- // Consecutive releases from the same year share a group, so the list reads as
2166
- // a year rail beside the rows; undated entries (sorted last) form a final
2167
- // group with no year label.
2168
- const groups: { items: typeof items; year: string | null }[] = [];
2169
- for (const item of items) {
2170
- const last = groups[groups.length - 1];
2171
- if (last && last.year === item.year) {
2172
- last.items.push(item);
2173
- } else {
2174
- groups.push({ items: [item], year: item.year });
2175
- }
2176
- }
2177
-
2178
2112
  const base = data.config.site ? data.config.site.replace(/\\/$/, "") : null;
2179
2113
  // The canonical URL carries the deployment base (the page is served under it),
2180
2114
  // matching how the catch-all canonicalizes via \`withMountedBase(route)\`.
@@ -2187,15 +2121,16 @@ const canonical = base ? base + basedRoute : null;
2187
2121
  const ogPath = data.config.og.enabled ? withMountedBase("/og/changelog.png") : null;
2188
2122
  const ogImage = ogPath && base ? base + ogPath : ogPath;
2189
2123
 
2190
- // The page chrome (h1, title, description, empty state) comes from the
2191
- // translatable \`changelog\` group, which carries the \`changelog\` config's title and
2124
+ // The page chrome (h1, title, description) comes from the translatable
2125
+ // \`changelog\` group, which carries the \`changelog\` config's title and
2192
2126
  // description when it sets them; optional chaining tolerates a
2193
- // not-yet-regenerated data snapshot from before these keys existed.
2127
+ // not-yet-regenerated data snapshot from before these keys existed. The list
2128
+ // itself is \`<Changelog />\`, the same component an authored page can place to
2129
+ // put prose above it.
2194
2130
  const changelogTitle = data.ui.changelog?.title ?? "Changelog";
2195
2131
  const changelogDescription =
2196
2132
  data.ui.changelog?.description ??
2197
2133
  "Product updates, new features, and fixes from every release.";
2198
- const changelogEmpty = data.ui.changelog?.empty ?? "No changelog entries yet.";
2199
2134
  // The layout suffixes "- {site title}" itself, so the page title is just the
2200
2135
  // changelog's own name — prefixing the site title too would double it
2201
2136
  // ("Acme Changelog - Acme").
@@ -2246,51 +2181,7 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
2246
2181
  >
2247
2182
  <h1>{changelogTitle}</h1>
2248
2183
  <p class="text-lg text-muted-foreground">{changelogDescription}</p>
2249
- {
2250
- items.length === 0 ? (
2251
- <p>{changelogEmpty}</p>
2252
- ) : (
2253
- <div class="not-prose mt-10 divide-y divide-border border-border border-y">
2254
- {groups.map((group) => (
2255
- <section
2256
- aria-label={group.year ?? undefined}
2257
- class="grid md:grid-cols-[6rem_minmax(0,1fr)] md:gap-x-8"
2258
- >
2259
- <h2 class="mt-0! pt-3! font-medium! text-muted-foreground text-sm! leading-5! tabular-nums max-md:pb-1">
2260
- {group.year}
2261
- </h2>
2262
- <ul class="m-0! list-none divide-y divide-border p-0!">
2263
- {group.items.map((item) => (
2264
- <li class="m-0! p-0!" id={item.id}>
2265
- <a
2266
- class="group/release flex items-baseline gap-4 py-3 no-underline! hover:no-underline!"
2267
- href={item.href ?? "#" + item.id}
2268
- >
2269
- <span class="min-w-0 flex-1 font-medium text-foreground text-sm transition-colors group-hover/release:text-accent">
2270
- {item.label}
2271
- </span>
2272
- {item.tag && (
2273
- <span class="shrink-0 rounded-full bg-muted px-2 py-0.5 font-medium text-[0.65rem] text-muted-foreground">
2274
- {item.tag}
2275
- </span>
2276
- )}
2277
- {item.date && (
2278
- <time
2279
- class="shrink-0 font-mono text-muted-foreground text-xs tabular-nums"
2280
- datetime={item.dateTime}
2281
- >
2282
- {item.date}
2283
- </time>
2284
- )}
2285
- </a>
2286
- </li>
2287
- ))}
2288
- </ul>
2289
- </section>
2290
- ))}
2291
- </div>
2292
- )
2293
- }
2184
+ <Changelog />
2294
2185
  </LayoutComponent>
2295
2186
  `;
2296
2187
  };
@@ -2801,5 +2692,5 @@ var runtimeTsconfigTemplate = () => `${JSON.stringify({
2801
2692
 
2802
2693
  export { deployOutputDir, deployStaticDir, surfaceAdapterOutput, planComponentSlots, publishRuntimeModules, runtimeDependencies, EJECTED_CONFIG_HEADER, astroConfigTemplate, stagedContentDir, contentConfigTemplate, askEndpointTemplate, askComponentTemplate, searchEndpointTemplate, featuresTemplate, consentClientTemplate, searchClientTemplate, mixedbreadSearchEndpointTemplate, rawMarkdownEndpointTemplate, contentAssetsEndpointTemplate, mcpPageFile, mcpEndpointTemplate, playgroundProxyTemplate, staticJsonEndpointTemplate, rssEndpointTemplate, navFragmentTemplate, ogEndpointTemplate, scalarReferenceTemplate, catchAllPageTemplate, changelogIndexTemplate, notFoundPageTemplate, notFoundMarkdownTemplate, notFoundJsonTemplate, apiPagesIndexTemplate, apiPageTemplate, apiNavigationTemplate, apiSearchTemplate, apiNotFoundTemplate, exampleSlug, exampleWrapperTemplate, examplesRouteBase, exampleMapTemplate, examplesPageTemplate, runtimePackageTemplate, runtimeTsconfigTemplate };
2803
2694
 
2804
- //# debugId=FCEABB4236B6B32C64756E2164756E21
2805
- //# sourceMappingURL=chunk-dpy8qdjf.js.map
2695
+ //# debugId=89A234A45FD2077E64756E2164756E21
2696
+ //# sourceMappingURL=chunk-k45sq16q.js.map