blume 2.0.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (601) hide show
  1. package/AGENTS.md +1 -0
  2. package/CHANGELOG.md +113 -0
  3. package/README.md +1 -1
  4. package/dist/cli/{chunk-6k4ftwze.js → chunk-0gz36akr.js} +18 -2
  5. package/dist/cli/{chunk-6k4ftwze.js.map → chunk-0gz36akr.js.map} +3 -3
  6. package/dist/cli/{chunk-zp79m0ts.js → chunk-1n228xqb.js} +2 -2
  7. package/dist/cli/{chunk-ddndchfr.js → chunk-2f3ndkpw.js} +57 -29
  8. package/dist/cli/chunk-2f3ndkpw.js.map +14 -0
  9. package/dist/cli/{chunk-fsmrqk8a.js → chunk-2f7n4qzt.js} +8 -2
  10. package/dist/cli/{chunk-fsmrqk8a.js.map → chunk-2f7n4qzt.js.map} +3 -3
  11. package/dist/cli/{chunk-ppzjqwx2.js → chunk-2n4ps1b3.js} +17 -18
  12. package/dist/cli/{chunk-ppzjqwx2.js.map → chunk-2n4ps1b3.js.map} +3 -3
  13. package/dist/cli/{chunk-5r8g91qn.js → chunk-43zcf4gz.js} +398 -159
  14. package/dist/cli/chunk-43zcf4gz.js.map +36 -0
  15. package/dist/cli/chunk-4ejxbzee.js +39 -0
  16. package/dist/cli/chunk-4ejxbzee.js.map +10 -0
  17. package/dist/cli/{chunk-hr8ne106.js → chunk-4h8z9vv5.js} +296 -77
  18. package/dist/cli/chunk-4h8z9vv5.js.map +16 -0
  19. package/dist/cli/{chunk-k7pj68a8.js → chunk-5cg2rzgf.js} +18 -16
  20. package/dist/cli/{chunk-k7pj68a8.js.map → chunk-5cg2rzgf.js.map} +2 -2
  21. package/dist/cli/{chunk-h2ez8dzb.js → chunk-5ffywsmb.js} +4 -4
  22. package/dist/cli/{chunk-g698a744.js → chunk-5wj2qwn2.js} +5 -5
  23. package/dist/cli/chunk-6bm0xpgd.js +18 -0
  24. package/dist/cli/chunk-6bm0xpgd.js.map +10 -0
  25. package/dist/cli/{chunk-3yce002v.js → chunk-713mngdq.js} +15 -8
  26. package/dist/cli/chunk-713mngdq.js.map +14 -0
  27. package/dist/cli/{chunk-91ws1n6j.js → chunk-9geymqns.js} +17 -15
  28. package/dist/cli/{chunk-91ws1n6j.js.map → chunk-9geymqns.js.map} +2 -2
  29. package/dist/cli/{chunk-6dtt0zfn.js → chunk-9xr4dgee.js} +27 -18
  30. package/dist/cli/chunk-9xr4dgee.js.map +10 -0
  31. package/dist/cli/{chunk-sqw4ekg1.js → chunk-amrb6hgh.js} +2 -2
  32. package/dist/cli/chunk-cm89scdv.js +443 -0
  33. package/dist/cli/chunk-cm89scdv.js.map +11 -0
  34. package/dist/cli/{chunk-wdrt2k2v.js → chunk-cmtcnh9f.js} +90 -26
  35. package/dist/cli/chunk-cmtcnh9f.js.map +10 -0
  36. package/dist/cli/chunk-cy5bm0j0.js +104 -0
  37. package/dist/cli/chunk-cy5bm0j0.js.map +11 -0
  38. package/dist/cli/{chunk-7mbqtmgb.js → chunk-e7vvk5ya.js} +21 -12
  39. package/dist/cli/chunk-e7vvk5ya.js.map +10 -0
  40. package/dist/cli/{chunk-qkb5a8sa.js → chunk-g2z9x01v.js} +6 -98
  41. package/dist/cli/chunk-g2z9x01v.js.map +10 -0
  42. package/dist/cli/{chunk-273ygyr4.js → chunk-ga0pf4aj.js} +7 -7
  43. package/dist/cli/{chunk-273ygyr4.js.map → chunk-ga0pf4aj.js.map} +3 -3
  44. package/dist/cli/{chunk-h7k3nq3v.js → chunk-gp84za0h.js} +2 -2
  45. package/dist/cli/{chunk-hqp2ajnh.js → chunk-h2a48yhd.js} +195 -73
  46. package/dist/cli/chunk-h2a48yhd.js.map +36 -0
  47. package/dist/cli/{chunk-pbg5a4s3.js → chunk-jnwj5kjj.js} +71 -47
  48. package/dist/cli/chunk-jnwj5kjj.js.map +19 -0
  49. package/dist/cli/chunk-kwrg63tm.js +31 -0
  50. package/dist/cli/chunk-kwrg63tm.js.map +10 -0
  51. package/dist/cli/{chunk-8g8ytmgx.js → chunk-nd1821sk.js} +21 -19
  52. package/dist/cli/{chunk-8g8ytmgx.js.map → chunk-nd1821sk.js.map} +2 -2
  53. package/dist/cli/{chunk-w4bxdvsa.js → chunk-ntv4qrt7.js} +17 -15
  54. package/dist/cli/{chunk-w4bxdvsa.js.map → chunk-ntv4qrt7.js.map} +2 -2
  55. package/dist/cli/{chunk-bfwp9vp6.js → chunk-p804f3pe.js} +7 -7
  56. package/dist/cli/{chunk-4e9b9ra6.js → chunk-py62fewh.js} +6 -6
  57. package/dist/cli/{chunk-4e9b9ra6.js.map → chunk-py62fewh.js.map} +1 -1
  58. package/dist/cli/chunk-q3wxxq39.js +126 -0
  59. package/dist/cli/chunk-q3wxxq39.js.map +11 -0
  60. package/dist/cli/{chunk-j85scx15.js → chunk-rekqz4qg.js} +142 -46
  61. package/dist/cli/chunk-rekqz4qg.js.map +10 -0
  62. package/dist/cli/{chunk-00gs3wqs.js → chunk-ta27feev.js} +1 -1
  63. package/dist/cli/{chunk-v6ya5kcb.js → chunk-xkz5xbtv.js} +4031 -1132
  64. package/dist/cli/chunk-xkz5xbtv.js.map +213 -0
  65. package/dist/cli/{chunk-bbnwccaz.js → chunk-y4ykbark.js} +2 -2
  66. package/dist/cli/{chunk-n1yg3tj3.js → chunk-y5h4r2y0.js} +6 -6
  67. package/dist/cli/{chunk-n1yg3tj3.js.map → chunk-y5h4r2y0.js.map} +3 -3
  68. package/dist/cli/{chunk-nfcyttvj.js → chunk-yj17vs39.js} +9 -9
  69. package/dist/cli/{chunk-nfcyttvj.js.map → chunk-yj17vs39.js.map} +1 -1
  70. package/dist/cli/{chunk-7vtckvaw.js → chunk-yxmk4pec.js} +16 -14
  71. package/dist/cli/{chunk-7vtckvaw.js.map → chunk-yxmk4pec.js.map} +2 -2
  72. package/dist/cli/{chunk-gs7r695n.js → chunk-zccbjcj0.js} +22 -8
  73. package/dist/cli/{chunk-gs7r695n.js.map → chunk-zccbjcj0.js.map} +3 -3
  74. package/dist/cli/{chunk-xh43dwgw.js → chunk-zf748avv.js} +415 -225
  75. package/dist/cli/chunk-zf748avv.js.map +37 -0
  76. package/dist/cli/{chunk-d1v5rhy0.js → chunk-zhvd6adm.js} +16 -14
  77. package/dist/cli/{chunk-d1v5rhy0.js.map → chunk-zhvd6adm.js.map} +2 -2
  78. package/dist/cli/index.js +28 -20
  79. package/dist/cli/index.js.map +5 -5
  80. package/dist/types/ai/agent-surface.d.ts +8 -7
  81. package/dist/types/ai/ai-catalog.d.ts +7 -0
  82. package/dist/types/ai/ask-context.d.ts +22 -0
  83. package/dist/types/ai/ask.d.ts +271 -58
  84. package/dist/types/ai/index.d.ts +2 -2
  85. package/dist/types/ai/link-headers.d.ts +8 -1
  86. package/dist/types/ai/openapi-components.d.ts +5 -2
  87. package/dist/types/ai/relative-links.d.ts +9 -7
  88. package/dist/types/ai/site-skill.d.ts +26 -0
  89. package/dist/types/ai/skills.d.ts +20 -1
  90. package/dist/types/ai/tar.d.ts +1 -3
  91. package/dist/types/analytics/index.d.ts +2 -0
  92. package/dist/types/analytics/one-dollar-stats.d.ts +48 -0
  93. package/dist/types/analytics/schema.d.ts +14 -0
  94. package/dist/types/astro/integration.d.ts +11 -2
  95. package/dist/types/captcha/hcaptcha.d.ts +27 -0
  96. package/dist/types/captcha/index.d.ts +28 -0
  97. package/dist/types/captcha/schema.d.ts +29 -0
  98. package/dist/types/captcha/turnstile.d.ts +28 -0
  99. package/dist/types/components/content/api-field.d.ts +59 -0
  100. package/dist/types/components/content/api-page.d.ts +95 -0
  101. package/dist/types/components/layout/nav-utils.d.ts +26 -0
  102. package/dist/types/components/openapi/helpers.d.ts +137 -0
  103. package/dist/types/components/openapi/security.d.ts +85 -0
  104. package/dist/types/consent/ethyca.d.ts +48 -0
  105. package/dist/types/consent/index.d.ts +37 -0
  106. package/dist/types/consent/native.d.ts +28 -0
  107. package/dist/types/consent/osano.d.ts +42 -0
  108. package/dist/types/consent/schema.d.ts +110 -0
  109. package/dist/types/core/base-path.d.ts +21 -7
  110. package/dist/types/core/config-input.d.ts +196 -27
  111. package/dist/types/core/data.d.ts +49 -4
  112. package/dist/types/core/directive-diagnostics.d.ts +12 -0
  113. package/dist/types/core/footer.d.ts +8 -0
  114. package/dist/types/core/heading-markers.d.ts +5 -7
  115. package/dist/types/core/i18n-ui.d.ts +86 -0
  116. package/dist/types/core/i18n.d.ts +2 -0
  117. package/dist/types/core/includes.d.ts +8 -2
  118. package/dist/types/core/last-modified.d.ts +10 -0
  119. package/dist/types/core/localizable.d.ts +7 -0
  120. package/dist/types/core/meta.d.ts +8 -0
  121. package/dist/types/core/page-modes.d.ts +29 -0
  122. package/dist/types/core/redirect-patterns.d.ts +144 -0
  123. package/dist/types/core/related.d.ts +40 -0
  124. package/dist/types/core/schema.d.ts +558 -56
  125. package/dist/types/core/sources/lower.d.ts +29 -16
  126. package/dist/types/core/sources/normalize.d.ts +13 -1
  127. package/dist/types/core/sources/read.d.ts +5 -0
  128. package/dist/types/core/sources/watch.d.ts +12 -5
  129. package/dist/types/core/standard-schema.d.ts +5 -0
  130. package/dist/types/core/types.d.ts +1 -1
  131. package/dist/types/core/variables.d.ts +42 -0
  132. package/dist/types/deploy/artifacts.d.ts +6 -4
  133. package/dist/types/deploy/headers.d.ts +5 -0
  134. package/dist/types/deploy/node-headers.d.ts +13 -2
  135. package/dist/types/deploy/platforms/cloudflare.d.ts +5 -0
  136. package/dist/types/deploy/platforms/netlify.d.ts +7 -0
  137. package/dist/types/deploy/platforms/types.d.ts +8 -0
  138. package/dist/types/deploy/platforms/vercel.d.ts +6 -0
  139. package/dist/types/deploy/redirects.d.ts +61 -22
  140. package/dist/types/deploy/vercel-negotiation.d.ts +9 -0
  141. package/dist/types/markdown/code-title.d.ts +17 -0
  142. package/dist/types/markdown/directives.d.ts +62 -0
  143. package/dist/types/markdown/features.d.ts +24 -2
  144. package/dist/types/markdown/mdast.d.ts +63 -0
  145. package/dist/types/narration/build.d.ts +70 -0
  146. package/dist/types/narration/provider.d.ts +26 -0
  147. package/dist/types/narration/script.d.ts +154 -0
  148. package/dist/types/openapi/asyncapi.d.ts +4 -2
  149. package/dist/types/openapi/model.d.ts +12 -6
  150. package/dist/types/openapi/overlay.d.ts +54 -0
  151. package/dist/types/openapi/parse.d.ts +13 -0
  152. package/dist/types/openapi/references.d.ts +14 -4
  153. package/dist/types/ratelimit/cloudflare.d.ts +39 -0
  154. package/dist/types/ratelimit/index.d.ts +27 -0
  155. package/dist/types/ratelimit/memory.d.ts +36 -0
  156. package/dist/types/ratelimit/schema.d.ts +111 -0
  157. package/dist/types/ratelimit/upstash.d.ts +21 -0
  158. package/dist/types/ratelimit/wrangler.d.ts +23 -0
  159. package/dist/types/reference/asyncapi.d.ts +10 -10
  160. package/dist/types/reference/graphql.d.ts +13 -10
  161. package/dist/types/reference/openapi.d.ts +33 -12
  162. package/dist/types/reference/options.d.ts +45 -5
  163. package/dist/types/reference/scalar.d.ts +13 -0
  164. package/dist/types/reference/schema.d.ts +60 -36
  165. package/dist/types/search/documents.d.ts +12 -1
  166. package/dist/types/search/orama-index.d.ts +4 -0
  167. package/dist/types/seo/metatags.d.ts +20 -0
  168. package/docs/02-deployment.mdx +44 -6
  169. package/docs/03-upgrading.mdx +4 -4
  170. package/docs/04-migrating.mdx +1 -1
  171. package/docs/08-faq.mdx +1 -1
  172. package/docs/advanced/changelog.mdx +2 -2
  173. package/docs/advanced/custom-pages.mdx +3 -3
  174. package/docs/advanced/skills.mdx +14 -0
  175. package/docs/cli/audit.mdx +38 -2
  176. package/docs/cli/evals.mdx +3 -3
  177. package/docs/cli/index.mdx +1 -0
  178. package/docs/cli/translate.mdx +3 -3
  179. package/docs/cli/version.mdx +1 -1
  180. package/docs/configuration/analytics.mdx +22 -1
  181. package/docs/configuration/assistant.mdx +188 -36
  182. package/docs/configuration/consent.mdx +100 -0
  183. package/docs/configuration/customization.mdx +6 -4
  184. package/docs/configuration/index.mdx +63 -5
  185. package/docs/configuration/meta.ts +3 -0
  186. package/docs/configuration/narration.mdx +119 -0
  187. package/docs/configuration/rate-limiting.mdx +69 -0
  188. package/docs/configuration/search.mdx +30 -2
  189. package/docs/configuration/theming.mdx +3 -1
  190. package/docs/content/components.mdx +107 -1
  191. package/docs/content/frontmatter.mdx +77 -1
  192. package/docs/content/i18n.mdx +40 -3
  193. package/docs/content/includes.mdx +16 -0
  194. package/docs/content/index.mdx +4 -2
  195. package/docs/content/islands.mdx +1 -1
  196. package/docs/content/meta.mdx +4 -1
  197. package/docs/content/meta.ts +1 -0
  198. package/docs/content/navigation.mdx +28 -6
  199. package/docs/content/sources/contentful.mdx +32 -0
  200. package/docs/content/sources/custom.mdx +39 -0
  201. package/docs/content/sources/github-releases.mdx +31 -0
  202. package/docs/content/sources/index.mdx +91 -0
  203. package/docs/content/sources/meta.ts +16 -0
  204. package/docs/content/sources/notion.mdx +32 -0
  205. package/docs/content/sources/obsidian.mdx +37 -0
  206. package/docs/content/sources/payload.mdx +30 -0
  207. package/docs/content/sources/remote-mdx.mdx +40 -0
  208. package/docs/content/sources/sanity.mdx +29 -0
  209. package/docs/content/sources/strapi.mdx +31 -0
  210. package/docs/content/syntax.mdx +81 -2
  211. package/docs/content/variables.mdx +41 -0
  212. package/docs/content/versioning.mdx +1 -1
  213. package/docs/discoverability/agent-discovery.mdx +30 -3
  214. package/docs/discoverability/index.mdx +3 -2
  215. package/docs/discoverability/llms-txt.mdx +1 -1
  216. package/docs/discoverability/markdown.mdx +2 -2
  217. package/docs/discoverability/metadata.mdx +17 -0
  218. package/docs/discoverability/open-graph.mdx +5 -3
  219. package/docs/discoverability/rss.mdx +1 -1
  220. package/docs/references/api-pages.mdx +74 -0
  221. package/docs/references/asyncapi.mdx +2 -2
  222. package/docs/references/graphql.mdx +3 -3
  223. package/docs/references/meta.ts +1 -1
  224. package/docs/references/openapi.mdx +106 -5
  225. package/docs/references/scalar.mdx +3 -1
  226. package/package.json +36 -1
  227. package/skills/blume/SKILL.md +3 -0
  228. package/skills/blume-migrate/SKILL.md +5 -5
  229. package/skills/blume-migrate/references/docusaurus.md +3 -3
  230. package/skills/blume-migrate/references/fumadocs.md +1 -1
  231. package/skills/blume-migrate/references/mintlify.md +37 -19
  232. package/skills/blume-migrate/references/nextra.md +3 -3
  233. package/skills/blume-migrate/references/starlight.md +2 -1
  234. package/skills/blume-migrate/scripts/mintlify-codemod.mjs +67 -16
  235. package/skills/blume-write-skill/SKILL.md +82 -0
  236. package/src/ai/agent-readability.ts +4 -3
  237. package/src/ai/agent-surface.ts +9 -7
  238. package/src/ai/ai-catalog.ts +12 -5
  239. package/src/ai/api/handlers.ts +2 -2
  240. package/src/ai/api/spec.ts +2 -2
  241. package/src/ai/api-catalog.ts +6 -2
  242. package/src/ai/ask-context.ts +73 -20
  243. package/src/ai/ask-data.ts +6 -0
  244. package/src/ai/ask-tools.ts +142 -0
  245. package/src/ai/ask.ts +354 -76
  246. package/src/ai/changelog-markdown.ts +2 -2
  247. package/src/ai/component-markdown.ts +75 -0
  248. package/src/ai/cors.ts +2 -0
  249. package/src/ai/index.ts +12 -0
  250. package/src/ai/link-headers.ts +14 -5
  251. package/src/ai/llms.ts +24 -9
  252. package/src/ai/markdown.ts +2 -1
  253. package/src/ai/mcp/data.ts +6 -0
  254. package/src/ai/mcp/discovery.ts +2 -2
  255. package/src/ai/mcp/query.ts +2 -2
  256. package/src/ai/mcp/server.ts +2 -2
  257. package/src/ai/openapi-components.ts +31 -9
  258. package/src/ai/relative-links.ts +42 -26
  259. package/src/ai/serializers.ts +2 -1
  260. package/src/ai/site-skill.ts +274 -0
  261. package/src/ai/skills.ts +49 -3
  262. package/src/ai/tar.ts +139 -12
  263. package/src/ai/write-skill.ts +97 -0
  264. package/src/analytics/head.ts +4 -0
  265. package/src/analytics/index.ts +5 -0
  266. package/src/analytics/one-dollar-stats.ts +86 -0
  267. package/src/analytics/schema.ts +2 -0
  268. package/src/astro/generate.ts +133 -19
  269. package/src/astro/include-hmr.ts +31 -12
  270. package/src/astro/include-refresh.ts +19 -8
  271. package/src/astro/index.ts +1 -0
  272. package/src/astro/integration.ts +143 -14
  273. package/src/astro/module-types.ts +6 -0
  274. package/src/astro/runtime-modules.ts +28 -13
  275. package/src/astro/templates.ts +364 -67
  276. package/src/astro/variables.ts +31 -0
  277. package/src/audit/catalog.ts +19 -0
  278. package/src/audit/checks/contrast.ts +183 -0
  279. package/src/audit/checks/i18n.ts +2 -3
  280. package/src/audit/checks/indexability.ts +2 -3
  281. package/src/audit/checks/links.ts +13 -13
  282. package/src/audit/checks/sitemap.ts +2 -3
  283. package/src/audit/graph.ts +3 -1
  284. package/src/audit/redirects.ts +46 -15
  285. package/src/audit/run.ts +14 -9
  286. package/src/audit/snapshot.ts +5 -0
  287. package/src/audit/types.ts +2 -1
  288. package/src/blume-modules.d.ts +7 -0
  289. package/src/captcha/client.ts +152 -0
  290. package/src/captcha/hcaptcha.ts +36 -0
  291. package/src/captcha/index.ts +28 -0
  292. package/src/captcha/schema.ts +32 -0
  293. package/src/captcha/turnstile.ts +38 -0
  294. package/src/captcha/verify.ts +71 -0
  295. package/src/cli/args.ts +32 -0
  296. package/src/cli/command-meta.ts +5 -0
  297. package/src/cli/commands/audit.ts +4 -1
  298. package/src/cli/commands/doctor.ts +25 -17
  299. package/src/cli/commands/eval.ts +19 -11
  300. package/src/cli/commands/skill.ts +96 -0
  301. package/src/cli/commands/translate.ts +9 -12
  302. package/src/cli/commands/validate.ts +3 -1
  303. package/src/cli/dev-lock.ts +157 -37
  304. package/src/cli/index.ts +5 -0
  305. package/src/cli/report-format.ts +11 -6
  306. package/src/cli/required-secrets.ts +71 -29
  307. package/src/components/BlumePage.astro +2 -0
  308. package/src/components/colors.ts +19 -0
  309. package/src/components/content/ApiEndpoint.astro +18 -0
  310. package/src/components/content/ApiField.astro +79 -0
  311. package/src/components/content/ApiPlayground.astro +62 -0
  312. package/src/components/content/ApiRail.astro +19 -0
  313. package/src/components/content/Badge.astro +5 -3
  314. package/src/components/content/Color.astro +1 -0
  315. package/src/components/content/Component.astro +2 -2
  316. package/src/components/content/FileTree.astro +1 -0
  317. package/src/components/content/GithubInfo.astro +1 -0
  318. package/src/components/content/Panel.astro +1 -0
  319. package/src/components/content/ParamField.astro +25 -0
  320. package/src/components/content/RequestExample.astro +17 -0
  321. package/src/components/content/ResponseExample.astro +17 -0
  322. package/src/components/content/ResponseField.astro +32 -0
  323. package/src/components/content/Step.astro +1 -0
  324. package/src/components/content/Tab.astro +0 -1
  325. package/src/components/content/Tabs.astro +4 -0
  326. package/src/components/content/Tile.astro +1 -0
  327. package/src/components/content/Tooltip.astro +1 -0
  328. package/src/components/content/Tree.astro +1 -0
  329. package/src/components/content/TypeTable.astro +4 -1
  330. package/src/components/content/View.astro +21 -0
  331. package/src/components/content/ViewSwitcher.astro +168 -0
  332. package/src/components/content/api-field.ts +100 -0
  333. package/src/components/content/api-page.ts +224 -0
  334. package/src/components/content/badge-color.ts +5 -2
  335. package/src/components/content/base-href.ts +13 -36
  336. package/src/components/content/view-switcher.ts +71 -0
  337. package/src/components/index.ts +2 -0
  338. package/src/components/islands/Assistant.astro +10 -1
  339. package/src/components/islands/assistant.tsx +125 -18
  340. package/src/components/islands/base-path.ts +47 -10
  341. package/src/components/islands/code-question.ts +62 -0
  342. package/src/components/islands/hooks.ts +145 -40
  343. package/src/components/islands/support-link.ts +68 -0
  344. package/src/components/islands/webmcp.ts +4 -2
  345. package/src/components/layout/Analytics.astro +11 -2
  346. package/src/components/layout/Banner.astro +14 -10
  347. package/src/components/layout/Breadcrumbs.astro +11 -4
  348. package/src/components/layout/ConsentBanner.astro +62 -0
  349. package/src/components/layout/ConsentHead.astro +38 -0
  350. package/src/components/layout/Directory.astro +94 -0
  351. package/src/components/layout/DiscoveryLinks.astro +9 -5
  352. package/src/components/layout/DrawerSwitchers.astro +51 -0
  353. package/src/components/layout/Empty.astro +2 -2
  354. package/src/components/layout/Header.astro +124 -82
  355. package/src/components/layout/LanguageSwitcher.astro +50 -17
  356. package/src/components/layout/NarrationPlayer.astro +1085 -0
  357. package/src/components/layout/NavSelector.astro +35 -9
  358. package/src/components/layout/NavTabMenu.astro +3 -3
  359. package/src/components/layout/NavTree.astro +16 -6
  360. package/src/components/layout/PageActions.astro +4 -3
  361. package/src/components/layout/PageFeedback.astro +54 -49
  362. package/src/components/layout/PageLayout.astro +78 -9
  363. package/src/components/layout/Pagination.astro +3 -3
  364. package/src/components/layout/ReferenceLayout.astro +17 -6
  365. package/src/components/layout/RelatedPages.astro +42 -0
  366. package/src/components/layout/RootLayout.astro +313 -50
  367. package/src/components/layout/Search.astro +64 -30
  368. package/src/components/layout/SiteFooter.astro +124 -0
  369. package/src/components/layout/SiteMetatags.astro +16 -0
  370. package/src/components/layout/VersionBanner.astro +2 -2
  371. package/src/components/layout/analytics-client.ts +12 -0
  372. package/src/components/layout/consent/native.ts +79 -0
  373. package/src/components/layout/consent/types.ts +37 -0
  374. package/src/components/layout/footer-links.ts +53 -0
  375. package/src/components/layout/footer-socials.ts +87 -0
  376. package/src/components/layout/locale-redirect.ts +107 -0
  377. package/src/components/layout/nav-utils.ts +83 -0
  378. package/src/components/layout/page-feedback.ts +96 -0
  379. package/src/components/layout/search/analytics.ts +98 -0
  380. package/src/components/layout/search/flexsearch.ts +17 -5
  381. package/src/components/layout/search/orama-cloud.ts +26 -14
  382. package/src/components/layout/search/types.ts +20 -0
  383. package/src/components/layout/search/typesense.ts +5 -1
  384. package/src/components/layout/toc-active.ts +41 -0
  385. package/src/components/layout/toc-element.ts +8 -14
  386. package/src/components/openapi/ApiTagOperations.astro +2 -2
  387. package/src/components/openapi/AsyncApiOperation.astro +7 -4
  388. package/src/components/openapi/GraphqlChip.astro +2 -2
  389. package/src/components/openapi/Operation.astro +163 -13
  390. package/src/components/openapi/Playground.astro +4 -4
  391. package/src/components/openapi/RequestBody.astro +6 -4
  392. package/src/components/openapi/RequestPanel.astro +63 -8
  393. package/src/components/openapi/Responses.astro +6 -4
  394. package/src/components/openapi/SchemaTable.astro +7 -0
  395. package/src/components/openapi/async-snippets.ts +4 -4
  396. package/src/components/openapi/async.ts +38 -6
  397. package/src/components/openapi/code-samples.ts +97 -0
  398. package/src/components/openapi/helpers.ts +19 -9
  399. package/src/components/openapi/message-composer.ts +6 -1
  400. package/src/components/openapi/message.ts +17 -2
  401. package/src/components/openapi/operation-model.ts +81 -11
  402. package/src/components/openapi/panel.ts +4 -2
  403. package/src/components/openapi/param-style.ts +181 -0
  404. package/src/components/openapi/playground-client.ts +73 -16
  405. package/src/components/openapi/request.ts +190 -26
  406. package/src/components/openapi/schema-tree.ts +30 -24
  407. package/src/components/openapi/security.ts +6 -3
  408. package/src/components/openapi/snippets.ts +953 -13
  409. package/src/components/openapi/ws-client.ts +18 -2
  410. package/src/components/props.ts +6 -0
  411. package/src/consent/client.ts +95 -0
  412. package/src/consent/clients.ts +19 -0
  413. package/src/consent/ethyca.ts +71 -0
  414. package/src/consent/head.ts +24 -0
  415. package/src/consent/index.ts +37 -0
  416. package/src/consent/init.ts +29 -0
  417. package/src/consent/native.ts +36 -0
  418. package/src/consent/osano.ts +59 -0
  419. package/src/consent/schema.ts +30 -0
  420. package/src/core/base-path.ts +62 -16
  421. package/src/core/builtin-tags.ts +5 -0
  422. package/src/core/client-address.ts +19 -0
  423. package/src/core/config-input.ts +203 -27
  424. package/src/core/data.ts +44 -4
  425. package/src/core/diagnostics.ts +5 -2
  426. package/src/core/directive-diagnostics.ts +99 -0
  427. package/src/core/footer.ts +26 -0
  428. package/src/core/frontmatter.ts +21 -18
  429. package/src/core/graph.ts +39 -36
  430. package/src/core/heading-markers.ts +5 -18
  431. package/src/core/i18n-ui.ts +82 -2
  432. package/src/core/i18n.ts +31 -3
  433. package/src/core/includes.ts +20 -3
  434. package/src/core/last-modified.ts +25 -3
  435. package/src/core/links.ts +16 -2
  436. package/src/core/locale-links.ts +5 -1
  437. package/src/core/localizable.ts +26 -0
  438. package/src/core/meta.ts +33 -19
  439. package/src/core/navigation.ts +71 -20
  440. package/src/core/page-modes.ts +56 -0
  441. package/src/core/project-graph.ts +138 -10
  442. package/src/core/redirect-patterns.ts +491 -0
  443. package/src/core/related.ts +131 -0
  444. package/src/core/schema.ts +342 -68
  445. package/src/core/sources/contentful-rich-text.ts +27 -20
  446. package/src/core/sources/filesystem.ts +20 -2
  447. package/src/core/sources/github-releases.ts +25 -6
  448. package/src/core/sources/lexical.ts +23 -18
  449. package/src/core/sources/lower.ts +201 -34
  450. package/src/core/sources/mdx-remote.ts +51 -16
  451. package/src/core/sources/normalize.ts +327 -91
  452. package/src/core/sources/notion.ts +52 -25
  453. package/src/core/sources/obsidian.ts +23 -6
  454. package/src/core/sources/portable-text.ts +38 -21
  455. package/src/core/sources/read.ts +8 -3
  456. package/src/core/sources/strapi-blocks.ts +20 -16
  457. package/src/core/sources/watch.ts +20 -7
  458. package/src/core/standard-schema.ts +10 -6
  459. package/src/core/types.ts +1 -1
  460. package/src/core/ui-packs/ar.ts +43 -0
  461. package/src/core/ui-packs/bg.ts +45 -0
  462. package/src/core/ui-packs/bn.ts +43 -0
  463. package/src/core/ui-packs/ca.ts +46 -0
  464. package/src/core/ui-packs/cs.ts +44 -0
  465. package/src/core/ui-packs/da.ts +45 -0
  466. package/src/core/ui-packs/de.ts +46 -0
  467. package/src/core/ui-packs/el.ts +45 -0
  468. package/src/core/ui-packs/es.ts +46 -0
  469. package/src/core/ui-packs/fa.ts +45 -0
  470. package/src/core/ui-packs/fi.ts +45 -0
  471. package/src/core/ui-packs/fr.ts +46 -0
  472. package/src/core/ui-packs/he.ts +43 -0
  473. package/src/core/ui-packs/hi.ts +44 -0
  474. package/src/core/ui-packs/hr.ts +45 -0
  475. package/src/core/ui-packs/hu.ts +44 -0
  476. package/src/core/ui-packs/id.ts +45 -0
  477. package/src/core/ui-packs/it.ts +45 -0
  478. package/src/core/ui-packs/ja.ts +45 -0
  479. package/src/core/ui-packs/ko.ts +44 -0
  480. package/src/core/ui-packs/nl.ts +46 -0
  481. package/src/core/ui-packs/no.ts +44 -0
  482. package/src/core/ui-packs/pl.ts +45 -0
  483. package/src/core/ui-packs/pt-br.ts +46 -0
  484. package/src/core/ui-packs/pt.ts +45 -0
  485. package/src/core/ui-packs/ro.ts +45 -0
  486. package/src/core/ui-packs/ru.ts +45 -0
  487. package/src/core/ui-packs/sk.ts +44 -0
  488. package/src/core/ui-packs/sr.ts +45 -0
  489. package/src/core/ui-packs/sv.ts +44 -0
  490. package/src/core/ui-packs/th.ts +43 -0
  491. package/src/core/ui-packs/tr.ts +45 -0
  492. package/src/core/ui-packs/uk.ts +45 -0
  493. package/src/core/ui-packs/vi.ts +45 -0
  494. package/src/core/ui-packs/zh-tw.ts +43 -0
  495. package/src/core/ui-packs/zh.ts +43 -0
  496. package/src/core/variables.ts +103 -0
  497. package/src/core/version-cut.ts +52 -15
  498. package/src/deploy/artifacts.ts +104 -14
  499. package/src/deploy/cloudflare-negotiation.ts +39 -17
  500. package/src/deploy/headers.ts +10 -5
  501. package/src/deploy/node-headers.ts +64 -10
  502. package/src/deploy/platforms/cloudflare.ts +44 -3
  503. package/src/deploy/platforms/netlify.ts +34 -1
  504. package/src/deploy/platforms/node.ts +1 -0
  505. package/src/deploy/platforms/static.ts +1 -0
  506. package/src/deploy/platforms/types.ts +8 -0
  507. package/src/deploy/platforms/vercel.ts +38 -2
  508. package/src/deploy/redirects.ts +139 -36
  509. package/src/deploy/robots.ts +2 -2
  510. package/src/deploy/rss.ts +4 -3
  511. package/src/deploy/sitemap.ts +7 -5
  512. package/src/deploy/vercel-negotiation.ts +36 -0
  513. package/src/markdown/api-rail.ts +259 -0
  514. package/src/markdown/base-links.ts +34 -36
  515. package/src/markdown/code-title.ts +35 -9
  516. package/src/markdown/directives.ts +242 -36
  517. package/src/markdown/features.ts +20 -2
  518. package/src/markdown/fence-meta.ts +2 -0
  519. package/src/markdown/include.ts +11 -1
  520. package/src/markdown/index.ts +35 -11
  521. package/src/markdown/math.ts +4 -4
  522. package/src/markdown/mdast.ts +5 -2
  523. package/src/markdown/relative-links.ts +12 -4
  524. package/src/markdown/variables.ts +56 -0
  525. package/src/markdown/views.ts +82 -0
  526. package/src/narration/build.ts +412 -0
  527. package/src/narration/player.ts +249 -0
  528. package/src/narration/provider.ts +29 -0
  529. package/src/narration/script.ts +592 -0
  530. package/src/og/card.ts +136 -11
  531. package/src/og/derive.ts +41 -31
  532. package/src/og/index.ts +1 -0
  533. package/src/openapi/asyncapi.ts +4 -2
  534. package/src/openapi/model.ts +77 -36
  535. package/src/openapi/overlay.ts +256 -0
  536. package/src/openapi/parse.ts +55 -2
  537. package/src/openapi/proxy.ts +63 -10
  538. package/src/openapi/references.ts +21 -5
  539. package/src/openapi/render-mdx.ts +46 -3
  540. package/src/openapi/scalar.ts +40 -6
  541. package/src/openapi/source.ts +1 -1
  542. package/src/ratelimit/cloudflare.ts +54 -0
  543. package/src/ratelimit/index.ts +30 -0
  544. package/src/ratelimit/memory.ts +45 -0
  545. package/src/ratelimit/runtime.ts +229 -0
  546. package/src/ratelimit/schema.ts +28 -0
  547. package/src/ratelimit/upstash.ts +30 -0
  548. package/src/ratelimit/wrangler.ts +70 -0
  549. package/src/reference/asyncapi.ts +2 -2
  550. package/src/reference/graphql.ts +5 -2
  551. package/src/reference/openapi.ts +21 -7
  552. package/src/reference/options.ts +51 -7
  553. package/src/reference/scalar.ts +33 -8
  554. package/src/registry/eject.ts +201 -28
  555. package/src/registry/registry.ts +7 -0
  556. package/src/search/adapters/version-scope.ts +30 -0
  557. package/src/search/documents.ts +93 -28
  558. package/src/search/orama-index.ts +28 -3
  559. package/src/search/pagefind-ranking.ts +39 -0
  560. package/src/search/popular.ts +2 -1
  561. package/src/search/sync/algolia.ts +15 -4
  562. package/src/search/sync/orama-cloud.ts +3 -0
  563. package/src/search/sync/typesense.ts +5 -0
  564. package/src/seo/jsonld.ts +7 -3
  565. package/src/seo/metatags.ts +67 -0
  566. package/src/theme/chrome-icons.ts +1 -0
  567. package/src/theme/color.ts +500 -0
  568. package/src/theme/entry.ts +56 -3
  569. package/src/theme/palette.ts +121 -45
  570. package/src/translate/meta.ts +68 -24
  571. package/src/translate/prompts.ts +1 -0
  572. package/src/translate/run.ts +3 -3
  573. package/src/translate/validate.ts +12 -3
  574. package/src/translate/work-list.ts +56 -17
  575. package/src/upgrade/upgrade.ts +4 -171
  576. package/dist/cli/chunk-3yce002v.js.map +0 -14
  577. package/dist/cli/chunk-5r8g91qn.js.map +0 -34
  578. package/dist/cli/chunk-6dtt0zfn.js.map +0 -10
  579. package/dist/cli/chunk-7mbqtmgb.js.map +0 -10
  580. package/dist/cli/chunk-ddndchfr.js.map +0 -14
  581. package/dist/cli/chunk-esh98wmb.js +0 -23
  582. package/dist/cli/chunk-esh98wmb.js.map +0 -10
  583. package/dist/cli/chunk-hqp2ajnh.js.map +0 -35
  584. package/dist/cli/chunk-hr8ne106.js.map +0 -13
  585. package/dist/cli/chunk-j85scx15.js.map +0 -10
  586. package/dist/cli/chunk-mqc662a6.js +0 -75
  587. package/dist/cli/chunk-mqc662a6.js.map +0 -11
  588. package/dist/cli/chunk-pbg5a4s3.js.map +0 -19
  589. package/dist/cli/chunk-qkb5a8sa.js.map +0 -10
  590. package/dist/cli/chunk-v6ya5kcb.js.map +0 -189
  591. package/dist/cli/chunk-wdrt2k2v.js.map +0 -10
  592. package/dist/cli/chunk-xh43dwgw.js.map +0 -36
  593. package/docs/content/sources.mdx +0 -338
  594. /package/dist/cli/{chunk-zp79m0ts.js.map → chunk-1n228xqb.js.map} +0 -0
  595. /package/dist/cli/{chunk-h2ez8dzb.js.map → chunk-5ffywsmb.js.map} +0 -0
  596. /package/dist/cli/{chunk-g698a744.js.map → chunk-5wj2qwn2.js.map} +0 -0
  597. /package/dist/cli/{chunk-sqw4ekg1.js.map → chunk-amrb6hgh.js.map} +0 -0
  598. /package/dist/cli/{chunk-h7k3nq3v.js.map → chunk-gp84za0h.js.map} +0 -0
  599. /package/dist/cli/{chunk-bfwp9vp6.js.map → chunk-p804f3pe.js.map} +0 -0
  600. /package/dist/cli/{chunk-00gs3wqs.js.map → chunk-ta27feev.js.map} +0 -0
  601. /package/dist/cli/{chunk-bbnwccaz.js.map → chunk-y4ykbark.js.map} +0 -0
@@ -1,5 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ resolveFallbackLocale,
4
+ localizeRoute,
5
+ localizeInternalPath,
6
+ i18nDiagnostics,
3
7
  blumeReferences,
4
8
  frontmatter_default,
5
9
  resolveDocsCollection,
@@ -12,21 +16,23 @@ import {
12
16
  pollingWatch,
13
17
  snapshotCache,
14
18
  loadWithCache,
15
- resolveFallbackLocale,
16
- localizeRoute,
17
- localizeInternalPath,
18
- i18nDiagnostics,
19
+ MDX_BODY_FEATURES,
19
20
  normalizeRef,
20
21
  isPageRef,
21
22
  pagesByRef,
22
23
  buildNavigation,
23
24
  PUBLIC_API_URL,
25
+ pathsUnderPattern,
26
+ hasVariables,
27
+ substituteVariables,
28
+ undefinedVariables,
24
29
  pageMetaSchema,
25
30
  folderMetaSchema,
26
31
  versionizeRoute,
27
32
  versionsDiagnostics,
28
33
  slugify,
29
34
  slugifyPath,
35
+ unloadablePathDiagnostic,
30
36
  extractHeadings,
31
37
  strippedLineOffset,
32
38
  isStringValue,
@@ -42,7 +48,7 @@ import {
42
48
  guardBlockStart,
43
49
  renderInline,
44
50
  destination,
45
- renderLink,
51
+ linkParts,
46
52
  headingPrefix,
47
53
  blockquote,
48
54
  listItem,
@@ -57,15 +63,17 @@ import {
57
63
  neutralizeUnsafeLinks,
58
64
  columnsPrefix,
59
65
  openApiSource,
60
- BLUME_IGNORE_DIRS,
61
- baselineScanIgnore,
62
- BLUME_WATCH_IGNORE_DIRS,
63
- excludeDirSegments,
64
- ignoringWatchListener,
66
+ isJsonObject,
67
+ getPath,
68
+ isStringValue2,
69
+ asString,
70
+ asObject,
71
+ asNumber,
72
+ objectsIn,
65
73
  createModuleLoader,
66
74
  resolveProjectContext,
67
75
  loadConfig
68
- } from "./chunk-v6ya5kcb.js";
76
+ } from "./chunk-xkz5xbtv.js";
69
77
  import {
70
78
  getBlumeVersion,
71
79
  BlumeError,
@@ -76,7 +84,14 @@ import {
76
84
  isInternalPath,
77
85
  withBasePath,
78
86
  mountBasePath
79
- } from "./chunk-gs7r695n.js";
87
+ } from "./chunk-zccbjcj0.js";
88
+ import {
89
+ BLUME_IGNORE_DIRS,
90
+ baselineScanIgnore,
91
+ BLUME_WATCH_IGNORE_DIRS,
92
+ excludeDirSegments,
93
+ ignoringWatchListener
94
+ } from "./chunk-kwrg63tm.js";
80
95
 
81
96
  // src/core/manifest.ts
82
97
  var versionAlternateKey = (versionKey, locale) => `${versionKey}\x00${locale}`;
@@ -203,6 +218,112 @@ var buildManifest = (options) => {
203
218
  // src/core/project-graph.ts
204
219
  import { isAbsolute as isAbsolute3, relative as relative5 } from "pathe";
205
220
 
221
+ // src/core/directive-diagnostics.ts
222
+ import { mdxToMdast } from "satteri";
223
+
224
+ // src/markdown/directives.ts
225
+ import { toString as mdastToString } from "mdast-util-to-string";
226
+ var CALLOUT_TYPES = new Set([
227
+ "danger",
228
+ "info",
229
+ "note",
230
+ "success",
231
+ "tip",
232
+ "warning"
233
+ ]);
234
+ var CALLOUT_ALIASES = {
235
+ caution: "warning",
236
+ error: "danger",
237
+ important: "note",
238
+ warn: "warning"
239
+ };
240
+ var calloutTypeFor = (name) => {
241
+ const lower = name.toLowerCase();
242
+ if (CALLOUT_TYPES.has(lower)) {
243
+ return lower;
244
+ }
245
+ return CALLOUT_ALIASES[lower] ?? null;
246
+ };
247
+ var LITERAL_MARKERS = new Map([
248
+ ["leafDirective", "::"],
249
+ ["textDirective", ":"]
250
+ ]);
251
+ var labelSource = (label) => label.length > 0 ? `[${mdastToString(label, { includeImageAlt: false })}]` : "";
252
+ var attributeSource = (node) => {
253
+ const attributes = Object.entries(node.attributes ?? {}).map(([key, value]) => value ? `${key}="${value}"` : key);
254
+ return attributes.length > 0 ? `{${attributes.join(" ")}}` : "";
255
+ };
256
+ var spannedSource = (node, source) => {
257
+ const start = node.position?.start?.offset;
258
+ const end = node.position?.end?.offset;
259
+ return start !== undefined && end !== undefined ? source.slice(start, end) : null;
260
+ };
261
+ var directiveSource = (node, marker, source) => {
262
+ const opening = `${marker}${node.name}`;
263
+ const slice = spannedSource(node, source);
264
+ if (slice?.startsWith(opening)) {
265
+ return slice;
266
+ }
267
+ return `${opening}${labelSource(node.children ?? [])}${attributeSource(node)}`;
268
+ };
269
+
270
+ // src/core/directive-diagnostics.ts
271
+ var CONTAINER_OPENING = /^[\t >]*:{3,}(?<name>[a-z][\w-]*)/gimu;
272
+ var codeList = (names) => [...names].map((name) => `\`${name}\``).join(", ");
273
+ var CALLOUT_NAMES = `${codeList(CALLOUT_TYPES)} (or the aliases ${codeList(Object.keys(CALLOUT_ALIASES))})`;
274
+ var unknownContainers = (text) => {
275
+ const named = [...text.matchAll(CONTAINER_OPENING)].some((match) => calloutTypeFor(match.groups?.name ?? "") === null);
276
+ if (!named) {
277
+ return [];
278
+ }
279
+ let tree;
280
+ try {
281
+ tree = mdxToMdast(text, { features: MDX_BODY_FEATURES });
282
+ } catch {
283
+ return [];
284
+ }
285
+ const found = [];
286
+ const walk = (node) => {
287
+ if (node.type === "containerDirective" && calloutTypeFor(node.name) === null) {
288
+ found.push({ line: node.position?.start.line ?? 1, name: node.name });
289
+ }
290
+ if ("children" in node) {
291
+ for (const child of node.children) {
292
+ walk(child);
293
+ }
294
+ }
295
+ };
296
+ walk(tree);
297
+ return found;
298
+ };
299
+ var unknownDirectiveDiagnostics = (entry, sourceName) => {
300
+ if (entry.body.format !== "mdx") {
301
+ return [];
302
+ }
303
+ const page = entry.sourcePath ?? `${sourceName}:${entry.ref}`;
304
+ const offset = entry.bodyLineOffset ?? strippedLineOffset(entry.raw, entry.body.text);
305
+ return unknownContainers(entry.expanded?.text ?? entry.body.text).map(({ line, name }) => {
306
+ const origin = entry.expanded?.origins[line - 1];
307
+ return {
308
+ code: "BLUME_UNKNOWN_DIRECTIVE",
309
+ file: origin?.file ?? page,
310
+ line: origin?.line ?? line + offset,
311
+ message: `\`:::${name}\` isn't a callout type, so the page shows its \`:::\` lines as written around its content.`,
312
+ severity: "warning",
313
+ suggestion: `Use a callout type — ${CALLOUT_NAMES} — or remove the \`:::\` lines to keep the content as plain prose.`
314
+ };
315
+ });
316
+ };
317
+
318
+ // src/core/localizable.ts
319
+ var isSingleLabel = (label) => typeof label === "string";
320
+ var resolveLocalizable = (label, locale, defaultLocale) => {
321
+ if (isSingleLabel(label)) {
322
+ return label;
323
+ }
324
+ return (locale === undefined ? undefined : label[locale]) ?? (defaultLocale === undefined ? undefined : label[defaultLocale]) ?? Object.values(label)[0] ?? "";
325
+ };
326
+
206
327
  // src/theme/icon-kind.ts
207
328
  var IMAGE_ICON = /^(?:https?:\/\/|data:image\/|\/|\.{1,2}\/)|\.(?:avif|gif|jpe?g|png|svg|webp)$/iu;
208
329
  var INLINE_SVG = /^\s*<svg[\s\S]*<\/svg>\s*$/u;
@@ -467,13 +588,6 @@ var localePagesFor = (code, real, fallback, fallbackByKey, i18n, basePath) => {
467
588
  }
468
589
  return [...real, ...filled];
469
590
  };
470
- var isSingleLabel = (label) => typeof label === "string";
471
- var resolveLabel = (label, locale, defaultLocale) => {
472
- if (isSingleLabel(label)) {
473
- return label;
474
- }
475
- return label[locale] ?? (defaultLocale === undefined ? undefined : label[defaultLocale]) ?? Object.values(label)[0] ?? "";
476
- };
477
591
  var localizeSidebarHrefs = (items, localize) => items.map((item) => {
478
592
  if (isPageRef(item)) {
479
593
  return item;
@@ -491,10 +605,19 @@ var resolveTabLabels = (tabs, locale, defaultLocale) => (tabs ?? []).map((tab) =
491
605
  ...tab,
492
606
  items: tab.items?.map((item) => ({
493
607
  ...item,
494
- label: resolveLabel(item.label, locale, defaultLocale)
608
+ label: resolveLocalizable(item.label, locale, defaultLocale)
495
609
  })),
496
- label: resolveLabel(tab.label, locale, defaultLocale)
610
+ label: resolveLocalizable(tab.label, locale, defaultLocale)
497
611
  }));
612
+ var withLabel = (link, locale, defaultLocale) => ({
613
+ ...link,
614
+ label: resolveLocalizable(link.label, locale, defaultLocale)
615
+ });
616
+ var resolveHeaderLinks = (navigation, locale, defaultLocale) => ({
617
+ actions: navigation.actions.map((link) => withLabel(link, locale, defaultLocale)),
618
+ cta: navigation.cta ? withLabel(navigation.cta, locale, defaultLocale) : null,
619
+ featured: navigation.featured.map((link) => withLabel(link, locale, defaultLocale))
620
+ });
498
621
  var mountConfiguredLink = (path, basePath, extraRoutes) => extraRoutes.has(path) ? path : withBasePath(basePath, path);
499
622
  var buildLocaleNavigation = (code, pages, fallback, fallbackByKey, options, i18n, diagnostics, version = "") => {
500
623
  const basePath = options.basePath ?? "";
@@ -538,17 +661,17 @@ var buildLocaleNavigation = (code, pages, fallback, fallbackByKey, options, i18n
538
661
  ...item,
539
662
  href: localizeServed(item.href, false)
540
663
  });
541
- const { actions, cta, featured } = options.navigation;
664
+ const { actions, cta, featured } = resolveHeaderLinks(options.navigation, code, i18n.defaultLocale);
542
665
  const sidebarItems = options.navigation.sidebar.items;
543
666
  const navigation = buildNavigation(localePages, {
544
- actions: actions?.map(localizeHref),
667
+ actions: actions.map(localizeHref),
545
668
  basePath,
546
669
  cta: cta ? localizeHref(cta) : null,
547
670
  diagnostics,
548
671
  display: options.navigation.sidebar.display,
549
672
  extraRoutes: options.extraRoutes,
550
673
  fallbackMetaPrefix,
551
- featured: featured?.map(localizeHref),
674
+ featured: featured.map(localizeHref),
552
675
  folderMeta: options.folderMeta,
553
676
  localizedRoot: localizeRoute(versionizeRoute("/", version), code, i18n),
554
677
  metaPrefix: [version, localeDir].filter(Boolean).join("/"),
@@ -610,13 +733,11 @@ var buildVersionNavigation = (id, versionPages, options, diagnostics) => {
610
733
  }
611
734
  return {
612
735
  "": buildNavigation(versionPages, {
613
- actions: options.navigation.actions,
736
+ ...resolveHeaderLinks(options.navigation, ""),
614
737
  basePath: options.basePath ?? "",
615
- cta: options.navigation.cta,
616
738
  diagnostics,
617
739
  display: options.navigation.sidebar.display,
618
740
  extraRoutes: options.extraRoutes,
619
- featured: options.navigation.featured,
620
741
  folderMeta: options.folderMeta,
621
742
  localizedRoot: versionizeRoute("/", id),
622
743
  metaPrefix: id,
@@ -638,13 +759,11 @@ var buildContentGraph = (pages, options) => {
638
759
  ({ navigation, navigationByLocale } = buildI18nNavigation(currentPages, options, i18n, diagnostics));
639
760
  } else {
640
761
  navigation = buildNavigation(currentPages, {
641
- actions: options.navigation.actions,
762
+ ...resolveHeaderLinks(options.navigation, ""),
642
763
  basePath: options.basePath ?? "",
643
- cta: options.navigation.cta,
644
764
  diagnostics,
645
765
  display: options.navigation.sidebar.display,
646
766
  extraRoutes: options.extraRoutes,
647
- featured: options.navigation.featured,
648
767
  folderMeta: options.folderMeta,
649
768
  selectors: options.navigation.selectors,
650
769
  sharedFolderMeta: options.sharedFolderMeta,
@@ -681,7 +800,8 @@ var buildContentGraph = (pages, options) => {
681
800
 
682
801
  // src/core/last-modified.ts
683
802
  import { execFileSync } from "node:child_process";
684
- import { relative } from "pathe";
803
+ import { realpathSync } from "node:fs";
804
+ import { normalize as normalize2, relative } from "pathe";
685
805
  var GIT_LOCATION_VARS = new Set([
686
806
  "GIT_COMMON_DIR",
687
807
  "GIT_DIR",
@@ -705,6 +825,13 @@ var parseGitLog = (output) => {
705
825
  }
706
826
  return times;
707
827
  };
828
+ var realPath = (path) => {
829
+ try {
830
+ return normalize2(realpathSync.native(path));
831
+ } catch {
832
+ return path;
833
+ }
834
+ };
708
835
  var gitRepositoryRoot = (root) => {
709
836
  try {
710
837
  return execFileSync("git", ["-C", root, "rev-parse", "--show-toplevel"], { encoding: "utf-8", env: gitEnv(), stdio: ["ignore", "pipe", "ignore"] }).trim();
@@ -720,6 +847,7 @@ var gitLastModifiedTimes = (root, contentRoots, sourcePaths, repositoryRoot) =>
720
847
  if (gitRoot === null) {
721
848
  return new Map;
722
849
  }
850
+ const top = realPath(gitRoot);
723
851
  try {
724
852
  const output = execFileSync("git", [
725
853
  "-C",
@@ -730,12 +858,12 @@ var gitLastModifiedTimes = (root, contentRoots, sourcePaths, repositoryRoot) =>
730
858
  "--format=%x00%cI",
731
859
  "--name-only",
732
860
  "--",
733
- ...contentRoots
861
+ ...contentRoots.map(realPath)
734
862
  ], { encoding: "utf-8", env: gitEnv(), maxBuffer: 256 * 1024 * 1024 });
735
863
  const byRepoPath = parseGitLog(output);
736
864
  const result = new Map;
737
865
  for (const sourcePath of sourcePaths) {
738
- const iso = byRepoPath.get(relative(gitRoot, sourcePath));
866
+ const iso = byRepoPath.get(relative(top, realPath(sourcePath)));
739
867
  if (iso) {
740
868
  result.set(sourcePath, iso);
741
869
  }
@@ -797,6 +925,20 @@ var globBase = (pattern) => {
797
925
  };
798
926
  var onPathOf = (dir, base) => dir === base || base === "" || dir === "" || dir.startsWith(`${base}/`) || base.startsWith(`${dir}/`);
799
927
  var withinInclude = (dir, include) => include === undefined || include.some((pattern) => !pattern.startsWith("!") && onPathOf(dir, globBase(pattern)));
928
+ var findFolderMetaFiles = async (source, patterns = META_FILES) => {
929
+ const found = await glob([...patterns], {
930
+ absolute: true,
931
+ cwd: source.root,
932
+ ignore: [
933
+ ...source.exclude ?? [],
934
+ "**/node_modules/**",
935
+ "**/.blume/**",
936
+ "**/dist/**"
937
+ ],
938
+ onlyFiles: true
939
+ });
940
+ return found.filter((file) => withinInclude(relative2(source.root, dirname(file)), source.include));
941
+ };
800
942
  var metaKeyFor = (prefix, dir) => {
801
943
  const clean = prefix ? trimChar(prefix, "/") : "";
802
944
  if (!clean) {
@@ -813,18 +955,7 @@ var discoverFolderMeta = async (sources, options = {}) => {
813
955
  const shared = new Map;
814
956
  const diagnostics = [];
815
957
  const perSource = await Promise.all(list.map(async (source) => {
816
- const found = await glob(META_FILES, {
817
- absolute: true,
818
- cwd: source.root,
819
- ignore: [
820
- ...source.exclude ?? [],
821
- "**/node_modules/**",
822
- "**/.blume/**",
823
- "**/dist/**"
824
- ],
825
- onlyFiles: true
826
- });
827
- const files = found.filter((file) => withinInclude(relative2(source.root, dirname(file)), source.include));
958
+ const files = await findFolderMetaFiles(source);
828
959
  const loaded = await Promise.all(files.map(async (file) => {
829
960
  try {
830
961
  return {
@@ -875,30 +1006,6 @@ var discoverFolderMeta = async (sources, options = {}) => {
875
1006
  // src/core/sources/resolve.ts
876
1007
  import { join as join7 } from "pathe";
877
1008
 
878
- // src/core/sources/json.ts
879
- var isJsonObject = (value) => typeof value === "object" && value !== null;
880
- var getPath = (doc, path) => {
881
- let current = doc;
882
- for (const key of path.split(".")) {
883
- if (isJsonObject(current)) {
884
- current = current[key];
885
- } else {
886
- return;
887
- }
888
- }
889
- return current;
890
- };
891
- var isStringValue2 = (value) => typeof value === "string";
892
- var asString = (value) => isStringValue2(value) ? value : undefined;
893
- var asArray = (value) => Array.isArray(value) ? value : [];
894
- var asObject = (value) => isJsonObject(value) && !Array.isArray(value) ? value : undefined;
895
- var isNumberValue = (value) => typeof value === "number";
896
- var asNumber = (value) => isNumberValue(value) ? value : undefined;
897
- var objectsIn = (value) => asArray(value).flatMap((item) => {
898
- const object = asObject(item);
899
- return object ? [object] : [];
900
- });
901
-
902
1009
  // src/core/sources/contentful-rich-text.ts
903
1010
  var HEADING = /^heading-(?<level>[1-6])$/u;
904
1011
  var CELL_PIPE = /\|/gu;
@@ -965,30 +1072,31 @@ var embeddedEntry = (node, options) => {
965
1072
  }
966
1073
  return unsupported(`Contentful embedded entry${contentType ? `: ${contentType}` : ""}`, writesMdx(options.serializers));
967
1074
  };
968
- var renderInlines = (nodes, options) => nodes.map((node) => renderInlineNode(node, options)).join("");
969
- var renderInlineNode = (node, options) => {
1075
+ var inlineParts = (nodes, options) => nodes.flatMap((node) => inlineNodeParts(node, options));
1076
+ var inlineNodeParts = (node, options) => {
970
1077
  switch (asString(node.nodeType)) {
971
1078
  case "text": {
972
- return renderInline(asString(node.value) ?? "", marksOf(node));
1079
+ return [{ marks: marksOf(node), text: asString(node.value) ?? "" }];
973
1080
  }
974
1081
  case "hyperlink": {
975
- return renderLink(renderInlines(children(node), options), asString(getPath(node, "data.uri")));
1082
+ return linkParts(inlineParts(children(node), options), asString(getPath(node, "data.uri")));
976
1083
  }
977
1084
  case "asset-hyperlink": {
978
- return renderLink(renderInlines(children(node), options), linkedAsset(node, options)?.url);
1085
+ return linkParts(inlineParts(children(node), options), linkedAsset(node, options)?.url);
979
1086
  }
980
1087
  case "embedded-entry-inline": {
981
- return embeddedEntry(node, options);
1088
+ return [{ markdown: embeddedEntry(node, options) }];
982
1089
  }
983
1090
  default: {
984
- return renderInlines(children(node), options);
1091
+ return inlineParts(children(node), options);
985
1092
  }
986
1093
  }
987
1094
  };
1095
+ var blockText = (node, options) => guardBlockStart(renderInline(inlineParts(children(node), options)));
988
1096
  var renderList = (items, marker, options) => items.map((item, index) => listItem(marker(index), children(item).map((child) => renderBlock(child, options)).filter((block) => block !== "").join(`
989
1097
  `))).join(`
990
1098
  `);
991
- var cellText = (cell, options) => children(cell).map((paragraph) => renderInlines(children(paragraph), options)).join(" ").replaceAll(CELL_BREAK, " ").replaceAll(CELL_PIPE, String.raw`\|`);
1099
+ var cellText = (cell, options) => children(cell).map((paragraph) => blockText(paragraph, options)).join(" ").replaceAll(CELL_BREAK, " ").replaceAll(CELL_PIPE, String.raw`\|`);
992
1100
  var tableRow = (cells) => `| ${cells.join(" | ")} |`;
993
1101
  var renderTable = (node, options) => {
994
1102
  const rows = children(node).map((row) => children(row).map((cell) => cellText(cell, options)));
@@ -1007,11 +1115,11 @@ var renderBlock = (node, options) => {
1007
1115
  const type = asString(node.nodeType) ?? "";
1008
1116
  const heading = HEADING.exec(type)?.groups?.level;
1009
1117
  if (heading) {
1010
- return `${headingPrefix(Number(heading))}${guardBlockStart(renderInlines(children(node), options))}`;
1118
+ return `${headingPrefix(Number(heading))}${blockText(node, options)}`;
1011
1119
  }
1012
1120
  switch (type) {
1013
1121
  case "paragraph": {
1014
- return guardBlockStart(renderInlines(children(node), options));
1122
+ return blockText(node, options);
1015
1123
  }
1016
1124
  case "blockquote": {
1017
1125
  return blockquote(joinBlocks(children(node).map((child) => renderBlock(child, options))));
@@ -1230,7 +1338,17 @@ var filesystemSource = (options) => {
1230
1338
  onlyFiles: true
1231
1339
  });
1232
1340
  files.sort();
1233
- const entries = await Promise.all(files.map(async (file) => {
1341
+ const diagnostics = [];
1342
+ const loadable = [];
1343
+ for (const file of files) {
1344
+ const unloadable = unloadablePathDiagnostic(relative3(contentRoot, file), file);
1345
+ if (unloadable) {
1346
+ diagnostics.push(unloadable);
1347
+ } else {
1348
+ loadable.push(file);
1349
+ }
1350
+ }
1351
+ const entries = await Promise.all(loadable.map(async (file) => {
1234
1352
  const source = await readFile(file, "utf-8");
1235
1353
  const ext = extname(file).toLowerCase();
1236
1354
  const format = ext === ".mdx" ? "mdx" : "md";
@@ -1243,7 +1361,7 @@ var filesystemSource = (options) => {
1243
1361
  sourcePath: file
1244
1362
  };
1245
1363
  }));
1246
- return { diagnostics: [], entries };
1364
+ return { diagnostics, entries };
1247
1365
  };
1248
1366
  const validate = () => {
1249
1367
  if (!existsSync(contentRoot)) {
@@ -1284,7 +1402,7 @@ var filesystemSource = (options) => {
1284
1402
  // src/core/sources/github-releases.ts
1285
1403
  import { fromMarkdown } from "mdast-util-from-markdown";
1286
1404
  import { gfmFromMarkdown } from "mdast-util-gfm";
1287
- import { toString as mdastToString } from "mdast-util-to-string";
1405
+ import { toString as mdastToString2 } from "mdast-util-to-string";
1288
1406
  import { gfm } from "micromark-extension-gfm";
1289
1407
  import stringWidth from "string-width";
1290
1408
  var DEFAULT_LIMIT = 100;
@@ -1303,7 +1421,7 @@ var releaseDescription = (body) => {
1303
1421
  extensions: [gfm()],
1304
1422
  mdastExtensions: [gfmFromMarkdown()]
1305
1423
  });
1306
- const text = tree.children.filter((node) => !NON_PROSE.has(node.type)).map((node) => mdastToString(node, { includeHtml: false, includeImageAlt: false })).join(" ").replaceAll(WHITESPACE, " ").trim();
1424
+ const text = tree.children.filter((node) => !NON_PROSE.has(node.type)).map((node) => mdastToString2(node, { includeHtml: false, includeImageAlt: false })).join(" ").replaceAll(WHITESPACE, " ").trim();
1307
1425
  if (!text) {
1308
1426
  return;
1309
1427
  }
@@ -1357,7 +1475,7 @@ var rewrittenLink = (markdown, node, path) => {
1357
1475
  }
1358
1476
  const start = node.position?.start.offset ?? 0;
1359
1477
  if (markdown[start] !== "[") {
1360
- return `[${escapeMarkdownText(mdastToString(node))}](${target})`;
1478
+ return `[${escapeMarkdownText(mdastToString2(node))}](${target})`;
1361
1479
  }
1362
1480
  const first = node.children.at(0)?.position?.start.offset ?? start + 1;
1363
1481
  const last = node.children.at(-1)?.position?.end.offset ?? first;
@@ -1449,11 +1567,21 @@ var githubReleasesSource = (options, ctx) => {
1449
1567
  const include = (release) => (options.drafts || !release.draft) && (options.prereleases || !release.prerelease);
1450
1568
  const fetchPage = async (page) => {
1451
1569
  const url = `${base}/repos/${options.owner}/${options.repo}/releases?per_page=${PER_PAGE}&page=${page}`;
1452
- const res = await doFetch(url, { headers: githubHeaders() });
1453
- if (!res.ok) {
1454
- throw new Error(`${url} -> ${res.status}`);
1570
+ try {
1571
+ const res = await doFetch(url, {
1572
+ headers: githubHeaders(),
1573
+ signal: AbortSignal.timeout(REMOTE_TIMEOUT_MS)
1574
+ });
1575
+ if (!res.ok) {
1576
+ throw new Error(`${url} -> ${res.status}`);
1577
+ }
1578
+ return await res.json();
1579
+ } catch (error) {
1580
+ if (error instanceof DOMException && error.name === "TimeoutError") {
1581
+ throw new Error(`${url} did not respond within ${REMOTE_TIMEOUT_MS / 1000}s`, { cause: error });
1582
+ }
1583
+ throw error;
1455
1584
  }
1456
- return await res.json();
1457
1585
  };
1458
1586
  const fetchReleases = async () => {
1459
1587
  const collected = [];
@@ -1527,15 +1655,29 @@ var githubHeaders2 = (url) => {
1527
1655
  }
1528
1656
  return GITHUB_HOSTS.has(host) ? { authorization: `Bearer ${token}` } : {};
1529
1657
  };
1658
+ var fetchText = async (url, doFetch) => {
1659
+ try {
1660
+ const res = await doFetch(url, {
1661
+ headers: githubHeaders2(url),
1662
+ signal: AbortSignal.timeout(REMOTE_TIMEOUT_MS)
1663
+ });
1664
+ if (!res.ok) {
1665
+ throw new Error(`${url} -> ${res.status}`);
1666
+ }
1667
+ return await res.text();
1668
+ } catch (error) {
1669
+ if (error instanceof DOMException && error.name === "TimeoutError") {
1670
+ throw new Error(`${url} did not respond within ${REMOTE_TIMEOUT_MS / 1000}s`, { cause: error });
1671
+ }
1672
+ throw error;
1673
+ }
1674
+ };
1530
1675
  var enumerateGithub = async (github, include, doFetch) => {
1531
1676
  const { owner, repo, ref } = github;
1532
1677
  const base = github.path.replaceAll(/^\/|\/$/gu, "");
1533
1678
  const treeUrl = `https://api.github.com/repos/${owner}/${repo}/git/trees/${ref}?recursive=1`;
1534
- const res = await doFetch(treeUrl, { headers: githubHeaders2(treeUrl) });
1535
- if (!res.ok) {
1536
- throw new Error(`${treeUrl} -> ${res.status}`);
1537
- }
1538
- const body = await res.json();
1679
+ const text = await fetchText(treeUrl, doFetch);
1680
+ const body = JSON.parse(text);
1539
1681
  const prefix = base ? `${base}/` : "";
1540
1682
  const included = picomatch(include);
1541
1683
  const refs = (body.tree ?? []).flatMap((node) => {
@@ -1580,13 +1722,7 @@ var mdxRemoteSource = (options, ctx) => {
1580
1722
  return { refs, truncated: false };
1581
1723
  };
1582
1724
  const fetchEntry = async (item) => {
1583
- const res = await doFetch(item.fetchUrl, {
1584
- headers: githubHeaders2(item.fetchUrl)
1585
- });
1586
- if (!res.ok) {
1587
- throw new Error(`${item.fetchUrl} -> ${res.status}`);
1588
- }
1589
- const text = await res.text();
1725
+ const text = await fetchText(item.fetchUrl, doFetch);
1590
1726
  const parsed = frontmatter_default(text);
1591
1727
  const format = item.ref.toLowerCase().endsWith(".mdx") ? "mdx" : "md";
1592
1728
  return {
@@ -1610,13 +1746,16 @@ var mdxRemoteSource = (options, ctx) => {
1610
1746
  severity: "warning"
1611
1747
  });
1612
1748
  }
1749
+ const reasons = [];
1613
1750
  const settled = await Promise.all(refs.map(async (ref) => {
1614
1751
  try {
1615
1752
  return await fetchEntry(ref);
1616
1753
  } catch (error) {
1754
+ const reason = error.message;
1755
+ reasons.push(reason);
1617
1756
  skipped.push({
1618
1757
  code: "BLUME_SOURCE_FETCH_FAILED",
1619
- message: `Source "${options.name}" skipped "${ref.ref}" (${error.message}); the rest were imported.`,
1758
+ message: `Source "${options.name}" skipped "${ref.ref}" (${reason}); the rest were imported.`,
1620
1759
  severity: "warning"
1621
1760
  });
1622
1761
  return null;
@@ -1625,7 +1764,7 @@ var mdxRemoteSource = (options, ctx) => {
1625
1764
  const entries = settled.filter((entry) => entry !== null);
1626
1765
  if (refs.length > 0 && entries.length === 0) {
1627
1766
  skipped.length = 0;
1628
- throw new Error(`all ${refs.length} remote file(s) failed to fetch`);
1767
+ throw new Error(`all ${refs.length} remote file(s) failed to fetch (${reasons[0]})`);
1629
1768
  }
1630
1769
  return entries;
1631
1770
  }, refresh);
@@ -1647,6 +1786,7 @@ var mdxRemoteSource = (options, ctx) => {
1647
1786
  return {
1648
1787
  load,
1649
1788
  name: options.name,
1789
+ orderedNames: true,
1650
1790
  prefix: options.prefix,
1651
1791
  read,
1652
1792
  staged: true,
@@ -1825,12 +1965,27 @@ var materializeAssets = async (markdown, ctx) => {
1825
1965
  };
1826
1966
 
1827
1967
  // src/core/sources/notion.ts
1828
- var richToMarkdown = (rich = []) => rich.map(({ annotations = {}, href, plain_text: text }) => renderLink(renderInline(text, {
1829
- bold: annotations.bold,
1830
- code: annotations.code,
1831
- italic: annotations.italic,
1832
- strike: annotations.strikethrough
1833
- }), href ?? undefined)).join("");
1968
+ var richToMarkdown = (rich = []) => {
1969
+ const linked = [];
1970
+ for (const { annotations = {}, href, plain_text: text } of rich) {
1971
+ const run = {
1972
+ marks: {
1973
+ bold: annotations.bold,
1974
+ code: annotations.code,
1975
+ italic: annotations.italic,
1976
+ strike: annotations.strikethrough
1977
+ },
1978
+ text
1979
+ };
1980
+ const last = linked.at(-1);
1981
+ if (last && last.href === (href ?? undefined)) {
1982
+ last.runs.push(run);
1983
+ } else {
1984
+ linked.push({ href: href ?? undefined, runs: [run] });
1985
+ }
1986
+ }
1987
+ return renderInline(linked.flatMap(({ href, runs }) => linkParts(runs, href)));
1988
+ };
1834
1989
  var isBlockPayload = (value) => typeof value === "object";
1835
1990
  var payloadOf = (block) => {
1836
1991
  const value = block[block.type];
@@ -1884,7 +2039,7 @@ var renderVideo = (data) => {
1884
2039
  }
1885
2040
  const caption = richToMarkdown(data.caption);
1886
2041
  const title = caption ? ` title=${jsxString(richToPlain(data.caption))}` : "";
1887
- const media = isYouTubeUrl(url) ? `<YouTube${title} url=${JSON.stringify(url)} />` : `<video controls src=${JSON.stringify(url)} />`;
2042
+ const media = isYouTubeUrl(url) ? `<YouTube${title} url=${jsxString(url)} />` : `<video controls src="${url.replaceAll('"', "%22")}" />`;
1888
2043
  return caption ? `<Frame caption=${jsxString(caption.replaceAll(FRAME_ESCAPED, ""))}>
1889
2044
  ${media}
1890
2045
  </Frame>` : media;
@@ -2074,7 +2229,7 @@ ${nested}`;
2074
2229
  data.sidebar = { order };
2075
2230
  }
2076
2231
  const slugProp = richToPlain(page.properties[props.slug ?? "Slug"]?.rich_text);
2077
- const slug = slugifyPath(slugProp || title) || page.id;
2232
+ const slug = (slugProp ? slugifyPath(slugProp) : slugify(title.replaceAll("/", "-"))) || page.id;
2078
2233
  return { data, slug };
2079
2234
  };
2080
2235
  const toEntry = async (client, page) => {
@@ -2567,14 +2722,26 @@ var obsidianSource = (options, ctx) => {
2567
2722
  const vaultDir = resolve2(ctx.projectRoot, options.vault);
2568
2723
  const exclude = new Set([...BLUME_IGNORE_DIRS, ...options.exclude ?? []]);
2569
2724
  const load = async () => {
2570
- const files = await walkVault(vaultDir, vaultDir, exclude);
2725
+ const skipped = [];
2726
+ const files = [];
2727
+ for (const rel of await walkVault(vaultDir, vaultDir, exclude)) {
2728
+ const unloadable = unloadablePathDiagnostic(rel, join5(vaultDir, rel));
2729
+ if (unloadable) {
2730
+ skipped.push(unloadable);
2731
+ } else {
2732
+ files.push(rel);
2733
+ }
2734
+ }
2571
2735
  const read = await Promise.all(files.map((rel) => readNote(vaultDir, rel, options)));
2572
2736
  const notes = read.filter((note) => note !== null);
2573
2737
  const { index, pairs } = buildLinkIndex(notes, options);
2574
2738
  const unresolved = noTargets();
2575
2739
  const entries = pairs.map((pair) => noteToEntry(pair, index, options, unresolved));
2576
2740
  return {
2577
- diagnostics: unresolvedDiagnostics(options.name, unresolved),
2741
+ diagnostics: [
2742
+ ...skipped,
2743
+ ...unresolvedDiagnostics(options.name, unresolved)
2744
+ ],
2578
2745
  entries
2579
2746
  };
2580
2747
  };
@@ -2652,32 +2819,33 @@ var customBlock = (node, options) => {
2652
2819
  }
2653
2820
  return unsupported(`Lexical block${blockType ? `: ${blockType}` : ""}`, writesMdx(options.serializers));
2654
2821
  };
2655
- var renderInlines2 = (nodes, options) => nodes.map((node) => renderInlineNode2(node, options)).join("");
2656
- var renderInlineNode2 = (node, options) => {
2822
+ var inlineParts2 = (nodes, options) => nodes.flatMap((node) => inlineNodeParts2(node, options));
2823
+ var inlineNodeParts2 = (node, options) => {
2657
2824
  switch (typeOf(node)) {
2658
2825
  case "text": {
2659
- return renderInline(asString(node.text) ?? "", marksOf2(node));
2826
+ return [{ marks: marksOf2(node), text: asString(node.text) ?? "" }];
2660
2827
  }
2661
2828
  case "linebreak": {
2662
- return `
2663
- `;
2829
+ return [{ markdown: `
2830
+ ` }];
2664
2831
  }
2665
2832
  case "tab": {
2666
- return "\t";
2833
+ return [{ markdown: "\t" }];
2667
2834
  }
2668
2835
  case "link":
2669
2836
  case "autolink": {
2670
- return renderLink(renderInlines2(children2(node), options), asString(getPath(node, "fields.url")) ?? asString(node.url));
2837
+ return linkParts(inlineParts2(children2(node), options), asString(getPath(node, "fields.url")) ?? asString(node.url));
2671
2838
  }
2672
2839
  case "inlineBlock": {
2673
- return customBlock(node, options);
2840
+ return [{ markdown: customBlock(node, options) }];
2674
2841
  }
2675
2842
  default: {
2676
- return renderInlines2(children2(node), options);
2843
+ return inlineParts2(children2(node), options);
2677
2844
  }
2678
2845
  }
2679
2846
  };
2680
- var blockText = (node, options) => guardBlockStart(renderInlines2(children2(node), options));
2847
+ var inlineText = (nodes, options) => guardBlockStart(renderInline(inlineParts2(nodes, options)));
2848
+ var blockText2 = (node, options) => inlineText(children2(node), options);
2681
2849
  var renderUpload = (node, options) => {
2682
2850
  const value = asObject(node.value);
2683
2851
  const url = value ? asString(value.url) : undefined;
@@ -2708,7 +2876,7 @@ var renderList2 = (node, options) => {
2708
2876
  if (listType === "check") {
2709
2877
  check = item.checked === true ? "[x] " : "[ ] ";
2710
2878
  }
2711
- const line = `${check}${guardBlockStart(renderInlines2(inline, options))}`;
2879
+ const line = `${check}${inlineText(inline, options)}`;
2712
2880
  items.push(listItem(lastMarker, sub ? `${line}
2713
2881
  ${sub}` : line));
2714
2882
  index += 1;
@@ -2719,14 +2887,14 @@ ${sub}` : line));
2719
2887
  var renderBlock2 = (node, options) => {
2720
2888
  switch (typeOf(node)) {
2721
2889
  case "paragraph": {
2722
- return blockText(node, options);
2890
+ return blockText2(node, options);
2723
2891
  }
2724
2892
  case "heading": {
2725
2893
  const level = Number((asString(node.tag) ?? "h1").slice(1));
2726
- return `${headingPrefix(level)}${blockText(node, options)}`;
2894
+ return `${headingPrefix(level)}${blockText2(node, options)}`;
2727
2895
  }
2728
2896
  case "quote": {
2729
- return blockquote(blockText(node, options));
2897
+ return blockquote(blockText2(node, options));
2730
2898
  }
2731
2899
  case "list": {
2732
2900
  return renderList2(node, options);
@@ -2825,19 +2993,31 @@ var HEADING_STYLES = new Map([
2825
2993
  ["h5", "##### "],
2826
2994
  ["h6", "###### "]
2827
2995
  ]);
2828
- var renderSpan = (span, defs) => {
2996
+ var spanRun = (span) => {
2829
2997
  const marks = span.marks ?? [];
2830
- const link = marks.map((mark) => defs.get(mark)).findLast((def) => def?._type === "link");
2831
- return renderLink(renderInline(span.text ?? "", {
2832
- bold: marks.includes("strong"),
2833
- code: marks.includes("code"),
2834
- italic: marks.includes("em"),
2835
- strike: marks.includes("strike-through")
2836
- }), link?.href);
2998
+ return {
2999
+ marks: {
3000
+ bold: marks.includes("strong"),
3001
+ code: marks.includes("code"),
3002
+ italic: marks.includes("em"),
3003
+ strike: marks.includes("strike-through")
3004
+ },
3005
+ text: span.text ?? ""
3006
+ };
2837
3007
  };
2838
3008
  var renderChildren = (block) => {
2839
3009
  const defs = new Map((block.markDefs ?? []).map((def) => [def._key, def]));
2840
- return guardBlockStart((block.children ?? []).map((span) => renderSpan(span, defs)).join(""));
3010
+ const linked = [];
3011
+ for (const span of block.children ?? []) {
3012
+ const link = (span.marks ?? []).map((mark) => defs.get(mark)).findLast((def) => def?._type === "link");
3013
+ const last = linked.at(-1);
3014
+ if (last && last.link === link) {
3015
+ last.runs.push(spanRun(span));
3016
+ } else {
3017
+ linked.push({ link, runs: [spanRun(span)] });
3018
+ }
3019
+ }
3020
+ return guardBlockStart(renderInline(linked.flatMap(({ link, runs }) => linkParts(runs, link?.href))));
2841
3021
  };
2842
3022
  var isAltText = (value) => typeof value === "string";
2843
3023
  var listMarker = (block) => block.listItem === "number" ? "1." : "-";
@@ -2996,31 +3176,36 @@ var sanitySource = (options, ctx) => {
2996
3176
  // src/core/sources/strapi-blocks.ts
2997
3177
  var children3 = (node) => objectsIn(node.children);
2998
3178
  var typeOf2 = (node) => asString(node.type) ?? "";
2999
- var renderInlines3 = (nodes) => nodes.map((node) => renderInlineNode3(node)).join("");
3000
- var renderInlineNode3 = (node) => {
3179
+ var inlineParts3 = (nodes) => nodes.flatMap((node) => inlineNodeParts3(node));
3180
+ var inlineNodeParts3 = (node) => {
3001
3181
  switch (typeOf2(node)) {
3002
3182
  case "text": {
3003
- return renderInline(asString(node.text) ?? "", {
3004
- bold: node.bold === true,
3005
- code: node.code === true,
3006
- italic: node.italic === true,
3007
- strike: node.strikethrough === true
3008
- });
3183
+ return [
3184
+ {
3185
+ marks: {
3186
+ bold: node.bold === true,
3187
+ code: node.code === true,
3188
+ italic: node.italic === true,
3189
+ strike: node.strikethrough === true
3190
+ },
3191
+ text: asString(node.text) ?? ""
3192
+ }
3193
+ ];
3009
3194
  }
3010
3195
  case "link": {
3011
- return renderLink(renderInlines3(children3(node)), asString(node.url));
3196
+ return linkParts(inlineParts3(children3(node)), asString(node.url));
3012
3197
  }
3013
3198
  default: {
3014
- return renderInlines3(children3(node));
3199
+ return inlineParts3(children3(node));
3015
3200
  }
3016
3201
  }
3017
3202
  };
3018
- var blockText2 = (nodes) => guardBlockStart(renderInlines3(nodes));
3203
+ var blockText3 = (nodes) => guardBlockStart(renderInline(inlineParts3(nodes)));
3019
3204
  var renderList3 = (node) => {
3020
3205
  const ordered = asString(node.format) === "ordered";
3021
3206
  return children3(node).map((item, index) => {
3022
3207
  const kids = children3(item);
3023
- const line = blockText2(kids.filter((kid) => typeOf2(kid) !== "list"));
3208
+ const line = blockText3(kids.filter((kid) => typeOf2(kid) !== "list"));
3024
3209
  const sub = kids.filter((kid) => typeOf2(kid) === "list").map((list) => renderList3(list)).join(`
3025
3210
  `);
3026
3211
  const body = sub ? `${line}
@@ -3040,13 +3225,13 @@ var renderImage = (node, options) => {
3040
3225
  var renderBlock4 = (node, options) => {
3041
3226
  switch (typeOf2(node)) {
3042
3227
  case "paragraph": {
3043
- return blockText2(children3(node));
3228
+ return blockText3(children3(node));
3044
3229
  }
3045
3230
  case "heading": {
3046
- return `${headingPrefix(asNumber(node.level) ?? 1)}${blockText2(children3(node))}`;
3231
+ return `${headingPrefix(asNumber(node.level) ?? 1)}${blockText3(children3(node))}`;
3047
3232
  }
3048
3233
  case "quote": {
3049
- return blockquote(blockText2(children3(node)));
3234
+ return blockquote(blockText3(children3(node)));
3050
3235
  }
3051
3236
  case "list": {
3052
3237
  return renderList3(node);
@@ -3317,13 +3502,63 @@ var normalizeLoadedEntries = (loaded, config) => {
3317
3502
  }
3318
3503
  pages.push(...normalized.pages);
3319
3504
  allDiagnostics.push(...normalized.diagnostics);
3505
+ if (normalized.pages.length > 0) {
3506
+ allDiagnostics.push(...unknownDirectiveDiagnostics(entry, source.name));
3507
+ }
3320
3508
  }
3321
3509
  }
3322
3510
  return { diagnostics: allDiagnostics, droppedPages, pages };
3323
3511
  };
3512
+ var gitContentRoots = (sources, gitRoot) => {
3513
+ if (gitRoot === null) {
3514
+ return [];
3515
+ }
3516
+ const top = realPath(gitRoot);
3517
+ return sources.flatMap((source) => source.contentRoot ? [source.contentRoot] : []).filter((dir) => isWithin(top, realPath(dir)));
3518
+ };
3324
3519
  var isLogoShorthand = (logo) => typeof logo === "string";
3325
3520
  var logoHref = (logo) => logo === undefined || isLogoShorthand(logo) ? "/" : logo.href ?? "/";
3326
3521
  var isBannerShorthand = (banner) => typeof banner === "string";
3522
+ var substituteEntryVariables = (entry, variables) => {
3523
+ const { expanded } = entry;
3524
+ const text = expanded?.text ?? entry.body.text;
3525
+ const offset = expanded ? 0 : strippedLineOffset(entry.raw, entry.body.text);
3526
+ const diagnostics = undefinedVariables(text, variables).map(({ line, name }) => {
3527
+ const origin = expanded?.origins[line - 1];
3528
+ return {
3529
+ code: "BLUME_UNDEFINED_VARIABLE",
3530
+ file: origin?.file ?? entry.sourcePath,
3531
+ line: origin?.line ?? line + offset,
3532
+ message: `{{${name}}} isn't a defined variable, so it would show as written.`,
3533
+ severity: "error",
3534
+ suggestion: `Define "${name}" under variables in blume.config.ts, or put it in inline code to show it as written.`
3535
+ };
3536
+ });
3537
+ if (expanded) {
3538
+ expanded.text = substituteVariables(expanded.text, variables);
3539
+ } else {
3540
+ entry.body.text = substituteVariables(entry.body.text, variables);
3541
+ }
3542
+ return diagnostics;
3543
+ };
3544
+ var substituteLoadedVariables = (loaded, variables) => hasVariables(variables) ? loaded.flatMap(({ entries }) => entries.flatMap((entry) => substituteEntryVariables(entry, variables))) : [];
3545
+ var redirectPageDiagnostics = (config, pages, configFile) => config.redirects.flatMap((redirect) => {
3546
+ const matched = pathsUnderPattern(withBasePath(config.basePath, redirect.from), pages);
3547
+ const [first] = matched;
3548
+ if (first === undefined) {
3549
+ return [];
3550
+ }
3551
+ const more = matched.length > 1 ? ` and ${matched.length - 1} more` : "";
3552
+ return [
3553
+ {
3554
+ code: "BLUME_REDIRECT_MATCHES_PAGE",
3555
+ file: configFile ?? undefined,
3556
+ message: `The redirect from ${redirect.from} also matches the page ${first}${more}, which some hosts would redirect and others would serve.`,
3557
+ severity: "error",
3558
+ suggestion: "Narrow the pattern to the paths that moved, or move the pages out from under it."
3559
+ }
3560
+ ];
3561
+ });
3327
3562
  var bannerLinkHref = (banner) => banner === undefined || isBannerShorthand(banner) ? undefined : banner.link?.href;
3328
3563
  var scanProject = async (root, options = {}) => {
3329
3564
  const mode = options.mode ?? "dev";
@@ -3377,6 +3612,7 @@ var scanProject = async (root, options = {}) => {
3377
3612
  includeDiagnostics.push(...expansion.errors);
3378
3613
  });
3379
3614
  }));
3615
+ const variableDiagnostics = substituteLoadedVariables(loaded, config.variables);
3380
3616
  const sharedFolderMeta = new Map([
3381
3617
  ...loaded.flatMap(({ folderMeta: sourceMeta }) => Object.entries(sourceMeta ?? {})),
3382
3618
  ...folderMeta.shared
@@ -3392,7 +3628,7 @@ var scanProject = async (root, options = {}) => {
3392
3628
  if (lastModified.enabled && lastModified.source === "git") {
3393
3629
  const fsPaths = pages.map((page) => page.sourcePath).filter((path) => path !== undefined);
3394
3630
  const gitRoot = gitRepositoryRoot(context.root);
3395
- const contentRoots = sources.flatMap((source) => source.contentRoot ? [source.contentRoot] : []).filter((dir) => gitRoot !== null && isWithin(gitRoot, dir));
3631
+ const contentRoots = gitContentRoots(sources, gitRoot);
3396
3632
  const gitTimes = gitLastModifiedTimes(context.root, contentRoots, fsPaths, gitRoot);
3397
3633
  for (const page of pages) {
3398
3634
  if (!page.lastModified && page.sourcePath) {
@@ -3403,14 +3639,15 @@ var scanProject = async (root, options = {}) => {
3403
3639
  lastModifiedWarnings.push(...lastModifiedShallowWarning(context.root, undated));
3404
3640
  }
3405
3641
  const customPages = context.pagesRoot ? await discoverPages(context.pagesRoot) : [];
3642
+ const extraRoutes = new Set([
3643
+ ...customStaticRoutes(customPages),
3644
+ ...hasChangelogIndex(pages, config) ? [CHANGELOG_INDEX_ROUTE] : []
3645
+ ]);
3406
3646
  const graph = buildContentGraph(pages, {
3407
3647
  bannerHref: bannerLinkHref(config.banner),
3408
3648
  basePath: config.basePath,
3409
3649
  brandHref: logoHref(config.logo),
3410
- extraRoutes: new Set([
3411
- ...customStaticRoutes(customPages),
3412
- ...hasChangelogIndex(pages, config) ? [CHANGELOG_INDEX_ROUTE] : []
3413
- ]),
3650
+ extraRoutes,
3414
3651
  folderMeta: folderMeta.meta,
3415
3652
  i18n: config.i18n,
3416
3653
  navigation: config.navigation,
@@ -3426,12 +3663,14 @@ var scanProject = async (root, options = {}) => {
3426
3663
  diagnostics: [
3427
3664
  ...contentDiagnostics,
3428
3665
  ...includeDiagnostics,
3666
+ ...variableDiagnostics,
3429
3667
  ...folderMeta.diagnostics,
3430
3668
  ...entryIdDiagnostics(pages, resolveDocsCollection(config, context.root).base),
3431
3669
  ...graph.diagnostics,
3432
3670
  ...i18nWarnings,
3433
3671
  ...versionWarnings,
3434
- ...lastModifiedWarnings
3672
+ ...lastModifiedWarnings,
3673
+ ...redirectPageDiagnostics(config, [...manifest.routes.map((route) => route.path), ...extraRoutes], context.configFile)
3435
3674
  ],
3436
3675
  droppedPages,
3437
3676
  graph,
@@ -3442,7 +3681,7 @@ var scanProject = async (root, options = {}) => {
3442
3681
  };
3443
3682
  };
3444
3683
 
3445
- export { validateSearchPopularIcons, validateNavTargets, contentIndexable, buildManifest, isWithin, scanProject };
3684
+ export { directiveSource, resolveLocalizable, validateSearchPopularIcons, validateNavTargets, contentIndexable, buildManifest, findFolderMetaFiles, isWithin, scanProject };
3446
3685
 
3447
- //# debugId=B3E8BA7A9A3228DD64756E2164756E21
3448
- //# sourceMappingURL=chunk-5r8g91qn.js.map
3686
+ //# debugId=89E5C13A316C75D864756E2164756E21
3687
+ //# sourceMappingURL=chunk-43zcf4gz.js.map