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
@@ -44,9 +44,15 @@ export type FrameProps = ComponentProps<
44
44
  export type PanelProps = ComponentProps<
45
45
  typeof import("./content/Panel.astro").default
46
46
  >;
47
+ export type ParamFieldProps = ComponentProps<
48
+ typeof import("./content/ParamField.astro").default
49
+ >;
47
50
  export type PromptProps = ComponentProps<
48
51
  typeof import("./content/Prompt.astro").default
49
52
  >;
53
+ export type ResponseFieldProps = ComponentProps<
54
+ typeof import("./content/ResponseField.astro").default
55
+ >;
50
56
  export type StepProps = ComponentProps<
51
57
  typeof import("./content/Step.astro").default
52
58
  >;
@@ -0,0 +1,95 @@
1
+ /**
2
+ * The browser half of the consent layer (`consent` in `blume.config.ts`),
3
+ * bundled into every layout by `ConsentHead.astro` and started once per real
4
+ * page load. It answers `window.blumeConsent` (see `init.ts`):
5
+ *
6
+ * - Analytics scripts wait in the page as `<script type="text/plain"
7
+ * data-blume-consent="analytics">` (see `Analytics.astro`). Once the reader
8
+ * allows analytics, each one runs, once per page load: the client router
9
+ * brings the held tags back on every navigation, and running them again
10
+ * would count every visit twice.
11
+ * - A reader who takes consent back after the scripts ran gets a reload, the
12
+ * one way to stop scripts that already started.
13
+ * - Any element with `data-blume-consent-open` (the footer's Cookie settings
14
+ * link) reopens the adapter's preferences.
15
+ * - An adapter with a browser module (`native()`'s banner, say) is started
16
+ * from here once the runtime is listening; see `consent/clients.ts`.
17
+ */
18
+ import type { BlumeConsent } from "../components/layout/consent/types.ts";
19
+
20
+ /** The window, with the state the init script puts on it. */
21
+ type ConsentWindow = Window & { blumeConsent?: BlumeConsent };
22
+
23
+ /** Analytics tags held until the reader allows analytics. */
24
+ export const HELD_SCRIPTS =
25
+ 'script[type="text/plain"][data-blume-consent="analytics"]';
26
+
27
+ const OPEN = "[data-blume-consent-open]";
28
+
29
+ /**
30
+ * Run each held tag the page hasn't run yet, as a new `<script>` beside it
31
+ * with the same attributes and body. `ran` is keyed by the tag's markup,
32
+ * which is the same on every page, so a tag the router brings back is
33
+ * skipped.
34
+ */
35
+ export const runHeldScripts = (ran: Set<string>): void => {
36
+ for (const held of document.querySelectorAll(HELD_SCRIPTS)) {
37
+ const key = held.outerHTML;
38
+ if (ran.has(key)) {
39
+ continue;
40
+ }
41
+ ran.add(key);
42
+ const script = document.createElement("script");
43
+ for (const { name, value } of held.attributes) {
44
+ if (name !== "type" && name !== "data-blume-consent") {
45
+ script.setAttribute(name, value);
46
+ }
47
+ }
48
+ // A created script is async unless told otherwise; keep the tags in
49
+ // document order, as the parser would have, unless one asked for async.
50
+ if (!held.hasAttribute("async")) {
51
+ script.async = false;
52
+ }
53
+ script.text = held.textContent ?? "";
54
+ held.after(script);
55
+ }
56
+ };
57
+
58
+ /**
59
+ * Start the consent runtime on this page load, then the configured adapter's
60
+ * browser module (`startClient`, from the generated `blume:consent-client`;
61
+ * none for a hosted manager, whose `<head>` tags report its answers).
62
+ */
63
+ export const startConsent = (
64
+ startClient: (consent: BlumeConsent) => void = () => {
65
+ // No browser module: a hosted manager's <head> tags report its answers.
66
+ }
67
+ ): void => {
68
+ // SAFETY: ConsentWindow only adds the optional state the init script
69
+ // creates; it's checked before use.
70
+ const consent = (window as ConsentWindow).blumeConsent;
71
+ if (!consent) {
72
+ return;
73
+ }
74
+ const ran = new Set<string>();
75
+ const run = () => {
76
+ if (consent.analytics === true) {
77
+ runHeldScripts(ran);
78
+ }
79
+ };
80
+ window.addEventListener("blume:consent", () => {
81
+ if (consent.analytics === true) {
82
+ runHeldScripts(ran);
83
+ } else if (ran.size > 0) {
84
+ location.reload();
85
+ }
86
+ });
87
+ document.addEventListener("click", (event) => {
88
+ if (event.target instanceof Element && event.target.closest(OPEN)) {
89
+ consent.open?.();
90
+ }
91
+ });
92
+ startClient(consent);
93
+ run();
94
+ document.addEventListener("astro:after-swap", run);
95
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The browser module each consent adapter brings, by `kind`. The generated
3
+ * `blume:consent-client` (see `consentClientTemplate`) imports the configured
4
+ * adapter's, so a site bundles only its own adapter's browser code, the way
5
+ * `blume:search-client` does for search.
6
+ *
7
+ * Hosted managers (`osano()`, `ethyca()`) have none: their `<head>` tags load
8
+ * them and report their answers (see `head.ts`). A manager that ships as an
9
+ * npm package adds its module under `components/layout/consent/` instead: a
10
+ * `start` (`ConsentClientStart` in its `types.ts`) that reports the reader's answer with
11
+ * `consent.set({ analytics })` and sets `consent.open`, with the packages it
12
+ * imports listed in its factory's `runtimeDeps`, so only the sites that pick
13
+ * it install them.
14
+ */
15
+
16
+ /** Each adapter's browser module, as the generated project imports it. */
17
+ export const CONSENT_CLIENT_MODULES = new Map([
18
+ ["native", "blume/components/layout/consent/native.ts"],
19
+ ]);
@@ -0,0 +1,71 @@
1
+ import { z } from "zod";
2
+
3
+ import type { HeadScript } from "../analytics/head.ts";
4
+ import type { AdapterDescriptor } from "../core/adapter.ts";
5
+ import { adapterDescriptorSchema } from "../core/adapter.ts";
6
+
7
+ /** Options for {@link ethyca}. */
8
+ export interface EthycaOptions {
9
+ /**
10
+ * The key of the privacy notice that covers analytics, as you named it in
11
+ * Fides. Defaults to `analytics`.
12
+ */
13
+ notice?: string;
14
+ /** Your Fides privacy center's origin, which serves `fides.js`. */
15
+ privacyCenter: string;
16
+ /** The Fides property to load, when you have more than one. */
17
+ propertyId?: string;
18
+ }
19
+
20
+ export const ethycaOptionsSchema = z.strictObject({
21
+ notice: z.string().min(1).optional(),
22
+ privacyCenter: z.url({ protocol: /^https?$/u }),
23
+ propertyId: z.string().min(1).optional(),
24
+ });
25
+
26
+ export type EthycaAdapter = AdapterDescriptor<"ethyca", EthycaOptions>;
27
+
28
+ export const ethycaAdapterSchema = adapterDescriptorSchema(
29
+ "ethyca",
30
+ ethycaOptionsSchema
31
+ );
32
+
33
+ /**
34
+ * Ethyca's Fides consent manager, loaded from your privacy center. Fides
35
+ * shows its own banner and modal, set up in Fides, and Blume runs the
36
+ * analytics once the reader's analytics notice is on. Nothing here is
37
+ * secret.
38
+ */
39
+ export const ethyca = (options: EthycaOptions): EthycaAdapter => ({
40
+ kind: "ethyca",
41
+ options,
42
+ requiredSecrets: [],
43
+ runtimeDeps: [],
44
+ });
45
+
46
+ /**
47
+ * Reports the analytics notice to `window.blumeConsent` when Fides is ready
48
+ * and whenever the reader saves a change, and reopens Fides' modal from the
49
+ * Cookie settings link. The notice key rides in as `data-notice`. It counts
50
+ * as allowed when on (`true`), opted in, or a notice that only asks for
51
+ * acknowledgment.
52
+ */
53
+ export const ETHYCA_BRIDGE = `(()=>{const c=window.blumeConsent;if(!c){return;}const k=document.currentScript?.dataset.notice??"analytics";const sync=(e)=>{const v=(e?.detail?.consent??window.Fides?.consent??{})[k];c.set({analytics:v===true||v==="opt_in"||v==="acknowledge"});};c.open=()=>window.Fides?.showModal();addEventListener("FidesReady",sync);addEventListener("FidesUpdated",sync);if(window.Fides?.initialized){sync();}})();`;
54
+
55
+ /** Fides' script from the privacy center, then the bridge. */
56
+ export const ethycaHead = (options: EthycaOptions): HeadScript[] => {
57
+ const src = new URL(
58
+ "fides.js",
59
+ `${options.privacyCenter.replace(/\/+$/u, "")}/`
60
+ );
61
+ if (options.propertyId) {
62
+ src.searchParams.set("property_id", options.propertyId);
63
+ }
64
+ return [
65
+ { attributes: { src: src.href }, content: null },
66
+ {
67
+ attributes: { "data-notice": options.notice ?? "analytics" },
68
+ content: ETHYCA_BRIDGE,
69
+ },
70
+ ];
71
+ };
@@ -0,0 +1,24 @@
1
+ import type { HeadScript } from "../analytics/head.ts";
2
+ import { ethycaHead } from "./ethyca.ts";
3
+ import { osanoHead } from "./osano.ts";
4
+ import type { ConsentAdapter } from "./schema.ts";
5
+
6
+ /**
7
+ * The tags one consent adapter emits into `<head>`, after the init script and
8
+ * ahead of the held analytics: a hosted manager's loader and the bridge that
9
+ * reports its answers to `window.blumeConsent`. `native()` has none; its
10
+ * banner is markup (`ConsentBanner.astro`) and its logic is the runtime's.
11
+ */
12
+ export const consentHead = (adapter: ConsentAdapter): HeadScript[] => {
13
+ switch (adapter.kind) {
14
+ case "ethyca": {
15
+ return ethycaHead(adapter.options);
16
+ }
17
+ case "osano": {
18
+ return osanoHead(adapter.options);
19
+ }
20
+ default: {
21
+ return [];
22
+ }
23
+ }
24
+ };
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Consent adapters for `blume.config.ts`:
3
+ *
4
+ * ```ts
5
+ * import { defineConfig } from "blume";
6
+ * import { googleAnalytics } from "blume/analytics";
7
+ * import { native } from "blume/consent";
8
+ *
9
+ * export default defineConfig({
10
+ * analytics: [googleAnalytics({ id: "G-XXXXXXXXXX" })],
11
+ * consent: native({ policy: "/privacy" }),
12
+ * });
13
+ * ```
14
+ *
15
+ * With `consent` set, analytics waits for the reader: every adapter's tags are
16
+ * held until the consent adapter reports that analytics is allowed. Each
17
+ * factory returns a plain descriptor (see `core/adapter.ts`).
18
+ *
19
+ * Adding a consent manager: a factory and option schema in its own module,
20
+ * and a member of `consentAdapterSchema` (`schema.ts`). Then connect it to
21
+ * `window.blumeConsent` (see `init.ts` for the contract): report the reader's
22
+ * choice with `set({ analytics })` on load and on every change, and set
23
+ * `open` to reopen the manager's preferences. A hosted manager does that
24
+ * with tags in `consentHead` (`head.ts`): its loader, then a constant bridge
25
+ * script (`osano.ts` is an example). A manager that ships as an npm package
26
+ * does it in a browser module instead, registered in `clients.ts`, with its
27
+ * packages in the factory's `runtimeDeps` (`native()`'s banner is the
28
+ * example).
29
+ */
30
+ export type { AdapterDescriptor, JsonValue } from "../core/adapter.ts";
31
+ export { ethyca } from "./ethyca.ts";
32
+ export type { EthycaAdapter, EthycaOptions } from "./ethyca.ts";
33
+ export { native } from "./native.ts";
34
+ export type { NativeAdapter, NativeOptions } from "./native.ts";
35
+ export { osano } from "./osano.ts";
36
+ export type { OsanoAdapter, OsanoOptions } from "./osano.ts";
37
+ export type { ConsentAdapter } from "./schema.ts";
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The consent layer's first script, inlined at the top of `<head>` on every
3
+ * page when `consent` is configured, ahead of any adapter's script and the
4
+ * held analytics. It creates `window.blumeConsent`, the one contract every
5
+ * consent adapter talks to:
6
+ *
7
+ * - `analytics`: `null` until an adapter reports, then the reader's choice.
8
+ * - `set({ analytics })`: what an adapter calls with the reader's choice, on
9
+ * load for a returning reader and again whenever it changes. A change fires
10
+ * a `blume:consent` event on `window` (`detail: { analytics }`), which the
11
+ * runtime (`client.ts`) answers by running the held analytics, and which a
12
+ * site can listen to for its own scripts.
13
+ * - `open()`: set by an adapter to reopen its preferences; the footer's
14
+ * Cookie settings link calls it.
15
+ * - `kind`: the configured adapter (`native`, `osano`, …), from the tag's
16
+ * `data-kind`.
17
+ *
18
+ * It also sets `window.webAnalyticsBeforeSend`, which Vercel Web Analytics
19
+ * reads when it starts, so `vercel()` sends nothing until analytics is
20
+ * allowed; its script is a component rather than a tag, so it can't be held
21
+ * like the others.
22
+ *
23
+ * A constant, like the layouts' other inline scripts (see
24
+ * `components/layout/head-scripts.ts`): the kind rides in as an attribute,
25
+ * never as interpolated source. It runs once per real page load; the client
26
+ * router never runs an inline script twice, and the state it creates lives
27
+ * on across navigations.
28
+ */
29
+ export const CONSENT_INIT_SCRIPT = `(()=>{if(window.blumeConsent){return;}const c={analytics:null,kind:document.currentScript?.dataset.kind??"",set(s){const a=s?.analytics===true;if(c.analytics===a){return;}c.analytics=a;dispatchEvent(new CustomEvent("blume:consent",{detail:{analytics:a}}));}};window.blumeConsent=c;window.webAnalyticsBeforeSend=(e)=>c.analytics===true?e:null;})();`;
@@ -0,0 +1,36 @@
1
+ import { z } from "zod";
2
+
3
+ import type { AdapterDescriptor } from "../core/adapter.ts";
4
+ import { adapterDescriptorSchema } from "../core/adapter.ts";
5
+
6
+ /** Options for {@link native}. */
7
+ export interface NativeOptions {
8
+ /** Where the banner's privacy policy link goes: a page route or a URL. */
9
+ policy?: string;
10
+ }
11
+
12
+ export const nativeOptionsSchema = z.strictObject({
13
+ policy: z.string().min(1).optional(),
14
+ });
15
+
16
+ export type NativeAdapter = AdapterDescriptor<"native", NativeOptions>;
17
+
18
+ export const nativeAdapterSchema = adapterDescriptorSchema(
19
+ "native",
20
+ nativeOptionsSchema
21
+ );
22
+
23
+ /**
24
+ * Blume's own consent banner: a card at the foot of the page asking to use
25
+ * analytics cookies, with Accept and Decline side by side and an optional
26
+ * link to your privacy policy. The answer stays in the reader's browser, and
27
+ * the footer's Cookie settings link brings the banner back to change it. Its
28
+ * text comes from the `consent` UI strings, translated in every built-in
29
+ * language.
30
+ */
31
+ export const native = (options: NativeOptions = {}): NativeAdapter => ({
32
+ kind: "native",
33
+ options,
34
+ requiredSecrets: [],
35
+ runtimeDeps: [],
36
+ });
@@ -0,0 +1,59 @@
1
+ import { z } from "zod";
2
+
3
+ import type { HeadScript } from "../analytics/head.ts";
4
+ import type { AdapterDescriptor } from "../core/adapter.ts";
5
+ import { adapterDescriptorSchema } from "../core/adapter.ts";
6
+
7
+ /** Options for {@link osano}. */
8
+ export interface OsanoOptions {
9
+ /** The configuration ID from the script tag Osano gives you. */
10
+ configId: string;
11
+ /** The customer ID from the script tag Osano gives you. */
12
+ customerId: string;
13
+ }
14
+
15
+ export const osanoOptionsSchema = z.strictObject({
16
+ configId: z.string().min(1),
17
+ customerId: z.string().min(1),
18
+ });
19
+
20
+ export type OsanoAdapter = AdapterDescriptor<"osano", OsanoOptions>;
21
+
22
+ export const osanoAdapterSchema = adapterDescriptorSchema(
23
+ "osano",
24
+ osanoOptionsSchema
25
+ );
26
+
27
+ /**
28
+ * Osano Cookie Consent. Osano shows its own banner and drawer, set up in the
29
+ * Osano dashboard, and Blume runs the analytics once Osano reports the
30
+ * reader's `ANALYTICS` consent. Both IDs come from the script tag Osano
31
+ * gives you, and neither is secret.
32
+ */
33
+ export const osano = (options: OsanoOptions): OsanoAdapter => ({
34
+ kind: "osano",
35
+ options,
36
+ requiredSecrets: [],
37
+ runtimeDeps: [],
38
+ });
39
+
40
+ /**
41
+ * Reports Osano's analytics consent to `window.blumeConsent` now (`Osano.cm`
42
+ * is ready as soon as its script ran) and on every Osano consent event, and
43
+ * reopens Osano's drawer from the Cookie settings link.
44
+ */
45
+ export const OSANO_BRIDGE = `(()=>{const o=window.Osano?.cm;const c=window.blumeConsent;if(!o||!c){return;}const sync=()=>c.set({analytics:o.analytics===true});c.open=()=>o.showDrawer();for(const e of ["osano-cm-initialized","osano-cm-consent-saved","osano-cm-consent-changed"]){o.addEventListener(e,sync);}sync();})();`;
46
+
47
+ /**
48
+ * Osano's loader, synchronous as its install guide requires, then the
49
+ * bridge. The IDs are path segments, so each is encoded.
50
+ */
51
+ export const osanoHead = (options: OsanoOptions): HeadScript[] => [
52
+ {
53
+ attributes: {
54
+ src: `https://cmp.osano.com/${encodeURIComponent(options.customerId)}/${encodeURIComponent(options.configId)}/osano.js`,
55
+ },
56
+ content: null,
57
+ },
58
+ { attributes: {}, content: OSANO_BRIDGE },
59
+ ];
@@ -0,0 +1,30 @@
1
+ import { z } from "zod";
2
+
3
+ import { ethycaAdapterSchema } from "./ethyca.ts";
4
+ import { nativeAdapterSchema } from "./native.ts";
5
+ import { osanoAdapterSchema } from "./osano.ts";
6
+
7
+ const ADAPTER_HINT =
8
+ 'consent takes one adapter — e.g. `consent: native()` or `consent: osano({ customerId, configId })`, imported from "blume/consent".';
9
+
10
+ /**
11
+ * The configured consent adapter, as its factory returned it. Anything that
12
+ * isn't one (`true`, a list, an unknown `kind`) fails with the adapter hint;
13
+ * an adapter's own option errors keep their messages.
14
+ */
15
+ export const consentAdapterSchema = z.discriminatedUnion(
16
+ "kind",
17
+ [ethycaAdapterSchema, nativeAdapterSchema, osanoAdapterSchema],
18
+ { error: ADAPTER_HINT }
19
+ );
20
+
21
+ export type ConsentAdapter = z.output<typeof consentAdapterSchema>;
22
+
23
+ /**
24
+ * `blume.config.consent`: the adapter that asks readers before analytics
25
+ * runs. Unset (`null` once resolved) means no consent layer, and analytics
26
+ * runs as it loads.
27
+ */
28
+ export const consentConfigSchema = consentAdapterSchema
29
+ .optional()
30
+ .transform((adapter) => adapter ?? null);
@@ -31,7 +31,11 @@ export const BUILTIN_MDX_TAGS = new Set<string>([
31
31
  "Math",
32
32
  "Operation",
33
33
  "Panel",
34
+ "ParamField",
34
35
  "Prompt",
36
+ "RequestExample",
37
+ "ResponseExample",
38
+ "ResponseField",
35
39
  "Step",
36
40
  "Steps",
37
41
  "Tab",
@@ -40,6 +44,7 @@ export const BUILTIN_MDX_TAGS = new Set<string>([
40
44
  "Tooltip",
41
45
  "Tree",
42
46
  "TypeTable",
47
+ "View",
43
48
  "Visibility",
44
49
  "YouTube",
45
50
  ]);
@@ -0,0 +1,19 @@
1
+ /** The slice of Astro's `APIContext` a server route reads the reader from. */
2
+ export interface ClientContext {
3
+ /** The reader's address; Astro's getter throws where the host can't tell. */
4
+ readonly clientAddress?: string;
5
+ readonly request: Request;
6
+ }
7
+
8
+ /**
9
+ * The reader's IP address as the host reports it (Astro resolves the
10
+ * platform's trusted header, or the socket on a Node server), or `undefined`
11
+ * where the host can't tell.
12
+ */
13
+ export const clientAddressOf = (context: ClientContext): string | undefined => {
14
+ try {
15
+ return context.clientAddress || undefined;
16
+ } catch {
17
+ return undefined;
18
+ }
19
+ };