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
@@ -0,0 +1,39 @@
1
+ import type { ResponseLike } from "../components/openapi/example-panels.ts";
2
+ import type { MediaLike } from "../components/openapi/helpers.ts";
3
+ import type { ApiDocument } from "../openapi/model.ts";
4
+ /**
5
+ * The body and responses of an OpenAPI operation as compact Markdown, for the
6
+ * agent-facing copy of its page (`<route>.md`, llms-full.txt, MCP
7
+ * `get_page`): the request body's media type and top-level properties, its
8
+ * example (every named one), each response's status and description, and
9
+ * the examples the spec records. Without these an agent read an endpoint
10
+ * with no word of what to send or what comes back, though the spec, and the
11
+ * page, had both. Built from the helpers the page's own components use, so
12
+ * the two can't disagree: the same JSON-ish media type, the same examples,
13
+ * `readOnly` and `writeOnly` properties left out the same way.
14
+ *
15
+ * Kept compact: properties one level deep (an example shows the rest), and
16
+ * a sampled response example only for the first success response that
17
+ * records none, since error bodies often all share one schema.
18
+ */
19
+ /** A request body, `$ref` resolved. */
20
+ interface RequestBodyLike {
21
+ description?: string;
22
+ required?: boolean;
23
+ content?: Record<string, MediaLike>;
24
+ }
25
+ /** The operation fields read here. */
26
+ export interface OperationParts {
27
+ requestBody?: RequestBodyLike & {
28
+ $ref?: string;
29
+ };
30
+ responses?: Record<string, ResponseLike & {
31
+ $ref?: string;
32
+ }>;
33
+ }
34
+ /**
35
+ * An operation's body and responses as Markdown blocks, `$ref`s to
36
+ * `components` resolved, ready to join with blank lines.
37
+ */
38
+ export declare const operationDetails: (document: ApiDocument, operation: OperationParts, webhook: boolean) => string[];
39
+ export {};
@@ -13,7 +13,9 @@ import type { BlumeProject } from "../core/project-graph.ts";
13
13
  * `basePath` prefix, a public file (`/spec.pdf`) or image the
14
14
  * `deployment.base` alone, and, on a page in a prefixed locale, a page link
15
15
  * that locale's copy of the route when it is served
16
- * (`components/layout/LocaleLinks.astro`). Inline links, images, component
16
+ * (`components/layout/LocaleLinks.astro`). A root-relative link to a content
17
+ * file (`/guide/new.md`) lands on that file's page, as on the rendered page
18
+ * (`resolveRootFileHref`). Inline links, images, component
17
19
  * `href`s, and reference definitions are rewritten; fenced and inline code,
18
20
  * relative images and asset links, and external URLs are left as written.
19
21
  */
@@ -3,11 +3,13 @@ import type { BlumeProject } from "../core/project-graph.ts";
3
3
  * Every serializer a project brings to a downlevel pass, layered once for all
4
4
  * the agent surfaces (`<route>.md`, llms-full.txt, the search and assistant
5
5
  * corpora): the built-in families that read project data — examples, then the
6
- * API reference — under the user's `agents.markdownComponents`, which is spread
7
- * last so an entry of the same name still wins. One layering, so a new family
8
- * or a new surface cannot leave one consumer printing raw JSX.
6
+ * API reference, then the changelog index — under the user's
7
+ * `agents.markdownComponents`, which is spread last so an entry of the same
8
+ * name still wins. One layering, so a new family or a new surface cannot leave
9
+ * one consumer printing raw JSX.
9
10
  */
10
- export declare const projectComponentSerializers: (project: Pick<BlumeProject, "config" | "examples" | "sources">) => {
11
+ export declare const projectComponentSerializers: (project: BlumeProject) => {
12
+ Changelog: () => string;
11
13
  ApiOverview: ({ props }: import("./component-markdown.ts").ComponentMarkdownContext) => string | null;
12
14
  ApiTagOperations: ({ props }: import("./component-markdown.ts").ComponentMarkdownContext) => string | null;
13
15
  Operation: ({ props }: import("./component-markdown.ts").ComponentMarkdownContext) => string | null;
@@ -25,6 +25,8 @@ export type HeadNode = (HeadScript & {
25
25
  /**
26
26
  * Map the configured adapters to what `Analytics.astro` renders, in declared
27
27
  * order. A second `vercel()` is dropped — two copies of the component would
28
- * count every pageview twice — so the first one keeps its position.
28
+ * count every pageview twice — so the first one keeps its position. `base` is
29
+ * the deployment base a `script()` adapter's root-relative `src` is served
30
+ * under.
29
31
  */
30
- export declare const analyticsHead: (adapters: AnalyticsAdapter[]) => HeadNode[];
32
+ export declare const analyticsHead: (adapters: AnalyticsAdapter[], base?: string) => HeadNode[];
@@ -42,5 +42,11 @@ export declare const scriptAdapterSchema: z.ZodObject<{
42
42
  * passthrough here — every entry lands on the tag as-is.
43
43
  */
44
44
  export declare const script: (options: ScriptOptions) => ScriptAdapter;
45
- /** The tag. Explicit `src`/`strategy` win over a same-named spread attribute. */
46
- export declare const scriptHead: (options: ScriptOptions) => HeadScript[];
45
+ /**
46
+ * The tag. Explicit `src`/`strategy` win over a same-named spread attribute.
47
+ * A root-relative `src` (`/js/x.js`, a file in `public/`) is served under the
48
+ * deployment `base`, so it gets the base the way a link does; one already
49
+ * under it is left alone, and absolute and protocol-relative URLs pass
50
+ * through.
51
+ */
52
+ export declare const scriptHead: (options: ScriptOptions, base: string) => HeadScript[];
@@ -9,6 +9,12 @@
9
9
  * nothing rather than a broken embed.
10
10
  */
11
11
  export declare const parseYouTubeId: (input: string) => string | null;
12
+ /**
13
+ * The playlist id of a YouTube playlist URL (`/embed/videoseries?list=…` or
14
+ * `/playlist?list=…`), or `null` for anything else — a video URL that also
15
+ * carries a `list` (`watch?v=…&list=…`) is that video.
16
+ */
17
+ export declare const parseYouTubePlaylist: (input: string) => string | null;
12
18
  /**
13
19
  * Build a privacy-enhanced (`youtube-nocookie.com`) embed URL, optionally
14
20
  * starting at `start` seconds.
@@ -16,3 +22,17 @@ export declare const parseYouTubeId: (input: string) => string | null;
16
22
  export declare const youtubeEmbedUrl: (id: string, options?: {
17
23
  start?: number;
18
24
  }) => string;
25
+ /**
26
+ * The privacy-enhanced embed URL for a playlist, optionally starting its
27
+ * first video at `start` seconds.
28
+ */
29
+ export declare const youtubePlaylistEmbedUrl: (list: string, options?: {
30
+ start?: number;
31
+ }) => string;
32
+ /**
33
+ * The embed URL for a `<YouTube>`'s `id` or `url`: a video, else a playlist,
34
+ * else `null` when the input names neither.
35
+ */
36
+ export declare const youtubeEmbedSrc: (input: string, options?: {
37
+ start?: number;
38
+ }) => string | null;
@@ -73,6 +73,14 @@ export declare const getPagination: (flat: FlatPage[], route: string) => {
73
73
  export type NavGroup = Extract<NavNode, {
74
74
  kind: "group";
75
75
  }>;
76
+ /**
77
+ * Whether a `group`-mode disclosure renders open: it holds the current page,
78
+ * its meta forces it open (`collapsed: false`), or it is the only row at the
79
+ * top of the sidebar, where starting closed would leave a sidebar of one row
80
+ * to click before any link shows (a wrapper folder around every page). An
81
+ * explicit `collapsed: true` keeps that lone group closed.
82
+ */
83
+ export declare const groupStartsOpen: (group: NavGroup, active: boolean, lone: boolean) => boolean;
76
84
  /**
77
85
  * The group whose own page `route` is, when that page lists the group's
78
86
  * pages: its `directory` (inherited when the group sets none) is `card` or
@@ -0,0 +1,33 @@
1
+ import type { ComponentsLike, MediaLike, SchemaLike, SpecValue } from "./helpers.ts";
2
+ /**
3
+ * The example tabs of an operation's rail (`RequestPanel.astro`): one per
4
+ * response status, or per webhook payload media type — and one per named
5
+ * example where its `examples` map names two or more, labeled by the
6
+ * example's `summary` (else its key) after the status or media type, so
7
+ * every recorded example shows, under its name. Values are left for the
8
+ * component to highlight.
9
+ */
10
+ /** One tab before highlighting. */
11
+ export interface ExamplePanel {
12
+ key: string;
13
+ label: string;
14
+ /** The status or media type the tab is under. */
15
+ name: string;
16
+ /** The media type the value is an example of. */
17
+ type: string;
18
+ /** The example, or `null`/`undefined` when there's none to show. */
19
+ value: SpecValue;
20
+ /** What the tab says when there's no example. */
21
+ text: string;
22
+ }
23
+ /** A response: its description and its body's media types. */
24
+ export interface ResponseLike {
25
+ description?: string;
26
+ content?: Record<string, MediaLike>;
27
+ }
28
+ /** The media entry a body shows: the first JSON-ish one, else the first. */
29
+ export declare const preferredMedia: (content?: Record<string, MediaLike>) => [string, MediaLike] | undefined;
30
+ /** The Response tabs: per status, per named example. */
31
+ export declare const responsePanels: (responses: Record<string, ResponseLike>, schemas: Record<string, SchemaLike>, components?: ComponentsLike) => ExamplePanel[];
32
+ /** A webhook's Payload tabs: per media type, per named example. */
33
+ export declare const payloadPanels: (payload: Record<string, MediaLike> | undefined, schemas: Record<string, SchemaLike>, components?: ComponentsLike) => ExamplePanel[];
@@ -83,7 +83,10 @@ export declare const soleAllOfMember: (schema: SchemaLike) => SchemaLike | undef
83
83
  /**
84
84
  * Resolve one level of `$ref` against the document's component schemas. A
85
85
  * single-member `allOf` wrapper resolves like its member, with the wrapper's
86
- * own keywords on top: its `description` is about this field.
86
+ * own keywords on top: its `description` is about this field. So does a
87
+ * `$ref` with keywords beside it, which OpenAPI 3.1 allows and .NET writes
88
+ * for every enum-typed property: the `description` beside the `$ref` is the
89
+ * property's, the referenced one the type's.
87
90
  */
88
91
  export declare const resolveSchema: (schemas: Record<string, SchemaLike>, schema?: SchemaLike) => SchemaLike;
89
92
  /**
@@ -121,16 +124,30 @@ export interface ObjectPropertySet {
121
124
  * the merged required set.
122
125
  */
123
126
  export declare const objectProperties: (schema: SchemaLike, schemas: Record<string, SchemaLike>) => ObjectPropertySet;
127
+ /** Which way an example travels: to the API, or back from it. */
128
+ export type ExampleDirection = "request" | "response";
129
+ /**
130
+ * An example value with the properties that don't travel `direction` left
131
+ * out, at every depth its schema describes: `readOnly` ones from a request,
132
+ * which the server sets, and `writeOnly` ones from a response, which it
133
+ * never returns. openapi-sampler skips those only in the values it builds; a
134
+ * declared example (a model's `example`, which TypeSpec writes, or a media
135
+ * type's) keeps them, so a request sample would send the model's `id`. A
136
+ * property the schema doesn't describe stays as written.
137
+ */
138
+ export declare const forDirection: (value: SpecValue, schema: SchemaLike | undefined, schemas: Record<string, SchemaLike>, direction: ExampleDirection) => SpecValue;
124
139
  /**
125
140
  * Build a representative example value for a schema via openapi-sampler
126
141
  * (Redoc's generator): declared `example`/`const`/`default`/`enum` values
127
- * win, formats produce realistic placeholders (`email`, `uuid`, `date-time`),
128
- * and circular `$ref` chains — which keeping refs intact allows — terminate
129
- * safely. A request sample skips `readOnly` fields (a server-generated field
130
- * has no place in one); a response sample skips `writeOnly` fields (a
131
- * password the client sends never comes back) and keeps the `readOnly` ones.
142
+ * win, a value beside a `$ref` included, formats produce realistic
143
+ * placeholders (`email`, `uuid`, `date-time`), and circular `$ref` chains —
144
+ * which keeping refs intact allows — terminate safely. A request sample
145
+ * leaves out `readOnly` fields (a server-generated field has no place in
146
+ * one); a response sample leaves out `writeOnly` fields (a password the
147
+ * client sends never comes back) and keeps the `readOnly` ones. That holds
148
+ * inside a declared value the sampler copies too (see {@link forDirection}).
132
149
  */
133
- export declare const exampleValue: (schema: SchemaLike | undefined, schemas: Record<string, SchemaLike>, direction?: "request" | "response") => SpecValue;
150
+ export declare const exampleValue: (schema: SchemaLike | undefined, schemas: Record<string, SchemaLike>, direction?: ExampleDirection) => SpecValue;
134
151
  /** Where an author can declare an example: a parameter or a media type. */
135
152
  export interface ExampleCarrier {
136
153
  example?: SpecValue;
@@ -146,13 +163,38 @@ export interface ExampleCarrier {
146
163
  * declared.
147
164
  */
148
165
  export declare const declaredExample: (carrier: ExampleCarrier, components?: ComponentsLike) => SpecValue;
166
+ /** A media type: the schema of a body and the examples it declares. */
167
+ export type MediaLike = ExampleCarrier & {
168
+ schema?: SchemaLike;
169
+ };
170
+ /**
171
+ * A media type's example for a body travelling `direction`: the declared
172
+ * one, else a sample built from its schema, with the properties that don't
173
+ * travel that way left out (see {@link forDirection}).
174
+ */
175
+ export declare const mediaExample: (media: MediaLike, schemas: Record<string, SchemaLike>, direction: ExampleDirection, components?: ComponentsLike) => SpecValue;
149
176
  /**
150
177
  * A response media type's example for the Response panel: the declared one,
151
178
  * else a sample built for the response direction (`readOnly` kept,
152
- * `writeOnly` skipped).
179
+ * `writeOnly` left out).
153
180
  */
154
- export declare const responseExample: (media: ExampleCarrier & {
155
- schema?: SchemaLike;
156
- }, schemas: Record<string, SchemaLike>, components?: ComponentsLike) => SpecValue;
181
+ export declare const responseExample: (media: MediaLike, schemas: Record<string, SchemaLike>, components?: ComponentsLike) => SpecValue;
182
+ /** One of a media type's named examples, as a tab or the Markdown copy shows it. */
183
+ export interface NamedExample {
184
+ /** The example's key in the `examples` map. */
185
+ key: string;
186
+ /** Its `summary`, else its key. */
187
+ label: string;
188
+ value: SpecValue;
189
+ }
190
+ /**
191
+ * Every example a media type's `examples` map names, in order, `$ref`s to
192
+ * `#/components/examples` resolved, each labeled by its `summary` or else
193
+ * its key, with the properties that don't travel `direction` left out. Empty
194
+ * unless the map names two or more: Scalar's upgrade files a 3.0 `example`
195
+ * as the one entry `default`, which is no name to show, and a lone example
196
+ * is the one {@link mediaExample} already gives.
197
+ */
198
+ export declare const namedExamples: (media: MediaLike, schemas: Record<string, SchemaLike>, direction: ExampleDirection, components?: ComponentsLike) => NamedExample[];
157
199
  /** Pretty-print a JSON value for an example/code block. */
158
200
  export declare const toJson: <T>(value: T) => string;
@@ -53,8 +53,14 @@ export interface SampleLanguageInfo {
53
53
  export declare const sampleLanguageInfo: (raw: string) => SampleLanguageInfo | null;
54
54
  /** `openapi()`'s default `codeSamples`, which hand-written endpoint pages always use. */
55
55
  export declare const DEFAULT_SAMPLE_LANGUAGES: string[];
56
+ /**
57
+ * The configured ids Blume generates no sample for, as written: the ones
58
+ * {@link sampleLanguages} drops, which the reference source warns about.
59
+ */
60
+ export declare const unknownSampleLanguages: (ids: string[] | false) => string[];
56
61
  /**
57
62
  * The sample languages to render, resolved from config ids (unknown ids
58
- * dropped), in order. `false` and an empty list both render none.
63
+ * dropped, with a warning from the reference source), in order. `false` and
64
+ * an empty list both render none.
59
65
  */
60
66
  export declare const sampleLanguages: (ids: string[] | false) => SampleLanguage[];
@@ -0,0 +1,10 @@
1
+ import type { SourceEntry } from "./sources/types.ts";
2
+ import type { Diagnostic } from "./types.ts";
3
+ /**
4
+ * Warn about GitHub alerts (`> [!NOTE]`) in an `.md` entry, which renders
5
+ * them as plain quotes that show the marker as text: alerts become callouts
6
+ * only in `.mdx`, where Blume renders components (see
7
+ * `markdown/github-alerts.ts`). Lines point into the file the author wrote, a
8
+ * partial's own file for an alert an `<include>` brought in.
9
+ */
10
+ export declare const alertDiagnostics: (entry: SourceEntry, sourceName: string) => Diagnostic[];
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The MDX component tags Blume ships (the keys of the catch-all's component map,
3
+ * plus composed sub-parts like `Color.Item`/`Tree.File`). Used by the
4
+ * missing-component diagnostic to tell an unknown `<Tag>` from a built-in. Keep
5
+ * in sync with the component map in `astro/templates.ts`.
6
+ */
7
+ export declare const BUILTIN_MDX_TAGS: Set<string>;
8
+ /**
9
+ * The props each built-in that shows its children takes, keyed by MDX tag. A
10
+ * childless use with any other prop renders without the content its author
11
+ * meant it to carry (VitePress writes `<Badge type="tip" text="beta" />`, and
12
+ * Blume's Badge shows only its children), which the unknown-prop diagnostic
13
+ * reports. Each list is the component's own `Props` (or what it reads from
14
+ * `Astro.props`); a test checks them against the `.astro` files.
15
+ */
16
+ export declare const BUILTIN_CHILD_PROPS: ReadonlyMap<string, readonly string[]>;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The policy the changelog index lists by, shared by the surfaces that build
3
+ * it: the `<Changelog />` component (reading Astro collection entries) and
4
+ * `ai/changelog-markdown.ts` (reading the build-time page graph for the
5
+ * `/changelog.md` mirror and MCP `get_page`).
6
+ *
7
+ * The data sources genuinely differ — a collection entry on the Astro side, a
8
+ * `PageRecord` on the Node side — so what lives here is the *decisions*, not
9
+ * the access: which date a row carries, what order rows come in, and how they
10
+ * fall into year groups. Keeping them in one place is what stops the rendered
11
+ * page and the Markdown an agent reads from drifting apart.
12
+ */
13
+ /**
14
+ * A changelog entry's date, from `date` or the `changelog.date` it may live
15
+ * under instead. Front matter hands either a `Date` (an unquoted YAML date) or
16
+ * a string, and an unparseable value is treated as no date at all rather than
17
+ * failing the build — a malformed date costs the row its stamp and its year
18
+ * group, not the page.
19
+ */
20
+ export declare const parseChangelogDate: (value: Date | string | null | undefined) => Date | null;
21
+ /**
22
+ * Newest first. An undated entry sorts as the epoch, so undated rows collect
23
+ * at the end of the list (and, through {@link groupChangelogYears}, into a
24
+ * final group with no year label).
25
+ */
26
+ export declare const compareChangelogDates: (a: Date | null, b: Date | null) => number;
27
+ /** One year's run of rows. `year` is `null` for the undated group. */
28
+ export interface ChangelogYearGroup<T> {
29
+ items: T[];
30
+ year: string | null;
31
+ }
32
+ /**
33
+ * Consecutive rows sharing a year, in list order, so the index reads as a year
34
+ * rail beside its rows. Runs are consecutive rather than keyed, which matters
35
+ * only for a list that isn't sorted by date: such a list keeps its order and
36
+ * repeats the year heading instead of silently regrouping around it.
37
+ *
38
+ * `yearOf` returns the label the surface wants — a locale-formatted year on the
39
+ * rendered page, a plain number in Markdown — or `null` for an undated row.
40
+ */
41
+ export declare const groupChangelogYears: <T>(items: T[], yearOf: (item: T) => string | null) => ChangelogYearGroup<T>[];
42
+ /**
43
+ * Make each row's anchor unique. Repeated labels slug to the same id (two
44
+ * entries with neither a title nor a version both fall back to "update"), so
45
+ * the later ones take a `-2`, `-3`, … suffix and the first keeps the plain
46
+ * slug — every row ends up with its own hash anchor.
47
+ */
48
+ export declare const uniqueAnchorIds: (ids: string[]) => string[];
@@ -0,0 +1,6 @@
1
+ /**
2
+ * The candidate closest to `name`, when it's close enough to be the likely
3
+ * intent: at most two edits away, and fewer edits than half the candidate's
4
+ * length, so a short typo doesn't "suggest" an unrelated short word.
5
+ */
6
+ export declare const closestMatch: (name: string, candidates: readonly string[]) => string | undefined;
@@ -0,0 +1,18 @@
1
+ import type { SourceEntry } from "./sources/types.ts";
2
+ import type { Diagnostic } from "./types.ts";
3
+ /**
4
+ * Warn about code fences that don't render as their author meant:
5
+ *
6
+ * - `BLUME_UNKNOWN_CODE_LANGUAGE`: a language Shiki doesn't know, so the block
7
+ * renders as plain text. Shiki itself only logs a console line naming the
8
+ * language, with no page or line.
9
+ * - `BLUME_CODE_FENCE_OPTION`: an option another docs tool reads, like MkDocs'
10
+ * `hl_lines="2 3"`, Docusaurus' `showLineNumbers`, Mintlify's `lines`, or
11
+ * rustdoc's `no_run`, which Blume ignores. None of them becomes part of the
12
+ * block's title. The suggestion gives the Blume spelling, or says to remove
13
+ * an option Blume has no use for.
14
+ *
15
+ * Lines point into the file the author wrote, a partial's own file for a
16
+ * fence an `<include>` brought in.
17
+ */
18
+ export declare const codeFenceDiagnostics: (entry: SourceEntry, sourceName: string) => Diagnostic[];
@@ -1,11 +1,18 @@
1
- /** The open fence's delimiter char and run length, or null outside one. */
1
+ /**
2
+ * The open fence's delimiter char, its run length, and the block-quote depth
3
+ * it opened at, or null outside one.
4
+ */
2
5
  export type FenceState = {
3
6
  delimiter: "`" | "~";
4
7
  length: number;
8
+ quotes: number;
5
9
  } | null;
6
10
  /**
7
11
  * Advance the fenced-code state for one line: an opening fence records its
8
12
  * delimiter and run length, only a bare run of the same character at least as
9
13
  * long closes it (CommonMark), and any other line leaves the state untouched.
14
+ * A fence inside block quotes is read past the quote markers it opened under,
15
+ * and a line without them ends the quote, and the fence with it: code takes
16
+ * no lazy continuation lines (CommonMark).
10
17
  */
11
18
  export declare const nextFenceState: (line: string, fence: FenceState) => FenceState;
@@ -13,7 +13,7 @@ import type { AnySearchAdapter } from "../search/adapters/registry.ts";
13
13
  import type { SourceAdapterInput } from "../sources/registry.ts";
14
14
  import type { FontSlug } from "../theme/fonts.ts";
15
15
  import type { FooterSocial } from "./footer.ts";
16
- import type { OpenInChatProvider, SidebarDisplay, SidebarItemConfig } from "./schema.ts";
16
+ import type { McpClient, McpCustomClient, OpenInChatProvider, SidebarDisplay, SidebarItemConfig } from "./schema.ts";
17
17
  import type { StandardSchema } from "./standard-schema.ts";
18
18
  /**
19
19
  * The public, hand-documented authoring type for `blume.config.ts`.
@@ -115,9 +115,15 @@ export interface FooterLink {
115
115
  }
116
116
  /**
117
117
  * The site footer, below the content on every page: a row of links on one
118
- * side, and social profile icons on the other.
118
+ * side, social profile icons on the other, and a copyright line centered
119
+ * between them.
119
120
  */
120
121
  export interface FooterConfig {
122
+ /**
123
+ * A line of plain text centered between the links and the icons, like
124
+ * `© 2026 Acme, Inc.`, or a map of locale code to text.
125
+ */
126
+ copyright?: LocalizableLabel;
121
127
  /** Links in one row, left to right. */
122
128
  links?: FooterLink[];
123
129
  /**
@@ -147,7 +153,7 @@ export interface ChangelogConfig {
147
153
  export interface ContentConfig {
148
154
  /** Default page `type` for content that sets none. Defaults to `doc`. */
149
155
  defaultType?: string;
150
- /** Glob patterns to ignore. Defaults to `["**\/_*", "**\/.*"]`. Shorthand; not allowed beside `sources`. */
156
+ /** Glob patterns to ignore, on top of `["**\/_*", "**\/.*"]`; a `!pattern` entry stops ignoring that pattern, a default included. Shorthand; not allowed beside `sources`. */
151
157
  exclude?: string[];
152
158
  /** Glob patterns to include. Defaults to `["**\/*.{md,mdx}"]`. Shorthand; not allowed beside `sources`. */
153
159
  include?: string[];
@@ -638,6 +644,32 @@ export interface LlmsTxtConfig {
638
644
  }
639
645
  /** Expose the docs as an MCP server for connecting agents. */
640
646
  export interface McpConfig {
647
+ /**
648
+ * The clients the "Connect to MCP" page action installs the server into,
649
+ * beside its "Copy server URL" row. Defaults to `true` (every built-in
650
+ * client). Set `false` to list none, or list built-in keys and your own
651
+ * clients, in order. A custom client's `command` is copied with `{name}`
652
+ * (the server name as an id) and `{url}` (the server's URL) filled in; its
653
+ * `label` localizes like a header link's, and `icon` defaults to `terminal`.
654
+ *
655
+ * ```ts
656
+ * agents: {
657
+ * mcp: {
658
+ * enabled: true,
659
+ * clients: [
660
+ * "claude-code",
661
+ * {
662
+ * label: "Copy Copilot CLI command",
663
+ * command: "copilot mcp add --transport http {name} {url}",
664
+ * icon: "terminal",
665
+ * },
666
+ * "vscode",
667
+ * ],
668
+ * },
669
+ * }
670
+ * ```
671
+ */
672
+ clients?: boolean | (McpClient | McpCustomClient)[];
641
673
  /** Turn the MCP server on. Defaults to `false`. */
642
674
  enabled?: boolean;
643
675
  /** Optional system hint passed to connecting agents. */
@@ -1408,8 +1440,8 @@ export interface BlumeConfig {
1408
1440
  */
1409
1441
  feedback?: boolean | FeedbackConfig;
1410
1442
  /**
1411
- * The site footer: social profile icons and up to four link columns. Unset,
1412
- * the site has no footer.
1443
+ * The site footer: a copyright line, a row of links, and social profile
1444
+ * icons. Unset, the site has no footer.
1413
1445
  */
1414
1446
  footer?: FooterConfig;
1415
1447
  /** Opt-in custom frontmatter keys, validated by schemas you supply. */
@@ -1438,7 +1470,7 @@ export interface BlumeConfig {
1438
1470
  * Limit how often one reader (by IP address) can call the server routes —
1439
1471
  * the assistant, the API playground proxy, server-side search — with an
1440
1472
  * adapter from `blume/ratelimit`: `memory()` (the default, 30 requests per
1441
- * 10 minutes), `upstash()`, or `cloudflare()`. `false` turns it off.
1473
+ * 10 minutes), `upstash()`, `cloudflare()`, or `unkey()`. `false` turns it off.
1442
1474
  */
1443
1475
  rateLimit?: false | RateLimitAdapter;
1444
1476
  /** React island behavior (compiler auto-memoization). */
@@ -10,8 +10,15 @@ import type { PageRecord } from "./types.ts";
10
10
  * `/blume-assets/content/<project-relative path>` by a generated endpoint (see
11
11
  * `contentAssetsEndpointTemplate`), and these helpers rewrite the relative
12
12
  * references in agent-facing output to that URL.
13
+ *
14
+ * Other files beside a page are published the same way: a link to one
15
+ * (`[spec](./spec.pdf)`, a reference definition), a raw HTML or `.mdx`
16
+ * element's `src` (`<img src="./diagram.png">`, `<video>`, `<source>`,
17
+ * `<audio>`), and an `<a>`'s or a component's `href`. Nothing else serves
18
+ * them, so the HTML render points those at the same URLs (see
19
+ * `markdown/content-assets.ts`).
13
20
  */
14
- /** The endpoint route prefix colocated content images are served under. */
21
+ /** The endpoint route prefix colocated content files are served under. */
15
22
  export declare const CONTENT_ASSETS_PREFIX = "/blume-assets/content";
16
23
  /**
17
24
  * The endpoint param a colocated image is served under: its project-relative
@@ -21,29 +28,20 @@ export declare const CONTENT_ASSETS_PREFIX = "/blume-assets/content";
21
28
  */
22
29
  export declare const contentAssetParam: (projectRoot: string, absPath: string) => string;
23
30
  /**
24
- * Whether a target is *shaped* like a colocated image reference: a relative
25
- * filesystem path with an image extension. Exported so link validation can
26
- * tell "not a colocated candidate" apart from "a candidate that resolves
27
- * nowhere" — the former falls through to the public-dir probe, the latter is
28
- * a broken reference beside the page source.
31
+ * The URL a colocated image's endpoint param is served at, under
32
+ * `deployment.base` when set, encoded for a Markdown or HTML URL with its `/`
33
+ * separators kept.
29
34
  */
30
- export declare const isRelativeImageTarget: (target: string) => boolean;
35
+ export declare const contentAssetUrl: (param: string, deployBase?: string) => string;
31
36
  /**
32
- * Resolve one image target against its page's directory. Returns the absolute
33
- * file path when the target is relative, is an image, and exists on disk —
34
- * anything else (remote URLs, `public/` absolutes, broken refs, code-block
35
- * examples that happen to look like paths) is null and left untouched. Shared
36
- * with link validation, so what counts as a colocated image is decided once.
37
- */
38
- export declare const resolveRelativeImage: (sourceDir: string, target: string) => string | null;
39
- /**
40
- * Rewrite a page's relative image references to their served
37
+ * Rewrite a page's relative image references, and its links and element
38
+ * URLs naming other files beside it, to their served
41
39
  * `/blume-assets/content/…` URLs (under `deployment.base` when set). Fenced
42
40
  * code blocks and inline code are skipped; only references whose file actually
43
41
  * exists next to the source are touched. `register` observes each rewritten
44
42
  * asset so a caller can accumulate the files the endpoint must serve.
45
43
  */
46
- export declare const rewriteRelativeImages: (options: {
44
+ export declare const rewriteRelativeAssets: (options: {
47
45
  source: string;
48
46
  sourcePath: string;
49
47
  projectRoot: string;
@@ -51,7 +49,7 @@ export declare const rewriteRelativeImages: (options: {
51
49
  register?: (param: string, absPath: string) => void;
52
50
  }) => string;
53
51
  /**
54
- * Every colocated image the project's pages reference, keyed by endpoint param.
52
+ * Every colocated file the project's pages reference, keyed by endpoint param.
55
53
  * Serialized to `generated/content-assets.json`, which the
56
54
  * `/blume-assets/[...asset]` endpoint reads to serve the original files. Runs
57
55
  * the same rewrite the agent-Markdown builders apply — over the same
@@ -193,7 +193,7 @@ export interface BlumeDataConfig {
193
193
  feedback: boolean;
194
194
  /** Whether the rating asks for a written comment after it (`feedback.comments`). */
195
195
  feedbackComments: boolean;
196
- /** `footer`: social profile icons and link columns, or `null` when unset. */
196
+ /** `footer`: the copyright line, links, and social profile icons, or `null` when unset. */
197
197
  footer: ResolvedConfig["footer"] | null;
198
198
  /**
199
199
  * Repo coordinates for content components that address the API or build
@@ -217,8 +217,12 @@ export interface BlumeDataConfig {
217
217
  /** `markdown.imageZoom`: click-to-zoom content images. */
218
218
  imageZoom: boolean;
219
219
  logo: BlumeLogo | null;
220
- /** Hosted MCP server, or `null` when MCP is off. */
220
+ /**
221
+ * Hosted MCP server, or `null` when MCP is off, with the clients its
222
+ * "Connect to MCP" page action lists (`agents.mcp.clients`), in order.
223
+ */
221
224
  mcp: {
225
+ clients: ResolvedConfig["agents"]["mcp"]["clients"];
222
226
  name: string;
223
227
  route: string;
224
228
  } | null;
@@ -10,6 +10,20 @@ export declare const createDiagnostic: (diagnostic: Diagnostic) => Diagnostic;
10
10
  export declare const resolveDocsUrl: (code: string) => string | undefined;
11
11
  /** Fill in `docsUrl` from the code map where a diagnostic doesn't set its own. */
12
12
  export declare const enrichDiagnostic: (diagnostic: Diagnostic) => Diagnostic;
13
+ /**
14
+ * Best-effort source position for a Zod issue path (e.g. `["seo", "title"]`,
15
+ * `["redirects", 2, "status"]`) in the raw config / frontmatter text. Narrows
16
+ * segment by segment: a key is found among its parent's own entries (or, where
17
+ * there are no brackets, in the parent's indented lines), an index picks that
18
+ * element of an array literal. A segment that isn't there — a missing key —
19
+ * stops the walk at its parent, so the position never escapes into a sibling.
20
+ * Returns 1-based line/column, or undefined when not even the first segment
21
+ * matches.
22
+ */
23
+ export declare const locatePath: (source: string, path: readonly (string | number)[]) => {
24
+ column: number;
25
+ line: number;
26
+ } | undefined;
13
27
  /**
14
28
  * Locate a front matter key in a content file, e.g. `["seo", "description"]` in
15
29
  * `docs/api.mdx`. Scoped to the front matter block so a `title:` written in the