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,273 @@
1
+ import type { OperationObject } from "@scalar/openapi-types/3.2";
2
+
3
+ import type { ApiDocument } from "./model.ts";
4
+ import { HTTP_METHODS } from "./model.ts";
5
+
6
+ /**
7
+ * Targeted checks for spec mistakes that would otherwise render silently
8
+ * wrong. This is not a validator — a linter such as Spectral or oasdiff owns
9
+ * that — and a spec that fails one of these still renders. Each check names
10
+ * one mistake whose symptom on the page is quiet: a path placeholder sent
11
+ * as literal text, a Try it input whose value goes nowhere, an Authorization
12
+ * section with no scheme to describe. Each reports a warning with its own
13
+ * code, so a build says what's wrong instead of shipping it.
14
+ */
15
+
16
+ /** One mistake a check found, before the source names the spec it's in. */
17
+ export interface SpecIssue {
18
+ code: string;
19
+ message: string;
20
+ suggestion: string;
21
+ }
22
+
23
+ /** A `{name}` placeholder in a path template. */
24
+ const PATH_TEMPLATE = /\{(?<name>[^{}]+)\}/gu;
25
+
26
+ /** A reference to a parameter declared under `components.parameters`. */
27
+ const PARAMETER_REF = /^#\/components\/parameters\/(?<name>[^/]+)$/u;
28
+
29
+ /** How many operations a security-scheme warning names before counting the rest. */
30
+ const NAMED_OPERATIONS = 3;
31
+
32
+ /** One entry of a document's `paths` or `webhooks` map. */
33
+ type PathItem = NonNullable<ApiDocument["paths"]>[string];
34
+
35
+ /**
36
+ * How a warning names an operation: `GET /pets`, or a webhook by its name
37
+ * (`Webhook "newPet" (POST)`), since a webhook has no path.
38
+ */
39
+ export const operationLabel = (
40
+ name: string,
41
+ method: string,
42
+ webhook: boolean
43
+ ): string =>
44
+ webhook
45
+ ? `Webhook "${name}" (${method.toUpperCase()})`
46
+ : `${method.toUpperCase()} ${name}`;
47
+
48
+ /** One entry of a `parameters` list: a parameter, or a `$ref` to one. */
49
+ type ParameterEntry = NonNullable<OperationObject["parameters"]>[number];
50
+
51
+ // The runtime object checks stand guard because the document was parsed from
52
+ // arbitrary YAML/JSON: a spec can put a scalar or null where the type
53
+ // promises an object.
54
+ const isObject = <Value>(value: Value): value is NonNullable<Value> =>
55
+ typeof value === "object" && value !== null;
56
+
57
+ /** A parameter's `name`, which a hand-written spec may have left out or mistyped. */
58
+ const isName = <Value>(value: Value): value is Value & string =>
59
+ typeof value === "string";
60
+
61
+ /** A declared list, or none when a hand-written spec put something else there. */
62
+ const listOf = <Item>(value: Item[] | undefined): NonNullable<Item>[] =>
63
+ Array.isArray(value) ? value.filter(isObject) : [];
64
+
65
+ /** A resolved parameter: one that isn't a `$ref`. */
66
+ type Parameter = Extract<ParameterEntry, { in: string }>;
67
+
68
+ /**
69
+ * The parameters an operation declares, its path item's and its own, `$ref`s
70
+ * resolved through `components.parameters`. One that doesn't resolve is left
71
+ * out, as the page leaves it out.
72
+ */
73
+ const parametersOf = (
74
+ document: ApiDocument,
75
+ item: PathItem,
76
+ operation: OperationObject
77
+ ): Parameter[] => {
78
+ const components = document.components?.parameters ?? {};
79
+ return [
80
+ ...listOf<ParameterEntry>(item.parameters),
81
+ ...listOf<ParameterEntry>(operation.parameters),
82
+ ].flatMap((entry) => {
83
+ const refName =
84
+ "$ref" in entry
85
+ ? PARAMETER_REF.exec(entry.$ref)?.groups?.name
86
+ : undefined;
87
+ const parameter = (refName ? components[refName] : undefined) ?? entry;
88
+ return "in" in parameter ? [parameter] : [];
89
+ });
90
+ };
91
+
92
+ /**
93
+ * A path whose template and declared path parameters disagree. A placeholder
94
+ * with no parameter gets no input in Try it and no row in the table, so
95
+ * requests send it as literal text; a parameter with no placeholder gets an
96
+ * input whose value never reaches the URL.
97
+ */
98
+ const pathParameterIssues = (
99
+ signature: string,
100
+ path: string,
101
+ declared: Set<string>
102
+ ): SpecIssue[] => {
103
+ const used = new Set(
104
+ [...path.matchAll(PATH_TEMPLATE)].map((match) => match.groups?.name ?? "")
105
+ );
106
+ const issues: SpecIssue[] = [];
107
+ for (const name of used) {
108
+ if (!declared.has(name)) {
109
+ issues.push({
110
+ code: "BLUME_OPENAPI_PATH_PARAMETER_MISSING",
111
+ message: `${signature} has {${name}} in its path but declares no "${name}" path parameter, so Try it and the code samples send "{${name}}" as literal text.`,
112
+ suggestion: `Declare "${name}" in the operation's or the path's \`parameters\`, with \`in: path\` and \`required: true\`.`,
113
+ });
114
+ }
115
+ }
116
+ for (const name of declared) {
117
+ if (!used.has(name)) {
118
+ issues.push({
119
+ code: "BLUME_OPENAPI_PATH_PARAMETER_UNUSED",
120
+ message: `${signature} declares a "${name}" path parameter, but its path has no {${name}}, so the value Try it asks for never reaches the URL.`,
121
+ suggestion: `Add {${name}} to the path, or remove the parameter.`,
122
+ });
123
+ }
124
+ }
125
+ return issues;
126
+ };
127
+
128
+ /** The scheme names a `security` list requires. */
129
+ const requiredSchemes = (
130
+ security: ApiDocument["security"] | OperationObject["security"]
131
+ ): string[] =>
132
+ listOf(security).flatMap((requirement) => Object.keys(requirement));
133
+
134
+ /**
135
+ * Security schemes a requirement names that `components.securitySchemes`
136
+ * doesn't define: the Authorization section has nothing to describe, and
137
+ * Try it and the code samples send no credential for them. One warning per
138
+ * scheme, naming where it's required: the root `security`, or the first few
139
+ * operations that list it.
140
+ */
141
+ const securitySchemeIssues = (
142
+ document: ApiDocument,
143
+ requirers: Map<string, string[]>
144
+ ): SpecIssue[] => {
145
+ const defined = document.components?.securitySchemes ?? {};
146
+ const root = new Set(requiredSchemes(document.security));
147
+ const issues: SpecIssue[] = [];
148
+ for (const scheme of new Set([...root, ...requirers.keys()])) {
149
+ if (Object.hasOwn(defined, scheme)) {
150
+ continue;
151
+ }
152
+ const operations = requirers.get(scheme) ?? [];
153
+ const more = operations.length - NAMED_OPERATIONS;
154
+ const where = root.has(scheme)
155
+ ? "The spec's root `security` requires"
156
+ : `${operations.slice(0, NAMED_OPERATIONS).join(", ")}${more > 0 ? ` and ${more} more` : ""} ${operations.length === 1 ? "requires" : "require"}`;
157
+ issues.push({
158
+ code: "BLUME_OPENAPI_UNKNOWN_SECURITY_SCHEME",
159
+ message: `${where} the "${scheme}" security scheme, which \`components.securitySchemes\` doesn't define, so the Authorization section can't describe it and requests send no credential for it.`,
160
+ suggestion: `Define "${scheme}" in \`components.securitySchemes\`, or fix the name in \`security\`.`,
161
+ });
162
+ }
163
+ return issues;
164
+ };
165
+
166
+ /**
167
+ * An operation's `in: querystring` parameter (OpenAPI 3.2: the whole query
168
+ * string as one value), which the parameter table, Try it, and the code
169
+ * samples don't handle yet, so it would drop out of all three without a sign.
170
+ */
171
+ const querystringIssue = (signature: string): SpecIssue => ({
172
+ code: "BLUME_OPENAPI_UNSUPPORTED",
173
+ message: `${signature} declares an \`in: querystring\` parameter, which OpenAPI 3.2 added and Blume doesn't render yet, so the page has no row or Try it input for it and the code samples leave the query string out.`,
174
+ suggestion:
175
+ "Describe the query string in the operation's `description` until Blume renders `querystring` parameters.",
176
+ });
177
+
178
+ /**
179
+ * A path item's `additionalOperations` (OpenAPI 3.2: methods beyond the ones
180
+ * a path item names directly, like `COPY`), which the extractor doesn't
181
+ * collect yet, so those operations would be missing without a sign.
182
+ */
183
+ const additionalOperationsIssue = (
184
+ label: string,
185
+ methods: string[]
186
+ ): SpecIssue => ({
187
+ code: "BLUME_OPENAPI_UNSUPPORTED",
188
+ message: `${label} declares \`additionalOperations\` (${methods.join(", ")}), which OpenAPI 3.2 added and Blume doesn't render yet, so those operations are missing from the reference.`,
189
+ suggestion:
190
+ "Document those operations on a page of their own until Blume renders `additionalOperations`.",
191
+ });
192
+
193
+ /**
194
+ * A root `x-webhooks` and no `webhooks`. It's the extension OpenAPI 3.0 tools
195
+ * read for webhooks, and upgrading a 3.0 spec renames it to `webhooks`; a spec
196
+ * already at 3.1 or later isn't upgraded, so it stays an extension and its
197
+ * webhooks would be missing without a sign.
198
+ */
199
+ const xWebhooksIssues = (document: ApiDocument): SpecIssue[] =>
200
+ "x-webhooks" in document && document.webhooks === undefined
201
+ ? [
202
+ {
203
+ code: "BLUME_OPENAPI_X_WEBHOOKS",
204
+ message:
205
+ "The spec declares its webhooks under `x-webhooks`, the extension OpenAPI 3.0 tools read. Blume reads it only from a 3.0 spec, which it upgrades, so these webhooks are missing from the reference.",
206
+ suggestion:
207
+ "Rename `x-webhooks` to `webhooks`, the field OpenAPI 3.1 added for them.",
208
+ },
209
+ ]
210
+ : [];
211
+
212
+ /**
213
+ * Check a parsed document for the mistakes above, and for the OpenAPI 3.2
214
+ * features Blume doesn't render yet. `$ref` path items are skipped: the
215
+ * extractor already reports them as missing from the reference.
216
+ */
217
+ export const specIssues = (document: ApiDocument): SpecIssue[] => {
218
+ const issues: SpecIssue[] = [...xWebhooksIssues(document)];
219
+ // Scheme name -> the operations whose own `security` lists it.
220
+ const requirers = new Map<string, string[]>();
221
+ const visit = (name: string, item: PathItem, webhook: boolean): void => {
222
+ if (!isObject(item) || "$ref" in item) {
223
+ return;
224
+ }
225
+ const additional = isObject(item.additionalOperations)
226
+ ? Object.keys(item.additionalOperations)
227
+ : [];
228
+ if (additional.length > 0) {
229
+ issues.push(
230
+ additionalOperationsIssue(
231
+ webhook ? `Webhook "${name}"` : `Path "${name}"`,
232
+ additional
233
+ )
234
+ );
235
+ }
236
+ for (const method of HTTP_METHODS) {
237
+ const operation = item[method];
238
+ if (!isObject(operation)) {
239
+ continue;
240
+ }
241
+ const signature = operationLabel(name, method, webhook);
242
+ for (const scheme of requiredSchemes(operation.security)) {
243
+ requirers.set(scheme, [...(requirers.get(scheme) ?? []), signature]);
244
+ }
245
+ const parameters = parametersOf(document, item, operation);
246
+ // A webhook is keyed by its name, not a path: it has no template.
247
+ if (!webhook) {
248
+ issues.push(
249
+ ...pathParameterIssues(
250
+ signature,
251
+ name,
252
+ new Set(
253
+ parameters
254
+ .filter((parameter) => parameter.in === "path")
255
+ .map((parameter) => parameter.name)
256
+ .filter(isName)
257
+ )
258
+ )
259
+ );
260
+ }
261
+ if (parameters.some((parameter) => parameter.in === "querystring")) {
262
+ issues.push(querystringIssue(signature));
263
+ }
264
+ }
265
+ };
266
+ for (const [path, item] of Object.entries(document.paths ?? {})) {
267
+ visit(path, item, false);
268
+ }
269
+ for (const [name, item] of Object.entries(document.webhooks ?? {})) {
270
+ visit(name, item, true);
271
+ }
272
+ return [...issues, ...securitySchemeIssues(document, requirers)];
273
+ };
@@ -26,6 +26,7 @@ import {
26
26
  parse,
27
27
  print,
28
28
  specifiedDirectives,
29
+ valueFromASTUntyped,
29
30
  visit,
30
31
  } from "graphql";
31
32
 
@@ -34,6 +35,7 @@ import type {
34
35
  GraphqlEnumValue,
35
36
  GraphqlField as ModelField,
36
37
  GraphqlInputValue,
38
+ GraphqlJsonValue,
37
39
  GraphqlTypeDef,
38
40
  GraphqlTypeRef,
39
41
  } from "./graphql.ts";
@@ -68,6 +70,21 @@ const defaultLiteral = (
68
70
  return literal ? print(literal) : undefined;
69
71
  };
70
72
 
73
+ /**
74
+ * The same default as the JSON a client sends in `variables`, which the
75
+ * example variables start from.
76
+ */
77
+ const defaultJson = (
78
+ input: GraphQLArgument | GraphQLInputField
79
+ ): GraphqlJsonValue | undefined => {
80
+ const literal = input.default?.literal;
81
+ // SAFETY: a const literal has no variables, so it lowers to JSON values
82
+ // only: numbers, strings, booleans, null, enum names, lists and objects.
83
+ return literal
84
+ ? (valueFromASTUntyped(literal) as GraphqlJsonValue)
85
+ : undefined;
86
+ };
87
+
71
88
  const inputValue = (
72
89
  input: GraphQLArgument | GraphQLInputField
73
90
  ): GraphqlInputValue => {
@@ -80,6 +97,10 @@ const inputValue = (
80
97
  if (printed !== undefined) {
81
98
  value.default = printed;
82
99
  }
100
+ const json = defaultJson(input);
101
+ if (json !== undefined) {
102
+ value.defaultValue = json;
103
+ }
83
104
  // `deprecationReason` is null on non-deprecated members in some builds;
84
105
  // absent means "not deprecated" downstream, so both collapse to absent.
85
106
  if (
@@ -58,6 +58,15 @@ export interface GraphqlTypeRef {
58
58
  name: string;
59
59
  }
60
60
 
61
+ /** A GraphQL input value as JSON carries it in `variables` (enums by name). */
62
+ export type GraphqlJsonValue =
63
+ | string
64
+ | number
65
+ | boolean
66
+ | null
67
+ | GraphqlJsonValue[]
68
+ | { [key: string]: GraphqlJsonValue };
69
+
61
70
  /** An argument or input-object field. */
62
71
  export interface GraphqlInputValue {
63
72
  name: string;
@@ -65,6 +74,8 @@ export interface GraphqlInputValue {
65
74
  type: GraphqlTypeRef;
66
75
  /** Default value printed as a GraphQL literal (`10`, `"asc"`, `[1, 2]`). */
67
76
  default?: string;
77
+ /** The same default as JSON, for the example variables. */
78
+ defaultValue?: GraphqlJsonValue;
68
79
  deprecationReason?: string;
69
80
  }
70
81
 
@@ -1,5 +1,6 @@
1
- import type { Document, OperationObject } from "@scalar/openapi-types/3.1";
1
+ import type { Document, OperationObject } from "@scalar/openapi-types/3.2";
2
2
 
3
+ import type { GraphqlAuthOptions } from "../reference/options.ts";
3
4
  import type {
4
5
  AsyncApiAction,
5
6
  AsyncApiDocument,
@@ -26,10 +27,18 @@ export { slugify } from "./references.ts";
26
27
  * per-operation route so it becomes a first-class Blume page.
27
28
  */
28
29
 
29
- /** A normalized OpenAPI 3.1 document, internal `$ref`s intact. */
30
+ /**
31
+ * A normalized OpenAPI document, internal `$ref`s intact. Typed as 3.2, which
32
+ * is backward compatible with 3.1, so one type covers both the upgraded 3.1
33
+ * documents and the 3.2 ones read as written.
34
+ */
30
35
  export type ApiDocument = Document;
31
36
 
32
- /** The HTTP methods an OpenAPI path item may declare, in spec order. */
37
+ /**
38
+ * The HTTP methods an OpenAPI path item may declare, in spec order. `query`
39
+ * is OpenAPI 3.2's (the QUERY method: a safe request that carries a body); a
40
+ * 3.1 path item can't declare it, so listing it changes nothing there.
41
+ */
33
42
  export const HTTP_METHODS = [
34
43
  "get",
35
44
  "put",
@@ -39,6 +48,7 @@ export const HTTP_METHODS = [
39
48
  "head",
40
49
  "patch",
41
50
  "trace",
51
+ "query",
42
52
  ] as const;
43
53
 
44
54
  export type HttpMethod = (typeof HTTP_METHODS)[number];
@@ -46,6 +56,9 @@ export type HttpMethod = (typeof HTTP_METHODS)[number];
46
56
  /** Group used for operations that declare no tag. */
47
57
  const UNTAGGED = "Operations";
48
58
 
59
+ /** Group used for webhooks that declare no tag. */
60
+ const UNTAGGED_WEBHOOKS = "Webhooks";
61
+
49
62
  /** A lower-case letter or digit followed by a capital: `addPet`, `v2List`. */
50
63
  const CASE_BOUNDARY = /(?<before>[\p{Ll}\p{N}])(?<capital>\p{Lu})/gu;
51
64
  /** The last capital of an acronym before a capitalized word: `HTTPResponse`. */
@@ -101,6 +114,12 @@ export interface ApiOperationRef {
101
114
  deprecated: boolean;
102
115
  /** The channel the operation acts on (AsyncAPI only). */
103
116
  channelId?: string;
117
+ /**
118
+ * An OpenAPI 3.1 webhook: a request the API sends to the reader's endpoint
119
+ * rather than one it serves. `path` then holds the webhook's name, the key
120
+ * it has under the document's `webhooks`.
121
+ */
122
+ webhook?: true;
104
123
  }
105
124
 
106
125
  /**
@@ -131,11 +150,13 @@ export interface ApiSpecData {
131
150
  * (GraphQL only; OpenAPI documents carry their servers in the document).
132
151
  */
133
152
  endpoint?: string;
153
+ /** How the GraphQL endpoint authenticates (GraphQL only). */
154
+ auth?: GraphqlAuthOptions;
134
155
  /** Operations keyed by {@link ApiOperationRef.key}. */
135
156
  operations: Record<string, ApiOperationRef>;
136
157
  tags: ApiTagRef[];
137
- /** Code-sample languages to render per operation. */
138
- codeSamples: string[];
158
+ /** Code-sample languages to render per operation; `false` for none. */
159
+ codeSamples: string[] | false;
139
160
  /** Whether nested schema rows start expanded. */
140
161
  expandSchemas: boolean;
141
162
  /**
@@ -301,6 +322,11 @@ export const tagSlugger = (): ((name: string) => string) => {
301
322
  };
302
323
  };
303
324
 
325
+ /** One entry of a document's `paths` or `webhooks` map. */
326
+ type PathItemEntry =
327
+ | NonNullable<ApiDocument["paths"]>[string]
328
+ | NonNullable<ApiDocument["webhooks"]>[string];
329
+
304
330
  /** An operation before the collector assigns its unique key and route. */
305
331
  type CollectedOperation = Omit<ApiOperationRef, "route" | "tagSlug">;
306
332
 
@@ -386,10 +412,10 @@ export const operationCollector = (
386
412
 
387
413
  /**
388
414
  * Flatten a 3.1 document into a route-mapped operation list and its ordered
389
- * tags. Operations inherit the first tag they declare; keys are de-duplicated so
390
- * a repeated `operationId` still yields distinct routes. `warnings` reports
391
- * anything skipped (a `$ref` path item, webhooks), so missing operations
392
- * aren't silent.
415
+ * tags, webhooks included. Operations inherit the first tag they declare; keys
416
+ * are de-duplicated so a repeated `operationId` still yields distinct routes.
417
+ * `warnings` reports anything skipped (a `$ref` path item), so missing
418
+ * operations aren't silent.
393
419
  */
394
420
  export const extractOperations = (
395
421
  document: ApiDocument,
@@ -404,16 +430,24 @@ export const extractOperations = (
404
430
  );
405
431
  const collector = operationCollector(baseRoute, tagMeta);
406
432
 
407
- for (const [path, item] of Object.entries(document.paths ?? {})) {
433
+ // A path item's operations, filed under `name`: a path for `paths`, the
434
+ // webhook's key for `webhooks`.
435
+ const addPathItem = (
436
+ name: string,
437
+ item: PathItemEntry,
438
+ webhook: boolean
439
+ ): void => {
408
440
  // A parsed spec can carry a null path item despite the type; skip it.
409
441
  if (!item) {
410
- continue;
442
+ return;
411
443
  }
412
444
  if ("$ref" in item) {
413
445
  warnings.push(
414
- `Path "${path}" is a $ref to a shared path item; referenced path items are not resolved, so its operations are missing from the reference. Inline the path item under "paths" to render it.`
446
+ webhook
447
+ ? `Webhook "${name}" is a $ref to a shared path item; referenced path items are not resolved, so it is missing from the reference. Inline the path item under "webhooks" to render it.`
448
+ : `Path "${name}" is a $ref to a shared path item; referenced path items are not resolved, so its operations are missing from the reference. Inline the path item under "paths" to render it.`
415
449
  );
416
- continue;
450
+ return;
417
451
  }
418
452
  for (const method of HTTP_METHODS) {
419
453
  const operation = item[method];
@@ -421,26 +455,35 @@ export const extractOperations = (
421
455
  continue;
422
456
  }
423
457
  const operationId = specText(operation.operationId);
424
- collector.add({
458
+ const entry: CollectedOperation = {
425
459
  deprecated: operation.deprecated ?? false,
426
460
  description: specText(operation.description) ?? "",
427
- key: operationKey(method, path, operationId),
461
+ // A webhook without an operationId is keyed by its name, which is
462
+ // already an identifier (`newPet` -> `new-pet`).
463
+ key: operationKey(
464
+ method,
465
+ name,
466
+ operationId ?? (webhook ? name : undefined)
467
+ ),
428
468
  method,
429
469
  operationId,
430
- path,
470
+ path: name,
431
471
  summary: specText(operation.summary) ?? "",
432
- tag: specText(operation.tags?.[0]) ?? UNTAGGED,
433
- });
472
+ tag:
473
+ specText(operation.tags?.[0]) ??
474
+ (webhook ? UNTAGGED_WEBHOOKS : UNTAGGED),
475
+ };
476
+ collector.add(webhook ? { ...entry, webhook: true } : entry);
434
477
  }
435
- }
478
+ };
436
479
 
437
- // OpenAPI 3.1 webhooks (requests the API sends, not ones it serves) have no
438
- // page renderer; say so rather than dropping them silently.
439
- const webhooks = Object.keys(document.webhooks ?? {});
440
- if (webhooks.length > 0) {
441
- warnings.push(
442
- `The spec declares ${webhooks.length === 1 ? "a webhook" : `${webhooks.length} webhooks`} under "webhooks" (${webhooks.join(", ")}); webhooks aren't rendered, so they are missing from the reference.`
443
- );
480
+ for (const [path, item] of Object.entries(document.paths ?? {})) {
481
+ addPathItem(path, item, false);
482
+ }
483
+ // OpenAPI 3.1 webhooks: requests the API sends rather than serves. They
484
+ // follow the paths, so an untagged webhook group sits after the endpoints.
485
+ for (const [name, item] of Object.entries(document.webhooks ?? {})) {
486
+ addPathItem(name, item, true);
444
487
  }
445
488
 
446
489
  return { ...collector.finish(), warnings };
@@ -458,7 +501,9 @@ export const operationObject = (
458
501
  // (AsyncAPI documents go to `asyncApiOperationObject`), so the spec's
459
502
  // document is the OpenAPI shape.
460
503
  const document = spec.document as ApiDocument;
461
- const item = document.paths?.[ref.path];
504
+ const item = ref.webhook
505
+ ? document.webhooks?.[ref.path]
506
+ : document.paths?.[ref.path];
462
507
  const operation = method === undefined ? undefined : item?.[method];
463
508
  return isOperation(operation) ? operation : undefined;
464
509
  };