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
@@ -1,3 +1,4 @@
1
+ import { BlumeError } from "../../core/diagnostics.ts";
1
2
  import type { BlumeProject } from "../../core/project-graph.ts";
2
3
  import type { ResolvedSearchAdapter } from "../adapters/registry.ts";
3
4
  import { buildSearchDocuments, toSearchRecords } from "../documents.ts";
@@ -13,23 +14,49 @@ export interface SyncReporter {
13
14
  warn: (message: string) => void;
14
15
  }
15
16
 
17
+ /** A hosted adapter's build-time sync. */
18
+ interface HostedSync {
19
+ /** The env var holding the admin key the sync reads. */
20
+ key: string;
21
+ /**
22
+ * Whether the sync is set up to run: its admin key is set, and for Orama
23
+ * Cloud, the `indexId` that turns the sync on.
24
+ */
25
+ ready: boolean;
26
+ /** The upload, closed over the adapter's options. */
27
+ run: (records: SearchRecord[]) => Promise<void>;
28
+ }
29
+
16
30
  /**
17
- * The sync a hosted adapter runs after a build, closed over its options, or
18
- * `null` for adapters with no in-process sync (static and Pagefind indexes are
19
- * built locally; Mixedbread syncs out-of-band via the `mxbai` CLI).
31
+ * The sync a hosted adapter runs after a build, or `null` for adapters with no
32
+ * in-process sync (static and Pagefind indexes are built locally; Mixedbread
33
+ * syncs out-of-band via the `mxbai` CLI).
20
34
  */
21
- const searchSync = (
22
- provider: ResolvedSearchAdapter
23
- ): ((records: SearchRecord[]) => Promise<void>) | null => {
35
+ const searchSync = (provider: ResolvedSearchAdapter): HostedSync | null => {
24
36
  switch (provider.kind) {
25
37
  case "algolia": {
26
- return (records) => syncAlgolia(records, provider.options);
38
+ const key = "ALGOLIA_ADMIN_API_KEY";
39
+ return {
40
+ key,
41
+ ready: Boolean(process.env[key]),
42
+ run: (records) => syncAlgolia(records, provider.options),
43
+ };
27
44
  }
28
45
  case "orama-cloud": {
29
- return (records) => syncOramaCloud(records, provider.options);
46
+ const key = "ORAMA_PRIVATE_API_KEY";
47
+ return {
48
+ key,
49
+ ready: Boolean(process.env[key] && provider.options.indexId),
50
+ run: (records) => syncOramaCloud(records, provider.options),
51
+ };
30
52
  }
31
53
  case "typesense": {
32
- return (records) => syncTypesense(records, provider.options);
54
+ const key = "TYPESENSE_ADMIN_API_KEY";
55
+ return {
56
+ key,
57
+ ready: Boolean(process.env[key]),
58
+ run: (records) => syncTypesense(records, provider.options),
59
+ };
33
60
  }
34
61
  default: {
35
62
  return null;
@@ -41,7 +68,9 @@ const searchSync = (
41
68
  * After a build, upload the per-page records to the configured hosted adapter.
42
69
  * Reads secret admin keys from the environment; if a key (or option) is
43
70
  * missing the sync is skipped with a warning rather than failing the build —
44
- * CI may sync in a separate step.
71
+ * a local build has no secrets, and CI may sync in a separate step. Once the
72
+ * sync is set up, a failure fails the build (`BLUME_SEARCH_SYNC_FAILED`):
73
+ * the site would otherwise deploy against an index this build didn't update.
45
74
  */
46
75
  export const syncSearchProvider = async (
47
76
  project: BlumeProject,
@@ -57,11 +86,21 @@ export const syncSearchProvider = async (
57
86
  reporter.start(`Syncing ${records.length} record(s) to ${provider.kind}`);
58
87
 
59
88
  try {
60
- await sync(records);
89
+ await sync.run(records);
61
90
  reporter.success(`Synced ${records.length} record(s) to ${provider.kind}`);
62
91
  } catch (error) {
63
92
  // SAFETY: the three sync clients surface network/auth failures as Error
64
- // instances; the message is read only to annotate the skip warning.
65
- reporter.warn(`Search sync skipped: ${(error as Error).message}`);
93
+ // instances; the message is read only to annotate the warning or error.
94
+ const { message } = error as Error;
95
+ if (!sync.ready) {
96
+ reporter.warn(`Search sync skipped: ${message}`);
97
+ return;
98
+ }
99
+ throw new BlumeError({
100
+ code: "BLUME_SEARCH_SYNC_FAILED",
101
+ message: `Search sync to ${provider.kind} failed: ${message}`,
102
+ severity: "error",
103
+ suggestion: `Check ${sync.key} and the adapter's options, or unset ${sync.key} to build without syncing.`,
104
+ });
66
105
  }
67
106
  };
@@ -31,9 +31,12 @@ export const syncOramaCloud = async (
31
31
  const index = manager.index(config.indexId);
32
32
  await index.snapshot(
33
33
  records.map((record) => ({
34
+ // The dialog multiplies each hit's score by it (search.boost).
35
+ boost: record.boost,
34
36
  content: record.content,
35
37
  description: record.description,
36
38
  id: record._id,
39
+ keywords: record.keywords ?? [],
37
40
  // Carried so an i18n site can filter hosted results per language.
38
41
  locale: record.locale,
39
42
  tag: record.tag,
@@ -7,17 +7,44 @@ import type { SearchRecord } from "../documents.ts";
7
7
  /** The adapter options the sync reads (the public `apiKey` is never used). */
8
8
  export type TypesenseSyncConfig = Pick<
9
9
  TypesenseOptions,
10
- "collection" | "host" | "port" | "protocol"
10
+ "collection" | "host" | "locale" | "port" | "protocol"
11
11
  >;
12
12
 
13
+ type TypesenseClient = InstanceType<typeof TypesenseSdk.Client>;
14
+
15
+ /**
16
+ * The collection an alias points at, or `undefined` when there is no such
17
+ * alias. Only a 404 means that: any other failure (a key that can't read
18
+ * aliases, an outage) throws before the sync has touched anything.
19
+ */
20
+ const aliasTarget = async (
21
+ client: TypesenseClient,
22
+ alias: string,
23
+ errors: typeof TypesenseSdk.Errors
24
+ ): Promise<string | undefined> => {
25
+ try {
26
+ const { collection_name: target } = await client.aliases(alias).retrieve();
27
+ return target;
28
+ } catch (error) {
29
+ if (error instanceof errors.ObjectNotFound) {
30
+ return undefined;
31
+ }
32
+ throw error;
33
+ }
34
+ };
35
+
13
36
  /**
14
- * Import the search records into a Typesense collection. Uses the admin key
15
- * from `TYPESENSE_ADMIN_API_KEY`. Throws on a missing key so the caller can
16
- * warn.
37
+ * Import the search records into Typesense. Uses the admin key from
38
+ * `TYPESENSE_ADMIN_API_KEY`. Throws on a missing key so the caller can warn.
17
39
  *
18
- * The collection is dropped and recreated on each sync so that pages deleted or
19
- * renamed since the last sync don't linger as stale search hits that 404 when
20
- * clicked (an upsert alone never removes them).
40
+ * `collection` names an alias. Each sync imports every record into a new
41
+ * collection (`<collection>_<timestamp>`), points the alias at it, then drops
42
+ * the collection it replaced: searches keep reading the previous collection
43
+ * until the new one is complete, pages deleted or renamed since the last sync
44
+ * don't linger as stale hits that 404 when clicked, and a sync that fails
45
+ * leaves the previous collection serving. A collection named `collection`
46
+ * itself, from a sync before the alias existed, is dropped just before the
47
+ * alias takes its name, since Typesense won't let the two share one.
21
48
  */
22
49
  export const syncTypesense = async (
23
50
  records: SearchRecord[],
@@ -29,7 +56,7 @@ export const syncTypesense = async (
29
56
  }
30
57
  // `require`, not `import()`: this runs in `astro:build:done` (see
31
58
  // `core/node-require.ts`).
32
- const { Client }: typeof TypesenseSdk = nodeRequire("typesense");
59
+ const { Client, Errors }: typeof TypesenseSdk = nodeRequire("typesense");
33
60
  const client = new Client({
34
61
  apiKey: adminKey,
35
62
  nodes: [
@@ -41,43 +68,66 @@ export const syncTypesense = async (
41
68
  ],
42
69
  });
43
70
 
44
- const collection = client.collections(config.collection);
45
- let exists = true;
46
- try {
47
- await collection.retrieve();
48
- } catch {
49
- exists = false;
50
- }
51
- if (exists) {
52
- await collection.delete();
53
- }
71
+ const alias = config.collection;
72
+ const previous = await aliasTarget(client, alias, Errors);
73
+ const name = `${alias}_${Date.now()}`;
74
+ // The searched text fields, tokenized for `locale` when the site sets one.
75
+ const text = config.locale ? { locale: config.locale } : {};
54
76
  await client.collections().create({
55
77
  fields: [
56
- { name: "title", type: "string" },
57
- { name: "description", optional: true, type: "string" },
58
- { name: "content", type: "string" },
78
+ { name: "title", type: "string", ...text },
79
+ { name: "description", optional: true, type: "string", ...text },
80
+ { name: "content", type: "string", ...text },
59
81
  { name: "url", type: "string" },
82
+ { name: "keywords", optional: true, type: "string[]", ...text },
83
+ // The dialog sorts close matches by it (search.boost, 1 by default).
84
+ { name: "boost", type: "float" },
60
85
  { facet: true, name: "tag", optional: true, type: "string" },
61
86
  // Carried as facets so hosted results can filter per language and per
62
87
  // docs version (the SearchRecord contract; current docs = "current").
63
88
  { facet: true, name: "locale", optional: true, type: "string" },
64
89
  { facet: true, name: "version", optional: true, type: "string" },
65
90
  ],
66
- name: config.collection,
91
+ name,
67
92
  });
68
93
 
69
94
  const documents = records.map((record) => ({
95
+ boost: record.boost,
70
96
  content: record.content,
71
97
  description: record.description,
72
98
  id: record._id,
99
+ keywords: record.keywords ?? [],
73
100
  locale: record.locale,
74
101
  tag: record.tag,
75
102
  title: record.title,
76
103
  url: record.url,
77
104
  version: record.version,
78
105
  }));
79
- await client
80
- .collections(config.collection)
81
- .documents()
82
- .import(documents, { action: "upsert" });
106
+ try {
107
+ await client
108
+ .collections(name)
109
+ .documents()
110
+ .import(documents, { action: "upsert" });
111
+ } catch (error) {
112
+ // Nothing reads the new collection yet: drop it, and the alias keeps
113
+ // serving the last complete sync.
114
+ await client.collections(name).delete();
115
+ throw error;
116
+ }
117
+
118
+ if (previous === undefined) {
119
+ let legacy = true;
120
+ try {
121
+ await client.collections(alias).retrieve();
122
+ } catch {
123
+ legacy = false;
124
+ }
125
+ if (legacy) {
126
+ await client.collections(alias).delete();
127
+ }
128
+ }
129
+ await client.aliases().upsert(alias, { collection_name: name });
130
+ if (previous !== undefined) {
131
+ await client.collections(previous).delete();
132
+ }
83
133
  };
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Site-wide meta tags (`seo.metatags`): tags written into every page's head,
3
+ * for what Blume has no setting of its own for, such as site-verification
4
+ * tokens, `theme-color`, or an app banner. The tags Blume writes itself are
5
+ * refused, each pointing at the setting that controls it, so a page never
6
+ * carries two values for one tag.
7
+ */
8
+
9
+ const IMAGE =
10
+ "`seo.og` for the generated cards, or `seo.image` in a page's frontmatter";
11
+ const TITLE = "`title`, or `seo.title` in a page's frontmatter";
12
+ const DESCRIPTION =
13
+ "`description` in a page's frontmatter or the config, or a page's `seo.description`";
14
+ const FROM_PAGE = "Blume sets it from each page's type and dates";
15
+
16
+ /** The tags Blume writes itself, by lowercase name, and what sets each. */
17
+ const OWNED = new Map([
18
+ ["article:modified_time", FROM_PAGE],
19
+ ["article:published_time", FROM_PAGE],
20
+ ["description", DESCRIPTION],
21
+ ["og:description", DESCRIPTION],
22
+ ["og:site_name", "the config's `title`"],
23
+ ["og:title", TITLE],
24
+ ["og:type", FROM_PAGE],
25
+ ["og:url", "`deployment.site`, which sets each page's canonical URL"],
26
+ ["robots", "`seo.noindex` in a page's frontmatter"],
27
+ ["twitter:card", "Blume sets it from each page's image"],
28
+ ["twitter:creator", "`seo.x.creator` in the config or a page's frontmatter"],
29
+ ["twitter:description", DESCRIPTION],
30
+ ["twitter:site", "`seo.x.handle`"],
31
+ ["twitter:title", TITLE],
32
+ ["viewport", "Blume sets it for every page"],
33
+ ]);
34
+
35
+ /** `og:image` and `twitter:image`, and their sub-properties. */
36
+ const IMAGE_TAG = /^(?:og|twitter):image(?::|$)/u;
37
+
38
+ /**
39
+ * What sets a tag Blume writes itself, or `undefined` for a tag the site can
40
+ * add.
41
+ */
42
+ export const ownedMetatag = (name: string): string | undefined => {
43
+ const key = name.trim().toLowerCase();
44
+ return IMAGE_TAG.test(key) ? IMAGE : OWNED.get(key);
45
+ };
46
+
47
+ /**
48
+ * The Open Graph families, which the protocol names with `property`; every
49
+ * other tag takes `name`.
50
+ */
51
+ const PROPERTY_TAG =
52
+ /^(?:og|fb|article|book|profile|music|video|al|product):/iu;
53
+
54
+ /** One site-wide tag, as its `<meta>` element's attributes. */
55
+ export interface MetatagAttributes {
56
+ content: string;
57
+ name?: string;
58
+ property?: string;
59
+ }
60
+
61
+ /** The site's `seo.metatags` as `<meta>` attributes, in the order written. */
62
+ export const metatagAttributes = (
63
+ tags?: Readonly<Record<string, string>> | null
64
+ ): MetatagAttributes[] =>
65
+ Object.entries(tags ?? {}).map(([name, content]) =>
66
+ PROPERTY_TAG.test(name) ? { content, property: name } : { content, name }
67
+ );
@@ -21,10 +21,20 @@ export interface ContentfulOptions extends SharedSourceOptions {
21
21
  * / `sys.updatedAt`.
22
22
  */
23
23
  fields?: SourceFieldMap;
24
+ /**
25
+ * Delivery API host name. Defaults to `cdn.contentful.com`; a space with
26
+ * EU data residency reads from `cdn.eu.contentful.com`.
27
+ */
28
+ host?: string;
24
29
  /** Locale code to fetch; omit for the space's default locale. */
25
30
  locale?: string;
26
31
  /** Extra query parameters for the entries request (`"fields.section": "sdk"`). */
27
32
  params?: Record<string, string>;
33
+ /**
34
+ * Preview API host name for `--preview`. Defaults to
35
+ * `preview.contentful.com` (`preview.eu.contentful.com` in the EU).
36
+ */
37
+ previewHost?: string;
28
38
  /** Space id. */
29
39
  space: string;
30
40
  }
@@ -33,8 +43,10 @@ export const contentfulOptionsSchema = sharedSourceOptionsSchema.extend({
33
43
  contentType: z.string(),
34
44
  environment: z.string().optional(),
35
45
  fields: sourceFieldMapSchema.optional(),
46
+ host: z.string().optional(),
36
47
  locale: z.string().optional(),
37
48
  params: queryParamsSchema.optional(),
49
+ previewHost: z.string().optional(),
38
50
  space: z.string(),
39
51
  });
40
52
 
@@ -7,7 +7,12 @@ import { sharedSourceOptionsSchema } from "./shared.ts";
7
7
 
8
8
  /** Options for {@link githubReleases}. */
9
9
  export interface GithubReleasesOptions extends SharedSourceOptions {
10
- /** Include draft releases (needs a token with repo write access). */
10
+ /**
11
+ * The GitHub REST API base URL. Defaults to `https://api.github.com`; a
12
+ * GitHub Enterprise Server's is `https://<host>/api/v3`.
13
+ */
14
+ baseUrl?: string;
15
+ /** Include draft releases, tagged `Draft` (needs a token with repo write access). */
11
16
  drafts?: boolean;
12
17
  /** Cap the number of releases materialized, newest-first. Defaults to 100. */
13
18
  limit?: number;
@@ -20,6 +25,7 @@ export interface GithubReleasesOptions extends SharedSourceOptions {
20
25
  }
21
26
 
22
27
  export const githubReleasesOptionsSchema = sharedSourceOptionsSchema.extend({
28
+ baseUrl: z.string().optional(),
23
29
  drafts: z.boolean().optional(),
24
30
  limit: z.number().positive().optional(),
25
31
  owner: z.string(),
@@ -33,6 +33,8 @@ export interface SourceFieldMap {
33
33
  description?: string;
34
34
  /** Field holding the last-modified date. */
35
35
  lastModified?: string;
36
+ /** Field holding the sidebar order (a number). No default: unset, none is read. */
37
+ order?: string;
36
38
  /** Field holding the page slug. */
37
39
  slug?: string;
38
40
  /** Field holding the page title. */
@@ -44,6 +46,7 @@ export const sourceFieldMapSchema = z.strictObject({
44
46
  body: z.string().optional(),
45
47
  description: z.string().optional(),
46
48
  lastModified: z.string().optional(),
49
+ order: z.string().optional(),
47
50
  slug: z.string().optional(),
48
51
  title: z.string().optional(),
49
52
  });
@@ -19,6 +19,7 @@ interface ChromeIconSet {
19
19
 
20
20
  export const chromeIcons: ChromeIconSet = {
21
21
  check: '<path d="M20 6 9 17l-5-5"/>',
22
+ "chevron-down": '<path d="m6 9 6 6 6-6"/>',
22
23
  copy: '<rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/>',
23
24
  file: '<path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/>',
24
25
  search: '<circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>',