blume 2.1.2 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (377) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +133 -0
  3. package/README.md +4 -4
  4. package/dist/cli/{chunk-74wfhv79.js → chunk-05f21r8h.js} +1 -1
  5. package/dist/cli/{chunk-9qzgg6mj.js → chunk-1cm0h819.js} +3 -3
  6. package/dist/cli/{chunk-nbyvgnnm.js → chunk-1rkxzg3n.js} +104 -47
  7. package/dist/cli/chunk-1rkxzg3n.js.map +36 -0
  8. package/dist/cli/{chunk-desvm72z.js → chunk-2nr29y95.js} +22 -26
  9. package/dist/cli/chunk-2nr29y95.js.map +13 -0
  10. package/dist/cli/{chunk-32khwcb6.js → chunk-49r370mb.js} +42 -69
  11. package/dist/cli/{chunk-32khwcb6.js.map → chunk-49r370mb.js.map} +9 -10
  12. package/dist/cli/{chunk-ms9z66nz.js → chunk-4rftmttv.js} +2 -2
  13. package/dist/cli/{chunk-s0bdnc7v.js → chunk-79bzzkx4.js} +5 -4
  14. package/dist/cli/chunk-79bzzkx4.js.map +10 -0
  15. package/dist/cli/{chunk-hvcxng5f.js → chunk-7tekknev.js} +6 -6
  16. package/dist/cli/{chunk-dv2z0rzf.js → chunk-8b489v1b.js} +38 -13
  17. package/dist/cli/{chunk-dv2z0rzf.js.map → chunk-8b489v1b.js.map} +5 -4
  18. package/dist/cli/{chunk-0pmb4tr4.js → chunk-8f8xw4x2.js} +1195 -222
  19. package/dist/cli/chunk-8f8xw4x2.js.map +44 -0
  20. package/dist/cli/chunk-96snx8yy.js +329 -0
  21. package/dist/cli/chunk-96snx8yy.js.map +13 -0
  22. package/dist/cli/{chunk-ckrcm08h.js → chunk-a3ydrqny.js} +48 -62
  23. package/dist/cli/{chunk-ckrcm08h.js.map → chunk-a3ydrqny.js.map} +4 -5
  24. package/dist/cli/{chunk-bxwhtvw8.js → chunk-ahc5gc9h.js} +5 -5
  25. package/dist/cli/{chunk-dpy8qdjf.js → chunk-as09pafp.js} +73 -182
  26. package/dist/cli/chunk-as09pafp.js.map +18 -0
  27. package/dist/cli/{chunk-tfycddbt.js → chunk-bjk964fp.js} +2 -2
  28. package/dist/cli/{chunk-gfc5fqvf.js → chunk-br0n8n3e.js} +18 -18
  29. package/dist/cli/{chunk-gfc5fqvf.js.map → chunk-br0n8n3e.js.map} +1 -1
  30. package/dist/cli/{chunk-297ajdcv.js → chunk-c69tw29j.js} +6 -6
  31. package/dist/cli/{chunk-297ajdcv.js.map → chunk-c69tw29j.js.map} +3 -3
  32. package/dist/cli/chunk-cn3dy3hz.js +146 -0
  33. package/dist/cli/chunk-cn3dy3hz.js.map +11 -0
  34. package/dist/cli/{chunk-124fvmzq.js → chunk-dm4mg9bj.js} +11064 -8742
  35. package/dist/cli/{chunk-124fvmzq.js.map → chunk-dm4mg9bj.js.map} +78 -64
  36. package/dist/cli/{chunk-dqhg54mr.js → chunk-dmx6cezx.js} +1 -1
  37. package/dist/cli/{chunk-60hz265r.js → chunk-dpcahcrb.js} +24 -11
  38. package/dist/cli/chunk-dpcahcrb.js.map +10 -0
  39. package/dist/cli/{chunk-a57yh0h9.js → chunk-dyk3r7jw.js} +7 -7
  40. package/dist/cli/{chunk-a57yh0h9.js.map → chunk-dyk3r7jw.js.map} +1 -1
  41. package/dist/cli/{chunk-twy7psdz.js → chunk-enk76qd5.js} +14 -10
  42. package/dist/cli/chunk-enk76qd5.js.map +10 -0
  43. package/dist/cli/{chunk-k3gr1nm9.js → chunk-fqy4n3q2.js} +13 -16
  44. package/dist/cli/{chunk-k3gr1nm9.js.map → chunk-fqy4n3q2.js.map} +3 -3
  45. package/dist/cli/{chunk-sc93apfs.js → chunk-frk2wdq1.js} +17 -17
  46. package/dist/cli/{chunk-sc93apfs.js.map → chunk-frk2wdq1.js.map} +2 -2
  47. package/dist/cli/{chunk-kdpzw38a.js → chunk-gprwej7h.js} +95 -7
  48. package/dist/cli/chunk-gprwej7h.js.map +11 -0
  49. package/dist/cli/chunk-kkrteb15.js +157 -0
  50. package/dist/cli/chunk-kkrteb15.js.map +10 -0
  51. package/dist/cli/{chunk-ave1wcbr.js → chunk-m9bp2hc1.js} +1 -1
  52. package/dist/cli/{chunk-58bt3hag.js → chunk-mrvh4c88.js} +4 -4
  53. package/dist/cli/{chunk-5cmts6dv.js → chunk-p8zg3a2h.js} +7 -7
  54. package/dist/cli/{chunk-5cmts6dv.js.map → chunk-p8zg3a2h.js.map} +1 -1
  55. package/dist/cli/{chunk-0w6hs479.js → chunk-rkqae7kh.js} +30 -18
  56. package/dist/cli/chunk-rkqae7kh.js.map +10 -0
  57. package/dist/cli/{chunk-bqxaqn5p.js → chunk-t5xx74rd.js} +8 -8
  58. package/dist/cli/{chunk-bqxaqn5p.js.map → chunk-t5xx74rd.js.map} +1 -1
  59. package/dist/cli/{chunk-1f882900.js → chunk-th0pgaj5.js} +2 -2
  60. package/dist/cli/{chunk-dhwtqnnd.js → chunk-vnbvhgmd.js} +2 -2
  61. package/dist/cli/{chunk-gxtg6ed2.js → chunk-vzy9rh6y.js} +21 -21
  62. package/dist/cli/{chunk-gxtg6ed2.js.map → chunk-vzy9rh6y.js.map} +3 -3
  63. package/dist/cli/{chunk-j1x92mx9.js → chunk-w6e455pz.js} +1 -1
  64. package/dist/cli/chunk-wehv26ry.js +155 -0
  65. package/dist/cli/chunk-wehv26ry.js.map +11 -0
  66. package/dist/cli/{chunk-y4msrwm9.js → chunk-xgq4eytj.js} +15 -15
  67. package/dist/cli/{chunk-36bxs9c7.js → chunk-xt0qvz1t.js} +27 -23
  68. package/dist/cli/chunk-xt0qvz1t.js.map +10 -0
  69. package/dist/cli/index.js +78 -42
  70. package/dist/cli/index.js.map +7 -6
  71. package/dist/types/ai/changelog-components.d.ts +18 -0
  72. package/dist/types/ai/changelog-markdown.d.ts +12 -0
  73. package/dist/types/ai/openapi-components.d.ts +7 -7
  74. package/dist/types/ai/operation-details.d.ts +39 -0
  75. package/dist/types/ai/relative-links.d.ts +3 -1
  76. package/dist/types/ai/serializers.d.ts +6 -4
  77. package/dist/types/analytics/head.d.ts +4 -2
  78. package/dist/types/analytics/script.d.ts +8 -2
  79. package/dist/types/components/content/youtube.d.ts +20 -0
  80. package/dist/types/components/layout/nav-utils.d.ts +8 -0
  81. package/dist/types/components/openapi/example-panels.d.ts +33 -0
  82. package/dist/types/components/openapi/helpers.d.ts +53 -11
  83. package/dist/types/components/openapi/snippets.d.ts +7 -1
  84. package/dist/types/core/alert-diagnostics.d.ts +10 -0
  85. package/dist/types/core/builtin-tags.d.ts +16 -0
  86. package/dist/types/core/changelog-list.d.ts +48 -0
  87. package/dist/types/core/closest-match.d.ts +6 -0
  88. package/dist/types/core/code-fence-diagnostics.d.ts +18 -0
  89. package/dist/types/core/code-fences.d.ts +8 -1
  90. package/dist/types/core/config-input.d.ts +1 -1
  91. package/dist/types/core/content-assets.d.ts +16 -18
  92. package/dist/types/core/diagnostics.d.ts +14 -0
  93. package/dist/types/core/directive-diagnostics.d.ts +22 -8
  94. package/dist/types/core/former-routes.d.ts +14 -0
  95. package/dist/types/core/github.d.ts +5 -4
  96. package/dist/types/core/heading-markers.d.ts +65 -2
  97. package/dist/types/core/hidden-pages.d.ts +3 -0
  98. package/dist/types/core/includes.d.ts +23 -0
  99. package/dist/types/core/last-modified.d.ts +18 -6
  100. package/dist/types/core/links.d.ts +42 -2
  101. package/dist/types/core/load-module.d.ts +19 -4
  102. package/dist/types/core/manifest.d.ts +14 -1
  103. package/dist/types/core/markdown-mirrors.d.ts +22 -0
  104. package/dist/types/core/mdx-elements.d.ts +32 -0
  105. package/dist/types/core/mdx-syntax.d.ts +100 -0
  106. package/dist/types/core/meta-diagnostics.d.ts +7 -0
  107. package/dist/types/core/meta.d.ts +32 -5
  108. package/dist/types/core/nav-diagnostics.d.ts +9 -2
  109. package/dist/types/core/navigation.d.ts +13 -0
  110. package/dist/types/core/ordering-prefix.d.ts +6 -0
  111. package/dist/types/core/pinned-ids.d.ts +23 -0
  112. package/dist/types/core/project-graph.d.ts +9 -1
  113. package/dist/types/core/redirect-patterns.d.ts +18 -0
  114. package/dist/types/core/relative-files.d.ts +31 -0
  115. package/dist/types/core/schema.d.ts +267 -7
  116. package/dist/types/core/sources/normalize.d.ts +101 -9
  117. package/dist/types/core/sources/types.d.ts +16 -0
  118. package/dist/types/core/static-files.d.ts +10 -0
  119. package/dist/types/core/static-host.d.ts +42 -0
  120. package/dist/types/core/svg-images.d.ts +26 -0
  121. package/dist/types/core/syntax-diagnostics.d.ts +14 -0
  122. package/dist/types/core/types.d.ts +42 -1
  123. package/dist/types/deploy/generated-files.d.ts +41 -0
  124. package/dist/types/deploy/redirects.d.ts +21 -7
  125. package/dist/types/markdown/code-title.d.ts +9 -5
  126. package/dist/types/markdown/directives.d.ts +8 -0
  127. package/dist/types/markdown/fence-language.d.ts +51 -0
  128. package/dist/types/markdown/fence-meta.d.ts +5 -0
  129. package/dist/types/markdown/github-alerts.d.ts +35 -0
  130. package/dist/types/openapi/asyncapi.d.ts +6 -5
  131. package/dist/types/openapi/checks.d.ts +10 -5
  132. package/dist/types/openapi/model.d.ts +55 -8
  133. package/dist/types/openapi/parse.d.ts +4 -1
  134. package/dist/types/sources/filesystem.d.ts +14 -4
  135. package/dist/types/sources/mdx-remote.d.ts +6 -3
  136. package/dist/types/sources/registry.d.ts +3 -3
  137. package/dist/types/theme/color.d.ts +33 -0
  138. package/dist/types/theme/palette.d.ts +122 -0
  139. package/docs/01-quickstart.mdx +1 -1
  140. package/docs/02-deployment.mdx +23 -8
  141. package/docs/04-migrating.mdx +16 -4
  142. package/docs/advanced/changelog.mdx +27 -1
  143. package/docs/advanced/skills.mdx +1 -1
  144. package/docs/cli/audit.mdx +1 -1
  145. package/docs/cli/doctor.mdx +2 -2
  146. package/docs/cli/evals.mdx +1 -1
  147. package/docs/cli/index.mdx +4 -2
  148. package/docs/cli/validate.mdx +10 -7
  149. package/docs/configuration/analytics.mdx +2 -0
  150. package/docs/configuration/customization.mdx +3 -1
  151. package/docs/configuration/index.mdx +2 -2
  152. package/docs/configuration/theming.mdx +5 -1
  153. package/docs/content/components.mdx +26 -6
  154. package/docs/content/frontmatter.mdx +1 -1
  155. package/docs/content/includes.mdx +6 -2
  156. package/docs/content/index.mdx +11 -1
  157. package/docs/content/islands.mdx +2 -0
  158. package/docs/content/meta.mdx +9 -3
  159. package/docs/content/navigation.mdx +14 -6
  160. package/docs/content/sources/obsidian.mdx +1 -1
  161. package/docs/content/sources/remote-mdx.mdx +3 -1
  162. package/docs/content/syntax.mdx +76 -8
  163. package/docs/content/variables.mdx +3 -1
  164. package/docs/discoverability/agent-discovery.mdx +1 -1
  165. package/docs/discoverability/json-api.mdx +1 -1
  166. package/docs/discoverability/llms-txt.mdx +1 -1
  167. package/docs/discoverability/markdown.mdx +2 -2
  168. package/docs/discoverability/open-graph.mdx +1 -1
  169. package/docs/discoverability/sitemap-and-robots.mdx +1 -1
  170. package/docs/references/graphql.mdx +2 -0
  171. package/docs/references/openapi.mdx +45 -7
  172. package/package.json +10 -9
  173. package/skills/blume/SKILL.md +2 -2
  174. package/skills/blume-migrate/SKILL.md +49 -27
  175. package/skills/blume-migrate/references/docsify.md +262 -0
  176. package/skills/blume-migrate/references/docus.md +298 -0
  177. package/skills/blume-migrate/references/docusaurus.md +3 -3
  178. package/skills/blume-migrate/references/fern.md +327 -0
  179. package/skills/blume-migrate/references/fumadocs.md +1 -1
  180. package/skills/blume-migrate/references/gitbook.md +267 -0
  181. package/skills/blume-migrate/references/github-wiki.md +259 -0
  182. package/skills/blume-migrate/references/jekyll.md +253 -0
  183. package/skills/blume-migrate/references/mdbook.md +256 -0
  184. package/skills/blume-migrate/references/mintlify.md +5 -5
  185. package/skills/blume-migrate/references/mkdocs.md +236 -0
  186. package/skills/blume-migrate/references/monorepo.md +20 -8
  187. package/skills/blume-migrate/references/nextra.md +2 -2
  188. package/skills/blume-migrate/references/readme.md +257 -0
  189. package/skills/blume-migrate/references/redocly.md +198 -0
  190. package/skills/blume-migrate/references/starlight.md +3 -3
  191. package/skills/blume-migrate/references/vitepress.md +204 -0
  192. package/skills/blume-migrate/references/vuepress.md +271 -0
  193. package/skills/blume-migrate/scripts/docsify-codemod.mjs +2387 -0
  194. package/skills/blume-migrate/scripts/docus-codemod.mjs +2542 -0
  195. package/skills/blume-migrate/scripts/fern-codemod.mjs +2633 -0
  196. package/skills/blume-migrate/scripts/github-wiki-codemod.mjs +2808 -0
  197. package/skills/blume-migrate/scripts/include-excerpts.mjs +649 -0
  198. package/skills/blume-migrate/scripts/jekyll-codemod.mjs +3649 -0
  199. package/skills/blume-migrate/scripts/mintlify-codemod.mjs +17 -13
  200. package/skills/blume-migrate/scripts/mkdocs-codemod.mjs +2526 -0
  201. package/skills/blume-migrate/scripts/operation-routes.mjs +508 -0
  202. package/skills/blume-migrate/scripts/pin-heading-ids.mjs +1049 -0
  203. package/skills/blume-migrate/scripts/readme-codemod.mjs +4139 -0
  204. package/skills/blume-migrate/scripts/vitepress-codemod.mjs +1511 -0
  205. package/src/ai/changelog-components.ts +24 -0
  206. package/src/ai/changelog-markdown.ts +45 -41
  207. package/src/ai/component-markdown.ts +22 -9
  208. package/src/ai/llms.ts +36 -5
  209. package/src/ai/markdown.ts +2 -2
  210. package/src/ai/openapi-components.ts +25 -9
  211. package/src/ai/operation-details.ts +208 -0
  212. package/src/ai/relative-links.ts +48 -8
  213. package/src/ai/serializers.ts +7 -6
  214. package/src/ai/site-skill.ts +6 -2
  215. package/src/analytics/head.ts +11 -5
  216. package/src/analytics/script.ts +13 -3
  217. package/src/astro/generate.ts +32 -6
  218. package/src/astro/index.ts +1 -0
  219. package/src/astro/integration.ts +27 -1
  220. package/src/astro/mdx-source-errors.ts +46 -0
  221. package/src/astro/templates.ts +89 -185
  222. package/src/audit/checks/redirects.ts +5 -1
  223. package/src/audit/redirects.ts +36 -19
  224. package/src/audit/report.ts +22 -9
  225. package/src/audit/run.ts +12 -28
  226. package/src/audit/terms.ts +23 -0
  227. package/src/audit/url.ts +2 -2
  228. package/src/cli/build-failure.ts +256 -7
  229. package/src/cli/command-meta.ts +1 -1
  230. package/src/cli/commands/audit.ts +1 -1
  231. package/src/cli/commands/build.ts +12 -3
  232. package/src/cli/commands/check.ts +13 -2
  233. package/src/cli/commands/dev.ts +1 -1
  234. package/src/cli/commands/doctor.ts +4 -2
  235. package/src/cli/commands/init.ts +3 -3
  236. package/src/cli/commands/preview.ts +17 -1
  237. package/src/cli/commands/validate.ts +22 -10
  238. package/src/cli/prepare.ts +1 -1
  239. package/src/cli/preview-pages.ts +161 -0
  240. package/src/cli/unknown-flags.ts +1 -42
  241. package/src/components/code-copy.ts +51 -0
  242. package/src/components/code-language.ts +75 -0
  243. package/src/components/content/AccordionItem.astro +16 -1
  244. package/src/components/content/Callout.astro +11 -1
  245. package/src/components/content/Changelog.astro +189 -0
  246. package/src/components/content/CodeBlock.astro +8 -11
  247. package/src/components/content/Tabs.astro +16 -2
  248. package/src/components/content/YouTube.astro +6 -4
  249. package/src/components/content/code-block.ts +33 -0
  250. package/src/components/content/content-strings.ts +5 -1
  251. package/src/components/content/inline-markdown.ts +35 -8
  252. package/src/components/content/youtube.ts +49 -7
  253. package/src/components/layout/Analytics.astro +5 -1
  254. package/src/components/layout/NavTree.astro +8 -3
  255. package/src/components/layout/RootLayout.astro +18 -31
  256. package/src/components/layout/nav-utils.ts +14 -0
  257. package/src/components/layout/search/pagefind.ts +2 -1
  258. package/src/components/openapi/Operation.astro +4 -0
  259. package/src/components/openapi/PanelTabs.astro +9 -3
  260. package/src/components/openapi/RequestBody.astro +42 -8
  261. package/src/components/openapi/RequestPanel.astro +34 -53
  262. package/src/components/openapi/example-panels.ts +110 -0
  263. package/src/components/openapi/helpers.ts +195 -20
  264. package/src/components/openapi/operation-model.ts +63 -26
  265. package/src/components/openapi/request.ts +13 -0
  266. package/src/components/openapi/snippets.ts +14 -2
  267. package/src/core/alert-diagnostics.ts +89 -0
  268. package/src/core/builtin-tags.ts +76 -0
  269. package/src/core/changelog-list.ts +87 -0
  270. package/src/core/closest-match.ts +41 -0
  271. package/src/core/code-fence-diagnostics.ts +267 -0
  272. package/src/core/code-fences.ts +43 -7
  273. package/src/core/component-diagnostics.ts +65 -12
  274. package/src/core/config-input.ts +1 -1
  275. package/src/core/config.ts +46 -1
  276. package/src/core/content-assets.ts +64 -144
  277. package/src/core/diagnostics.ts +36 -3
  278. package/src/core/directive-diagnostics.ts +265 -47
  279. package/src/core/former-routes.ts +46 -0
  280. package/src/core/git-ignored.ts +53 -0
  281. package/src/core/github.ts +5 -4
  282. package/src/core/heading-markers.ts +156 -2
  283. package/src/core/hidden-pages.ts +64 -0
  284. package/src/core/includes.ts +181 -41
  285. package/src/core/last-modified.ts +47 -10
  286. package/src/core/links.ts +438 -83
  287. package/src/core/load-module.ts +98 -9
  288. package/src/core/manifest.ts +12 -9
  289. package/src/core/markdown-mirrors.ts +52 -0
  290. package/src/core/mdx-elements.ts +153 -0
  291. package/src/core/mdx-syntax.ts +377 -0
  292. package/src/core/meta-diagnostics.ts +134 -0
  293. package/src/core/meta.ts +154 -55
  294. package/src/core/nav-diagnostics.ts +16 -4
  295. package/src/core/navigation.ts +70 -10
  296. package/src/core/ordering-prefix.ts +22 -2
  297. package/src/core/pinned-ids.ts +141 -0
  298. package/src/core/project-graph.ts +221 -29
  299. package/src/core/redirect-patterns.ts +41 -0
  300. package/src/core/relative-files.ts +145 -0
  301. package/src/core/schema.ts +17 -3
  302. package/src/core/sources/mdx-remote.ts +75 -14
  303. package/src/core/sources/normalize.ts +885 -179
  304. package/src/core/sources/notion.ts +5 -4
  305. package/src/core/sources/obsidian.ts +2 -5
  306. package/src/core/sources/types.ts +17 -0
  307. package/src/core/static-files.ts +40 -0
  308. package/src/core/static-host.ts +125 -0
  309. package/src/core/svg-images.ts +98 -0
  310. package/src/core/syntax-diagnostics.ts +491 -0
  311. package/src/core/types.ts +43 -1
  312. package/src/deploy/artifacts.ts +2 -28
  313. package/src/deploy/generated-files.ts +128 -0
  314. package/src/deploy/platforms/vercel.ts +25 -1
  315. package/src/deploy/redirects.ts +43 -16
  316. package/src/deploy/sitemap.ts +2 -1
  317. package/src/markdown/base-links.ts +87 -6
  318. package/src/markdown/code-title.ts +29 -13
  319. package/src/markdown/content-assets.ts +210 -0
  320. package/src/markdown/directives.ts +69 -5
  321. package/src/markdown/fence-language.ts +106 -0
  322. package/src/markdown/fence-meta.ts +42 -0
  323. package/src/markdown/github-alerts.ts +172 -0
  324. package/src/markdown/heading-anchors.ts +265 -56
  325. package/src/markdown/include.ts +30 -3
  326. package/src/markdown/index.ts +145 -40
  327. package/src/markdown/prompt-text.ts +95 -0
  328. package/src/markdown/relative-links.ts +37 -2
  329. package/src/markdown/route-snapshot.ts +22 -12
  330. package/src/markdown/svg-fallback.ts +51 -0
  331. package/src/markdown/title-heading.ts +134 -0
  332. package/src/migrate/migrate.ts +127 -2
  333. package/src/og/card.ts +14 -4
  334. package/src/openapi/asyncapi.ts +14 -6
  335. package/src/openapi/checks.ts +160 -15
  336. package/src/openapi/model.ts +172 -33
  337. package/src/openapi/parse.ts +13 -4
  338. package/src/openapi/render-mdx.ts +55 -9
  339. package/src/openapi/source.ts +87 -6
  340. package/src/registry/eject.ts +0 -1
  341. package/src/search/documents.ts +10 -2
  342. package/src/sources/filesystem.ts +28 -3
  343. package/src/sources/mdx-remote.ts +7 -15
  344. package/src/theme/color.ts +14 -0
  345. package/src/theme/entry.ts +22 -1
  346. package/src/theme/palette.ts +74 -1
  347. package/dist/cli/chunk-0pmb4tr4.js.map +0 -35
  348. package/dist/cli/chunk-0w6hs479.js.map +0 -10
  349. package/dist/cli/chunk-150jk7km.js +0 -52
  350. package/dist/cli/chunk-150jk7km.js.map +0 -10
  351. package/dist/cli/chunk-36bxs9c7.js.map +0 -10
  352. package/dist/cli/chunk-53jqw8z0.js +0 -89
  353. package/dist/cli/chunk-53jqw8z0.js.map +0 -10
  354. package/dist/cli/chunk-60hz265r.js.map +0 -10
  355. package/dist/cli/chunk-desvm72z.js.map +0 -14
  356. package/dist/cli/chunk-dpy8qdjf.js.map +0 -17
  357. package/dist/cli/chunk-es8h0v3j.js +0 -441
  358. package/dist/cli/chunk-es8h0v3j.js.map +0 -11
  359. package/dist/cli/chunk-kdpzw38a.js.map +0 -11
  360. package/dist/cli/chunk-nbyvgnnm.js.map +0 -36
  361. package/dist/cli/chunk-s0bdnc7v.js.map +0 -10
  362. package/dist/cli/chunk-twy7psdz.js.map +0 -10
  363. package/dist/cli/chunk-ydp3065p.js +0 -64
  364. package/dist/cli/chunk-ydp3065p.js.map +0 -10
  365. /package/dist/cli/{chunk-74wfhv79.js.map → chunk-05f21r8h.js.map} +0 -0
  366. /package/dist/cli/{chunk-9qzgg6mj.js.map → chunk-1cm0h819.js.map} +0 -0
  367. /package/dist/cli/{chunk-ms9z66nz.js.map → chunk-4rftmttv.js.map} +0 -0
  368. /package/dist/cli/{chunk-hvcxng5f.js.map → chunk-7tekknev.js.map} +0 -0
  369. /package/dist/cli/{chunk-bxwhtvw8.js.map → chunk-ahc5gc9h.js.map} +0 -0
  370. /package/dist/cli/{chunk-tfycddbt.js.map → chunk-bjk964fp.js.map} +0 -0
  371. /package/dist/cli/{chunk-dqhg54mr.js.map → chunk-dmx6cezx.js.map} +0 -0
  372. /package/dist/cli/{chunk-ave1wcbr.js.map → chunk-m9bp2hc1.js.map} +0 -0
  373. /package/dist/cli/{chunk-58bt3hag.js.map → chunk-mrvh4c88.js.map} +0 -0
  374. /package/dist/cli/{chunk-1f882900.js.map → chunk-th0pgaj5.js.map} +0 -0
  375. /package/dist/cli/{chunk-dhwtqnnd.js.map → chunk-vnbvhgmd.js.map} +0 -0
  376. /package/dist/cli/{chunk-j1x92mx9.js.map → chunk-w6e455pz.js.map} +0 -0
  377. /package/dist/cli/{chunk-y4msrwm9.js.map → chunk-xgq4eytj.js.map} +0 -0
@@ -12,11 +12,13 @@ import {
12
12
  buildFileRouteIndex,
13
13
  isIndexFileName,
14
14
  resolveRelativeHref,
15
+ resolveRootFileHref,
15
16
  routeOfLinkedFile,
16
17
  } from "../core/links.ts";
17
18
  import type { RelativeLinkBase } from "../core/links.ts";
18
19
  import { localizeHref, servesRoute } from "../core/locale-links.ts";
19
20
  import type { BlumeProject } from "../core/project-graph.ts";
21
+ import { resolveDocsCollection } from "../core/sources/collection.ts";
20
22
  import { extractLinks } from "../core/sources/normalize.ts";
21
23
 
22
24
  /**
@@ -33,7 +35,9 @@ import { extractLinks } from "../core/sources/normalize.ts";
33
35
  * `basePath` prefix, a public file (`/spec.pdf`) or image the
34
36
  * `deployment.base` alone, and, on a page in a prefixed locale, a page link
35
37
  * that locale's copy of the route when it is served
36
- * (`components/layout/LocaleLinks.astro`). Inline links, images, component
38
+ * (`components/layout/LocaleLinks.astro`). A root-relative link to a content
39
+ * file (`/guide/new.md`) lands on that file's page, as on the rendered page
40
+ * (`resolveRootFileHref`). Inline links, images, component
37
41
  * `href`s, and reference definitions are rewritten; fenced and inline code,
38
42
  * relative images and asset links, and external URLs are left as written.
39
43
  */
@@ -64,6 +68,13 @@ const MAYBE_RELATIVE =
64
68
  const MAYBE_PAGE_LINK =
65
69
  /\]\([\t ]*<?(?![a-z][\d+.a-z-]*:|\/\/|#)|^ {0,3}\[[^\]\n]+\]:[\t ]*<?(?![a-z][\d+.a-z-]*:|\/\/|#)|\shref=["'](?![a-z][\d+.a-z-]*:|\/\/|#)/imu;
66
70
 
71
+ /**
72
+ * Whether a text could hold a root-relative link to a Markdown file
73
+ * (`[x](/guide/new.md)`), which lands on that file's page whatever the base.
74
+ */
75
+ const MAYBE_ROOT_FILE =
76
+ /(?:\]\(|\]:|\shref=["'])[\t ]*<?\/(?!\/)[^\s"'()<>]*\.mdx?\b/imu;
77
+
67
78
  interface Splice {
68
79
  column: number;
69
80
  length: number;
@@ -85,11 +96,12 @@ const spliceLine = (line: string, splices: readonly Splice[]): string => {
85
96
  /**
86
97
  * Every routed splice in `text`, by 0-based line: links, images, and
87
98
  * reference definitions, as `extractLinks` finds them. An image target goes
88
- * through `imaged`, everything else through `routed`.
99
+ * through `imaged`, everything else through `routed`, told whether it's a
100
+ * raw HTML element's.
89
101
  */
90
102
  const collectSplices = (
91
103
  text: string,
92
- routed: (target: string) => string | undefined,
104
+ routed: (target: string, raw: boolean) => string | undefined,
93
105
  imaged: (target: string) => string | undefined
94
106
  ): Map<number, Splice[]> => {
95
107
  const splices = new Map<number, Splice[]>();
@@ -97,11 +109,13 @@ const collectSplices = (
97
109
  splices.set(index, [...(splices.get(index) ?? []), splice]);
98
110
  };
99
111
  for (const link of extractLinks(text)) {
100
- const route = (link.image ? imaged : routed)(link.target);
112
+ const route = link.image
113
+ ? imaged(link.target)
114
+ : routed(link.target, link.raw === true);
101
115
  if (route !== undefined) {
102
116
  add(link.line - 1, {
103
117
  column: link.column - 1,
104
- length: link.target.length,
118
+ length: link.sourceLength ?? link.target.length,
105
119
  text: route,
106
120
  });
107
121
  }
@@ -120,6 +134,10 @@ export const relativeLinkRewriter = (
120
134
  ): RelativeLinkRewriter => {
121
135
  const { basePath, deployment, i18n } = project.config;
122
136
  const deployBase = normalizeBasePath(deployment.options.base);
137
+ const contentRoot = resolveDocsCollection(
138
+ project.config,
139
+ project.context.root
140
+ ).base;
123
141
  const localeTokens = i18n
124
142
  ? ["$", ...i18n.locales.map((locale) => locale.code)]
125
143
  : [];
@@ -179,7 +197,10 @@ export const relativeLinkRewriter = (
179
197
  deployBase !== "" || basePath !== "" || localize !== undefined;
180
198
  if (
181
199
  !(page.sourcePath || rootLinks) ||
182
- !(rootLinks ? MAYBE_PAGE_LINK : MAYBE_RELATIVE).test(text)
200
+ !(
201
+ (rootLinks ? MAYBE_PAGE_LINK : MAYBE_RELATIVE).test(text) ||
202
+ MAYBE_ROOT_FILE.test(text)
203
+ )
183
204
  ) {
184
205
  return text;
185
206
  }
@@ -197,8 +218,27 @@ export const relativeLinkRewriter = (
197
218
  const href = localize ? localizeHref(based, localize) : based;
198
219
  return href === target ? undefined : href;
199
220
  };
200
- const routed = (target: string): string | undefined =>
201
- isInternalPath(target) ? rooted(target) : relative?.(target);
221
+ // A root-relative link naming a content file (`/guide/new.md`) means
222
+ // that file's page, as a relative one does; a raw `<a href>` keeps it,
223
+ // as the rendered page's does.
224
+ const rootFile = (target: string): string | undefined => {
225
+ const route = resolveRootFileHref(target, {
226
+ contentRoot,
227
+ deployBase,
228
+ routeOfFile: (file) => fileRoutes.bySource.get(file),
229
+ });
230
+ if (route === undefined) {
231
+ return undefined;
232
+ }
233
+ const based = mountBasePath(deployBase, route);
234
+ return localize ? localizeHref(based, localize) : based;
235
+ };
236
+ const routed = (target: string, raw: boolean): string | undefined => {
237
+ if (!isInternalPath(target)) {
238
+ return relative?.(target);
239
+ }
240
+ return (raw ? undefined : rootFile(target)) ?? rooted(target);
241
+ };
202
242
  // An image is always a file: `public/` (or a generated asset endpoint),
203
243
  // served under the deployment base but never `basePath`. A relative one
204
244
  // is left to `core/content-assets.ts`.
@@ -1,5 +1,6 @@
1
1
  import type { BlumeProject } from "../core/project-graph.ts";
2
2
  import { isOpenApiSource } from "../openapi/source.ts";
3
+ import { changelogComponentSerializers } from "./changelog-components.ts";
3
4
  import type { ComponentMarkdown } from "./component-markdown.ts";
4
5
  import { exampleComponentSerializers } from "./component-markdown.ts";
5
6
  import { openapiComponentSerializers } from "./openapi-components.ts";
@@ -8,18 +9,18 @@ import { openapiComponentSerializers } from "./openapi-components.ts";
8
9
  * Every serializer a project brings to a downlevel pass, layered once for all
9
10
  * the agent surfaces (`<route>.md`, llms-full.txt, the search and assistant
10
11
  * corpora): the built-in families that read project data — examples, then the
11
- * API reference — under the user's `agents.markdownComponents`, which is spread
12
- * last so an entry of the same name still wins. One layering, so a new family
13
- * or a new surface cannot leave one consumer printing raw JSX.
12
+ * API reference, then the changelog index — under the user's
13
+ * `agents.markdownComponents`, which is spread last so an entry of the same
14
+ * name still wins. One layering, so a new family or a new surface cannot leave
15
+ * one consumer printing raw JSX.
14
16
  */
15
- export const projectComponentSerializers = (
16
- project: Pick<BlumeProject, "config" | "examples" | "sources">
17
- ) =>
17
+ export const projectComponentSerializers = (project: BlumeProject) =>
18
18
  ({
19
19
  ...exampleComponentSerializers(project.examples ?? {}),
20
20
  ...openapiComponentSerializers(
21
21
  project.sources.find(isOpenApiSource)?.openApiData() ?? {},
22
22
  project.config.deployment.options.base
23
23
  ),
24
+ ...changelogComponentSerializers(project),
24
25
  ...project.config.agents.markdownComponents,
25
26
  }) satisfies Record<string, ComponentMarkdown>;
@@ -6,6 +6,8 @@ import {
6
6
  } from "../core/base-path.ts";
7
7
  import { CHANGELOG_INDEX_ROUTE } from "../core/changelog-index.ts";
8
8
  import { discoverPagesSync } from "../core/custom-pages.ts";
9
+ import { isHiddenPage } from "../core/hidden-pages.ts";
10
+ import { metaDescription } from "../core/manifest.ts";
9
11
  import type { BlumeProject } from "../core/project-graph.ts";
10
12
  import { absoluteUrl } from "../core/site-url.ts";
11
13
  import type { NavNode, PageRecord } from "../core/types.ts";
@@ -67,7 +69,7 @@ const mappedPages = (project: BlumeProject): PageRecord[] => {
67
69
  !(
68
70
  page.meta.ai.exclude ||
69
71
  page.meta.draft ||
70
- page.meta.sidebar.hidden ||
72
+ isHiddenPage(page, project.graph) ||
71
73
  page.meta.seo.noindex ||
72
74
  page.version !== "" ||
73
75
  page.source.name === "openapi" ||
@@ -104,7 +106,9 @@ class PageMap {
104
106
  return [];
105
107
  }
106
108
  this.#listed.add(route);
107
- const summary = page.description ? `: ${page.description}` : "";
109
+ // As `llms.txt` lists it: the page's meta description.
110
+ const description = metaDescription(page);
111
+ const summary = description ? `: ${description}` : "";
108
112
  return [`- [${linkText(page.title)}](${this.#url(route)})${summary}`];
109
113
  }
110
114
 
@@ -50,7 +50,8 @@ export type HeadNode =
50
50
  */
51
51
  // oxlint-disable-next-line complexity -- each adapter has one exhaustive, type-narrowed dispatch case
52
52
  const adapterScripts = (
53
- adapter: Exclude<AnalyticsAdapter, { kind: "vercel" }>
53
+ adapter: Exclude<AnalyticsAdapter, { kind: "vercel" }>,
54
+ base: string
54
55
  ): HeadScript[] => {
55
56
  switch (adapter.kind) {
56
57
  case "adobe": {
@@ -114,7 +115,7 @@ const adapterScripts = (
114
115
  return segmentHead(adapter.options);
115
116
  }
116
117
  default: {
117
- return scriptHead(adapter.options);
118
+ return scriptHead(adapter.options, base);
118
119
  }
119
120
  }
120
121
  };
@@ -122,9 +123,14 @@ const adapterScripts = (
122
123
  /**
123
124
  * Map the configured adapters to what `Analytics.astro` renders, in declared
124
125
  * order. A second `vercel()` is dropped — two copies of the component would
125
- * count every pageview twice — so the first one keeps its position.
126
+ * count every pageview twice — so the first one keeps its position. `base` is
127
+ * the deployment base a `script()` adapter's root-relative `src` is served
128
+ * under.
126
129
  */
127
- export const analyticsHead = (adapters: AnalyticsAdapter[]): HeadNode[] => {
130
+ export const analyticsHead = (
131
+ adapters: AnalyticsAdapter[],
132
+ base = "/"
133
+ ): HeadNode[] => {
128
134
  const nodes: HeadNode[] = [];
129
135
  let hasVercel = false;
130
136
  for (const adapter of adapters) {
@@ -134,7 +140,7 @@ export const analyticsHead = (adapters: AnalyticsAdapter[]): HeadNode[] => {
134
140
  nodes.push({ props: adapter.options, type: "vercel" });
135
141
  }
136
142
  } else {
137
- for (const tag of adapterScripts(adapter)) {
143
+ for (const tag of adapterScripts(adapter, base)) {
138
144
  nodes.push({ ...tag, type: "script" });
139
145
  }
140
146
  }
@@ -2,6 +2,7 @@ import { z } from "zod";
2
2
 
3
3
  import type { AdapterDescriptor } from "../core/adapter.ts";
4
4
  import { adapterDescriptorSchema } from "../core/adapter.ts";
5
+ import { normalizeBasePath, withBasePath } from "../core/base-path.ts";
5
6
  import type { HeadScript } from "./head.ts";
6
7
 
7
8
  /** Options for {@link script}; set exactly one of `src` or `content`. */
@@ -46,8 +47,17 @@ export const script = (options: ScriptOptions): ScriptAdapter => ({
46
47
  runtimeDeps: [],
47
48
  });
48
49
 
49
- /** The tag. Explicit `src`/`strategy` win over a same-named spread attribute. */
50
- export const scriptHead = (options: ScriptOptions): HeadScript[] => {
50
+ /**
51
+ * The tag. Explicit `src`/`strategy` win over a same-named spread attribute.
52
+ * A root-relative `src` (`/js/x.js`, a file in `public/`) is served under the
53
+ * deployment `base`, so it gets the base the way a link does; one already
54
+ * under it is left alone, and absolute and protocol-relative URLs pass
55
+ * through.
56
+ */
57
+ export const scriptHead = (
58
+ options: ScriptOptions,
59
+ base: string
60
+ ): HeadScript[] => {
51
61
  const attributes: HeadScript["attributes"] = { ...options.attributes };
52
62
  if (!options.src) {
53
63
  return [{ attributes, content: options.content ?? "" }];
@@ -55,6 +65,6 @@ export const scriptHead = (options: ScriptOptions): HeadScript[] => {
55
65
  if (options.strategy) {
56
66
  attributes[options.strategy] = true;
57
67
  }
58
- attributes.src = options.src;
68
+ attributes.src = withBasePath(normalizeBasePath(base), options.src);
59
69
  return [{ attributes, content: null }];
60
70
  };
@@ -37,6 +37,7 @@ import { normalizeBasePath, withBasePath } from "../core/base-path.ts";
37
37
  import { withChangelogIndexText } from "../core/changelog-index.ts";
38
38
  import {
39
39
  missingExampleDiagnostics,
40
+ unknownPropDiagnostics,
40
41
  validateUsedComponents,
41
42
  } from "../core/component-diagnostics.ts";
42
43
  import {
@@ -46,7 +47,7 @@ import {
46
47
  import type { ComponentOverrideAnalysis } from "../core/component-overrides.ts";
47
48
  import {
48
49
  collectContentAssets,
49
- rewriteRelativeImages,
50
+ rewriteRelativeAssets,
50
51
  } from "../core/content-assets.ts";
51
52
  import type {
52
53
  BlumeBanner,
@@ -55,8 +56,13 @@ import type {
55
56
  BlumeFavicon,
56
57
  BlumeLogo,
57
58
  } from "../core/data.ts";
58
- import { BlumeError } from "../core/diagnostics.ts";
59
+ import {
60
+ BlumeError,
61
+ enrichDiagnostic,
62
+ formatDiagnostic,
63
+ } from "../core/diagnostics.ts";
59
64
  import { writeTextAtomic } from "../core/fs-atomic.ts";
65
+ import { gitIgnoredPaths } from "../core/git-ignored.ts";
60
66
  import {
61
67
  apiUrl as githubApiUrl,
62
68
  editBaseUrl as githubEditBaseUrl,
@@ -79,6 +85,7 @@ import { trimChar } from "../core/trim.ts";
79
85
  import { resolveTsconfigAliases } from "../core/tsconfig-aliases.ts";
80
86
  import type { Diagnostic, Navigation } from "../core/types.ts";
81
87
  import { getBlumeVersion } from "../core/version.ts";
88
+ import { servedFiles } from "../deploy/generated-files.ts";
82
89
  import { buildRssFeeds, renderRssFeed } from "../deploy/rss.ts";
83
90
  import {
84
91
  languageIconCss,
@@ -697,7 +704,7 @@ export const collectStaged = (project: BlumeProject): Map<string, string> => {
697
704
  // Point it at the served original instead — the same rewrite the
698
705
  // agent-facing Markdown gets.
699
706
  const text = page.sourcePath
700
- ? rewriteRelativeImages({
707
+ ? rewriteRelativeAssets({
701
708
  deployBase: project.config.deployment.options.base,
702
709
  projectRoot: project.context.root,
703
710
  source: page.body.text,
@@ -1120,9 +1127,22 @@ export const buildRuntimeData = (project: BlumeProject): string => {
1120
1127
  const editBase = github ? githubEditBaseUrl(github) : null;
1121
1128
  const logo = resolveLogo(project);
1122
1129
  const ogLogo = resolveOgMark(project, logo?.svg);
1130
+ // Files git ignores (a generated reference in a gitignored folder) are
1131
+ // never in the repository, so an edit link would 404. One git call covers
1132
+ // every page an edit link is built for.
1133
+ const ignored = editBase
1134
+ ? gitIgnoredPaths(
1135
+ context.root,
1136
+ manifest.routes.flatMap((route) =>
1137
+ route.editUrl === undefined && route.sourcePath
1138
+ ? [route.sourcePath]
1139
+ : []
1140
+ )
1141
+ )
1142
+ : new Set<string>();
1123
1143
 
1124
1144
  const editUrlFor = (sourcePath?: string): string | null => {
1125
- if (!(editBase && sourcePath)) {
1145
+ if (!(editBase && sourcePath) || ignored.has(sourcePath)) {
1126
1146
  return null;
1127
1147
  }
1128
1148
  const rel = relative(context.root, sourcePath).split("\\").join("/");
@@ -2194,6 +2214,7 @@ export const generateRuntime = async (
2194
2214
  context,
2195
2215
  filesystem: hasFilesystemSource,
2196
2216
  staged: hasStaged,
2217
+ unparsable: project.unparsable,
2197
2218
  })
2198
2219
  ),
2199
2220
  write(
@@ -2308,7 +2329,6 @@ export const generateRuntime = async (
2308
2329
  exportEpub,
2309
2330
  exportPdf,
2310
2331
  needsReact,
2311
- staged: hasStaged,
2312
2332
  })
2313
2333
  );
2314
2334
  }
@@ -2425,7 +2445,8 @@ export const generateRuntime = async (
2425
2445
  ...[
2426
2446
  ...validateNavTargets(
2427
2447
  project.graph.navigation,
2428
- navTargetRoutes(project, pages)
2448
+ navTargetRoutes(project, pages),
2449
+ servedFiles(project)
2429
2450
  ),
2430
2451
  ...validateSearchPopularIcons(config.search.popular),
2431
2452
  ].map(diagnosticWarning)
@@ -2449,6 +2470,11 @@ export const generateRuntime = async (
2449
2470
  context.root,
2450
2471
  knownComponentTags
2451
2472
  ).map(diagnosticWarning),
2473
+ // Printed whole, like a scan diagnostic, so the line it names shows.
2474
+ ...unknownPropDiagnostics(project.graph.pages, knownComponentTags).map(
2475
+ (diagnostic) =>
2476
+ formatDiagnostic(enrichDiagnostic(diagnostic), context.root)
2477
+ ),
2452
2478
  ...dependencyWarnings
2453
2479
  );
2454
2480
  if (hasScalarReferences(config)) {
@@ -2,6 +2,7 @@ export { withAdapterRoot } from "./adapter-root.ts";
2
2
  export { generateRuntime, prerenderDepsPlugin } from "./generate.ts";
3
3
  export { includeHmrPlugin } from "./include-hmr.ts";
4
4
  export { withIncludeRefresh } from "./include-refresh.ts";
5
+ export { mdxSourceErrorsPlugin } from "./mdx-source-errors.ts";
5
6
  export { variablesVitePlugin } from "./variables.ts";
6
7
  export type { GenerateResult } from "./generate.ts";
7
8
  export {
@@ -1,10 +1,12 @@
1
+ import { Server } from "node:http";
1
2
  import type { IncomingMessage, ServerResponse } from "node:http";
2
3
  import { fileURLToPath } from "node:url";
3
4
 
4
- import type { AstroIntegration } from "astro";
5
+ import type { AstroConfig, AstroIntegration } from "astro";
5
6
  import { join, relative, resolve } from "pathe";
6
7
 
7
8
  import { loadEnvFiles } from "../cli/env.ts";
9
+ import { normalizeBasePath } from "../core/base-path.ts";
8
10
  import type { CustomPageRoute } from "../core/custom-pages.ts";
9
11
  import { enrichDiagnostic } from "../core/diagnostics.ts";
10
12
  import { POWERED_BY_HEADERS } from "../core/powered-by.ts";
@@ -15,6 +17,11 @@ import {
15
17
  requestPath,
16
18
  } from "../core/redirect-patterns.ts";
17
19
  import type { CompiledRedirect } from "../core/redirect-patterns.ts";
20
+ import {
21
+ answerRequestsFirst,
22
+ publicFolder,
23
+ trailingSlashAnswer,
24
+ } from "../core/static-host.ts";
18
25
  import type { Diagnostic } from "../core/types.ts";
19
26
  import { publishBuildArtifacts } from "../deploy/artifacts.ts";
20
27
  import type { ArtifactLogger } from "../deploy/artifacts.ts";
@@ -492,6 +499,9 @@ export const blumeIntegration = (
492
499
  // The Astro root, kept for the build-artifacts scan: `astro:build:done`
493
500
  // receives no config.
494
501
  let astroRoot: URL | null = null;
502
+ // What the dev server's trailing-slash handling needs from the config
503
+ // (see `core/static-host.ts`): the base the URLs carry, and `public/`.
504
+ let staticHost: Pick<AstroConfig, "base" | "publicDir"> | null = null;
495
505
  return {
496
506
  hooks: {
497
507
  "astro:build:done": async ({ dir, logger }) => {
@@ -511,6 +521,7 @@ export const blumeIntegration = (
511
521
  },
512
522
  "astro:config:done": ({ config, injectTypes }) => {
513
523
  astroRoot = config.root;
524
+ staticHost = config;
514
525
  const from = fileURLToPath(
515
526
  codegenDir ?? defaultCodegenDir(config.root)
516
527
  );
@@ -587,6 +598,21 @@ export const blumeIntegration = (
587
598
  route: "",
588
599
  });
589
600
  }
601
+ // A trailing slash is answered the way a static host answers it,
602
+ // ahead of Astro's own middleware, which would 404 it (see
603
+ // `core/static-host.ts`). They're unshifted after this hook runs,
604
+ // so this goes on the HTTP server instead.
605
+ if (staticHost && server.httpServer instanceof Server) {
606
+ const base = normalizeBasePath(staticHost.base);
607
+ const isPublicFolder = publicFolder(
608
+ fileURLToPath(staticHost.publicDir)
609
+ );
610
+ answerRequestsFirst(
611
+ server.httpServer,
612
+ (request) => trailingSlashAnswer(request, base, isPublicFolder),
613
+ options.poweredBy === false ? {} : POWERED_BY_HEADERS
614
+ );
615
+ }
590
616
  },
591
617
  },
592
618
  name: "blume",
@@ -0,0 +1,46 @@
1
+ /**
2
+ * A Vite plugin that names an `.mdx` page's file on an error the page throws
3
+ * while it renders. A `{…}` expression that reads a name nothing defines
4
+ * (`{user.name}`, or `{{version}}` on a site without that variable) compiles,
5
+ * then throws a `ReferenceError` from inside the page's module, and Astro pins
6
+ * it on the route that rendered it: the catch-all every page shares. Setting
7
+ * the error's `id`, as Vite does for a module that fails, points it at the
8
+ * page's file instead, so the build report can find the expression (see
9
+ * `cli/build-failure.ts`) and the dev overlay shows the page.
10
+ *
11
+ * It runs after `@astrojs/mdx` and wraps the module's `MDXContent`, the
12
+ * function the compiler emits for the body and Astro's `Content` export calls
13
+ * by name. A module without one is left alone.
14
+ */
15
+
16
+ /** The Vite plugin slice this needs (structurally typed, like Blume's other plugins). */
17
+ export interface MdxSourceErrorsPlugin {
18
+ enforce: "post";
19
+ name: string;
20
+ transform: (code: string, id: string) => { code: string; map: null } | null;
21
+ }
22
+
23
+ const MDX_CONTENT = /^\s*function MDXContent\(/mu;
24
+
25
+ /** The statement that wraps `MDXContent` so its errors carry `id`. */
26
+ const wrapContent = (id: string): string => `
27
+ MDXContent = ((render, id) => function MDXContent(props) {
28
+ try {
29
+ return render(props);
30
+ } catch (error) {
31
+ if (error instanceof Error && !("id" in error)) error.id = id;
32
+ throw error;
33
+ }
34
+ })(MDXContent, ${JSON.stringify(id)});`;
35
+
36
+ export const mdxSourceErrorsPlugin = (): MdxSourceErrorsPlugin => ({
37
+ enforce: "post",
38
+ name: "blume:mdx-source-errors",
39
+ // A query (`?astroPropagatedAssets`) marks another module made from the
40
+ // same file, which holds no body.
41
+ transform(code, id) {
42
+ return id.endsWith(".mdx") && MDX_CONTENT.test(code)
43
+ ? { code: code + wrapContent(id), map: null }
44
+ : null;
45
+ },
46
+ });