blume 1.7.2 → 2.0.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 (677) hide show
  1. package/AGENTS.md +19 -0
  2. package/CHANGELOG.md +227 -0
  3. package/README.md +34 -21
  4. package/dist/cli/chunk-11j0384y.js +148 -0
  5. package/dist/cli/chunk-11j0384y.js.map +10 -0
  6. package/dist/cli/{chunk-xhtpx3ff.js → chunk-1w8dp3qb.js} +17 -16
  7. package/dist/cli/{chunk-xhtpx3ff.js.map → chunk-1w8dp3qb.js.map} +3 -3
  8. package/dist/cli/chunk-2q1dwty4.js +75 -0
  9. package/dist/cli/chunk-2q1dwty4.js.map +11 -0
  10. package/dist/cli/chunk-41za066z.js +122 -0
  11. package/dist/cli/chunk-41za066z.js.map +11 -0
  12. package/dist/cli/chunk-5a2z0198.js +133 -0
  13. package/dist/cli/chunk-5a2z0198.js.map +10 -0
  14. package/dist/cli/{chunk-9he6crym.js → chunk-6k8vp3ta.js} +25 -13
  15. package/dist/cli/{chunk-9he6crym.js.map → chunk-6k8vp3ta.js.map} +4 -4
  16. package/dist/cli/{chunk-mt76t7dj.js → chunk-79njf86q.js} +133 -54
  17. package/dist/cli/chunk-79njf86q.js.map +11 -0
  18. package/dist/cli/{chunk-3w7b2vcx.js → chunk-7ez8ny0t.js} +2 -2
  19. package/dist/cli/{chunk-688e0dde.js → chunk-88cpgt6h.js} +1 -1
  20. package/dist/cli/chunk-a9kptbw5.js +361 -0
  21. package/dist/cli/chunk-a9kptbw5.js.map +14 -0
  22. package/dist/cli/chunk-abh8yjkn.js +31 -0
  23. package/dist/cli/chunk-abh8yjkn.js.map +10 -0
  24. package/dist/cli/chunk-b5aj94ah.js +91 -0
  25. package/dist/cli/chunk-b5aj94ah.js.map +10 -0
  26. package/dist/cli/{chunk-hs3gbh8p.js → chunk-bctazmbk.js} +9 -5
  27. package/dist/cli/chunk-bctazmbk.js.map +10 -0
  28. package/dist/cli/chunk-beat36xx.js +279 -0
  29. package/dist/cli/chunk-beat36xx.js.map +10 -0
  30. package/dist/cli/chunk-bnbmcwfb.js +145 -0
  31. package/dist/cli/chunk-bnbmcwfb.js.map +11 -0
  32. package/dist/cli/{chunk-9bkjd11x.js → chunk-bw22s759.js} +15 -5
  33. package/dist/cli/{chunk-9bkjd11x.js.map → chunk-bw22s759.js.map} +4 -4
  34. package/dist/cli/chunk-by2290sx.js +39 -0
  35. package/dist/cli/chunk-by2290sx.js.map +10 -0
  36. package/dist/cli/chunk-d1tadaw7.js +79 -0
  37. package/dist/cli/chunk-d1tadaw7.js.map +10 -0
  38. package/dist/cli/{chunk-t3tj0dgr.js → chunk-d80hr03s.js} +24 -19
  39. package/dist/cli/chunk-d80hr03s.js.map +15 -0
  40. package/dist/cli/chunk-ernrthtr.js +97 -0
  41. package/dist/cli/chunk-ernrthtr.js.map +10 -0
  42. package/dist/cli/chunk-f2972sbt.js +374 -0
  43. package/dist/cli/chunk-f2972sbt.js.map +10 -0
  44. package/dist/cli/{chunk-exeeb35e.js → chunk-f7t03s3g.js} +2 -2
  45. package/dist/cli/{chunk-2z47ypj8.js → chunk-fa25z98p.js} +16 -3
  46. package/dist/cli/chunk-fa25z98p.js.map +11 -0
  47. package/dist/cli/{chunk-12dxjqk7.js → chunk-fh5hj5jt.js} +44 -21
  48. package/dist/cli/chunk-fh5hj5jt.js.map +10 -0
  49. package/dist/cli/{chunk-8cd8tj54.js → chunk-j8mw0za6.js} +86 -57
  50. package/dist/cli/chunk-j8mw0za6.js.map +35 -0
  51. package/dist/cli/chunk-jts8mvcz.js +106 -0
  52. package/dist/cli/{chunk-2mzebbbz.js.map → chunk-jts8mvcz.js.map} +6 -4
  53. package/dist/cli/{chunk-ejjx8znq.js → chunk-mnqj32sj.js} +505 -536
  54. package/dist/cli/chunk-mnqj32sj.js.map +12 -0
  55. package/dist/cli/{chunk-196vjxp9.js → chunk-mwt1k8n7.js} +100 -372
  56. package/dist/cli/chunk-mwt1k8n7.js.map +10 -0
  57. package/dist/cli/chunk-nk3ts2xk.js +51 -0
  58. package/dist/cli/chunk-nk3ts2xk.js.map +10 -0
  59. package/dist/cli/{chunk-n9sra6sy.js → chunk-pat2zzwc.js} +10 -14
  60. package/dist/cli/{chunk-n9sra6sy.js.map → chunk-pat2zzwc.js.map} +2 -2
  61. package/dist/cli/chunk-pnnvybbk.js +176 -0
  62. package/dist/cli/chunk-pnnvybbk.js.map +11 -0
  63. package/dist/cli/{chunk-cvky9gb2.js → chunk-sqn5t4q0.js} +81 -87
  64. package/dist/cli/chunk-sqn5t4q0.js.map +10 -0
  65. package/dist/cli/{chunk-eevwt1sc.js → chunk-tzne8qfq.js} +15 -15
  66. package/dist/cli/{chunk-eevwt1sc.js.map → chunk-tzne8qfq.js.map} +1 -1
  67. package/dist/cli/chunk-xaz13gwg.js +12449 -0
  68. package/dist/cli/chunk-xaz13gwg.js.map +182 -0
  69. package/dist/cli/chunk-y3e45rc8.js +102 -0
  70. package/dist/cli/chunk-y3e45rc8.js.map +10 -0
  71. package/dist/cli/chunk-z01ze5c1.js +261 -0
  72. package/dist/cli/chunk-z01ze5c1.js.map +10 -0
  73. package/dist/cli/{chunk-5n7t497w.js → chunk-z1f5arsg.js} +247 -755
  74. package/dist/cli/chunk-z1f5arsg.js.map +36 -0
  75. package/dist/cli/{chunk-hdm2dkd2.js → chunk-zg2gtj10.js} +1086 -2596
  76. package/dist/cli/chunk-zg2gtj10.js.map +35 -0
  77. package/dist/cli/{chunk-ppfvdcd4.js → chunk-zxccj738.js} +1 -1
  78. package/dist/cli/index.js +214 -57
  79. package/dist/cli/index.js.map +8 -7
  80. package/dist/types/ai/agent-readability.d.ts +52 -0
  81. package/dist/types/ai/ai-catalog.d.ts +42 -0
  82. package/dist/types/ai/api/paths.d.ts +17 -0
  83. package/dist/types/ai/api-catalog.d.ts +18 -0
  84. package/dist/types/ai/ask.d.ts +368 -0
  85. package/dist/types/ai/changelog-markdown.d.ts +2 -0
  86. package/dist/types/ai/component-markdown.d.ts +2 -2
  87. package/dist/types/ai/index.d.ts +24 -0
  88. package/dist/types/ai/link-headers.d.ts +24 -0
  89. package/dist/types/ai/llms.d.ts +25 -0
  90. package/dist/types/ai/markdown.d.ts +45 -0
  91. package/dist/types/ai/mcp/discovery.d.ts +68 -0
  92. package/dist/types/ai/mcp/tools.d.ts +16 -0
  93. package/dist/types/ai/openapi-components.d.ts +43 -0
  94. package/dist/types/ai/relative-links.d.ts +26 -0
  95. package/dist/types/ai/serializers.d.ts +15 -0
  96. package/dist/types/ai/skills.d.ts +42 -0
  97. package/dist/types/ai/tar.d.ts +25 -0
  98. package/dist/types/ai/visibility.d.ts +17 -0
  99. package/dist/types/ai/web-bot-auth.d.ts +16 -0
  100. package/dist/types/analytics/adobe.d.ts +35 -0
  101. package/dist/types/analytics/amplitude.d.ts +50 -0
  102. package/dist/types/analytics/clarity.d.ts +31 -0
  103. package/dist/types/analytics/clearbit.d.ts +29 -0
  104. package/dist/types/analytics/cloudflare.d.ts +41 -0
  105. package/dist/types/analytics/fathom.d.ts +41 -0
  106. package/dist/types/analytics/google-analytics.d.ts +44 -0
  107. package/dist/types/analytics/google-tag-manager.d.ts +40 -0
  108. package/dist/types/analytics/head.d.ts +30 -0
  109. package/dist/types/analytics/heap.d.ts +40 -0
  110. package/dist/types/analytics/hightouch.d.ts +44 -0
  111. package/dist/types/analytics/hotjar.d.ts +33 -0
  112. package/dist/types/analytics/index.d.ts +61 -0
  113. package/dist/types/analytics/inline.d.ts +17 -0
  114. package/dist/types/analytics/logrocket.d.ts +44 -0
  115. package/dist/types/analytics/mixpanel.d.ts +67 -0
  116. package/dist/types/analytics/pirsch.d.ts +42 -0
  117. package/dist/types/analytics/plausible.d.ts +56 -0
  118. package/dist/types/analytics/posthog.d.ts +45 -0
  119. package/dist/types/analytics/schema.d.ts +320 -0
  120. package/dist/types/analytics/script.d.ts +46 -0
  121. package/dist/types/analytics/segment.d.ts +50 -0
  122. package/dist/types/analytics/vercel.d.ts +48 -0
  123. package/dist/types/astro/integration.d.ts +76 -0
  124. package/dist/types/astro/markdown-negotiation.d.ts +23 -0
  125. package/dist/types/astro/module-types.d.ts +14 -0
  126. package/dist/types/astro/pages.d.ts +44 -0
  127. package/dist/types/cli/env.d.ts +12 -0
  128. package/dist/types/cli/init/scaffold.d.ts +154 -0
  129. package/dist/types/components/layout/nav-utils.d.ts +11 -0
  130. package/dist/types/core/adapter.d.ts +47 -0
  131. package/dist/types/core/api-name.d.ts +7 -0
  132. package/dist/types/core/changelog-index.d.ts +13 -0
  133. package/dist/types/core/config-input.d.ts +209 -505
  134. package/dist/types/core/config.d.ts +60 -34
  135. package/dist/types/core/content-assets.d.ts +76 -0
  136. package/dist/types/core/custom-pages.d.ts +33 -0
  137. package/dist/types/core/data.d.ts +28 -11
  138. package/dist/types/core/define-components.d.ts +12 -9
  139. package/dist/types/core/deployment-env.d.ts +6 -11
  140. package/dist/types/core/frontmatter.d.ts +10 -0
  141. package/dist/types/core/graph.d.ts +18 -0
  142. package/dist/types/core/heading-markers.d.ts +54 -0
  143. package/dist/types/core/i18n-ui.d.ts +6 -2
  144. package/dist/types/core/i18n.d.ts +87 -0
  145. package/dist/types/core/includes.d.ts +138 -0
  146. package/dist/types/core/last-modified.d.ts +47 -0
  147. package/dist/types/core/links.d.ts +95 -0
  148. package/dist/types/core/locale-links.d.ts +60 -0
  149. package/dist/types/core/manifest.d.ts +17 -0
  150. package/dist/types/core/meta.d.ts +38 -0
  151. package/dist/types/core/nav-diagnostics.d.ts +26 -0
  152. package/dist/types/core/navigation.d.ts +6 -0
  153. package/dist/types/core/node-require.d.ts +19 -0
  154. package/dist/types/core/package-json.d.ts +13 -0
  155. package/dist/types/core/probe.d.ts +42 -0
  156. package/dist/types/core/project-graph.d.ts +51 -0
  157. package/dist/types/core/project.d.ts +2 -0
  158. package/dist/types/core/safe-href.d.ts +2 -0
  159. package/dist/types/core/safe-links.d.ts +26 -0
  160. package/dist/types/core/schema.d.ts +2291 -441
  161. package/dist/types/core/site-url.d.ts +16 -0
  162. package/dist/types/core/sources/assets.d.ts +36 -0
  163. package/dist/types/core/sources/cache.d.ts +37 -0
  164. package/dist/types/core/sources/collection.d.ts +28 -0
  165. package/dist/types/core/sources/contentful-rich-text.d.ts +31 -0
  166. package/dist/types/core/sources/contentful.d.ts +40 -0
  167. package/dist/types/core/sources/filesystem.d.ts +24 -0
  168. package/dist/types/core/sources/github-releases.d.ts +31 -0
  169. package/dist/types/core/sources/json.d.ts +30 -0
  170. package/dist/types/core/sources/lexical.d.ts +19 -0
  171. package/dist/types/core/sources/lower.d.ts +75 -0
  172. package/dist/types/core/sources/mdx-remote.d.ts +28 -0
  173. package/dist/types/core/sources/normalize.d.ts +147 -0
  174. package/dist/types/core/sources/notion.d.ts +131 -0
  175. package/dist/types/core/sources/obsidian.d.ts +46 -0
  176. package/dist/types/core/sources/payload.d.ts +39 -0
  177. package/dist/types/core/sources/portable-text.d.ts +42 -0
  178. package/dist/types/core/sources/read.d.ts +23 -0
  179. package/dist/types/core/sources/remote.d.ts +74 -0
  180. package/dist/types/core/sources/resolve.d.ts +19 -0
  181. package/dist/types/core/sources/sanity.d.ts +43 -0
  182. package/dist/types/core/sources/strapi-blocks.d.ts +12 -0
  183. package/dist/types/core/sources/strapi.d.ts +33 -0
  184. package/dist/types/core/sources/types.d.ts +7 -0
  185. package/dist/types/core/sources/watch.d.ts +45 -0
  186. package/dist/types/core/text-width.d.ts +11 -0
  187. package/dist/types/core/types.d.ts +20 -1
  188. package/dist/types/core/unrecognized-keys.d.ts +7 -0
  189. package/dist/types/core/versions.d.ts +72 -0
  190. package/dist/types/core/yaml.d.ts +9 -0
  191. package/dist/types/deploy/adapter-output.d.ts +45 -0
  192. package/dist/types/deploy/adapters/cloudflare.d.ts +40 -0
  193. package/dist/types/deploy/adapters/index.d.ts +29 -0
  194. package/dist/types/deploy/adapters/netlify.d.ts +37 -0
  195. package/dist/types/deploy/adapters/node.d.ts +37 -0
  196. package/dist/types/deploy/adapters/registry.d.ts +133 -0
  197. package/dist/types/deploy/adapters/types.d.ts +71 -0
  198. package/dist/types/deploy/adapters/vercel.d.ts +38 -0
  199. package/dist/types/deploy/artifacts.d.ts +65 -0
  200. package/dist/types/deploy/cloudflare-negotiation.d.ts +196 -0
  201. package/dist/types/deploy/function-bundle.d.ts +80 -0
  202. package/dist/types/deploy/headers.d.ts +50 -0
  203. package/dist/types/deploy/node-headers.d.ts +42 -0
  204. package/dist/types/deploy/platforms/cloudflare.d.ts +40 -0
  205. package/dist/types/deploy/platforms/index.d.ts +18 -0
  206. package/dist/types/deploy/platforms/netlify.d.ts +13 -0
  207. package/dist/types/deploy/platforms/node.d.ts +11 -0
  208. package/dist/types/deploy/platforms/paths.d.ts +27 -0
  209. package/dist/types/deploy/platforms/static.d.ts +10 -0
  210. package/dist/types/deploy/platforms/types.d.ts +104 -0
  211. package/dist/types/deploy/platforms/vercel.d.ts +32 -0
  212. package/dist/types/deploy/redirects.d.ts +53 -0
  213. package/dist/types/deploy/robots.d.ts +8 -0
  214. package/dist/types/deploy/rss.d.ts +31 -0
  215. package/dist/types/deploy/sitemap.d.ts +21 -0
  216. package/dist/types/deploy/vercel-negotiation.d.ts +109 -0
  217. package/dist/types/markdown/code-title.d.ts +32 -0
  218. package/dist/types/markdown/fence-meta.d.ts +23 -0
  219. package/dist/types/markdown/themes.d.ts +3 -3
  220. package/dist/types/openapi/asyncapi.d.ts +129 -0
  221. package/dist/types/openapi/graphql-build.d.ts +8 -0
  222. package/dist/types/openapi/graphql.d.ts +122 -0
  223. package/dist/types/openapi/model.d.ts +158 -0
  224. package/dist/types/openapi/parse.d.ts +57 -0
  225. package/dist/types/openapi/references.d.ts +37 -25
  226. package/dist/types/openapi/render-mdx.d.ts +33 -0
  227. package/dist/types/openapi/sentence.d.ts +7 -0
  228. package/dist/types/openapi/signature.d.ts +10 -0
  229. package/dist/types/openapi/source.d.ts +22 -0
  230. package/dist/types/openapi/spec-dependency-error.d.ts +10 -0
  231. package/dist/types/reference/asyncapi.d.ts +166 -0
  232. package/dist/types/reference/graphql.d.ts +181 -0
  233. package/dist/types/reference/index.d.ts +32 -0
  234. package/dist/types/reference/openapi.d.ts +165 -0
  235. package/dist/types/reference/options.d.ts +157 -0
  236. package/dist/types/reference/scalar.d.ts +136 -0
  237. package/dist/types/reference/schema.d.ts +630 -0
  238. package/dist/types/search/adapters/algolia.d.ts +32 -0
  239. package/dist/types/search/adapters/flexsearch.d.ts +12 -0
  240. package/dist/types/search/adapters/index.d.ts +31 -0
  241. package/dist/types/search/adapters/mixedbread.d.ts +22 -0
  242. package/dist/types/search/adapters/orama-cloud.d.ts +33 -0
  243. package/dist/types/search/adapters/orama.d.ts +13 -0
  244. package/dist/types/search/adapters/pagefind.d.ts +12 -0
  245. package/dist/types/search/adapters/registry.d.ts +228 -0
  246. package/dist/types/search/adapters/types.d.ts +34 -0
  247. package/dist/types/search/adapters/typesense.d.ts +42 -0
  248. package/dist/types/search/build.d.ts +23 -0
  249. package/dist/types/search/documents.d.ts +90 -0
  250. package/dist/types/search/facets.d.ts +3 -0
  251. package/dist/types/search/sync/algolia.d.ts +14 -0
  252. package/dist/types/search/sync/index.d.ts +14 -0
  253. package/dist/types/search/sync/orama-cloud.d.ts +10 -0
  254. package/dist/types/search/sync/typesense.d.ts +14 -0
  255. package/dist/types/sources/contentful.d.ts +68 -0
  256. package/dist/types/sources/custom.d.ts +20 -0
  257. package/dist/types/sources/filesystem.d.ts +42 -0
  258. package/dist/types/sources/github-releases.d.ts +46 -0
  259. package/dist/types/sources/index.d.ts +48 -0
  260. package/dist/types/sources/mdx-remote.d.ts +63 -0
  261. package/dist/types/sources/notion.d.ts +65 -0
  262. package/dist/types/sources/obsidian.d.ts +34 -0
  263. package/dist/types/sources/payload.d.ts +68 -0
  264. package/dist/types/sources/registry.d.ts +1414 -0
  265. package/dist/types/sources/sanity.d.ts +69 -0
  266. package/dist/types/sources/shared.d.ts +46 -0
  267. package/dist/types/sources/strapi.d.ts +66 -0
  268. package/dist/types/theme/icon-kind.d.ts +11 -0
  269. package/dist/types/theme/icons.d.ts +20 -0
  270. package/docs/01-quickstart.mdx +18 -18
  271. package/docs/02-deployment.mdx +50 -26
  272. package/docs/03-upgrading.mdx +351 -0
  273. package/docs/04-migrating.mdx +58 -0
  274. package/docs/08-faq.mdx +3 -3
  275. package/docs/advanced/blog.mdx +13 -6
  276. package/docs/advanced/changelog.mdx +23 -35
  277. package/docs/advanced/custom-pages.mdx +20 -8
  278. package/docs/advanced/meta.ts +1 -8
  279. package/docs/advanced/skills.mdx +8 -0
  280. package/docs/cli/audit.mdx +646 -0
  281. package/docs/cli/doctor.mdx +29 -0
  282. package/docs/{reference/eval.mdx → cli/evals.mdx} +9 -8
  283. package/docs/cli/index.mdx +105 -0
  284. package/docs/cli/meta.ts +7 -0
  285. package/docs/{reference → cli}/translate.mdx +1 -1
  286. package/docs/cli/validate.mdx +41 -0
  287. package/docs/cli/version.mdx +40 -0
  288. package/docs/configuration/analytics.mdx +350 -59
  289. package/docs/configuration/ask-ai.mdx +176 -61
  290. package/docs/configuration/customization.mdx +15 -9
  291. package/docs/configuration/index.mdx +52 -31
  292. package/docs/configuration/search.mdx +75 -54
  293. package/docs/configuration/theming.mdx +24 -15
  294. package/docs/content/components.mdx +21 -5
  295. package/docs/{reference → content}/frontmatter.mdx +37 -1
  296. package/docs/content/i18n.mdx +8 -6
  297. package/docs/content/includes.mdx +2 -4
  298. package/docs/content/index.mdx +1 -1
  299. package/docs/content/islands.mdx +10 -5
  300. package/docs/content/meta.mdx +1 -1
  301. package/docs/content/meta.ts +1 -0
  302. package/docs/content/navigation.mdx +12 -7
  303. package/docs/content/sources.mdx +145 -50
  304. package/docs/content/syntax.mdx +26 -12
  305. package/docs/content/versioning.mdx +3 -3
  306. package/docs/discoverability/agent-discovery.mdx +91 -10
  307. package/docs/discoverability/index.mdx +5 -5
  308. package/docs/discoverability/json-api.mdx +4 -4
  309. package/docs/discoverability/llms-txt.mdx +6 -6
  310. package/docs/discoverability/markdown.mdx +4 -4
  311. package/docs/discoverability/mcp.mdx +11 -11
  312. package/docs/discoverability/sitemap-and-robots.mdx +3 -3
  313. package/docs/index.mdx +2 -2
  314. package/docs/references/asyncapi.mdx +59 -0
  315. package/docs/{advanced → references}/graphql.mdx +45 -32
  316. package/docs/{reference → references}/meta.ts +2 -2
  317. package/docs/references/openapi.mdx +171 -0
  318. package/docs/references/scalar.mdx +64 -0
  319. package/package.json +42 -8
  320. package/skills/blume/SKILL.md +21 -8
  321. package/skills/blume-migrate/SKILL.md +22 -21
  322. package/skills/blume-migrate/assets/oxfmt@0.67.0.patch +49 -0
  323. package/skills/blume-migrate/references/docusaurus.md +5 -4
  324. package/skills/blume-migrate/references/fumadocs.md +4 -4
  325. package/skills/blume-migrate/references/mintlify.md +23 -8
  326. package/skills/blume-migrate/references/monorepo.md +6 -6
  327. package/skills/blume-migrate/references/starlight.md +4 -4
  328. package/src/ai/agent-readability.ts +26 -22
  329. package/src/ai/ai-catalog.ts +259 -0
  330. package/src/ai/api/handlers.ts +46 -11
  331. package/src/ai/api-catalog.ts +8 -8
  332. package/src/ai/ask-data.ts +1 -1
  333. package/src/ai/ask.ts +624 -100
  334. package/src/ai/changelog-markdown.ts +91 -0
  335. package/src/ai/component-markdown.ts +328 -12
  336. package/src/ai/index.ts +45 -0
  337. package/src/ai/link-headers.ts +19 -6
  338. package/src/ai/llms.ts +26 -15
  339. package/src/ai/markdown.ts +35 -5
  340. package/src/ai/mcp/data.ts +9 -5
  341. package/src/ai/mcp/discovery.ts +1 -1
  342. package/src/ai/openapi-components.ts +4 -1
  343. package/src/ai/relative-links.ts +170 -0
  344. package/src/ai/serializers.ts +2 -2
  345. package/src/ai/skills.ts +1 -1
  346. package/src/ai/web-bot-auth.ts +2 -2
  347. package/src/analytics/adobe.ts +46 -0
  348. package/src/analytics/amplitude.ts +79 -0
  349. package/src/analytics/clarity.ts +46 -0
  350. package/src/analytics/clearbit.ts +47 -0
  351. package/src/analytics/cloudflare.ts +67 -0
  352. package/src/analytics/fathom.ts +64 -0
  353. package/src/analytics/google-analytics.ts +84 -0
  354. package/src/analytics/google-tag-manager.ts +61 -0
  355. package/src/analytics/head.ts +130 -0
  356. package/src/analytics/heap.ts +65 -0
  357. package/src/analytics/hightouch.ts +77 -0
  358. package/src/analytics/hotjar.ts +47 -0
  359. package/src/analytics/index.ts +71 -0
  360. package/src/analytics/inline.ts +21 -0
  361. package/src/analytics/logrocket.ts +71 -0
  362. package/src/analytics/mixpanel.ts +92 -0
  363. package/src/analytics/pirsch.ts +66 -0
  364. package/src/analytics/plausible.ts +83 -0
  365. package/src/analytics/posthog.ts +78 -0
  366. package/src/analytics/schema.ts +60 -0
  367. package/src/analytics/script.ts +60 -0
  368. package/src/analytics/segment.ts +85 -0
  369. package/src/analytics/vercel.ts +50 -0
  370. package/src/astro/adapter-root.ts +7 -9
  371. package/src/astro/component-slots.ts +131 -91
  372. package/src/astro/generate.ts +114 -345
  373. package/src/astro/integration.ts +2 -6
  374. package/src/astro/pages.ts +13 -101
  375. package/src/astro/render-deps.ts +379 -0
  376. package/src/astro/runtime-deps.ts +201 -0
  377. package/src/astro/templates.ts +554 -541
  378. package/src/audit/agent.ts +24 -0
  379. package/src/audit/catalog.ts +2 -2
  380. package/src/audit/checks/assets.ts +2 -2
  381. package/src/audit/checks/dns-aid.ts +1 -1
  382. package/src/audit/checks/duplicates.ts +3 -1
  383. package/src/audit/checks/i18n.ts +1 -1
  384. package/src/audit/checks/indexability.ts +7 -7
  385. package/src/audit/checks/links.ts +2 -2
  386. package/src/audit/checks/llms.ts +6 -6
  387. package/src/audit/checks/network.ts +3 -3
  388. package/src/audit/checks/og-image.ts +2 -2
  389. package/src/audit/checks/robots.ts +1 -1
  390. package/src/audit/checks/sitemap.ts +2 -2
  391. package/src/audit/checks/social.ts +1 -1
  392. package/src/audit/run.ts +4 -3
  393. package/src/audit/terms.ts +31 -0
  394. package/src/audit/url.ts +13 -13
  395. package/src/cli/command-meta.ts +10 -0
  396. package/src/cli/commands/audit.ts +39 -20
  397. package/src/cli/commands/build.ts +71 -314
  398. package/src/cli/commands/check.ts +1 -0
  399. package/src/cli/commands/dev.ts +40 -1
  400. package/src/cli/commands/doctor.ts +90 -14
  401. package/src/cli/commands/eject.ts +44 -7
  402. package/src/cli/commands/eval.ts +2 -2
  403. package/src/cli/commands/init.ts +161 -41
  404. package/src/cli/commands/migrate.ts +121 -0
  405. package/src/cli/commands/preview.ts +7 -1
  406. package/src/cli/commands/translate.ts +2 -2
  407. package/src/cli/commands/upgrade.ts +141 -0
  408. package/src/cli/commands/version.ts +57 -44
  409. package/src/cli/eject-scripts.ts +121 -6
  410. package/src/cli/index.ts +11 -1
  411. package/src/cli/init/install.ts +70 -0
  412. package/src/cli/init/questions.ts +7 -0
  413. package/src/cli/init/scaffold.ts +459 -75
  414. package/src/cli/lazy-command.ts +37 -1
  415. package/src/cli/prepare.ts +40 -6
  416. package/src/cli/required-secrets.ts +38 -11
  417. package/src/cli/unknown-flags.ts +266 -0
  418. package/src/cli/yarn-pnp.ts +52 -0
  419. package/src/components/content/AccordionItem.astro +7 -1
  420. package/src/components/content/Card.astro +4 -3
  421. package/src/components/content/ColorItem.astro +22 -4
  422. package/src/components/content/GithubInfo.astro +2 -2
  423. package/src/components/content/Prompt.astro +25 -25
  424. package/src/components/content/Tabs.astro +3 -1
  425. package/src/components/content/Tile.astro +2 -3
  426. package/src/components/content/Tooltip.astro +57 -9
  427. package/src/components/content/content-strings.ts +34 -0
  428. package/src/components/content/diff.ts +1 -1
  429. package/src/components/content/mermaid-element.ts +13 -2
  430. package/src/components/content/prompt-markdown.ts +292 -0
  431. package/src/components/content/tooltip-id.ts +41 -0
  432. package/src/components/islands/hooks.ts +75 -3
  433. package/src/components/layout/Analytics.astro +21 -79
  434. package/src/components/layout/Banner.astro +3 -1
  435. package/src/components/layout/DiscoveryLinks.astro +69 -0
  436. package/src/components/layout/Header.astro +83 -20
  437. package/src/components/layout/LanguageSwitcher.astro +4 -1
  438. package/src/components/layout/Logo.astro +23 -2
  439. package/src/components/layout/NavSelector.astro +13 -2
  440. package/src/components/layout/NavTree.astro +12 -3
  441. package/src/components/layout/NavTreeScript.astro +17 -3
  442. package/src/components/layout/PageActions.astro +3 -3
  443. package/src/components/layout/PageFeedback.astro +11 -1
  444. package/src/components/layout/PageLayout.astro +52 -5
  445. package/src/components/layout/ReferenceLayout.astro +21 -12
  446. package/src/components/layout/RootLayout.astro +69 -43
  447. package/src/components/layout/Search.astro +30 -6
  448. package/src/components/layout/WebMcp.astro +1 -1
  449. package/src/components/layout/analytics-client.ts +101 -15
  450. package/src/components/layout/drawer-inert.ts +113 -15
  451. package/src/components/layout/dropdown-clamp.ts +105 -0
  452. package/src/components/layout/head-scripts.ts +15 -6
  453. package/src/components/layout/nav-utils.ts +17 -0
  454. package/src/components/layout/search/algolia.ts +8 -8
  455. package/src/components/layout/search/orama-cloud.ts +9 -7
  456. package/src/components/layout/search/typesense.ts +11 -17
  457. package/src/components/openapi/MessageComposer.astro +2 -2
  458. package/src/components/openapi/Playground.astro +2 -2
  459. package/src/components/openapi/playground-client.ts +79 -10
  460. package/src/core/changelog-index.ts +24 -0
  461. package/src/core/component-overrides.ts +399 -154
  462. package/src/core/config-input.ts +212 -543
  463. package/src/core/config.ts +130 -41
  464. package/src/core/custom-pages.ts +105 -0
  465. package/src/core/data.ts +32 -11
  466. package/src/core/define-components.ts +12 -9
  467. package/src/core/deployment-env.ts +18 -74
  468. package/src/core/diagnostics.ts +14 -7
  469. package/src/core/graph.ts +69 -25
  470. package/src/core/i18n-ui.ts +6 -2
  471. package/src/core/i18n.ts +17 -0
  472. package/src/core/includes.ts +156 -38
  473. package/src/core/last-modified.ts +6 -11
  474. package/src/core/links.ts +166 -2
  475. package/src/core/manifest.ts +10 -3
  476. package/src/core/navigation.ts +137 -19
  477. package/src/core/new-tab.ts +35 -0
  478. package/src/core/node-require.ts +21 -0
  479. package/src/core/project-graph.ts +42 -26
  480. package/src/core/project.ts +9 -4
  481. package/src/core/request-body.ts +61 -0
  482. package/src/core/safe-href.ts +28 -0
  483. package/src/core/safe-links.ts +68 -0
  484. package/src/core/schema.ts +531 -721
  485. package/src/core/server-features.ts +8 -9
  486. package/src/core/sources/assets.ts +47 -11
  487. package/src/core/sources/collection.ts +67 -0
  488. package/src/core/sources/contentful-rich-text.ts +285 -0
  489. package/src/core/sources/contentful.ts +173 -0
  490. package/src/core/sources/github-releases.ts +51 -1
  491. package/src/core/sources/json.ts +71 -0
  492. package/src/core/sources/lexical.ts +195 -0
  493. package/src/core/sources/lower.ts +226 -0
  494. package/src/core/sources/normalize.ts +52 -2
  495. package/src/core/sources/notion.ts +39 -28
  496. package/src/core/sources/payload.ts +135 -0
  497. package/src/core/sources/portable-text.ts +11 -16
  498. package/src/core/sources/remote.ts +226 -0
  499. package/src/core/sources/resolve.ts +104 -166
  500. package/src/core/sources/sanity.ts +16 -49
  501. package/src/core/sources/strapi-blocks.ts +124 -0
  502. package/src/core/sources/strapi.ts +191 -0
  503. package/src/core/sources/types.ts +12 -1
  504. package/src/core/types.ts +20 -1
  505. package/src/core/ui-packs/ar.ts +6 -2
  506. package/src/core/ui-packs/bg.ts +6 -2
  507. package/src/core/ui-packs/bn.ts +6 -2
  508. package/src/core/ui-packs/ca.ts +3 -1
  509. package/src/core/ui-packs/cs.ts +6 -2
  510. package/src/core/ui-packs/da.ts +6 -2
  511. package/src/core/ui-packs/de.ts +6 -2
  512. package/src/core/ui-packs/el.ts +3 -1
  513. package/src/core/ui-packs/es.ts +3 -1
  514. package/src/core/ui-packs/fa.ts +6 -2
  515. package/src/core/ui-packs/fi.ts +6 -2
  516. package/src/core/ui-packs/fr.ts +3 -1
  517. package/src/core/ui-packs/he.ts +6 -2
  518. package/src/core/ui-packs/hi.ts +6 -2
  519. package/src/core/ui-packs/hr.ts +6 -2
  520. package/src/core/ui-packs/hu.ts +6 -2
  521. package/src/core/ui-packs/id.ts +6 -2
  522. package/src/core/ui-packs/it.ts +3 -1
  523. package/src/core/ui-packs/ja.ts +3 -1
  524. package/src/core/ui-packs/ko.ts +3 -1
  525. package/src/core/ui-packs/nl.ts +6 -2
  526. package/src/core/ui-packs/no.ts +6 -2
  527. package/src/core/ui-packs/pl.ts +6 -2
  528. package/src/core/ui-packs/pt-br.ts +3 -1
  529. package/src/core/ui-packs/pt.ts +3 -1
  530. package/src/core/ui-packs/ro.ts +6 -2
  531. package/src/core/ui-packs/ru.ts +6 -2
  532. package/src/core/ui-packs/sk.ts +6 -2
  533. package/src/core/ui-packs/sr.ts +6 -2
  534. package/src/core/ui-packs/sv.ts +6 -2
  535. package/src/core/ui-packs/th.ts +3 -1
  536. package/src/core/ui-packs/tr.ts +6 -2
  537. package/src/core/ui-packs/uk.ts +6 -2
  538. package/src/core/ui-packs/vi.ts +3 -1
  539. package/src/core/ui-packs/zh-tw.ts +3 -1
  540. package/src/core/ui-packs/zh.ts +3 -1
  541. package/src/core/unrecognized-keys.ts +10 -0
  542. package/src/core/version-cut.ts +116 -8
  543. package/src/deploy/adapter-output.ts +57 -97
  544. package/src/deploy/adapters/cloudflare.ts +39 -0
  545. package/src/deploy/adapters/index.ts +41 -0
  546. package/src/deploy/adapters/netlify.ts +34 -0
  547. package/src/deploy/adapters/node.ts +34 -0
  548. package/src/deploy/adapters/registry.ts +127 -0
  549. package/src/deploy/adapters/types.ts +92 -0
  550. package/src/deploy/adapters/vercel.ts +35 -0
  551. package/src/deploy/artifacts.ts +67 -28
  552. package/src/deploy/cloudflare-negotiation.ts +179 -100
  553. package/src/deploy/function-bundle.ts +18 -3
  554. package/src/deploy/headers.ts +129 -22
  555. package/src/deploy/node-headers.ts +198 -0
  556. package/src/deploy/platforms/cloudflare.ts +312 -0
  557. package/src/deploy/platforms/index.ts +67 -0
  558. package/src/deploy/platforms/netlify.ts +52 -0
  559. package/src/deploy/platforms/node.ts +40 -0
  560. package/src/deploy/platforms/paths.ts +42 -0
  561. package/src/deploy/platforms/static.ts +29 -0
  562. package/src/deploy/platforms/types.ts +112 -0
  563. package/src/deploy/platforms/vercel.ts +193 -0
  564. package/src/deploy/redirects.ts +30 -18
  565. package/src/deploy/robots.ts +3 -3
  566. package/src/deploy/rss.ts +2 -2
  567. package/src/deploy/sitemap.ts +2 -2
  568. package/src/deploy/vercel-negotiation.ts +27 -4
  569. package/src/eval/agents.ts +32 -1
  570. package/src/eval/findings.ts +19 -11
  571. package/src/eval/report.ts +10 -2
  572. package/src/markdown/external-links.ts +65 -0
  573. package/src/markdown/include.ts +45 -27
  574. package/src/markdown/index.ts +34 -9
  575. package/src/markdown/inline-code.ts +12 -6
  576. package/src/markdown/relative-links.ts +324 -0
  577. package/src/markdown/themes.ts +3 -3
  578. package/src/migrate/migrate.ts +149 -0
  579. package/src/openapi/parse.ts +64 -16
  580. package/src/openapi/proxy.ts +62 -10
  581. package/src/openapi/references.ts +147 -147
  582. package/src/openapi/render-mdx.ts +32 -10
  583. package/src/openapi/scalar.ts +15 -13
  584. package/src/openapi/sentence.ts +14 -0
  585. package/src/openapi/source.ts +37 -21
  586. package/src/openapi/spec-dependency-error.ts +15 -0
  587. package/src/reference/asyncapi.ts +83 -0
  588. package/src/reference/graphql.ts +89 -0
  589. package/src/reference/index.ts +40 -0
  590. package/src/reference/openapi.ts +83 -0
  591. package/src/reference/options.ts +201 -0
  592. package/src/reference/scalar.ts +136 -0
  593. package/src/reference/schema.ts +88 -0
  594. package/src/registry/eject.ts +97 -42
  595. package/src/search/adapters/algolia.ts +46 -0
  596. package/src/search/adapters/flexsearch.ts +29 -0
  597. package/src/search/adapters/index.ts +39 -0
  598. package/src/search/adapters/mixedbread.ts +39 -0
  599. package/src/search/adapters/orama-cloud.ts +51 -0
  600. package/src/search/adapters/orama.ts +24 -0
  601. package/src/search/adapters/pagefind.ts +27 -0
  602. package/src/search/adapters/registry.ts +131 -0
  603. package/src/search/adapters/types.ts +46 -0
  604. package/src/search/adapters/typesense.ts +57 -0
  605. package/src/search/build.ts +33 -7
  606. package/src/search/documents.ts +6 -0
  607. package/src/search/sync/algolia.ts +12 -11
  608. package/src/search/sync/index.ts +35 -20
  609. package/src/search/sync/orama-cloud.ts +12 -9
  610. package/src/search/sync/typesense.ts +15 -13
  611. package/src/sources/contentful.ts +63 -0
  612. package/src/sources/custom.ts +38 -0
  613. package/src/sources/filesystem.ts +51 -0
  614. package/src/sources/github-releases.ts +52 -0
  615. package/src/sources/index.ts +60 -0
  616. package/src/sources/mdx-remote.ts +76 -0
  617. package/src/sources/notion.ts +63 -0
  618. package/src/sources/obsidian.ts +38 -0
  619. package/src/sources/payload.ts +60 -0
  620. package/src/sources/registry.ts +182 -0
  621. package/src/sources/sanity.ts +66 -0
  622. package/src/sources/shared.ts +52 -0
  623. package/src/sources/strapi.ts +58 -0
  624. package/src/theme/entry.ts +47 -2
  625. package/src/translate/report.ts +40 -7
  626. package/src/upgrade/upgrade.ts +499 -0
  627. package/dist/cli/chunk-12dxjqk7.js.map +0 -10
  628. package/dist/cli/chunk-196vjxp9.js.map +0 -13
  629. package/dist/cli/chunk-2mzebbbz.js +0 -69
  630. package/dist/cli/chunk-2z47ypj8.js.map +0 -11
  631. package/dist/cli/chunk-30e87n55.js +0 -108
  632. package/dist/cli/chunk-30e87n55.js.map +0 -10
  633. package/dist/cli/chunk-450a7rcr.js +0 -185
  634. package/dist/cli/chunk-450a7rcr.js.map +0 -11
  635. package/dist/cli/chunk-5n7t497w.js.map +0 -40
  636. package/dist/cli/chunk-61j18dwk.js +0 -5342
  637. package/dist/cli/chunk-61j18dwk.js.map +0 -58
  638. package/dist/cli/chunk-88by27n5.js +0 -17
  639. package/dist/cli/chunk-88by27n5.js.map +0 -10
  640. package/dist/cli/chunk-8cd8tj54.js.map +0 -34
  641. package/dist/cli/chunk-aztttvb3.js +0 -381
  642. package/dist/cli/chunk-aztttvb3.js.map +0 -12
  643. package/dist/cli/chunk-cvky9gb2.js.map +0 -11
  644. package/dist/cli/chunk-ejjx8znq.js.map +0 -15
  645. package/dist/cli/chunk-fmceyezb.js +0 -1007
  646. package/dist/cli/chunk-fmceyezb.js.map +0 -13
  647. package/dist/cli/chunk-hdm2dkd2.js.map +0 -48
  648. package/dist/cli/chunk-hs3gbh8p.js.map +0 -10
  649. package/dist/cli/chunk-jbj4qhfw.js +0 -30
  650. package/dist/cli/chunk-jbj4qhfw.js.map +0 -10
  651. package/dist/cli/chunk-mqb2ka8m.js +0 -68
  652. package/dist/cli/chunk-mqb2ka8m.js.map +0 -10
  653. package/dist/cli/chunk-mt76t7dj.js.map +0 -11
  654. package/dist/cli/chunk-q4rae3bg.js +0 -60
  655. package/dist/cli/chunk-q4rae3bg.js.map +0 -10
  656. package/dist/cli/chunk-ra1v2nc2.js +0 -35
  657. package/dist/cli/chunk-ra1v2nc2.js.map +0 -10
  658. package/dist/cli/chunk-t3tj0dgr.js.map +0 -15
  659. package/dist/cli/chunk-tqa1s0k8.js +0 -69
  660. package/dist/cli/chunk-tqa1s0k8.js.map +0 -11
  661. package/dist/cli/chunk-vh9w1sgp.js +0 -73
  662. package/dist/cli/chunk-vh9w1sgp.js.map +0 -10
  663. package/dist/cli/chunk-vkrsvbr5.js +0 -107
  664. package/dist/cli/chunk-vkrsvbr5.js.map +0 -11
  665. package/dist/cli/chunk-vrfp10qk.js +0 -81
  666. package/dist/cli/chunk-vrfp10qk.js.map +0 -10
  667. package/dist/cli/chunk-wjt80jps.js +0 -1049
  668. package/dist/cli/chunk-wjt80jps.js.map +0 -24
  669. package/docs/advanced/api-reference.mdx +0 -240
  670. package/docs/reference/cli.mdx +0 -197
  671. package/skills/blume-migrate/assets/oxfmt@0.55.0.patch +0 -20
  672. package/src/components/content/changelog-element.ts +0 -69
  673. package/src/search/providers.ts +0 -91
  674. /package/dist/cli/{chunk-3w7b2vcx.js.map → chunk-7ez8ny0t.js.map} +0 -0
  675. /package/dist/cli/{chunk-688e0dde.js.map → chunk-88cpgt6h.js.map} +0 -0
  676. /package/dist/cli/{chunk-exeeb35e.js.map → chunk-f7t03s3g.js.map} +0 -0
  677. /package/dist/cli/{chunk-ppfvdcd4.js.map → chunk-zxccj738.js.map} +0 -0
@@ -5,6 +5,7 @@ import type { AstroIntegration } from "astro";
5
5
  import { join, relative, resolve } from "pathe";
6
6
 
7
7
  import { loadEnvFiles } from "../cli/env.ts";
8
+ import type { CustomPageRoute } from "../core/custom-pages.ts";
8
9
  import { enrichDiagnostic } from "../core/diagnostics.ts";
9
10
  import { scanProject } from "../core/project-graph.ts";
10
11
  import type { BlumeProject } from "../core/project-graph.ts";
@@ -221,12 +222,7 @@ export const showBlumeErrorOverlay = (diagnostics: Diagnostic[]): void => {
221
222
  };
222
223
 
223
224
  /** A user page mounted into the generated runtime. */
224
- export interface BlumePageRoute {
225
- /** Route pattern, e.g. `/changelog` or `/examples/[slug]`. */
226
- pattern: string;
227
- /** Absolute path to the user's `.astro` page file. */
228
- entrypoint: string;
229
- }
225
+ export type BlumePageRoute = CustomPageRoute;
230
226
 
231
227
  export interface BlumeIntegrationOptions {
232
228
  pages: BlumePageRoute[];
@@ -1,62 +1,16 @@
1
- import { extname, relative } from "pathe";
2
- import { glob, globSync } from "tinyglobby";
3
-
1
+ import {
2
+ CHANGELOG_INDEX_ROUTE,
3
+ hasChangelogIndex,
4
+ } from "../core/changelog-index.ts";
5
+ import { staticSegments } from "../core/custom-pages.ts";
4
6
  import type { BlumeProject } from "../core/project-graph.ts";
5
7
  import type { BlumePageRoute } from "./integration.ts";
6
8
 
7
- const PAGE_GLOB = ["**/*.astro"];
8
-
9
- /**
10
- * Astro's routing convention: a file or folder whose name starts with `_` is a
11
- * private partial — importable (shared layouts, home-page sections), but never
12
- * built into a route. Blume injects pages itself, so it must reproduce the same
13
- * exclusion or every `pages/_home/Hero.astro`-style component ships as an HTML
14
- * page.
15
- */
16
- const isPrivatePage = (rel: string): boolean =>
17
- rel.split("/").some((segment) => segment.startsWith("_"));
18
-
19
- /** Map discovered page files to routes; shared by the async/sync discoverers. */
20
- const toPageRoutes = (pagesRoot: string, files: string[]): BlumePageRoute[] => {
21
- files.sort();
22
- const routes: BlumePageRoute[] = [];
23
- for (const file of files) {
24
- const rel = relative(pagesRoot, file);
25
- if (isPrivatePage(rel)) {
26
- continue;
27
- }
28
- const withoutExt = rel.slice(0, rel.length - extname(rel).length);
29
- const parts = withoutExt.split("/");
30
- // Only a trailing `index` maps to its parent dir; a folder literally named
31
- // `index` (e.g. `index/foo.astro`) must keep its segment.
32
- if (parts.at(-1) === "index") {
33
- parts.pop();
34
- }
35
- const pattern = parts.length === 0 ? "/" : `/${parts.join("/")}`;
36
- routes.push({ entrypoint: file, pattern });
37
- }
38
- return routes;
39
- };
40
-
41
- /**
42
- * Discover user `.astro` pages and map them to route patterns. Files keep their
43
- * original location; only the route pattern is derived (index -> parent,
44
- * dynamic `[param]` segments preserved).
45
- */
46
- export const discoverPages = async (
47
- pagesRoot: string
48
- ): Promise<BlumePageRoute[]> =>
49
- toPageRoutes(
50
- pagesRoot,
51
- await glob(PAGE_GLOB, { absolute: true, cwd: pagesRoot, onlyFiles: true })
52
- );
53
-
54
- /** {@link discoverPages} for synchronous callers (e.g. the sitemap builder). */
55
- export const discoverPagesSync = (pagesRoot: string): BlumePageRoute[] =>
56
- toPageRoutes(
57
- pagesRoot,
58
- globSync(PAGE_GLOB, { absolute: true, cwd: pagesRoot, onlyFiles: true })
59
- );
9
+ export {
10
+ customStaticRoutes,
11
+ discoverPages,
12
+ discoverPagesSync,
13
+ } from "../core/custom-pages.ts";
60
14
 
61
15
  /**
62
16
  * Whether the project already owns `route` — through a custom `.astro` page
@@ -80,37 +34,6 @@ export interface OgCustomRoute {
80
34
  title: string;
81
35
  }
82
36
 
83
- /** Skip private (`_partial`, `.well-known`) and Astro dynamic (`[param]`) parts. */
84
- const PRIVATE_SEGMENT = /^[._]/u;
85
-
86
- /** Segments of a static, shareable page pattern; null for dynamic/private ones. */
87
- const staticSegments = (pattern: string): string[] | null => {
88
- const segments = pattern.split("/").filter(Boolean);
89
- return segments.some(
90
- (part) => PRIVATE_SEGMENT.test(part) || part.includes("[")
91
- )
92
- ? null
93
- : segments;
94
- };
95
-
96
- /**
97
- * The static routes served by custom `.astro` pages — the same filtering as
98
- * {@link customOgRoutes}, but yielding the routes themselves. Feeds the route
99
- * sets that must know every servable page beyond the content graph (the link
100
- * checker, the sitemap); dynamic (`[param]`) and private segments are skipped
101
- * because their concrete URLs can't be enumerated statically.
102
- */
103
- export const customStaticRoutes = (pages: { pattern: string }[]): string[] => {
104
- const routes = new Set<string>();
105
- for (const { pattern } of pages) {
106
- const segments = staticSegments(pattern);
107
- if (segments !== null) {
108
- routes.add(segments.length === 0 ? "/" : `/${segments.join("/")}`);
109
- }
110
- }
111
- return [...routes];
112
- };
113
-
114
37
  /**
115
38
  * Whether the generated `/changelog` index route exists for this project —
116
39
  * `generate.ts` (which writes the page) and the sitemap/link validator all
@@ -121,20 +44,9 @@ export const customStaticRoutes = (pages: { pattern: string }[]): string[] => {
121
44
  export const hasGeneratedChangelog = (
122
45
  project: BlumeProject,
123
46
  userPages: { pattern: string }[]
124
- ): boolean => {
125
- const hasChangelog = project.graph.pages.some(
126
- (page) =>
127
- page.contentType === "changelog" &&
128
- !(page.meta.draft || page.meta.sidebar.hidden)
129
- );
130
- const hasChangelogSource = (project.config.content.sources ?? []).some(
131
- (source) => source.type === "github-releases"
132
- );
133
- return (
134
- (hasChangelog || hasChangelogSource) &&
135
- !routeIsTaken(userPages, project.graph.pages, "/changelog")
136
- );
137
- };
47
+ ): boolean =>
48
+ hasChangelogIndex(project.graph.pages, project.config) &&
49
+ !routeIsTaken(userPages, project.graph.pages, CHANGELOG_INDEX_ROUTE);
138
50
 
139
51
  const humanizeSegment = (segment: string): string =>
140
52
  segment
@@ -0,0 +1,379 @@
1
+ import { existsSync, realpathSync } from "node:fs";
2
+ import {
3
+ lstat,
4
+ mkdir,
5
+ readdir,
6
+ readlink,
7
+ realpath,
8
+ rm,
9
+ symlink,
10
+ } from "node:fs/promises";
11
+ import { isBuiltin } from "node:module";
12
+
13
+ import {
14
+ basename,
15
+ dirname,
16
+ isAbsolute,
17
+ join,
18
+ normalize,
19
+ relative,
20
+ resolve,
21
+ } from "pathe";
22
+
23
+ import { packageRoot } from "../core/package-root.ts";
24
+
25
+ /**
26
+ * The two places an installer can put Blume's dependencies:
27
+ * - `<blume>/node_modules` — deps nested under the package (workspace source,
28
+ * or npm nesting them away from a conflicting hoisted copy)
29
+ * - `dirname(<blume>)` — deps as siblings in the store (isolated/pnpm)
30
+ *
31
+ * `packageRoot()` resolves to Blume's real on-disk path (Node follows the
32
+ * install symlink), so its parent is the store's package directory where the
33
+ * isolated linker places the siblings.
34
+ */
35
+ export const depsCandidates = (pkgDir: string): string[] => [
36
+ join(pkgDir, "node_modules"),
37
+ dirname(pkgDir),
38
+ ];
39
+
40
+ /** First dependency candidate containing the package dir `segments`, or null. */
41
+ export const candidateHolding = (
42
+ pkgDir: string,
43
+ ...segments: string[]
44
+ ): string | null =>
45
+ depsCandidates(pkgDir).find((dir) => existsSync(join(dir, ...segments))) ??
46
+ null;
47
+
48
+ const holdsAstro = (dir: string): boolean => existsSync(join(dir, "astro"));
49
+ const holdsMdx = (dir: string): boolean =>
50
+ existsSync(join(dir, "@astrojs", "mdx"));
51
+
52
+ /**
53
+ * Locate the directory that holds Blume's installed dependencies (Astro and its
54
+ * integrations).
55
+ *
56
+ * With a clean hoisted install this is moot — the deps sit in a `node_modules`
57
+ * the generated `.blume/` already walks up into. But under isolated linkers
58
+ * (Bun's `isolated` mode, pnpm) Blume's deps are NOT hoisted into the project;
59
+ * they live beside the Blume package in a virtual store, invisible to the
60
+ * upward walk from `.blume/` — so probe the {@link depsCandidates}.
61
+ *
62
+ * Astro alone is a bad probe: an npm split install (an `overrides` pin plus an
63
+ * incremental install) hoists `astro` to the project root while Blume's other
64
+ * deps stay nested, and probing for astro then picks the root directory — one
65
+ * that holds none of them. Prefer a candidate with the full set (astro beside
66
+ * `@astrojs/mdx`, the integration every generated runtime declares), then one
67
+ * with the integrations (astro hoisted away — the rest of Blume's deps sit
68
+ * there too), then one with astro alone.
69
+ */
70
+ export const blumeDepsDir = (pkgDir: string = packageRoot()): string | null => {
71
+ const candidates = depsCandidates(pkgDir);
72
+ return (
73
+ candidates.find((dir) => holdsAstro(dir) && holdsMdx(dir)) ??
74
+ candidates.find(holdsMdx) ??
75
+ candidates.find(holdsAstro) ??
76
+ null
77
+ );
78
+ };
79
+
80
+ /**
81
+ * The package a bare specifier names (`@scope/name` or `name`, whatever
82
+ * subpath follows), or null for a Node builtin.
83
+ */
84
+ export const packageNameOf = (specifier: string): string | null => {
85
+ if (isBuiltin(specifier)) {
86
+ return null;
87
+ }
88
+ const [first = "", second] = specifier.split("/");
89
+ if (!first.startsWith("@")) {
90
+ return first || null;
91
+ }
92
+ return second ? `${first}/${second}` : null;
93
+ };
94
+
95
+ /**
96
+ * The directory an import of package `name` loads from when resolved from
97
+ * `fromDir`: the first `node_modules/<name>` up the physical ancestors — the
98
+ * walk Node itself performs — as a real path, or null when none holds it.
99
+ */
100
+ export const packageDirFrom = (
101
+ name: string,
102
+ fromDir: string
103
+ ): string | null => {
104
+ let dir = normalize(fromDir);
105
+ while (true) {
106
+ const candidate = join(dir, "node_modules", name);
107
+ if (existsSync(join(candidate, "package.json"))) {
108
+ return normalize(realpathSync(candidate));
109
+ }
110
+ const parent = dirname(dir);
111
+ if (parent === dir) {
112
+ return null;
113
+ }
114
+ dir = parent;
115
+ }
116
+ };
117
+
118
+ /** Whether `child` is `parent` or sits somewhere under it. */
119
+ const isWithin = (parent: string, child: string): boolean => {
120
+ const path = relative(parent, child);
121
+ return path === "" || !(path.startsWith("..") || isAbsolute(path));
122
+ };
123
+
124
+ /**
125
+ * Point `link` at the package directory `target`, replacing a link to anything
126
+ * else and leaving a real directory alone. The link is relative, so it keeps
127
+ * working when the project moves as a whole (a server build shipped with its
128
+ * `node_modules`); without symlink privilege on Windows it falls back to a
129
+ * junction, which must be absolute.
130
+ */
131
+ const linkPackageDir = async (link: string, target: string): Promise<void> => {
132
+ await mkdir(dirname(link), { recursive: true });
133
+ // A relative link resolves from its folder's real path, which differs from
134
+ // the logical one under a symlinked parent (macOS's `/var` → `/private/var`),
135
+ // so the relative target is computed from the real path.
136
+ const from = normalize(await realpath(dirname(link)));
137
+ let existing: Awaited<ReturnType<typeof lstat>> | null;
138
+ try {
139
+ existing = await lstat(link);
140
+ } catch {
141
+ existing = null;
142
+ }
143
+ if (existing) {
144
+ if (!existing.isSymbolicLink()) {
145
+ return;
146
+ }
147
+ try {
148
+ // Both sides in one separator style: Windows hands back `\\` paths.
149
+ if (resolve(from, await readlink(link)) === normalize(target)) {
150
+ return;
151
+ }
152
+ } catch {
153
+ // An unreadable link is replaced below.
154
+ }
155
+ await rm(link, { force: true });
156
+ }
157
+ try {
158
+ await symlink(relative(from, target), link, "dir");
159
+ } catch {
160
+ await symlink(target, link, "junction");
161
+ }
162
+ };
163
+
164
+ /** The package names a `node_modules` directory holds, scoped ones included. */
165
+ const packageNames = async (modulesDir: string): Promise<string[]> => {
166
+ const entries = await readdir(modulesDir);
167
+ const grouped = await Promise.all(
168
+ entries
169
+ .filter((entry) => !entry.startsWith("."))
170
+ .map(async (entry) => {
171
+ if (!entry.startsWith("@")) {
172
+ return [entry];
173
+ }
174
+ const scoped = await readdir(join(modulesDir, entry));
175
+ return scoped.map((name) => `${entry}/${name}`);
176
+ })
177
+ );
178
+ return grouped.flat();
179
+ };
180
+
181
+ /**
182
+ * Give a server-side build output its own `node_modules`: one link per package
183
+ * its bundles import by bare name, each to the copy the importing module
184
+ * resolves. A render bundle mixes code from Blume, Astro, and the adapters
185
+ * into one set of chunks, and its bare imports resolve by walking up from the
186
+ * chunk — so without these links the copy the package manager happened to
187
+ * hoist wins, not the one the importer declared. A root `js-yaml@4` (pulled in
188
+ * by the Netlify or Cloudflare adapter) then breaks Blume's `js-yaml@5`
189
+ * import, a Yarn-hoisted `cookie@0.7` breaks Astro's `cookie@2` import, and
190
+ * under pnpm the server bundle can't reach Blume's dependencies at all.
191
+ *
192
+ * Under an isolated linker the links also cover the rest of Blume's own
193
+ * dependencies, which the upward walk can't reach from the output, so a
194
+ * specifier the build never saw (loaded by a dependency at runtime) still
195
+ * resolves as it did before.
196
+ */
197
+ export const linkRenderDeps = async (
198
+ dir: string,
199
+ imported: ReadonlyMap<string, string>,
200
+ pkgDir: string = packageRoot()
201
+ ): Promise<void> => {
202
+ const modulesDir = join(dir, "node_modules");
203
+ // An earlier release linked the whole directory here; per-package links
204
+ // need a real directory in its place.
205
+ try {
206
+ const existing = await lstat(modulesDir);
207
+ if (existing.isSymbolicLink()) {
208
+ await rm(modulesDir, { force: true });
209
+ }
210
+ } catch {
211
+ // Nothing there yet.
212
+ }
213
+ const links = new Map(imported);
214
+ const depsDir = blumeDepsDir(pkgDir);
215
+ if (
216
+ depsDir &&
217
+ !(basename(depsDir) === "node_modules" && isWithin(dirname(depsDir), dir))
218
+ ) {
219
+ for (const name of await packageNames(depsDir)) {
220
+ if (!links.has(name)) {
221
+ links.set(name, normalize(realpathSync(join(depsDir, name))));
222
+ }
223
+ }
224
+ }
225
+ await Promise.all(
226
+ [...links].map(([name, target]) =>
227
+ linkPackageDir(join(modulesDir, name), target)
228
+ )
229
+ );
230
+ };
231
+
232
+ /** The Vite environment a hook runs in (`client`, `ssr`, `prerender`). */
233
+ interface PluginEnvironment {
234
+ name: string;
235
+ }
236
+
237
+ /** What `this.resolve` returns: the resolved id, and whether it's external. */
238
+ interface ResolvedModule {
239
+ external?: boolean | "absolute" | "relative";
240
+ id: string;
241
+ }
242
+
243
+ /** The `resolveId` hook options this plugin forwards to `this.resolve`. */
244
+ interface ResolveIdOptions {
245
+ attributes?: Record<string, string>;
246
+ isEntry?: boolean;
247
+ kind?: string;
248
+ }
249
+
250
+ /** The slice of the plugin context the `resolveId` hook uses. */
251
+ interface ResolveContext {
252
+ environment?: PluginEnvironment;
253
+ resolve: (
254
+ source: string,
255
+ importer: string | undefined,
256
+ options: ResolveIdOptions & { skipSelf: boolean }
257
+ ) => Promise<ResolvedModule | null>;
258
+ }
259
+
260
+ /** The Vite plugin {@link prerenderDepsPlugin} returns. */
261
+ export interface PrerenderDepsPlugin {
262
+ apply: "build";
263
+ configResolved: (config: { root: string }) => void;
264
+ enforce: "pre";
265
+ name: string;
266
+ resolveId: {
267
+ filter: { id: RegExp };
268
+ handler: (
269
+ this: ResolveContext,
270
+ source: string,
271
+ importer: string | undefined,
272
+ options: ResolveIdOptions
273
+ ) => Promise<ResolvedModule | null>;
274
+ };
275
+ writeBundle: (
276
+ this: { environment?: PluginEnvironment } | undefined,
277
+ options: { dir?: string }
278
+ ) => Promise<void>;
279
+ }
280
+
281
+ /**
282
+ * A specifier that could name a package: not relative, absolute, virtual
283
+ * (`\0`), or carrying a scheme or drive letter (`node:`, `virtual:`, `C:`).
284
+ */
285
+ const BARE_SPECIFIER = /^[^\0./\\][^:]*$/u;
286
+
287
+ /**
288
+ * The directory a module id's imports resolve from, or undefined for an id
289
+ * that isn't a file (a virtual module).
290
+ */
291
+ const importerDir = (importer: string | undefined): string | undefined => {
292
+ const [path = ""] = (importer ?? "").split("?");
293
+ return isAbsolute(path) ? dirname(path) : undefined;
294
+ };
295
+
296
+ /**
297
+ * Vite plugin that makes a server-side build's externalized imports resolve
298
+ * to the copies their importers declared, for the static prerender bundle
299
+ * Astro imports to write the HTML and for a server build's output alike.
300
+ *
301
+ * While each server-side environment (`ssr`, `prerender`) builds, it records
302
+ * every import Vite leaves external together with the package directory that
303
+ * import resolves to from the module that makes it. Once the environment's
304
+ * bundle is written, {@link linkRenderDeps} gives the output directory a
305
+ * `node_modules` of links to exactly those directories. Astro deletes the
306
+ * prerender output once generation finishes — `fs.rm` unlinks the links
307
+ * without following them — while a server build ships its links, relative so
308
+ * they survive the project moving as a whole, and a deploy adapter's file
309
+ * trace follows them to the real files.
310
+ *
311
+ * Outside an environment-aware build (a direct call, as in the tests) only a
312
+ * `.prerender` output is handled. The client build is never touched.
313
+ */
314
+ export const prerenderDepsPlugin = (
315
+ pkgDir: string = packageRoot()
316
+ ): PrerenderDepsPlugin => {
317
+ const imported = new Map<string, Map<string, string>>();
318
+ let root: string | undefined;
319
+
320
+ const record = (
321
+ environment: string,
322
+ source: string,
323
+ importer: string | undefined
324
+ ): void => {
325
+ const name = packageNameOf(source);
326
+ const packages = imported.get(environment) ?? new Map<string, string>();
327
+ imported.set(environment, packages);
328
+ if (!name || packages.has(name)) {
329
+ return;
330
+ }
331
+ const from = importerDir(importer) ?? root;
332
+ const target = from === undefined ? null : packageDirFrom(name, from);
333
+ if (target) {
334
+ packages.set(name, target);
335
+ }
336
+ };
337
+
338
+ return {
339
+ apply: "build",
340
+ configResolved: (config) => {
341
+ ({ root } = config);
342
+ },
343
+ enforce: "pre",
344
+ name: "blume:prerender-deps",
345
+ resolveId: {
346
+ filter: { id: BARE_SPECIFIER },
347
+ async handler(source, importer, options) {
348
+ const environment = this.environment?.name;
349
+ if (environment === undefined || environment === "client") {
350
+ return null;
351
+ }
352
+ const resolved = await this.resolve(source, importer, {
353
+ ...options,
354
+ skipSelf: true,
355
+ });
356
+ if (resolved?.external) {
357
+ record(environment, source, importer);
358
+ }
359
+ return resolved;
360
+ },
361
+ },
362
+ async writeBundle(options) {
363
+ const environment = this?.environment?.name;
364
+ const { dir } = options;
365
+ const serverSide =
366
+ environment === undefined
367
+ ? dir !== undefined && basename(dir) === ".prerender"
368
+ : environment !== "client";
369
+ if (!dir || !serverSide) {
370
+ return;
371
+ }
372
+ await linkRenderDeps(
373
+ dir,
374
+ imported.get(environment ?? "") ?? new Map<string, string>(),
375
+ pkgDir
376
+ );
377
+ },
378
+ };
379
+ };