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,7 +1,9 @@
1
1
  import { join } from "pathe";
2
2
 
3
+ import { BlumeError } from "../diagnostics.ts";
3
4
  import matter from "../frontmatter.ts";
4
5
  import { neutralizeUnsafeLinks } from "../safe-links.ts";
6
+ import type { Diagnostic } from "../types.ts";
5
7
  import {
6
8
  hashText,
7
9
  loadWithCache,
@@ -9,7 +11,7 @@ import {
9
11
  snapshotCache,
10
12
  } from "./cache.ts";
11
13
  import type { JsonObject, JsonValue } from "./json.ts";
12
- import { asString, getPath, isStringValue } from "./json.ts";
14
+ import { asNumber, asString, getPath, isStringValue } from "./json.ts";
13
15
  import { slugify, slugifyPath } from "./normalize.ts";
14
16
  import type {
15
17
  ContentSource,
@@ -27,8 +29,15 @@ export interface RemoteSourceOptions {
27
29
  * offline warning.
28
30
  */
29
31
  assertConfigured?: () => void;
30
- /** Pull every entry from the API; called on refresh and on each poll. */
31
- fetchEntries: () => Promise<SourceEntry[]>;
32
+ /**
33
+ * Pull every entry from the API; called on refresh and on each poll.
34
+ * `warn` reports a problem with the content itself (an embed the API
35
+ * couldn't resolve, a node with no Markdown), which the load returns
36
+ * beside the entries; a load served from the snapshot repeats none.
37
+ */
38
+ fetchEntries: (
39
+ warn: (diagnostic: Diagnostic) => void
40
+ ) => Promise<SourceEntry[]>;
32
41
  name: string;
33
42
  /** Opt-in dev polling interval (seconds); omit to freeze for the session. */
34
43
  pollInterval?: number;
@@ -56,14 +65,24 @@ export const remoteSource = (
56
65
  refresh = ctx?.refresh ?? true
57
66
  ): Promise<SourceLoadResult> => {
58
67
  options.assertConfigured?.();
68
+ // Set only once a fetch succeeds, so a failed one that falls back to the
69
+ // snapshot reports nothing about pages it never delivered.
70
+ let warnings: Diagnostic[] = [];
59
71
  const result = await loadWithCache(
60
72
  options.name,
61
73
  cache,
62
- options.fetchEntries,
74
+ async () => {
75
+ const found: Diagnostic[] = [];
76
+ const entries = await options.fetchEntries((diagnostic) => {
77
+ found.push(diagnostic);
78
+ });
79
+ warnings = found;
80
+ return entries;
81
+ },
63
82
  refresh
64
83
  );
65
84
  snapshot = new Map(result.entries.map((entry) => [entry.ref, entry]));
66
- return result;
85
+ return { ...result, diagnostics: [...result.diagnostics, ...warnings] };
67
86
  };
68
87
 
69
88
  const read = async (ref: string): Promise<string> => {
@@ -96,6 +115,7 @@ export const remoteSource = (
96
115
  export interface RemoteFrontmatter {
97
116
  description?: string;
98
117
  draft?: boolean;
118
+ sidebar?: { order: number };
99
119
  title?: string;
100
120
  }
101
121
 
@@ -124,6 +144,20 @@ export const stagedEntry = (
124
144
  };
125
145
  };
126
146
 
147
+ /**
148
+ * The error a source throws before its first request when the token its API
149
+ * always requires is unset (Notion, Contentful's Delivery API). Sent without
150
+ * one, the request could only fail, and the build would report the API's
151
+ * wording as a fetch failure instead of the variable to set.
152
+ */
153
+ export const missingSecretError = (name: string, env: string): BlumeError =>
154
+ new BlumeError({
155
+ code: "BLUME_MISSING_SECRET",
156
+ message: `Source "${name}" needs ${env}, which is not set.`,
157
+ severity: "error",
158
+ suggestion: `Set ${env} in .env.local for local dev, or in your host's environment for production.`,
159
+ });
160
+
127
161
  /** How a source calls its CMS: the API's auth headers and an injectable fetch. */
128
162
  export interface RestClient {
129
163
  /** Injected for tests; defaults to the global `fetch`. */
@@ -183,31 +217,50 @@ export interface RemoteFieldMap {
183
217
  description?: string;
184
218
  /** Field holding the last-modified ISO date. */
185
219
  lastModified?: string;
220
+ /** Field holding the sidebar order (a number); no default. */
221
+ order?: string;
186
222
  /** Field holding the route slug. */
187
223
  slug?: string;
188
224
  /** Field holding the page title. */
189
225
  title?: string;
190
226
  }
191
227
 
228
+ /** A field map with its defaults filled in; `order` is read only when set. */
229
+ export type RemoteFields = Required<Omit<RemoteFieldMap, "order">> &
230
+ Pick<RemoteFieldMap, "order">;
231
+
232
+ /**
233
+ * The slug a document's staged entry is named by. It falls back to the
234
+ * document's id when the slug field is missing or slugifies to nothing (pure
235
+ * punctuation), so distinct documents never collapse onto one
236
+ * `untitled.md`; a slashed slug keeps its segments.
237
+ */
238
+ export const documentSlug = (
239
+ doc: JsonObject,
240
+ slugField: string,
241
+ id: string
242
+ ): string =>
243
+ slugifyPath(asString(getPath(doc, slugField)) ?? id) ||
244
+ slugify(id) ||
245
+ "untitled";
246
+
192
247
  /**
193
- * Map a document to a staged entry. The slug falls back to the document's id
194
- * when the slug field is missing or slugifies to nothing (pure punctuation),
195
- * so distinct documents never collapse onto one `untitled.md`; a slashed
196
- * slug keeps its segments. A string body is Markdown and passes through as
197
- * `.md`, its unsafe links reduced to their labels; any other shape goes to
198
- * the CMS's lowerer, and is written as `.mdx`
199
- * when `lowersToMdx` (the source has serializers, see `writesMdx`).
248
+ * Map a document to a staged entry named by its {@link documentSlug}. A
249
+ * number in the `order` field, when one is mapped, becomes the page's
250
+ * sidebar order. A string body is Markdown and passes through as `.md`, its
251
+ * unsafe links reduced to their labels; any other shape goes to the CMS's
252
+ * lowerer, and is written as `.mdx` when `lowersToMdx` (the source has
253
+ * serializers, see `writesMdx`).
200
254
  */
201
255
  export const documentEntry = (
202
256
  doc: JsonObject,
203
- fields: Required<RemoteFieldMap>,
257
+ fields: RemoteFields,
204
258
  id: string,
205
259
  lower: (body: JsonValue) => string,
206
260
  draft = false,
207
261
  lowersToMdx = false
208
262
  ): SourceEntry => {
209
- const slugValue = asString(getPath(doc, fields.slug)) ?? id;
210
- const slug = slugifyPath(slugValue) || slugify(id) || "untitled";
263
+ const slug = documentSlug(doc, fields.slug, id);
211
264
  const data: RemoteFrontmatter = {};
212
265
  const title = asString(getPath(doc, fields.title));
213
266
  const description = asString(getPath(doc, fields.description));
@@ -220,6 +273,10 @@ export const documentEntry = (
220
273
  if (draft) {
221
274
  data.draft = true;
222
275
  }
276
+ const order = fields.order ? asNumber(getPath(doc, fields.order)) : undefined;
277
+ if (order !== undefined) {
278
+ data.sidebar = { order };
279
+ }
223
280
  const body = getPath(doc, fields.body);
224
281
  let markdown = "";
225
282
  let format: "md" | "mdx" = "md";
@@ -138,7 +138,17 @@ const buildSource = (
138
138
  return notionSource({ ...adapter.options, name }, ctx());
139
139
  }
140
140
  case "contentful": {
141
- return contentfulSource({ ...adapter.options, name }, ctx());
141
+ // i18n and versions place an entry hyperlink's route as they do the
142
+ // linked entry's page.
143
+ return contentfulSource(
144
+ {
145
+ ...adapter.options,
146
+ i18n: config.i18n,
147
+ name,
148
+ versions: config.versions,
149
+ },
150
+ ctx()
151
+ );
142
152
  }
143
153
  case "payload": {
144
154
  return payloadSource({ ...adapter.options, name }, ctx());
@@ -3,6 +3,8 @@ import { join } from "pathe";
3
3
  import { BlumeError } from "../diagnostics.ts";
4
4
  import matter from "../frontmatter.ts";
5
5
  import { nodeRequire } from "../node-require.ts";
6
+ import { neutralizeUnsafeLinks } from "../safe-links.ts";
7
+ import type { Diagnostic } from "../types.ts";
6
8
  import {
7
9
  hashText,
8
10
  loadWithCache,
@@ -10,7 +12,7 @@ import {
10
12
  snapshotCache,
11
13
  } from "./cache.ts";
12
14
  import type { JsonObject } from "./json.ts";
13
- import { asString, getPath } from "./json.ts";
15
+ import { asString, getPath, isStringValue } from "./json.ts";
14
16
  import { writesMdx } from "./lower.ts";
15
17
  import { slugify, slugifyPath } from "./normalize.ts";
16
18
  import { portableTextToMarkdown } from "./portable-text.ts";
@@ -35,7 +37,7 @@ export interface SanityFieldMap {
35
37
  description?: string;
36
38
  /** Route slug (dot path); default `slug.current`. */
37
39
  slug?: string;
38
- /** Portable Text body field; default `body`. */
40
+ /** Body field, Portable Text or a Markdown string; default `body`. */
39
41
  body?: string;
40
42
  /** Last-modified ISO date; default `_updatedAt`. */
41
43
  lastModified?: string;
@@ -172,29 +174,32 @@ export const sanitySource = (
172
174
  data.description = description;
173
175
  }
174
176
 
175
- // SAFETY: the configured body field holds Portable Text blocks; a value of
176
- // any other shape fails the `Array.isArray` check below and yields an
177
- // empty body, and the serializer tolerates malformed blocks.
178
- const blocks = (getPath(doc, fields.body ?? "body") ??
179
- []) as PortableTextBlock[];
180
- const markdown = Array.isArray(blocks)
181
- ? portableTextToMarkdown(blocks, {
182
- imageUrl: (block) => {
183
- // SAFETY: `asset` on an image block is Sanity's asset reference
184
- // object; any other shape yields no `_ref` and the image is
185
- // skipped.
186
- const ref = (block.asset as { _ref?: string } | undefined)?._ref;
187
- return ref
188
- ? imageUrlFromRef(ref, options.projectId, options.dataset)
189
- : null;
190
- },
191
- serializers: options.serializers,
192
- })
193
- : "";
194
-
177
+ const body = getPath(doc, fields.body ?? "body");
178
+ let markdown = "";
195
179
  // Serializer output is MDX (components, directives), so a source with
196
- // serializers writes its entries as `.mdx`.
197
- const format = writesMdx(options.serializers) ? "mdx" : "md";
180
+ // serializers writes its Portable Text entries as `.mdx`.
181
+ let format: "md" | "mdx" = writesMdx(options.serializers) ? "mdx" : "md";
182
+ if (isStringValue(body)) {
183
+ // A Markdown field passes through as `.md`, its unsafe links reduced to
184
+ // their labels, as the other CMS sources do (see `documentEntry`).
185
+ markdown = neutralizeUnsafeLinks(`${body.trimEnd()}\n`);
186
+ format = "md";
187
+ } else if (Array.isArray(body)) {
188
+ // SAFETY: an array in the body field is Portable Text blocks; the
189
+ // serializer tolerates malformed blocks.
190
+ markdown = portableTextToMarkdown(body as PortableTextBlock[], {
191
+ imageUrl: (block) => {
192
+ // SAFETY: `asset` on an image block is Sanity's asset reference
193
+ // object; any other shape yields no `_ref` and the image is
194
+ // skipped.
195
+ const ref = (block.asset as { _ref?: string } | undefined)?._ref;
196
+ return ref
197
+ ? imageUrlFromRef(ref, options.projectId, options.dataset)
198
+ : null;
199
+ },
200
+ serializers: options.serializers,
201
+ });
202
+ }
198
203
  const raw = matter.stringify(markdown, data);
199
204
  return {
200
205
  body: { format, text: markdown },
@@ -211,18 +216,31 @@ export const sanitySource = (
211
216
  const load = async (
212
217
  refresh = ctx?.refresh ?? true
213
218
  ): Promise<SourceLoadResult> => {
219
+ const empty: Diagnostic[] = [];
214
220
  const result = await loadWithCache(
215
221
  options.name,
216
222
  cache,
217
223
  async () => {
218
224
  const client = resolveClient(options, ctx?.preview ?? false);
219
225
  const docs = await client.fetch<SanityDocument[]>(options.query);
226
+ // A private dataset answers a query without a token with no
227
+ // documents rather than an error, so an empty result is the only
228
+ // sign the token is missing.
229
+ if (docs.length === 0 && !(options.token ?? process.env.SANITY_TOKEN)) {
230
+ empty.push({
231
+ code: "BLUME_MISSING_SECRET",
232
+ message: `Source "${options.name}" found no documents, and SANITY_TOKEN is not set. A private dataset returns nothing to a query without a token.`,
233
+ severity: "warning",
234
+ suggestion:
235
+ "Set SANITY_TOKEN to a token with read access if the dataset is private.",
236
+ });
237
+ }
220
238
  return docs.map(toEntry);
221
239
  },
222
240
  refresh
223
241
  );
224
242
  snapshot = new Map(result.entries.map((entry) => [entry.ref, entry]));
225
- return result;
243
+ return { ...result, diagnostics: [...result.diagnostics, ...empty] };
226
244
  };
227
245
 
228
246
  const read = async (ref: string): Promise<string> => {
@@ -1,6 +1,6 @@
1
1
  import type { JsonObject } from "./json.ts";
2
2
  import { asNumber, asObject, asString, getPath, objectsIn } from "./json.ts";
3
- import type { RemoteFieldMap, RestClient } from "./remote.ts";
3
+ import type { RemoteFieldMap, RemoteFields, RestClient } from "./remote.ts";
4
4
  import {
5
5
  documentEntry,
6
6
  fetchJson,
@@ -38,7 +38,7 @@ export interface StrapiSourceOptions {
38
38
 
39
39
  const PAGE_SIZE = 100;
40
40
 
41
- const DEFAULT_FIELDS: Required<RemoteFieldMap> = {
41
+ const DEFAULT_FIELDS: RemoteFields = {
42
42
  body: "content",
43
43
  description: "description",
44
44
  lastModified: "updatedAt",
package/src/core/types.ts CHANGED
@@ -62,6 +62,10 @@ export interface PageLink {
62
62
  * only those go through the image pipeline; a plain link to the same path
63
63
  * resolves as a site route. */
64
64
  image?: boolean;
65
+ /** Set when the target is a lowercase `<a href>`, which ships as written:
66
+ * the Markdown pipeline neither resolves its relative path file-style nor
67
+ * mounts the base path on it, so it's checked the way a browser reads it. */
68
+ raw?: boolean;
65
69
  /** 1-based line number in the source file. */
66
70
  line: number;
67
71
  /** 1-based column of the target within the line. */
@@ -72,6 +76,18 @@ export interface PageLink {
72
76
  file?: string;
73
77
  }
74
78
 
79
+ /** A `<Component path="…">` in a page, located like a {@link PageLink}. */
80
+ export interface ExampleUse {
81
+ /** The example's key as written: its path under `examples/`, sans extension. */
82
+ path: string;
83
+ /** 1-based line number in the source file. */
84
+ line: number;
85
+ /** 1-based column of the `path` value within the line. */
86
+ column: number;
87
+ /** Absolute path of the included partial it was written in, if not the page. */
88
+ file?: string;
89
+ }
90
+
75
91
  /**
76
92
  * Resolved project paths. Computed once per CLI invocation and threaded
77
93
  * through the core pipeline.
@@ -194,6 +210,8 @@ export interface PageRecord {
194
210
  links: PageLink[];
195
211
  /** Capitalized JSX component tags used in the body (`.mdx` only). */
196
212
  componentsUsed?: string[];
213
+ /** The string `path` of each `<Component>` example in the body (`.mdx` only). */
214
+ examplesUsed?: ExampleUse[];
197
215
  /** Resolved "last updated" ISO date, when the feature is enabled. */
198
216
  lastModified?: string;
199
217
  /** Absolute paths of files this page `<include>`s, transitively. Drives the
@@ -316,7 +334,7 @@ export interface Navigation {
316
334
  cta?: HeaderAction | null;
317
335
  /** Pinned links shown above the sidebar sections, unscoped by tab. */
318
336
  featured: FeaturedLink[];
319
- /** Repo URL for the header link, or null when hidden (`navigation.repo`). */
337
+ /** Repo URL for the footer's GitHub link, or null when hidden (`navigation.repo`). */
320
338
  repoUrl?: string | null;
321
339
  /**
322
340
  * Where the header's brand link points in this locale: `logo.href` moved
@@ -5,6 +5,7 @@ export const ar: UIStringsOverride = {
5
5
  actions: {
6
6
  addToCursor: "إضافة إلى Cursor",
7
7
  addToVscode: "إضافة إلى VS Code",
8
+ askAboutCode: "اسأل عن هذه الشيفرة",
8
9
  connectMcp: "الاتصال بـ MCP",
9
10
  copied: "تم النسخ!",
10
11
  copyClaudeCode: "نسخ أمر Claude Code",
@@ -30,18 +31,34 @@ export const ar: UIStringsOverride = {
30
31
  copy: "نسخ المحادثة",
31
32
  empty: "اطرح سؤالاً حول الوثائق.",
32
33
  error: "عذراً، حدث خطأ ما.",
34
+ explainCode: "اشرح هذه الشيفرة.",
33
35
  label: "اطرح سؤالاً",
36
+ open: "فتح المساعد",
34
37
  placeholder: "اطرح سؤالاً…",
38
+ rateLimited: "لقد طرحت الكثير من الأسئلة. حاول مرة أخرى بعد بضع دقائق.",
39
+ removeCode: "إزالة الشيفرة",
35
40
  send: "إرسال",
41
+ support: "تواصل مع الدعم",
42
+ supportSubject: "سؤال من التوثيق",
36
43
  tip: "نصيحة: يمكنك فتح المحادثة وإغلاقها باستخدام",
37
44
  title: "المساعد",
45
+ verifyFailed: "تعذّر التحقق من أنك إنسان. حاول مرة أخرى.",
38
46
  you: "أنت",
39
47
  },
40
48
  banner: { dismiss: "إغلاق الإعلان" },
41
49
  changelog: {
42
50
  description: "تحديثات المنتج وملاحظات الإصدارات.",
51
+ empty: "لا توجد إدخالات في سجل التغييرات بعد.",
43
52
  title: "سجل التغييرات",
44
53
  },
54
+ consent: {
55
+ accept: "قبول",
56
+ decline: "رفض",
57
+ label: "الموافقة على ملفات تعريف الارتباط",
58
+ message: "نودّ استخدام ملفات تعريف الارتباط لفهم كيفية استخدام هذا التوثيق.",
59
+ policy: "سياسة الخصوصية",
60
+ settings: "إعدادات ملفات تعريف الارتباط",
61
+ },
45
62
  content: {
46
63
  code: "الكود",
47
64
  copyColor: "نسخ اللون {name} {value}",
@@ -52,6 +69,8 @@ export const ar: UIStringsOverride = {
52
69
  preview: "معاينة",
53
70
  prop: "الخاصية",
54
71
  selectTab: "اختيار علامة تبويب",
72
+ selectView: "اختيار طريقة العرض",
73
+ showLess: "عرض أقل",
55
74
  showMore: "عرض المزيد",
56
75
  stars: "النجوم",
57
76
  tab: "علامة التبويب {n}",
@@ -59,12 +78,36 @@ export const ar: UIStringsOverride = {
59
78
  update: "تحديث",
60
79
  },
61
80
  feedback: {
81
+ comment: "أخبرنا بالمزيد (اختياري)",
62
82
  no: "لا",
63
83
  question: "هل كانت هذه الصفحة مفيدة؟",
84
+ send: "إرسال",
64
85
  thanks: "شكراً على ملاحظاتك!",
65
86
  yes: "نعم",
66
87
  },
67
88
  languageSwitcher: { label: "اللغة", untranslated: "غير مترجم" },
89
+ narration: {
90
+ cueDanger: "خطر.",
91
+ cueInfo: "معلومة.",
92
+ cueNote: "ملاحظة.",
93
+ cueSection: "قسم قابل للتوسيع.",
94
+ cueStep: "الخطوة {n}.",
95
+ cueSuccess: "نجاح.",
96
+ cueTab: "علامة التبويب {title}.",
97
+ cueTip: "نصيحة.",
98
+ cueWarning: "تحذير.",
99
+ error: "تعذّر تحميل القراءة الصوتية.",
100
+ follow: "متابعة القراءة",
101
+ label: "استمع إلى هذه الصفحة",
102
+ minutes: "{n} دقيقة",
103
+ next: "الجملة التالية",
104
+ pause: "إيقاف مؤقت",
105
+ play: "تشغيل",
106
+ previous: "الجملة السابقة",
107
+ progress: "تقدّم القراءة",
108
+ speed: "سرعة التشغيل",
109
+ stop: "إيقاف الاستماع",
110
+ },
68
111
  nav: {
69
112
  back: "رجوع",
70
113
  breadcrumb: "مسار التنقل",
@@ -89,6 +132,7 @@ export const ar: UIStringsOverride = {
89
132
  next: "التالي",
90
133
  pagination: "ترقيم الصفحات",
91
134
  previous: "السابق",
135
+ related: "صفحات ذات صلة",
92
136
  skipToContent: "الانتقال إلى المحتوى",
93
137
  },
94
138
  search: {
@@ -5,6 +5,7 @@ export const bg: UIStringsOverride = {
5
5
  actions: {
6
6
  addToCursor: "Добави в Cursor",
7
7
  addToVscode: "Добави във VS Code",
8
+ askAboutCode: "Попитай за този код",
8
9
  connectMcp: "Свържи се с MCP",
9
10
  copied: "Копирано!",
10
11
  copyClaudeCode: "Копирай командата на Claude Code",
@@ -31,18 +32,36 @@ export const bg: UIStringsOverride = {
31
32
  copy: "Копирай разговора",
32
33
  empty: "Задайте въпрос за документацията.",
33
34
  error: "Съжаляваме, нещо се обърка.",
35
+ explainCode: "Обясни този код.",
34
36
  label: "Задайте въпрос",
37
+ open: "Отваряне на асистента",
35
38
  placeholder: "Задайте въпрос…",
39
+ rateLimited:
40
+ "Зададохте много въпроси. Опитайте отново след няколко минути.",
41
+ removeCode: "Премахни кода",
36
42
  send: "Изпрати",
43
+ support: "Свържете се с поддръжката",
44
+ supportSubject: "Въпрос от документацията",
37
45
  tip: "Съвет: Можете да отваряте и затваряте чата с",
38
46
  title: "Асистент",
47
+ verifyFailed: "Не успяхме да потвърдим, че сте човек. Опитайте отново.",
39
48
  you: "Вие",
40
49
  },
41
50
  banner: { dismiss: "Затваряне на съобщението" },
42
51
  changelog: {
43
52
  description: "Актуализации на продукта и бележки към изданията.",
53
+ empty: "Все още няма записи в дневника на промените.",
44
54
  title: "Дневник на промените",
45
55
  },
56
+ consent: {
57
+ accept: "Приемам",
58
+ decline: "Отказвам",
59
+ label: "Съгласие за бисквитки",
60
+ message:
61
+ "Бихме искали да използваме бисквитки, за да разберем как се използва тази документация.",
62
+ policy: "Политика за поверителност",
63
+ settings: "Настройки за бисквитки",
64
+ },
46
65
  content: {
47
66
  code: "Код",
48
67
  copyColor: "Копирай цвета {name} {value}",
@@ -53,6 +72,8 @@ export const bg: UIStringsOverride = {
53
72
  preview: "Преглед",
54
73
  prop: "Свойство",
55
74
  selectTab: "Избери раздел",
75
+ selectView: "Избери изглед",
76
+ showLess: "Покажи по-малко",
56
77
  showMore: "Покажи още",
57
78
  stars: "Звезди",
58
79
  tab: "Раздел {n}",
@@ -60,12 +81,36 @@ export const bg: UIStringsOverride = {
60
81
  update: "Актуализация",
61
82
  },
62
83
  feedback: {
84
+ comment: "Разкажете ни повече (по избор)",
63
85
  no: "Не",
64
86
  question: "Беше ли полезна тази страница?",
87
+ send: "Изпрати",
65
88
  thanks: "Благодарим за обратната връзка!",
66
89
  yes: "Да",
67
90
  },
68
91
  languageSwitcher: { label: "Език", untranslated: "Непреведено" },
92
+ narration: {
93
+ cueDanger: "Опасност.",
94
+ cueInfo: "Информация.",
95
+ cueNote: "Бележка.",
96
+ cueSection: "Разгъваем раздел.",
97
+ cueStep: "Стъпка {n}.",
98
+ cueSuccess: "Успех.",
99
+ cueTab: "Раздел {title}.",
100
+ cueTip: "Съвет.",
101
+ cueWarning: "Предупреждение.",
102
+ error: "Аудиоверсията не можа да бъде заредена.",
103
+ follow: "Следи четенето",
104
+ label: "Слушай тази страница",
105
+ minutes: "{n} мин",
106
+ next: "Следващо изречение",
107
+ pause: "Пауза",
108
+ play: "Пусни",
109
+ previous: "Предишно изречение",
110
+ progress: "Напредък на четенето",
111
+ speed: "Скорост на възпроизвеждане",
112
+ stop: "Спри слушането",
113
+ },
69
114
  nav: {
70
115
  back: "Назад",
71
116
  breadcrumb: "Навигационна пътека",
@@ -90,6 +135,7 @@ export const bg: UIStringsOverride = {
90
135
  next: "Напред",
91
136
  pagination: "Пагинация",
92
137
  previous: "Назад",
138
+ related: "Свързани страници",
93
139
  skipToContent: "Към съдържанието",
94
140
  },
95
141
  search: {
@@ -5,6 +5,7 @@ export const bn: UIStringsOverride = {
5
5
  actions: {
6
6
  addToCursor: "Cursor-এ যোগ করুন",
7
7
  addToVscode: "VS Code-এ যোগ করুন",
8
+ askAboutCode: "এই কোড সম্পর্কে জিজ্ঞাসা করুন",
8
9
  connectMcp: "MCP-তে সংযোগ করুন",
9
10
  copied: "অনুলিপি করা হয়েছে!",
10
11
  copyClaudeCode: "Claude Code কমান্ড অনুলিপি করুন",
@@ -30,18 +31,34 @@ export const bn: UIStringsOverride = {
30
31
  copy: "কথোপকথন অনুলিপি করুন",
31
32
  empty: "ডকুমেন্টেশন সম্পর্কে একটি প্রশ্ন করুন।",
32
33
  error: "দুঃখিত, কিছু একটা ভুল হয়েছে।",
34
+ explainCode: "এই কোডটি ব্যাখ্যা করুন।",
33
35
  label: "একটি প্রশ্ন করুন",
36
+ open: "সহকারী খুলুন",
34
37
  placeholder: "একটি প্রশ্ন করুন…",
38
+ rateLimited: "আপনি অনেক প্রশ্ন করেছেন। কয়েক মিনিট পরে আবার চেষ্টা করুন।",
39
+ removeCode: "কোড সরান",
35
40
  send: "পাঠান",
41
+ support: "সহায়তার সঙ্গে যোগাযোগ করুন",
42
+ supportSubject: "ডকুমেন্টেশন থেকে প্রশ্ন",
36
43
  tip: "টিপ: চ্যাট খুলতে ও বন্ধ করতে চাপুন",
37
44
  title: "সহকারী",
45
+ verifyFailed: "আপনি মানুষ কি না তা যাচাই করা যায়নি। আবার চেষ্টা করুন।",
38
46
  you: "আপনি",
39
47
  },
40
48
  banner: { dismiss: "ঘোষণা বন্ধ করুন" },
41
49
  changelog: {
42
50
  description: "পণ্য আপডেট এবং রিলিজ নোট।",
51
+ empty: "পরিবর্তন লগে এখনও কোনো এন্ট্রি নেই।",
43
52
  title: "পরিবর্তন লগ",
44
53
  },
54
+ consent: {
55
+ accept: "গ্রহণ করুন",
56
+ decline: "প্রত্যাখ্যান করুন",
57
+ label: "কুকি সম্মতি",
58
+ message: "এই ডকুমেন্টেশন কীভাবে ব্যবহার হয় তা বুঝতে আমরা কুকি ব্যবহার করতে চাই।",
59
+ policy: "গোপনীয়তা নীতি",
60
+ settings: "কুকি সেটিংস",
61
+ },
45
62
  content: {
46
63
  code: "কোড",
47
64
  copyColor: "{name} রং {value} অনুলিপি করুন",
@@ -52,6 +69,8 @@ export const bn: UIStringsOverride = {
52
69
  preview: "প্রিভিউ",
53
70
  prop: "প্রপ",
54
71
  selectTab: "ট্যাব নির্বাচন করুন",
72
+ selectView: "ভিউ নির্বাচন করুন",
73
+ showLess: "কম দেখান",
55
74
  showMore: "আরও দেখান",
56
75
  stars: "স্টার",
57
76
  tab: "ট্যাব {n}",
@@ -59,12 +78,36 @@ export const bn: UIStringsOverride = {
59
78
  update: "আপডেট",
60
79
  },
61
80
  feedback: {
81
+ comment: "আরও বলুন (ঐচ্ছিক)",
62
82
  no: "না",
63
83
  question: "এই পৃষ্ঠাটি কি সহায়ক ছিল?",
84
+ send: "পাঠান",
64
85
  thanks: "আপনার মতামতের জন্য ধন্যবাদ!",
65
86
  yes: "হ্যাঁ",
66
87
  },
67
88
  languageSwitcher: { label: "ভাষা", untranslated: "অনূদিত নয়" },
89
+ narration: {
90
+ cueDanger: "বিপদ।",
91
+ cueInfo: "তথ্য।",
92
+ cueNote: "নোট।",
93
+ cueSection: "প্রসারণযোগ্য অংশ।",
94
+ cueStep: "ধাপ {n}।",
95
+ cueSuccess: "সফল।",
96
+ cueTab: "{title} ট্যাব।",
97
+ cueTip: "টিপ।",
98
+ cueWarning: "সতর্কতা।",
99
+ error: "অডিও লোড করা যায়নি।",
100
+ follow: "পাঠের সাথে থাকুন",
101
+ label: "এই পৃষ্ঠাটি শুনুন",
102
+ minutes: "{n} মিনিট",
103
+ next: "পরবর্তী বাক্য",
104
+ pause: "বিরতি",
105
+ play: "চালান",
106
+ previous: "পূর্ববর্তী বাক্য",
107
+ progress: "পাঠের অগ্রগতি",
108
+ speed: "প্লেব্যাকের গতি",
109
+ stop: "শোনা বন্ধ করুন",
110
+ },
68
111
  nav: {
69
112
  back: "ফিরে যান",
70
113
  breadcrumb: "ব্রেডক্রাম্ব",
@@ -89,6 +132,7 @@ export const bn: UIStringsOverride = {
89
132
  next: "পরবর্তী",
90
133
  pagination: "পেজিনেশন",
91
134
  previous: "পূর্ববর্তী",
135
+ related: "সম্পর্কিত পৃষ্ঠা",
92
136
  skipToContent: "বিষয়বস্তুতে যান",
93
137
  },
94
138
  search: {