blume 2.0.3 → 2.1.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 (455) hide show
  1. package/AGENTS.md +1 -0
  2. package/CHANGELOG.md +48 -0
  3. package/README.md +1 -1
  4. package/dist/cli/{chunk-1d7ve1dm.js → chunk-0gz36akr.js} +18 -2
  5. package/dist/cli/{chunk-1d7ve1dm.js.map → chunk-0gz36akr.js.map} +3 -3
  6. package/dist/cli/{chunk-2eytanqx.js → chunk-1n228xqb.js} +2 -2
  7. package/dist/cli/{chunk-yfyb25rh.js → chunk-2f3ndkpw.js} +24 -8
  8. package/dist/cli/chunk-2f3ndkpw.js.map +14 -0
  9. package/dist/cli/{chunk-r20tn01b.js → chunk-2f7n4qzt.js} +8 -2
  10. package/dist/cli/{chunk-r20tn01b.js.map → chunk-2f7n4qzt.js.map} +3 -3
  11. package/dist/cli/{chunk-35d4wj9f.js → chunk-2n4ps1b3.js} +7 -7
  12. package/dist/cli/{chunk-j85vccga.js → chunk-43zcf4gz.js} +97 -57
  13. package/dist/cli/{chunk-j85vccga.js.map → chunk-43zcf4gz.js.map} +6 -6
  14. package/dist/cli/{chunk-e04dxsz1.js → chunk-4ejxbzee.js} +1 -1
  15. package/dist/cli/{chunk-5m5nmvyq.js → chunk-4h8z9vv5.js} +233 -39
  16. package/dist/cli/chunk-4h8z9vv5.js.map +16 -0
  17. package/dist/cli/{chunk-5f86nr5m.js → chunk-5cg2rzgf.js} +18 -16
  18. package/dist/cli/{chunk-5f86nr5m.js.map → chunk-5cg2rzgf.js.map} +2 -2
  19. package/dist/cli/{chunk-tzmab476.js → chunk-5ffywsmb.js} +4 -4
  20. package/dist/cli/{chunk-2z928egk.js → chunk-5wj2qwn2.js} +5 -5
  21. package/dist/cli/chunk-6bm0xpgd.js +18 -0
  22. package/dist/cli/chunk-6bm0xpgd.js.map +10 -0
  23. package/dist/cli/{chunk-vg9r4eb9.js → chunk-713mngdq.js} +12 -5
  24. package/dist/cli/{chunk-vg9r4eb9.js.map → chunk-713mngdq.js.map} +3 -3
  25. package/dist/cli/{chunk-5xvm6tfj.js → chunk-9geymqns.js} +17 -15
  26. package/dist/cli/{chunk-5xvm6tfj.js.map → chunk-9geymqns.js.map} +2 -2
  27. package/dist/cli/{chunk-q58y5e6a.js → chunk-9xr4dgee.js} +26 -17
  28. package/dist/cli/chunk-9xr4dgee.js.map +10 -0
  29. package/dist/cli/{chunk-b07cmahc.js → chunk-amrb6hgh.js} +2 -2
  30. package/dist/cli/chunk-cm89scdv.js +443 -0
  31. package/dist/cli/chunk-cm89scdv.js.map +11 -0
  32. package/dist/cli/{chunk-akbpwfxc.js → chunk-cmtcnh9f.js} +2 -2
  33. package/dist/cli/chunk-cy5bm0j0.js +104 -0
  34. package/dist/cli/chunk-cy5bm0j0.js.map +11 -0
  35. package/dist/cli/{chunk-crgn1q09.js → chunk-e7vvk5ya.js} +4 -4
  36. package/dist/cli/{chunk-pehfxfta.js → chunk-g2z9x01v.js} +6 -98
  37. package/dist/cli/chunk-g2z9x01v.js.map +10 -0
  38. package/dist/cli/{chunk-tkacnehg.js → chunk-gp84za0h.js} +2 -2
  39. package/dist/cli/{chunk-wrr3j9w9.js → chunk-h2a48yhd.js} +186 -63
  40. package/dist/cli/chunk-h2a48yhd.js.map +36 -0
  41. package/dist/cli/{chunk-hm3vjy5s.js → chunk-jnwj5kjj.js} +14 -9
  42. package/dist/cli/{chunk-hm3vjy5s.js.map → chunk-jnwj5kjj.js.map} +4 -4
  43. package/dist/cli/chunk-kwrg63tm.js +31 -0
  44. package/dist/cli/chunk-kwrg63tm.js.map +10 -0
  45. package/dist/cli/{chunk-2hsdwb9n.js → chunk-nd1821sk.js} +18 -16
  46. package/dist/cli/{chunk-2hsdwb9n.js.map → chunk-nd1821sk.js.map} +2 -2
  47. package/dist/cli/{chunk-6dsbexzp.js → chunk-ntv4qrt7.js} +17 -15
  48. package/dist/cli/{chunk-6dsbexzp.js.map → chunk-ntv4qrt7.js.map} +2 -2
  49. package/dist/cli/{chunk-r9rcc4w7.js → chunk-p804f3pe.js} +7 -7
  50. package/dist/cli/{chunk-ey84smr6.js → chunk-py62fewh.js} +6 -6
  51. package/dist/cli/{chunk-ey84smr6.js.map → chunk-py62fewh.js.map} +1 -1
  52. package/dist/cli/chunk-q3wxxq39.js +126 -0
  53. package/dist/cli/chunk-q3wxxq39.js.map +11 -0
  54. package/dist/cli/{chunk-9t7a85s3.js → chunk-rekqz4qg.js} +23 -13
  55. package/dist/cli/chunk-rekqz4qg.js.map +10 -0
  56. package/dist/cli/{chunk-8ktnccpt.js → chunk-ta27feev.js} +1 -1
  57. package/dist/cli/{chunk-pv29h0wf.js → chunk-xkz5xbtv.js} +3476 -822
  58. package/dist/cli/chunk-xkz5xbtv.js.map +213 -0
  59. package/dist/cli/{chunk-a58773jm.js → chunk-y4ykbark.js} +2 -2
  60. package/dist/cli/{chunk-p3v96n38.js → chunk-y5h4r2y0.js} +4 -4
  61. package/dist/cli/{chunk-acanzt5p.js → chunk-yj17vs39.js} +6 -6
  62. package/dist/cli/{chunk-p73c0m7w.js → chunk-yxmk4pec.js} +16 -14
  63. package/dist/cli/{chunk-p73c0m7w.js.map → chunk-yxmk4pec.js.map} +2 -2
  64. package/dist/cli/{chunk-3em5wd2y.js → chunk-zccbjcj0.js} +4 -3
  65. package/dist/cli/{chunk-3em5wd2y.js.map → chunk-zccbjcj0.js.map} +2 -2
  66. package/dist/cli/{chunk-c8chx29p.js → chunk-zf748avv.js} +384 -207
  67. package/dist/cli/chunk-zf748avv.js.map +37 -0
  68. package/dist/cli/{chunk-g4hq16wv.js → chunk-zhvd6adm.js} +16 -14
  69. package/dist/cli/{chunk-g4hq16wv.js.map → chunk-zhvd6adm.js.map} +2 -2
  70. package/dist/cli/index.js +26 -20
  71. package/dist/cli/index.js.map +5 -5
  72. package/dist/types/ai/agent-surface.d.ts +8 -7
  73. package/dist/types/ai/ai-catalog.d.ts +7 -0
  74. package/dist/types/ai/ask-context.d.ts +22 -0
  75. package/dist/types/ai/ask.d.ts +271 -58
  76. package/dist/types/ai/index.d.ts +2 -2
  77. package/dist/types/ai/site-skill.d.ts +26 -0
  78. package/dist/types/ai/skills.d.ts +16 -0
  79. package/dist/types/astro/integration.d.ts +8 -0
  80. package/dist/types/captcha/hcaptcha.d.ts +27 -0
  81. package/dist/types/captcha/index.d.ts +28 -0
  82. package/dist/types/captcha/schema.d.ts +29 -0
  83. package/dist/types/captcha/turnstile.d.ts +28 -0
  84. package/dist/types/components/content/api-field.d.ts +59 -0
  85. package/dist/types/components/content/api-page.d.ts +95 -0
  86. package/dist/types/components/layout/nav-utils.d.ts +26 -0
  87. package/dist/types/components/openapi/helpers.d.ts +137 -0
  88. package/dist/types/components/openapi/security.d.ts +85 -0
  89. package/dist/types/consent/ethyca.d.ts +48 -0
  90. package/dist/types/consent/index.d.ts +37 -0
  91. package/dist/types/consent/native.d.ts +28 -0
  92. package/dist/types/consent/osano.d.ts +42 -0
  93. package/dist/types/consent/schema.d.ts +110 -0
  94. package/dist/types/core/config-input.d.ts +187 -20
  95. package/dist/types/core/data.d.ts +49 -4
  96. package/dist/types/core/footer.d.ts +8 -0
  97. package/dist/types/core/i18n-ui.d.ts +86 -0
  98. package/dist/types/core/includes.d.ts +8 -2
  99. package/dist/types/core/localizable.d.ts +7 -0
  100. package/dist/types/core/page-modes.d.ts +29 -0
  101. package/dist/types/core/redirect-patterns.d.ts +144 -0
  102. package/dist/types/core/related.d.ts +40 -0
  103. package/dist/types/core/schema.d.ts +551 -56
  104. package/dist/types/core/sources/read.d.ts +5 -0
  105. package/dist/types/core/types.d.ts +1 -1
  106. package/dist/types/core/variables.d.ts +42 -0
  107. package/dist/types/deploy/node-headers.d.ts +13 -2
  108. package/dist/types/deploy/platforms/cloudflare.d.ts +5 -0
  109. package/dist/types/deploy/platforms/netlify.d.ts +7 -0
  110. package/dist/types/deploy/platforms/vercel.d.ts +6 -0
  111. package/dist/types/deploy/redirects.d.ts +39 -11
  112. package/dist/types/deploy/vercel-negotiation.d.ts +9 -0
  113. package/dist/types/markdown/code-title.d.ts +17 -0
  114. package/dist/types/markdown/features.d.ts +3 -2
  115. package/dist/types/narration/build.d.ts +70 -0
  116. package/dist/types/narration/provider.d.ts +26 -0
  117. package/dist/types/narration/script.d.ts +154 -0
  118. package/dist/types/openapi/model.d.ts +12 -6
  119. package/dist/types/openapi/overlay.d.ts +54 -0
  120. package/dist/types/openapi/parse.d.ts +13 -0
  121. package/dist/types/openapi/references.d.ts +14 -4
  122. package/dist/types/ratelimit/cloudflare.d.ts +39 -0
  123. package/dist/types/ratelimit/index.d.ts +27 -0
  124. package/dist/types/ratelimit/memory.d.ts +36 -0
  125. package/dist/types/ratelimit/schema.d.ts +111 -0
  126. package/dist/types/ratelimit/upstash.d.ts +21 -0
  127. package/dist/types/ratelimit/wrangler.d.ts +23 -0
  128. package/dist/types/reference/asyncapi.d.ts +10 -10
  129. package/dist/types/reference/graphql.d.ts +13 -10
  130. package/dist/types/reference/openapi.d.ts +33 -12
  131. package/dist/types/reference/options.d.ts +45 -5
  132. package/dist/types/reference/scalar.d.ts +13 -0
  133. package/dist/types/reference/schema.d.ts +60 -36
  134. package/dist/types/search/documents.d.ts +12 -1
  135. package/dist/types/search/orama-index.d.ts +4 -0
  136. package/dist/types/seo/metatags.d.ts +20 -0
  137. package/docs/02-deployment.mdx +41 -5
  138. package/docs/03-upgrading.mdx +4 -4
  139. package/docs/04-migrating.mdx +1 -1
  140. package/docs/advanced/changelog.mdx +2 -2
  141. package/docs/advanced/skills.mdx +14 -0
  142. package/docs/cli/audit.mdx +21 -1
  143. package/docs/cli/index.mdx +1 -0
  144. package/docs/configuration/analytics.mdx +3 -1
  145. package/docs/configuration/assistant.mdx +188 -36
  146. package/docs/configuration/consent.mdx +100 -0
  147. package/docs/configuration/customization.mdx +4 -4
  148. package/docs/configuration/index.mdx +63 -5
  149. package/docs/configuration/meta.ts +3 -0
  150. package/docs/configuration/narration.mdx +119 -0
  151. package/docs/configuration/rate-limiting.mdx +69 -0
  152. package/docs/configuration/search.mdx +29 -1
  153. package/docs/configuration/theming.mdx +3 -1
  154. package/docs/content/components.mdx +106 -0
  155. package/docs/content/frontmatter.mdx +76 -0
  156. package/docs/content/i18n.mdx +38 -3
  157. package/docs/content/includes.mdx +16 -0
  158. package/docs/content/meta.mdx +1 -0
  159. package/docs/content/meta.ts +1 -0
  160. package/docs/content/navigation.mdx +28 -6
  161. package/docs/content/sources/contentful.mdx +32 -0
  162. package/docs/content/sources/custom.mdx +39 -0
  163. package/docs/content/sources/github-releases.mdx +31 -0
  164. package/docs/content/sources/index.mdx +91 -0
  165. package/docs/content/sources/meta.ts +16 -0
  166. package/docs/content/sources/notion.mdx +32 -0
  167. package/docs/content/sources/obsidian.mdx +37 -0
  168. package/docs/content/sources/payload.mdx +30 -0
  169. package/docs/content/sources/remote-mdx.mdx +40 -0
  170. package/docs/content/sources/sanity.mdx +29 -0
  171. package/docs/content/sources/strapi.mdx +31 -0
  172. package/docs/content/syntax.mdx +67 -2
  173. package/docs/content/variables.mdx +41 -0
  174. package/docs/discoverability/agent-discovery.mdx +29 -2
  175. package/docs/discoverability/index.mdx +1 -1
  176. package/docs/discoverability/llms-txt.mdx +1 -1
  177. package/docs/discoverability/metadata.mdx +17 -0
  178. package/docs/references/api-pages.mdx +74 -0
  179. package/docs/references/asyncapi.mdx +1 -1
  180. package/docs/references/graphql.mdx +2 -2
  181. package/docs/references/meta.ts +1 -1
  182. package/docs/references/openapi.mdx +102 -3
  183. package/docs/references/scalar.mdx +3 -1
  184. package/package.json +36 -1
  185. package/skills/blume/SKILL.md +3 -0
  186. package/skills/blume-migrate/SKILL.md +5 -5
  187. package/skills/blume-migrate/references/docusaurus.md +3 -3
  188. package/skills/blume-migrate/references/mintlify.md +37 -19
  189. package/skills/blume-migrate/references/nextra.md +2 -2
  190. package/skills/blume-migrate/references/starlight.md +2 -1
  191. package/skills/blume-migrate/scripts/mintlify-codemod.mjs +60 -14
  192. package/skills/blume-write-skill/SKILL.md +82 -0
  193. package/src/ai/agent-readability.ts +2 -1
  194. package/src/ai/agent-surface.ts +9 -7
  195. package/src/ai/ai-catalog.ts +6 -3
  196. package/src/ai/ask-context.ts +73 -20
  197. package/src/ai/ask-data.ts +6 -0
  198. package/src/ai/ask-tools.ts +142 -0
  199. package/src/ai/ask.ts +354 -76
  200. package/src/ai/component-markdown.ts +75 -0
  201. package/src/ai/cors.ts +2 -0
  202. package/src/ai/index.ts +12 -0
  203. package/src/ai/llms.ts +6 -2
  204. package/src/ai/markdown.ts +2 -1
  205. package/src/ai/mcp/data.ts +6 -0
  206. package/src/ai/openapi-components.ts +9 -3
  207. package/src/ai/site-skill.ts +274 -0
  208. package/src/ai/skills.ts +35 -2
  209. package/src/ai/write-skill.ts +97 -0
  210. package/src/astro/generate.ts +132 -18
  211. package/src/astro/index.ts +1 -0
  212. package/src/astro/integration.ts +35 -0
  213. package/src/astro/module-types.ts +6 -0
  214. package/src/astro/templates.ts +283 -30
  215. package/src/astro/variables.ts +31 -0
  216. package/src/audit/catalog.ts +19 -0
  217. package/src/audit/checks/contrast.ts +183 -0
  218. package/src/audit/checks/i18n.ts +2 -3
  219. package/src/audit/checks/indexability.ts +2 -3
  220. package/src/audit/checks/links.ts +5 -12
  221. package/src/audit/checks/sitemap.ts +2 -3
  222. package/src/audit/redirects.ts +46 -15
  223. package/src/audit/run.ts +2 -0
  224. package/src/audit/types.ts +2 -1
  225. package/src/blume-modules.d.ts +7 -0
  226. package/src/captcha/client.ts +152 -0
  227. package/src/captcha/hcaptcha.ts +36 -0
  228. package/src/captcha/index.ts +28 -0
  229. package/src/captcha/schema.ts +32 -0
  230. package/src/captcha/turnstile.ts +38 -0
  231. package/src/captcha/verify.ts +71 -0
  232. package/src/cli/command-meta.ts +5 -0
  233. package/src/cli/commands/doctor.ts +22 -16
  234. package/src/cli/commands/skill.ts +96 -0
  235. package/src/cli/index.ts +5 -0
  236. package/src/cli/required-secrets.ts +71 -29
  237. package/src/components/BlumePage.astro +2 -0
  238. package/src/components/content/ApiEndpoint.astro +18 -0
  239. package/src/components/content/ApiField.astro +79 -0
  240. package/src/components/content/ApiPlayground.astro +62 -0
  241. package/src/components/content/ApiRail.astro +19 -0
  242. package/src/components/content/Color.astro +1 -0
  243. package/src/components/content/FileTree.astro +1 -0
  244. package/src/components/content/GithubInfo.astro +1 -0
  245. package/src/components/content/Panel.astro +1 -0
  246. package/src/components/content/ParamField.astro +25 -0
  247. package/src/components/content/RequestExample.astro +17 -0
  248. package/src/components/content/ResponseExample.astro +17 -0
  249. package/src/components/content/ResponseField.astro +32 -0
  250. package/src/components/content/Step.astro +1 -0
  251. package/src/components/content/Tile.astro +1 -0
  252. package/src/components/content/Tooltip.astro +1 -0
  253. package/src/components/content/Tree.astro +1 -0
  254. package/src/components/content/TypeTable.astro +4 -1
  255. package/src/components/content/View.astro +21 -0
  256. package/src/components/content/ViewSwitcher.astro +168 -0
  257. package/src/components/content/api-field.ts +100 -0
  258. package/src/components/content/api-page.ts +224 -0
  259. package/src/components/content/view-switcher.ts +71 -0
  260. package/src/components/index.ts +2 -0
  261. package/src/components/islands/Assistant.astro +10 -1
  262. package/src/components/islands/assistant.tsx +104 -14
  263. package/src/components/islands/code-question.ts +62 -0
  264. package/src/components/islands/hooks.ts +110 -21
  265. package/src/components/islands/support-link.ts +68 -0
  266. package/src/components/layout/Analytics.astro +11 -2
  267. package/src/components/layout/Banner.astro +14 -10
  268. package/src/components/layout/Breadcrumbs.astro +6 -2
  269. package/src/components/layout/ConsentBanner.astro +62 -0
  270. package/src/components/layout/ConsentHead.astro +38 -0
  271. package/src/components/layout/Directory.astro +94 -0
  272. package/src/components/layout/DrawerSwitchers.astro +51 -0
  273. package/src/components/layout/Empty.astro +2 -2
  274. package/src/components/layout/Header.astro +122 -80
  275. package/src/components/layout/LanguageSwitcher.astro +48 -15
  276. package/src/components/layout/NarrationPlayer.astro +1085 -0
  277. package/src/components/layout/NavSelector.astro +33 -7
  278. package/src/components/layout/PageFeedback.astro +54 -49
  279. package/src/components/layout/PageLayout.astro +71 -3
  280. package/src/components/layout/ReferenceLayout.astro +17 -6
  281. package/src/components/layout/RelatedPages.astro +42 -0
  282. package/src/components/layout/RootLayout.astro +308 -45
  283. package/src/components/layout/Search.astro +31 -17
  284. package/src/components/layout/SiteFooter.astro +124 -0
  285. package/src/components/layout/SiteMetatags.astro +16 -0
  286. package/src/components/layout/consent/native.ts +79 -0
  287. package/src/components/layout/consent/types.ts +37 -0
  288. package/src/components/layout/footer-links.ts +53 -0
  289. package/src/components/layout/footer-socials.ts +87 -0
  290. package/src/components/layout/locale-redirect.ts +107 -0
  291. package/src/components/layout/nav-utils.ts +83 -0
  292. package/src/components/layout/page-feedback.ts +96 -0
  293. package/src/components/layout/search/analytics.ts +98 -0
  294. package/src/components/layout/search/flexsearch.ts +17 -5
  295. package/src/components/layout/search/orama-cloud.ts +26 -14
  296. package/src/components/layout/search/types.ts +20 -0
  297. package/src/components/layout/search/typesense.ts +5 -1
  298. package/src/components/openapi/Operation.astro +161 -13
  299. package/src/components/openapi/RequestBody.astro +6 -4
  300. package/src/components/openapi/RequestPanel.astro +59 -7
  301. package/src/components/openapi/Responses.astro +6 -4
  302. package/src/components/openapi/async-snippets.ts +4 -4
  303. package/src/components/openapi/code-samples.ts +97 -0
  304. package/src/components/openapi/security.ts +6 -3
  305. package/src/components/openapi/snippets.ts +869 -8
  306. package/src/components/props.ts +6 -0
  307. package/src/consent/client.ts +95 -0
  308. package/src/consent/clients.ts +19 -0
  309. package/src/consent/ethyca.ts +71 -0
  310. package/src/consent/head.ts +24 -0
  311. package/src/consent/index.ts +37 -0
  312. package/src/consent/init.ts +29 -0
  313. package/src/consent/native.ts +36 -0
  314. package/src/consent/osano.ts +59 -0
  315. package/src/consent/schema.ts +30 -0
  316. package/src/core/builtin-tags.ts +5 -0
  317. package/src/core/client-address.ts +19 -0
  318. package/src/core/config-input.ts +194 -20
  319. package/src/core/data.ts +44 -4
  320. package/src/core/diagnostics.ts +3 -2
  321. package/src/core/footer.ts +26 -0
  322. package/src/core/graph.ts +39 -36
  323. package/src/core/i18n-ui.ts +82 -2
  324. package/src/core/includes.ts +20 -3
  325. package/src/core/links.ts +16 -2
  326. package/src/core/localizable.ts +26 -0
  327. package/src/core/navigation.ts +43 -12
  328. package/src/core/page-modes.ts +56 -0
  329. package/src/core/project-graph.ts +111 -5
  330. package/src/core/redirect-patterns.ts +491 -0
  331. package/src/core/related.ts +131 -0
  332. package/src/core/schema.ts +318 -64
  333. package/src/core/sources/normalize.ts +2 -1
  334. package/src/core/sources/read.ts +8 -3
  335. package/src/core/types.ts +1 -1
  336. package/src/core/ui-packs/ar.ts +43 -0
  337. package/src/core/ui-packs/bg.ts +45 -0
  338. package/src/core/ui-packs/bn.ts +43 -0
  339. package/src/core/ui-packs/ca.ts +46 -0
  340. package/src/core/ui-packs/cs.ts +44 -0
  341. package/src/core/ui-packs/da.ts +45 -0
  342. package/src/core/ui-packs/de.ts +46 -0
  343. package/src/core/ui-packs/el.ts +45 -0
  344. package/src/core/ui-packs/es.ts +46 -0
  345. package/src/core/ui-packs/fa.ts +45 -0
  346. package/src/core/ui-packs/fi.ts +45 -0
  347. package/src/core/ui-packs/fr.ts +46 -0
  348. package/src/core/ui-packs/he.ts +43 -0
  349. package/src/core/ui-packs/hi.ts +44 -0
  350. package/src/core/ui-packs/hr.ts +45 -0
  351. package/src/core/ui-packs/hu.ts +44 -0
  352. package/src/core/ui-packs/id.ts +45 -0
  353. package/src/core/ui-packs/it.ts +45 -0
  354. package/src/core/ui-packs/ja.ts +45 -0
  355. package/src/core/ui-packs/ko.ts +44 -0
  356. package/src/core/ui-packs/nl.ts +46 -0
  357. package/src/core/ui-packs/no.ts +44 -0
  358. package/src/core/ui-packs/pl.ts +45 -0
  359. package/src/core/ui-packs/pt-br.ts +46 -0
  360. package/src/core/ui-packs/pt.ts +45 -0
  361. package/src/core/ui-packs/ro.ts +45 -0
  362. package/src/core/ui-packs/ru.ts +45 -0
  363. package/src/core/ui-packs/sk.ts +44 -0
  364. package/src/core/ui-packs/sr.ts +45 -0
  365. package/src/core/ui-packs/sv.ts +44 -0
  366. package/src/core/ui-packs/th.ts +43 -0
  367. package/src/core/ui-packs/tr.ts +45 -0
  368. package/src/core/ui-packs/uk.ts +45 -0
  369. package/src/core/ui-packs/vi.ts +45 -0
  370. package/src/core/ui-packs/zh-tw.ts +43 -0
  371. package/src/core/ui-packs/zh.ts +43 -0
  372. package/src/core/variables.ts +103 -0
  373. package/src/deploy/artifacts.ts +77 -8
  374. package/src/deploy/cloudflare-negotiation.ts +35 -5
  375. package/src/deploy/headers.ts +2 -1
  376. package/src/deploy/node-headers.ts +63 -9
  377. package/src/deploy/platforms/cloudflare.ts +32 -0
  378. package/src/deploy/platforms/netlify.ts +33 -1
  379. package/src/deploy/platforms/vercel.ts +37 -2
  380. package/src/deploy/redirects.ts +91 -24
  381. package/src/deploy/vercel-negotiation.ts +36 -0
  382. package/src/markdown/api-rail.ts +259 -0
  383. package/src/markdown/code-title.ts +35 -9
  384. package/src/markdown/features.ts +3 -2
  385. package/src/markdown/fence-meta.ts +2 -0
  386. package/src/markdown/include.ts +11 -1
  387. package/src/markdown/index.ts +28 -5
  388. package/src/markdown/math.ts +4 -4
  389. package/src/markdown/variables.ts +56 -0
  390. package/src/markdown/views.ts +82 -0
  391. package/src/narration/build.ts +412 -0
  392. package/src/narration/player.ts +249 -0
  393. package/src/narration/provider.ts +29 -0
  394. package/src/narration/script.ts +592 -0
  395. package/src/og/card.ts +7 -6
  396. package/src/openapi/model.ts +57 -24
  397. package/src/openapi/overlay.ts +256 -0
  398. package/src/openapi/parse.ts +55 -2
  399. package/src/openapi/references.ts +21 -5
  400. package/src/openapi/render-mdx.ts +5 -1
  401. package/src/openapi/scalar.ts +40 -6
  402. package/src/openapi/source.ts +1 -1
  403. package/src/ratelimit/cloudflare.ts +54 -0
  404. package/src/ratelimit/index.ts +30 -0
  405. package/src/ratelimit/memory.ts +45 -0
  406. package/src/ratelimit/runtime.ts +229 -0
  407. package/src/ratelimit/schema.ts +28 -0
  408. package/src/ratelimit/upstash.ts +30 -0
  409. package/src/ratelimit/wrangler.ts +70 -0
  410. package/src/reference/asyncapi.ts +2 -2
  411. package/src/reference/graphql.ts +5 -2
  412. package/src/reference/openapi.ts +21 -7
  413. package/src/reference/options.ts +51 -7
  414. package/src/reference/scalar.ts +33 -8
  415. package/src/registry/eject.ts +20 -4
  416. package/src/registry/registry.ts +7 -0
  417. package/src/search/documents.ts +26 -2
  418. package/src/search/orama-index.ts +28 -3
  419. package/src/search/pagefind-ranking.ts +39 -0
  420. package/src/search/sync/algolia.ts +15 -4
  421. package/src/search/sync/orama-cloud.ts +3 -0
  422. package/src/search/sync/typesense.ts +5 -0
  423. package/src/seo/metatags.ts +67 -0
  424. package/src/theme/chrome-icons.ts +1 -0
  425. package/src/theme/color.ts +500 -0
  426. package/src/theme/entry.ts +56 -3
  427. package/src/theme/palette.ts +121 -45
  428. package/src/translate/prompts.ts +1 -0
  429. package/src/translate/validate.ts +8 -2
  430. package/src/upgrade/upgrade.ts +4 -171
  431. package/dist/cli/chunk-364znk6q.js +0 -75
  432. package/dist/cli/chunk-364znk6q.js.map +0 -11
  433. package/dist/cli/chunk-5m5nmvyq.js.map +0 -13
  434. package/dist/cli/chunk-9t7a85s3.js.map +0 -10
  435. package/dist/cli/chunk-c8chx29p.js.map +0 -36
  436. package/dist/cli/chunk-pehfxfta.js.map +0 -10
  437. package/dist/cli/chunk-pv29h0wf.js.map +0 -190
  438. package/dist/cli/chunk-q58y5e6a.js.map +0 -10
  439. package/dist/cli/chunk-wrr3j9w9.js.map +0 -35
  440. package/dist/cli/chunk-yfyb25rh.js.map +0 -14
  441. package/docs/content/sources.mdx +0 -334
  442. /package/dist/cli/{chunk-2eytanqx.js.map → chunk-1n228xqb.js.map} +0 -0
  443. /package/dist/cli/{chunk-35d4wj9f.js.map → chunk-2n4ps1b3.js.map} +0 -0
  444. /package/dist/cli/{chunk-e04dxsz1.js.map → chunk-4ejxbzee.js.map} +0 -0
  445. /package/dist/cli/{chunk-tzmab476.js.map → chunk-5ffywsmb.js.map} +0 -0
  446. /package/dist/cli/{chunk-2z928egk.js.map → chunk-5wj2qwn2.js.map} +0 -0
  447. /package/dist/cli/{chunk-b07cmahc.js.map → chunk-amrb6hgh.js.map} +0 -0
  448. /package/dist/cli/{chunk-akbpwfxc.js.map → chunk-cmtcnh9f.js.map} +0 -0
  449. /package/dist/cli/{chunk-crgn1q09.js.map → chunk-e7vvk5ya.js.map} +0 -0
  450. /package/dist/cli/{chunk-tkacnehg.js.map → chunk-gp84za0h.js.map} +0 -0
  451. /package/dist/cli/{chunk-r9rcc4w7.js.map → chunk-p804f3pe.js.map} +0 -0
  452. /package/dist/cli/{chunk-8ktnccpt.js.map → chunk-ta27feev.js.map} +0 -0
  453. /package/dist/cli/{chunk-a58773jm.js.map → chunk-y4ykbark.js.map} +0 -0
  454. /package/dist/cli/{chunk-p3v96n38.js.map → chunk-y5h4r2y0.js.map} +0 -0
  455. /package/dist/cli/{chunk-acanzt5p.js.map → chunk-yj17vs39.js.map} +0 -0
@@ -0,0 +1,11 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/theme/color.ts", "../src/theme/palette.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * Just enough CSS color math to check contrast at build time: parse the color\n * syntaxes a theme config takes (hex, `rgb()`, `hsl()`, `hwb()`, `lab()`,\n * `lch()`, `oklab()`, `oklch()`, and named colors) to sRGB, then measure WCAG\n * 2 relative luminance and contrast. A color outside sRGB is clipped to it,\n * which is what a browser shows on an sRGB display. Anything else — `var()`,\n * `color-mix()`, `color()` — parses to `null`, and the caller says it couldn't\n * check it rather than guessing.\n */\n\n/** An sRGB color: gamma-encoded channels and alpha, each 0–1. */\nexport interface Rgba {\n alpha: number;\n blue: number;\n green: number;\n red: number;\n}\n\n/** One parsed function argument. */\ninterface Component {\n /** `\"%\"`, an angle unit, or `\"\"` for a bare number. */\n unit: string;\n value: number;\n}\n\n/** A color function's three channel arguments. */\ntype Channels = readonly [Component, Component, Component];\n\n/** A parsed color function: its name and its channel and alpha arguments. */\ninterface ColorFunction {\n alpha?: Component;\n channels: Channels;\n name: string;\n}\n\n/** The CSS named colors, as hex. A `Map`, so `constructor` names nothing. */\nconst NAMED = new Map(\n Object.entries({\n aliceblue: \"f0f8ff\",\n antiquewhite: \"faebd7\",\n aqua: \"00ffff\",\n aquamarine: \"7fffd4\",\n azure: \"f0ffff\",\n beige: \"f5f5dc\",\n bisque: \"ffe4c4\",\n black: \"000000\",\n blanchedalmond: \"ffebcd\",\n blue: \"0000ff\",\n blueviolet: \"8a2be2\",\n brown: \"a52a2a\",\n burlywood: \"deb887\",\n cadetblue: \"5f9ea0\",\n chartreuse: \"7fff00\",\n chocolate: \"d2691e\",\n coral: \"ff7f50\",\n cornflowerblue: \"6495ed\",\n cornsilk: \"fff8dc\",\n crimson: \"dc143c\",\n cyan: \"00ffff\",\n darkblue: \"00008b\",\n darkcyan: \"008b8b\",\n darkgoldenrod: \"b8860b\",\n darkgray: \"a9a9a9\",\n darkgreen: \"006400\",\n darkgrey: \"a9a9a9\",\n darkkhaki: \"bdb76b\",\n darkmagenta: \"8b008b\",\n darkolivegreen: \"556b2f\",\n darkorange: \"ff8c00\",\n darkorchid: \"9932cc\",\n darkred: \"8b0000\",\n darksalmon: \"e9967a\",\n darkseagreen: \"8fbc8f\",\n darkslateblue: \"483d8b\",\n darkslategray: \"2f4f4f\",\n darkslategrey: \"2f4f4f\",\n darkturquoise: \"00ced1\",\n darkviolet: \"9400d3\",\n deeppink: \"ff1493\",\n deepskyblue: \"00bfff\",\n dimgray: \"696969\",\n dimgrey: \"696969\",\n dodgerblue: \"1e90ff\",\n firebrick: \"b22222\",\n floralwhite: \"fffaf0\",\n forestgreen: \"228b22\",\n fuchsia: \"ff00ff\",\n gainsboro: \"dcdcdc\",\n ghostwhite: \"f8f8ff\",\n gold: \"ffd700\",\n goldenrod: \"daa520\",\n gray: \"808080\",\n green: \"008000\",\n greenyellow: \"adff2f\",\n grey: \"808080\",\n honeydew: \"f0fff0\",\n hotpink: \"ff69b4\",\n indianred: \"cd5c5c\",\n indigo: \"4b0082\",\n ivory: \"fffff0\",\n khaki: \"f0e68c\",\n lavender: \"e6e6fa\",\n lavenderblush: \"fff0f5\",\n lawngreen: \"7cfc00\",\n lemonchiffon: \"fffacd\",\n lightblue: \"add8e6\",\n lightcoral: \"f08080\",\n lightcyan: \"e0ffff\",\n lightgoldenrodyellow: \"fafad2\",\n lightgray: \"d3d3d3\",\n lightgreen: \"90ee90\",\n lightgrey: \"d3d3d3\",\n lightpink: \"ffb6c1\",\n lightsalmon: \"ffa07a\",\n lightseagreen: \"20b2aa\",\n lightskyblue: \"87cefa\",\n lightslategray: \"778899\",\n lightslategrey: \"778899\",\n lightsteelblue: \"b0c4de\",\n lightyellow: \"ffffe0\",\n lime: \"00ff00\",\n limegreen: \"32cd32\",\n linen: \"faf0e6\",\n magenta: \"ff00ff\",\n maroon: \"800000\",\n mediumaquamarine: \"66cdaa\",\n mediumblue: \"0000cd\",\n mediumorchid: \"ba55d3\",\n mediumpurple: \"9370db\",\n mediumseagreen: \"3cb371\",\n mediumslateblue: \"7b68ee\",\n mediumspringgreen: \"00fa9a\",\n mediumturquoise: \"48d1cc\",\n mediumvioletred: \"c71585\",\n midnightblue: \"191970\",\n mintcream: \"f5fffa\",\n mistyrose: \"ffe4e1\",\n moccasin: \"ffe4b5\",\n navajowhite: \"ffdead\",\n navy: \"000080\",\n oldlace: \"fdf5e6\",\n olive: \"808000\",\n olivedrab: \"6b8e23\",\n orange: \"ffa500\",\n orangered: \"ff4500\",\n orchid: \"da70d6\",\n palegoldenrod: \"eee8aa\",\n palegreen: \"98fb98\",\n paleturquoise: \"afeeee\",\n palevioletred: \"db7093\",\n papayawhip: \"ffefd5\",\n peachpuff: \"ffdab9\",\n peru: \"cd853f\",\n pink: \"ffc0cb\",\n plum: \"dda0dd\",\n powderblue: \"b0e0e6\",\n purple: \"800080\",\n rebeccapurple: \"663399\",\n red: \"ff0000\",\n rosybrown: \"bc8f8f\",\n royalblue: \"4169e1\",\n saddlebrown: \"8b4513\",\n salmon: \"fa8072\",\n sandybrown: \"f4a460\",\n seagreen: \"2e8b57\",\n seashell: \"fff5ee\",\n sienna: \"a0522d\",\n silver: \"c0c0c0\",\n skyblue: \"87ceeb\",\n slateblue: \"6a5acd\",\n slategray: \"708090\",\n slategrey: \"708090\",\n snow: \"fffafa\",\n springgreen: \"00ff7f\",\n steelblue: \"4682b4\",\n tan: \"d2b48c\",\n teal: \"008080\",\n thistle: \"d8bfd8\",\n tomato: \"ff6347\",\n transparent: \"00000000\",\n turquoise: \"40e0d0\",\n violet: \"ee82ee\",\n wheat: \"f5deb3\",\n white: \"ffffff\",\n whitesmoke: \"f5f5f5\",\n yellow: \"ffff00\",\n yellowgreen: \"9acd32\",\n })\n);\n\nconst HEX = /^#(?<digits>[\\da-f]{3,4}|[\\da-f]{6}|[\\da-f]{8})$/iu;\nconst FUNCTION = /^(?<name>[a-z]+)\\((?<args>[^()]*)\\)$/iu;\nconst COMPONENT =\n /^(?<value>[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?)(?<unit>%|deg|grad|rad|turn)?$/iu;\n\n/** Turns per angle unit; a bare hue is in degrees. */\nconst TURNS_PER_UNIT = new Map([\n [\"\", 1 / 360],\n [\"deg\", 1 / 360],\n [\"grad\", 1 / 400],\n [\"rad\", 1 / (2 * Math.PI)],\n [\"turn\", 1],\n]);\n\nconst clamp = (value: number): number => Math.min(1, Math.max(0, value));\n\nconst fromHex = (digits: string): Rgba => {\n const full =\n digits.length <= 4\n ? [...digits].map((digit) => `${digit}${digit}`).join(\"\")\n : digits;\n const channel = (index: number): number =>\n Number.parseInt(full.slice(index * 2, index * 2 + 2), 16) / 255;\n return {\n alpha: full.length === 8 ? channel(3) : 1,\n blue: channel(2),\n green: channel(1),\n red: channel(0),\n };\n};\n\nconst parseComponent = (token: string): Component | null => {\n if (token.toLowerCase() === \"none\") {\n return { unit: \"\", value: 0 };\n }\n const match = COMPONENT.exec(token)?.groups;\n return match?.value === undefined\n ? null\n : { unit: (match.unit ?? \"\").toLowerCase(), value: Number(match.value) };\n};\n\n/** Split a function's arguments: commas or spaces, with `/` before alpha. */\nconst parseFunction = (value: string): ColorFunction | null => {\n const match = FUNCTION.exec(value)?.groups;\n if (match?.name === undefined || match.args === undefined) {\n return null;\n }\n const [channelText = \"\", alphaText, extra] = match.args.split(\"/\");\n const tokens = channelText\n .split(/[\\s,]+/u)\n .filter(Boolean)\n .map(parseComponent);\n // The legacy comma syntax (`rgba(0, 0, 0, 0.5)`) puts alpha fourth.\n const legacyAlpha =\n alphaText === undefined && tokens.length === 4 ? tokens.pop() : undefined;\n const alpha =\n alphaText === undefined ? legacyAlpha : parseComponent(alphaText.trim());\n const [first, second, third, ...rest] = tokens;\n if (\n extra !== undefined ||\n alpha === null ||\n rest.length > 0 ||\n !first ||\n !second ||\n !third\n ) {\n return null;\n }\n return {\n alpha,\n channels: [first, second, third],\n name: match.name.toLowerCase(),\n };\n};\n\n/** A number, or a percentage of `full`. */\nconst scaled = (component: Component, full: number): number =>\n component.unit === \"%\" ? (component.value / 100) * full : component.value;\n\n/** A hue in degrees (0–360), from any angle unit. */\nconst hueDegrees = (component: Component): number => {\n const degrees =\n component.value * (TURNS_PER_UNIT.get(component.unit) ?? 0) * 360;\n return ((degrees % 360) + 360) % 360;\n};\n\n/** An sRGB channel from its linear-light value. */\nconst encode = (linear: number): number =>\n clamp(\n linear <= 0.0031308 ? 12.92 * linear : 1.055 * linear ** (1 / 2.4) - 0.055\n );\n\n/** A linear-light value from its sRGB channel. */\nconst decode = (channel: number): number =>\n channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4;\n\nconst fromLinear = (\n [red, green, blue]: readonly [number, number, number],\n alpha: number\n): Rgba => ({\n alpha,\n blue: encode(blue),\n green: encode(green),\n red: encode(red),\n});\n\nconst fromHsl = (hue: number, saturation: number, lightness: number) => {\n const chroma = (1 - Math.abs(2 * lightness - 1)) * saturation;\n const channel = (offset: number): number => {\n const k = (offset + hue / 30) % 12;\n return lightness - (chroma / 2) * Math.max(-1, Math.min(k - 3, 9 - k, 1));\n };\n return [channel(0), channel(8), channel(4)] as const;\n};\n\nconst fromHwb = (hue: number, white: number, black: number) => {\n if (white + black >= 1) {\n const gray = white / (white + black);\n return [gray, gray, gray] as const;\n }\n const [red, green, blue] = fromHsl(hue, 1, 0.5);\n const scale = 1 - white - black;\n return [\n red * scale + white,\n green * scale + white,\n blue * scale + white,\n ] as const;\n};\n\n/** Linear sRGB from OKLab (Björn Ottosson's matrices). */\nconst fromOklab = (lightness: number, a: number, b: number) => {\n const l = (lightness + 0.3963377774 * a + 0.2158037573 * b) ** 3;\n const m = (lightness - 0.1055613458 * a - 0.0638541728 * b) ** 3;\n const s = (lightness - 0.0894841775 * a - 1.291485548 * b) ** 3;\n return [\n 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,\n -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,\n -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s,\n ] as const;\n};\n\n/** Linear sRGB from CIE Lab (D50), through XYZ and a Bradford adaptation. */\nconst fromLab = (lightness: number, a: number, b: number) => {\n const epsilon = 216 / 24_389;\n const kappa = 24_389 / 27;\n const fy = (lightness + 16) / 116;\n const fx = fy + a / 500;\n const fz = fy - b / 200;\n const cube = (f: number): number =>\n f ** 3 > epsilon ? f ** 3 : (116 * f - 16) / kappa;\n const x = cube(fx) * 0.96422;\n const y = lightness > kappa * epsilon ? fy ** 3 : lightness / kappa;\n const z = cube(fz) * 0.82521;\n // D50 to D65.\n const x65 =\n 0.955473421488075 * x - 0.02309845494876471 * y + 0.06325924320057072 * z;\n const y65 =\n -0.0283697093338637 * x + 1.0099953980813041 * y + 0.021041441191917323 * z;\n const z65 =\n 0.012314014864481998 * x - 0.020507649298898964 * y + 1.330365926242124 * z;\n return [\n 3.2409699419045226 * x65 -\n 1.537383177570094 * y65 -\n 0.4986107602930034 * z65,\n -0.9692436362808796 * x65 +\n 1.8759675015077202 * y65 +\n 0.04155505740717559 * z65,\n 0.05563007969699366 * x65 -\n 0.20397695888897652 * y65 +\n 1.0569715142428786 * z65,\n ] as const;\n};\n\n/** Polar (lightness, chroma, hue) to rectangular (lightness, a, b). */\nconst rectangular = (lightness: number, chroma: number, hue: number) => {\n const radians = (hue * Math.PI) / 180;\n return [\n lightness,\n chroma * Math.cos(radians),\n chroma * Math.sin(radians),\n ] as const;\n};\n\n/** A color function's channels, converted to sRGB with `alpha`. */\ntype Converter = (channels: Channels, alpha: number) => Rgba;\n\nconst rgb: Converter = ([red, green, blue], alpha) => {\n const channel = (component: Component): number =>\n clamp(scaled(component, 255) / 255);\n return {\n alpha,\n blue: channel(blue),\n green: channel(green),\n red: channel(red),\n };\n};\n\n/** A converter for a hue-and-two-percentages function (`hsl()`, `hwb()`). */\nconst cylindrical =\n (\n convert: (hue: number, x: number, y: number) => readonly number[]\n ): Converter =>\n ([hue, x, y], alpha) => {\n const [red = 0, green = 0, blue = 0] = convert(\n hueDegrees(hue),\n clamp(scaled(x, 100) / 100),\n clamp(scaled(y, 100) / 100)\n );\n return { alpha, blue: clamp(blue), green: clamp(green), red: clamp(red) };\n };\n\nconst hsl = cylindrical(fromHsl);\n\n/** The color functions this module reads, by name. */\nconst CONVERTERS = new Map<string, Converter>([\n [\"hsl\", hsl],\n [\"hsla\", hsl],\n [\"hwb\", cylindrical(fromHwb)],\n [\n \"lab\",\n ([lightness, a, b], alpha) =>\n fromLinear(\n fromLab(scaled(lightness, 100), scaled(a, 125), scaled(b, 125)),\n alpha\n ),\n ],\n [\n \"lch\",\n ([lightness, chroma, hue], alpha) =>\n fromLinear(\n fromLab(\n ...rectangular(\n scaled(lightness, 100),\n scaled(chroma, 150),\n hueDegrees(hue)\n )\n ),\n alpha\n ),\n ],\n [\n \"oklab\",\n ([lightness, a, b], alpha) =>\n fromLinear(\n fromOklab(scaled(lightness, 1), scaled(a, 0.4), scaled(b, 0.4)),\n alpha\n ),\n ],\n [\n \"oklch\",\n ([lightness, chroma, hue], alpha) =>\n fromLinear(\n fromOklab(\n ...rectangular(\n scaled(lightness, 1),\n scaled(chroma, 0.4),\n hueDegrees(hue)\n )\n ),\n alpha\n ),\n ],\n [\"rgb\", rgb],\n [\"rgba\", rgb],\n]);\n\n/** Parse a CSS color to sRGB, or `null` for syntax this module doesn't read. */\nexport const parseColor = (value: string): Rgba | null => {\n const color = value.trim().toLowerCase();\n const hex = NAMED.get(color) ?? HEX.exec(color)?.groups?.digits;\n if (hex !== undefined) {\n return fromHex(hex);\n }\n const parsed = parseFunction(color);\n const convert = parsed && CONVERTERS.get(parsed.name);\n return parsed && convert\n ? convert(\n parsed.channels,\n parsed.alpha === undefined ? 1 : clamp(scaled(parsed.alpha, 1))\n )\n : null;\n};\n\n/** `color` painted over an opaque `backdrop`. */\nexport const composite = (color: Rgba, backdrop: Rgba): Rgba => {\n const mix = (top: number, bottom: number): number =>\n top * color.alpha + bottom * (1 - color.alpha);\n return {\n alpha: 1,\n blue: mix(color.blue, backdrop.blue),\n green: mix(color.green, backdrop.green),\n red: mix(color.red, backdrop.red),\n };\n};\n\n/** WCAG 2 relative luminance of an opaque color. */\nexport const luminance = (color: Rgba): number =>\n 0.2126 * decode(color.red) +\n 0.7152 * decode(color.green) +\n 0.0722 * decode(color.blue);\n\n/**\n * WCAG 2 contrast ratio of `foreground` on an opaque `background`, from 1 to\n * 21. A translucent foreground is painted over the background first.\n */\nexport const contrastRatio = (foreground: Rgba, background: Rgba): number => {\n const top = luminance(composite(foreground, background));\n const bottom = luminance(background);\n return (Math.max(top, bottom) + 0.05) / (Math.min(top, bottom) + 0.05);\n};\n",
6
+ "import type { ResolvedConfig } from \"../core/schema.ts\";\nimport { composite, contrastRatio, parseColor } from \"./color.ts\";\nimport type { Rgba } from \"./color.ts\";\n\n/** Per-mode CSS colors. */\nexport interface AccentColors {\n dark: string;\n light: string;\n}\n\n/** A color mode. */\nexport type ColorMode = keyof AccentColors;\n\n/**\n * Named accent presets mapped to OKLCH values, per mode. The single source of\n * truth for preset colors: the theme CSS and the OG card (og/card.ts) both\n * resolve from this table, so a site and its social cards can't disagree\n * about \"blue\". Each clears WCAG AA (4.5:1) as text on its mode's page and\n * under its button label ({@link readableOn}), with room to spare on the\n * tinted surfaces accent text also sits on: the light shades are dark enough\n * for white labels, the dark shades light enough to read on the dark page.\n */\nexport const ACCENTS = {\n blue: { dark: \"oklch(0.62 0.16 250)\", light: \"oklch(0.55 0.16 250)\" },\n green: { dark: \"oklch(0.6 0.16 150)\", light: \"oklch(0.53 0.16 150)\" },\n orange: { dark: \"oklch(0.68 0.17 50)\", light: \"oklch(0.56 0.17 50)\" },\n pink: { dark: \"oklch(0.65 0.2 350)\", light: \"oklch(0.58 0.2 350)\" },\n purple: { dark: \"oklch(0.6 0.2 290)\", light: \"oklch(0.57 0.2 290)\" },\n red: { dark: \"oklch(0.61 0.22 25)\", light: \"oklch(0.58 0.22 25)\" },\n teal: { dark: \"oklch(0.6 0.12 195)\", light: \"oklch(0.53 0.12 195)\" },\n} satisfies Record<string, AccentColors>;\n\n/** The contrast WCAG AA asks of body-size text. */\nexport const MIN_TEXT_CONTRAST = 4.5;\n\n/**\n * The theme's own colors a configured accent is drawn against: each mode's\n * page background and text, and the dark ink a filled accent can carry.\n * Mirrors the defaults in `entry.ts`.\n */\nexport const THEME_INKS = {\n dark: {\n background: \"oklch(0.085 0 0)\",\n foreground: \"oklch(0.96 0 0)\",\n ink: \"oklch(0.085 0 0)\",\n mutedForeground: \"oklch(0.68 0 0)\",\n },\n light: {\n background: \"oklch(1 0 0)\",\n foreground: \"oklch(0.145 0 0)\",\n ink: \"oklch(0.145 0 0)\",\n mutedForeground: \"oklch(0.53 0 0)\",\n },\n} satisfies Record<ColorMode, Record<string, string>>;\n\nconst WHITE = \"oklch(1 0 0)\";\n\n/** A color this module writes itself, parsed (they all parse). */\nconst own = (value: string): Rgba =>\n parseColor(value) ?? { alpha: 1, blue: 0, green: 0, red: 0 };\n\n/** {@link THEME_INKS}, parsed, for contrast math. */\nexport const themeInk = (\n mode: ColorMode,\n name: keyof (typeof THEME_INKS)[ColorMode]\n): Rgba => own(THEME_INKS[mode][name]);\n\n/**\n * The label color for text on a filled `fill` (a button, a step number): white\n * while it reaches AA, else the mode's dark ink when that reads better, so a\n * light accent (every dark-mode preset) gets dark text instead of white text\n * nobody can read.\n */\nexport const labelOn = (fill: Rgba, mode: ColorMode): string => {\n const opaque = composite(fill, themeInk(mode, \"background\"));\n const onWhite = contrastRatio(own(WHITE), opaque);\n return onWhite >= MIN_TEXT_CONTRAST ||\n onWhite >= contrastRatio(themeInk(mode, \"ink\"), opaque)\n ? WHITE\n : THEME_INKS[mode].ink;\n};\n\n/** {@link labelOn} for a CSS color; one this module can't parse keeps white. */\nexport const readableOn = (fill: string, mode: ColorMode): string => {\n const color = parseColor(fill);\n return color ? labelOn(color, mode) : WHITE;\n};\n\n/**\n * Whether a raw config value names an accent preset. `hasOwn` keeps a value\n * like \"constructor\" from resolving an Object.prototype member — which would\n * stringify a function into the generated CSS, breaking the rule (the exact\n * breakout {@link safeColor} exists to prevent).\n */\nexport const isAccentPreset = (value: string): value is keyof typeof ACCENTS =>\n Object.hasOwn(ACCENTS, value);\n\n// Characters valid in a CSS color value (hex, rgb/hsl/oklch functions, named\n// colors). Anything else — notably `;`, `{`, `}` — could break out of the\n// declaration and inject rules, so such a value is rejected.\nconst CSS_COLOR = /^[\\w\\s#%.,()/+-]+$/u;\n\n/** Pass a raw color through only if it can't break out of a CSS declaration. */\nconst safeColor = (value: string, fallback: string): string =>\n CSS_COLOR.test(value.trim()) ? value.trim() : fallback;\n\n/** Resolve a named preset in `mode`, or fall back to {@link safeColor}. */\nconst presetOrColor = (value: string, mode: ColorMode): string =>\n isAccentPreset(value)\n ? ACCENTS[value][mode]\n : safeColor(value, ACCENTS.blue[mode]);\n\n/** Like {@link safeColor} but drops an unsafe/absent value to `null`. */\nconst safeColorOrNull = (value: string | undefined): string | null =>\n value && CSS_COLOR.test(value.trim()) ? value.trim() : null;\n\nconst RADII = {\n lg: \"0.75rem\",\n md: \"0.5rem\",\n none: \"0\",\n sm: \"0.25rem\",\n} satisfies Record<ResolvedConfig[\"theme\"][\"radius\"], string>;\n\nconst cssString = (value: string): string => JSON.stringify(value);\n\nconst backgroundImageCss = (image: string): string =>\n `url(${cssString(image)})`;\n\nconst cssToken = (name: string, value?: string | null): string[] =>\n value ? [` ${name}: ${value};`] : [];\n\n/** One mode's resolved accent and action fills. */\ninterface ModeFills {\n accent: string;\n action: string | null;\n}\n\nconst themeRootCss = (\n theme: ResolvedConfig[\"theme\"],\n options: ModeFills & { radius: string }\n): string =>\n [\n ` --blume-accent: ${options.accent};`,\n ` --blume-accent-foreground: ${readableOn(options.accent, \"light\")};`,\n ...cssToken(\"--blume-action\", options.action),\n ...cssToken(\n \"--blume-action-foreground\",\n options.action ? readableOn(options.action, \"light\") : null\n ),\n ...cssToken(\"--blume-background\", safeColorOrNull(theme.background?.light)),\n ...cssToken(\n \"--blume-background-image\",\n theme.backgroundImage?.light\n ? backgroundImageCss(theme.backgroundImage.light)\n : null\n ),\n ` --blume-radius: ${options.radius};`,\n ]\n .filter(Boolean)\n .join(\"\\n\");\n\nconst themeDarkCss = (\n theme: ResolvedConfig[\"theme\"],\n options: ModeFills\n): string => {\n // Mode-shared tokens (accent, action) must be re-declared here: the base\n // stylesheet's own `:root[data-theme=\"dark\"]` block outranks the `:root`\n // config tokens on specificity, so without this block dark mode would\n // silently keep its neutral defaults and ignore the config.\n const tokens = [\n ` --blume-accent: ${options.accent};`,\n ` --blume-accent-foreground: ${readableOn(options.accent, \"dark\")};`,\n ...cssToken(\"--blume-action\", options.action),\n ...cssToken(\n \"--blume-action-foreground\",\n options.action ? readableOn(options.action, \"dark\") : null\n ),\n ...cssToken(\"--blume-background\", safeColorOrNull(theme.background?.dark)),\n ...cssToken(\n \"--blume-background-image\",\n theme.backgroundImage?.dark\n ? backgroundImageCss(theme.backgroundImage.dark)\n : null\n ),\n ].filter(Boolean);\n return `:root[data-theme=\"dark\"] {\n${tokens.join(\"\\n\")}\n}\n`;\n};\n\n/**\n * Resolve the configured accent to per-mode CSS colors. A named accent\n * resolves to its preset's shade for each mode; any other value is treated as\n * a raw CSS color so users can pass arbitrary colors without a config change.\n * A string accent has already been normalized by the config schema to the\n * same value for both modes.\n */\nexport const resolveAccent = (\n theme: ResolvedConfig[\"theme\"]\n): AccentColors => ({\n dark: presetOrColor(theme.accent.dark, \"dark\"),\n light: presetOrColor(theme.accent.light, \"light\"),\n});\n\n/** Resolve the configured `action` fill per mode, or `null` when unset. */\nexport const resolveAction = (\n theme: ResolvedConfig[\"theme\"]\n): AccentColors | null =>\n theme.action\n ? {\n dark: presetOrColor(theme.action, \"dark\"),\n light: presetOrColor(theme.action, \"light\"),\n }\n : null;\n\n/** Resolve the configured radius preset to a CSS length. */\nexport const resolveRadius = (theme: ResolvedConfig[\"theme\"]): string =>\n RADII[theme.radius];\n\n/**\n * Compile theme config into CSS custom properties. A named accent resolves to\n * its preset; any other value is treated as a raw CSS color so users can pass\n * arbitrary colors without a config change. Labels on accent and action fills\n * take whichever of white or dark ink reads ({@link readableOn}).\n */\nexport const buildThemeCss = (theme: ResolvedConfig[\"theme\"]): string => {\n const accent = resolveAccent(theme);\n const action = resolveAction(theme);\n const root = themeRootCss(theme, {\n accent: accent.light,\n action: action?.light ?? null,\n radius: RADII[theme.radius],\n });\n const dark = themeDarkCss(theme, {\n accent: accent.dark,\n action: action?.dark ?? null,\n });\n\n return `/* Generated by Blume from theme config. */\n:root {\n${root}\n}\n${dark}`;\n};\n"
7
+ ],
8
+ "mappings": ";;;AAoCA,IAAM,QAAQ,IAAI,IAChB,OAAO,QAAQ;AAAA,EACb,WAAW;AAAA,EACX,cAAc;AAAA,EACd,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,gBAAgB;AAAA,EAChB,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,WAAW;AAAA,EACX,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,OAAO;AAAA,EACP,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV,SAAS;AAAA,EACT,MAAM;AAAA,EACN,UAAU;AAAA,EACV,UAAU;AAAA,EACV,eAAe;AAAA,EACf,UAAU;AAAA,EACV,WAAW;AAAA,EACX,UAAU;AAAA,EACV,WAAW;AAAA,EACX,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,aAAa;AAAA,EACb,SAAS;AAAA,EACT,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,aAAa;AAAA,EACb,aAAa;AAAA,EACb,SAAS;AAAA,EACT,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,WAAW;AAAA,EACX,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aAAa;AAAA,EACb,MAAM;AAAA,EACN,UAAU;AAAA,EACV,SAAS;AAAA,EACT,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAU;AAAA,EACV,eAAe;AAAA,EACf,WAAW;AAAA,EACX,cAAc;AAAA,EACd,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,sBAAsB;AAAA,EACtB,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,WAAW;AAAA,EACX,aAAa;AAAA,EACb,eAAe;AAAA,EACf,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,MAAM;AAAA,EACN,WAAW;AAAA,EACX,OAAO;AAAA,EACP,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,kBAAkB;AAAA,EAClB,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,cAAc;AAAA,EACd,WAAW;AAAA,EACX,WAAW;AAAA,EACX,UAAU;AAAA,EACV,aAAa;AAAA,EACb,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,WAAW;AAAA,EACX,eAAe;AAAA,EACf,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,KAAK;AAAA,EACL,WAAW;AAAA,EACX,WAAW;AAAA,EACX,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,WAAW;AAAA,EACX,WAAW;AAAA,EACX,WAAW;AAAA,EACX,MAAM;AAAA,EACN,aAAa;AAAA,EACb,WAAW;AAAA,EACX,KAAK;AAAA,EACL,MAAM;AAAA,EACN,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,aAAa;AACf,CAAC,CACH;AAEA,IAAM,MAAM;AACZ,IAAM,WAAW;AACjB,IAAM,YACJ;AAGF,IAAM,iBAAiB,IAAI,IAAI;AAAA,EAC7B,CAAC,IAAI,IAAI,GAAG;AAAA,EACZ,CAAC,OAAO,IAAI,GAAG;AAAA,EACf,CAAC,QAAQ,IAAI,GAAG;AAAA,EAChB,CAAC,OAAO,KAAK,IAAI,KAAK,GAAG;AAAA,EACzB,CAAC,QAAQ,CAAC;AACZ,CAAC;AAED,IAAM,QAAQ,CAAC,UAA0B,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,CAAC;AAEvE,IAAM,UAAU,CAAC,WAAyB;AAAA,EACxC,MAAM,OACJ,OAAO,UAAU,IACb,CAAC,GAAG,MAAM,EAAE,IAAI,CAAC,UAAU,GAAG,QAAQ,OAAO,EAAE,KAAK,EAAE,IACtD;AAAA,EACN,MAAM,UAAU,CAAC,UACf,OAAO,SAAS,KAAK,MAAM,QAAQ,GAAG,QAAQ,IAAI,CAAC,GAAG,EAAE,IAAI;AAAA,EAC9D,OAAO;AAAA,IACL,OAAO,KAAK,WAAW,IAAI,QAAQ,CAAC,IAAI;AAAA,IACxC,MAAM,QAAQ,CAAC;AAAA,IACf,OAAO,QAAQ,CAAC;AAAA,IAChB,KAAK,QAAQ,CAAC;AAAA,EAChB;AAAA;AAGF,IAAM,iBAAiB,CAAC,UAAoC;AAAA,EAC1D,IAAI,MAAM,YAAY,MAAM,QAAQ;AAAA,IAClC,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE;AAAA,EAC9B;AAAA,EACA,MAAM,QAAQ,UAAU,KAAK,KAAK,GAAG;AAAA,EACrC,OAAO,OAAO,UAAU,YACpB,OACA,EAAE,OAAO,MAAM,QAAQ,IAAI,YAAY,GAAG,OAAO,OAAO,MAAM,KAAK,EAAE;AAAA;AAI3E,IAAM,gBAAgB,CAAC,UAAwC;AAAA,EAC7D,MAAM,QAAQ,SAAS,KAAK,KAAK,GAAG;AAAA,EACpC,IAAI,OAAO,SAAS,aAAa,MAAM,SAAS,WAAW;AAAA,IACzD,OAAO;AAAA,EACT;AAAA,EACA,OAAO,cAAc,IAAI,WAAW,SAAS,MAAM,KAAK,MAAM,GAAG;AAAA,EACjE,MAAM,SAAS,YACZ,MAAM,SAAS,EACf,OAAO,OAAO,EACd,IAAI,cAAc;AAAA,EAErB,MAAM,cACJ,cAAc,aAAa,OAAO,WAAW,IAAI,OAAO,IAAI,IAAI;AAAA,EAClE,MAAM,QACJ,cAAc,YAAY,cAAc,eAAe,UAAU,KAAK,CAAC;AAAA,EACzE,OAAO,OAAO,QAAQ,UAAU,QAAQ;AAAA,EACxC,IACE,UAAU,aACV,UAAU,QACV,KAAK,SAAS,KACd,CAAC,SACD,CAAC,UACD,CAAC,OACD;AAAA,IACA,OAAO;AAAA,EACT;AAAA,EACA,OAAO;AAAA,IACL;AAAA,IACA,UAAU,CAAC,OAAO,QAAQ,KAAK;AAAA,IAC/B,MAAM,MAAM,KAAK,YAAY;AAAA,EAC/B;AAAA;AAIF,IAAM,SAAS,CAAC,WAAsB,SACpC,UAAU,SAAS,MAAO,UAAU,QAAQ,MAAO,OAAO,UAAU;AAGtE,IAAM,aAAa,CAAC,cAAiC;AAAA,EACnD,MAAM,UACJ,UAAU,SAAS,eAAe,IAAI,UAAU,IAAI,KAAK,KAAK;AAAA,EAChE,QAAS,UAAU,MAAO,OAAO;AAAA;AAInC,IAAM,SAAS,CAAC,WACd,MACE,UAAU,YAAY,QAAQ,SAAS,QAAQ,WAAW,IAAI,OAAO,KACvE;AAGF,IAAM,SAAS,CAAC,YACd,WAAW,UAAU,UAAU,UAAU,UAAU,SAAS,UAAU;AAExE,IAAM,aAAa,EAChB,KAAK,OAAO,OACb,WACU;AAAA,EACV;AAAA,EACA,MAAM,OAAO,IAAI;AAAA,EACjB,OAAO,OAAO,KAAK;AAAA,EACnB,KAAK,OAAO,GAAG;AACjB;AAEA,IAAM,UAAU,CAAC,KAAa,YAAoB,cAAsB;AAAA,EACtE,MAAM,UAAU,IAAI,KAAK,IAAI,IAAI,YAAY,CAAC,KAAK;AAAA,EACnD,MAAM,UAAU,CAAC,WAA2B;AAAA,IAC1C,MAAM,KAAK,SAAS,MAAM,MAAM;AAAA,IAChC,OAAO,YAAa,SAAS,IAAK,KAAK,IAAI,IAAI,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC;AAAA;AAAA,EAE1E,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC;AAAA;AAG5C,IAAM,UAAU,CAAC,KAAa,OAAe,UAAkB;AAAA,EAC7D,IAAI,QAAQ,SAAS,GAAG;AAAA,IACtB,MAAM,OAAO,SAAS,QAAQ;AAAA,IAC9B,OAAO,CAAC,MAAM,MAAM,IAAI;AAAA,EAC1B;AAAA,EACA,OAAO,KAAK,OAAO,QAAQ,QAAQ,KAAK,GAAG,GAAG;AAAA,EAC9C,MAAM,QAAQ,IAAI,QAAQ;AAAA,EAC1B,OAAO;AAAA,IACL,MAAM,QAAQ;AAAA,IACd,QAAQ,QAAQ;AAAA,IAChB,OAAO,QAAQ;AAAA,EACjB;AAAA;AAIF,IAAM,YAAY,CAAC,WAAmB,GAAW,MAAc;AAAA,EAC7D,MAAM,KAAK,YAAY,eAAe,IAAI,eAAe,MAAM;AAAA,EAC/D,MAAM,KAAK,YAAY,eAAe,IAAI,eAAe,MAAM;AAAA,EAC/D,MAAM,KAAK,YAAY,eAAe,IAAI,cAAc,MAAM;AAAA,EAC9D,OAAO;AAAA,IACL,eAAe,IAAI,eAAe,IAAI,eAAe;AAAA,IACrD,gBAAgB,IAAI,eAAe,IAAI,eAAe;AAAA,IACtD,gBAAgB,IAAI,eAAe,IAAI,cAAc;AAAA,EACvD;AAAA;AAIF,IAAM,UAAU,CAAC,WAAmB,GAAW,MAAc;AAAA,EAC3D,MAAM,UAAU,MAAM;AAAA,EACtB,MAAM,QAAQ,QAAS;AAAA,EACvB,MAAM,MAAM,YAAY,MAAM;AAAA,EAC9B,MAAM,KAAK,KAAK,IAAI;AAAA,EACpB,MAAM,KAAK,KAAK,IAAI;AAAA,EACpB,MAAM,OAAO,CAAC,MACZ,KAAK,IAAI,UAAU,KAAK,KAAK,MAAM,IAAI,MAAM;AAAA,EAC/C,MAAM,IAAI,KAAK,EAAE,IAAI;AAAA,EACrB,MAAM,IAAI,YAAY,QAAQ,UAAU,MAAM,IAAI,YAAY;AAAA,EAC9D,MAAM,IAAI,KAAK,EAAE,IAAI;AAAA,EAErB,MAAM,MACJ,oBAAoB,IAAI,sBAAsB,IAAI,sBAAsB;AAAA,EAC1E,MAAM,MACJ,sBAAsB,IAAI,qBAAqB,IAAI,uBAAuB;AAAA,EAC5E,MAAM,MACJ,uBAAuB,IAAI,uBAAuB,IAAI,oBAAoB;AAAA,EAC5E,OAAO;AAAA,IACL,qBAAqB,MACnB,oBAAoB,MACpB,qBAAqB;AAAA,IACvB,sBAAsB,MACpB,qBAAqB,MACrB,sBAAsB;AAAA,IACxB,sBAAsB,MACpB,sBAAsB,MACtB,qBAAqB;AAAA,EACzB;AAAA;AAIF,IAAM,cAAc,CAAC,WAAmB,QAAgB,QAAgB;AAAA,EACtE,MAAM,UAAW,MAAM,KAAK,KAAM;AAAA,EAClC,OAAO;AAAA,IACL;AAAA,IACA,SAAS,KAAK,IAAI,OAAO;AAAA,IACzB,SAAS,KAAK,IAAI,OAAO;AAAA,EAC3B;AAAA;AAMF,IAAM,MAAiB,EAAE,KAAK,OAAO,OAAO,UAAU;AAAA,EACpD,MAAM,UAAU,CAAC,cACf,MAAM,OAAO,WAAW,GAAG,IAAI,GAAG;AAAA,EACpC,OAAO;AAAA,IACL;AAAA,IACA,MAAM,QAAQ,IAAI;AAAA,IAClB,OAAO,QAAQ,KAAK;AAAA,IACpB,KAAK,QAAQ,GAAG;AAAA,EAClB;AAAA;AAIF,IAAM,cACJ,CACE,YAEF,EAAE,KAAK,GAAG,IAAI,UAAU;AAAA,EACtB,OAAO,MAAM,GAAG,QAAQ,GAAG,OAAO,KAAK,QACrC,WAAW,GAAG,GACd,MAAM,OAAO,GAAG,GAAG,IAAI,GAAG,GAC1B,MAAM,OAAO,GAAG,GAAG,IAAI,GAAG,CAC5B;AAAA,EACA,OAAO,EAAE,OAAO,MAAM,MAAM,IAAI,GAAG,OAAO,MAAM,KAAK,GAAG,KAAK,MAAM,GAAG,EAAE;AAAA;AAG5E,IAAM,MAAM,YAAY,OAAO;AAG/B,IAAM,aAAa,IAAI,IAAuB;AAAA,EAC5C,CAAC,OAAO,GAAG;AAAA,EACX,CAAC,QAAQ,GAAG;AAAA,EACZ,CAAC,OAAO,YAAY,OAAO,CAAC;AAAA,EAC5B;AAAA,IACE;AAAA,IACA,EAAE,WAAW,GAAG,IAAI,UAClB,WACE,QAAQ,OAAO,WAAW,GAAG,GAAG,OAAO,GAAG,GAAG,GAAG,OAAO,GAAG,GAAG,CAAC,GAC9D,KACF;AAAA,EACJ;AAAA,EACA;AAAA,IACE;AAAA,IACA,EAAE,WAAW,QAAQ,MAAM,UACzB,WACE,QACE,GAAG,YACD,OAAO,WAAW,GAAG,GACrB,OAAO,QAAQ,GAAG,GAClB,WAAW,GAAG,CAChB,CACF,GACA,KACF;AAAA,EACJ;AAAA,EACA;AAAA,IACE;AAAA,IACA,EAAE,WAAW,GAAG,IAAI,UAClB,WACE,UAAU,OAAO,WAAW,CAAC,GAAG,OAAO,GAAG,GAAG,GAAG,OAAO,GAAG,GAAG,CAAC,GAC9D,KACF;AAAA,EACJ;AAAA,EACA;AAAA,IACE;AAAA,IACA,EAAE,WAAW,QAAQ,MAAM,UACzB,WACE,UACE,GAAG,YACD,OAAO,WAAW,CAAC,GACnB,OAAO,QAAQ,GAAG,GAClB,WAAW,GAAG,CAChB,CACF,GACA,KACF;AAAA,EACJ;AAAA,EACA,CAAC,OAAO,GAAG;AAAA,EACX,CAAC,QAAQ,GAAG;AACd,CAAC;AAGM,IAAM,aAAa,CAAC,UAA+B;AAAA,EACxD,MAAM,QAAQ,MAAM,KAAK,EAAE,YAAY;AAAA,EACvC,MAAM,MAAM,MAAM,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK,GAAG,QAAQ;AAAA,EACzD,IAAI,QAAQ,WAAW;AAAA,IACrB,OAAO,QAAQ,GAAG;AAAA,EACpB;AAAA,EACA,MAAM,SAAS,cAAc,KAAK;AAAA,EAClC,MAAM,UAAU,UAAU,WAAW,IAAI,OAAO,IAAI;AAAA,EACpD,OAAO,UAAU,UACb,QACE,OAAO,UACP,OAAO,UAAU,YAAY,IAAI,MAAM,OAAO,OAAO,OAAO,CAAC,CAAC,CAChE,IACA;AAAA;AAIC,IAAM,YAAY,CAAC,OAAa,aAAyB;AAAA,EAC9D,MAAM,MAAM,CAAC,KAAa,WACxB,MAAM,MAAM,QAAQ,UAAU,IAAI,MAAM;AAAA,EAC1C,OAAO;AAAA,IACL,OAAO;AAAA,IACP,MAAM,IAAI,MAAM,MAAM,SAAS,IAAI;AAAA,IACnC,OAAO,IAAI,MAAM,OAAO,SAAS,KAAK;AAAA,IACtC,KAAK,IAAI,MAAM,KAAK,SAAS,GAAG;AAAA,EAClC;AAAA;AAIK,IAAM,YAAY,CAAC,UACxB,SAAS,OAAO,MAAM,GAAG,IACzB,SAAS,OAAO,MAAM,KAAK,IAC3B,SAAS,OAAO,MAAM,IAAI;AAMrB,IAAM,gBAAgB,CAAC,YAAkB,eAA6B;AAAA,EAC3E,MAAM,MAAM,UAAU,UAAU,YAAY,UAAU,CAAC;AAAA,EACvD,MAAM,SAAS,UAAU,UAAU;AAAA,EACnC,QAAQ,KAAK,IAAI,KAAK,MAAM,IAAI,SAAS,KAAK,IAAI,KAAK,MAAM,IAAI;AAAA;;;AC5d5D,IAAM,UAAU;AAAA,EACrB,MAAM,EAAE,MAAM,wBAAwB,OAAO,uBAAuB;AAAA,EACpE,OAAO,EAAE,MAAM,uBAAuB,OAAO,uBAAuB;AAAA,EACpE,QAAQ,EAAE,MAAM,uBAAuB,OAAO,sBAAsB;AAAA,EACpE,MAAM,EAAE,MAAM,uBAAuB,OAAO,sBAAsB;AAAA,EAClE,QAAQ,EAAE,MAAM,sBAAsB,OAAO,sBAAsB;AAAA,EACnE,KAAK,EAAE,MAAM,uBAAuB,OAAO,sBAAsB;AAAA,EACjE,MAAM,EAAE,MAAM,uBAAuB,OAAO,uBAAuB;AACrE;AAGO,IAAM,oBAAoB;AAO1B,IAAM,aAAa;AAAA,EACxB,MAAM;AAAA,IACJ,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,KAAK;AAAA,IACL,iBAAiB;AAAA,EACnB;AAAA,EACA,OAAO;AAAA,IACL,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,KAAK;AAAA,IACL,iBAAiB;AAAA,EACnB;AACF;AAEA,IAAM,QAAQ;AAGd,IAAM,MAAM,CAAC,UACX,WAAW,KAAK,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,EAAE;AAGtD,IAAM,WAAW,CACtB,MACA,SACS,IAAI,WAAW,MAAM,KAAK;AAQ9B,IAAM,UAAU,CAAC,MAAY,SAA4B;AAAA,EAC9D,MAAM,SAAS,UAAU,MAAM,SAAS,MAAM,YAAY,CAAC;AAAA,EAC3D,MAAM,UAAU,cAAc,IAAI,KAAK,GAAG,MAAM;AAAA,EAChD,OAAO,WAAW,qBAChB,WAAW,cAAc,SAAS,MAAM,KAAK,GAAG,MAAM,IACpD,QACA,WAAW,MAAM;AAAA;AAIhB,IAAM,aAAa,CAAC,MAAc,SAA4B;AAAA,EACnE,MAAM,QAAQ,WAAW,IAAI;AAAA,EAC7B,OAAO,QAAQ,QAAQ,OAAO,IAAI,IAAI;AAAA;AASjC,IAAM,iBAAiB,CAAC,UAC7B,OAAO,OAAO,SAAS,KAAK;AAK9B,IAAM,YAAY;AAGlB,IAAM,YAAY,CAAC,OAAe,aAChC,UAAU,KAAK,MAAM,KAAK,CAAC,IAAI,MAAM,KAAK,IAAI;AAGhD,IAAM,gBAAgB,CAAC,OAAe,SACpC,eAAe,KAAK,IAChB,QAAQ,OAAO,QACf,UAAU,OAAO,QAAQ,KAAK,KAAK;AAGzC,IAAM,kBAAkB,CAAC,UACvB,SAAS,UAAU,KAAK,MAAM,KAAK,CAAC,IAAI,MAAM,KAAK,IAAI;AAEzD,IAAM,QAAQ;AAAA,EACZ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,IAAI;AACN;AAEA,IAAM,YAAY,CAAC,UAA0B,KAAK,UAAU,KAAK;AAEjE,IAAM,qBAAqB,CAAC,UAC1B,OAAO,UAAU,KAAK;AAExB,IAAM,WAAW,CAAC,MAAc,UAC9B,QAAQ,CAAC,KAAK,SAAS,QAAQ,IAAI,CAAC;AAQtC,IAAM,eAAe,CACnB,OACA,YAEA;AAAA,EACE,qBAAqB,QAAQ;AAAA,EAC7B,gCAAgC,WAAW,QAAQ,QAAQ,OAAO;AAAA,EAClE,GAAG,SAAS,kBAAkB,QAAQ,MAAM;AAAA,EAC5C,GAAG,SACD,6BACA,QAAQ,SAAS,WAAW,QAAQ,QAAQ,OAAO,IAAI,IACzD;AAAA,EACA,GAAG,SAAS,sBAAsB,gBAAgB,MAAM,YAAY,KAAK,CAAC;AAAA,EAC1E,GAAG,SACD,4BACA,MAAM,iBAAiB,QACnB,mBAAmB,MAAM,gBAAgB,KAAK,IAC9C,IACN;AAAA,EACA,qBAAqB,QAAQ;AAC/B,EACG,OAAO,OAAO,EACd,KAAK;AAAA,CAAI;AAEd,IAAM,eAAe,CACnB,OACA,YACW;AAAA,EAKX,MAAM,SAAS;AAAA,IACb,qBAAqB,QAAQ;AAAA,IAC7B,gCAAgC,WAAW,QAAQ,QAAQ,MAAM;AAAA,IACjE,GAAG,SAAS,kBAAkB,QAAQ,MAAM;AAAA,IAC5C,GAAG,SACD,6BACA,QAAQ,SAAS,WAAW,QAAQ,QAAQ,MAAM,IAAI,IACxD;AAAA,IACA,GAAG,SAAS,sBAAsB,gBAAgB,MAAM,YAAY,IAAI,CAAC;AAAA,IACzE,GAAG,SACD,4BACA,MAAM,iBAAiB,OACnB,mBAAmB,MAAM,gBAAgB,IAAI,IAC7C,IACN;AAAA,EACF,EAAE,OAAO,OAAO;AAAA,EAChB,OAAO;AAAA,EACP,OAAO,KAAK;AAAA,CAAI;AAAA;AAAA;AAAA;AAYX,IAAM,gBAAgB,CAC3B,WACkB;AAAA,EAClB,MAAM,cAAc,MAAM,OAAO,MAAM,MAAM;AAAA,EAC7C,OAAO,cAAc,MAAM,OAAO,OAAO,OAAO;AAClD;AAGO,IAAM,gBAAgB,CAC3B,UAEA,MAAM,SACF;AAAA,EACE,MAAM,cAAc,MAAM,QAAQ,MAAM;AAAA,EACxC,OAAO,cAAc,MAAM,QAAQ,OAAO;AAC5C,IACA;AAGC,IAAM,gBAAgB,CAAC,UAC5B,MAAM,MAAM;AAQP,IAAM,gBAAgB,CAAC,UAA2C;AAAA,EACvE,MAAM,SAAS,cAAc,KAAK;AAAA,EAClC,MAAM,SAAS,cAAc,KAAK;AAAA,EAClC,MAAM,OAAO,aAAa,OAAO;AAAA,IAC/B,QAAQ,OAAO;AAAA,IACf,QAAQ,QAAQ,SAAS;AAAA,IACzB,QAAQ,MAAM,MAAM;AAAA,EACtB,CAAC;AAAA,EACD,MAAM,OAAO,aAAa,OAAO;AAAA,IAC/B,QAAQ,OAAO;AAAA,IACf,QAAQ,QAAQ,QAAQ;AAAA,EAC1B,CAAC;AAAA,EAED,OAAO;AAAA;AAAA,EAEP;AAAA;AAAA,EAEA;AAAA;",
9
+ "debugId": "9A390AB579BDCE3E64756E2164756E21",
10
+ "names": []
11
+ }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  resolveRuntimeDir
4
- } from "./chunk-pv29h0wf.js";
4
+ } from "./chunk-xkz5xbtv.js";
5
5
  import {
6
6
  logger
7
7
  } from "./index.js";
@@ -197,4 +197,4 @@ var refuseIfDevRunning = (root, action, options = {}) => {
197
197
  export { readDevLock, DevLockHeldError, acquireDevLock, updateDevLockPort, describeDevLock, refuseIfDevRunning };
198
198
 
199
199
  //# debugId=BA0F0BBCC7BD124F64756E2164756E21
200
- //# sourceMappingURL=chunk-akbpwfxc.js.map
200
+ //# sourceMappingURL=chunk-cmtcnh9f.js.map
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ needsPlaygroundProxy,
4
+ resolveAskBackend
5
+ } from "./chunk-xkz5xbtv.js";
6
+
7
+ // src/core/server-features.ts
8
+ var serverFeatures = (config) => {
9
+ const features = [];
10
+ if (config.ai.assistant?.enabled && !config.ai.assistant.endpoint) {
11
+ features.push("Assistant");
12
+ }
13
+ if (config.agents.mcp.enabled) {
14
+ features.push("MCP server");
15
+ }
16
+ if (needsPlaygroundProxy(config)) {
17
+ features.push("API playground proxy");
18
+ }
19
+ if (config.search.provider.mode === "server") {
20
+ features.push(`Search (${config.search.provider.kind})`);
21
+ }
22
+ return features;
23
+ };
24
+
25
+ // src/cli/required-secrets.ts
26
+ var adapterSecretOwners = (config) => {
27
+ const { consent, deployment, rateLimit } = config;
28
+ const { provider } = config.search;
29
+ const owners = [
30
+ { feature: `Search (${provider.kind})`, secrets: provider.requiredSecrets },
31
+ ...config.analytics.map((adapter) => ({
32
+ feature: `Analytics (${adapter.kind})`,
33
+ secrets: adapter.requiredSecrets
34
+ })),
35
+ ...config.content.sources.map((source) => ({
36
+ feature: `Content source (${source.kind})`,
37
+ secrets: source.requiredSecrets
38
+ })),
39
+ ...config.reference.map((adapter) => ({
40
+ feature: `API reference (${adapter.kind})`,
41
+ secrets: adapter.requiredSecrets
42
+ })),
43
+ {
44
+ feature: `Deployment (${deployment.kind})`,
45
+ secrets: deployment.requiredSecrets
46
+ }
47
+ ];
48
+ if (consent) {
49
+ owners.push({
50
+ feature: `Consent (${consent.kind})`,
51
+ secrets: consent.requiredSecrets
52
+ });
53
+ }
54
+ if (rateLimit) {
55
+ owners.push({
56
+ feature: `Rate limiting (${rateLimit.kind})`,
57
+ note: "read at request time; without it the routes count in memory",
58
+ secrets: rateLimit.requiredSecrets
59
+ });
60
+ }
61
+ return owners;
62
+ };
63
+ var checkRequiredSecrets = (config) => {
64
+ const diagnostics = [];
65
+ const requireSecret = (feature, env, note) => {
66
+ if (process.env[env]) {
67
+ return;
68
+ }
69
+ const noteSuffix = note ? ` (${note})` : "";
70
+ diagnostics.push({
71
+ code: "BLUME_MISSING_SECRET",
72
+ message: `${feature} is enabled but ${env} is not set${noteSuffix}.`,
73
+ severity: "warning",
74
+ suggestion: `Set ${env} in .env.local for local dev, or in your host's environment for production.`
75
+ });
76
+ };
77
+ if (config.ai.assistant?.enabled && !config.ai.assistant.endpoint) {
78
+ const { captcha, provider } = config.ai.assistant;
79
+ const backend = resolveAskBackend(provider);
80
+ for (const env of provider.requiredSecrets) {
81
+ requireSecret(`Assistant (${backend.label})`, env, backend.secretNote);
82
+ }
83
+ for (const env of captcha?.requiredSecrets ?? []) {
84
+ requireSecret(`Assistant bot check (${captcha?.kind})`, env);
85
+ }
86
+ }
87
+ const { narration } = config;
88
+ if (narration.enabled && narration.provider) {
89
+ for (const env of narration.provider.requiredSecrets) {
90
+ requireSecret("Narration audio", env, "read at build; without it pages use browser voices");
91
+ }
92
+ }
93
+ for (const owner of adapterSecretOwners(config)) {
94
+ for (const env of owner.secrets) {
95
+ requireSecret(owner.feature, env, owner.note);
96
+ }
97
+ }
98
+ return diagnostics;
99
+ };
100
+
101
+ export { serverFeatures, checkRequiredSecrets };
102
+
103
+ //# debugId=D62D6223654FF46464756E2164756E21
104
+ //# sourceMappingURL=chunk-cy5bm0j0.js.map
@@ -0,0 +1,11 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/core/server-features.ts", "../src/cli/required-secrets.ts"],
4
+ "sourcesContent": [
5
+ "import { needsPlaygroundProxy } from \"../openapi/references.ts\";\nimport type { ResolvedConfig } from \"./schema.ts\";\n\n/**\n * List the enabled features that require Astro server output. Static builds\n * fail clearly when any of these are enabled.\n */\nexport const serverFeatures = (config: ResolvedConfig): string[] => {\n const features: string[] = [];\n if (config.ai.assistant?.enabled && !config.ai.assistant.endpoint) {\n features.push(\"Assistant\");\n }\n // The hosted MCP server is a live JSON-RPC endpoint, so it needs a runtime.\n if (config.agents.mcp.enabled) {\n features.push(\"MCP server\");\n }\n // The built-in playground proxy (`playground.proxy: true` on an `openapi()`\n // or `graphql()` adapter) is a live fetch endpoint at `/_api-proxy`; an\n // external proxy URL (string) or a proxy-less playground stays fully static.\n if (needsPlaygroundProxy(config)) {\n features.push(\"API playground proxy\");\n }\n // A `server` adapter (Mixedbread) proxies queries through a secret server\n // endpoint, so it can't run on a static build.\n if (config.search.provider.mode === \"server\") {\n features.push(`Search (${config.search.provider.kind})`);\n }\n return features;\n};\n",
6
+ "import { resolveAskBackend } from \"../ai/ask.ts\";\nimport type { ResolvedConfig } from \"../core/schema.ts\";\nimport type { Diagnostic } from \"../core/types.ts\";\n\n/** A feature, and the secrets the adapter behind it reads. */\ninterface SecretOwner {\n feature: string;\n note?: string;\n secrets: string[];\n}\n\n/**\n * The adapters that name their own secrets. The built-ins mostly declare\n * none: analytics ships public tokens in the page, consent managers load\n * public scripts, reference adapters read public specs, and host adapters\n * read platform-injected env.\n */\nconst adapterSecretOwners = (config: ResolvedConfig): SecretOwner[] => {\n const { consent, deployment, rateLimit } = config;\n const { provider } = config.search;\n const owners: SecretOwner[] = [\n // Each search adapter declares the secrets its generated runtime reads.\n { feature: `Search (${provider.kind})`, secrets: provider.requiredSecrets },\n ...config.analytics.map((adapter) => ({\n feature: `Analytics (${adapter.kind})`,\n secrets: adapter.requiredSecrets,\n })),\n // Each content source adapter declares the env vars its fetch reads.\n ...config.content.sources.map((source) => ({\n feature: `Content source (${source.kind})`,\n secrets: source.requiredSecrets,\n })),\n ...config.reference.map((adapter) => ({\n feature: `API reference (${adapter.kind})`,\n secrets: adapter.requiredSecrets,\n })),\n {\n feature: `Deployment (${deployment.kind})`,\n secrets: deployment.requiredSecrets,\n },\n ];\n if (consent) {\n owners.push({\n feature: `Consent (${consent.kind})`,\n secrets: consent.requiredSecrets,\n });\n }\n // Upstash's endpoint and token.\n if (rateLimit) {\n owners.push({\n feature: `Rate limiting (${rateLimit.kind})`,\n note: \"read at request time; without it the routes count in memory\",\n secrets: rateLimit.requiredSecrets,\n });\n }\n return owners;\n};\n\n/**\n * Warn early when an enabled feature needs a secret env var that isn't set, so\n * the failure surfaces at `blume dev`/`build` instead of at the first request in\n * production. These are runtime secrets (the endpoint reads them on the server),\n * so this warns rather than hard-fails — the value may live only in the deploy\n * environment. Build-time secrets (search-index sync) already warn during sync.\n */\nexport const checkRequiredSecrets = (config: ResolvedConfig): Diagnostic[] => {\n const diagnostics: Diagnostic[] = [];\n const requireSecret = (feature: string, env: string, note?: string): void => {\n if (process.env[env]) {\n return;\n }\n const noteSuffix = note ? ` (${note})` : \"\";\n diagnostics.push({\n code: \"BLUME_MISSING_SECRET\",\n message: `${feature} is enabled but ${env} is not set${noteSuffix}.`,\n severity: \"warning\",\n suggestion: `Set ${env} in .env.local for local dev, or in your host's environment for production.`,\n });\n };\n\n if (config.ai.assistant?.enabled && !config.ai.assistant.endpoint) {\n // The adapter descriptor names the env vars its route reads.\n const { captcha, provider } = config.ai.assistant;\n const backend = resolveAskBackend(provider);\n for (const env of provider.requiredSecrets) {\n requireSecret(`Assistant (${backend.label})`, env, backend.secretNote);\n }\n // The bot check's secret key, which the route verifies tokens with.\n for (const env of captcha?.requiredSecrets ?? []) {\n requireSecret(`Assistant bot check (${captcha?.kind})`, env);\n }\n }\n\n // Generated narration reads its key at build, not at runtime; without it the\n // build skips the audio and pages read with browser voices.\n const { narration } = config;\n if (narration.enabled && narration.provider) {\n for (const env of narration.provider.requiredSecrets) {\n requireSecret(\n \"Narration audio\",\n env,\n \"read at build; without it pages use browser voices\"\n );\n }\n }\n\n for (const owner of adapterSecretOwners(config)) {\n for (const env of owner.secrets) {\n requireSecret(owner.feature, env, owner.note);\n }\n }\n\n return diagnostics;\n};\n"
7
+ ],
8
+ "mappings": "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",
9
+ "debugId": "D62D6223654FF46464756E2164756E21",
10
+ "names": []
11
+ }
@@ -8,15 +8,15 @@ import {
8
8
  VERSION_ID,
9
9
  VERSION_LIKE,
10
10
  versionizeRoute
11
- } from "./chunk-pv29h0wf.js";
11
+ } from "./chunk-xkz5xbtv.js";
12
12
  import {
13
13
  mountBasePath,
14
14
  stripBasePath
15
- } from "./chunk-3em5wd2y.js";
15
+ } from "./chunk-zccbjcj0.js";
16
16
  import {
17
17
  isWithin,
18
18
  scanProject
19
- } from "./chunk-j85vccga.js";
19
+ } from "./chunk-43zcf4gz.js";
20
20
 
21
21
  // src/core/version-cut.ts
22
22
  import { existsSync } from "node:fs";
@@ -280,4 +280,4 @@ var cutVersion = async (root, id, options = {}) => {
280
280
  export { CutError, unregisteredSnapshotDiagnostics, cutVersion };
281
281
 
282
282
  //# debugId=8631919BA7BA49B664756E2164756E21
283
- //# sourceMappingURL=chunk-crgn1q09.js.map
283
+ //# sourceMappingURL=chunk-e7vvk5ya.js.map
@@ -1,30 +1,22 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- BlumeError,
4
- locateFrontmatterKey
3
+ BlumeError
5
4
  } from "./index.js";
6
5
  import {
7
6
  ComponentOverridesError,
8
7
  analyzeComponentOverrides
9
- } from "./chunk-8ktnccpt.js";
8
+ } from "./chunk-ta27feev.js";
10
9
  import {
11
- frontmatter_default,
12
- DEFAULT_CONTENT_INCLUDE,
13
- DEFAULT_CONTENT_EXCLUDE,
14
- pageMetaSchema,
15
- baselineScanIgnore,
16
- createModuleLoader,
17
10
  findConfigFile,
18
11
  findComponentsFile,
19
12
  ConfigValidationError,
20
13
  loadConfig
21
- } from "./chunk-pv29h0wf.js";
14
+ } from "./chunk-xkz5xbtv.js";
22
15
 
23
16
  // src/upgrade/upgrade.ts
24
17
  import { existsSync } from "node:fs";
25
18
  import { readFile, writeFile } from "node:fs/promises";
26
- import { join, relative, resolve } from "pathe";
27
- import { glob } from "tinyglobby";
19
+ import { join, relative } from "pathe";
28
20
  import { z } from "zod";
29
21
  var UPGRADE_GUIDE_URL = "https://useblume.dev/docs/upgrading";
30
22
  var UPGRADE_GUIDE_FILE = join("docs", "03-upgrading.mdx");
@@ -151,89 +143,6 @@ var scriptFindings = async (root) => {
151
143
  ];
152
144
  });
153
145
  };
154
- var globFields = {
155
- exclude: z.array(z.string()).optional(),
156
- include: z.array(z.string()).optional(),
157
- root: z.string().optional()
158
- };
159
- var rawFilesystemSourceSchema = z.union([
160
- z.looseObject({
161
- kind: z.literal("filesystem"),
162
- options: z.looseObject(globFields).default({})
163
- }).transform((source) => source.options),
164
- z.looseObject({ type: z.literal("filesystem"), ...globFields })
165
- ]);
166
- var rawContentSchema = z.looseObject({
167
- content: z.looseObject({ ...globFields, sources: z.array(z.unknown()).optional() }).optional()
168
- });
169
- var contentGlobs = ({
170
- content
171
- }) => {
172
- const sources = (content?.sources ?? []).flatMap((source) => {
173
- const filesystem = rawFilesystemSourceSchema.safeParse(source);
174
- return filesystem.success ? [filesystem.data] : [];
175
- });
176
- return (sources.length > 0 ? sources : [content ?? {}]).map((globs) => ({
177
- exclude: globs.exclude ?? DEFAULT_CONTENT_EXCLUDE,
178
- include: globs.include ?? DEFAULT_CONTENT_INCLUDE,
179
- root: globs.root ?? "docs"
180
- }));
181
- };
182
- var configContentGlobs = async (root) => {
183
- const file = findConfigFile(root);
184
- let raw = {};
185
- if (file) {
186
- try {
187
- const parsed = rawContentSchema.safeParse(await createModuleLoader()(file));
188
- raw = parsed.success ? parsed.data : {};
189
- } catch {}
190
- }
191
- return contentGlobs(raw);
192
- };
193
- var isPathKey = (segment) => typeof segment !== "symbol";
194
- var PLAIN_UNKNOWN_KEY = "Unrecognized key";
195
- var removedFieldFindings = (file, text, issues) => issues.flatMap((issue) => {
196
- if (issue.code !== "unrecognized_keys" || issue.message.startsWith(PLAIN_UNKNOWN_KEY)) {
197
- return [];
198
- }
199
- const path = issue.path.filter(isPathKey);
200
- const position = locateFrontmatterKey(text, [...path, ...issue.keys.slice(0, 1)]) ?? locateFrontmatterKey(text, path);
201
- return [
202
- {
203
- code: "BLUME_FRONTMATTER_INVALID",
204
- column: position?.column,
205
- file,
206
- line: position?.line,
207
- message: issue.message,
208
- severity: "error"
209
- }
210
- ];
211
- });
212
- var pageFindings = async (file) => {
213
- const text = await readFile(file, "utf-8");
214
- let parsed;
215
- try {
216
- parsed = pageMetaSchema.safeParse(frontmatter_default(text).data);
217
- } catch {
218
- return [];
219
- }
220
- return parsed.success ? [] : removedFieldFindings(file, text, parsed.error.issues);
221
- };
222
- var frontmatterFindings = async (root) => {
223
- const roots = await configContentGlobs(root);
224
- const matches = await Promise.all(roots.map((globs) => {
225
- const cwd = resolve(root, globs.root);
226
- return existsSync(cwd) ? glob(globs.include, {
227
- absolute: true,
228
- cwd,
229
- ignore: [...globs.exclude, ...baselineScanIgnore()],
230
- onlyFiles: true
231
- }) : [];
232
- }));
233
- const files = [...new Set(matches.flat())].toSorted();
234
- const findings = await Promise.all(files.map(pageFindings));
235
- return findings.flat();
236
- };
237
146
  var findingsOf = async (check) => {
238
147
  try {
239
148
  await check();
@@ -257,7 +166,6 @@ var collectUpgradeFindings = async (root) => {
257
166
  ...componentsFile ? await findingsOf(async () => {
258
167
  analyzeComponentOverrides(await readFile(componentsFile, "utf-8"), componentsFile);
259
168
  }) : [],
260
- ...await frontmatterFindings(root),
261
169
  ...await scriptFindings(root)
262
170
  ];
263
171
  };
@@ -290,5 +198,5 @@ When \`${options.runner} blume doctor\` reports no errors, run \`${options.runne
290
198
 
291
199
  export { UPGRADE_GUIDE_URL, UPGRADE_GUIDE_FILE, manualBumpAdvice, bumpBlumeDependency, isOutsideBlumeProject, removedBuildFlags, flagList, removedBuildFlagsAdvice, collectUpgradeFindings, upgradePrompt };
292
200
 
293
- //# debugId=220AF85AD7ADA53D64756E2164756E21
294
- //# sourceMappingURL=chunk-pehfxfta.js.map
201
+ //# debugId=1E503C224ED252A564756E2164756E21
202
+ //# sourceMappingURL=chunk-g2z9x01v.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/upgrade/upgrade.ts"],
4
+ "sourcesContent": [
5
+ "import { existsSync } from \"node:fs\";\nimport { readFile, writeFile } from \"node:fs/promises\";\n\nimport { join, relative } from \"pathe\";\nimport { z } from \"zod\";\n\nimport {\n analyzeComponentOverrides,\n ComponentOverridesError,\n} from \"../core/component-overrides.ts\";\nimport { ConfigValidationError, loadConfig } from \"../core/config.ts\";\nimport { BlumeError } from \"../core/diagnostics.ts\";\nimport { findComponentsFile, findConfigFile } from \"../core/project.ts\";\nimport type { Diagnostic } from \"../core/types.ts\";\n\n/**\n * `blume upgrade`'s logic, kept out of the command module so it runs (and is\n * covered) in-process: bump the `blume` dependency to the running CLI's major,\n * then check the project against it — the config through the same loader\n * every command uses, which names each removed or renamed field and its\n * replacement, `components.ts` through the same static planner the build\n * runs, and each page's front matter for fields the schema removed. The\n * command prints the findings or hands them to a coding agent.\n */\n\n/** The upgrade guide's route on the Blume docs site. */\nexport const UPGRADE_GUIDE_URL = \"https://useblume.dev/docs/upgrading\";\n\n/** The upgrade guide's file inside the published package's bundled docs. */\nexport const UPGRADE_GUIDE_FILE = join(\"docs\", \"03-upgrading.mdx\");\n\n/** What `bumpBlumeDependency` did to `package.json`. */\nexport type DependencyBump =\n | {\n field: DependencyField;\n from: string;\n status: \"bumped\";\n to: string;\n }\n | { range: string; status: \"current\" }\n | { range: string; status: \"manual\" }\n | { status: \"missing\" };\n\ntype DependencyField = \"dependencies\" | \"devDependencies\";\n\nconst DEPENDENCY_FIELDS: DependencyField[] = [\n \"dependencies\",\n \"devDependencies\",\n];\n\n/** The slice of `package.json` the bump reads and rewrites. */\ninterface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\n// Leading comparators and a `v` may precede the major (`^1.7.3`, `>=1 <2`,\n// `v1`); a protocol (`workspace:`, `file:`, `npm:`) or a tag (`latest`) names\n// no major at all, and those ranges are left to the user.\nconst RANGE_MAJOR = /^[\\s<=>^~v]*(?<major>\\d+)/u;\n\n/** The major version a dependency range pins, or null when it names none. */\nexport const rangeMajor = (range: string): number | null => {\n const major = RANGE_MAJOR.exec(range)?.groups?.major;\n return major === undefined ? null : Number(major);\n};\n\n// Ranges whose version lives somewhere the bump doesn't rewrite: a pnpm\n// catalog in pnpm-workspace.yaml, or the `range` of an `npm:name@range` alias.\nconst CATALOG_RANGE = /^catalog:(?<name>.*)$/u;\nconst NPM_ALIAS = /^npm:.+@(?<range>[^@]*)$/u;\n\n/**\n * What to change by hand for a `blume` range the bump can't rewrite (a\n * `manual` {@link DependencyBump}): the pnpm catalog entry it points at, or\n * the version inside its `npm:` alias.\n */\nexport const manualBumpAdvice = (range: string, version: string): string => {\n const catalog = CATALOG_RANGE.exec(range)?.groups?.name;\n if (catalog === undefined) {\n return `package.json installs blume through the alias \\`${range}\\`, which \\`blume upgrade\\` doesn't rewrite: set the alias's version to ^${version}, then reinstall.`;\n }\n const entry =\n catalog === \"\" || catalog === \"default\"\n ? \"`catalog`\"\n : `\\`catalogs.${catalog}\\``;\n return `package.json takes blume from the pnpm catalog (\\`${range}\\`), which \\`blume upgrade\\` can't bump: set blume to ^${version} under ${entry} in pnpm-workspace.yaml if it isn't already, then reinstall.`;\n};\n\n// The file's own indentation (two spaces, four, or a tab), so a fallback\n// rewrite doesn't reformat a package.json the user keeps differently.\nconst INDENT = /^(?<indent>[ \\t]+)\"/mu;\n\nconst REGEXP_SPECIAL = /[$()*+.?[\\\\\\]^{|}]/gu;\nconst escapeRegExp = (value: string): string =>\n value.replaceAll(REGEXP_SPECIAL, String.raw`\\$&`);\n\n/**\n * `text` with the `blume` range under `field` replaced in place, so the file\n * keeps its own formatting, key order, and inline objects; null when the entry\n * isn't written the plain way (an escaped key or value).\n */\nconst replaceRange = (\n text: string,\n field: DependencyField,\n from: string,\n to: string\n): string | null => {\n const value = JSON.stringify(from);\n const entry = new RegExp(`\"blume\"\\\\s*:\\\\s*${escapeRegExp(value)}`, \"gu\");\n entry.lastIndex = Math.max(text.indexOf(JSON.stringify(field)), 0);\n const match = entry.exec(text);\n if (!match) {\n return null;\n }\n const end = match.index + match[0].length;\n return `${text.slice(0, end - value.length)}${JSON.stringify(to)}${text.slice(end)}`;\n};\n\n/**\n * Point `package.json`'s `blume` dependency at `^version` when it pins an\n * older major. A range already on this major, or one that names no version\n * (`workspace:*`, `latest`), is reported as current and left alone; one whose\n * version lives elsewhere (`catalog:`, an `npm:` alias of an older major) is\n * `manual`, for the user to change; a project with no `package.json`, or none\n * that lists `blume`, is `missing`. Only the range changes: the rest of the\n * file is kept byte for byte.\n */\nexport const bumpBlumeDependency = async (\n root: string,\n version: string\n): Promise<DependencyBump> => {\n const path = join(root, \"package.json\");\n if (!existsSync(path)) {\n return { status: \"missing\" };\n }\n const text = await readFile(path, \"utf-8\");\n // SAFETY: package.json is a JSON object; only its dependency maps, which\n // map package names to range strings, are read.\n const pkg = JSON.parse(text) as PackageJson;\n const field = DEPENDENCY_FIELDS.find(\n (name) => pkg[name]?.blume !== undefined\n );\n const from = field ? pkg[field]?.blume : undefined;\n if (!(field && from)) {\n return { status: \"missing\" };\n }\n if (CATALOG_RANGE.test(from)) {\n return { range: from, status: \"manual\" };\n }\n const aliased = NPM_ALIAS.exec(from)?.groups?.range;\n const current = rangeMajor(aliased ?? from);\n const target = rangeMajor(version);\n if (current === null || target === null || current >= target) {\n return { range: from, status: \"current\" };\n }\n if (aliased !== undefined) {\n return { range: from, status: \"manual\" };\n }\n const to = `^${version}`;\n const indent = INDENT.exec(text)?.groups?.indent ?? \" \";\n const updated = { ...pkg, [field]: { ...pkg[field], blume: to } };\n await writeFile(\n path,\n replaceRange(text, field, from, to) ??\n `${JSON.stringify(updated, null, indent)}\\n`\n );\n return { field, from, status: \"bumped\", to };\n};\n\n/**\n * Whether `root` is no Blume project at all: no config file and no `blume`\n * dependency, so the upgrade would only check the defaults and report the\n * folder ready. A zero-config project still lists `blume`.\n */\nexport const isOutsideBlumeProject = (\n root: string,\n bump: DependencyBump\n): boolean => bump.status === \"missing\" && findConfigFile(root) === null;\n\n// ---------------------------------------------------------------------------\n// Removed `blume build` flags\n// ---------------------------------------------------------------------------\n\n/** A `blume build` flag Blume 2 removed, bare or with an `=value`. */\nconst REMOVED_BUILD_FLAG = /^--(?<flag>adapter|base|output)(?:=|$)/u;\n\n/** The removed `blume build` flags among `args`, in order, each once. */\nexport const removedBuildFlags = (args: readonly string[]): string[] => [\n ...new Set(\n args.flatMap((arg) => {\n const flag = REMOVED_BUILD_FLAG.exec(arg)?.groups?.flag;\n return flag ? [flag] : [];\n })\n ),\n];\n\n/** The flags as the reader typed them: `--adapter, --output`. */\nexport const flagList = (flags: string[]): string =>\n flags.map((flag) => `--${flag}`).join(\", \");\n\n/** What replaces each removed flag: the `deployment` config. */\nexport const removedBuildFlagsAdvice = (flags: string[]): string => {\n const advice: string[] = [];\n if (flags.includes(\"adapter\") || flags.includes(\"output\")) {\n advice.push(\n 'name the host in blume.config.ts with `deployment: vercel()` (or `netlify()`, `cloudflare()`, `node()`) from \"blume/deploy\" — a host adapter builds for the server, and `output: \"static\"` keeps it static'\n );\n }\n if (flags.includes(\"base\")) {\n advice.push(\n 'set the subpath with `deployment: { base: \"/docs\" }`, or the host adapter\\'s `base` option'\n );\n }\n return `Drop ${flagList(flags)} and ${advice.join(\"; \")}.`;\n};\n\n// A command that runs the Blume CLI: the bare bin, a versioned package\n// (`blume@2`), or a path to it (`./node_modules/.bin/blume`).\nconst BLUME_BIN = /(?:^|[/\\\\])blume(?:@\\S+)?$/u;\nconst COMMAND_SEPARATOR = /&&|\\|\\||[;|]/u;\nconst WHITESPACE = /\\s+/u;\n\n/** The arguments each `blume build` in a script passes, flattened. */\nconst buildArgs = (script: string): string[] =>\n script.split(COMMAND_SEPARATOR).flatMap((command) => {\n const words = command.trim().split(WHITESPACE);\n const at = words.findIndex(\n (word, index) => BLUME_BIN.test(word) && words[index + 1] === \"build\"\n );\n return at === -1 ? [] : words.slice(at + 2);\n });\n\n/** The slice of package.json the script check reads. */\nconst scriptsSchema = z.looseObject({\n scripts: z.record(z.string(), z.string()).default({}),\n});\n\nconst lineOf = (text: string, index: number): number =>\n text.slice(0, index).split(\"\\n\").length;\n\n/**\n * A finding for each package.json script that still passes a removed flag to\n * `blume build` — it would otherwise build a static site without a word.\n */\nconst scriptFindings = async (root: string): Promise<Diagnostic[]> => {\n const path = join(root, \"package.json\");\n if (!existsSync(path)) {\n return [];\n }\n const text = await readFile(path, \"utf-8\");\n const pkg = scriptsSchema.safeParse(JSON.parse(text));\n const scripts = pkg.success ? pkg.data.scripts : {};\n const scriptsAt = text.indexOf('\"scripts\"');\n return Object.entries(scripts).flatMap(([name, script]) => {\n const flags = removedBuildFlags(buildArgs(script));\n if (flags.length === 0) {\n return [];\n }\n const at = text.indexOf(JSON.stringify(name), scriptsAt);\n return [\n {\n code: \"BLUME_BUILD_FLAG_REMOVED\",\n file: path,\n line: at === -1 ? undefined : lineOf(text, at),\n message: `The \"${name}\" script passes ${flagList(flags)} to \\`blume build\\`, which Blume 2 removed.`,\n severity: \"error\",\n suggestion: removedBuildFlagsAdvice(flags),\n } satisfies Diagnostic,\n ];\n });\n};\n\n/**\n * Run one check, turning the {@link BlumeError} it throws into its findings:\n * each config issue or `components.ts` entry on its own, or the one diagnostic\n * any other check has.\n */\nconst findingsOf = async (\n check: () => Promise<void>\n): Promise<Diagnostic[]> => {\n try {\n await check();\n return [];\n } catch (error) {\n if (\n error instanceof ConfigValidationError ||\n error instanceof ComponentOverridesError\n ) {\n return error.issues;\n }\n if (error instanceof BlumeError) {\n return [error.diagnostic];\n }\n throw error;\n }\n};\n\n/**\n * Check a project against this version of Blume: its config through the\n * loader (every invalid field, each with its line and replacement), its\n * `components.ts` through the static override planner (each entry at its\n * line), and its package.json scripts for `blume build` flags that no longer\n * exist. Returns the failures;\n * an empty list means the project is ready.\n */\nexport const collectUpgradeFindings = async (\n root: string\n): Promise<Diagnostic[]> => {\n const componentsFile = findComponentsFile(root);\n return [\n ...(await findingsOf(async () => {\n await loadConfig(root);\n })),\n ...(componentsFile\n ? await findingsOf(async () => {\n analyzeComponentOverrides(\n await readFile(componentsFile, \"utf-8\"),\n componentsFile\n );\n })\n : []),\n ...(await scriptFindings(root)),\n ];\n};\n\n/** A finding as plain text for the agent: where, what, and the fix. */\nconst plainFinding = (finding: Diagnostic, root: string): string => {\n const where = finding.file\n ? `${relative(root, finding.file)}${finding.line === undefined ? \"\" : `:${finding.line}`}`\n : \"blume.config.ts\";\n const fix = finding.suggestion ? `\\n Fix: ${finding.suggestion}` : \"\";\n return `- ${where} (${finding.code})\\n ${finding.message.replaceAll(\"\\n\", \"\\n \")}${fix}`;\n};\n\n/**\n * The handoff prompt: the findings inline (they're few, and each already\n * names its replacement), where the guide is, and the ground rules — change\n * the config's shape, never the site's behavior, and verify with the site's\n * own checks, run through the project's package runner (`npx`, `pnpm exec`),\n * since a local install puts no `blume` on PATH.\n */\nexport const upgradePrompt = (options: {\n findings: Diagnostic[];\n guidePath: string;\n root: string;\n runner: string;\n version: string;\n}): string =>\n `Upgrade this Blume project to Blume ${options.version}. \\`blume upgrade\\` has bumped the \\`blume\\` dependency in package.json where it could; what's left is the config.\n\nThe upgrade guide is at ${options.guidePath} (online at ${UPGRADE_GUIDE_URL}). It covers every change between Blume 1 and 2 with before-and-after examples: search, deployment, content sources, API references, analytics, and the assistant's model provider become adapters imported from \\`blume/*\\` subpaths; the machine-readable settings move from \\`ai\\` to \\`agents\\`; Ask AI is renamed the assistant, so \\`ai.ask\\` becomes \\`ai.assistant\\`; and \\`components.ts\\` entries must be one of the static forms.\n\n\\`blume upgrade\\` found:\n\n${options.findings.map((finding) => plainFinding(finding, options.root)).join(\"\\n\\n\")}\n\nWork through every finding:\n1. Read the guide section for each change before editing.\n2. Rewrite the config to the Blume 2 form, adding the adapter imports it needs. Keep the site's behavior the same: the same content, routes, search backend, deployment target, analytics, and credentials (keep reading secrets from the same environment variables).\n3. The config loader reports every invalid field at once, but some changes only surface once earlier ones are fixed, so rerun \\`${options.runner} blume doctor\\` after each round of edits.\n4. Never delete content, or remove a setting only to silence an error; if something needs a human decision, leave it and say so in your summary.\n\nWhen \\`${options.runner} blume doctor\\` reports no errors, run \\`${options.runner} blume build\\` and fix anything it reports until it succeeds.`;\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "1E503C224ED252A564756E2164756E21",
9
+ "names": []
10
+ }
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  commandsFor
4
- } from "./chunk-pv29h0wf.js";
4
+ } from "./chunk-xkz5xbtv.js";
5
5
 
6
6
  // src/cli/init/install.ts
7
7
  import { spawn } from "node:child_process";
@@ -36,4 +36,4 @@ var installDependencies = async (root, pm, { quiet }) => {
36
36
  export { installDependencies };
37
37
 
38
38
  //# debugId=3BBCF1D4B57D128664756E2164756E21
39
- //# sourceMappingURL=chunk-tkacnehg.js.map
39
+ //# sourceMappingURL=chunk-gp84za0h.js.map