blume 2.0.3 → 2.1.1

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 (607) hide show
  1. package/AGENTS.md +1 -0
  2. package/CHANGELOG.md +142 -0
  3. package/README.md +1 -1
  4. package/dist/cli/{chunk-5f86nr5m.js → chunk-073rdvgb.js} +21 -48
  5. package/dist/cli/{chunk-5f86nr5m.js.map → chunk-073rdvgb.js.map} +4 -5
  6. package/dist/cli/{chunk-ga0pf4aj.js → chunk-0n9xkp3d.js} +12 -3
  7. package/dist/cli/{chunk-ga0pf4aj.js.map → chunk-0n9xkp3d.js.map} +3 -3
  8. package/dist/cli/chunk-150jk7km.js +52 -0
  9. package/dist/cli/chunk-150jk7km.js.map +10 -0
  10. package/dist/cli/{chunk-9t7a85s3.js → chunk-313vnn40.js} +30 -19
  11. package/dist/cli/chunk-313vnn40.js.map +10 -0
  12. package/dist/cli/{chunk-tkacnehg.js → chunk-3v3ffbrj.js} +2 -2
  13. package/dist/cli/{chunk-q58y5e6a.js → chunk-3x6x3pph.js} +46 -24
  14. package/dist/cli/chunk-3x6x3pph.js.map +10 -0
  15. package/dist/cli/{chunk-1d7ve1dm.js → chunk-42t4jxdx.js} +37 -5
  16. package/dist/cli/chunk-42t4jxdx.js.map +12 -0
  17. package/dist/cli/{chunk-8ktnccpt.js → chunk-54ztw1nj.js} +21 -2
  18. package/dist/cli/chunk-54ztw1nj.js.map +10 -0
  19. package/dist/cli/{chunk-hm3vjy5s.js → chunk-5vjtgs6e.js} +28 -10
  20. package/dist/cli/{chunk-hm3vjy5s.js.map → chunk-5vjtgs6e.js.map} +4 -4
  21. package/dist/cli/chunk-66w9j7p6.js +322 -0
  22. package/dist/cli/chunk-66w9j7p6.js.map +14 -0
  23. package/dist/cli/{chunk-2hsdwb9n.js → chunk-7ppf1rva.js} +34 -18
  24. package/dist/cli/chunk-7ppf1rva.js.map +10 -0
  25. package/dist/cli/{chunk-r9rcc4w7.js → chunk-8y2kmjv8.js} +7 -7
  26. package/dist/cli/{chunk-r20tn01b.js → chunk-c1y538kd.js} +8 -2
  27. package/dist/cli/{chunk-r20tn01b.js.map → chunk-c1y538kd.js.map} +3 -3
  28. package/dist/cli/{chunk-2eytanqx.js → chunk-c887fj0s.js} +2 -2
  29. package/dist/cli/{chunk-p3v96n38.js → chunk-cfyg47zg.js} +16 -6
  30. package/dist/cli/chunk-cfyg47zg.js.map +10 -0
  31. package/dist/cli/chunk-cm89scdv.js +443 -0
  32. package/dist/cli/chunk-cm89scdv.js.map +11 -0
  33. package/dist/cli/{chunk-akbpwfxc.js → chunk-dzwehpy7.js} +2 -2
  34. package/dist/cli/{chunk-wrr3j9w9.js → chunk-e6atmn4h.js} +299 -72
  35. package/dist/cli/chunk-e6atmn4h.js.map +36 -0
  36. package/dist/cli/{chunk-tzmab476.js → chunk-e8xw9qkh.js} +8 -6
  37. package/dist/cli/{chunk-tzmab476.js.map → chunk-e8xw9qkh.js.map} +3 -3
  38. package/dist/cli/{chunk-6dsbexzp.js → chunk-e9q7a2ak.js} +17 -15
  39. package/dist/cli/{chunk-6dsbexzp.js.map → chunk-e9q7a2ak.js.map} +2 -2
  40. package/dist/cli/{chunk-pv29h0wf.js → chunk-ehweg4fr.js} +5155 -1249
  41. package/dist/cli/chunk-ehweg4fr.js.map +218 -0
  42. package/dist/cli/{chunk-c8chx29p.js → chunk-ep6nd0rn.js} +390 -318
  43. package/dist/cli/chunk-ep6nd0rn.js.map +36 -0
  44. package/dist/cli/{chunk-p73c0m7w.js → chunk-fdrkhpjy.js} +18 -15
  45. package/dist/cli/{chunk-p73c0m7w.js.map → chunk-fdrkhpjy.js.map} +3 -3
  46. package/dist/cli/{chunk-2z928egk.js → chunk-ft9vfys6.js} +5 -5
  47. package/dist/cli/{chunk-5m5nmvyq.js → chunk-gb420vvz.js} +316 -79
  48. package/dist/cli/chunk-gb420vvz.js.map +17 -0
  49. package/dist/cli/{chunk-vg9r4eb9.js → chunk-hebn0tpx.js} +86 -13
  50. package/dist/cli/chunk-hebn0tpx.js.map +14 -0
  51. package/dist/cli/{chunk-35d4wj9f.js → chunk-htrwgabr.js} +41 -23
  52. package/dist/cli/chunk-htrwgabr.js.map +15 -0
  53. package/dist/cli/{chunk-g4hq16wv.js → chunk-hx3xqnk9.js} +16 -14
  54. package/dist/cli/{chunk-g4hq16wv.js.map → chunk-hx3xqnk9.js.map} +2 -2
  55. package/dist/cli/chunk-j134vrp2.js +65 -0
  56. package/dist/cli/chunk-j134vrp2.js.map +10 -0
  57. package/dist/cli/{chunk-a58773jm.js → chunk-kma9f6sf.js} +2 -2
  58. package/dist/cli/chunk-kwrg63tm.js +31 -0
  59. package/dist/cli/chunk-kwrg63tm.js.map +10 -0
  60. package/dist/cli/{chunk-ey84smr6.js → chunk-mrcccgnh.js} +6 -6
  61. package/dist/cli/{chunk-ey84smr6.js.map → chunk-mrcccgnh.js.map} +1 -1
  62. package/dist/cli/{chunk-yfyb25rh.js → chunk-n0v7m8ry.js} +24 -8
  63. package/dist/cli/chunk-n0v7m8ry.js.map +14 -0
  64. package/dist/cli/{chunk-j85vccga.js → chunk-ncj7w596.js} +576 -367
  65. package/dist/cli/chunk-ncj7w596.js.map +35 -0
  66. package/dist/cli/{chunk-5xvm6tfj.js → chunk-nq1d20w2.js} +17 -15
  67. package/dist/cli/{chunk-5xvm6tfj.js.map → chunk-nq1d20w2.js.map} +2 -2
  68. package/dist/cli/{chunk-pehfxfta.js → chunk-nrns10mj.js} +6 -98
  69. package/dist/cli/chunk-nrns10mj.js.map +10 -0
  70. package/dist/cli/{chunk-crgn1q09.js → chunk-sds923fa.js} +4 -4
  71. package/dist/cli/chunk-t2m5j4pr.js +104 -0
  72. package/dist/cli/chunk-t2m5j4pr.js.map +11 -0
  73. package/dist/cli/{chunk-acanzt5p.js → chunk-tdqhyxfz.js} +6 -6
  74. package/dist/cli/chunk-tphac74f.js +126 -0
  75. package/dist/cli/chunk-tphac74f.js.map +11 -0
  76. package/dist/cli/chunk-w1r4vase.js +18 -0
  77. package/dist/cli/chunk-w1r4vase.js.map +10 -0
  78. package/dist/cli/{chunk-3em5wd2y.js → chunk-zccbjcj0.js} +4 -3
  79. package/dist/cli/{chunk-3em5wd2y.js.map → chunk-zccbjcj0.js.map} +2 -2
  80. package/dist/cli/index.js +31 -20
  81. package/dist/cli/index.js.map +5 -5
  82. package/dist/types/ai/agent-surface.d.ts +8 -7
  83. package/dist/types/ai/ai-catalog.d.ts +7 -0
  84. package/dist/types/ai/ask-context.d.ts +26 -0
  85. package/dist/types/ai/ask.d.ts +271 -58
  86. package/dist/types/ai/component-markdown.d.ts +2 -0
  87. package/dist/types/ai/index.d.ts +2 -2
  88. package/dist/types/ai/openapi-components.d.ts +4 -1
  89. package/dist/types/ai/site-skill.d.ts +26 -0
  90. package/dist/types/ai/skills.d.ts +16 -0
  91. package/dist/types/astro/integration.d.ts +9 -0
  92. package/dist/types/astro/markdown-negotiation.d.ts +3 -0
  93. package/dist/types/astro/pages.d.ts +10 -0
  94. package/dist/types/captcha/hcaptcha.d.ts +27 -0
  95. package/dist/types/captcha/index.d.ts +28 -0
  96. package/dist/types/captcha/schema.d.ts +29 -0
  97. package/dist/types/captcha/turnstile.d.ts +28 -0
  98. package/dist/types/cli/init/scaffold.d.ts +1 -1
  99. package/dist/types/components/content/api-field.d.ts +62 -0
  100. package/dist/types/components/content/api-page.d.ts +100 -0
  101. package/dist/types/components/layout/nav-utils.d.ts +26 -0
  102. package/dist/types/components/openapi/code-samples.d.ts +29 -0
  103. package/dist/types/components/openapi/helpers.d.ts +158 -0
  104. package/dist/types/components/openapi/security.d.ts +95 -0
  105. package/dist/types/components/openapi/snippets.d.ts +60 -0
  106. package/dist/types/consent/ethyca.d.ts +48 -0
  107. package/dist/types/consent/index.d.ts +37 -0
  108. package/dist/types/consent/native.d.ts +28 -0
  109. package/dist/types/consent/osano.d.ts +42 -0
  110. package/dist/types/consent/schema.d.ts +110 -0
  111. package/dist/types/core/changelog-index.d.ts +8 -0
  112. package/dist/types/core/config-input.d.ts +217 -23
  113. package/dist/types/core/data.d.ts +53 -4
  114. package/dist/types/core/footer.d.ts +8 -0
  115. package/dist/types/core/i18n-ui.d.ts +88 -0
  116. package/dist/types/core/includes.d.ts +8 -2
  117. package/dist/types/core/links.d.ts +8 -0
  118. package/dist/types/core/localizable.d.ts +7 -0
  119. package/dist/types/core/page-modes.d.ts +29 -0
  120. package/dist/types/core/probe.d.ts +2 -0
  121. package/dist/types/core/project-graph.d.ts +6 -0
  122. package/dist/types/core/redirect-patterns.d.ts +152 -0
  123. package/dist/types/core/related.d.ts +40 -0
  124. package/dist/types/core/schema.d.ts +670 -56
  125. package/dist/types/core/sources/cache.d.ts +3 -0
  126. package/dist/types/core/sources/contentful-rich-text.d.ts +11 -2
  127. package/dist/types/core/sources/contentful.d.ts +17 -1
  128. package/dist/types/core/sources/lexical.d.ts +5 -0
  129. package/dist/types/core/sources/normalize.d.ts +20 -1
  130. package/dist/types/core/sources/read.d.ts +5 -0
  131. package/dist/types/core/sources/remote.d.ts +37 -10
  132. package/dist/types/core/sources/sanity.d.ts +1 -1
  133. package/dist/types/core/types.d.ts +18 -1
  134. package/dist/types/core/variables.d.ts +42 -0
  135. package/dist/types/deploy/adapter-output.d.ts +2 -1
  136. package/dist/types/deploy/adapters/cloudflare.d.ts +7 -5
  137. package/dist/types/deploy/adapters/node.d.ts +58 -23
  138. package/dist/types/deploy/adapters/registry.d.ts +10 -0
  139. package/dist/types/deploy/adapters/types.d.ts +3 -2
  140. package/dist/types/deploy/node-headers.d.ts +13 -2
  141. package/dist/types/deploy/platforms/cloudflare.d.ts +15 -7
  142. package/dist/types/deploy/platforms/netlify.d.ts +7 -0
  143. package/dist/types/deploy/platforms/node.d.ts +3 -1
  144. package/dist/types/deploy/platforms/types.d.ts +18 -7
  145. package/dist/types/deploy/platforms/vercel.d.ts +26 -1
  146. package/dist/types/deploy/redirects.d.ts +55 -11
  147. package/dist/types/deploy/sitemap.d.ts +2 -1
  148. package/dist/types/deploy/vercel-negotiation.d.ts +51 -21
  149. package/dist/types/markdown/code-title.d.ts +17 -0
  150. package/dist/types/markdown/features.d.ts +3 -2
  151. package/dist/types/narration/build.d.ts +70 -0
  152. package/dist/types/narration/provider.d.ts +26 -0
  153. package/dist/types/narration/script.d.ts +154 -0
  154. package/dist/types/openapi/checks.d.ts +27 -0
  155. package/dist/types/openapi/graphql.d.ts +6 -0
  156. package/dist/types/openapi/model.d.ts +27 -10
  157. package/dist/types/openapi/overlay.d.ts +54 -0
  158. package/dist/types/openapi/parse.d.ts +16 -0
  159. package/dist/types/openapi/references.d.ts +30 -4
  160. package/dist/types/ratelimit/cloudflare.d.ts +39 -0
  161. package/dist/types/ratelimit/index.d.ts +27 -0
  162. package/dist/types/ratelimit/memory.d.ts +36 -0
  163. package/dist/types/ratelimit/schema.d.ts +119 -0
  164. package/dist/types/ratelimit/upstash.d.ts +46 -0
  165. package/dist/types/ratelimit/wrangler.d.ts +23 -0
  166. package/dist/types/reference/asyncapi.d.ts +10 -10
  167. package/dist/types/reference/graphql.d.ts +89 -11
  168. package/dist/types/reference/index.d.ts +1 -1
  169. package/dist/types/reference/openapi.d.ts +33 -12
  170. package/dist/types/reference/options.d.ts +82 -6
  171. package/dist/types/reference/scalar.d.ts +13 -0
  172. package/dist/types/reference/schema.d.ts +144 -36
  173. package/dist/types/search/adapters/registry.d.ts +3 -0
  174. package/dist/types/search/adapters/typesense.d.ts +14 -4
  175. package/dist/types/search/build.d.ts +3 -1
  176. package/dist/types/search/documents.d.ts +12 -1
  177. package/dist/types/search/orama-index.d.ts +13 -9
  178. package/dist/types/search/sync/algolia.d.ts +5 -2
  179. package/dist/types/search/sync/index.d.ts +3 -1
  180. package/dist/types/search/sync/typesense.d.ts +11 -7
  181. package/dist/types/seo/metatags.d.ts +20 -0
  182. package/dist/types/sources/contentful.d.ts +16 -0
  183. package/dist/types/sources/github-releases.d.ts +8 -1
  184. package/dist/types/sources/payload.d.ts +2 -0
  185. package/dist/types/sources/registry.d.ts +54 -0
  186. package/dist/types/sources/shared.d.ts +3 -0
  187. package/dist/types/sources/strapi.d.ts +2 -0
  188. package/docs/01-quickstart.mdx +4 -2
  189. package/docs/02-deployment.mdx +71 -17
  190. package/docs/03-upgrading.mdx +4 -4
  191. package/docs/04-migrating.mdx +1 -1
  192. package/docs/advanced/changelog.mdx +13 -2
  193. package/docs/advanced/skills.mdx +15 -1
  194. package/docs/cli/audit.mdx +51 -8
  195. package/docs/cli/doctor.mdx +5 -1
  196. package/docs/cli/evals.mdx +4 -4
  197. package/docs/cli/index.mdx +1 -0
  198. package/docs/cli/translate.mdx +1 -0
  199. package/docs/cli/validate.mdx +4 -3
  200. package/docs/configuration/analytics.mdx +3 -1
  201. package/docs/configuration/assistant.mdx +194 -38
  202. package/docs/configuration/consent.mdx +100 -0
  203. package/docs/configuration/customization.mdx +8 -6
  204. package/docs/configuration/export.mdx +5 -3
  205. package/docs/configuration/index.mdx +64 -5
  206. package/docs/configuration/meta.ts +3 -0
  207. package/docs/configuration/narration.mdx +119 -0
  208. package/docs/configuration/rate-limiting.mdx +90 -0
  209. package/docs/configuration/search.mdx +63 -12
  210. package/docs/configuration/theming.mdx +3 -1
  211. package/docs/content/components.mdx +108 -2
  212. package/docs/content/frontmatter.mdx +80 -2
  213. package/docs/content/i18n.mdx +39 -4
  214. package/docs/content/includes.mdx +16 -0
  215. package/docs/content/meta.mdx +1 -0
  216. package/docs/content/meta.ts +1 -0
  217. package/docs/content/navigation.mdx +32 -10
  218. package/docs/content/sources/contentful.mdx +35 -0
  219. package/docs/content/sources/custom.mdx +43 -0
  220. package/docs/content/sources/github-releases.mdx +39 -0
  221. package/docs/content/sources/index.mdx +91 -0
  222. package/docs/content/sources/meta.ts +16 -0
  223. package/docs/content/sources/notion.mdx +32 -0
  224. package/docs/content/sources/obsidian.mdx +37 -0
  225. package/docs/content/sources/payload.mdx +31 -0
  226. package/docs/content/sources/remote-mdx.mdx +44 -0
  227. package/docs/content/sources/sanity.mdx +29 -0
  228. package/docs/content/sources/strapi.mdx +32 -0
  229. package/docs/content/syntax.mdx +69 -4
  230. package/docs/content/variables.mdx +41 -0
  231. package/docs/discoverability/agent-discovery.mdx +29 -2
  232. package/docs/discoverability/index.mdx +2 -2
  233. package/docs/discoverability/json-api.mdx +2 -0
  234. package/docs/discoverability/llms-txt.mdx +2 -2
  235. package/docs/discoverability/markdown.mdx +3 -1
  236. package/docs/discoverability/mcp.mdx +4 -0
  237. package/docs/discoverability/metadata.mdx +17 -0
  238. package/docs/discoverability/sitemap-and-robots.mdx +1 -1
  239. package/docs/references/api-pages.mdx +74 -0
  240. package/docs/references/asyncapi.mdx +4 -2
  241. package/docs/references/graphql.mdx +14 -2
  242. package/docs/references/meta.ts +1 -1
  243. package/docs/references/openapi.mdx +148 -7
  244. package/docs/references/scalar.mdx +3 -1
  245. package/package.json +43 -8
  246. package/skills/blume/SKILL.md +3 -0
  247. package/skills/blume-migrate/SKILL.md +6 -6
  248. package/skills/blume-migrate/references/docusaurus.md +7 -7
  249. package/skills/blume-migrate/references/fumadocs.md +17 -13
  250. package/skills/blume-migrate/references/mintlify.md +37 -19
  251. package/skills/blume-migrate/references/nextra.md +10 -7
  252. package/skills/blume-migrate/references/starlight.md +11 -8
  253. package/skills/blume-migrate/scripts/mintlify-codemod.mjs +60 -14
  254. package/skills/blume-write-skill/SKILL.md +82 -0
  255. package/src/ai/agent-readability.ts +2 -1
  256. package/src/ai/agent-surface.ts +9 -7
  257. package/src/ai/ai-catalog.ts +6 -3
  258. package/src/ai/ask-context.ts +103 -20
  259. package/src/ai/ask-data.ts +6 -0
  260. package/src/ai/ask-limits.ts +13 -0
  261. package/src/ai/ask-tools.ts +142 -0
  262. package/src/ai/ask.ts +354 -76
  263. package/src/ai/changelog-markdown.ts +11 -6
  264. package/src/ai/component-markdown.ts +76 -1
  265. package/src/ai/cors.ts +14 -3
  266. package/src/ai/index.ts +12 -0
  267. package/src/ai/llms.ts +6 -2
  268. package/src/ai/markdown.ts +2 -1
  269. package/src/ai/mcp/data.ts +6 -0
  270. package/src/ai/mcp/query.ts +14 -6
  271. package/src/ai/openapi-components.ts +36 -6
  272. package/src/ai/relative-links.ts +4 -38
  273. package/src/ai/site-skill.ts +274 -0
  274. package/src/ai/skills.ts +35 -2
  275. package/src/ai/write-skill.ts +97 -0
  276. package/src/astro/generate.ts +210 -66
  277. package/src/astro/index.ts +1 -0
  278. package/src/astro/integration.ts +42 -4
  279. package/src/astro/markdown-negotiation.ts +3 -0
  280. package/src/astro/module-types.ts +9 -1
  281. package/src/astro/pages.ts +23 -0
  282. package/src/astro/templates.ts +406 -108
  283. package/src/astro/variables.ts +31 -0
  284. package/src/audit/catalog.ts +38 -3
  285. package/src/audit/checks/contrast.ts +183 -0
  286. package/src/audit/checks/i18n.ts +2 -3
  287. package/src/audit/checks/indexability.ts +2 -3
  288. package/src/audit/checks/links.ts +19 -13
  289. package/src/audit/checks/network.ts +110 -6
  290. package/src/audit/checks/redirects.ts +6 -4
  291. package/src/audit/checks/robots.ts +58 -2
  292. package/src/audit/checks/sitemap.ts +2 -3
  293. package/src/audit/redirects.ts +46 -15
  294. package/src/audit/run.ts +5 -0
  295. package/src/audit/types.ts +4 -1
  296. package/src/audit/url.ts +14 -5
  297. package/src/blume-modules.d.ts +12 -1
  298. package/src/captcha/client.ts +152 -0
  299. package/src/captcha/hcaptcha.ts +36 -0
  300. package/src/captcha/index.ts +28 -0
  301. package/src/captcha/schema.ts +32 -0
  302. package/src/captcha/turnstile.ts +38 -0
  303. package/src/captcha/verify.ts +71 -0
  304. package/src/cli/args.ts +51 -0
  305. package/src/cli/build-failure.ts +23 -0
  306. package/src/cli/command-meta.ts +5 -0
  307. package/src/cli/commands/audit.ts +10 -1
  308. package/src/cli/commands/dev.ts +18 -2
  309. package/src/cli/commands/doctor.ts +67 -28
  310. package/src/cli/commands/eval.ts +36 -4
  311. package/src/cli/commands/init.ts +6 -4
  312. package/src/cli/commands/skill.ts +96 -0
  313. package/src/cli/commands/validate.ts +10 -1
  314. package/src/cli/index.ts +5 -0
  315. package/src/cli/init/scaffold.ts +3 -3
  316. package/src/cli/prepare.ts +6 -3
  317. package/src/cli/required-secrets.ts +72 -30
  318. package/src/components/BlumePage.astro +2 -0
  319. package/src/components/content/ApiEndpoint.astro +18 -0
  320. package/src/components/content/ApiField.astro +79 -0
  321. package/src/components/content/ApiPlayground.astro +66 -0
  322. package/src/components/content/ApiRail.astro +19 -0
  323. package/src/components/content/Color.astro +1 -0
  324. package/src/components/content/FileTree.astro +1 -0
  325. package/src/components/content/GithubInfo.astro +1 -0
  326. package/src/components/content/Panel.astro +1 -0
  327. package/src/components/content/ParamField.astro +25 -0
  328. package/src/components/content/RequestExample.astro +17 -0
  329. package/src/components/content/ResponseExample.astro +17 -0
  330. package/src/components/content/ResponseField.astro +32 -0
  331. package/src/components/content/Step.astro +1 -0
  332. package/src/components/content/Tile.astro +1 -0
  333. package/src/components/content/Tooltip.astro +1 -0
  334. package/src/components/content/Tree.astro +1 -0
  335. package/src/components/content/TypeTable.astro +4 -1
  336. package/src/components/content/View.astro +21 -0
  337. package/src/components/content/ViewSwitcher.astro +168 -0
  338. package/src/components/content/api-field.ts +103 -0
  339. package/src/components/content/api-page.ts +248 -0
  340. package/src/components/content/mermaid-element.ts +15 -1
  341. package/src/components/content/view-switcher.ts +71 -0
  342. package/src/components/index.ts +2 -0
  343. package/src/components/islands/Assistant.astro +10 -1
  344. package/src/components/islands/assistant.tsx +104 -14
  345. package/src/components/islands/code-question.ts +62 -0
  346. package/src/components/islands/hooks.ts +136 -21
  347. package/src/components/islands/support-link.ts +68 -0
  348. package/src/components/layout/Analytics.astro +11 -2
  349. package/src/components/layout/Banner.astro +14 -10
  350. package/src/components/layout/Breadcrumbs.astro +6 -2
  351. package/src/components/layout/ConsentBanner.astro +62 -0
  352. package/src/components/layout/ConsentHead.astro +38 -0
  353. package/src/components/layout/Directory.astro +94 -0
  354. package/src/components/layout/DrawerSwitchers.astro +51 -0
  355. package/src/components/layout/Empty.astro +2 -2
  356. package/src/components/layout/Header.astro +122 -80
  357. package/src/components/layout/LanguageSwitcher.astro +48 -15
  358. package/src/components/layout/NarrationPlayer.astro +1085 -0
  359. package/src/components/layout/NavSelector.astro +33 -7
  360. package/src/components/layout/PageActions.astro +139 -24
  361. package/src/components/layout/PageFeedback.astro +54 -49
  362. package/src/components/layout/PageLayout.astro +71 -3
  363. package/src/components/layout/ReferenceLayout.astro +17 -6
  364. package/src/components/layout/RelatedPages.astro +42 -0
  365. package/src/components/layout/RootLayout.astro +318 -47
  366. package/src/components/layout/Search.astro +47 -19
  367. package/src/components/layout/SiteFooter.astro +124 -0
  368. package/src/components/layout/SiteMetatags.astro +16 -0
  369. package/src/components/layout/TableOfContents.astro +24 -17
  370. package/src/components/layout/consent/native.ts +79 -0
  371. package/src/components/layout/consent/types.ts +37 -0
  372. package/src/components/layout/footer-links.ts +53 -0
  373. package/src/components/layout/footer-socials.ts +87 -0
  374. package/src/components/layout/head-scripts.ts +6 -1
  375. package/src/components/layout/locale-redirect.ts +107 -0
  376. package/src/components/layout/nav-utils.ts +83 -0
  377. package/src/components/layout/page-feedback.ts +96 -0
  378. package/src/components/layout/search/algolia.ts +10 -1
  379. package/src/components/layout/search/analytics.ts +126 -0
  380. package/src/components/layout/search/endpoint.ts +48 -5
  381. package/src/components/layout/search/flexsearch.ts +17 -5
  382. package/src/components/layout/search/orama-cloud.ts +26 -14
  383. package/src/components/layout/search/pagefind.ts +114 -5
  384. package/src/components/layout/search/types.ts +32 -0
  385. package/src/components/layout/search/typesense.ts +19 -3
  386. package/src/components/openapi/AsyncApiOperation.astro +14 -7
  387. package/src/components/openapi/Authorization.astro +10 -0
  388. package/src/components/openapi/GraphqlOperation.astro +5 -0
  389. package/src/components/openapi/Operation.astro +184 -13
  390. package/src/components/openapi/ParametersTable.astro +8 -4
  391. package/src/components/openapi/Playground.astro +7 -1
  392. package/src/components/openapi/RequestBody.astro +24 -5
  393. package/src/components/openapi/RequestPanel.astro +59 -7
  394. package/src/components/openapi/Responses.astro +7 -4
  395. package/src/components/openapi/SchemaTable.astro +15 -3
  396. package/src/components/openapi/async-snippets.ts +65 -9
  397. package/src/components/openapi/async.ts +123 -29
  398. package/src/components/openapi/code-samples.ts +97 -0
  399. package/src/components/openapi/graphql-helpers.ts +35 -12
  400. package/src/components/openapi/helpers.ts +36 -2
  401. package/src/components/openapi/message-model.ts +54 -11
  402. package/src/components/openapi/message.ts +14 -4
  403. package/src/components/openapi/operation-model.ts +16 -7
  404. package/src/components/openapi/playground-client.ts +24 -5
  405. package/src/components/openapi/playground-schema.ts +1 -1
  406. package/src/components/openapi/schema-tree.ts +44 -14
  407. package/src/components/openapi/security.ts +16 -3
  408. package/src/components/openapi/snippets.ts +873 -10
  409. package/src/components/openapi/validate-json.ts +4 -3
  410. package/src/components/props.ts +6 -0
  411. package/src/consent/client.ts +95 -0
  412. package/src/consent/clients.ts +19 -0
  413. package/src/consent/ethyca.ts +71 -0
  414. package/src/consent/head.ts +24 -0
  415. package/src/consent/index.ts +37 -0
  416. package/src/consent/init.ts +29 -0
  417. package/src/consent/native.ts +36 -0
  418. package/src/consent/osano.ts +59 -0
  419. package/src/consent/schema.ts +30 -0
  420. package/src/core/builtin-tags.ts +5 -0
  421. package/src/core/changelog-index.ts +31 -1
  422. package/src/core/client-address.ts +19 -0
  423. package/src/core/component-diagnostics.ts +53 -0
  424. package/src/core/component-overrides.ts +32 -0
  425. package/src/core/config-input.ts +225 -23
  426. package/src/core/data.ts +46 -4
  427. package/src/core/diagnostics.ts +8 -2
  428. package/src/core/footer.ts +26 -0
  429. package/src/core/graph.ts +39 -36
  430. package/src/core/i18n-ui.ts +84 -2
  431. package/src/core/includes.ts +21 -4
  432. package/src/core/links.ts +63 -19
  433. package/src/core/localizable.ts +26 -0
  434. package/src/core/navigation.ts +43 -12
  435. package/src/core/page-modes.ts +56 -0
  436. package/src/core/probe.ts +26 -6
  437. package/src/core/project-graph.ts +163 -16
  438. package/src/core/redirect-patterns.ts +520 -0
  439. package/src/core/related.ts +131 -0
  440. package/src/core/schema.ts +339 -66
  441. package/src/core/sources/cache.ts +6 -0
  442. package/src/core/sources/contentful-rich-text.ts +29 -6
  443. package/src/core/sources/contentful.ts +135 -25
  444. package/src/core/sources/filesystem.ts +26 -4
  445. package/src/core/sources/github-releases.ts +12 -1
  446. package/src/core/sources/lexical.ts +15 -10
  447. package/src/core/sources/mdx-remote.ts +62 -10
  448. package/src/core/sources/normalize.ts +228 -41
  449. package/src/core/sources/notion.ts +7 -1
  450. package/src/core/sources/obsidian.ts +16 -3
  451. package/src/core/sources/payload.ts +38 -15
  452. package/src/core/sources/read.ts +8 -3
  453. package/src/core/sources/remote.ts +72 -15
  454. package/src/core/sources/resolve.ts +11 -1
  455. package/src/core/sources/sanity.ts +43 -25
  456. package/src/core/sources/strapi.ts +2 -2
  457. package/src/core/types.ts +19 -1
  458. package/src/core/ui-packs/ar.ts +44 -0
  459. package/src/core/ui-packs/bg.ts +46 -0
  460. package/src/core/ui-packs/bn.ts +44 -0
  461. package/src/core/ui-packs/ca.ts +47 -0
  462. package/src/core/ui-packs/cs.ts +45 -0
  463. package/src/core/ui-packs/da.ts +46 -0
  464. package/src/core/ui-packs/de.ts +47 -0
  465. package/src/core/ui-packs/el.ts +46 -0
  466. package/src/core/ui-packs/es.ts +47 -0
  467. package/src/core/ui-packs/fa.ts +46 -0
  468. package/src/core/ui-packs/fi.ts +46 -0
  469. package/src/core/ui-packs/fr.ts +47 -0
  470. package/src/core/ui-packs/he.ts +44 -0
  471. package/src/core/ui-packs/hi.ts +45 -0
  472. package/src/core/ui-packs/hr.ts +46 -0
  473. package/src/core/ui-packs/hu.ts +45 -0
  474. package/src/core/ui-packs/id.ts +46 -0
  475. package/src/core/ui-packs/it.ts +46 -0
  476. package/src/core/ui-packs/ja.ts +46 -0
  477. package/src/core/ui-packs/ko.ts +45 -0
  478. package/src/core/ui-packs/nl.ts +47 -0
  479. package/src/core/ui-packs/no.ts +45 -0
  480. package/src/core/ui-packs/pl.ts +46 -0
  481. package/src/core/ui-packs/pt-br.ts +47 -0
  482. package/src/core/ui-packs/pt.ts +46 -0
  483. package/src/core/ui-packs/ro.ts +46 -0
  484. package/src/core/ui-packs/ru.ts +46 -0
  485. package/src/core/ui-packs/sk.ts +45 -0
  486. package/src/core/ui-packs/sr.ts +46 -0
  487. package/src/core/ui-packs/sv.ts +45 -0
  488. package/src/core/ui-packs/th.ts +44 -0
  489. package/src/core/ui-packs/tr.ts +46 -0
  490. package/src/core/ui-packs/uk.ts +46 -0
  491. package/src/core/ui-packs/vi.ts +46 -0
  492. package/src/core/ui-packs/zh-tw.ts +44 -0
  493. package/src/core/ui-packs/zh.ts +44 -0
  494. package/src/core/variables.ts +103 -0
  495. package/src/deploy/adapter-output.ts +7 -2
  496. package/src/deploy/adapters/cloudflare.ts +7 -5
  497. package/src/deploy/adapters/node.ts +47 -9
  498. package/src/deploy/adapters/types.ts +7 -3
  499. package/src/deploy/artifacts.ts +79 -9
  500. package/src/deploy/cloudflare-negotiation.ts +35 -5
  501. package/src/deploy/headers.ts +2 -1
  502. package/src/deploy/node-headers.ts +63 -9
  503. package/src/deploy/platforms/cloudflare.ts +45 -9
  504. package/src/deploy/platforms/netlify.ts +35 -2
  505. package/src/deploy/platforms/node.ts +12 -2
  506. package/src/deploy/platforms/types.ts +21 -7
  507. package/src/deploy/platforms/vercel.ts +149 -17
  508. package/src/deploy/redirects.ts +151 -24
  509. package/src/deploy/rss.ts +3 -1
  510. package/src/deploy/sitemap.ts +39 -5
  511. package/src/deploy/vercel-negotiation.ts +326 -102
  512. package/src/eval/agents.ts +18 -1
  513. package/src/eval/prompts.ts +6 -3
  514. package/src/eval/report.ts +34 -13
  515. package/src/eval/run.ts +5 -0
  516. package/src/markdown/api-rail.ts +259 -0
  517. package/src/markdown/code-title.ts +35 -9
  518. package/src/markdown/features.ts +3 -2
  519. package/src/markdown/fence-meta.ts +2 -0
  520. package/src/markdown/include.ts +11 -1
  521. package/src/markdown/index.ts +28 -5
  522. package/src/markdown/math.ts +4 -4
  523. package/src/markdown/relative-links.ts +3 -2
  524. package/src/markdown/variables.ts +56 -0
  525. package/src/markdown/views.ts +82 -0
  526. package/src/narration/build.ts +412 -0
  527. package/src/narration/player.ts +249 -0
  528. package/src/narration/provider.ts +29 -0
  529. package/src/narration/script.ts +592 -0
  530. package/src/og/card.ts +7 -6
  531. package/src/openapi/checks.ts +273 -0
  532. package/src/openapi/graphql-build.ts +21 -0
  533. package/src/openapi/graphql.ts +11 -0
  534. package/src/openapi/model.ts +72 -27
  535. package/src/openapi/overlay.ts +256 -0
  536. package/src/openapi/parse.ts +182 -4
  537. package/src/openapi/references.ts +64 -8
  538. package/src/openapi/render-mdx.ts +5 -1
  539. package/src/openapi/scalar.ts +40 -6
  540. package/src/openapi/source.ts +40 -15
  541. package/src/ratelimit/cloudflare.ts +54 -0
  542. package/src/ratelimit/index.ts +30 -0
  543. package/src/ratelimit/memory.ts +45 -0
  544. package/src/ratelimit/runtime.ts +247 -0
  545. package/src/ratelimit/schema.ts +28 -0
  546. package/src/ratelimit/upstash.ts +60 -0
  547. package/src/ratelimit/wrangler.ts +70 -0
  548. package/src/reference/asyncapi.ts +2 -2
  549. package/src/reference/graphql.ts +20 -3
  550. package/src/reference/index.ts +1 -0
  551. package/src/reference/openapi.ts +21 -7
  552. package/src/reference/options.ts +80 -8
  553. package/src/reference/scalar.ts +33 -8
  554. package/src/registry/eject.ts +23 -5
  555. package/src/registry/registry.ts +7 -0
  556. package/src/search/adapters/locale-scope.ts +30 -0
  557. package/src/search/adapters/typesense.ts +14 -4
  558. package/src/search/build.ts +21 -3
  559. package/src/search/documents.ts +26 -2
  560. package/src/search/orama-index.ts +191 -34
  561. package/src/search/pagefind-ranking.ts +39 -0
  562. package/src/search/source-pages.ts +29 -0
  563. package/src/search/sync/algolia.ts +111 -10
  564. package/src/search/sync/index.ts +52 -13
  565. package/src/search/sync/orama-cloud.ts +3 -0
  566. package/src/search/sync/typesense.ts +76 -26
  567. package/src/seo/metatags.ts +67 -0
  568. package/src/sources/contentful.ts +12 -0
  569. package/src/sources/github-releases.ts +7 -1
  570. package/src/sources/shared.ts +3 -0
  571. package/src/theme/chrome-icons.ts +1 -0
  572. package/src/theme/color.ts +500 -0
  573. package/src/theme/entry.ts +85 -6
  574. package/src/theme/palette.ts +121 -45
  575. package/src/translate/prompts.ts +1 -0
  576. package/src/translate/validate.ts +31 -3
  577. package/src/upgrade/upgrade.ts +4 -171
  578. package/dist/cli/chunk-1d7ve1dm.js.map +0 -12
  579. package/dist/cli/chunk-2hsdwb9n.js.map +0 -10
  580. package/dist/cli/chunk-35d4wj9f.js.map +0 -15
  581. package/dist/cli/chunk-364znk6q.js +0 -75
  582. package/dist/cli/chunk-364znk6q.js.map +0 -11
  583. package/dist/cli/chunk-5m5nmvyq.js.map +0 -13
  584. package/dist/cli/chunk-8ktnccpt.js.map +0 -10
  585. package/dist/cli/chunk-9t7a85s3.js.map +0 -10
  586. package/dist/cli/chunk-b07cmahc.js +0 -145
  587. package/dist/cli/chunk-b07cmahc.js.map +0 -11
  588. package/dist/cli/chunk-c8chx29p.js.map +0 -36
  589. package/dist/cli/chunk-e04dxsz1.js +0 -39
  590. package/dist/cli/chunk-e04dxsz1.js.map +0 -10
  591. package/dist/cli/chunk-j85vccga.js.map +0 -36
  592. package/dist/cli/chunk-p3v96n38.js.map +0 -10
  593. package/dist/cli/chunk-pehfxfta.js.map +0 -10
  594. package/dist/cli/chunk-pv29h0wf.js.map +0 -190
  595. package/dist/cli/chunk-q58y5e6a.js.map +0 -10
  596. package/dist/cli/chunk-vg9r4eb9.js.map +0 -14
  597. package/dist/cli/chunk-wrr3j9w9.js.map +0 -35
  598. package/dist/cli/chunk-yfyb25rh.js.map +0 -14
  599. package/docs/content/sources.mdx +0 -334
  600. /package/dist/cli/{chunk-tkacnehg.js.map → chunk-3v3ffbrj.js.map} +0 -0
  601. /package/dist/cli/{chunk-r9rcc4w7.js.map → chunk-8y2kmjv8.js.map} +0 -0
  602. /package/dist/cli/{chunk-2eytanqx.js.map → chunk-c887fj0s.js.map} +0 -0
  603. /package/dist/cli/{chunk-akbpwfxc.js.map → chunk-dzwehpy7.js.map} +0 -0
  604. /package/dist/cli/{chunk-2z928egk.js.map → chunk-ft9vfys6.js.map} +0 -0
  605. /package/dist/cli/{chunk-a58773jm.js.map → chunk-kma9f6sf.js.map} +0 -0
  606. /package/dist/cli/{chunk-crgn1q09.js.map → chunk-sds923fa.js.map} +0 -0
  607. /package/dist/cli/{chunk-acanzt5p.js.map → chunk-tdqhyxfz.js.map} +0 -0
@@ -0,0 +1,168 @@
1
+ ---
2
+ import type { PageView } from "../../markdown/views.ts";
3
+ import Icon from "../Icon.astro";
4
+ import { VIEW_INIT_SCRIPT, viewStyle } from "./view-switcher.ts";
5
+
6
+ /**
7
+ * The picker for a page written in `<View>` blocks, rendered above the
8
+ * content with the page's views (collected by `markdown/views.ts`). The
9
+ * style hides every other view's blocks and table of contents entries, and
10
+ * the inline script applies a linked or remembered choice before the views
11
+ * paint (see `view-switcher.ts`).
12
+ */
13
+ interface Props {
14
+ /** The select's accessible name (`content.selectView`). */
15
+ label: string;
16
+ views: PageView[];
17
+ }
18
+
19
+ const { label, views } = Astro.props;
20
+ const titles = views.map((view) => view.title);
21
+ ---
22
+
23
+ <blume-view-switcher
24
+ class="not-prose mt-4 mb-8 flex items-center gap-2"
25
+ data-views={JSON.stringify(titles)}
26
+ >
27
+ <style is:inline set:html={viewStyle(titles)} />
28
+ {
29
+ views.map(
30
+ (view) =>
31
+ view.icon && (
32
+ <span
33
+ class="inline-flex shrink-0 text-muted-foreground"
34
+ data-blume-view={view.title}
35
+ >
36
+ <Icon name={view.icon} size={16} />
37
+ </span>
38
+ )
39
+ )
40
+ }
41
+ <select
42
+ aria-label={label}
43
+ class="cursor-pointer rounded-blume border border-border bg-background px-3 py-1.5 font-medium text-foreground text-sm"
44
+ >
45
+ {views.map((view) => <option value={view.title}>{view.title}</option>)}
46
+ </select>
47
+ <script is:inline set:html={VIEW_INIT_SCRIPT} />
48
+ </blume-view-switcher>
49
+
50
+ <script>
51
+ import {
52
+ chooseView,
53
+ VIEW_PARAM,
54
+ VIEW_STORAGE_KEY,
55
+ } from "./view-switcher.ts";
56
+
57
+ const HEADINGS = "h2[id], h3[id], h4[id], h5[id], h6[id]";
58
+
59
+ const stored = (): string | null => {
60
+ try {
61
+ return localStorage.getItem(VIEW_STORAGE_KEY);
62
+ } catch {
63
+ return null;
64
+ }
65
+ };
66
+
67
+ /** The view holding the element a `#hash` link points at, if any. */
68
+ const linkedView = (): string | undefined => {
69
+ const id = decodeURIComponent(location.hash.slice(1));
70
+ const target = id ? document.getElementById(id) : null;
71
+ return (
72
+ target?.closest<HTMLElement>("article [data-blume-view]")?.dataset
73
+ .blumeView ?? undefined
74
+ );
75
+ };
76
+
77
+ /**
78
+ * Tag each table of contents entry with the view its heading is in, so the
79
+ * page's view style hides it with the view.
80
+ */
81
+ const tagTableOfContents = () => {
82
+ const views = new Map<string, string>();
83
+ for (const view of document.querySelectorAll<HTMLElement>(
84
+ "article [data-blume-view]"
85
+ )) {
86
+ for (const heading of view.querySelectorAll(HEADINGS)) {
87
+ views.set(heading.id, view.dataset.blumeView ?? "");
88
+ }
89
+ }
90
+ for (const link of document.querySelectorAll<HTMLAnchorElement>(
91
+ 'blume-toc a[href^="#"]'
92
+ )) {
93
+ const id = decodeURIComponent(link.getAttribute("href")?.slice(1) ?? "");
94
+ const item = link.closest("li");
95
+ const title = views.get(id);
96
+ if (item && title) {
97
+ item.dataset.blumeView = title;
98
+ }
99
+ }
100
+ };
101
+
102
+ class BlumeViewSwitcher extends HTMLElement {
103
+ #titles: string[] = [];
104
+
105
+ connectedCallback() {
106
+ try {
107
+ this.#titles = JSON.parse(this.dataset.views ?? "[]");
108
+ } catch {
109
+ this.#titles = [];
110
+ }
111
+ tagTableOfContents();
112
+ this.#show(
113
+ chooseView(this.#titles, [
114
+ linkedView(),
115
+ new URL(location.href).searchParams.get(VIEW_PARAM),
116
+ stored(),
117
+ ])
118
+ );
119
+ this.querySelector("select")?.addEventListener("change", this.#onPick);
120
+ window.addEventListener("hashchange", this.#onHash);
121
+ }
122
+
123
+ disconnectedCallback() {
124
+ this.querySelector("select")?.removeEventListener("change", this.#onPick);
125
+ window.removeEventListener("hashchange", this.#onHash);
126
+ }
127
+
128
+ #show(title: string | undefined) {
129
+ if (title === undefined) {
130
+ return;
131
+ }
132
+ document.body.dataset.blumeView = title;
133
+ const select = this.querySelector("select");
134
+ if (select) {
135
+ select.value = title;
136
+ }
137
+ }
138
+
139
+ #onPick = (event: Event) => {
140
+ // SAFETY: the listener is only added to this picker's <select>.
141
+ const { value } = event.currentTarget as HTMLSelectElement;
142
+ this.#show(value);
143
+ try {
144
+ localStorage.setItem(VIEW_STORAGE_KEY, value);
145
+ } catch {
146
+ // Storage can be off; the choice still holds for this page.
147
+ }
148
+ // replaceState: the link stays shareable without a history entry per
149
+ // pick, and the client router needs the entry's state kept.
150
+ const url = new URL(location.href);
151
+ url.searchParams.set(VIEW_PARAM, value);
152
+ history.replaceState(history.state, "", url);
153
+ };
154
+
155
+ // An in-page link to a heading in another view switches to that view.
156
+ #onHash = () => {
157
+ const view = linkedView();
158
+ if (view && view !== document.body.dataset.blumeView) {
159
+ this.#show(view);
160
+ document.getElementById(decodeURIComponent(location.hash.slice(1)))?.scrollIntoView();
161
+ }
162
+ };
163
+ }
164
+
165
+ if (!customElements.get("blume-view-switcher")) {
166
+ customElements.define("blume-view-switcher", BlumeViewSwitcher);
167
+ }
168
+ </script>
@@ -0,0 +1,103 @@
1
+ /**
2
+ * The props `<ParamField>` and `<ResponseField>` take, in Mintlify's shape: a
3
+ * parameter names its location with the attribute that carries its name
4
+ * (`<ParamField query="limit">`), and both take `type`, `required`,
5
+ * `deprecated`, and `default`; a response field adds `pre` and `post` labels
6
+ * around its name. Pure, so the Markdown downlevel and the playground can
7
+ * read fields the way the components render them.
8
+ */
9
+
10
+ /** Where a `<ParamField>` parameter goes, in the order the attributes are checked. */
11
+ export const PARAM_LOCATIONS = ["path", "query", "header", "body"] as const;
12
+
13
+ /** A parameter's location. */
14
+ export type ParamLocation = (typeof PARAM_LOCATIONS)[number];
15
+
16
+ /** A literal value as MDX passes it: a string attribute, or an expression's data. */
17
+ export type FieldValue =
18
+ | string
19
+ | number
20
+ | boolean
21
+ | null
22
+ | undefined
23
+ | FieldValue[]
24
+ | { [key: string]: FieldValue };
25
+
26
+ /** A boolean prop: MDX shorthand (`required`) is `true`, `required="true"` a string. */
27
+ export type FlagProp = boolean | string;
28
+
29
+ /** What both field components take. */
30
+ export interface FieldProps {
31
+ /** The value used when none is given. */
32
+ default?: FieldValue;
33
+ deprecated?: FlagProp;
34
+ required?: FlagProp;
35
+ /** Free text: `string`, `integer`, `string[]`, `object`. */
36
+ type?: string;
37
+ }
38
+
39
+ /** `<ParamField>`: a request parameter, named by its location attribute. */
40
+ export interface ParamFieldProps extends FieldProps {
41
+ body?: string;
42
+ header?: string;
43
+ /** The name, for a field with no location attribute. */
44
+ name?: string;
45
+ path?: string;
46
+ /**
47
+ * An example value: the one the playground and request samples start
48
+ * with, not an input's placeholder hint (see `fieldSchema`).
49
+ */
50
+ placeholder?: string;
51
+ query?: string;
52
+ }
53
+
54
+ /** `<ResponseField>`: a field of the response. */
55
+ export interface ResponseFieldProps extends FieldProps {
56
+ name: string;
57
+ /** Labels after the name. */
58
+ post?: string | string[];
59
+ /** Labels before the name. */
60
+ pre?: string | string[];
61
+ }
62
+
63
+ /** Whether a flag prop is on. */
64
+ export const isOn = (value?: FlagProp): boolean =>
65
+ value === true || value === "true";
66
+
67
+ /** Where a parameter goes, and what it's called. */
68
+ export interface ParamFieldName {
69
+ location?: ParamLocation;
70
+ name?: string;
71
+ }
72
+
73
+ /** A parameter's location and name: the first location attribute set, else `name`. */
74
+ export const paramField = (props: ParamFieldProps): ParamFieldName => {
75
+ for (const location of PARAM_LOCATIONS) {
76
+ const name = props[location];
77
+ if (name !== undefined) {
78
+ return { location, name };
79
+ }
80
+ }
81
+ return { name: props.name };
82
+ };
83
+
84
+ const isText = (value: FieldValue): value is string =>
85
+ typeof value === "string";
86
+
87
+ /** A default value as shown: text as written, anything else as JSON; `null` when there is none. */
88
+ export const defaultLabel = (value?: FieldValue): string | null => {
89
+ if (value === undefined || value === null || value === "") {
90
+ return null;
91
+ }
92
+ return isText(value) ? value : JSON.stringify(value);
93
+ };
94
+
95
+ /** `pre`/`post` labels as a list, whether one was written or several. */
96
+ export const fieldLabels = (value?: string | string[]): string[] => {
97
+ if (value === undefined) {
98
+ return [];
99
+ }
100
+ return (Array.isArray(value) ? value : [value]).filter(
101
+ (label) => label !== ""
102
+ );
103
+ };
@@ -0,0 +1,248 @@
1
+ import { exampleValue } from "../openapi/helpers.ts";
2
+ import type { ParameterLike, SchemaLike } from "../openapi/helpers.ts";
3
+ import { resolveSecurity } from "../openapi/security.ts";
4
+ import type { OperationSecurity } from "../openapi/security.ts";
5
+ import type { FieldValue, ParamLocation } from "./api-field.ts";
6
+
7
+ /**
8
+ * A hand-written API page's endpoint, as its `api` frontmatter and its
9
+ * `<ParamField>`s describe it, turned into the OpenAPI-shaped pieces the
10
+ * operation playground and code samples are built from: a page with
11
+ * `api: "POST /v1/users"` gets the same Try it panel and request samples as
12
+ * a spec'd operation, with no spec. Mintlify's frontmatter, so migrated pages
13
+ * keep it as written.
14
+ */
15
+
16
+ /** How a hand-written endpoint authenticates (`authMethod`, `api.auth.method`). */
17
+ export const AUTH_METHODS = ["bearer", "basic", "key", "none"] as const;
18
+ export type AuthMethod = (typeof AUTH_METHODS)[number];
19
+
20
+ /** What a page's playground shows: all of it, the samples only, or none. */
21
+ export const PLAYGROUND_MODES = ["interactive", "simple", "none"] as const;
22
+ export type PlaygroundMode = (typeof PLAYGROUND_MODES)[number];
23
+
24
+ /** `api` frontmatter: an HTTP method, then a path or a full URL. */
25
+ export const API_ENDPOINT =
26
+ /^(?<method>GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS|TRACE)\s+(?<target>\S+)$/iu;
27
+
28
+ /** The site's default auth for hand-written endpoints (`api.auth`). */
29
+ export interface EndpointAuth {
30
+ method: AuthMethod;
31
+ /** The header an API key goes in. */
32
+ name?: string;
33
+ }
34
+
35
+ /** One `<ParamField>`, as the page's plugin collected it. */
36
+ export interface EndpointField {
37
+ default?: FieldValue;
38
+ deprecated?: boolean;
39
+ /** Body fields nested in this one's `<Expandable>`. */
40
+ fields?: EndpointField[];
41
+ location: ParamLocation;
42
+ name: string;
43
+ placeholder?: string;
44
+ required?: boolean;
45
+ type?: string;
46
+ }
47
+
48
+ /** What the page's plugin hands the endpoint components. */
49
+ export interface EndpointSpec {
50
+ authMethod?: AuthMethod;
51
+ fields: EndpointField[];
52
+ method: string;
53
+ playground?: PlaygroundMode;
54
+ /** The page has a `<RequestExample>`, which stands in for generated samples. */
55
+ requestExample: boolean;
56
+ /** The `api` target as written: a path, or a full URL. */
57
+ target: string;
58
+ }
59
+
60
+ /** The method and target of an `api` value, or `null` when it isn't one. */
61
+ export const parseApiEndpoint = (
62
+ value: string
63
+ ): { method: string; target: string } | null => {
64
+ const groups = API_ENDPOINT.exec(value.trim())?.groups;
65
+ return groups?.method && groups.target
66
+ ? { method: groups.method.toUpperCase(), target: groups.target }
67
+ : null;
68
+ };
69
+
70
+ const ABSOLUTE_URL = /^(?<origin>https?:\/\/[^/?#]+)(?<rest>.*)$/iu;
71
+
72
+ /** An endpoint's target, split the way the operation model takes it. */
73
+ export interface EndpointTarget {
74
+ path: string;
75
+ servers: { url: string }[];
76
+ }
77
+
78
+ /**
79
+ * The target split into a server and a path: a full URL is its own server,
80
+ * and a path joins the site's `api.server`, or stays relative to the docs
81
+ * when there is none.
82
+ */
83
+ export const endpointTarget = (
84
+ target: string,
85
+ server?: string
86
+ ): EndpointTarget => {
87
+ const absolute = ABSOLUTE_URL.exec(target)?.groups;
88
+ if (absolute?.origin) {
89
+ return {
90
+ path: absolute.rest || "/",
91
+ servers: [{ url: absolute.origin }],
92
+ };
93
+ }
94
+ return {
95
+ path: target.startsWith("/") ? target : `/${target}`,
96
+ servers: server ? [{ url: server.replace(/\/+$/u, "") }] : [],
97
+ };
98
+ };
99
+
100
+ const PRIMITIVES = new Set([
101
+ "string",
102
+ "number",
103
+ "integer",
104
+ "boolean",
105
+ "object",
106
+ ]);
107
+
108
+ /**
109
+ * A field's JSON schema from its `type`: `string[]` an array of strings, a
110
+ * field with nested fields an object with those properties, and anything
111
+ * that isn't a JSON type (`enum<string>`, `Date`) a string, which is what it
112
+ * goes over the wire as. A default and placeholder carry over, the
113
+ * placeholder as the example the samples show.
114
+ */
115
+ export const fieldSchema = (field: EndpointField): SchemaLike => {
116
+ const type = field.type?.trim().toLowerCase() ?? "";
117
+ if (type.endsWith("[]")) {
118
+ return {
119
+ items: fieldSchema({
120
+ ...field,
121
+ default: undefined,
122
+ type: type.slice(0, -2),
123
+ }),
124
+ type: "array",
125
+ };
126
+ }
127
+ const nested = field.fields ?? [];
128
+ const schema: SchemaLike =
129
+ nested.length > 0
130
+ ? {
131
+ properties: Object.fromEntries(
132
+ nested.map((child) => [child.name, fieldSchema(child)])
133
+ ),
134
+ type: "object",
135
+ }
136
+ : { type: PRIMITIVES.has(type) ? type : "string" };
137
+ const required = nested
138
+ .filter((child) => child.required)
139
+ .map((child) => child.name);
140
+ if (required.length > 0) {
141
+ schema.required = required;
142
+ }
143
+ if (field.default !== undefined) {
144
+ schema.default = field.default;
145
+ }
146
+ if (field.placeholder) {
147
+ schema.example = field.placeholder;
148
+ }
149
+ if (field.deprecated) {
150
+ schema.deprecated = true;
151
+ }
152
+ return schema;
153
+ };
154
+
155
+ /** The path, query, and header fields as OpenAPI parameters. */
156
+ export const endpointParameters = (fields: EndpointField[]): ParameterLike[] =>
157
+ fields.flatMap((field) =>
158
+ field.location === "body"
159
+ ? []
160
+ : [
161
+ {
162
+ deprecated: field.deprecated === true,
163
+ in: field.location,
164
+ name: field.name,
165
+ // A path parameter is always required.
166
+ required: field.location === "path" || field.required === true,
167
+ schema: fieldSchema(field),
168
+ },
169
+ ]
170
+ );
171
+
172
+ /** Whether a field, or one nested in it, has a `default` or `placeholder`. */
173
+ const hasValue = (field: EndpointField): boolean =>
174
+ field.default !== undefined ||
175
+ Boolean(field.placeholder) ||
176
+ (field.fields ?? []).some(hasValue);
177
+
178
+ /**
179
+ * The fields a request starts with: required ones, and ones with a value to
180
+ * send. An optional field with neither is left for the reader to fill,
181
+ * rather than sent as the sampler's `"string"`, `0`, or `true`.
182
+ */
183
+ const sentFields = (fields: EndpointField[]): EndpointField[] =>
184
+ fields
185
+ .filter((field) => field.required === true || hasValue(field))
186
+ .map((field) => ({ ...field, fields: sentFields(field.fields ?? []) }));
187
+
188
+ /**
189
+ * The body fields as a JSON request body, or `undefined` when there are none.
190
+ * Its example, which the playground and samples start from, holds only the
191
+ * {@link sentFields}.
192
+ */
193
+ export const endpointBody = (fields: EndpointField[]) => {
194
+ const body = fields.filter((field) => field.location === "body");
195
+ const object = (members: EndpointField[]): SchemaLike =>
196
+ fieldSchema({
197
+ fields: members,
198
+ location: "body",
199
+ name: "",
200
+ type: "object",
201
+ });
202
+ return body.length > 0
203
+ ? {
204
+ content: {
205
+ "application/json": {
206
+ example: exampleValue(object(sentFields(body)), {}),
207
+ schema: object(body),
208
+ },
209
+ },
210
+ }
211
+ : undefined;
212
+ };
213
+
214
+ /**
215
+ * The security an endpoint enforces: its page's `authMethod`, else the
216
+ * site's `api.auth`, else none. An API key goes in the configured header,
217
+ * `x-api-key` when none is named.
218
+ */
219
+ export const endpointSecurity = (
220
+ authMethod?: AuthMethod,
221
+ siteAuth?: EndpointAuth
222
+ ): OperationSecurity => {
223
+ const method = authMethod ?? siteAuth?.method ?? "none";
224
+ if (method === "none") {
225
+ return { alternatives: [], optional: false };
226
+ }
227
+ if (method === "key") {
228
+ return resolveSecurity([{ apiKey: [] }], {
229
+ apiKey: {
230
+ in: "header",
231
+ name: siteAuth?.name ?? "x-api-key",
232
+ type: "apiKey",
233
+ },
234
+ });
235
+ }
236
+ return resolveSecurity([{ [method]: [] }], {
237
+ [method]: { scheme: method, type: "http" },
238
+ });
239
+ };
240
+
241
+ /**
242
+ * The endpoint spec the page's plugin wrote into the `spec` attribute of
243
+ * `<ApiEndpoint>` and `<ApiPlayground>`.
244
+ */
245
+ export const readEndpointSpec = (json: string): EndpointSpec =>
246
+ // SAFETY: the attribute is `JSON.stringify` of an `EndpointSpec`, written
247
+ // by `markdown/api-rail.ts` at build; authors never write it.
248
+ JSON.parse(json) as EndpointSpec;
@@ -55,6 +55,9 @@ export class BlumeMermaid extends HTMLElement {
55
55
  look: "classic",
56
56
  securityLevel: "strict",
57
57
  startOnLoad: false,
58
+ // Without this, a diagram that fails to parse leaves Mermaid's own
59
+ // "Syntax error in text" graphic appended to <body>, below the page.
60
+ suppressErrorRendering: true,
58
61
  theme: prefersDark() ? "dark" : "default",
59
62
  });
60
63
  try {
@@ -71,13 +74,24 @@ export class BlumeMermaid extends HTMLElement {
71
74
  // oxlint-disable-next-line github/no-inner-html -- Mermaid-generated SVG must be injected as HTML
72
75
  output.innerHTML = svg;
73
76
  }
74
- } catch {
77
+ } catch (error) {
75
78
  // Localized message stamped on <body> by RootLayout's markup (the
76
79
  // data-attribute channel); English fallback when the attribute is
77
80
  // missing (a stale snapshot or a custom layout).
78
81
  output.textContent =
79
82
  document.body.dataset.i18nDiagramError ||
80
83
  "Could not render this diagram.";
84
+ // Readers get only the message above; the writer needs Mermaid's
85
+ // parser error (line and expected token) to fix the source. It goes
86
+ // to the console, and `blume dev` also shows it under the message.
87
+ console.error("[blume] Mermaid could not render a diagram:", error);
88
+ if (import.meta.env.DEV) {
89
+ const detail = document.createElement("pre");
90
+ detail.className =
91
+ "mt-2 overflow-x-auto text-muted-foreground text-xs";
92
+ detail.textContent = String(error);
93
+ output.append(detail);
94
+ }
81
95
  }
82
96
  output.removeAttribute("aria-busy");
83
97
  };
@@ -0,0 +1,71 @@
1
+ /**
2
+ * The page view picker's logic (see `ViewSwitcher.astro`). A page written in
3
+ * `<View title>` blocks shows one view at a time. The choice sits on
4
+ * `<body data-blume-view>`, which each page brings fresh, and a per-page style
5
+ * hides everything tagged with another view: the `<View>` blocks, the
6
+ * picker's icons, and the table of contents entries for their headings.
7
+ */
8
+
9
+ /**
10
+ * Where a reader's last-picked view is remembered, across pages. The init
11
+ * script below spells it out, as it does {@link VIEW_PARAM}.
12
+ */
13
+ export const VIEW_STORAGE_KEY = "blume-view";
14
+
15
+ /** The query parameter a shared link picks a view with (`?view=Python`). */
16
+ export const VIEW_PARAM = "view";
17
+
18
+ /**
19
+ * The view to show: the first of the candidates the page has, most specific
20
+ * first (a linked heading's view, the link's `?view=`, the reader's last
21
+ * pick), else the page's first view.
22
+ */
23
+ export const chooseView = (
24
+ titles: readonly string[],
25
+ candidates: readonly (string | null | undefined)[]
26
+ ): string | undefined =>
27
+ candidates.find(
28
+ (candidate): candidate is string =>
29
+ candidate !== null &&
30
+ candidate !== undefined &&
31
+ titles.includes(candidate)
32
+ ) ?? titles[0];
33
+
34
+ /**
35
+ * A CSS string for `value`, safe inside a `<style>` element: quotes and
36
+ * backslashes escaped, `<` as a hex escape so the text can't close the
37
+ * element, and line breaks (which a CSS string can't hold) as spaces.
38
+ */
39
+ const cssString = (value: string): string =>
40
+ `"${value
41
+ .replaceAll(/["\\]/gu, String.raw`\$&`)
42
+ .replaceAll("<", String.raw`\3c `)
43
+ .replaceAll(/[\n\r\f]/gu, " ")}"`;
44
+
45
+ /**
46
+ * The page's view CSS: with a view chosen on `<body>`, everything tagged with
47
+ * another is hidden; before a choice, everything but the first view is.
48
+ */
49
+ export const viewStyle = (titles: readonly string[]): string => {
50
+ const [first] = titles;
51
+ if (first === undefined) {
52
+ return "";
53
+ }
54
+ const other = (title: string): string =>
55
+ `[data-blume-view]:not([data-blume-view=${cssString(title)}])`;
56
+ const selectors = [
57
+ `body:not([data-blume-view]) ${other(first)}`,
58
+ ...titles.map(
59
+ (title) => `body[data-blume-view=${cssString(title)}] ${other(title)}`
60
+ ),
61
+ ];
62
+ return `${selectors.join(",")}{display:none!important}`;
63
+ };
64
+
65
+ /**
66
+ * Runs inline as the picker is parsed, ahead of the views it controls, so a
67
+ * link's `?view=` or the reader's last pick applies before anything paints.
68
+ * Inline scripts run once per session under the client router; after that
69
+ * the picker element applies the choice as each page swaps in.
70
+ */
71
+ export const VIEW_INIT_SCRIPT = `(()=>{const s=document.currentScript;const p=s&&s.closest("blume-view-switcher");if(!p)return;let t=[];try{t=JSON.parse(p.getAttribute("data-views")||"[]")}catch{}let r=null;try{r=localStorage.getItem("blume-view")}catch{}const l=new URLSearchParams(location.search).get("view");const v=[l,r].find((c)=>c&&t.includes(c))||t[0];if(!v)return;document.body.setAttribute("data-blume-view",v);const e=p.querySelector("select");if(e)e.value=v;})();`;
@@ -25,7 +25,9 @@ export type {
25
25
  FrameProps,
26
26
  IconProps,
27
27
  PanelProps,
28
+ ParamFieldProps,
28
29
  PromptProps,
30
+ ResponseFieldProps,
29
31
  StepProps,
30
32
  StepsProps,
31
33
  TabProps,
@@ -1,4 +1,5 @@
1
1
  ---
2
+ import type { CaptchaSettings } from "../../captcha/schema.ts";
2
3
  import type { UIStrings } from "../../core/i18n-ui.ts";
3
4
  import { resolveIcon } from "../../theme/icons.ts";
4
5
  import Assistant from "./assistant.tsx";
@@ -9,12 +10,17 @@ interface Suggestion {
9
10
  }
10
11
 
11
12
  interface Props {
13
+ /** The bot check's public settings (`ai.assistant.captcha`). */
14
+ captcha?: CaptchaSettings;
12
15
  endpoint?: string;
13
16
  strings?: UIStrings["assistant"];
14
17
  suggestions?: Suggestion[];
18
+ /** The Contact support link (`ai.assistant.support`). */
19
+ support?: string;
15
20
  }
16
21
 
17
- const { endpoint, strings, suggestions = [] } = Astro.props;
22
+ const { captcha, endpoint, strings, suggestions = [], support } =
23
+ Astro.props;
18
24
 
19
25
  // Icons resolve to inline SVG here (server-only module), so the client island
20
26
  // gets ready-to-render markup rather than a name it can't resolve. Bare Lucide
@@ -41,6 +47,7 @@ const icons = {
41
47
  clear: bodyFor("trash-2"),
42
48
  close: bodyFor("chevrons-right"),
43
49
  copy: bodyFor("copy"),
50
+ remove: bodyFor("x"),
44
51
  };
45
52
  ---
46
53
 
@@ -50,11 +57,13 @@ const icons = {
50
57
  panel and re-stamps the body push attribute itself on astro:after-swap
51
58
  (see assistant.tsx), since the swap replaces <body> wholesale. */}
52
59
  <Assistant
60
+ captcha={captcha}
53
61
  client:load
54
62
  endpoint={endpoint}
55
63
  icons={icons}
56
64
  strings={strings}
57
65
  suggestions={items}
66
+ support={support}
58
67
  transition:persist="blume-assistant"
59
68
  />
60
69