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
@@ -1,5 +1,14 @@
1
1
  import type { ArgsDef, CommandDef, CommandMeta } from "citty";
2
2
 
3
+ import { BlumeError } from "../core/diagnostics.ts";
4
+ import { reportInternalError } from "./internal-error.ts";
5
+ import { reportDiagnostics } from "./log.ts";
6
+ import {
7
+ COMMAND_HANDLED_FLAGS,
8
+ unknownFlags,
9
+ unknownFlagsDiagnostic,
10
+ } from "./unknown-flags.ts";
11
+
3
12
  /**
4
13
  * Wrap a command so its module is imported only when citty needs its `args`
5
14
  * or runs it. `meta` stays static (from `command-meta.ts`), so rendering root
@@ -11,6 +20,12 @@ import type { ArgsDef, CommandDef, CommandMeta } from "citty";
11
20
  *
12
21
  * Only `args`, `setup`, `run`, and `cleanup` are forwarded: no Blume command
13
22
  * declares `default`, `plugins`, or nested `subCommands`.
23
+ *
24
+ * Two behaviors every command shares live here rather than in each command:
25
+ * `setup` rejects flags the command doesn't declare (citty accepts and drops
26
+ * them, so `blume build --isolatd` would run a real, non-isolated build), and
27
+ * `run` reports a {@link BlumeError} a command lets escape — a config that
28
+ * fails validation, say — as its diagnostic instead of citty's raw stack dump.
14
29
  */
15
30
  export const lazyCommand = <Args extends ArgsDef, Key extends string>(
16
31
  meta: CommandMeta,
@@ -21,6 +36,7 @@ export const lazyCommand = <Args extends ArgsDef, Key extends string>(
21
36
  const module = await load();
22
37
  return module[key];
23
38
  };
39
+ const name = meta.name ?? key;
24
40
  return {
25
41
  args: async () => {
26
42
  const { args } = await command();
@@ -37,10 +53,30 @@ export const lazyCommand = <Args extends ArgsDef, Key extends string>(
37
53
  meta,
38
54
  run: async (context) => {
39
55
  const loaded = await command();
40
- await loaded.run?.(context);
56
+ try {
57
+ await loaded.run?.(context);
58
+ } catch (error) {
59
+ if (error instanceof BlumeError) {
60
+ reportDiagnostics([error.diagnostic], process.cwd());
61
+ } else {
62
+ reportInternalError(error);
63
+ }
64
+ process.exit(1);
65
+ }
41
66
  },
42
67
  setup: async (context) => {
43
68
  const loaded = await command();
69
+ // SAFETY: as for `args` above, every command's `args` is a plain object.
70
+ const argsDef = (loaded.args ?? {}) as ArgsDef;
71
+ const unknown = unknownFlags(
72
+ context.rawArgs,
73
+ argsDef,
74
+ COMMAND_HANDLED_FLAGS.get(name)
75
+ );
76
+ if (unknown.length > 0) {
77
+ reportDiagnostics([unknownFlagsDiagnostic(name, unknown, argsDef)]);
78
+ process.exit(1);
79
+ }
44
80
  await loaded.setup?.(context);
45
81
  },
46
82
  };
@@ -11,11 +11,19 @@ import { loadEnvFiles } from "./env.ts";
11
11
  import { reportInternalError } from "./internal-error.ts";
12
12
  import { logger, reportDiagnostics } from "./log.ts";
13
13
  import { checkRequiredSecrets } from "./required-secrets.ts";
14
+ import { yarnPnpDiagnostic } from "./yarn-pnp.ts";
14
15
 
15
16
  export interface PrepareOptions {
16
17
  root: string;
17
18
  mode?: BuildMode;
18
19
  strict?: boolean;
20
+ /**
21
+ * Whether the command is strict only on request (`blume check --strict`),
22
+ * which changes how the abort message says to continue. Defaults to true in
23
+ * dev mode (`blume dev`, `blume sync`) and false otherwise, where strict is
24
+ * the default a user turns off with `--no-strict` (`blume build`).
25
+ */
26
+ strictOptIn?: boolean;
19
27
  /** Local dev server URL, used as the `deployment.site` fallback (dev only). */
20
28
  devServerUrl?: string;
21
29
  /** Render drafts and fetch unpublished CMS content. */
@@ -35,6 +43,14 @@ export interface PrepareOptions {
35
43
  export const prepareProject = async (
36
44
  options: PrepareOptions
37
45
  ): Promise<BlumeProject> => {
46
+ // Under Yarn Plug'n'Play the generated runtime can't resolve anything; say
47
+ // so before scanning, instead of failing inside Astro's config load.
48
+ const pnp = yarnPnpDiagnostic(options.root);
49
+ if (pnp) {
50
+ reportDiagnostics([pnp], options.root);
51
+ process.exit(1);
52
+ }
53
+
38
54
  // Load `.env` files from the project root before the scan: remote sources
39
55
  // read their tokens from `process.env` during `scanProject`, and
40
56
  // `loadEnvFiles` never overrides variables that are already set.
@@ -62,18 +78,23 @@ export const prepareProject = async (
62
78
  // Hard gate: server-only features cannot ship in a static build.
63
79
  if (
64
80
  options.mode === "build" &&
65
- project.config.deployment.output === "static"
81
+ project.config.deployment.options.output === "static"
66
82
  ) {
67
83
  const features = serverFeatures(project.config);
68
84
  if (features.length > 0) {
85
+ // A host adapter already names the target, so only its
86
+ // `output: "static"` stands in the way; otherwise name one.
87
+ const { kind } = project.config.deployment;
69
88
  reportDiagnostics(
70
89
  [
71
90
  {
72
91
  code: "BLUME_SERVER_FEATURE_REQUIRED",
73
- message: `${features.join(", ")} require server output, but deployment.output is "static".`,
92
+ message: `${features.join(", ")} ${features.length === 1 ? "requires" : "require"} server output, but this is a static build.`,
74
93
  severity: "error",
75
94
  suggestion:
76
- 'Set deployment: { output: "server", adapter: "vercel" } in blume.config.ts.',
95
+ kind === "static"
96
+ ? 'Set deployment to a host adapter from "blume/deploy" in blume.config.ts, e.g. `deployment: vercel()`.'
97
+ : `Drop \`output: "static"\` from \`deployment: ${kind}()\` in blume.config.ts to build for the server.`,
77
98
  },
78
99
  ],
79
100
  options.root
@@ -87,19 +108,32 @@ export const prepareProject = async (
87
108
  project.droppedPages > 0
88
109
  ? `${project.droppedPages} page(s) failed frontmatter validation and were dropped from the site. `
89
110
  : "";
111
+ const optIn = options.strictOptIn ?? options.mode === "dev";
90
112
  if (hadErrors && options.strict) {
91
113
  logger.error(
92
- `Aborting due to errors. ${dropped}Fix the diagnostics above, or pass --no-strict to continue despite them.`
114
+ `Aborting due to errors. ${dropped}Fix the diagnostics above, or ${optIn ? "drop --strict" : "pass --no-strict"} to continue despite them.`
93
115
  );
94
116
  process.exit(1);
95
117
  }
96
118
  if (hasErrors(project.diagnostics) && !options.strict) {
97
119
  logger.warn(
98
- `Continuing despite errors. ${dropped}Use --strict to fail instead.`
120
+ `Continuing despite errors. ${dropped}${optIn ? "Pass --strict" : "Drop --no-strict"} to fail instead.`
99
121
  );
100
122
  }
101
123
 
102
- const { warnings } = await generateRuntime(project);
124
+ let warnings: string[];
125
+ try {
126
+ ({ warnings } = await generateRuntime(project));
127
+ } catch (error) {
128
+ // A config error the generator raised (an unplannable `components.ts`
129
+ // override, a missing font file) is the user's to fix, not an internal
130
+ // failure: report the diagnostic and stop, like a scan-time error.
131
+ if (error instanceof BlumeError) {
132
+ reportDiagnostics([error.diagnostic], options.root);
133
+ process.exit(1);
134
+ }
135
+ throw error;
136
+ }
103
137
  for (const warning of warnings) {
104
138
  logger.warn(warning);
105
139
  }
@@ -25,20 +25,47 @@ export const checkRequiredSecrets = (config: ResolvedConfig): Diagnostic[] => {
25
25
  };
26
26
 
27
27
  if (config.ai.ask?.enabled && !config.ai.ask.endpoint) {
28
- const backend = resolveAskBackend(config.ai.ask);
29
- if (backend.kind === "gateway") {
30
- requireSecret(
31
- "Ask AI (AI Gateway)",
32
- "AI_GATEWAY_API_KEY",
33
- "on Vercel the gateway can also authenticate via OIDC"
34
- );
35
- } else {
36
- requireSecret("Ask AI", backend.apiKeyEnv);
28
+ // The adapter descriptor names the env vars its route reads.
29
+ const { provider } = config.ai.ask;
30
+ const backend = resolveAskBackend(provider);
31
+ for (const env of provider.requiredSecrets) {
32
+ requireSecret(`Ask AI (${backend.label})`, env, backend.secretNote);
37
33
  }
38
34
  }
39
35
 
40
- if (config.search.provider === "mixedbread") {
41
- requireSecret("Mixedbread search", "MIXEDBREAD_API_KEY");
36
+ // Each search adapter declares the secrets its generated runtime reads.
37
+ const { provider } = config.search;
38
+ for (const env of provider.requiredSecrets) {
39
+ requireSecret(`Search (${provider.kind})`, env);
40
+ }
41
+
42
+ // Adapters name their own secrets; the built-in analytics adapters ship
43
+ // public tokens in the page and declare none.
44
+ for (const adapter of config.analytics) {
45
+ for (const env of adapter.requiredSecrets) {
46
+ requireSecret(`Analytics (${adapter.kind})`, env);
47
+ }
48
+ }
49
+
50
+ // Each content source adapter declares the env vars its fetch reads.
51
+ for (const source of config.content.sources) {
52
+ for (const env of source.requiredSecrets) {
53
+ requireSecret(`Content source (${source.kind})`, env);
54
+ }
55
+ }
56
+
57
+ // Adapters name their own secrets; the built-in reference adapters read
58
+ // public specs and declare none.
59
+ for (const adapter of config.reference) {
60
+ for (const env of adapter.requiredSecrets) {
61
+ requireSecret(`API reference (${adapter.kind})`, env);
62
+ }
63
+ }
64
+
65
+ // The deployment adapter names its own secrets; the built-in host adapters
66
+ // read platform-injected env and declare none.
67
+ for (const env of config.deployment.requiredSecrets) {
68
+ requireSecret(`Deployment (${config.deployment.kind})`, env);
42
69
  }
43
70
 
44
71
  return diagnostics;
@@ -0,0 +1,266 @@
1
+ import type { ArgsDef } from "citty";
2
+
3
+ import type { Diagnostic } from "../core/types.ts";
4
+
5
+ /** A flag the command doesn't declare, with the declared one it most resembles. */
6
+ export interface UnknownFlag {
7
+ /** The flag as typed, without any `=value`. */
8
+ flag: string;
9
+ /** The closest declared flag (`--isolated` for `--isolatd`), if one is close. */
10
+ suggestion?: string;
11
+ }
12
+
13
+ /** What a declared option spelling means for the token that follows it. */
14
+ interface KnownFlag {
15
+ /** Whether it's a boolean switch, which `--no-<name>` turns off. */
16
+ boolean: boolean;
17
+ /**
18
+ * How the flags a command takes list it: `--kebab-name`, or `--no-<name>`
19
+ * for a boolean that's on by default, since that's the form anyone types.
20
+ */
21
+ display: string;
22
+ /** The canonical kebab-case name, which typos are matched against. */
23
+ name: string;
24
+ /** Whether it reads the next token as its value (`--port 4000`). */
25
+ takesValue: boolean;
26
+ }
27
+
28
+ /** `budgetJs` → `budget-js`; a name already in kebab case is unchanged. */
29
+ const kebabCase = (name: string): string =>
30
+ name.replaceAll(/(?<upper>[A-Z])/gu, (letter) => `-${letter.toLowerCase()}`);
31
+
32
+ /** `budget-js` → `budgetJs`; a name already in camel case is unchanged. */
33
+ const camelCase = (name: string): string =>
34
+ name.replaceAll(/-(?<letter>[a-z])/gu, (match) =>
35
+ match.slice(1).toUpperCase()
36
+ );
37
+
38
+ const aliasesOf = (alias: string | string[] | undefined): string[] => {
39
+ if (alias === undefined) {
40
+ return [];
41
+ }
42
+ return Array.isArray(alias) ? alias : [alias];
43
+ };
44
+
45
+ /**
46
+ * Every spelling citty accepts for each declared option — the name, its camel
47
+ * and kebab forms, and its aliases — mapped to what that option is. Positional
48
+ * arguments aren't flags and don't appear.
49
+ */
50
+ const knownFlags = (argsDef: ArgsDef): Map<string, KnownFlag> => {
51
+ const flags = new Map<string, KnownFlag>();
52
+ for (const [name, def] of Object.entries(argsDef)) {
53
+ if (def.type === "positional") {
54
+ continue;
55
+ }
56
+ const kebab = kebabCase(name);
57
+ const boolean = def.type === "boolean";
58
+ const onByDefault = boolean && "default" in def && def.default === true;
59
+ const flag = {
60
+ boolean,
61
+ display: onByDefault ? `--no-${kebab}` : `--${kebab}`,
62
+ name: kebab,
63
+ takesValue: def.type === "string" || def.type === "enum",
64
+ };
65
+ for (const spelling of [
66
+ name,
67
+ kebabCase(name),
68
+ camelCase(name),
69
+ ...aliasesOf("alias" in def ? def.alias : undefined),
70
+ ]) {
71
+ flags.set(spelling, flag);
72
+ }
73
+ }
74
+ return flags;
75
+ };
76
+
77
+ /** Edit distance between two short strings (insertions, deletions, swaps of one letter). */
78
+ const distance = (from: string, to: string): number => {
79
+ let previous = Array.from({ length: to.length + 1 }, (_, index) => index);
80
+ for (const [row, fromChar] of [...from].entries()) {
81
+ const current = [row + 1];
82
+ for (const [column, toChar] of [...to].entries()) {
83
+ current.push(
84
+ Math.min(
85
+ (previous[column + 1] ?? 0) + 1,
86
+ (current[column] ?? 0) + 1,
87
+ (previous[column] ?? 0) + (fromChar === toChar ? 0 : 1)
88
+ )
89
+ );
90
+ }
91
+ previous = current;
92
+ }
93
+ return previous[to.length] ?? 0;
94
+ };
95
+
96
+ /**
97
+ * The candidate closest to `name`, when it's close enough to be the likely
98
+ * intent: at most two edits away, and fewer edits than half the candidate's
99
+ * length, so a short typo doesn't "suggest" an unrelated short word.
100
+ */
101
+ export const closestMatch = (
102
+ name: string,
103
+ candidates: readonly string[]
104
+ ): string | undefined => {
105
+ let best: { candidate: string; edits: number } | undefined;
106
+ for (const candidate of candidates) {
107
+ const edits = distance(name, candidate);
108
+ if (
109
+ edits <= 2 &&
110
+ edits * 2 < candidate.length &&
111
+ (best === undefined || edits < best.edits)
112
+ ) {
113
+ best = { candidate, edits };
114
+ }
115
+ }
116
+ return best?.candidate;
117
+ };
118
+
119
+ /** A `--name`, `--no-name`, `--name=value`, or `-n` token, taken apart. */
120
+ interface FlagToken {
121
+ /** Whether it carries its value inline (`--port=4000`). */
122
+ hasValue: boolean;
123
+ /** `--name` rather than `-n`. */
124
+ long: boolean;
125
+ /** The name as typed, without dashes or `=value`. */
126
+ name: string;
127
+ /** The negated flag's name, for a `--no-name` token. */
128
+ negated: string | undefined;
129
+ }
130
+
131
+ const parseToken = (arg: string): FlagToken => {
132
+ const long = arg.startsWith("--");
133
+ const [name = ""] = arg.slice(long ? 2 : 1).split("=");
134
+ return {
135
+ hasValue: arg.includes("="),
136
+ long,
137
+ name,
138
+ negated: long && name.startsWith("no-") ? name.slice(3) : undefined,
139
+ };
140
+ };
141
+
142
+ /**
143
+ * How many tokens after this one a declared flag consumes — one for a string
144
+ * flag's separate value (`--port 4000`, read whatever it looks like, as
145
+ * citty's parser does), none otherwise — or undefined when the token names no
146
+ * declared flag. A negation never reads a value; grouped single-letter
147
+ * booleans (`-ab`) are declared when every letter is.
148
+ */
149
+ const declaredWidth = (
150
+ token: FlagToken,
151
+ flags: Map<string, KnownFlag>
152
+ ): number | undefined => {
153
+ const known =
154
+ flags.get(token.name) ??
155
+ (token.negated === undefined ? undefined : flags.get(token.negated));
156
+ if (known) {
157
+ return known.takesValue && !token.hasValue && token.negated === undefined
158
+ ? 1
159
+ : 0;
160
+ }
161
+ const grouped =
162
+ !token.long &&
163
+ token.name.length > 1 &&
164
+ [...token.name].every((letter) => flags.get(letter)?.takesValue === false);
165
+ return grouped ? 0 : undefined;
166
+ };
167
+
168
+ /**
169
+ * An undeclared token as reported, with the declared flag it most resembles.
170
+ * A mistyped negation keeps its `no-` in the suggestion (`--no-instal` →
171
+ * `--no-install`), so the fix doesn't flip what was asked for; negating a flag
172
+ * that takes a value means nothing, so those suggest the flag itself.
173
+ */
174
+ const describeUnknown = (
175
+ token: FlagToken,
176
+ flags: Map<string, KnownFlag>
177
+ ): UnknownFlag => {
178
+ const unknown: UnknownFlag = {
179
+ flag: `${token.long ? "--" : "-"}${token.name}`,
180
+ };
181
+ const names = [...new Set([...flags.values()].map((flag) => flag.name))];
182
+ const match = closestMatch(token.negated ?? token.name, names);
183
+ if (match) {
184
+ const negate = token.negated !== undefined && flags.get(match)?.boolean;
185
+ unknown.suggestion = negate ? `--no-${match}` : `--${match}`;
186
+ }
187
+ return unknown;
188
+ };
189
+
190
+ /**
191
+ * The flags in `rawArgs` that the command's `args` don't declare. citty itself
192
+ * accepts any flag and drops the ones it doesn't know, so a typo like
193
+ * `--isolatd` would silently run a different command than the one intended.
194
+ *
195
+ * Mirrors what citty accepts: every spelling from {@link knownFlags}, a
196
+ * `--no-<flag>` negation of any of them, `--flag=value`, a declared string
197
+ * flag's separate value token, grouped single-letter boolean aliases, and
198
+ * everything after a bare `--`. `accepted` names extra flags the command
199
+ * handles itself (the removed `blume build --adapter`, which gets its own
200
+ * migration message).
201
+ */
202
+ export const unknownFlags = (
203
+ rawArgs: readonly string[],
204
+ argsDef: ArgsDef,
205
+ accepted: readonly string[] = []
206
+ ): UnknownFlag[] => {
207
+ const flags = knownFlags(argsDef);
208
+ const unknown: UnknownFlag[] = [];
209
+ for (let index = 0; index < rawArgs.length; index += 1) {
210
+ const arg = rawArgs[index] ?? "";
211
+ if (arg === "--") {
212
+ break;
213
+ }
214
+ if (!arg.startsWith("-") || arg === "-") {
215
+ continue;
216
+ }
217
+ const token = parseToken(arg);
218
+ const width = declaredWidth(token, flags);
219
+ if (width !== undefined) {
220
+ index += width;
221
+ } else if (!accepted.includes(token.negated ?? token.name)) {
222
+ unknown.push(describeUnknown(token, flags));
223
+ }
224
+ }
225
+ return unknown;
226
+ };
227
+
228
+ /**
229
+ * Flags a command reads from its raw arguments itself instead of declaring
230
+ * them, keyed by command name. `blume build` answers the Blume 1 `--adapter`,
231
+ * `--output`, and `--base` with the `deployment` setting that replaced each,
232
+ * which says more than "unknown option" would.
233
+ */
234
+ export const COMMAND_HANDLED_FLAGS = new Map([
235
+ ["build", ["adapter", "output", "base"]],
236
+ ]);
237
+
238
+ /**
239
+ * The error for a command run with flags it doesn't declare: each unknown
240
+ * flag (with its likely intended spelling), then every flag the command does
241
+ * take, so the fix is on screen without a trip to `--help`.
242
+ */
243
+ export const unknownFlagsDiagnostic = (
244
+ command: string,
245
+ unknown: readonly UnknownFlag[],
246
+ argsDef: ArgsDef
247
+ ): Diagnostic => {
248
+ const listed = unknown
249
+ .map(({ flag, suggestion }) =>
250
+ suggestion ? `${flag} (did you mean ${suggestion}?)` : flag
251
+ )
252
+ .join(", ");
253
+ const declared = [
254
+ ...new Set([...knownFlags(argsDef).values()].map((flag) => flag.display)),
255
+ ].toSorted();
256
+ const takes =
257
+ declared.length > 0
258
+ ? `It takes ${declared.join(", ")}.`
259
+ : "It takes no options.";
260
+ return {
261
+ code: "BLUME_UNKNOWN_OPTION",
262
+ message: `blume ${command} doesn't know ${unknown.length === 1 ? "the option" : "the options"} ${listed}.`,
263
+ severity: "error",
264
+ suggestion: `${takes} Run \`blume ${command} --help\` for what each does.`,
265
+ };
266
+ };
@@ -0,0 +1,52 @@
1
+ import { existsSync } from "node:fs";
2
+
3
+ import { dirname, join } from "pathe";
4
+
5
+ import { packageDirFrom } from "../astro/render-deps.ts";
6
+ import type { Diagnostic } from "../core/types.ts";
7
+
8
+ /** Whether `root` or one of its ancestors holds a Yarn Plug'n'Play manifest. */
9
+ const hasPnpManifest = (root: string): boolean => {
10
+ let dir = root;
11
+ while (true) {
12
+ if (existsSync(join(dir, ".pnp.cjs")) || existsSync(join(dir, ".pnp.js"))) {
13
+ return true;
14
+ }
15
+ const parent = dirname(dir);
16
+ if (parent === dir) {
17
+ return false;
18
+ }
19
+ dir = parent;
20
+ }
21
+ };
22
+
23
+ /**
24
+ * The diagnostic for a project installed with Yarn Plug'n'Play, or null.
25
+ *
26
+ * Plug'n'Play installs no `node_modules`, and the Astro project Blume
27
+ * generates in `.blume/` imports Astro and Blume's dependencies by name, which
28
+ * only a `node_modules` tree resolves — so under PnP the build dies loading
29
+ * `astro/config`, a failure that reads like a bug in Blume. Caught up front
30
+ * instead: when the command runs under the PnP runtime (`process.versions.pnp`,
31
+ * set by `yarn run`), or when a `.pnp.cjs` manifest sits in the project with no
32
+ * `node_modules` copy of Blume beside it.
33
+ */
34
+ export const yarnPnpDiagnostic = (
35
+ root: string,
36
+ pnpVersion: string | undefined = process.versions.pnp
37
+ ): Diagnostic | null => {
38
+ const underPnp =
39
+ pnpVersion !== undefined ||
40
+ (hasPnpManifest(root) && packageDirFrom("blume", root) === null);
41
+ if (!underPnp) {
42
+ return null;
43
+ }
44
+ return {
45
+ code: "BLUME_YARN_PNP",
46
+ message:
47
+ "Yarn Plug'n'Play isn't supported: the Astro project Blume generates in `.blume/` resolves Astro and Blume's dependencies from a `node_modules` folder, which Plug'n'Play doesn't create.",
48
+ severity: "error",
49
+ suggestion:
50
+ "Add `nodeLinker: node-modules` to `.yarnrc.yml`, run `yarn install`, then run this command again.",
51
+ };
52
+ };
@@ -110,7 +110,13 @@ const accordionId = id ?? componentSlug(title);
110
110
  return;
111
111
  }
112
112
 
113
- history.replaceState(null, "", `#${encodeURIComponent(accordion.id)}`);
113
+ // Keep the entry's state: the client router ignores a popstate whose
114
+ // state is null, so Back to this page would change only the URL.
115
+ history.replaceState(
116
+ history.state,
117
+ "",
118
+ `#${encodeURIComponent(accordion.id)}`
119
+ );
114
120
  },
115
121
  true
116
122
  );
@@ -1,4 +1,6 @@
1
1
  ---
2
+ import { isExternalUrl } from "../../core/base-path.ts";
3
+ import { newTabAttrs } from "../../core/new-tab.ts";
2
4
  import {
3
5
  ADMONITION_ICON,
4
6
  ADMONITION_ICON_CLASS,
@@ -23,7 +25,7 @@ interface Props {
23
25
  const { arrow, color, cta, horizontal, href, icon, img, title, type } =
24
26
  Astro.props;
25
27
  const Tag = href ? "a" : "div";
26
- const external = href?.startsWith("http");
28
+ const external = href !== undefined && isExternalUrl(href);
27
29
  const isHorizontal = horizontal === true || horizontal === "true";
28
30
  const showArrow =
29
31
  href && arrow === undefined ? external : arrow === true || arrow === "true";
@@ -51,8 +53,7 @@ const variantClass = {
51
53
  ]}
52
54
  data-blume-card
53
55
  href={href === undefined ? undefined : contentHref(href)}
54
- rel={external ? "noreferrer" : undefined}
55
- target={external ? "_blank" : undefined}
56
+ {...newTabAttrs(href)}
56
57
  >
57
58
  {
58
59
  img && (
@@ -1,4 +1,8 @@
1
1
  ---
2
+ import data from "blume:data";
3
+
4
+ import { contentStrings } from "./content-strings.ts";
5
+
2
6
  interface ColorValue {
3
7
  dark?: string;
4
8
  light?: string;
@@ -17,12 +21,22 @@ const displayValue =
17
21
  lightValue && darkValue && lightValue !== darkValue
18
22
  ? `${lightValue} / ${darkValue}`
19
23
  : lightValue;
24
+ const { actions: actionStrings, content: strings } = contentStrings(
25
+ data,
26
+ Astro.currentLocale
27
+ );
28
+ const label = strings.copyColor
29
+ .replace("{name}", name)
30
+ .replace("{value}", displayValue ?? "");
20
31
  ---
21
32
 
22
33
  <button
23
- aria-label={`Copy ${name} color ${displayValue}`}
34
+ aria-label={label}
24
35
  class="group flex w-full cursor-pointer flex-col gap-2.5 text-center focus:outline-none"
25
- data-blume-color-copy={displayValue}
36
+ data-blume-color-copy
37
+ data-copied={actionStrings.copied}
38
+ data-dark={darkValue}
39
+ data-light={lightValue}
26
40
  style={`--blume-color-light:${lightValue};--blume-color-dark:${darkValue};`}
27
41
  type="button"
28
42
  >
@@ -69,13 +83,17 @@ const displayValue =
69
83
  return;
70
84
  }
71
85
 
72
- if (!(await copyText(button.dataset.blumeColorCopy ?? ""))) {
86
+ // The value the swatch shows right now: a theme-aware color copies the
87
+ // active theme's value, not the "light / dark" pair it lists.
88
+ const dark = document.documentElement.dataset.theme === "dark";
89
+ const value = (dark ? button.dataset.dark : button.dataset.light) ?? "";
90
+ if (!(await copyText(value))) {
73
91
  return;
74
92
  }
75
93
 
76
94
  const status = button.querySelector<HTMLElement>("[data-blume-color-status]");
77
95
  if (status) {
78
- flashLabel(status, "Copied");
96
+ flashLabel(status, button.dataset.copied ?? "Copied!");
79
97
  }
80
98
  });
81
99
  }
@@ -5,6 +5,7 @@
5
5
  // If the API is unreachable the card still renders, just without counts.
6
6
  import { getSecret } from "astro:env/server";
7
7
  import { apiUrl, PUBLIC_HOST_URL } from "../../core/github.ts";
8
+ import { NEW_TAB_ATTRS } from "../../core/new-tab.ts";
8
9
  import { resolveIcon } from "../../theme/icons.ts";
9
10
  import data from "blume:data";
10
11
  import { GITHUB_MARK } from "../github-mark.ts";
@@ -69,8 +70,7 @@ const statIcon =
69
70
  <a
70
71
  class="not-prose my-6 flex flex-col gap-2 rounded-blume border border-border p-4 no-underline! transition-colors hover:border-foreground/30 hover:bg-muted/40"
71
72
  href={`${host}/${owner}/${repo}`}
72
- rel="noreferrer"
73
- target="_blank"
73
+ {...NEW_TAB_ATTRS}
74
74
  >
75
75
  <span class="flex items-center gap-2 font-medium text-foreground text-sm">
76
76
  <svg