blume 2.0.2 → 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 (601) hide show
  1. package/AGENTS.md +1 -0
  2. package/CHANGELOG.md +113 -0
  3. package/README.md +1 -1
  4. package/dist/cli/{chunk-6k4ftwze.js → chunk-0gz36akr.js} +18 -2
  5. package/dist/cli/{chunk-6k4ftwze.js.map → chunk-0gz36akr.js.map} +3 -3
  6. package/dist/cli/{chunk-zp79m0ts.js → chunk-1n228xqb.js} +2 -2
  7. package/dist/cli/{chunk-ddndchfr.js → chunk-2f3ndkpw.js} +57 -29
  8. package/dist/cli/chunk-2f3ndkpw.js.map +14 -0
  9. package/dist/cli/{chunk-fsmrqk8a.js → chunk-2f7n4qzt.js} +8 -2
  10. package/dist/cli/{chunk-fsmrqk8a.js.map → chunk-2f7n4qzt.js.map} +3 -3
  11. package/dist/cli/{chunk-ppzjqwx2.js → chunk-2n4ps1b3.js} +17 -18
  12. package/dist/cli/{chunk-ppzjqwx2.js.map → chunk-2n4ps1b3.js.map} +3 -3
  13. package/dist/cli/{chunk-5r8g91qn.js → chunk-43zcf4gz.js} +398 -159
  14. package/dist/cli/chunk-43zcf4gz.js.map +36 -0
  15. package/dist/cli/chunk-4ejxbzee.js +39 -0
  16. package/dist/cli/chunk-4ejxbzee.js.map +10 -0
  17. package/dist/cli/{chunk-hr8ne106.js → chunk-4h8z9vv5.js} +296 -77
  18. package/dist/cli/chunk-4h8z9vv5.js.map +16 -0
  19. package/dist/cli/{chunk-k7pj68a8.js → chunk-5cg2rzgf.js} +18 -16
  20. package/dist/cli/{chunk-k7pj68a8.js.map → chunk-5cg2rzgf.js.map} +2 -2
  21. package/dist/cli/{chunk-h2ez8dzb.js → chunk-5ffywsmb.js} +4 -4
  22. package/dist/cli/{chunk-g698a744.js → chunk-5wj2qwn2.js} +5 -5
  23. package/dist/cli/chunk-6bm0xpgd.js +18 -0
  24. package/dist/cli/chunk-6bm0xpgd.js.map +10 -0
  25. package/dist/cli/{chunk-3yce002v.js → chunk-713mngdq.js} +15 -8
  26. package/dist/cli/chunk-713mngdq.js.map +14 -0
  27. package/dist/cli/{chunk-91ws1n6j.js → chunk-9geymqns.js} +17 -15
  28. package/dist/cli/{chunk-91ws1n6j.js.map → chunk-9geymqns.js.map} +2 -2
  29. package/dist/cli/{chunk-6dtt0zfn.js → chunk-9xr4dgee.js} +27 -18
  30. package/dist/cli/chunk-9xr4dgee.js.map +10 -0
  31. package/dist/cli/{chunk-sqw4ekg1.js → chunk-amrb6hgh.js} +2 -2
  32. package/dist/cli/chunk-cm89scdv.js +443 -0
  33. package/dist/cli/chunk-cm89scdv.js.map +11 -0
  34. package/dist/cli/{chunk-wdrt2k2v.js → chunk-cmtcnh9f.js} +90 -26
  35. package/dist/cli/chunk-cmtcnh9f.js.map +10 -0
  36. package/dist/cli/chunk-cy5bm0j0.js +104 -0
  37. package/dist/cli/chunk-cy5bm0j0.js.map +11 -0
  38. package/dist/cli/{chunk-7mbqtmgb.js → chunk-e7vvk5ya.js} +21 -12
  39. package/dist/cli/chunk-e7vvk5ya.js.map +10 -0
  40. package/dist/cli/{chunk-qkb5a8sa.js → chunk-g2z9x01v.js} +6 -98
  41. package/dist/cli/chunk-g2z9x01v.js.map +10 -0
  42. package/dist/cli/{chunk-273ygyr4.js → chunk-ga0pf4aj.js} +7 -7
  43. package/dist/cli/{chunk-273ygyr4.js.map → chunk-ga0pf4aj.js.map} +3 -3
  44. package/dist/cli/{chunk-h7k3nq3v.js → chunk-gp84za0h.js} +2 -2
  45. package/dist/cli/{chunk-hqp2ajnh.js → chunk-h2a48yhd.js} +195 -73
  46. package/dist/cli/chunk-h2a48yhd.js.map +36 -0
  47. package/dist/cli/{chunk-pbg5a4s3.js → chunk-jnwj5kjj.js} +71 -47
  48. package/dist/cli/chunk-jnwj5kjj.js.map +19 -0
  49. package/dist/cli/chunk-kwrg63tm.js +31 -0
  50. package/dist/cli/chunk-kwrg63tm.js.map +10 -0
  51. package/dist/cli/{chunk-8g8ytmgx.js → chunk-nd1821sk.js} +21 -19
  52. package/dist/cli/{chunk-8g8ytmgx.js.map → chunk-nd1821sk.js.map} +2 -2
  53. package/dist/cli/{chunk-w4bxdvsa.js → chunk-ntv4qrt7.js} +17 -15
  54. package/dist/cli/{chunk-w4bxdvsa.js.map → chunk-ntv4qrt7.js.map} +2 -2
  55. package/dist/cli/{chunk-bfwp9vp6.js → chunk-p804f3pe.js} +7 -7
  56. package/dist/cli/{chunk-4e9b9ra6.js → chunk-py62fewh.js} +6 -6
  57. package/dist/cli/{chunk-4e9b9ra6.js.map → chunk-py62fewh.js.map} +1 -1
  58. package/dist/cli/chunk-q3wxxq39.js +126 -0
  59. package/dist/cli/chunk-q3wxxq39.js.map +11 -0
  60. package/dist/cli/{chunk-j85scx15.js → chunk-rekqz4qg.js} +142 -46
  61. package/dist/cli/chunk-rekqz4qg.js.map +10 -0
  62. package/dist/cli/{chunk-00gs3wqs.js → chunk-ta27feev.js} +1 -1
  63. package/dist/cli/{chunk-v6ya5kcb.js → chunk-xkz5xbtv.js} +4031 -1132
  64. package/dist/cli/chunk-xkz5xbtv.js.map +213 -0
  65. package/dist/cli/{chunk-bbnwccaz.js → chunk-y4ykbark.js} +2 -2
  66. package/dist/cli/{chunk-n1yg3tj3.js → chunk-y5h4r2y0.js} +6 -6
  67. package/dist/cli/{chunk-n1yg3tj3.js.map → chunk-y5h4r2y0.js.map} +3 -3
  68. package/dist/cli/{chunk-nfcyttvj.js → chunk-yj17vs39.js} +9 -9
  69. package/dist/cli/{chunk-nfcyttvj.js.map → chunk-yj17vs39.js.map} +1 -1
  70. package/dist/cli/{chunk-7vtckvaw.js → chunk-yxmk4pec.js} +16 -14
  71. package/dist/cli/{chunk-7vtckvaw.js.map → chunk-yxmk4pec.js.map} +2 -2
  72. package/dist/cli/{chunk-gs7r695n.js → chunk-zccbjcj0.js} +22 -8
  73. package/dist/cli/{chunk-gs7r695n.js.map → chunk-zccbjcj0.js.map} +3 -3
  74. package/dist/cli/{chunk-xh43dwgw.js → chunk-zf748avv.js} +415 -225
  75. package/dist/cli/chunk-zf748avv.js.map +37 -0
  76. package/dist/cli/{chunk-d1v5rhy0.js → chunk-zhvd6adm.js} +16 -14
  77. package/dist/cli/{chunk-d1v5rhy0.js.map → chunk-zhvd6adm.js.map} +2 -2
  78. package/dist/cli/index.js +28 -20
  79. package/dist/cli/index.js.map +5 -5
  80. package/dist/types/ai/agent-surface.d.ts +8 -7
  81. package/dist/types/ai/ai-catalog.d.ts +7 -0
  82. package/dist/types/ai/ask-context.d.ts +22 -0
  83. package/dist/types/ai/ask.d.ts +271 -58
  84. package/dist/types/ai/index.d.ts +2 -2
  85. package/dist/types/ai/link-headers.d.ts +8 -1
  86. package/dist/types/ai/openapi-components.d.ts +5 -2
  87. package/dist/types/ai/relative-links.d.ts +9 -7
  88. package/dist/types/ai/site-skill.d.ts +26 -0
  89. package/dist/types/ai/skills.d.ts +20 -1
  90. package/dist/types/ai/tar.d.ts +1 -3
  91. package/dist/types/analytics/index.d.ts +2 -0
  92. package/dist/types/analytics/one-dollar-stats.d.ts +48 -0
  93. package/dist/types/analytics/schema.d.ts +14 -0
  94. package/dist/types/astro/integration.d.ts +11 -2
  95. package/dist/types/captcha/hcaptcha.d.ts +27 -0
  96. package/dist/types/captcha/index.d.ts +28 -0
  97. package/dist/types/captcha/schema.d.ts +29 -0
  98. package/dist/types/captcha/turnstile.d.ts +28 -0
  99. package/dist/types/components/content/api-field.d.ts +59 -0
  100. package/dist/types/components/content/api-page.d.ts +95 -0
  101. package/dist/types/components/layout/nav-utils.d.ts +26 -0
  102. package/dist/types/components/openapi/helpers.d.ts +137 -0
  103. package/dist/types/components/openapi/security.d.ts +85 -0
  104. package/dist/types/consent/ethyca.d.ts +48 -0
  105. package/dist/types/consent/index.d.ts +37 -0
  106. package/dist/types/consent/native.d.ts +28 -0
  107. package/dist/types/consent/osano.d.ts +42 -0
  108. package/dist/types/consent/schema.d.ts +110 -0
  109. package/dist/types/core/base-path.d.ts +21 -7
  110. package/dist/types/core/config-input.d.ts +196 -27
  111. package/dist/types/core/data.d.ts +49 -4
  112. package/dist/types/core/directive-diagnostics.d.ts +12 -0
  113. package/dist/types/core/footer.d.ts +8 -0
  114. package/dist/types/core/heading-markers.d.ts +5 -7
  115. package/dist/types/core/i18n-ui.d.ts +86 -0
  116. package/dist/types/core/i18n.d.ts +2 -0
  117. package/dist/types/core/includes.d.ts +8 -2
  118. package/dist/types/core/last-modified.d.ts +10 -0
  119. package/dist/types/core/localizable.d.ts +7 -0
  120. package/dist/types/core/meta.d.ts +8 -0
  121. package/dist/types/core/page-modes.d.ts +29 -0
  122. package/dist/types/core/redirect-patterns.d.ts +144 -0
  123. package/dist/types/core/related.d.ts +40 -0
  124. package/dist/types/core/schema.d.ts +558 -56
  125. package/dist/types/core/sources/lower.d.ts +29 -16
  126. package/dist/types/core/sources/normalize.d.ts +13 -1
  127. package/dist/types/core/sources/read.d.ts +5 -0
  128. package/dist/types/core/sources/watch.d.ts +12 -5
  129. package/dist/types/core/standard-schema.d.ts +5 -0
  130. package/dist/types/core/types.d.ts +1 -1
  131. package/dist/types/core/variables.d.ts +42 -0
  132. package/dist/types/deploy/artifacts.d.ts +6 -4
  133. package/dist/types/deploy/headers.d.ts +5 -0
  134. package/dist/types/deploy/node-headers.d.ts +13 -2
  135. package/dist/types/deploy/platforms/cloudflare.d.ts +5 -0
  136. package/dist/types/deploy/platforms/netlify.d.ts +7 -0
  137. package/dist/types/deploy/platforms/types.d.ts +8 -0
  138. package/dist/types/deploy/platforms/vercel.d.ts +6 -0
  139. package/dist/types/deploy/redirects.d.ts +61 -22
  140. package/dist/types/deploy/vercel-negotiation.d.ts +9 -0
  141. package/dist/types/markdown/code-title.d.ts +17 -0
  142. package/dist/types/markdown/directives.d.ts +62 -0
  143. package/dist/types/markdown/features.d.ts +24 -2
  144. package/dist/types/markdown/mdast.d.ts +63 -0
  145. package/dist/types/narration/build.d.ts +70 -0
  146. package/dist/types/narration/provider.d.ts +26 -0
  147. package/dist/types/narration/script.d.ts +154 -0
  148. package/dist/types/openapi/asyncapi.d.ts +4 -2
  149. package/dist/types/openapi/model.d.ts +12 -6
  150. package/dist/types/openapi/overlay.d.ts +54 -0
  151. package/dist/types/openapi/parse.d.ts +13 -0
  152. package/dist/types/openapi/references.d.ts +14 -4
  153. package/dist/types/ratelimit/cloudflare.d.ts +39 -0
  154. package/dist/types/ratelimit/index.d.ts +27 -0
  155. package/dist/types/ratelimit/memory.d.ts +36 -0
  156. package/dist/types/ratelimit/schema.d.ts +111 -0
  157. package/dist/types/ratelimit/upstash.d.ts +21 -0
  158. package/dist/types/ratelimit/wrangler.d.ts +23 -0
  159. package/dist/types/reference/asyncapi.d.ts +10 -10
  160. package/dist/types/reference/graphql.d.ts +13 -10
  161. package/dist/types/reference/openapi.d.ts +33 -12
  162. package/dist/types/reference/options.d.ts +45 -5
  163. package/dist/types/reference/scalar.d.ts +13 -0
  164. package/dist/types/reference/schema.d.ts +60 -36
  165. package/dist/types/search/documents.d.ts +12 -1
  166. package/dist/types/search/orama-index.d.ts +4 -0
  167. package/dist/types/seo/metatags.d.ts +20 -0
  168. package/docs/02-deployment.mdx +44 -6
  169. package/docs/03-upgrading.mdx +4 -4
  170. package/docs/04-migrating.mdx +1 -1
  171. package/docs/08-faq.mdx +1 -1
  172. package/docs/advanced/changelog.mdx +2 -2
  173. package/docs/advanced/custom-pages.mdx +3 -3
  174. package/docs/advanced/skills.mdx +14 -0
  175. package/docs/cli/audit.mdx +38 -2
  176. package/docs/cli/evals.mdx +3 -3
  177. package/docs/cli/index.mdx +1 -0
  178. package/docs/cli/translate.mdx +3 -3
  179. package/docs/cli/version.mdx +1 -1
  180. package/docs/configuration/analytics.mdx +22 -1
  181. package/docs/configuration/assistant.mdx +188 -36
  182. package/docs/configuration/consent.mdx +100 -0
  183. package/docs/configuration/customization.mdx +6 -4
  184. package/docs/configuration/index.mdx +63 -5
  185. package/docs/configuration/meta.ts +3 -0
  186. package/docs/configuration/narration.mdx +119 -0
  187. package/docs/configuration/rate-limiting.mdx +69 -0
  188. package/docs/configuration/search.mdx +30 -2
  189. package/docs/configuration/theming.mdx +3 -1
  190. package/docs/content/components.mdx +107 -1
  191. package/docs/content/frontmatter.mdx +77 -1
  192. package/docs/content/i18n.mdx +40 -3
  193. package/docs/content/includes.mdx +16 -0
  194. package/docs/content/index.mdx +4 -2
  195. package/docs/content/islands.mdx +1 -1
  196. package/docs/content/meta.mdx +4 -1
  197. package/docs/content/meta.ts +1 -0
  198. package/docs/content/navigation.mdx +28 -6
  199. package/docs/content/sources/contentful.mdx +32 -0
  200. package/docs/content/sources/custom.mdx +39 -0
  201. package/docs/content/sources/github-releases.mdx +31 -0
  202. package/docs/content/sources/index.mdx +91 -0
  203. package/docs/content/sources/meta.ts +16 -0
  204. package/docs/content/sources/notion.mdx +32 -0
  205. package/docs/content/sources/obsidian.mdx +37 -0
  206. package/docs/content/sources/payload.mdx +30 -0
  207. package/docs/content/sources/remote-mdx.mdx +40 -0
  208. package/docs/content/sources/sanity.mdx +29 -0
  209. package/docs/content/sources/strapi.mdx +31 -0
  210. package/docs/content/syntax.mdx +81 -2
  211. package/docs/content/variables.mdx +41 -0
  212. package/docs/content/versioning.mdx +1 -1
  213. package/docs/discoverability/agent-discovery.mdx +30 -3
  214. package/docs/discoverability/index.mdx +3 -2
  215. package/docs/discoverability/llms-txt.mdx +1 -1
  216. package/docs/discoverability/markdown.mdx +2 -2
  217. package/docs/discoverability/metadata.mdx +17 -0
  218. package/docs/discoverability/open-graph.mdx +5 -3
  219. package/docs/discoverability/rss.mdx +1 -1
  220. package/docs/references/api-pages.mdx +74 -0
  221. package/docs/references/asyncapi.mdx +2 -2
  222. package/docs/references/graphql.mdx +3 -3
  223. package/docs/references/meta.ts +1 -1
  224. package/docs/references/openapi.mdx +106 -5
  225. package/docs/references/scalar.mdx +3 -1
  226. package/package.json +36 -1
  227. package/skills/blume/SKILL.md +3 -0
  228. package/skills/blume-migrate/SKILL.md +5 -5
  229. package/skills/blume-migrate/references/docusaurus.md +3 -3
  230. package/skills/blume-migrate/references/fumadocs.md +1 -1
  231. package/skills/blume-migrate/references/mintlify.md +37 -19
  232. package/skills/blume-migrate/references/nextra.md +3 -3
  233. package/skills/blume-migrate/references/starlight.md +2 -1
  234. package/skills/blume-migrate/scripts/mintlify-codemod.mjs +67 -16
  235. package/skills/blume-write-skill/SKILL.md +82 -0
  236. package/src/ai/agent-readability.ts +4 -3
  237. package/src/ai/agent-surface.ts +9 -7
  238. package/src/ai/ai-catalog.ts +12 -5
  239. package/src/ai/api/handlers.ts +2 -2
  240. package/src/ai/api/spec.ts +2 -2
  241. package/src/ai/api-catalog.ts +6 -2
  242. package/src/ai/ask-context.ts +73 -20
  243. package/src/ai/ask-data.ts +6 -0
  244. package/src/ai/ask-tools.ts +142 -0
  245. package/src/ai/ask.ts +354 -76
  246. package/src/ai/changelog-markdown.ts +2 -2
  247. package/src/ai/component-markdown.ts +75 -0
  248. package/src/ai/cors.ts +2 -0
  249. package/src/ai/index.ts +12 -0
  250. package/src/ai/link-headers.ts +14 -5
  251. package/src/ai/llms.ts +24 -9
  252. package/src/ai/markdown.ts +2 -1
  253. package/src/ai/mcp/data.ts +6 -0
  254. package/src/ai/mcp/discovery.ts +2 -2
  255. package/src/ai/mcp/query.ts +2 -2
  256. package/src/ai/mcp/server.ts +2 -2
  257. package/src/ai/openapi-components.ts +31 -9
  258. package/src/ai/relative-links.ts +42 -26
  259. package/src/ai/serializers.ts +2 -1
  260. package/src/ai/site-skill.ts +274 -0
  261. package/src/ai/skills.ts +49 -3
  262. package/src/ai/tar.ts +139 -12
  263. package/src/ai/write-skill.ts +97 -0
  264. package/src/analytics/head.ts +4 -0
  265. package/src/analytics/index.ts +5 -0
  266. package/src/analytics/one-dollar-stats.ts +86 -0
  267. package/src/analytics/schema.ts +2 -0
  268. package/src/astro/generate.ts +133 -19
  269. package/src/astro/include-hmr.ts +31 -12
  270. package/src/astro/include-refresh.ts +19 -8
  271. package/src/astro/index.ts +1 -0
  272. package/src/astro/integration.ts +143 -14
  273. package/src/astro/module-types.ts +6 -0
  274. package/src/astro/runtime-modules.ts +28 -13
  275. package/src/astro/templates.ts +364 -67
  276. package/src/astro/variables.ts +31 -0
  277. package/src/audit/catalog.ts +19 -0
  278. package/src/audit/checks/contrast.ts +183 -0
  279. package/src/audit/checks/i18n.ts +2 -3
  280. package/src/audit/checks/indexability.ts +2 -3
  281. package/src/audit/checks/links.ts +13 -13
  282. package/src/audit/checks/sitemap.ts +2 -3
  283. package/src/audit/graph.ts +3 -1
  284. package/src/audit/redirects.ts +46 -15
  285. package/src/audit/run.ts +14 -9
  286. package/src/audit/snapshot.ts +5 -0
  287. package/src/audit/types.ts +2 -1
  288. package/src/blume-modules.d.ts +7 -0
  289. package/src/captcha/client.ts +152 -0
  290. package/src/captcha/hcaptcha.ts +36 -0
  291. package/src/captcha/index.ts +28 -0
  292. package/src/captcha/schema.ts +32 -0
  293. package/src/captcha/turnstile.ts +38 -0
  294. package/src/captcha/verify.ts +71 -0
  295. package/src/cli/args.ts +32 -0
  296. package/src/cli/command-meta.ts +5 -0
  297. package/src/cli/commands/audit.ts +4 -1
  298. package/src/cli/commands/doctor.ts +25 -17
  299. package/src/cli/commands/eval.ts +19 -11
  300. package/src/cli/commands/skill.ts +96 -0
  301. package/src/cli/commands/translate.ts +9 -12
  302. package/src/cli/commands/validate.ts +3 -1
  303. package/src/cli/dev-lock.ts +157 -37
  304. package/src/cli/index.ts +5 -0
  305. package/src/cli/report-format.ts +11 -6
  306. package/src/cli/required-secrets.ts +71 -29
  307. package/src/components/BlumePage.astro +2 -0
  308. package/src/components/colors.ts +19 -0
  309. package/src/components/content/ApiEndpoint.astro +18 -0
  310. package/src/components/content/ApiField.astro +79 -0
  311. package/src/components/content/ApiPlayground.astro +62 -0
  312. package/src/components/content/ApiRail.astro +19 -0
  313. package/src/components/content/Badge.astro +5 -3
  314. package/src/components/content/Color.astro +1 -0
  315. package/src/components/content/Component.astro +2 -2
  316. package/src/components/content/FileTree.astro +1 -0
  317. package/src/components/content/GithubInfo.astro +1 -0
  318. package/src/components/content/Panel.astro +1 -0
  319. package/src/components/content/ParamField.astro +25 -0
  320. package/src/components/content/RequestExample.astro +17 -0
  321. package/src/components/content/ResponseExample.astro +17 -0
  322. package/src/components/content/ResponseField.astro +32 -0
  323. package/src/components/content/Step.astro +1 -0
  324. package/src/components/content/Tab.astro +0 -1
  325. package/src/components/content/Tabs.astro +4 -0
  326. package/src/components/content/Tile.astro +1 -0
  327. package/src/components/content/Tooltip.astro +1 -0
  328. package/src/components/content/Tree.astro +1 -0
  329. package/src/components/content/TypeTable.astro +4 -1
  330. package/src/components/content/View.astro +21 -0
  331. package/src/components/content/ViewSwitcher.astro +168 -0
  332. package/src/components/content/api-field.ts +100 -0
  333. package/src/components/content/api-page.ts +224 -0
  334. package/src/components/content/badge-color.ts +5 -2
  335. package/src/components/content/base-href.ts +13 -36
  336. package/src/components/content/view-switcher.ts +71 -0
  337. package/src/components/index.ts +2 -0
  338. package/src/components/islands/Assistant.astro +10 -1
  339. package/src/components/islands/assistant.tsx +125 -18
  340. package/src/components/islands/base-path.ts +47 -10
  341. package/src/components/islands/code-question.ts +62 -0
  342. package/src/components/islands/hooks.ts +145 -40
  343. package/src/components/islands/support-link.ts +68 -0
  344. package/src/components/islands/webmcp.ts +4 -2
  345. package/src/components/layout/Analytics.astro +11 -2
  346. package/src/components/layout/Banner.astro +14 -10
  347. package/src/components/layout/Breadcrumbs.astro +11 -4
  348. package/src/components/layout/ConsentBanner.astro +62 -0
  349. package/src/components/layout/ConsentHead.astro +38 -0
  350. package/src/components/layout/Directory.astro +94 -0
  351. package/src/components/layout/DiscoveryLinks.astro +9 -5
  352. package/src/components/layout/DrawerSwitchers.astro +51 -0
  353. package/src/components/layout/Empty.astro +2 -2
  354. package/src/components/layout/Header.astro +124 -82
  355. package/src/components/layout/LanguageSwitcher.astro +50 -17
  356. package/src/components/layout/NarrationPlayer.astro +1085 -0
  357. package/src/components/layout/NavSelector.astro +35 -9
  358. package/src/components/layout/NavTabMenu.astro +3 -3
  359. package/src/components/layout/NavTree.astro +16 -6
  360. package/src/components/layout/PageActions.astro +4 -3
  361. package/src/components/layout/PageFeedback.astro +54 -49
  362. package/src/components/layout/PageLayout.astro +78 -9
  363. package/src/components/layout/Pagination.astro +3 -3
  364. package/src/components/layout/ReferenceLayout.astro +17 -6
  365. package/src/components/layout/RelatedPages.astro +42 -0
  366. package/src/components/layout/RootLayout.astro +313 -50
  367. package/src/components/layout/Search.astro +64 -30
  368. package/src/components/layout/SiteFooter.astro +124 -0
  369. package/src/components/layout/SiteMetatags.astro +16 -0
  370. package/src/components/layout/VersionBanner.astro +2 -2
  371. package/src/components/layout/analytics-client.ts +12 -0
  372. package/src/components/layout/consent/native.ts +79 -0
  373. package/src/components/layout/consent/types.ts +37 -0
  374. package/src/components/layout/footer-links.ts +53 -0
  375. package/src/components/layout/footer-socials.ts +87 -0
  376. package/src/components/layout/locale-redirect.ts +107 -0
  377. package/src/components/layout/nav-utils.ts +83 -0
  378. package/src/components/layout/page-feedback.ts +96 -0
  379. package/src/components/layout/search/analytics.ts +98 -0
  380. package/src/components/layout/search/flexsearch.ts +17 -5
  381. package/src/components/layout/search/orama-cloud.ts +26 -14
  382. package/src/components/layout/search/types.ts +20 -0
  383. package/src/components/layout/search/typesense.ts +5 -1
  384. package/src/components/layout/toc-active.ts +41 -0
  385. package/src/components/layout/toc-element.ts +8 -14
  386. package/src/components/openapi/ApiTagOperations.astro +2 -2
  387. package/src/components/openapi/AsyncApiOperation.astro +7 -4
  388. package/src/components/openapi/GraphqlChip.astro +2 -2
  389. package/src/components/openapi/Operation.astro +163 -13
  390. package/src/components/openapi/Playground.astro +4 -4
  391. package/src/components/openapi/RequestBody.astro +6 -4
  392. package/src/components/openapi/RequestPanel.astro +63 -8
  393. package/src/components/openapi/Responses.astro +6 -4
  394. package/src/components/openapi/SchemaTable.astro +7 -0
  395. package/src/components/openapi/async-snippets.ts +4 -4
  396. package/src/components/openapi/async.ts +38 -6
  397. package/src/components/openapi/code-samples.ts +97 -0
  398. package/src/components/openapi/helpers.ts +19 -9
  399. package/src/components/openapi/message-composer.ts +6 -1
  400. package/src/components/openapi/message.ts +17 -2
  401. package/src/components/openapi/operation-model.ts +81 -11
  402. package/src/components/openapi/panel.ts +4 -2
  403. package/src/components/openapi/param-style.ts +181 -0
  404. package/src/components/openapi/playground-client.ts +73 -16
  405. package/src/components/openapi/request.ts +190 -26
  406. package/src/components/openapi/schema-tree.ts +30 -24
  407. package/src/components/openapi/security.ts +6 -3
  408. package/src/components/openapi/snippets.ts +953 -13
  409. package/src/components/openapi/ws-client.ts +18 -2
  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/base-path.ts +62 -16
  421. package/src/core/builtin-tags.ts +5 -0
  422. package/src/core/client-address.ts +19 -0
  423. package/src/core/config-input.ts +203 -27
  424. package/src/core/data.ts +44 -4
  425. package/src/core/diagnostics.ts +5 -2
  426. package/src/core/directive-diagnostics.ts +99 -0
  427. package/src/core/footer.ts +26 -0
  428. package/src/core/frontmatter.ts +21 -18
  429. package/src/core/graph.ts +39 -36
  430. package/src/core/heading-markers.ts +5 -18
  431. package/src/core/i18n-ui.ts +82 -2
  432. package/src/core/i18n.ts +31 -3
  433. package/src/core/includes.ts +20 -3
  434. package/src/core/last-modified.ts +25 -3
  435. package/src/core/links.ts +16 -2
  436. package/src/core/locale-links.ts +5 -1
  437. package/src/core/localizable.ts +26 -0
  438. package/src/core/meta.ts +33 -19
  439. package/src/core/navigation.ts +71 -20
  440. package/src/core/page-modes.ts +56 -0
  441. package/src/core/project-graph.ts +138 -10
  442. package/src/core/redirect-patterns.ts +491 -0
  443. package/src/core/related.ts +131 -0
  444. package/src/core/schema.ts +342 -68
  445. package/src/core/sources/contentful-rich-text.ts +27 -20
  446. package/src/core/sources/filesystem.ts +20 -2
  447. package/src/core/sources/github-releases.ts +25 -6
  448. package/src/core/sources/lexical.ts +23 -18
  449. package/src/core/sources/lower.ts +201 -34
  450. package/src/core/sources/mdx-remote.ts +51 -16
  451. package/src/core/sources/normalize.ts +327 -91
  452. package/src/core/sources/notion.ts +52 -25
  453. package/src/core/sources/obsidian.ts +23 -6
  454. package/src/core/sources/portable-text.ts +38 -21
  455. package/src/core/sources/read.ts +8 -3
  456. package/src/core/sources/strapi-blocks.ts +20 -16
  457. package/src/core/sources/watch.ts +20 -7
  458. package/src/core/standard-schema.ts +10 -6
  459. package/src/core/types.ts +1 -1
  460. package/src/core/ui-packs/ar.ts +43 -0
  461. package/src/core/ui-packs/bg.ts +45 -0
  462. package/src/core/ui-packs/bn.ts +43 -0
  463. package/src/core/ui-packs/ca.ts +46 -0
  464. package/src/core/ui-packs/cs.ts +44 -0
  465. package/src/core/ui-packs/da.ts +45 -0
  466. package/src/core/ui-packs/de.ts +46 -0
  467. package/src/core/ui-packs/el.ts +45 -0
  468. package/src/core/ui-packs/es.ts +46 -0
  469. package/src/core/ui-packs/fa.ts +45 -0
  470. package/src/core/ui-packs/fi.ts +45 -0
  471. package/src/core/ui-packs/fr.ts +46 -0
  472. package/src/core/ui-packs/he.ts +43 -0
  473. package/src/core/ui-packs/hi.ts +44 -0
  474. package/src/core/ui-packs/hr.ts +45 -0
  475. package/src/core/ui-packs/hu.ts +44 -0
  476. package/src/core/ui-packs/id.ts +45 -0
  477. package/src/core/ui-packs/it.ts +45 -0
  478. package/src/core/ui-packs/ja.ts +45 -0
  479. package/src/core/ui-packs/ko.ts +44 -0
  480. package/src/core/ui-packs/nl.ts +46 -0
  481. package/src/core/ui-packs/no.ts +44 -0
  482. package/src/core/ui-packs/pl.ts +45 -0
  483. package/src/core/ui-packs/pt-br.ts +46 -0
  484. package/src/core/ui-packs/pt.ts +45 -0
  485. package/src/core/ui-packs/ro.ts +45 -0
  486. package/src/core/ui-packs/ru.ts +45 -0
  487. package/src/core/ui-packs/sk.ts +44 -0
  488. package/src/core/ui-packs/sr.ts +45 -0
  489. package/src/core/ui-packs/sv.ts +44 -0
  490. package/src/core/ui-packs/th.ts +43 -0
  491. package/src/core/ui-packs/tr.ts +45 -0
  492. package/src/core/ui-packs/uk.ts +45 -0
  493. package/src/core/ui-packs/vi.ts +45 -0
  494. package/src/core/ui-packs/zh-tw.ts +43 -0
  495. package/src/core/ui-packs/zh.ts +43 -0
  496. package/src/core/variables.ts +103 -0
  497. package/src/core/version-cut.ts +52 -15
  498. package/src/deploy/artifacts.ts +104 -14
  499. package/src/deploy/cloudflare-negotiation.ts +39 -17
  500. package/src/deploy/headers.ts +10 -5
  501. package/src/deploy/node-headers.ts +64 -10
  502. package/src/deploy/platforms/cloudflare.ts +44 -3
  503. package/src/deploy/platforms/netlify.ts +34 -1
  504. package/src/deploy/platforms/node.ts +1 -0
  505. package/src/deploy/platforms/static.ts +1 -0
  506. package/src/deploy/platforms/types.ts +8 -0
  507. package/src/deploy/platforms/vercel.ts +38 -2
  508. package/src/deploy/redirects.ts +139 -36
  509. package/src/deploy/robots.ts +2 -2
  510. package/src/deploy/rss.ts +4 -3
  511. package/src/deploy/sitemap.ts +7 -5
  512. package/src/deploy/vercel-negotiation.ts +36 -0
  513. package/src/markdown/api-rail.ts +259 -0
  514. package/src/markdown/base-links.ts +34 -36
  515. package/src/markdown/code-title.ts +35 -9
  516. package/src/markdown/directives.ts +242 -36
  517. package/src/markdown/features.ts +20 -2
  518. package/src/markdown/fence-meta.ts +2 -0
  519. package/src/markdown/include.ts +11 -1
  520. package/src/markdown/index.ts +35 -11
  521. package/src/markdown/math.ts +4 -4
  522. package/src/markdown/mdast.ts +5 -2
  523. package/src/markdown/relative-links.ts +12 -4
  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 +136 -11
  531. package/src/og/derive.ts +41 -31
  532. package/src/og/index.ts +1 -0
  533. package/src/openapi/asyncapi.ts +4 -2
  534. package/src/openapi/model.ts +77 -36
  535. package/src/openapi/overlay.ts +256 -0
  536. package/src/openapi/parse.ts +55 -2
  537. package/src/openapi/proxy.ts +63 -10
  538. package/src/openapi/references.ts +21 -5
  539. package/src/openapi/render-mdx.ts +46 -3
  540. package/src/openapi/scalar.ts +40 -6
  541. package/src/openapi/source.ts +1 -1
  542. package/src/ratelimit/cloudflare.ts +54 -0
  543. package/src/ratelimit/index.ts +30 -0
  544. package/src/ratelimit/memory.ts +45 -0
  545. package/src/ratelimit/runtime.ts +229 -0
  546. package/src/ratelimit/schema.ts +28 -0
  547. package/src/ratelimit/upstash.ts +30 -0
  548. package/src/ratelimit/wrangler.ts +70 -0
  549. package/src/reference/asyncapi.ts +2 -2
  550. package/src/reference/graphql.ts +5 -2
  551. package/src/reference/openapi.ts +21 -7
  552. package/src/reference/options.ts +51 -7
  553. package/src/reference/scalar.ts +33 -8
  554. package/src/registry/eject.ts +201 -28
  555. package/src/registry/registry.ts +7 -0
  556. package/src/search/adapters/version-scope.ts +30 -0
  557. package/src/search/documents.ts +93 -28
  558. package/src/search/orama-index.ts +28 -3
  559. package/src/search/pagefind-ranking.ts +39 -0
  560. package/src/search/popular.ts +2 -1
  561. package/src/search/sync/algolia.ts +15 -4
  562. package/src/search/sync/orama-cloud.ts +3 -0
  563. package/src/search/sync/typesense.ts +5 -0
  564. package/src/seo/jsonld.ts +7 -3
  565. package/src/seo/metatags.ts +67 -0
  566. package/src/theme/chrome-icons.ts +1 -0
  567. package/src/theme/color.ts +500 -0
  568. package/src/theme/entry.ts +56 -3
  569. package/src/theme/palette.ts +121 -45
  570. package/src/translate/meta.ts +68 -24
  571. package/src/translate/prompts.ts +1 -0
  572. package/src/translate/run.ts +3 -3
  573. package/src/translate/validate.ts +12 -3
  574. package/src/translate/work-list.ts +56 -17
  575. package/src/upgrade/upgrade.ts +4 -171
  576. package/dist/cli/chunk-3yce002v.js.map +0 -14
  577. package/dist/cli/chunk-5r8g91qn.js.map +0 -34
  578. package/dist/cli/chunk-6dtt0zfn.js.map +0 -10
  579. package/dist/cli/chunk-7mbqtmgb.js.map +0 -10
  580. package/dist/cli/chunk-ddndchfr.js.map +0 -14
  581. package/dist/cli/chunk-esh98wmb.js +0 -23
  582. package/dist/cli/chunk-esh98wmb.js.map +0 -10
  583. package/dist/cli/chunk-hqp2ajnh.js.map +0 -35
  584. package/dist/cli/chunk-hr8ne106.js.map +0 -13
  585. package/dist/cli/chunk-j85scx15.js.map +0 -10
  586. package/dist/cli/chunk-mqc662a6.js +0 -75
  587. package/dist/cli/chunk-mqc662a6.js.map +0 -11
  588. package/dist/cli/chunk-pbg5a4s3.js.map +0 -19
  589. package/dist/cli/chunk-qkb5a8sa.js.map +0 -10
  590. package/dist/cli/chunk-v6ya5kcb.js.map +0 -189
  591. package/dist/cli/chunk-wdrt2k2v.js.map +0 -10
  592. package/dist/cli/chunk-xh43dwgw.js.map +0 -36
  593. package/docs/content/sources.mdx +0 -338
  594. /package/dist/cli/{chunk-zp79m0ts.js.map → chunk-1n228xqb.js.map} +0 -0
  595. /package/dist/cli/{chunk-h2ez8dzb.js.map → chunk-5ffywsmb.js.map} +0 -0
  596. /package/dist/cli/{chunk-g698a744.js.map → chunk-5wj2qwn2.js.map} +0 -0
  597. /package/dist/cli/{chunk-sqw4ekg1.js.map → chunk-amrb6hgh.js.map} +0 -0
  598. /package/dist/cli/{chunk-h7k3nq3v.js.map → chunk-gp84za0h.js.map} +0 -0
  599. /package/dist/cli/{chunk-bfwp9vp6.js.map → chunk-p804f3pe.js.map} +0 -0
  600. /package/dist/cli/{chunk-00gs3wqs.js.map → chunk-ta27feev.js.map} +0 -0
  601. /package/dist/cli/{chunk-bbnwccaz.js.map → chunk-y4ykbark.js.map} +0 -0
@@ -70,7 +70,7 @@ const security = resolveAsyncApiSecurity(
70
70
  );
71
71
  const parameters = channelParameters(channel, document);
72
72
  const messages = operation ? operationMessages(operation, channel, document) : [];
73
- const protocol = protocolOf(operation, channel, servers);
73
+ const protocol = protocolOf(operation, channel, servers, document.components);
74
74
 
75
75
  /** Declared example first, else a sampled value from the payload schema. */
76
76
  const exampleOf = (message: (typeof messages)[number]["message"]): unknown =>
@@ -115,8 +115,8 @@ const samplePanels = sample
115
115
  ? await languageSamplePanels(languages, sample, data.config.codeThemes)
116
116
  : [];
117
117
 
118
- const operationBindings = bindingGroups(operation?.bindings);
119
- const channelBindings = bindingGroups(channel?.bindings);
118
+ const operationBindings = bindingGroups(operation?.bindings, document.components);
119
+ const channelBindings = bindingGroups(channel?.bindings, document.components);
120
120
  ---
121
121
 
122
122
  {
@@ -144,7 +144,10 @@ const channelBindings = bindingGroups(channel?.bindings);
144
144
  // Headers may be multi-format too; undefined with `headers`
145
145
  // present means an inline-unrenderable schema format.
146
146
  const headers = schemaOf(named.message.headers);
147
- const messageBindings = bindingGroups(named.message.bindings);
147
+ const messageBindings = bindingGroups(
148
+ named.message.bindings,
149
+ document.components
150
+ );
148
151
  return (
149
152
  <section class="mt-6">
150
153
  <div
@@ -1,5 +1,5 @@
1
1
  ---
2
- import { withBase } from "../islands/base-path.ts";
2
+ import { withMountedBase } from "../islands/base-path.ts";
3
3
 
4
4
  /**
5
5
  * A schema name (or full type display like `[Pet!]!`) rendered as a link when
@@ -21,7 +21,7 @@ const { name, route, class: className } = Astro.props;
21
21
  route ? (
22
22
  <a
23
23
  class:list={["font-mono text-accent hover:underline", className]}
24
- href={withBase(route)}
24
+ href={withMountedBase(route)}
25
25
  >
26
26
  {name}
27
27
  </a>
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  import specs from "blume:openapi";
3
- import { operationOf, specOf } from "../../openapi/model.ts";
3
+ import { HTTP_METHODS, operationOf, specOf } from "../../openapi/model.ts";
4
4
  import {
5
5
  mergeParameters,
6
6
  type ParameterLike,
@@ -21,10 +21,13 @@ import {
21
21
  type SecuritySchemeLike,
22
22
  } from "./security.ts";
23
23
  import { DEPRECATED_LABEL_CLASS } from "../colors.ts";
24
+ import { customCodeSamples } from "./code-samples.ts";
25
+ import type { CodeSamplesCarrier } from "./code-samples.ts";
24
26
  import { sampleLanguages } from "./snippets.ts";
25
27
  import AsyncApiOperation from "./AsyncApiOperation.astro";
26
28
  import GraphqlOperation from "./GraphqlOperation.astro";
27
29
  import Authorization from "./Authorization.astro";
30
+ import Description from "./Description.astro";
28
31
  import MethodBadge from "./MethodBadge.astro";
29
32
  import ParametersTable from "./ParametersTable.astro";
30
33
  import Playground from "./Playground.astro";
@@ -57,7 +60,18 @@ interface ResponseLike {
57
60
  content?: Record<string, MediaTypeLike>;
58
61
  }
59
62
 
60
- interface FullOperation {
63
+ /**
64
+ * One callback: a map of runtime URL expressions
65
+ * (`{$request.body#/callbackUrl}`) to the path item the API will call there,
66
+ * or a `$ref` to one under `components.callbacks`.
67
+ */
68
+ type CallbackLike = { $ref?: string } & Record<
69
+ string,
70
+ Record<string, unknown> | string | undefined
71
+ >;
72
+
73
+ interface FullOperation extends CodeSamplesCarrier {
74
+ callbacks?: Record<string, CallbackLike>;
61
75
  summary?: string;
62
76
  description?: string;
63
77
  deprecated?: boolean;
@@ -77,15 +91,17 @@ const ref = spec ? operationOf(spec, id) : undefined;
77
91
  const isAsyncApi = spec?.kind === "asyncapi";
78
92
  const isGraphql = spec?.kind === "graphql";
79
93
 
94
+ type PathItemLike = Record<string, unknown> & {
95
+ parameters?: ParameterLike[];
96
+ servers?: ServerLike[];
97
+ };
98
+
80
99
  const doc = (spec?.document ?? {}) as {
81
- paths?: Record<
82
- string,
83
- Record<string, unknown> & {
84
- parameters?: ParameterLike[];
85
- servers?: ServerLike[];
86
- }
87
- >;
100
+ paths?: Record<string, PathItemLike>;
101
+ // OpenAPI 3.1 webhooks: requests the API sends, keyed by name.
102
+ webhooks?: Record<string, PathItemLike>;
88
103
  components?: {
104
+ callbacks?: Record<string, CallbackLike>;
89
105
  schemas?: Record<string, SchemaLike>;
90
106
  parameters?: Record<string, ParameterLike>;
91
107
  requestBodies?: Record<string, RequestBodyLike>;
@@ -95,7 +111,12 @@ const doc = (spec?.document ?? {}) as {
95
111
  security?: SecurityRequirementLike[];
96
112
  servers?: ServerLike[];
97
113
  };
98
- const pathItem = ref ? doc.paths?.[ref.path] : undefined;
114
+ const isWebhook = ref?.webhook === true;
115
+ const pathItem = ref
116
+ ? isWebhook
117
+ ? doc.webhooks?.[ref.path]
118
+ : doc.paths?.[ref.path]
119
+ : undefined;
99
120
  const operation = (
100
121
  pathItem && ref ? pathItem[ref.method] : undefined
101
122
  ) as FullOperation | undefined;
@@ -118,15 +139,18 @@ const responses = Object.fromEntries(
118
139
  );
119
140
 
120
141
  const security = resolveSecurity(
121
- effectiveSecurity(operation?.security, doc.security),
142
+ effectiveSecurity(operation?.security, doc.security, isWebhook),
122
143
  doc.components?.securitySchemes
123
144
  );
124
145
 
125
146
  // One derived model feeds the static default sample, the playground form,
126
- // and (client-side) the live samples + fetch — they can never drift apart.
147
+ // and (client-side) the live samples + fetch — they can never drift apart. A
148
+ // webhook has none: the API sends it, so there is nothing for a reader to
149
+ // call, and its rail shows the payload instead.
127
150
  const model =
128
- ref && operation
151
+ ref && operation && !isWebhook
129
152
  ? operationModel({
153
+ components,
130
154
  method: ref.method,
131
155
  parameters: params,
132
156
  path: ref.path,
@@ -144,6 +168,59 @@ const model =
144
168
  : null;
145
169
  const sample = model ? buildRequest(model, defaultValues(model)) : null;
146
170
  const languages = sampleLanguages(spec?.codeSamples ?? []);
171
+ // The spec's own `x-codeSamples`, shown ahead of the generated ones.
172
+ const customSamples = operation ? customCodeSamples(operation) : [];
173
+
174
+ /** One request the API makes back to the reader, flattened for rendering. */
175
+ interface CallbackEntry {
176
+ expression: string;
177
+ key: string;
178
+ method: string;
179
+ name: string;
180
+ operation: FullOperation;
181
+ }
182
+
183
+ // Callbacks: for each named callback (resolved through
184
+ // `components.callbacks`), each URL expression, each method it declares.
185
+ const callbacks: CallbackEntry[] = Object.entries(
186
+ operation?.callbacks ?? {}
187
+ ).flatMap(([name, raw]) => {
188
+ const callback = resolveComponentRef(raw, components, "callbacks");
189
+ return Object.entries(callback).flatMap(([expression, item]) => {
190
+ if (expression === "$ref" || typeof item !== "object" || item === null) {
191
+ return [];
192
+ }
193
+ return HTTP_METHODS.flatMap((method) => {
194
+ const entry = item[method];
195
+ return typeof entry === "object" && entry !== null
196
+ ? [
197
+ {
198
+ expression,
199
+ key: `${name}-${expression}-${method}`,
200
+ method,
201
+ name,
202
+ // SAFETY: a path item's method entry is an operation object; the
203
+ // object check above guards a spec that put a scalar there.
204
+ operation: entry as FullOperation,
205
+ },
206
+ ]
207
+ : [];
208
+ });
209
+ });
210
+ });
211
+
212
+ /** A callback's request body and responses, `$ref`s resolved. */
213
+ const callbackParts = (entry: CallbackEntry) => ({
214
+ requestBody: entry.operation.requestBody
215
+ ? resolveComponentRef(entry.operation.requestBody, components, "requestBodies")
216
+ : undefined,
217
+ responses: Object.fromEntries(
218
+ Object.entries(entry.operation.responses ?? {}).map(([status, response]) => [
219
+ status,
220
+ resolveComponentRef(response, components, "responses"),
221
+ ])
222
+ ),
223
+ });
147
224
  ---
148
225
  {
149
226
  isAsyncApi ? (
@@ -159,6 +236,11 @@ const languages = sampleLanguages(spec?.codeSamples ?? []);
159
236
  <code class="break-all font-mono text-foreground text-sm">
160
237
  {ref.path}
161
238
  </code>
239
+ {isWebhook && (
240
+ <span class="rounded-md border border-border px-1.5 py-0.5 font-medium text-[0.625rem] text-muted-foreground uppercase tracking-wide">
241
+ Webhook
242
+ </span>
243
+ )}
162
244
  {operation.deprecated && (
163
245
  <span class={DEPRECATED_LABEL_CLASS}>
164
246
  deprecated
@@ -183,7 +265,73 @@ const languages = sampleLanguages(spec?.codeSamples ?? []);
183
265
  schemas={schemas}
184
266
  />
185
267
  )}
268
+ {callbacks.length > 0 && (
269
+ <section class="mt-10">
270
+ <div
271
+ aria-level="2"
272
+ class="mb-3 font-semibold text-foreground text-lg"
273
+ role="heading"
274
+ >
275
+ Callbacks
276
+ </div>
277
+ <div class="flex flex-col gap-6">
278
+ {callbacks.map((entry) => {
279
+ const parts = callbackParts(entry);
280
+ return (
281
+ <div class="rounded-blume border border-border p-4">
282
+ <div
283
+ aria-level="3"
284
+ class="font-semibold text-foreground"
285
+ role="heading"
286
+ >
287
+ {entry.operation.summary || entry.name}
288
+ </div>
289
+ <div class="mt-2 flex flex-wrap items-center gap-2">
290
+ <MethodBadge method={entry.method} />
291
+ <code class="break-all font-mono text-muted-foreground text-xs">
292
+ {entry.expression}
293
+ </code>
294
+ </div>
295
+ {entry.operation.description && (
296
+ <Description
297
+ class="mt-2 text-muted-foreground text-sm"
298
+ text={entry.operation.description}
299
+ />
300
+ )}
301
+ {parts.requestBody && (
302
+ <RequestBody
303
+ expandAll={spec.expandSchemas}
304
+ level={4}
305
+ requestBody={parts.requestBody}
306
+ schemas={schemas}
307
+ />
308
+ )}
309
+ {entry.operation.responses && (
310
+ <Responses
311
+ expandAll={spec.expandSchemas}
312
+ level={4}
313
+ responses={parts.responses}
314
+ schemas={schemas}
315
+ />
316
+ )}
317
+ </div>
318
+ );
319
+ })}
320
+ </div>
321
+ </section>
322
+ )}
186
323
  </div>
324
+ {isWebhook && (requestBody?.content || operation.responses) && (
325
+ <OperationPanel>
326
+ <RequestPanel
327
+ components={components}
328
+ customSamples={customSamples}
329
+ payload={requestBody?.content}
330
+ responses={responses}
331
+ schemas={schemas}
332
+ />
333
+ </OperationPanel>
334
+ )}
187
335
  {sample && model && (
188
336
  <OperationPanel>
189
337
  {spec.playground.enabled && (
@@ -195,6 +343,8 @@ const languages = sampleLanguages(spec?.codeSamples ?? []);
195
343
  />
196
344
  )}
197
345
  <RequestPanel
346
+ components={components}
347
+ customSamples={customSamples}
198
348
  languages={languages}
199
349
  responses={responses}
200
350
  sample={sample}
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  import { stableId } from "../content/tooltip-id.ts";
3
- import { withBase } from "../islands/base-path.ts";
3
+ import { withMountedBase } from "../islands/base-path.ts";
4
4
 
5
5
  import { paramKey, type PlaygroundModel } from "./request.ts";
6
6
 
@@ -25,9 +25,9 @@ interface Props {
25
25
  const { model, proxy, slug, operation } = Astro.props;
26
26
 
27
27
  // The built-in proxy route carries the site `basePath` but, like every
28
- // internal URL in the spec data, not `deployment.base`; `withBase` adds it
29
- // and passes an external proxy URL through untouched.
30
- const proxyUrl = proxy ? withBase(proxy) : undefined;
28
+ // internal URL in the spec data, not `deployment.base`; `withMountedBase`
29
+ // adds it and passes an external proxy URL through untouched.
30
+ const proxyUrl = proxy ? withMountedBase(proxy) : undefined;
31
31
 
32
32
  // `</script>`-proof embedding: `<` only ever occurs inside JSON strings,
33
33
  // where the \u escape is equivalent, so a spec description can never close
@@ -17,9 +17,11 @@ interface Props {
17
17
  requestBody: RequestBodyLike;
18
18
  schemas: Record<string, SchemaLike>;
19
19
  expandAll?: boolean;
20
+ /** The heading's level: 2 on an operation, deeper inside a callback. */
21
+ level?: number;
20
22
  }
21
23
 
22
- const { requestBody, schemas, expandAll = false } = Astro.props;
24
+ const { requestBody, schemas, expandAll = false, level = 2 } = Astro.props;
23
25
 
24
26
  const entries = Object.entries(requestBody.content ?? {});
25
27
  const chosen = entries.find(([type]) => type.includes("json")) ?? entries[0];
@@ -27,11 +29,11 @@ const contentType = chosen?.[0] ?? "application/json";
27
29
  const schema = chosen?.[1]?.schema ?? {};
28
30
  ---
29
31
 
30
- <section class="mt-8">
32
+ <section class:list={[level > 2 ? "mt-5" : "mt-8"]}>
31
33
  <div class="mb-2 flex flex-wrap items-center gap-2">
32
34
  <div
33
- aria-level="2"
34
- class="font-semibold text-foreground text-lg"
35
+ aria-level={level}
36
+ class:list={["font-semibold text-foreground", level > 2 ? "text-sm" : "text-lg"]}
35
37
  role="heading"
36
38
  >
37
39
  Request body
@@ -3,11 +3,13 @@ import data from "blume:data";
3
3
 
4
4
  import { highlightCode } from "../../markdown/index.ts";
5
5
  import {
6
+ type ComponentsLike,
6
7
  responseExample,
7
8
  type SchemaLike,
8
9
  type SpecValue,
9
10
  toJson,
10
11
  } from "./helpers.ts";
12
+ import type { CustomCodeSample } from "./code-samples.ts";
11
13
  import { languageSamplePanels } from "./sample-panels.ts";
12
14
  import PanelTabs from "./PanelTabs.astro";
13
15
  import type { RequestSample, SampleLanguage } from "./snippets.ts";
@@ -24,19 +26,71 @@ interface ResponseLike {
24
26
  }
25
27
 
26
28
  interface Props {
27
- sample: RequestSample;
28
- languages: SampleLanguage[];
29
+ /** The document's `components`, which `$ref`'d examples resolve against. */
30
+ components?: ComponentsLike;
31
+ /** The spec's hand-written `x-codeSamples`, shown first and never re-rendered live. */
32
+ customSamples?: CustomCodeSample[];
33
+ /**
34
+ * A webhook's body: the rail shows it as a "Payload" example per media
35
+ * type in place of client code, since the API sends the request.
36
+ */
37
+ payload?: Record<string, MediaTypeLike>;
38
+ sample?: RequestSample;
39
+ languages?: SampleLanguage[];
29
40
  responses: Record<string, ResponseLike>;
30
41
  schemas: Record<string, SchemaLike>;
31
42
  }
32
43
 
33
- const { sample, languages, responses, schemas } = Astro.props;
34
-
35
- const requestPanels = await languageSamplePanels(
36
- languages,
44
+ const {
45
+ components,
46
+ customSamples = [],
47
+ payload,
37
48
  sample,
38
- data.config.codeThemes
49
+ languages = [],
50
+ responses,
51
+ schemas,
52
+ } = Astro.props;
53
+
54
+ /** A media type's example, highlighted, or null when it has none. */
55
+ const highlightExample = async (media: MediaTypeLike, type: string) => {
56
+ const example = responseExample(media, schemas, components);
57
+ if (example === undefined || example === null) {
58
+ return null;
59
+ }
60
+ const json = type.includes("json");
61
+ return highlightCode(
62
+ json || typeof example !== "string" ? toJson(example) : example,
63
+ json ? "json" : "text",
64
+ { icons: false, themes: data.config.codeThemes }
65
+ );
66
+ };
67
+
68
+ // Hand-written samples carry no `lang` key, so the playground leaves them
69
+ // as written when it re-renders the generated ones from the form.
70
+ const customPanels = await Promise.all(
71
+ customSamples.map(async (custom) => ({
72
+ html: await highlightCode(custom.source, custom.lang, {
73
+ icons: false,
74
+ themes: data.config.codeThemes,
75
+ }),
76
+ key: custom.key,
77
+ label: custom.label,
78
+ }))
79
+ );
80
+ const payloadPanels = await Promise.all(
81
+ Object.entries(payload ?? {}).map(async ([type, media]) => ({
82
+ html: await highlightExample(media, type),
83
+ key: type,
84
+ label: type,
85
+ text: "No example payload.",
86
+ }))
39
87
  );
88
+ const requestPanels = [
89
+ ...customPanels,
90
+ ...(sample
91
+ ? await languageSamplePanels(languages, sample, data.config.codeThemes)
92
+ : []),
93
+ ];
40
94
 
41
95
  const responsePanels = await Promise.all(
42
96
  Object.entries(responses).map(async ([status, response]) => {
@@ -44,7 +98,7 @@ const responsePanels = await Promise.all(
44
98
  Object.entries(response.content ?? {}).find(([type]) =>
45
99
  type.includes("json")
46
100
  )?.[1] ?? Object.values(response.content ?? {})[0];
47
- const example = media ? responseExample(media, schemas) : undefined;
101
+ const example = media ? responseExample(media, schemas, components) : undefined;
48
102
  const html =
49
103
  example === undefined || example === null
50
104
  ? null
@@ -63,6 +117,7 @@ const responsePanels = await Promise.all(
63
117
  ---
64
118
 
65
119
  <div class="not-prose flex flex-col gap-6">
120
+ <PanelTabs copy heading="Payload" mono panels={payloadPanels} />
66
121
  <PanelTabs copy heading="Request" panels={requestPanels} />
67
122
  <PanelTabs heading="Response" mono panels={responsePanels} />
68
123
  </div>
@@ -17,19 +17,21 @@ interface Props {
17
17
  responses: Record<string, ResponseLike>;
18
18
  schemas: Record<string, SchemaLike>;
19
19
  expandAll?: boolean;
20
+ /** The heading's level: 2 on an operation, deeper inside a callback. */
21
+ level?: number;
20
22
  }
21
23
 
22
- const { responses, schemas, expandAll = false } = Astro.props;
24
+ const { responses, schemas, expandAll = false, level = 2 } = Astro.props;
23
25
 
24
26
  const items = Object.entries(responses);
25
27
  ---
26
28
 
27
29
  {
28
30
  items.length > 0 && (
29
- <section class="mt-8">
31
+ <section class:list={[level > 2 ? "mt-5" : "mt-8"]}>
30
32
  <div
31
- aria-level="2"
32
- class="mb-3 font-semibold text-foreground text-lg"
33
+ aria-level={level}
34
+ class:list={["mb-3 font-semibold text-foreground", level > 2 ? "text-sm" : "text-lg"]}
33
35
  role="heading"
34
36
  >
35
37
  Responses
@@ -35,6 +35,13 @@ const node = planned ?? schemaTree(schema, schemas);
35
35
  </div>
36
36
  ) : node.kind === "branches" ? (
37
37
  <div class="flex flex-col gap-3">
38
+ {node.rows && (
39
+ <div class="not-prose">
40
+ {node.rows.map((row) => (
41
+ <SchemaProperty row={row} schemas={schemas} expandAll={expandAll} />
42
+ ))}
43
+ </div>
44
+ )}
38
45
  <div class="text-muted-foreground text-xs">{node.label}:</div>
39
46
  {node.branches.map((branch) => (
40
47
  <div class="rounded-blume border border-border p-3">
@@ -157,15 +157,15 @@ const ALIASES = new Map<string, ToolId>([
157
157
  /**
158
158
  * The sample tools to render for an operation. The protocol picks the
159
159
  * candidate set; a non-empty `codeSamples` config filters and orders it
160
- * (unknown ids are dropped, aliases accepted). No protocol, an unsupported
161
- * one, or a filter that matches nothing yields no samples.
160
+ * (unknown ids are dropped, aliases accepted). `false`, no protocol, an
161
+ * unsupported one, or a filter that matches nothing yields no samples.
162
162
  */
163
163
  export const asyncSampleLanguages = (
164
- ids: string[],
164
+ ids: string[] | false,
165
165
  protocol?: string
166
166
  ): AsyncSampleLanguage[] => {
167
167
  const candidates = PROTOCOL_TOOLS.get(protocol ?? "") ?? [];
168
- if (candidates.length === 0) {
168
+ if (ids === false || candidates.length === 0) {
169
169
  return [];
170
170
  }
171
171
  if (ids.length === 0) {
@@ -265,6 +265,32 @@ export const channelServers = (
265
265
  return servers;
266
266
  };
267
267
 
268
+ /** A protocol-keyed `bindings` map, whatever object it sits on. */
269
+ type BindingMap = Record<string, AsyncApiSpecValue>;
270
+
271
+ const BINDINGS_REF =
272
+ /^#\/components\/(?<section>(?:server|channel|operation|message)Bindings)\/(?<name>[^/]+)$/u;
273
+
274
+ /**
275
+ * A `bindings` map as declared: inline, or — which AsyncAPI allows in its
276
+ * place — a `$ref` to a `#/components/*Bindings` entry, resolved here. Read
277
+ * as-is, a referenced map's only key is `$ref`, which would pass for the
278
+ * protocol. `undefined` when a ref resolves to nothing.
279
+ */
280
+ export const resolveBindings = (
281
+ bindings: BindingMap | undefined,
282
+ components?: Components
283
+ ): BindingMap | undefined => {
284
+ const ref = bindings?.$ref;
285
+ if (!isString(ref)) {
286
+ return bindings;
287
+ }
288
+ const groups = BINDINGS_REF.exec(ref)?.groups;
289
+ const target =
290
+ components?.[groups?.section ?? ""]?.[unescapePointer(groups?.name ?? "")];
291
+ return isObject(target) ? target : undefined;
292
+ };
293
+
268
294
  /** Normalize protocol spellings onto the binding key they document. */
269
295
  const PROTOCOL_ALIASES = {
270
296
  "kafka-secure": "kafka",
@@ -277,15 +303,17 @@ const PROTOCOL_ALIASES = {
277
303
  /**
278
304
  * The protocol an operation speaks, for binding-aware code samples: the first
279
305
  * operation/channel binding key, else the first relevant server's `protocol`.
306
+ * `components` resolves bindings given as a `$ref`.
280
307
  */
281
308
  export const protocolOf = (
282
309
  operation: AsyncApiOperationObject | undefined,
283
310
  channel: AsyncApiChannelObject | undefined,
284
- servers: AsyncApiServerObject[]
311
+ servers: AsyncApiServerObject[],
312
+ components?: Components
285
313
  ): string | undefined => {
286
314
  const declared =
287
- Object.keys(operation?.bindings ?? {})[0] ??
288
- Object.keys(channel?.bindings ?? {})[0] ??
315
+ Object.keys(resolveBindings(operation?.bindings, components) ?? {})[0] ??
316
+ Object.keys(resolveBindings(channel?.bindings, components) ?? {})[0] ??
289
317
  servers.find((server) => isString(server.protocol))?.protocol;
290
318
  if (!isString(declared) || declared === "") {
291
319
  return undefined;
@@ -338,13 +366,17 @@ export interface BindingGroup {
338
366
  /**
339
367
  * Binding maps flattened for display, `bindingVersion` (metadata, not
340
368
  * behavior) dropped. Values stay unformatted — the component renders schema-ish
341
- * objects as nested schema tables and everything else as code.
369
+ * objects as nested schema tables and everything else as code. `components`
370
+ * resolves a map given as a `$ref`.
342
371
  */
343
372
  export const bindingGroups = (
344
- bindings?: AsyncApiChannelObject["bindings"]
373
+ bindings?: BindingMap,
374
+ components?: Components
345
375
  ): BindingGroup[] => {
346
376
  const groups: BindingGroup[] = [];
347
- for (const [protocol, fields] of Object.entries(bindings ?? {})) {
377
+ for (const [protocol, fields] of Object.entries(
378
+ resolveBindings(bindings, components) ?? {}
379
+ )) {
348
380
  if (!isObject(fields)) {
349
381
  continue;
350
382
  }