blume 2.0.1 → 2.0.3

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 (492) hide show
  1. package/CHANGELOG.md +147 -0
  2. package/dist/cli/{chunk-qwsrynx5.js → chunk-1d7ve1dm.js} +38 -19
  3. package/dist/cli/{chunk-qwsrynx5.js.map → chunk-1d7ve1dm.js.map} +4 -4
  4. package/dist/cli/{chunk-s6jhgk0q.js → chunk-2eytanqx.js} +2 -2
  5. package/dist/cli/{chunk-kdp5q7ke.js → chunk-2hsdwb9n.js} +18 -19
  6. package/dist/cli/{chunk-kdp5q7ke.js.map → chunk-2hsdwb9n.js.map} +2 -2
  7. package/dist/cli/{chunk-hdpx1tax.js → chunk-2z928egk.js} +5 -5
  8. package/dist/cli/{chunk-jwyddg7y.js → chunk-35d4wj9f.js} +30 -24
  9. package/dist/cli/chunk-35d4wj9f.js.map +15 -0
  10. package/dist/cli/{chunk-ah61y8py.js → chunk-364znk6q.js} +2 -2
  11. package/dist/cli/{chunk-jts8mvcz.js → chunk-3em5wd2y.js} +25 -6
  12. package/dist/cli/{chunk-jts8mvcz.js.map → chunk-3em5wd2y.js.map} +3 -3
  13. package/dist/cli/{chunk-s1p84fyh.js → chunk-5f86nr5m.js} +63 -22
  14. package/dist/cli/chunk-5f86nr5m.js.map +11 -0
  15. package/dist/cli/{chunk-2hn4b8z7.js → chunk-5m5nmvyq.js} +170 -76
  16. package/dist/cli/chunk-5m5nmvyq.js.map +13 -0
  17. package/dist/cli/{chunk-epjnccmv.js → chunk-5xvm6tfj.js} +18 -15
  18. package/dist/cli/chunk-5xvm6tfj.js.map +10 -0
  19. package/dist/cli/{chunk-fz5wtpmh.js → chunk-6dsbexzp.js} +18 -15
  20. package/dist/cli/chunk-6dsbexzp.js.map +10 -0
  21. package/dist/cli/{chunk-vtk4a6dg.js → chunk-8ktnccpt.js} +1 -1
  22. package/dist/cli/{chunk-6hsn950k.js → chunk-9t7a85s3.js} +178 -48
  23. package/dist/cli/chunk-9t7a85s3.js.map +10 -0
  24. package/dist/cli/{chunk-fxypxtvm.js → chunk-a58773jm.js} +2 -2
  25. package/dist/cli/{chunk-mb2919y2.js → chunk-acanzt5p.js} +17 -6
  26. package/dist/cli/chunk-acanzt5p.js.map +10 -0
  27. package/dist/cli/{chunk-27g6wdth.js → chunk-akbpwfxc.js} +90 -26
  28. package/dist/cli/chunk-akbpwfxc.js.map +10 -0
  29. package/dist/cli/{chunk-wm7js3j9.js → chunk-b07cmahc.js} +2 -2
  30. package/dist/cli/{chunk-wgm7m9qk.js → chunk-c8chx29p.js} +179 -51
  31. package/dist/cli/chunk-c8chx29p.js.map +36 -0
  32. package/dist/cli/{chunk-qs4q5p4e.js → chunk-crgn1q09.js} +32 -14
  33. package/dist/cli/chunk-crgn1q09.js.map +10 -0
  34. package/dist/cli/chunk-e04dxsz1.js +39 -0
  35. package/dist/cli/chunk-e04dxsz1.js.map +10 -0
  36. package/dist/cli/{chunk-yt5n7ppj.js → chunk-ey84smr6.js} +17 -7
  37. package/dist/cli/chunk-ey84smr6.js.map +10 -0
  38. package/dist/cli/{chunk-f2z5v128.js → chunk-g4hq16wv.js} +14 -15
  39. package/dist/cli/{chunk-f2z5v128.js.map → chunk-g4hq16wv.js.map} +2 -2
  40. package/dist/cli/{chunk-fa25z98p.js → chunk-ga0pf4aj.js} +9 -8
  41. package/dist/cli/chunk-ga0pf4aj.js.map +11 -0
  42. package/dist/cli/{chunk-kpf8rrjc.js → chunk-hm3vjy5s.js} +109 -58
  43. package/dist/cli/chunk-hm3vjy5s.js.map +19 -0
  44. package/dist/cli/{chunk-fs23ddbb.js → chunk-j85vccga.js} +625 -750
  45. package/dist/cli/chunk-j85vccga.js.map +36 -0
  46. package/dist/cli/{chunk-ch6g3ar0.js → chunk-p3v96n38.js} +6 -6
  47. package/dist/cli/{chunk-ch6g3ar0.js.map → chunk-p3v96n38.js.map} +3 -3
  48. package/dist/cli/{chunk-q5163e60.js → chunk-p73c0m7w.js} +21 -19
  49. package/dist/cli/chunk-p73c0m7w.js.map +11 -0
  50. package/dist/cli/{chunk-dh8cwk36.js → chunk-pehfxfta.js} +24 -9
  51. package/dist/cli/chunk-pehfxfta.js.map +10 -0
  52. package/dist/cli/{chunk-qkqwkpte.js → chunk-pv29h0wf.js} +3688 -1313
  53. package/dist/cli/chunk-pv29h0wf.js.map +190 -0
  54. package/dist/cli/{chunk-6vm74dry.js → chunk-q58y5e6a.js} +10 -10
  55. package/dist/cli/{chunk-6vm74dry.js.map → chunk-q58y5e6a.js.map} +3 -3
  56. package/dist/cli/{chunk-zxcczpyx.js → chunk-r20tn01b.js} +1 -1
  57. package/dist/cli/{chunk-m3vmjgmq.js → chunk-r9rcc4w7.js} +16 -8
  58. package/dist/cli/chunk-r9rcc4w7.js.map +10 -0
  59. package/dist/cli/{chunk-5shv93fd.js → chunk-tkacnehg.js} +2 -2
  60. package/dist/cli/{chunk-zxh4d9vy.js → chunk-tzmab476.js} +4 -4
  61. package/dist/cli/{chunk-yw7dm696.js → chunk-vg9r4eb9.js} +24 -11
  62. package/dist/cli/chunk-vg9r4eb9.js.map +14 -0
  63. package/dist/cli/{chunk-79jhk4py.js → chunk-wrr3j9w9.js} +260 -132
  64. package/dist/cli/chunk-wrr3j9w9.js.map +35 -0
  65. package/dist/cli/{chunk-6crbhc3x.js → chunk-yfyb25rh.js} +54 -27
  66. package/dist/cli/chunk-yfyb25rh.js.map +14 -0
  67. package/dist/cli/index.js +162 -35
  68. package/dist/cli/index.js.map +4 -4
  69. package/dist/types/ai/agent-surface.d.ts +32 -0
  70. package/dist/types/ai/api-catalog.d.ts +7 -1
  71. package/dist/types/ai/ask-context.d.ts +7 -0
  72. package/dist/types/ai/component-markdown.d.ts +4 -4
  73. package/dist/types/ai/link-headers.d.ts +8 -1
  74. package/dist/types/ai/openapi-components.d.ts +5 -2
  75. package/dist/types/ai/relative-links.d.ts +11 -4
  76. package/dist/types/ai/skills.d.ts +4 -1
  77. package/dist/types/ai/static-expression.d.ts +28 -0
  78. package/dist/types/ai/tar.d.ts +1 -3
  79. package/dist/types/analytics/databuddy.d.ts +43 -0
  80. package/dist/types/analytics/index.d.ts +4 -0
  81. package/dist/types/analytics/one-dollar-stats.d.ts +48 -0
  82. package/dist/types/analytics/schema.d.ts +28 -0
  83. package/dist/types/astro/integration.d.ts +3 -2
  84. package/dist/types/cli/env.d.ts +5 -0
  85. package/dist/types/cli/init/scaffold.d.ts +19 -3
  86. package/dist/types/cli/init/starter-spec.d.ts +11 -0
  87. package/dist/types/core/base-path.d.ts +24 -1
  88. package/dist/types/core/config-input.d.ts +13 -11
  89. package/dist/types/core/config.d.ts +2 -2
  90. package/dist/types/core/directive-diagnostics.d.ts +12 -0
  91. package/dist/types/core/graph.d.ts +2 -0
  92. package/dist/types/core/heading-markers.d.ts +5 -7
  93. package/dist/types/core/i18n-ui.d.ts +31 -0
  94. package/dist/types/core/i18n.d.ts +9 -1
  95. package/dist/types/core/last-modified.d.ts +10 -0
  96. package/dist/types/core/links.d.ts +3 -1
  97. package/dist/types/core/load-module.d.ts +10 -0
  98. package/dist/types/core/locale-links.d.ts +12 -2
  99. package/dist/types/core/meta.d.ts +13 -1
  100. package/dist/types/core/nav-diagnostics.d.ts +10 -0
  101. package/dist/types/core/navigation.d.ts +38 -0
  102. package/dist/types/core/ordering-prefix.d.ts +4 -0
  103. package/dist/types/core/safe-links.d.ts +3 -1
  104. package/dist/types/core/schema.d.ts +59 -13
  105. package/dist/types/core/sources/github-releases.d.ts +5 -0
  106. package/dist/types/core/sources/lower.d.ts +38 -13
  107. package/dist/types/core/sources/normalize.d.ts +23 -2
  108. package/dist/types/core/sources/remote.d.ts +11 -1
  109. package/dist/types/core/sources/resolve.d.ts +12 -0
  110. package/dist/types/core/sources/types.d.ts +31 -0
  111. package/dist/types/core/sources/watch.d.ts +12 -5
  112. package/dist/types/core/standard-schema.d.ts +5 -0
  113. package/dist/types/core/types.d.ts +9 -0
  114. package/dist/types/deploy/adapters/node.d.ts +5 -2
  115. package/dist/types/deploy/adapters/types.d.ts +7 -0
  116. package/dist/types/deploy/artifacts.d.ts +6 -4
  117. package/dist/types/deploy/cloudflare-negotiation.d.ts +3 -2
  118. package/dist/types/deploy/headers.d.ts +36 -7
  119. package/dist/types/deploy/node-headers.d.ts +43 -8
  120. package/dist/types/deploy/platforms/netlify.d.ts +27 -2
  121. package/dist/types/deploy/platforms/node.d.ts +6 -5
  122. package/dist/types/deploy/platforms/types.d.ts +15 -0
  123. package/dist/types/deploy/platforms/vercel.d.ts +3 -2
  124. package/dist/types/deploy/redirects.d.ts +31 -15
  125. package/dist/types/deploy/vercel-negotiation.d.ts +3 -2
  126. package/dist/types/markdown/directives.d.ts +62 -0
  127. package/dist/types/markdown/features.d.ts +21 -0
  128. package/dist/types/markdown/mdast.d.ts +63 -0
  129. package/dist/types/openapi/asyncapi.d.ts +4 -2
  130. package/dist/types/openapi/model.d.ts +20 -6
  131. package/dist/types/search/sync/algolia.d.ts +3 -1
  132. package/docs/01-quickstart.mdx +3 -2
  133. package/docs/02-deployment.mdx +20 -9
  134. package/docs/08-faq.mdx +10 -3
  135. package/docs/advanced/changelog.mdx +1 -1
  136. package/docs/advanced/custom-pages.mdx +7 -5
  137. package/docs/cli/audit.mdx +19 -3
  138. package/docs/cli/doctor.mdx +2 -2
  139. package/docs/cli/evals.mdx +4 -4
  140. package/docs/cli/index.mdx +4 -1
  141. package/docs/cli/translate.mdx +4 -4
  142. package/docs/cli/version.mdx +1 -1
  143. package/docs/configuration/analytics.mdx +42 -2
  144. package/docs/configuration/assistant.mdx +1 -1
  145. package/docs/configuration/customization.mdx +6 -3
  146. package/docs/configuration/index.mdx +5 -3
  147. package/docs/configuration/search.mdx +2 -2
  148. package/docs/content/components.mdx +2 -2
  149. package/docs/content/frontmatter.mdx +5 -1
  150. package/docs/content/i18n.mdx +3 -1
  151. package/docs/content/index.mdx +8 -4
  152. package/docs/content/islands.mdx +1 -1
  153. package/docs/content/meta.mdx +7 -3
  154. package/docs/content/navigation.mdx +29 -4
  155. package/docs/content/sources.mdx +18 -16
  156. package/docs/content/syntax.mdx +14 -0
  157. package/docs/content/versioning.mdx +2 -1
  158. package/docs/discoverability/agent-discovery.mdx +22 -8
  159. package/docs/discoverability/index.mdx +4 -3
  160. package/docs/discoverability/llms-txt.mdx +2 -5
  161. package/docs/discoverability/markdown.mdx +6 -4
  162. package/docs/discoverability/mcp.mdx +4 -0
  163. package/docs/discoverability/metadata.mdx +3 -2
  164. package/docs/discoverability/open-graph.mdx +8 -4
  165. package/docs/discoverability/rss.mdx +4 -2
  166. package/docs/references/asyncapi.mdx +2 -2
  167. package/docs/references/graphql.mdx +2 -2
  168. package/docs/references/openapi.mdx +6 -4
  169. package/package.json +1 -1
  170. package/skills/blume-migrate/SKILL.md +6 -6
  171. package/skills/blume-migrate/references/docusaurus.md +6 -6
  172. package/skills/blume-migrate/references/fumadocs.md +1 -1
  173. package/skills/blume-migrate/references/mintlify.md +3 -3
  174. package/skills/blume-migrate/references/monorepo.md +1 -1
  175. package/skills/blume-migrate/references/nextra.md +2 -2
  176. package/skills/blume-migrate/references/starlight.md +5 -5
  177. package/skills/blume-migrate/scripts/mintlify-codemod.mjs +9 -4
  178. package/skills/blume-update-docs/references/audit-checklist.md +1 -1
  179. package/src/ai/agent-readability.ts +2 -2
  180. package/src/ai/agent-surface.ts +56 -0
  181. package/src/ai/ai-catalog.ts +6 -2
  182. package/src/ai/api/handlers.ts +2 -2
  183. package/src/ai/api/spec.ts +17 -4
  184. package/src/ai/api-catalog.ts +13 -3
  185. package/src/ai/ask-context.ts +14 -2
  186. package/src/ai/ask-data.ts +26 -12
  187. package/src/ai/changelog-markdown.ts +2 -2
  188. package/src/ai/component-markdown.ts +43 -37
  189. package/src/ai/link-headers.ts +22 -8
  190. package/src/ai/llms.ts +22 -10
  191. package/src/ai/markdown.ts +23 -11
  192. package/src/ai/mcp/discovery.ts +2 -2
  193. package/src/ai/mcp/query.ts +2 -2
  194. package/src/ai/mcp/server.ts +80 -9
  195. package/src/ai/openapi-components.ts +22 -6
  196. package/src/ai/relative-links.ts +99 -15
  197. package/src/ai/serializers.ts +2 -1
  198. package/src/ai/skills.ts +14 -1
  199. package/src/ai/static-expression.ts +416 -0
  200. package/src/ai/tar.ts +139 -12
  201. package/src/ai/visibility.ts +45 -14
  202. package/src/analytics/databuddy.ts +67 -0
  203. package/src/analytics/head.ts +8 -0
  204. package/src/analytics/index.ts +7 -0
  205. package/src/analytics/one-dollar-stats.ts +86 -0
  206. package/src/analytics/posthog.ts +21 -3
  207. package/src/analytics/schema.ts +4 -0
  208. package/src/astro/generate.ts +72 -28
  209. package/src/astro/include-hmr.ts +31 -12
  210. package/src/astro/include-refresh.ts +19 -8
  211. package/src/astro/integration.ts +108 -14
  212. package/src/astro/runtime-modules.ts +28 -13
  213. package/src/astro/templates.ts +139 -57
  214. package/src/audit/catalog.ts +2 -2
  215. package/src/audit/checks/assets.ts +25 -5
  216. package/src/audit/checks/content.ts +20 -2
  217. package/src/audit/checks/i18n.ts +46 -8
  218. package/src/audit/checks/indexability.ts +39 -19
  219. package/src/audit/checks/links.ts +22 -1
  220. package/src/audit/checks/llms.ts +6 -3
  221. package/src/audit/checks/network.ts +3 -1
  222. package/src/audit/checks/og-image.ts +10 -0
  223. package/src/audit/checks/robots.ts +6 -1
  224. package/src/audit/checks/sitemap.ts +56 -31
  225. package/src/audit/checks/social.ts +21 -2
  226. package/src/audit/crawl.ts +88 -15
  227. package/src/audit/graph.ts +3 -1
  228. package/src/audit/report.ts +54 -17
  229. package/src/audit/run.ts +13 -9
  230. package/src/audit/snapshot.ts +5 -0
  231. package/src/audit/types.ts +18 -0
  232. package/src/audit/url.ts +37 -6
  233. package/src/cli/args.ts +32 -0
  234. package/src/cli/build-failure.ts +50 -0
  235. package/src/cli/commands/audit.ts +11 -1
  236. package/src/cli/commands/build.ts +19 -5
  237. package/src/cli/commands/check.ts +2 -0
  238. package/src/cli/commands/doctor.ts +3 -1
  239. package/src/cli/commands/eval.ts +20 -18
  240. package/src/cli/commands/init.ts +15 -5
  241. package/src/cli/commands/preview.ts +15 -0
  242. package/src/cli/commands/sync.ts +2 -0
  243. package/src/cli/commands/translate.ts +18 -18
  244. package/src/cli/commands/upgrade.ts +11 -0
  245. package/src/cli/commands/validate.ts +3 -1
  246. package/src/cli/dev-lock.ts +157 -37
  247. package/src/cli/eject-scripts.ts +32 -7
  248. package/src/cli/env.ts +12 -1
  249. package/src/cli/init/scaffold.ts +117 -11
  250. package/src/cli/init/starter-spec.ts +235 -0
  251. package/src/cli/report-format.ts +11 -6
  252. package/src/components/colors.ts +19 -0
  253. package/src/components/content/AccordionItem.astro +26 -22
  254. package/src/components/content/Badge.astro +7 -12
  255. package/src/components/content/Card.astro +2 -2
  256. package/src/components/content/Component.astro +11 -5
  257. package/src/components/content/Expandable.astro +5 -1
  258. package/src/components/content/Frame.astro +2 -7
  259. package/src/components/content/GithubInfo.astro +12 -2
  260. package/src/components/content/Prompt.astro +2 -7
  261. package/src/components/content/Tab.astro +0 -1
  262. package/src/components/content/Tabs.astro +58 -5
  263. package/src/components/content/Tile.astro +1 -1
  264. package/src/components/content/Tooltip.astro +69 -7
  265. package/src/components/content/Tree.astro +7 -2
  266. package/src/components/content/TypeTable.astro +10 -5
  267. package/src/components/content/Update.astro +8 -2
  268. package/src/components/content/auto-type-table.ts +4 -1
  269. package/src/components/content/badge-color.ts +20 -0
  270. package/src/components/content/base-href.ts +14 -22
  271. package/src/components/content/inline-markdown.ts +27 -7
  272. package/src/components/copy-feedback.ts +35 -8
  273. package/src/components/islands/assistant.tsx +37 -6
  274. package/src/components/islands/base-path.ts +47 -10
  275. package/src/components/islands/hooks.ts +42 -21
  276. package/src/components/islands/webmcp.ts +16 -10
  277. package/src/components/layout/Banner.astro +23 -4
  278. package/src/components/layout/Breadcrumbs.astro +5 -2
  279. package/src/components/layout/DiscoveryLinks.astro +9 -5
  280. package/src/components/layout/Header.astro +23 -10
  281. package/src/components/layout/LanguageSwitcher.astro +2 -2
  282. package/src/components/layout/Logo.astro +5 -0
  283. package/src/components/layout/NavSelector.astro +8 -3
  284. package/src/components/layout/NavTabMenu.astro +133 -0
  285. package/src/components/layout/NavTree.astro +31 -12
  286. package/src/components/layout/NavTreeCache.astro +5 -2
  287. package/src/components/layout/NavTreeScript.astro +45 -5
  288. package/src/components/layout/PageActions.astro +4 -3
  289. package/src/components/layout/PageLayout.astro +28 -13
  290. package/src/components/layout/Pagination.astro +3 -3
  291. package/src/components/layout/ReferenceLayout.astro +4 -1
  292. package/src/components/layout/RootLayout.astro +25 -12
  293. package/src/components/layout/Search.astro +38 -14
  294. package/src/components/layout/VersionBanner.astro +2 -2
  295. package/src/components/layout/analytics-client.ts +14 -0
  296. package/src/components/layout/toc-active.ts +41 -0
  297. package/src/components/layout/toc-element.ts +8 -14
  298. package/src/components/openapi/ApiTagOperations.astro +2 -2
  299. package/src/components/openapi/AsyncApiOperation.astro +7 -4
  300. package/src/components/openapi/GraphqlChip.astro +2 -2
  301. package/src/components/openapi/GraphqlType.astro +11 -3
  302. package/src/components/openapi/MessageComposer.astro +1 -1
  303. package/src/components/openapi/Operation.astro +23 -5
  304. package/src/components/openapi/PanelTabs.astro +4 -1
  305. package/src/components/openapi/Playground.astro +8 -2
  306. package/src/components/openapi/RequestPanel.astro +13 -6
  307. package/src/components/openapi/SchemaProperty.astro +11 -33
  308. package/src/components/openapi/SchemaTable.astro +34 -52
  309. package/src/components/openapi/async.ts +38 -6
  310. package/src/components/openapi/helpers.ts +100 -12
  311. package/src/components/openapi/message-composer.ts +14 -1
  312. package/src/components/openapi/message-model.ts +12 -2
  313. package/src/components/openapi/message.ts +21 -3
  314. package/src/components/openapi/operation-model.ts +119 -17
  315. package/src/components/openapi/panel.ts +31 -5
  316. package/src/components/openapi/param-style.ts +181 -0
  317. package/src/components/openapi/playground-client.ts +110 -23
  318. package/src/components/openapi/playground-schema.ts +25 -6
  319. package/src/components/openapi/request.ts +192 -26
  320. package/src/components/openapi/schema-tree.ts +209 -0
  321. package/src/components/openapi/snippets.ts +113 -19
  322. package/src/components/openapi/validate-json.ts +1 -1
  323. package/src/components/openapi/ws-client.ts +18 -2
  324. package/src/core/base-path.ts +69 -8
  325. package/src/core/config-input.ts +13 -11
  326. package/src/core/config.ts +18 -4
  327. package/src/core/diagnostics.ts +219 -30
  328. package/src/core/directive-diagnostics.ts +99 -0
  329. package/src/core/frontmatter.ts +21 -18
  330. package/src/core/graph.ts +120 -11
  331. package/src/core/heading-markers.ts +5 -18
  332. package/src/core/i18n-ui.ts +39 -2
  333. package/src/core/i18n.ts +44 -5
  334. package/src/core/last-modified.ts +25 -3
  335. package/src/core/links.ts +7 -4
  336. package/src/core/load-module.ts +20 -0
  337. package/src/core/locale-links.ts +22 -18
  338. package/src/core/manifest.ts +3 -2
  339. package/src/core/meta.ts +89 -12
  340. package/src/core/nav-diagnostics.ts +56 -1
  341. package/src/core/navigation.ts +272 -83
  342. package/src/core/ordering-prefix.ts +27 -0
  343. package/src/core/project-graph.ts +50 -6
  344. package/src/core/safe-href.ts +53 -1
  345. package/src/core/safe-links.ts +11 -2
  346. package/src/core/schema.ts +94 -18
  347. package/src/core/sources/assets.ts +83 -41
  348. package/src/core/sources/contentful-rich-text.ts +28 -20
  349. package/src/core/sources/contentful.ts +25 -12
  350. package/src/core/sources/filesystem.ts +25 -3
  351. package/src/core/sources/github-releases.ts +131 -11
  352. package/src/core/sources/lexical.ts +30 -20
  353. package/src/core/sources/lower.ts +276 -56
  354. package/src/core/sources/mdx-remote.ts +52 -16
  355. package/src/core/sources/normalize.ts +456 -119
  356. package/src/core/sources/notion.ts +77 -34
  357. package/src/core/sources/obsidian.ts +40 -9
  358. package/src/core/sources/payload.ts +1 -0
  359. package/src/core/sources/portable-text.ts +85 -49
  360. package/src/core/sources/remote.ts +18 -2
  361. package/src/core/sources/resolve.ts +52 -33
  362. package/src/core/sources/sanity.ts +1 -0
  363. package/src/core/sources/strapi-blocks.ts +28 -19
  364. package/src/core/sources/strapi.ts +1 -0
  365. package/src/core/sources/types.ts +31 -0
  366. package/src/core/sources/watch.ts +20 -7
  367. package/src/core/standard-schema.ts +10 -6
  368. package/src/core/types.ts +9 -0
  369. package/src/core/ui-packs/ar.ts +13 -0
  370. package/src/core/ui-packs/bg.ts +13 -0
  371. package/src/core/ui-packs/bn.ts +13 -0
  372. package/src/core/ui-packs/ca.ts +13 -0
  373. package/src/core/ui-packs/cs.ts +13 -0
  374. package/src/core/ui-packs/da.ts +13 -0
  375. package/src/core/ui-packs/de.ts +13 -0
  376. package/src/core/ui-packs/el.ts +13 -0
  377. package/src/core/ui-packs/es.ts +13 -0
  378. package/src/core/ui-packs/fa.ts +13 -0
  379. package/src/core/ui-packs/fi.ts +13 -0
  380. package/src/core/ui-packs/fr.ts +13 -0
  381. package/src/core/ui-packs/he.ts +13 -0
  382. package/src/core/ui-packs/hi.ts +13 -0
  383. package/src/core/ui-packs/hr.ts +13 -0
  384. package/src/core/ui-packs/hu.ts +13 -0
  385. package/src/core/ui-packs/id.ts +13 -0
  386. package/src/core/ui-packs/it.ts +13 -0
  387. package/src/core/ui-packs/ja.ts +13 -0
  388. package/src/core/ui-packs/ko.ts +13 -0
  389. package/src/core/ui-packs/nl.ts +13 -0
  390. package/src/core/ui-packs/no.ts +13 -0
  391. package/src/core/ui-packs/pl.ts +13 -0
  392. package/src/core/ui-packs/pt-br.ts +13 -0
  393. package/src/core/ui-packs/pt.ts +13 -0
  394. package/src/core/ui-packs/ro.ts +13 -0
  395. package/src/core/ui-packs/ru.ts +13 -0
  396. package/src/core/ui-packs/sk.ts +13 -0
  397. package/src/core/ui-packs/sr.ts +13 -0
  398. package/src/core/ui-packs/sv.ts +13 -0
  399. package/src/core/ui-packs/th.ts +13 -0
  400. package/src/core/ui-packs/tr.ts +13 -0
  401. package/src/core/ui-packs/uk.ts +13 -0
  402. package/src/core/ui-packs/vi.ts +13 -0
  403. package/src/core/ui-packs/zh-tw.ts +13 -0
  404. package/src/core/ui-packs/zh.ts +13 -0
  405. package/src/core/version-cut.ts +69 -17
  406. package/src/core/versions.ts +4 -1
  407. package/src/deploy/adapters/node.ts +5 -2
  408. package/src/deploy/adapters/registry.ts +2 -1
  409. package/src/deploy/adapters/types.ts +13 -1
  410. package/src/deploy/artifacts.ts +52 -11
  411. package/src/deploy/cloudflare-negotiation.ts +27 -16
  412. package/src/deploy/headers.ts +75 -55
  413. package/src/deploy/node-headers.ts +148 -27
  414. package/src/deploy/platforms/cloudflare.ts +13 -3
  415. package/src/deploy/platforms/netlify.ts +83 -5
  416. package/src/deploy/platforms/node.ts +8 -5
  417. package/src/deploy/platforms/static.ts +2 -0
  418. package/src/deploy/platforms/types.ts +15 -0
  419. package/src/deploy/platforms/vercel.ts +10 -3
  420. package/src/deploy/redirects.ts +68 -21
  421. package/src/deploy/robots.ts +2 -2
  422. package/src/deploy/rss.ts +4 -3
  423. package/src/deploy/sitemap.ts +7 -5
  424. package/src/deploy/vercel-negotiation.ts +35 -3
  425. package/src/eval/agents.ts +10 -2
  426. package/src/eval/run.ts +25 -0
  427. package/src/markdown/base-links.ts +74 -29
  428. package/src/markdown/directives.ts +242 -36
  429. package/src/markdown/features.ts +17 -0
  430. package/src/markdown/index.ts +13 -9
  431. package/src/markdown/mdast.ts +5 -2
  432. package/src/markdown/relative-links.ts +15 -27
  433. package/src/markdown/route-snapshot.ts +37 -0
  434. package/src/og/card.ts +149 -9
  435. package/src/og/derive.ts +156 -5
  436. package/src/og/index.ts +1 -0
  437. package/src/openapi/asyncapi.ts +4 -2
  438. package/src/openapi/graphql-build.ts +28 -2
  439. package/src/openapi/model.ts +99 -27
  440. package/src/openapi/proxy.ts +63 -10
  441. package/src/openapi/render-mdx.ts +51 -3
  442. package/src/registry/eject.ts +297 -43
  443. package/src/search/adapters/version-scope.ts +30 -0
  444. package/src/search/documents.ts +89 -27
  445. package/src/search/popular.ts +2 -1
  446. package/src/search/sync/algolia.ts +36 -2
  447. package/src/seo/jsonld.ts +7 -3
  448. package/src/sources/registry.ts +5 -0
  449. package/src/theme/entry.ts +11 -4
  450. package/src/translate/agents.ts +6 -1
  451. package/src/translate/ledger.ts +26 -3
  452. package/src/translate/meta.ts +76 -24
  453. package/src/translate/run.ts +14 -8
  454. package/src/translate/validate.ts +14 -2
  455. package/src/translate/work-list.ts +91 -19
  456. package/src/upgrade/upgrade.ts +36 -4
  457. package/dist/cli/chunk-27g6wdth.js.map +0 -10
  458. package/dist/cli/chunk-2hn4b8z7.js.map +0 -12
  459. package/dist/cli/chunk-6crbhc3x.js.map +0 -14
  460. package/dist/cli/chunk-6hsn950k.js.map +0 -10
  461. package/dist/cli/chunk-79jhk4py.js.map +0 -35
  462. package/dist/cli/chunk-82bbrxdn.js +0 -51
  463. package/dist/cli/chunk-82bbrxdn.js.map +0 -10
  464. package/dist/cli/chunk-abh8yjkn.js +0 -31
  465. package/dist/cli/chunk-abh8yjkn.js.map +0 -10
  466. package/dist/cli/chunk-ce574jw2.js +0 -23
  467. package/dist/cli/chunk-ce574jw2.js.map +0 -10
  468. package/dist/cli/chunk-dh8cwk36.js.map +0 -10
  469. package/dist/cli/chunk-epjnccmv.js.map +0 -10
  470. package/dist/cli/chunk-fa25z98p.js.map +0 -11
  471. package/dist/cli/chunk-fs23ddbb.js.map +0 -35
  472. package/dist/cli/chunk-fz5wtpmh.js.map +0 -10
  473. package/dist/cli/chunk-jwyddg7y.js.map +0 -15
  474. package/dist/cli/chunk-kpf8rrjc.js.map +0 -19
  475. package/dist/cli/chunk-m3vmjgmq.js.map +0 -10
  476. package/dist/cli/chunk-mb2919y2.js.map +0 -10
  477. package/dist/cli/chunk-q5163e60.js.map +0 -11
  478. package/dist/cli/chunk-qkqwkpte.js.map +0 -182
  479. package/dist/cli/chunk-qs4q5p4e.js.map +0 -10
  480. package/dist/cli/chunk-s1p84fyh.js.map +0 -10
  481. package/dist/cli/chunk-wgm7m9qk.js.map +0 -36
  482. package/dist/cli/chunk-yt5n7ppj.js.map +0 -10
  483. package/dist/cli/chunk-yw7dm696.js.map +0 -14
  484. /package/dist/cli/{chunk-s6jhgk0q.js.map → chunk-2eytanqx.js.map} +0 -0
  485. /package/dist/cli/{chunk-hdpx1tax.js.map → chunk-2z928egk.js.map} +0 -0
  486. /package/dist/cli/{chunk-ah61y8py.js.map → chunk-364znk6q.js.map} +0 -0
  487. /package/dist/cli/{chunk-vtk4a6dg.js.map → chunk-8ktnccpt.js.map} +0 -0
  488. /package/dist/cli/{chunk-fxypxtvm.js.map → chunk-a58773jm.js.map} +0 -0
  489. /package/dist/cli/{chunk-wm7js3j9.js.map → chunk-b07cmahc.js.map} +0 -0
  490. /package/dist/cli/{chunk-zxcczpyx.js.map → chunk-r20tn01b.js.map} +0 -0
  491. /package/dist/cli/{chunk-5shv93fd.js.map → chunk-tkacnehg.js.map} +0 -0
  492. /package/dist/cli/{chunk-zxh4d9vy.js.map → chunk-tzmab476.js.map} +0 -0
@@ -43,9 +43,20 @@ export const sk: UIStringsOverride = {
43
43
  title: "Zoznam zmien",
44
44
  },
45
45
  content: {
46
+ code: "Kód",
46
47
  copyColor: "Kopírovať farbu {name} {value}",
47
48
  copyPrompt: "Kopírovať prompt",
49
+ default: "Predvolené",
48
50
  diagramError: "Tento diagram sa nepodarilo vykresliť.",
51
+ forks: "Forky",
52
+ preview: "Náhľad",
53
+ prop: "Vlastnosť",
54
+ selectTab: "Vybrať kartu",
55
+ showMore: "Zobraziť viac",
56
+ stars: "Hviezdičky",
57
+ tab: "Karta {n}",
58
+ type: "Typ",
59
+ update: "Aktualizácia",
49
60
  },
50
61
  feedback: {
51
62
  no: "Nie",
@@ -87,8 +98,10 @@ export const sk: UIStringsOverride = {
87
98
  assistantHint: "Získajte okamžitú odpoveď od AI",
88
99
  button: "Hľadať",
89
100
  devOnly: "Vyhľadávanie je dostupné v produkčnom builde.",
101
+ docs: "Dokumentácia",
90
102
  error: "Niečo sa pokazilo. Skúste to znova.",
91
103
  label: "Prehľadať dokumentáciu",
104
+ latest: "najnovšia",
92
105
  navigate: "navigácia",
93
106
  noResults: "Nenašli sa žiadne výsledky.",
94
107
  open: "otvoriť",
@@ -43,9 +43,20 @@ export const sr: UIStringsOverride = {
43
43
  title: "Дневник измена",
44
44
  },
45
45
  content: {
46
+ code: "Код",
46
47
  copyColor: "Копирај боју {name} {value}",
47
48
  copyPrompt: "Копирај упит",
49
+ default: "Подразумевано",
48
50
  diagramError: "Није могуће приказати овај дијаграм.",
51
+ forks: "Форкови",
52
+ preview: "Преглед",
53
+ prop: "Својство",
54
+ selectTab: "Изабери картицу",
55
+ showMore: "Прикажи више",
56
+ stars: "Звездице",
57
+ tab: "Картица {n}",
58
+ type: "Тип",
59
+ update: "Ажурирање",
49
60
  },
50
61
  feedback: {
51
62
  no: "Не",
@@ -87,8 +98,10 @@ export const sr: UIStringsOverride = {
87
98
  assistantHint: "Добијте тренутан одговор од AI-ја",
88
99
  button: "Претражи",
89
100
  devOnly: "Претрага је доступна у продукцијској верзији.",
101
+ docs: "Документација",
90
102
  error: "Нешто је пошло наопако. Покушајте поново.",
91
103
  label: "Претражи документацију",
104
+ latest: "најновија",
92
105
  navigate: "навигација",
93
106
  noResults: "Нема резултата.",
94
107
  open: "отвори",
@@ -44,9 +44,20 @@ export const sv: UIStringsOverride = {
44
44
  title: "Ändringslogg",
45
45
  },
46
46
  content: {
47
+ code: "Kod",
47
48
  copyColor: "Kopiera färgen {name} {value}",
48
49
  copyPrompt: "Kopiera prompt",
50
+ default: "Standard",
49
51
  diagramError: "Det här diagrammet kunde inte visas.",
52
+ forks: "Forkar",
53
+ preview: "Förhandsgranskning",
54
+ prop: "Egenskap",
55
+ selectTab: "Välj flik",
56
+ showMore: "Visa mer",
57
+ stars: "Stjärnor",
58
+ tab: "Flik {n}",
59
+ type: "Typ",
60
+ update: "Uppdatering",
50
61
  },
51
62
  feedback: {
52
63
  no: "Nej",
@@ -88,8 +99,10 @@ export const sv: UIStringsOverride = {
88
99
  assistantHint: "Få ett omedelbart svar från AI",
89
100
  button: "Sök",
90
101
  devOnly: "Sökning är tillgänglig i produktionsbygget.",
102
+ docs: "Dokumentation",
91
103
  error: "Något gick fel. Försök igen.",
92
104
  label: "Sök i dokumentationen",
105
+ latest: "senaste",
93
106
  navigate: "navigera",
94
107
  noResults: "Inga resultat hittades.",
95
108
  open: "öppna",
@@ -43,9 +43,20 @@ export const th: UIStringsOverride = {
43
43
  title: "บันทึกการเปลี่ยนแปลง",
44
44
  },
45
45
  content: {
46
+ code: "โค้ด",
46
47
  copyColor: "คัดลอกสี {name} {value}",
47
48
  copyPrompt: "คัดลอกพรอมต์",
49
+ default: "ค่าเริ่มต้น",
48
50
  diagramError: "ไม่สามารถแสดงไดอะแกรมนี้ได้",
51
+ forks: "ฟอร์ก",
52
+ preview: "ตัวอย่าง",
53
+ prop: "คุณสมบัติ",
54
+ selectTab: "เลือกแท็บ",
55
+ showMore: "แสดงเพิ่มเติม",
56
+ stars: "ดาว",
57
+ tab: "แท็บ {n}",
58
+ type: "ชนิด",
59
+ update: "อัปเดต",
49
60
  },
50
61
  feedback: {
51
62
  no: "ไม่",
@@ -87,8 +98,10 @@ export const th: UIStringsOverride = {
87
98
  assistantHint: "รับคำตอบทันทีจาก AI",
88
99
  button: "ค้นหา",
89
100
  devOnly: "การค้นหาพร้อมใช้งานในบิลด์โปรดักชัน",
101
+ docs: "เอกสาร",
90
102
  error: "เกิดข้อผิดพลาดบางอย่าง โปรดลองอีกครั้ง",
91
103
  label: "ค้นหาเอกสาร",
104
+ latest: "ล่าสุด",
92
105
  navigate: "นำทาง",
93
106
  noResults: "ไม่พบผลลัพธ์",
94
107
  open: "เปิด",
@@ -44,9 +44,20 @@ export const tr: UIStringsOverride = {
44
44
  title: "Değişiklik günlüğü",
45
45
  },
46
46
  content: {
47
+ code: "Kod",
47
48
  copyColor: "Rengi kopyala: {name} {value}",
48
49
  copyPrompt: "İstemi kopyala",
50
+ default: "Varsayılan",
49
51
  diagramError: "Bu diyagram görüntülenemedi.",
52
+ forks: "Çatallar",
53
+ preview: "Önizleme",
54
+ prop: "Özellik",
55
+ selectTab: "Sekme seç",
56
+ showMore: "Daha fazla göster",
57
+ stars: "Yıldızlar",
58
+ tab: "Sekme {n}",
59
+ type: "Tür",
60
+ update: "Güncelleme",
50
61
  },
51
62
  feedback: {
52
63
  no: "Hayır",
@@ -88,8 +99,10 @@ export const tr: UIStringsOverride = {
88
99
  assistantHint: "Yapay zekâdan anında yanıt alın",
89
100
  button: "Ara",
90
101
  devOnly: "Arama, üretim derlemesinde kullanılabilir.",
102
+ docs: "Belgeler",
91
103
  error: "Bir şeyler ters gitti. Lütfen tekrar deneyin.",
92
104
  label: "Belgelerde ara",
105
+ latest: "en son",
93
106
  navigate: "gezin",
94
107
  noResults: "Sonuç bulunamadı.",
95
108
  open: "aç",
@@ -44,9 +44,20 @@ export const uk: UIStringsOverride = {
44
44
  title: "Журнал змін",
45
45
  },
46
46
  content: {
47
+ code: "Код",
47
48
  copyColor: "Скопіювати колір {name} {value}",
48
49
  copyPrompt: "Скопіювати промпт",
50
+ default: "За замовчуванням",
49
51
  diagramError: "Не вдалося відобразити цю діаграму.",
52
+ forks: "Форки",
53
+ preview: "Попередній перегляд",
54
+ prop: "Властивість",
55
+ selectTab: "Вибрати вкладку",
56
+ showMore: "Показати більше",
57
+ stars: "Зірки",
58
+ tab: "Вкладка {n}",
59
+ type: "Тип",
60
+ update: "Оновлення",
50
61
  },
51
62
  feedback: {
52
63
  no: "Ні",
@@ -88,8 +99,10 @@ export const uk: UIStringsOverride = {
88
99
  assistantHint: "Отримайте миттєву відповідь від ШІ",
89
100
  button: "Пошук",
90
101
  devOnly: "Пошук доступний у production-збірці.",
102
+ docs: "Документація",
91
103
  error: "Щось пішло не так. Спробуйте ще раз.",
92
104
  label: "Пошук у документації",
105
+ latest: "остання",
93
106
  navigate: "навігація",
94
107
  noResults: "Нічого не знайдено.",
95
108
  open: "відкрити",
@@ -43,9 +43,20 @@ export const vi: UIStringsOverride = {
43
43
  title: "Nhật ký thay đổi",
44
44
  },
45
45
  content: {
46
+ code: "Mã",
46
47
  copyColor: "Sao chép màu {name} {value}",
47
48
  copyPrompt: "Sao chép prompt",
49
+ default: "Mặc định",
48
50
  diagramError: "Không thể hiển thị sơ đồ này.",
51
+ forks: "Fork",
52
+ preview: "Xem trước",
53
+ prop: "Thuộc tính",
54
+ selectTab: "Chọn tab",
55
+ showMore: "Hiển thị thêm",
56
+ stars: "Sao",
57
+ tab: "Tab {n}",
58
+ type: "Kiểu",
59
+ update: "Cập nhật",
49
60
  },
50
61
  feedback: {
51
62
  no: "Không",
@@ -87,8 +98,10 @@ export const vi: UIStringsOverride = {
87
98
  assistantHint: "Nhận câu trả lời tức thì từ AI",
88
99
  button: "Tìm kiếm",
89
100
  devOnly: "Tìm kiếm có sẵn trong bản dựng production.",
101
+ docs: "Tài liệu",
90
102
  error: "Đã xảy ra sự cố. Vui lòng thử lại.",
91
103
  label: "Tìm kiếm tài liệu",
104
+ latest: "mới nhất",
92
105
  navigate: "di chuyển",
93
106
  noResults: "Không tìm thấy kết quả.",
94
107
  open: "mở",
@@ -43,9 +43,20 @@ export const zhTW: UIStringsOverride = {
43
43
  title: "更新日誌",
44
44
  },
45
45
  content: {
46
+ code: "程式碼",
46
47
  copyColor: "複製顏色 {name} {value}",
47
48
  copyPrompt: "複製提示詞",
49
+ default: "預設值",
48
50
  diagramError: "無法顯示此圖表。",
51
+ forks: "複刻",
52
+ preview: "預覽",
53
+ prop: "屬性",
54
+ selectTab: "選擇分頁",
55
+ showMore: "顯示更多",
56
+ stars: "星標",
57
+ tab: "分頁 {n}",
58
+ type: "型別",
59
+ update: "更新",
49
60
  },
50
61
  feedback: {
51
62
  no: "沒有幫助",
@@ -87,8 +98,10 @@ export const zhTW: UIStringsOverride = {
87
98
  assistantHint: "從 AI 即時取得解答",
88
99
  button: "搜尋",
89
100
  devOnly: "搜尋在正式版組建中可用。",
101
+ docs: "文件",
90
102
  error: "發生了一些問題,請再試一次。",
91
103
  label: "搜尋文件",
104
+ latest: "最新",
92
105
  navigate: "導覽",
93
106
  noResults: "找不到結果。",
94
107
  open: "開啟",
@@ -43,9 +43,20 @@ export const zh: UIStringsOverride = {
43
43
  title: "更新日志",
44
44
  },
45
45
  content: {
46
+ code: "代码",
46
47
  copyColor: "复制颜色 {name} {value}",
47
48
  copyPrompt: "复制提示词",
49
+ default: "默认值",
48
50
  diagramError: "无法渲染此图表。",
51
+ forks: "复刻",
52
+ preview: "预览",
53
+ prop: "属性",
54
+ selectTab: "选择标签页",
55
+ showMore: "显示更多",
56
+ stars: "星标",
57
+ tab: "标签页 {n}",
58
+ type: "类型",
59
+ update: "更新",
49
60
  },
50
61
  feedback: {
51
62
  no: "没有帮助",
@@ -87,8 +98,10 @@ export const zh: UIStringsOverride = {
87
98
  assistantHint: "从 AI 即时获取答案",
88
99
  button: "搜索",
89
100
  devOnly: "搜索在生产构建中可用。",
101
+ docs: "文档",
90
102
  error: "出了点问题,请重试。",
91
103
  label: "搜索文档",
104
+ latest: "最新",
92
105
  navigate: "导航",
93
106
  noResults: "未找到结果。",
94
107
  open: "打开",
@@ -3,7 +3,7 @@ import { cp, readdir, readFile, rm } from "node:fs/promises";
3
3
 
4
4
  import { join, relative } from "pathe";
5
5
 
6
- import { stripBasePath } from "./base-path.ts";
6
+ import { mountBasePath, stripBasePath } from "./base-path.ts";
7
7
  import { nextFenceState } from "./code-fences.ts";
8
8
  import type { FenceState } from "./code-fences.ts";
9
9
  import { writeTextAtomic } from "./fs-atomic.ts";
@@ -45,18 +45,22 @@ export class CutError extends Error {
45
45
  // matching so replacements can splice into the real line by index (the mask
46
46
  // preserves length). Mirrors the content-assets rewriter.
47
47
  const INLINE_CODE = /`[^`]*`/gu;
48
- // A markdown link/image target or an HTML href/src attribute whose value is
49
- // root-absolute. Named groups carry the prefix (kept) and target (rewritten).
50
- const ROOT_LINK = /(?<prefix>\]\(|href="|src=")(?<target>\/[^\s"')]*)/gu;
48
+ // A root-absolute markdown link/image target, reference-style link definition
49
+ // (`[setup]: /guides/setup`, up to three spaces in, never a `[^note]:`
50
+ // footnote), or HTML href/src attribute in either quote style. Named groups
51
+ // carry the prefix (kept) and target (rewritten).
52
+ const ROOT_LINK =
53
+ /(?<prefix>\]\(|^ {0,3}\[(?!\^)[^\]]+\]:[ \t]*<?|(?:href|src)=["'])(?<target>\/[^\s"'<>)]*)/gu;
51
54
 
52
55
  /**
53
56
  * Build the link-rewrite table: every current-version route (basePath
54
- * stripped, since authors write root-absolute links as if mounted at root)
55
- * mapped to the same page's route inside the new snapshot. Only pages the
56
- * snapshot actually contains qualify — filesystem pages under the content
57
- * root. Spec-rendered references (`/api`, `/events`) and remote sources
58
- * aren't copied, so links to them keep pointing at the live pages instead of
59
- * a 404 inside the snapshot.
57
+ * stripped, since authors write root-absolute links as if mounted at root;
58
+ * a link that spells the base out is looked up without it, see
59
+ * `snapshotTarget`) mapped to the same page's route inside the new snapshot.
60
+ * Only pages the snapshot actually contains qualify — filesystem pages under
61
+ * the content root. Spec-rendered references (`/api`, `/events`) and remote
62
+ * sources aren't copied, so links to them keep pointing at the live pages
63
+ * instead of a 404 inside the snapshot.
60
64
  */
61
65
  const buildRouteRewrites = (
62
66
  project: BlumeProject,
@@ -65,6 +69,13 @@ const buildRouteRewrites = (
65
69
  const { basePath, i18n } = project.config;
66
70
  const { contentRoot } = project.context;
67
71
  const rewrites = new Map<string, string>();
72
+ // Under i18n, authors write links in the unprefixed form (`/guides/setup`)
73
+ // and rendering moves them into the reader's locale — a form no page is
74
+ // routed at when the default locale keeps its prefix
75
+ // (`hideDefaultLocalePrefix: false`). So it is mapped too, to the
76
+ // unprefixed snapshot route, which rendering localizes the same way. Page
77
+ // routes win where the two forms coincide.
78
+ const logical = new Map<string, string>();
68
79
  for (const page of project.graph.pages) {
69
80
  // `sourcePath` marks a page backed by a local file, which excludes
70
81
  // generated and remote pages; the content-root check below excludes local
@@ -81,17 +92,52 @@ const buildRouteRewrites = (
81
92
  ) {
82
93
  continue;
83
94
  }
84
- const logical = versionizeRoute(page.versionKey, id);
95
+ const snapshot = versionizeRoute(page.versionKey, id);
85
96
  rewrites.set(
86
97
  stripBasePath(basePath, page.route),
87
- i18n ? localizeRoute(logical, page.locale, i18n) : logical
98
+ i18n ? localizeRoute(snapshot, page.locale, i18n) : snapshot
88
99
  );
100
+ if (i18n) {
101
+ logical.set(page.versionKey, snapshot);
102
+ }
103
+ }
104
+ for (const [route, snapshot] of logical) {
105
+ if (!rewrites.has(route)) {
106
+ rewrites.set(route, snapshot);
107
+ }
89
108
  }
90
109
  return rewrites;
91
110
  };
92
111
 
112
+ /**
113
+ * The snapshot link a root-absolute path rewrites to, or undefined when the
114
+ * snapshot has no copy of its page. A path written with the base path by hand
115
+ * (`/docs/guides/x` under `basePath: "/docs"`) names the same page as
116
+ * `/guides/x` — rendering leaves an already-based link alone (see
117
+ * `withBasePath`) — so it is looked up without the base and keeps it.
118
+ */
119
+ const snapshotTarget = (
120
+ path: string,
121
+ rewrites: Map<string, string>,
122
+ basePath: string
123
+ ): string | undefined => {
124
+ const based =
125
+ basePath !== "" && (path === basePath || path.startsWith(`${basePath}/`));
126
+ if (!based) {
127
+ return rewrites.get(path);
128
+ }
129
+ const replacement = rewrites.get(stripBasePath(basePath, path));
130
+ return replacement === undefined
131
+ ? undefined
132
+ : mountBasePath(basePath, replacement);
133
+ };
134
+
93
135
  /** Rewrite one line's root-absolute internal links via the rewrite table. */
94
- const rewriteLine = (line: string, rewrites: Map<string, string>): string => {
136
+ const rewriteLine = (
137
+ line: string,
138
+ rewrites: Map<string, string>,
139
+ basePath: string
140
+ ): string => {
95
141
  const masked = line.replaceAll(INLINE_CODE, (span) =>
96
142
  " ".repeat(span.length)
97
143
  );
@@ -105,7 +151,7 @@ const rewriteLine = (line: string, rewrites: Map<string, string>): string => {
105
151
  const path = hash === -1 ? target : target.slice(0, hash);
106
152
  const suffix = hash === -1 ? "" : target.slice(hash);
107
153
  const bare = path !== "/" && path.endsWith("/") ? path.slice(0, -1) : path;
108
- const replacement = rewrites.get(bare);
154
+ const replacement = snapshotTarget(bare, rewrites, basePath);
109
155
  if (replacement === undefined) {
110
156
  continue;
111
157
  }
@@ -127,10 +173,12 @@ export interface SnapshotRewrite {
127
173
  * Rewrite a copied page's root-absolute internal links to their snapshot
128
174
  * equivalents, skipping fenced and inline code. Relative links need no
129
175
  * rewriting — the whole tree copies together, so they stay self-contained.
176
+ * `basePath` is the site's, for links that spell it out by hand.
130
177
  */
131
178
  export const rewriteSnapshotLinks = (
132
179
  source: string,
133
- rewrites: Map<string, string>
180
+ rewrites: Map<string, string>,
181
+ basePath = ""
134
182
  ): SnapshotRewrite => {
135
183
  let fence: FenceState = null;
136
184
  let count = 0;
@@ -141,7 +189,7 @@ export const rewriteSnapshotLinks = (
141
189
  if (inFence) {
142
190
  return line;
143
191
  }
144
- const rewrittenLine = rewriteLine(line, rewrites);
192
+ const rewrittenLine = rewriteLine(line, rewrites, basePath);
145
193
  if (rewrittenLine !== line) {
146
194
  count += 1;
147
195
  }
@@ -401,7 +449,11 @@ export const cutVersion = async (
401
449
  return;
402
450
  }
403
451
  const source = await readFile(abs, "utf-8");
404
- const { text, count } = rewriteSnapshotLinks(source, rewrites);
452
+ const { text, count } = rewriteSnapshotLinks(
453
+ source,
454
+ rewrites,
455
+ project.config.basePath
456
+ );
405
457
  if (count > 0) {
406
458
  await writeTextAtomic(abs, text);
407
459
  rewritten.push({ count, file: relative(dir, abs) });
@@ -150,9 +150,12 @@ export const versionsDiagnostics = (
150
150
  for (const page of pages) {
151
151
  // The version-looking folder is the first segment of the source-local ref
152
152
  // (e.g. `v1.0/guide.md`), not the namespaced id (`filesystem:v1.0/guide.md`).
153
- const [first] = page.source.ref.split("/");
153
+ // Only a folder can be a snapshot: a root file like `v3-migration.md` has
154
+ // no further segments.
155
+ const [first, ...rest] = page.source.ref.split("/");
154
156
  if (
155
157
  first &&
158
+ rest.length > 0 &&
156
159
  !seen.has(first) &&
157
160
  VERSION_LIKE.test(first) &&
158
161
  !configured.has(first)
@@ -7,8 +7,11 @@ export const NODE_ADAPTER_PACKAGE = "@astrojs/node";
7
7
 
8
8
  /**
9
9
  * Options for {@link node}: `output`, `site`, and `base`, plus any option of
10
- * `@astrojs/node` forwarded verbatim (`mode`, `host`, `port`, …). Blume
11
- * defaults `mode` to `"standalone"`; an option you pass wins.
10
+ * `@astrojs/node` forwarded verbatim (`mode`, `staticHeaders`, …). Blume
11
+ * defaults `mode` to `"standalone"`; an option you pass wins. `host` and
12
+ * `port` are forwarded too, but `@astrojs/node` replaces both with Astro's
13
+ * own server settings, so the standalone server listens on `localhost:4321`
14
+ * unless the `HOST` and `PORT` environment variables are set when it starts.
12
15
  */
13
16
  export type NodeOptions = DeployOptions;
14
17
 
@@ -7,6 +7,7 @@ import { netlify, netlifyAdapterSchema } from "./netlify.ts";
7
7
  import type { NetlifyAdapter } from "./netlify.ts";
8
8
  import { node, nodeAdapterSchema } from "./node.ts";
9
9
  import type { NodeAdapter } from "./node.ts";
10
+ import { siteUrlSchema } from "./types.ts";
10
11
  import type { DeployOutput, StaticDeployment } from "./types.ts";
11
12
  import { vercel, vercelAdapterSchema } from "./vercel.ts";
12
13
  import type { VercelAdapter } from "./vercel.ts";
@@ -56,7 +57,7 @@ const staticDeploymentSchema = z.strictObject(
56
57
  {
57
58
  base: z.string().optional(),
58
59
  kind: z.literal("static").optional(),
59
- site: z.url().optional(),
60
+ site: siteUrlSchema.optional(),
60
61
  },
61
62
  {
62
63
  error: (issue) => (issue.code === "unrecognized_keys" ? HINT : undefined),
@@ -59,12 +59,24 @@ export interface StaticDeployment {
59
59
  site?: string;
60
60
  }
61
61
 
62
+ /**
63
+ * `deployment.site`: an absolute http(s) URL, which always has a host. A bare
64
+ * `z.url()` takes any scheme, so `localhost:4321` (scheme `localhost:`),
65
+ * `mailto:`, and `javascript:` all passed and became the prefix of every
66
+ * sitemap entry and canonical link.
67
+ */
68
+ export const siteUrlSchema = z.url({
69
+ error:
70
+ 'Use an absolute http(s) URL with a host, like "https://docs.example.com" or "http://localhost:4321".',
71
+ protocol: /^https?$/u,
72
+ });
73
+
62
74
  /** The named options' schema; every host adapter extends it with `z.json()` passthrough. */
63
75
  export const deployOptionsSchema = z
64
76
  .object({
65
77
  base: z.string().optional(),
66
78
  output: z.enum(["static", "server"]).optional(),
67
- site: z.url().optional(),
79
+ site: siteUrlSchema.optional(),
68
80
  })
69
81
  .catchall(z.json());
70
82
 
@@ -4,6 +4,7 @@ import { mkdir, readFile, writeFile } from "node:fs/promises";
4
4
  import { dirname, join, resolve } from "pathe";
5
5
 
6
6
  import { buildAgentReadability } from "../ai/agent-readability.ts";
7
+ import { advertisedConfig, servesMcp } from "../ai/agent-surface.ts";
7
8
  import {
8
9
  AI_CATALOG_PATH,
9
10
  ARD_MANIFEST_PATH,
@@ -15,6 +16,7 @@ import { buildLlmsFiles } from "../ai/llms.ts";
15
16
  import { markdownRoutePaths } from "../ai/markdown.ts";
16
17
  import {
17
18
  AGENT_SKILLS_DIR,
19
+ AGENT_SKILLS_INDEX_PATH,
18
20
  buildSkillsIndex,
19
21
  collectSkills,
20
22
  } from "../ai/skills.ts";
@@ -23,6 +25,8 @@ import {
23
25
  buildSignaturesDirectory,
24
26
  SIGNATURES_DIRECTORY_PATH,
25
27
  } from "../ai/web-bot-auth.ts";
28
+ import { normalizeBasePath } from "../core/base-path.ts";
29
+ import { discoverPagesSync } from "../core/custom-pages.ts";
26
30
  import type { BlumeProject } from "../core/project-graph.ts";
27
31
  import type { ResolvedConfig } from "../core/schema.ts";
28
32
  import { buildSearchIndex } from "../search/build.ts";
@@ -48,10 +52,12 @@ import { buildSitemapFiles, describeSitemapFiles } from "./sitemap.ts";
48
52
  * Written from the integration's `astro:build:done` hook — Astro's channel
49
53
  * for exactly this kind of post-build work — into the directory Astro
50
54
  * reports as the client output (`dist/`, or `dist/client` for a server
51
- * build). The Vercel adapter copies that directory into its Build Output
52
- * static tree in a later hook, so the artifacts ride along; every other
53
- * adapter serves it directly. Running inside the hook rather than after
54
- * `astro build` returns means an ejected project keeps producing them.
55
+ * build, or `dist/client/<base>/` on Cloudflare, whose `_headers` goes to
56
+ * the root the platform serves above it). The Vercel adapter copies that
57
+ * directory into its Build Output static tree in a later hook, so the
58
+ * artifacts ride along; every other adapter serves it directly. Running
59
+ * inside the hook rather than after `astro build` returns means an ejected
60
+ * project keeps producing them.
55
61
  *
56
62
  * Every file yields to one the user ships in `public/` (Astro copied it into
57
63
  * the output before this runs).
@@ -85,7 +91,7 @@ const emitRedirectFiles = async (
85
91
  return;
86
92
  }
87
93
  const platform = deployPlatform(config.deployment);
88
- const redirects = platformRedirects(config);
94
+ const redirects = platformRedirects(project);
89
95
  const vercelHeaders = platform.redirectFiles.includes(VERCEL_JSON_FILE)
90
96
  ? buildVercelHeaders(
91
97
  config,
@@ -124,6 +130,24 @@ const emitRedirectFiles = async (
124
130
  logger.info(`Emitted redirect files for ${redirects.length} redirect(s)`);
125
131
  };
126
132
 
133
+ /**
134
+ * The root of the static assets the platform serves, where it reads
135
+ * `_headers`: `distDir` itself, except on a server build whose adapter moved
136
+ * the client output under `deployment.base` (`@astrojs/cloudflare` hands
137
+ * `astro:build:done` `dist/client/<base>/` but serves `dist/client`). A file
138
+ * left in `distDir` there would never be read, and would be served publicly
139
+ * at `<base>/_headers`.
140
+ */
141
+ const assetsRoot = (config: ResolvedConfig, distDir: string): string => {
142
+ const base = normalizeBasePath(config.deployment.options.base);
143
+ const nested =
144
+ config.deployment.options.output === "server" &&
145
+ deployPlatform(config.deployment).serverClientUnderBase;
146
+ // One `..` per base segment climbs back out of `dist/client/<base>/`.
147
+ const depth = base.split("/").length - 1;
148
+ return nested && base ? join(distDir, "../".repeat(depth)) : distDir;
149
+ };
150
+
127
151
  /**
128
152
  * Emit a `_headers` file so Netlify / Cloudflare serve the raw AI-ready
129
153
  * endpoints (`*.md`, `*.mdx`, `*.txt`) with an explicit `charset=utf-8`. Without
@@ -176,7 +200,7 @@ export const emitHeaderFiles = async (
176
200
  // An adapter may have written its own rules here already (Cloudflare adds an
177
201
  // immutable Cache-Control for /_astro/*). Keep them and append ours: both
178
202
  // sets are wanted, and `_headers` has no merge semantics beyond order.
179
- const target = join(distDir, "_headers");
203
+ const target = join(assetsRoot(config, distDir), "_headers");
180
204
  const existing = existsSync(target) ? await readFile(target, "utf-8") : "";
181
205
  await writeFile(
182
206
  target,
@@ -367,9 +391,26 @@ export const publishBuildArtifacts = async (
367
391
  });
368
392
 
369
393
  // Collected once: llms.txt lists the skills the build publishes below.
394
+ const userSkillsIndex = existsSync(
395
+ join(distDir, AGENT_SKILLS_INDEX_PATH.slice(1))
396
+ );
370
397
  const skills = await collectConfiguredSkills(project, distDir, logger);
398
+ // The discovery documents advertise what this build serves: no MCP server
399
+ // when a page took its route, no skills index when nothing was published.
400
+ const advertised: BlumeProject = {
401
+ ...project,
402
+ config: advertisedConfig(project.config, {
403
+ mcp: servesMcp(
404
+ project,
405
+ project.context.pagesRoot
406
+ ? discoverPagesSync(project.context.pagesRoot)
407
+ : []
408
+ ),
409
+ skills: skills.length > 0 || userSkillsIndex,
410
+ }),
411
+ };
371
412
  if (project.config.agents.llmsTxt.enabled) {
372
- await publishLlmsFiles(project, distDir, skills, logger);
413
+ await publishLlmsFiles(advertised, distDir, skills, logger);
373
414
  }
374
415
 
375
416
  const sitemapFiles = buildSitemapFiles(project);
@@ -388,7 +429,7 @@ export const publishBuildArtifacts = async (
388
429
  logger.info("Generated robots.txt");
389
430
  }
390
431
 
391
- const agentReadability = buildAgentReadability(project);
432
+ const agentReadability = buildAgentReadability(advertised);
392
433
  if (
393
434
  agentReadability &&
394
435
  !existsSync(join(distDir, "agent-readability.json"))
@@ -401,9 +442,9 @@ export const publishBuildArtifacts = async (
401
442
  logger.info("Generated agent-readability.json");
402
443
  }
403
444
 
404
- await emitWellKnownFiles(project.config, distDir, skills, logger);
445
+ await emitWellKnownFiles(advertised.config, distDir, skills, logger);
405
446
  await emitAgentSkills(project, distDir, skills, logger);
406
447
 
407
- await emitRedirectFiles(project, distDir, logger);
408
- await emitHeaderFiles(project, distDir, logger);
448
+ await emitRedirectFiles(advertised, distDir, logger);
449
+ await emitHeaderFiles(advertised, distDir, logger);
409
450
  };