blume 2.0.1 → 2.0.3

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 (492) hide show
  1. package/CHANGELOG.md +147 -0
  2. package/dist/cli/{chunk-qwsrynx5.js → chunk-1d7ve1dm.js} +38 -19
  3. package/dist/cli/{chunk-qwsrynx5.js.map → chunk-1d7ve1dm.js.map} +4 -4
  4. package/dist/cli/{chunk-s6jhgk0q.js → chunk-2eytanqx.js} +2 -2
  5. package/dist/cli/{chunk-kdp5q7ke.js → chunk-2hsdwb9n.js} +18 -19
  6. package/dist/cli/{chunk-kdp5q7ke.js.map → chunk-2hsdwb9n.js.map} +2 -2
  7. package/dist/cli/{chunk-hdpx1tax.js → chunk-2z928egk.js} +5 -5
  8. package/dist/cli/{chunk-jwyddg7y.js → chunk-35d4wj9f.js} +30 -24
  9. package/dist/cli/chunk-35d4wj9f.js.map +15 -0
  10. package/dist/cli/{chunk-ah61y8py.js → chunk-364znk6q.js} +2 -2
  11. package/dist/cli/{chunk-jts8mvcz.js → chunk-3em5wd2y.js} +25 -6
  12. package/dist/cli/{chunk-jts8mvcz.js.map → chunk-3em5wd2y.js.map} +3 -3
  13. package/dist/cli/{chunk-s1p84fyh.js → chunk-5f86nr5m.js} +63 -22
  14. package/dist/cli/chunk-5f86nr5m.js.map +11 -0
  15. package/dist/cli/{chunk-2hn4b8z7.js → chunk-5m5nmvyq.js} +170 -76
  16. package/dist/cli/chunk-5m5nmvyq.js.map +13 -0
  17. package/dist/cli/{chunk-epjnccmv.js → chunk-5xvm6tfj.js} +18 -15
  18. package/dist/cli/chunk-5xvm6tfj.js.map +10 -0
  19. package/dist/cli/{chunk-fz5wtpmh.js → chunk-6dsbexzp.js} +18 -15
  20. package/dist/cli/chunk-6dsbexzp.js.map +10 -0
  21. package/dist/cli/{chunk-vtk4a6dg.js → chunk-8ktnccpt.js} +1 -1
  22. package/dist/cli/{chunk-6hsn950k.js → chunk-9t7a85s3.js} +178 -48
  23. package/dist/cli/chunk-9t7a85s3.js.map +10 -0
  24. package/dist/cli/{chunk-fxypxtvm.js → chunk-a58773jm.js} +2 -2
  25. package/dist/cli/{chunk-mb2919y2.js → chunk-acanzt5p.js} +17 -6
  26. package/dist/cli/chunk-acanzt5p.js.map +10 -0
  27. package/dist/cli/{chunk-27g6wdth.js → chunk-akbpwfxc.js} +90 -26
  28. package/dist/cli/chunk-akbpwfxc.js.map +10 -0
  29. package/dist/cli/{chunk-wm7js3j9.js → chunk-b07cmahc.js} +2 -2
  30. package/dist/cli/{chunk-wgm7m9qk.js → chunk-c8chx29p.js} +179 -51
  31. package/dist/cli/chunk-c8chx29p.js.map +36 -0
  32. package/dist/cli/{chunk-qs4q5p4e.js → chunk-crgn1q09.js} +32 -14
  33. package/dist/cli/chunk-crgn1q09.js.map +10 -0
  34. package/dist/cli/chunk-e04dxsz1.js +39 -0
  35. package/dist/cli/chunk-e04dxsz1.js.map +10 -0
  36. package/dist/cli/{chunk-yt5n7ppj.js → chunk-ey84smr6.js} +17 -7
  37. package/dist/cli/chunk-ey84smr6.js.map +10 -0
  38. package/dist/cli/{chunk-f2z5v128.js → chunk-g4hq16wv.js} +14 -15
  39. package/dist/cli/{chunk-f2z5v128.js.map → chunk-g4hq16wv.js.map} +2 -2
  40. package/dist/cli/{chunk-fa25z98p.js → chunk-ga0pf4aj.js} +9 -8
  41. package/dist/cli/chunk-ga0pf4aj.js.map +11 -0
  42. package/dist/cli/{chunk-kpf8rrjc.js → chunk-hm3vjy5s.js} +109 -58
  43. package/dist/cli/chunk-hm3vjy5s.js.map +19 -0
  44. package/dist/cli/{chunk-fs23ddbb.js → chunk-j85vccga.js} +625 -750
  45. package/dist/cli/chunk-j85vccga.js.map +36 -0
  46. package/dist/cli/{chunk-ch6g3ar0.js → chunk-p3v96n38.js} +6 -6
  47. package/dist/cli/{chunk-ch6g3ar0.js.map → chunk-p3v96n38.js.map} +3 -3
  48. package/dist/cli/{chunk-q5163e60.js → chunk-p73c0m7w.js} +21 -19
  49. package/dist/cli/chunk-p73c0m7w.js.map +11 -0
  50. package/dist/cli/{chunk-dh8cwk36.js → chunk-pehfxfta.js} +24 -9
  51. package/dist/cli/chunk-pehfxfta.js.map +10 -0
  52. package/dist/cli/{chunk-qkqwkpte.js → chunk-pv29h0wf.js} +3688 -1313
  53. package/dist/cli/chunk-pv29h0wf.js.map +190 -0
  54. package/dist/cli/{chunk-6vm74dry.js → chunk-q58y5e6a.js} +10 -10
  55. package/dist/cli/{chunk-6vm74dry.js.map → chunk-q58y5e6a.js.map} +3 -3
  56. package/dist/cli/{chunk-zxcczpyx.js → chunk-r20tn01b.js} +1 -1
  57. package/dist/cli/{chunk-m3vmjgmq.js → chunk-r9rcc4w7.js} +16 -8
  58. package/dist/cli/chunk-r9rcc4w7.js.map +10 -0
  59. package/dist/cli/{chunk-5shv93fd.js → chunk-tkacnehg.js} +2 -2
  60. package/dist/cli/{chunk-zxh4d9vy.js → chunk-tzmab476.js} +4 -4
  61. package/dist/cli/{chunk-yw7dm696.js → chunk-vg9r4eb9.js} +24 -11
  62. package/dist/cli/chunk-vg9r4eb9.js.map +14 -0
  63. package/dist/cli/{chunk-79jhk4py.js → chunk-wrr3j9w9.js} +260 -132
  64. package/dist/cli/chunk-wrr3j9w9.js.map +35 -0
  65. package/dist/cli/{chunk-6crbhc3x.js → chunk-yfyb25rh.js} +54 -27
  66. package/dist/cli/chunk-yfyb25rh.js.map +14 -0
  67. package/dist/cli/index.js +162 -35
  68. package/dist/cli/index.js.map +4 -4
  69. package/dist/types/ai/agent-surface.d.ts +32 -0
  70. package/dist/types/ai/api-catalog.d.ts +7 -1
  71. package/dist/types/ai/ask-context.d.ts +7 -0
  72. package/dist/types/ai/component-markdown.d.ts +4 -4
  73. package/dist/types/ai/link-headers.d.ts +8 -1
  74. package/dist/types/ai/openapi-components.d.ts +5 -2
  75. package/dist/types/ai/relative-links.d.ts +11 -4
  76. package/dist/types/ai/skills.d.ts +4 -1
  77. package/dist/types/ai/static-expression.d.ts +28 -0
  78. package/dist/types/ai/tar.d.ts +1 -3
  79. package/dist/types/analytics/databuddy.d.ts +43 -0
  80. package/dist/types/analytics/index.d.ts +4 -0
  81. package/dist/types/analytics/one-dollar-stats.d.ts +48 -0
  82. package/dist/types/analytics/schema.d.ts +28 -0
  83. package/dist/types/astro/integration.d.ts +3 -2
  84. package/dist/types/cli/env.d.ts +5 -0
  85. package/dist/types/cli/init/scaffold.d.ts +19 -3
  86. package/dist/types/cli/init/starter-spec.d.ts +11 -0
  87. package/dist/types/core/base-path.d.ts +24 -1
  88. package/dist/types/core/config-input.d.ts +13 -11
  89. package/dist/types/core/config.d.ts +2 -2
  90. package/dist/types/core/directive-diagnostics.d.ts +12 -0
  91. package/dist/types/core/graph.d.ts +2 -0
  92. package/dist/types/core/heading-markers.d.ts +5 -7
  93. package/dist/types/core/i18n-ui.d.ts +31 -0
  94. package/dist/types/core/i18n.d.ts +9 -1
  95. package/dist/types/core/last-modified.d.ts +10 -0
  96. package/dist/types/core/links.d.ts +3 -1
  97. package/dist/types/core/load-module.d.ts +10 -0
  98. package/dist/types/core/locale-links.d.ts +12 -2
  99. package/dist/types/core/meta.d.ts +13 -1
  100. package/dist/types/core/nav-diagnostics.d.ts +10 -0
  101. package/dist/types/core/navigation.d.ts +38 -0
  102. package/dist/types/core/ordering-prefix.d.ts +4 -0
  103. package/dist/types/core/safe-links.d.ts +3 -1
  104. package/dist/types/core/schema.d.ts +59 -13
  105. package/dist/types/core/sources/github-releases.d.ts +5 -0
  106. package/dist/types/core/sources/lower.d.ts +38 -13
  107. package/dist/types/core/sources/normalize.d.ts +23 -2
  108. package/dist/types/core/sources/remote.d.ts +11 -1
  109. package/dist/types/core/sources/resolve.d.ts +12 -0
  110. package/dist/types/core/sources/types.d.ts +31 -0
  111. package/dist/types/core/sources/watch.d.ts +12 -5
  112. package/dist/types/core/standard-schema.d.ts +5 -0
  113. package/dist/types/core/types.d.ts +9 -0
  114. package/dist/types/deploy/adapters/node.d.ts +5 -2
  115. package/dist/types/deploy/adapters/types.d.ts +7 -0
  116. package/dist/types/deploy/artifacts.d.ts +6 -4
  117. package/dist/types/deploy/cloudflare-negotiation.d.ts +3 -2
  118. package/dist/types/deploy/headers.d.ts +36 -7
  119. package/dist/types/deploy/node-headers.d.ts +43 -8
  120. package/dist/types/deploy/platforms/netlify.d.ts +27 -2
  121. package/dist/types/deploy/platforms/node.d.ts +6 -5
  122. package/dist/types/deploy/platforms/types.d.ts +15 -0
  123. package/dist/types/deploy/platforms/vercel.d.ts +3 -2
  124. package/dist/types/deploy/redirects.d.ts +31 -15
  125. package/dist/types/deploy/vercel-negotiation.d.ts +3 -2
  126. package/dist/types/markdown/directives.d.ts +62 -0
  127. package/dist/types/markdown/features.d.ts +21 -0
  128. package/dist/types/markdown/mdast.d.ts +63 -0
  129. package/dist/types/openapi/asyncapi.d.ts +4 -2
  130. package/dist/types/openapi/model.d.ts +20 -6
  131. package/dist/types/search/sync/algolia.d.ts +3 -1
  132. package/docs/01-quickstart.mdx +3 -2
  133. package/docs/02-deployment.mdx +20 -9
  134. package/docs/08-faq.mdx +10 -3
  135. package/docs/advanced/changelog.mdx +1 -1
  136. package/docs/advanced/custom-pages.mdx +7 -5
  137. package/docs/cli/audit.mdx +19 -3
  138. package/docs/cli/doctor.mdx +2 -2
  139. package/docs/cli/evals.mdx +4 -4
  140. package/docs/cli/index.mdx +4 -1
  141. package/docs/cli/translate.mdx +4 -4
  142. package/docs/cli/version.mdx +1 -1
  143. package/docs/configuration/analytics.mdx +42 -2
  144. package/docs/configuration/assistant.mdx +1 -1
  145. package/docs/configuration/customization.mdx +6 -3
  146. package/docs/configuration/index.mdx +5 -3
  147. package/docs/configuration/search.mdx +2 -2
  148. package/docs/content/components.mdx +2 -2
  149. package/docs/content/frontmatter.mdx +5 -1
  150. package/docs/content/i18n.mdx +3 -1
  151. package/docs/content/index.mdx +8 -4
  152. package/docs/content/islands.mdx +1 -1
  153. package/docs/content/meta.mdx +7 -3
  154. package/docs/content/navigation.mdx +29 -4
  155. package/docs/content/sources.mdx +18 -16
  156. package/docs/content/syntax.mdx +14 -0
  157. package/docs/content/versioning.mdx +2 -1
  158. package/docs/discoverability/agent-discovery.mdx +22 -8
  159. package/docs/discoverability/index.mdx +4 -3
  160. package/docs/discoverability/llms-txt.mdx +2 -5
  161. package/docs/discoverability/markdown.mdx +6 -4
  162. package/docs/discoverability/mcp.mdx +4 -0
  163. package/docs/discoverability/metadata.mdx +3 -2
  164. package/docs/discoverability/open-graph.mdx +8 -4
  165. package/docs/discoverability/rss.mdx +4 -2
  166. package/docs/references/asyncapi.mdx +2 -2
  167. package/docs/references/graphql.mdx +2 -2
  168. package/docs/references/openapi.mdx +6 -4
  169. package/package.json +1 -1
  170. package/skills/blume-migrate/SKILL.md +6 -6
  171. package/skills/blume-migrate/references/docusaurus.md +6 -6
  172. package/skills/blume-migrate/references/fumadocs.md +1 -1
  173. package/skills/blume-migrate/references/mintlify.md +3 -3
  174. package/skills/blume-migrate/references/monorepo.md +1 -1
  175. package/skills/blume-migrate/references/nextra.md +2 -2
  176. package/skills/blume-migrate/references/starlight.md +5 -5
  177. package/skills/blume-migrate/scripts/mintlify-codemod.mjs +9 -4
  178. package/skills/blume-update-docs/references/audit-checklist.md +1 -1
  179. package/src/ai/agent-readability.ts +2 -2
  180. package/src/ai/agent-surface.ts +56 -0
  181. package/src/ai/ai-catalog.ts +6 -2
  182. package/src/ai/api/handlers.ts +2 -2
  183. package/src/ai/api/spec.ts +17 -4
  184. package/src/ai/api-catalog.ts +13 -3
  185. package/src/ai/ask-context.ts +14 -2
  186. package/src/ai/ask-data.ts +26 -12
  187. package/src/ai/changelog-markdown.ts +2 -2
  188. package/src/ai/component-markdown.ts +43 -37
  189. package/src/ai/link-headers.ts +22 -8
  190. package/src/ai/llms.ts +22 -10
  191. package/src/ai/markdown.ts +23 -11
  192. package/src/ai/mcp/discovery.ts +2 -2
  193. package/src/ai/mcp/query.ts +2 -2
  194. package/src/ai/mcp/server.ts +80 -9
  195. package/src/ai/openapi-components.ts +22 -6
  196. package/src/ai/relative-links.ts +99 -15
  197. package/src/ai/serializers.ts +2 -1
  198. package/src/ai/skills.ts +14 -1
  199. package/src/ai/static-expression.ts +416 -0
  200. package/src/ai/tar.ts +139 -12
  201. package/src/ai/visibility.ts +45 -14
  202. package/src/analytics/databuddy.ts +67 -0
  203. package/src/analytics/head.ts +8 -0
  204. package/src/analytics/index.ts +7 -0
  205. package/src/analytics/one-dollar-stats.ts +86 -0
  206. package/src/analytics/posthog.ts +21 -3
  207. package/src/analytics/schema.ts +4 -0
  208. package/src/astro/generate.ts +72 -28
  209. package/src/astro/include-hmr.ts +31 -12
  210. package/src/astro/include-refresh.ts +19 -8
  211. package/src/astro/integration.ts +108 -14
  212. package/src/astro/runtime-modules.ts +28 -13
  213. package/src/astro/templates.ts +139 -57
  214. package/src/audit/catalog.ts +2 -2
  215. package/src/audit/checks/assets.ts +25 -5
  216. package/src/audit/checks/content.ts +20 -2
  217. package/src/audit/checks/i18n.ts +46 -8
  218. package/src/audit/checks/indexability.ts +39 -19
  219. package/src/audit/checks/links.ts +22 -1
  220. package/src/audit/checks/llms.ts +6 -3
  221. package/src/audit/checks/network.ts +3 -1
  222. package/src/audit/checks/og-image.ts +10 -0
  223. package/src/audit/checks/robots.ts +6 -1
  224. package/src/audit/checks/sitemap.ts +56 -31
  225. package/src/audit/checks/social.ts +21 -2
  226. package/src/audit/crawl.ts +88 -15
  227. package/src/audit/graph.ts +3 -1
  228. package/src/audit/report.ts +54 -17
  229. package/src/audit/run.ts +13 -9
  230. package/src/audit/snapshot.ts +5 -0
  231. package/src/audit/types.ts +18 -0
  232. package/src/audit/url.ts +37 -6
  233. package/src/cli/args.ts +32 -0
  234. package/src/cli/build-failure.ts +50 -0
  235. package/src/cli/commands/audit.ts +11 -1
  236. package/src/cli/commands/build.ts +19 -5
  237. package/src/cli/commands/check.ts +2 -0
  238. package/src/cli/commands/doctor.ts +3 -1
  239. package/src/cli/commands/eval.ts +20 -18
  240. package/src/cli/commands/init.ts +15 -5
  241. package/src/cli/commands/preview.ts +15 -0
  242. package/src/cli/commands/sync.ts +2 -0
  243. package/src/cli/commands/translate.ts +18 -18
  244. package/src/cli/commands/upgrade.ts +11 -0
  245. package/src/cli/commands/validate.ts +3 -1
  246. package/src/cli/dev-lock.ts +157 -37
  247. package/src/cli/eject-scripts.ts +32 -7
  248. package/src/cli/env.ts +12 -1
  249. package/src/cli/init/scaffold.ts +117 -11
  250. package/src/cli/init/starter-spec.ts +235 -0
  251. package/src/cli/report-format.ts +11 -6
  252. package/src/components/colors.ts +19 -0
  253. package/src/components/content/AccordionItem.astro +26 -22
  254. package/src/components/content/Badge.astro +7 -12
  255. package/src/components/content/Card.astro +2 -2
  256. package/src/components/content/Component.astro +11 -5
  257. package/src/components/content/Expandable.astro +5 -1
  258. package/src/components/content/Frame.astro +2 -7
  259. package/src/components/content/GithubInfo.astro +12 -2
  260. package/src/components/content/Prompt.astro +2 -7
  261. package/src/components/content/Tab.astro +0 -1
  262. package/src/components/content/Tabs.astro +58 -5
  263. package/src/components/content/Tile.astro +1 -1
  264. package/src/components/content/Tooltip.astro +69 -7
  265. package/src/components/content/Tree.astro +7 -2
  266. package/src/components/content/TypeTable.astro +10 -5
  267. package/src/components/content/Update.astro +8 -2
  268. package/src/components/content/auto-type-table.ts +4 -1
  269. package/src/components/content/badge-color.ts +20 -0
  270. package/src/components/content/base-href.ts +14 -22
  271. package/src/components/content/inline-markdown.ts +27 -7
  272. package/src/components/copy-feedback.ts +35 -8
  273. package/src/components/islands/assistant.tsx +37 -6
  274. package/src/components/islands/base-path.ts +47 -10
  275. package/src/components/islands/hooks.ts +42 -21
  276. package/src/components/islands/webmcp.ts +16 -10
  277. package/src/components/layout/Banner.astro +23 -4
  278. package/src/components/layout/Breadcrumbs.astro +5 -2
  279. package/src/components/layout/DiscoveryLinks.astro +9 -5
  280. package/src/components/layout/Header.astro +23 -10
  281. package/src/components/layout/LanguageSwitcher.astro +2 -2
  282. package/src/components/layout/Logo.astro +5 -0
  283. package/src/components/layout/NavSelector.astro +8 -3
  284. package/src/components/layout/NavTabMenu.astro +133 -0
  285. package/src/components/layout/NavTree.astro +31 -12
  286. package/src/components/layout/NavTreeCache.astro +5 -2
  287. package/src/components/layout/NavTreeScript.astro +45 -5
  288. package/src/components/layout/PageActions.astro +4 -3
  289. package/src/components/layout/PageLayout.astro +28 -13
  290. package/src/components/layout/Pagination.astro +3 -3
  291. package/src/components/layout/ReferenceLayout.astro +4 -1
  292. package/src/components/layout/RootLayout.astro +25 -12
  293. package/src/components/layout/Search.astro +38 -14
  294. package/src/components/layout/VersionBanner.astro +2 -2
  295. package/src/components/layout/analytics-client.ts +14 -0
  296. package/src/components/layout/toc-active.ts +41 -0
  297. package/src/components/layout/toc-element.ts +8 -14
  298. package/src/components/openapi/ApiTagOperations.astro +2 -2
  299. package/src/components/openapi/AsyncApiOperation.astro +7 -4
  300. package/src/components/openapi/GraphqlChip.astro +2 -2
  301. package/src/components/openapi/GraphqlType.astro +11 -3
  302. package/src/components/openapi/MessageComposer.astro +1 -1
  303. package/src/components/openapi/Operation.astro +23 -5
  304. package/src/components/openapi/PanelTabs.astro +4 -1
  305. package/src/components/openapi/Playground.astro +8 -2
  306. package/src/components/openapi/RequestPanel.astro +13 -6
  307. package/src/components/openapi/SchemaProperty.astro +11 -33
  308. package/src/components/openapi/SchemaTable.astro +34 -52
  309. package/src/components/openapi/async.ts +38 -6
  310. package/src/components/openapi/helpers.ts +100 -12
  311. package/src/components/openapi/message-composer.ts +14 -1
  312. package/src/components/openapi/message-model.ts +12 -2
  313. package/src/components/openapi/message.ts +21 -3
  314. package/src/components/openapi/operation-model.ts +119 -17
  315. package/src/components/openapi/panel.ts +31 -5
  316. package/src/components/openapi/param-style.ts +181 -0
  317. package/src/components/openapi/playground-client.ts +110 -23
  318. package/src/components/openapi/playground-schema.ts +25 -6
  319. package/src/components/openapi/request.ts +192 -26
  320. package/src/components/openapi/schema-tree.ts +209 -0
  321. package/src/components/openapi/snippets.ts +113 -19
  322. package/src/components/openapi/validate-json.ts +1 -1
  323. package/src/components/openapi/ws-client.ts +18 -2
  324. package/src/core/base-path.ts +69 -8
  325. package/src/core/config-input.ts +13 -11
  326. package/src/core/config.ts +18 -4
  327. package/src/core/diagnostics.ts +219 -30
  328. package/src/core/directive-diagnostics.ts +99 -0
  329. package/src/core/frontmatter.ts +21 -18
  330. package/src/core/graph.ts +120 -11
  331. package/src/core/heading-markers.ts +5 -18
  332. package/src/core/i18n-ui.ts +39 -2
  333. package/src/core/i18n.ts +44 -5
  334. package/src/core/last-modified.ts +25 -3
  335. package/src/core/links.ts +7 -4
  336. package/src/core/load-module.ts +20 -0
  337. package/src/core/locale-links.ts +22 -18
  338. package/src/core/manifest.ts +3 -2
  339. package/src/core/meta.ts +89 -12
  340. package/src/core/nav-diagnostics.ts +56 -1
  341. package/src/core/navigation.ts +272 -83
  342. package/src/core/ordering-prefix.ts +27 -0
  343. package/src/core/project-graph.ts +50 -6
  344. package/src/core/safe-href.ts +53 -1
  345. package/src/core/safe-links.ts +11 -2
  346. package/src/core/schema.ts +94 -18
  347. package/src/core/sources/assets.ts +83 -41
  348. package/src/core/sources/contentful-rich-text.ts +28 -20
  349. package/src/core/sources/contentful.ts +25 -12
  350. package/src/core/sources/filesystem.ts +25 -3
  351. package/src/core/sources/github-releases.ts +131 -11
  352. package/src/core/sources/lexical.ts +30 -20
  353. package/src/core/sources/lower.ts +276 -56
  354. package/src/core/sources/mdx-remote.ts +52 -16
  355. package/src/core/sources/normalize.ts +456 -119
  356. package/src/core/sources/notion.ts +77 -34
  357. package/src/core/sources/obsidian.ts +40 -9
  358. package/src/core/sources/payload.ts +1 -0
  359. package/src/core/sources/portable-text.ts +85 -49
  360. package/src/core/sources/remote.ts +18 -2
  361. package/src/core/sources/resolve.ts +52 -33
  362. package/src/core/sources/sanity.ts +1 -0
  363. package/src/core/sources/strapi-blocks.ts +28 -19
  364. package/src/core/sources/strapi.ts +1 -0
  365. package/src/core/sources/types.ts +31 -0
  366. package/src/core/sources/watch.ts +20 -7
  367. package/src/core/standard-schema.ts +10 -6
  368. package/src/core/types.ts +9 -0
  369. package/src/core/ui-packs/ar.ts +13 -0
  370. package/src/core/ui-packs/bg.ts +13 -0
  371. package/src/core/ui-packs/bn.ts +13 -0
  372. package/src/core/ui-packs/ca.ts +13 -0
  373. package/src/core/ui-packs/cs.ts +13 -0
  374. package/src/core/ui-packs/da.ts +13 -0
  375. package/src/core/ui-packs/de.ts +13 -0
  376. package/src/core/ui-packs/el.ts +13 -0
  377. package/src/core/ui-packs/es.ts +13 -0
  378. package/src/core/ui-packs/fa.ts +13 -0
  379. package/src/core/ui-packs/fi.ts +13 -0
  380. package/src/core/ui-packs/fr.ts +13 -0
  381. package/src/core/ui-packs/he.ts +13 -0
  382. package/src/core/ui-packs/hi.ts +13 -0
  383. package/src/core/ui-packs/hr.ts +13 -0
  384. package/src/core/ui-packs/hu.ts +13 -0
  385. package/src/core/ui-packs/id.ts +13 -0
  386. package/src/core/ui-packs/it.ts +13 -0
  387. package/src/core/ui-packs/ja.ts +13 -0
  388. package/src/core/ui-packs/ko.ts +13 -0
  389. package/src/core/ui-packs/nl.ts +13 -0
  390. package/src/core/ui-packs/no.ts +13 -0
  391. package/src/core/ui-packs/pl.ts +13 -0
  392. package/src/core/ui-packs/pt-br.ts +13 -0
  393. package/src/core/ui-packs/pt.ts +13 -0
  394. package/src/core/ui-packs/ro.ts +13 -0
  395. package/src/core/ui-packs/ru.ts +13 -0
  396. package/src/core/ui-packs/sk.ts +13 -0
  397. package/src/core/ui-packs/sr.ts +13 -0
  398. package/src/core/ui-packs/sv.ts +13 -0
  399. package/src/core/ui-packs/th.ts +13 -0
  400. package/src/core/ui-packs/tr.ts +13 -0
  401. package/src/core/ui-packs/uk.ts +13 -0
  402. package/src/core/ui-packs/vi.ts +13 -0
  403. package/src/core/ui-packs/zh-tw.ts +13 -0
  404. package/src/core/ui-packs/zh.ts +13 -0
  405. package/src/core/version-cut.ts +69 -17
  406. package/src/core/versions.ts +4 -1
  407. package/src/deploy/adapters/node.ts +5 -2
  408. package/src/deploy/adapters/registry.ts +2 -1
  409. package/src/deploy/adapters/types.ts +13 -1
  410. package/src/deploy/artifacts.ts +52 -11
  411. package/src/deploy/cloudflare-negotiation.ts +27 -16
  412. package/src/deploy/headers.ts +75 -55
  413. package/src/deploy/node-headers.ts +148 -27
  414. package/src/deploy/platforms/cloudflare.ts +13 -3
  415. package/src/deploy/platforms/netlify.ts +83 -5
  416. package/src/deploy/platforms/node.ts +8 -5
  417. package/src/deploy/platforms/static.ts +2 -0
  418. package/src/deploy/platforms/types.ts +15 -0
  419. package/src/deploy/platforms/vercel.ts +10 -3
  420. package/src/deploy/redirects.ts +68 -21
  421. package/src/deploy/robots.ts +2 -2
  422. package/src/deploy/rss.ts +4 -3
  423. package/src/deploy/sitemap.ts +7 -5
  424. package/src/deploy/vercel-negotiation.ts +35 -3
  425. package/src/eval/agents.ts +10 -2
  426. package/src/eval/run.ts +25 -0
  427. package/src/markdown/base-links.ts +74 -29
  428. package/src/markdown/directives.ts +242 -36
  429. package/src/markdown/features.ts +17 -0
  430. package/src/markdown/index.ts +13 -9
  431. package/src/markdown/mdast.ts +5 -2
  432. package/src/markdown/relative-links.ts +15 -27
  433. package/src/markdown/route-snapshot.ts +37 -0
  434. package/src/og/card.ts +149 -9
  435. package/src/og/derive.ts +156 -5
  436. package/src/og/index.ts +1 -0
  437. package/src/openapi/asyncapi.ts +4 -2
  438. package/src/openapi/graphql-build.ts +28 -2
  439. package/src/openapi/model.ts +99 -27
  440. package/src/openapi/proxy.ts +63 -10
  441. package/src/openapi/render-mdx.ts +51 -3
  442. package/src/registry/eject.ts +297 -43
  443. package/src/search/adapters/version-scope.ts +30 -0
  444. package/src/search/documents.ts +89 -27
  445. package/src/search/popular.ts +2 -1
  446. package/src/search/sync/algolia.ts +36 -2
  447. package/src/seo/jsonld.ts +7 -3
  448. package/src/sources/registry.ts +5 -0
  449. package/src/theme/entry.ts +11 -4
  450. package/src/translate/agents.ts +6 -1
  451. package/src/translate/ledger.ts +26 -3
  452. package/src/translate/meta.ts +76 -24
  453. package/src/translate/run.ts +14 -8
  454. package/src/translate/validate.ts +14 -2
  455. package/src/translate/work-list.ts +91 -19
  456. package/src/upgrade/upgrade.ts +36 -4
  457. package/dist/cli/chunk-27g6wdth.js.map +0 -10
  458. package/dist/cli/chunk-2hn4b8z7.js.map +0 -12
  459. package/dist/cli/chunk-6crbhc3x.js.map +0 -14
  460. package/dist/cli/chunk-6hsn950k.js.map +0 -10
  461. package/dist/cli/chunk-79jhk4py.js.map +0 -35
  462. package/dist/cli/chunk-82bbrxdn.js +0 -51
  463. package/dist/cli/chunk-82bbrxdn.js.map +0 -10
  464. package/dist/cli/chunk-abh8yjkn.js +0 -31
  465. package/dist/cli/chunk-abh8yjkn.js.map +0 -10
  466. package/dist/cli/chunk-ce574jw2.js +0 -23
  467. package/dist/cli/chunk-ce574jw2.js.map +0 -10
  468. package/dist/cli/chunk-dh8cwk36.js.map +0 -10
  469. package/dist/cli/chunk-epjnccmv.js.map +0 -10
  470. package/dist/cli/chunk-fa25z98p.js.map +0 -11
  471. package/dist/cli/chunk-fs23ddbb.js.map +0 -35
  472. package/dist/cli/chunk-fz5wtpmh.js.map +0 -10
  473. package/dist/cli/chunk-jwyddg7y.js.map +0 -15
  474. package/dist/cli/chunk-kpf8rrjc.js.map +0 -19
  475. package/dist/cli/chunk-m3vmjgmq.js.map +0 -10
  476. package/dist/cli/chunk-mb2919y2.js.map +0 -10
  477. package/dist/cli/chunk-q5163e60.js.map +0 -11
  478. package/dist/cli/chunk-qkqwkpte.js.map +0 -182
  479. package/dist/cli/chunk-qs4q5p4e.js.map +0 -10
  480. package/dist/cli/chunk-s1p84fyh.js.map +0 -10
  481. package/dist/cli/chunk-wgm7m9qk.js.map +0 -36
  482. package/dist/cli/chunk-yt5n7ppj.js.map +0 -10
  483. package/dist/cli/chunk-yw7dm696.js.map +0 -14
  484. /package/dist/cli/{chunk-s6jhgk0q.js.map → chunk-2eytanqx.js.map} +0 -0
  485. /package/dist/cli/{chunk-hdpx1tax.js.map → chunk-2z928egk.js.map} +0 -0
  486. /package/dist/cli/{chunk-ah61y8py.js.map → chunk-364znk6q.js.map} +0 -0
  487. /package/dist/cli/{chunk-vtk4a6dg.js.map → chunk-8ktnccpt.js.map} +0 -0
  488. /package/dist/cli/{chunk-fxypxtvm.js.map → chunk-a58773jm.js.map} +0 -0
  489. /package/dist/cli/{chunk-wm7js3j9.js.map → chunk-b07cmahc.js.map} +0 -0
  490. /package/dist/cli/{chunk-zxcczpyx.js.map → chunk-r20tn01b.js.map} +0 -0
  491. /package/dist/cli/{chunk-5shv93fd.js.map → chunk-tkacnehg.js.map} +0 -0
  492. /package/dist/cli/{chunk-zxh4d9vy.js.map → chunk-tzmab476.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  resolveRuntimeDir
4
- } from "./chunk-qkqwkpte.js";
4
+ } from "./chunk-pv29h0wf.js";
5
5
  import {
6
6
  logger
7
7
  } from "./index.js";
@@ -9,13 +9,58 @@ import {
9
9
  // src/cli/dev-lock.ts
10
10
  import {
11
11
  existsSync,
12
+ linkSync,
12
13
  mkdirSync,
13
14
  readFileSync,
15
+ renameSync,
14
16
  rmSync,
17
+ statSync,
15
18
  writeFileSync
16
19
  } from "node:fs";
17
20
  import { join } from "pathe";
18
21
  var lockPath = (outDir) => join(outDir, "dev.lock");
22
+ var reapPath = (outDir) => join(outDir, "dev.lock.reap");
23
+ var PARTIAL_LOCK_GRACE_MS = 2000;
24
+ var RETRY_DELAY_MS = 5;
25
+ var pause = (ms) => {
26
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
27
+ };
28
+ var tempSequence = 0;
29
+ var tempPath = (path) => {
30
+ tempSequence += 1;
31
+ return `${path}.${process.pid}.${tempSequence}.tmp`;
32
+ };
33
+ var createExclusive = (path, payload) => {
34
+ const temp = tempPath(path);
35
+ writeFileSync(temp, payload);
36
+ try {
37
+ linkSync(temp, path);
38
+ return true;
39
+ } catch (error) {
40
+ if (error.code !== "EEXIST") {
41
+ throw error;
42
+ }
43
+ return false;
44
+ } finally {
45
+ rmSync(temp, { force: true });
46
+ }
47
+ };
48
+ var replaceFile = (path, payload) => {
49
+ const temp = tempPath(path);
50
+ writeFileSync(temp, payload);
51
+ renameSync(temp, path);
52
+ };
53
+ var readIfExists = (path) => {
54
+ try {
55
+ const raw = readFileSync(path, "utf-8");
56
+ return { mtimeMs: statSync(path).mtimeMs, raw };
57
+ } catch (error) {
58
+ if (error.code !== "ENOENT") {
59
+ throw error;
60
+ }
61
+ return null;
62
+ }
63
+ };
19
64
  var isValidPid = (pid) => typeof pid === "number" && Number.isInteger(pid) && pid > 0;
20
65
  var isPortNumber = (port) => typeof port === "number";
21
66
  var isLockRecord = (data) => typeof data === "object" && data !== null;
@@ -45,13 +90,21 @@ var isProcessAlive = (pid) => {
45
90
  return error.code === "EPERM";
46
91
  }
47
92
  };
48
- var readDevLock = (outDir) => {
49
- const path = lockPath(outDir);
50
- if (!existsSync(path)) {
51
- return null;
93
+ var inspectLock = (outDir) => {
94
+ const file = readIfExists(lockPath(outDir));
95
+ if (!file) {
96
+ return { kind: "absent" };
97
+ }
98
+ const lock = parseLock(file.raw);
99
+ if (!lock) {
100
+ return Date.now() - file.mtimeMs < PARTIAL_LOCK_GRACE_MS ? { kind: "busy" } : { kind: "stale" };
52
101
  }
53
- const lock = parseLock(readFileSync(path, "utf-8"));
54
- return lock && isProcessAlive(lock.pid) ? lock : null;
102
+ return isProcessAlive(lock.pid) ? { kind: "live", lock } : { kind: "stale" };
103
+ };
104
+ var isClaimable = (state) => state.kind === "stale" || state.kind === "live" && state.lock.pid === process.pid;
105
+ var readDevLock = (outDir) => {
106
+ const state = inspectLock(outDir);
107
+ return state.kind === "live" ? state.lock : null;
55
108
  };
56
109
  var lockPayload = (port) => {
57
110
  const info = { pid: process.pid };
@@ -60,9 +113,6 @@ var lockPayload = (port) => {
60
113
  }
61
114
  return JSON.stringify(info);
62
115
  };
63
- var writeLock = (outDir, port) => {
64
- writeFileSync(lockPath(outDir), lockPayload(port));
65
- };
66
116
 
67
117
  class DevLockHeldError extends Error {
68
118
  lock;
@@ -83,25 +133,39 @@ var ownsLock = (outDir) => {
83
133
  return false;
84
134
  }
85
135
  };
86
- var tryClaimLock = (outDir, port) => {
87
- try {
88
- writeFileSync(lockPath(outDir), lockPayload(port), { flag: "wx" });
89
- return true;
90
- } catch (error) {
91
- if (error.code !== "EEXIST") {
92
- throw error;
136
+ var reapStaleLock = (outDir) => {
137
+ const mutex = reapPath(outDir);
138
+ if (!createExclusive(mutex, lockPayload())) {
139
+ const holder = readIfExists(mutex);
140
+ const pid = holder ? parseLock(holder.raw)?.pid : undefined;
141
+ if (pid !== undefined && pid !== process.pid && isProcessAlive(pid)) {
142
+ pause(RETRY_DELAY_MS);
143
+ } else if (holder) {
144
+ rmSync(mutex, { force: true });
93
145
  }
94
- const existing = readDevLock(outDir);
95
- if (existing && existing.pid !== process.pid) {
96
- throw new DevLockHeldError(existing);
146
+ return;
147
+ }
148
+ try {
149
+ if (isClaimable(inspectLock(outDir))) {
150
+ rmSync(lockPath(outDir), { force: true });
97
151
  }
98
- rmSync(lockPath(outDir), { force: true });
99
- return false;
152
+ } finally {
153
+ rmSync(mutex, { force: true });
100
154
  }
101
155
  };
102
156
  var acquireDevLock = (outDir, port) => {
103
157
  mkdirSync(outDir, { recursive: true });
104
- while (!tryClaimLock(outDir, port)) {}
158
+ const payload = lockPayload(port);
159
+ while (!createExclusive(lockPath(outDir), payload)) {
160
+ const state = inspectLock(outDir);
161
+ if (isClaimable(state)) {
162
+ reapStaleLock(outDir);
163
+ } else if (state.kind === "live") {
164
+ throw new DevLockHeldError(state.lock);
165
+ } else if (state.kind === "busy") {
166
+ pause(RETRY_DELAY_MS);
167
+ }
168
+ }
105
169
  let released = false;
106
170
  return () => {
107
171
  if (released) {
@@ -117,7 +181,7 @@ var acquireDevLock = (outDir, port) => {
117
181
  };
118
182
  var updateDevLockPort = (outDir, port) => {
119
183
  if (ownsLock(outDir)) {
120
- writeLock(outDir, port);
184
+ replaceFile(lockPath(outDir), lockPayload(port));
121
185
  }
122
186
  };
123
187
  var describeDevLock = (lock) => lock.port === undefined ? "" : ` at http://localhost:${lock.port}`;
@@ -132,5 +196,5 @@ var refuseIfDevRunning = (root, action, options = {}) => {
132
196
 
133
197
  export { readDevLock, DevLockHeldError, acquireDevLock, updateDevLockPort, describeDevLock, refuseIfDevRunning };
134
198
 
135
- //# debugId=1007843429DAE30664756E2164756E21
136
- //# sourceMappingURL=chunk-27g6wdth.js.map
199
+ //# debugId=BA0F0BBCC7BD124F64756E2164756E21
200
+ //# sourceMappingURL=chunk-akbpwfxc.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/cli/dev-lock.ts"],
4
+ "sourcesContent": [
5
+ "import {\n existsSync,\n linkSync,\n mkdirSync,\n readFileSync,\n renameSync,\n rmSync,\n statSync,\n writeFileSync,\n} from \"node:fs\";\n\nimport { join } from \"pathe\";\n\nimport { resolveRuntimeDir } from \"../core/project.ts\";\nimport { logger } from \"./log.ts\";\n\n/**\n * A best-effort PID lock in the shared `.blume/` runtime dir. `blume dev`\n * regenerates and serves `.blume` continuously, so a concurrent `build`,\n * `eject`, or second `dev` that regenerates or deletes it out from under the\n * running Vite server corrupts the dev session. The lock lets those commands\n * detect a live dev server and refuse — and, because it records the server's\n * port, point the caller (often an agent that just tried to start its own\n * server) at the URL to reuse instead.\n */\n\nexport interface DevLockInfo {\n pid: number;\n /** Port the dev server is bound to, when known. */\n port?: number;\n}\n\nconst lockPath = (outDir: string): string => join(outDir, \"dev.lock\");\n\n/** The mutex a process holds while it clears a stale lock. */\nconst reapPath = (outDir: string): string => join(outDir, \"dev.lock.reap\");\n\n/**\n * How long a lock file that doesn't parse counts as one being written right\n * now. Blume creates a lock with its whole content in place (see\n * {@link createExclusive}), but one left empty or cut off — by a crash, or by\n * an older Blume that opened the file before writing it — would otherwise\n * read as stale the instant it appears. Past this age it's debris.\n */\nconst PARTIAL_LOCK_GRACE_MS = 2000;\n\n/** Pause between claim attempts while another process is mid-claim. */\nconst RETRY_DELAY_MS = 5;\n\nconst pause = (ms: number): void => {\n // A synchronous sleep: the claim is synchronous, and what it waits on is\n // another process, so there's nothing in this one to yield to.\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\n};\n\n/** Per-process counter that keeps concurrent temp file names apart. */\nlet tempSequence = 0;\n\n/** A private sibling of `path` to stage a write in. */\nconst tempPath = (path: string): string => {\n tempSequence += 1;\n return `${path}.${process.pid}.${tempSequence}.tmp`;\n};\n\n/**\n * Create `path` holding `payload`, atomically and exclusively. The payload\n * goes to a private temp file first, which is then hard-linked into place:\n * the link fails when `path` exists, exactly like a `wx` open, but the file\n * appears with its whole content — no reader ever sees it empty or half\n * written. Returns false when `path` already exists.\n */\nconst createExclusive = (path: string, payload: string): boolean => {\n const temp = tempPath(path);\n writeFileSync(temp, payload);\n try {\n linkSync(temp, path);\n return true;\n } catch (error) {\n // SAFETY: `linkSync` failures are errno exceptions.\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") {\n throw error;\n }\n return false;\n } finally {\n rmSync(temp, { force: true });\n }\n};\n\n/** Replace `path` with `payload` in one step, so readers see old or new. */\nconst replaceFile = (path: string, payload: string): void => {\n const temp = tempPath(path);\n writeFileSync(temp, payload);\n renameSync(temp, path);\n};\n\n/** A file's text, or null when it doesn't exist (anymore). */\nconst readIfExists = (\n path: string\n): { raw: string; mtimeMs: number } | null => {\n try {\n const raw = readFileSync(path, \"utf-8\");\n return { mtimeMs: statSync(path).mtimeMs, raw };\n } catch (error) {\n // SAFETY: `readFileSync`/`statSync` failures are errno exceptions.\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n return null;\n }\n};\n\n/** What `JSON.parse` can yield for a lock file body. */\ntype LockFileValue =\n | string\n | number\n | boolean\n | null\n | LockFileValue[]\n | { [key: string]: LockFileValue };\n\nconst isValidPid = (pid: LockFileValue | undefined): pid is number =>\n typeof pid === \"number\" && Number.isInteger(pid) && pid > 0;\n\nconst isPortNumber = (port: LockFileValue | undefined): port is number =>\n typeof port === \"number\";\n\nconst isLockRecord = (\n data: LockFileValue\n): data is { pid?: LockFileValue; port?: LockFileValue } =>\n typeof data === \"object\" && data !== null;\n\n/**\n * Parse a lock file body. Current locks are JSON (`{\"pid\":123,\"port\":3001}`);\n * a bare integer (the pre-port format) still parses as a pid-only lock.\n */\nconst parseLock = (raw: string): DevLockInfo | null => {\n let data: LockFileValue;\n try {\n data = JSON.parse(raw.trim());\n } catch {\n return null;\n }\n if (isValidPid(data)) {\n return { pid: data };\n }\n if (isLockRecord(data)) {\n const { pid, port } = data;\n if (isValidPid(pid)) {\n return isPortNumber(port) ? { pid, port } : { pid };\n }\n }\n return null;\n};\n\nconst isProcessAlive = (pid: number): boolean => {\n try {\n // Signal 0 probes liveness without actually signaling the process.\n process.kill(pid, 0);\n return true;\n } catch (error) {\n // EPERM means the process exists but belongs to another user — still\n // live, so the lock must hold (only ESRCH proves it's gone).\n // SAFETY: `process.kill` failures are errno exceptions.\n return (error as NodeJS.ErrnoException).code === \"EPERM\";\n }\n};\n\n/** What the lock file on a dir says, read once. */\ntype LockState =\n | { kind: \"absent\" }\n /** Unparseable but brand new: another process is writing it right now. */\n | { kind: \"busy\" }\n | { kind: \"live\"; lock: DevLockInfo }\n /** A dead holder's lock, or unparseable debris. */\n | { kind: \"stale\" };\n\nconst inspectLock = (outDir: string): LockState => {\n const file = readIfExists(lockPath(outDir));\n if (!file) {\n return { kind: \"absent\" };\n }\n const lock = parseLock(file.raw);\n if (!lock) {\n return Date.now() - file.mtimeMs < PARTIAL_LOCK_GRACE_MS\n ? { kind: \"busy\" }\n : { kind: \"stale\" };\n }\n return isProcessAlive(lock.pid) ? { kind: \"live\", lock } : { kind: \"stale\" };\n};\n\n/**\n * Whether this process may clear the lock to claim the dir: a dead holder's\n * lock and debris, or this process's own leftover.\n */\nconst isClaimable = (state: LockState): boolean =>\n state.kind === \"stale\" ||\n (state.kind === \"live\" && state.lock.pid === process.pid);\n\n/**\n * Read the lock on `outDir` held by a live `blume dev`, or null. A lock left\n * by a process that has since exited (stale) is treated as absent.\n */\nexport const readDevLock = (outDir: string): DevLockInfo | null => {\n const state = inspectLock(outDir);\n return state.kind === \"live\" ? state.lock : null;\n};\n\n/** Whether another live `blume dev` holds the lock on `outDir`. */\nexport const isDevLocked = (outDir: string): boolean =>\n readDevLock(outDir) !== null;\n\nconst lockPayload = (port?: number): string => {\n const info: DevLockInfo = { pid: process.pid };\n if (port !== undefined) {\n info.port = port;\n }\n return JSON.stringify(info);\n};\n\n/** Thrown when another live `blume dev` already holds the lock. */\nexport class DevLockHeldError extends Error {\n readonly lock: DevLockInfo;\n\n constructor(lock: DevLockInfo) {\n super(`A blume dev server (pid ${lock.pid}) already holds the lock.`);\n this.name = \"DevLockHeldError\";\n this.lock = lock;\n }\n}\n\nconst ownsLock = (outDir: string): boolean => {\n const path = lockPath(outDir);\n if (!existsSync(path)) {\n return false;\n }\n try {\n return parseLock(readFileSync(path, \"utf-8\"))?.pid === process.pid;\n } catch {\n return false;\n }\n};\n\n/**\n * Clear a claimable lock without racing anyone else doing the same. Two\n * processes can both read the same stale lock; if each simply deleted the\n * file, the slower one could delete the lock the faster one had claimed in\n * between, and both would win. So removing a lock takes the reap mutex\n * (created the same atomic way), and whoever holds it reads the lock again\n * first: a live lock claimed since is left alone. A mutex whose holder died\n * mid-reap is cleared for the next attempt.\n */\nconst reapStaleLock = (outDir: string): void => {\n const mutex = reapPath(outDir);\n if (!createExclusive(mutex, lockPayload())) {\n const holder = readIfExists(mutex);\n const pid = holder ? parseLock(holder.raw)?.pid : undefined;\n if (pid !== undefined && pid !== process.pid && isProcessAlive(pid)) {\n pause(RETRY_DELAY_MS);\n } else if (holder) {\n rmSync(mutex, { force: true });\n }\n return;\n }\n try {\n if (isClaimable(inspectLock(outDir))) {\n rmSync(lockPath(outDir), { force: true });\n }\n } finally {\n rmSync(mutex, { force: true });\n }\n};\n\n/**\n * Write the current process's dev lock into `outDir` and return a release\n * function. Two `blume dev` processes starting at the same moment can't both\n * win: the lock appears whole and exclusively (a hard link, which fails when\n * the file exists), a lock still being written is waited on rather than read\n * as stale, and a stale lock (dead pid) or this process's own leftover is only\n * cleared under the reap mutex — the loser gets a {@link DevLockHeldError}\n * naming the live holder. The release only removes the file if it's still\n * ours, so a newer dev server's lock is never clobbered.\n */\nexport const acquireDevLock = (outDir: string, port?: number): (() => void) => {\n mkdirSync(outDir, { recursive: true });\n const payload = lockPayload(port);\n while (!createExclusive(lockPath(outDir), payload)) {\n const state = inspectLock(outDir);\n if (isClaimable(state)) {\n reapStaleLock(outDir);\n } else if (state.kind === \"live\") {\n throw new DevLockHeldError(state.lock);\n } else if (state.kind === \"busy\") {\n pause(RETRY_DELAY_MS);\n }\n // \"absent\": the holder released it just now — race for the claim again.\n }\n let released = false;\n return () => {\n if (released) {\n return;\n }\n released = true;\n try {\n if (ownsLock(outDir)) {\n rmSync(lockPath(outDir), { force: true });\n }\n } catch {\n // Best-effort cleanup; a stale lock is handled by the liveness check.\n }\n };\n};\n\n/**\n * Rewrite this process's lock with the port the server actually bound (the\n * lock is acquired before the server starts, and Vite may bump a busy port).\n * A lock owned by another process is left alone.\n */\nexport const updateDevLockPort = (outDir: string, port: number): void => {\n if (ownsLock(outDir)) {\n // Replaced in one step: rewriting in place would leave a moment where a\n // concurrent claim reads an empty lock.\n replaceFile(lockPath(outDir), lockPayload(port));\n }\n};\n\n/** Human-readable location of a locked dev server, e.g. \" at http://localhost:3001\". */\nexport const describeDevLock = (lock: DevLockInfo): string =>\n lock.port === undefined ? \"\" : ` at http://localhost:${lock.port}`;\n\n/**\n * Exit with an error when a live `blume dev` owns the runtime dir under `root`.\n * `action` names the operation being refused (e.g. \"building\"). `runtimeDir`\n * relocates the checked dir: an isolated verify (`.blume-verify`) targets a dir\n * dev never locks, so it proceeds; a default or `--runtime-dir .blume` run still\n * refuses. Only commands that actually accept `--isolated` (build, check) should\n * set `isolatedHint`, so the refusal never suggests a flag the command ignores.\n */\nexport const refuseIfDevRunning = (\n root: string,\n action: string,\n options: { runtimeDir?: string; isolatedHint?: boolean } = {}\n): void => {\n const lock = readDevLock(resolveRuntimeDir(root, options.runtimeDir));\n if (lock) {\n const remedies = options.isolatedHint\n ? \"Reuse that server, stop it first, or re-run with --isolated to build/verify against .blume-verify without touching it.\"\n : \"Reuse that server or stop it first.\";\n logger.error(\n `A \\`blume dev\\` server is running${describeDevLock(lock)}; ${action} would corrupt its .blume runtime. ${remedies}`\n );\n process.exit(1);\n }\n};\n"
6
+ ],
7
+ "mappings": ";;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWA;AAqBA,IAAM,WAAW,CAAC,WAA2B,KAAK,QAAQ,UAAU;AAGpE,IAAM,WAAW,CAAC,WAA2B,KAAK,QAAQ,eAAe;AASzE,IAAM,wBAAwB;AAG9B,IAAM,iBAAiB;AAEvB,IAAM,QAAQ,CAAC,OAAqB;AAAA,EAGlC,QAAQ,KAAK,IAAI,WAAW,IAAI,kBAAkB,CAAC,CAAC,GAAG,GAAG,GAAG,EAAE;AAAA;AAIjE,IAAI,eAAe;AAGnB,IAAM,WAAW,CAAC,SAAyB;AAAA,EACzC,gBAAgB;AAAA,EAChB,OAAO,GAAG,QAAQ,QAAQ,OAAO;AAAA;AAUnC,IAAM,kBAAkB,CAAC,MAAc,YAA6B;AAAA,EAClE,MAAM,OAAO,SAAS,IAAI;AAAA,EAC1B,cAAc,MAAM,OAAO;AAAA,EAC3B,IAAI;AAAA,IACF,SAAS,MAAM,IAAI;AAAA,IACnB,OAAO;AAAA,IACP,OAAO,OAAO;AAAA,IAEd,IAAK,MAAgC,SAAS,UAAU;AAAA,MACtD,MAAM;AAAA,IACR;AAAA,IACA,OAAO;AAAA,YACP;AAAA,IACA,OAAO,MAAM,EAAE,OAAO,KAAK,CAAC;AAAA;AAAA;AAKhC,IAAM,cAAc,CAAC,MAAc,YAA0B;AAAA,EAC3D,MAAM,OAAO,SAAS,IAAI;AAAA,EAC1B,cAAc,MAAM,OAAO;AAAA,EAC3B,WAAW,MAAM,IAAI;AAAA;AAIvB,IAAM,eAAe,CACnB,SAC4C;AAAA,EAC5C,IAAI;AAAA,IACF,MAAM,MAAM,aAAa,MAAM,OAAO;AAAA,IACtC,OAAO,EAAE,SAAS,SAAS,IAAI,EAAE,SAAS,IAAI;AAAA,IAC9C,OAAO,OAAO;AAAA,IAEd,IAAK,MAAgC,SAAS,UAAU;AAAA,MACtD,MAAM;AAAA,IACR;AAAA,IACA,OAAO;AAAA;AAAA;AAaX,IAAM,aAAa,CAAC,QAClB,OAAO,QAAQ,YAAY,OAAO,UAAU,GAAG,KAAK,MAAM;AAE5D,IAAM,eAAe,CAAC,SACpB,OAAO,SAAS;AAElB,IAAM,eAAe,CACnB,SAEA,OAAO,SAAS,YAAY,SAAS;AAMvC,IAAM,YAAY,CAAC,QAAoC;AAAA,EACrD,IAAI;AAAA,EACJ,IAAI;AAAA,IACF,OAAO,KAAK,MAAM,IAAI,KAAK,CAAC;AAAA,IAC5B,MAAM;AAAA,IACN,OAAO;AAAA;AAAA,EAET,IAAI,WAAW,IAAI,GAAG;AAAA,IACpB,OAAO,EAAE,KAAK,KAAK;AAAA,EACrB;AAAA,EACA,IAAI,aAAa,IAAI,GAAG;AAAA,IACtB,QAAQ,KAAK,SAAS;AAAA,IACtB,IAAI,WAAW,GAAG,GAAG;AAAA,MACnB,OAAO,aAAa,IAAI,IAAI,EAAE,KAAK,KAAK,IAAI,EAAE,IAAI;AAAA,IACpD;AAAA,EACF;AAAA,EACA,OAAO;AAAA;AAGT,IAAM,iBAAiB,CAAC,QAAyB;AAAA,EAC/C,IAAI;AAAA,IAEF,QAAQ,KAAK,KAAK,CAAC;AAAA,IACnB,OAAO;AAAA,IACP,OAAO,OAAO;AAAA,IAId,OAAQ,MAAgC,SAAS;AAAA;AAAA;AAarD,IAAM,cAAc,CAAC,WAA8B;AAAA,EACjD,MAAM,OAAO,aAAa,SAAS,MAAM,CAAC;AAAA,EAC1C,IAAI,CAAC,MAAM;AAAA,IACT,OAAO,EAAE,MAAM,SAAS;AAAA,EAC1B;AAAA,EACA,MAAM,OAAO,UAAU,KAAK,GAAG;AAAA,EAC/B,IAAI,CAAC,MAAM;AAAA,IACT,OAAO,KAAK,IAAI,IAAI,KAAK,UAAU,wBAC/B,EAAE,MAAM,OAAO,IACf,EAAE,MAAM,QAAQ;AAAA,EACtB;AAAA,EACA,OAAO,eAAe,KAAK,GAAG,IAAI,EAAE,MAAM,QAAQ,KAAK,IAAI,EAAE,MAAM,QAAQ;AAAA;AAO7E,IAAM,cAAc,CAAC,UACnB,MAAM,SAAS,WACd,MAAM,SAAS,UAAU,MAAM,KAAK,QAAQ,QAAQ;AAMhD,IAAM,cAAc,CAAC,WAAuC;AAAA,EACjE,MAAM,QAAQ,YAAY,MAAM;AAAA,EAChC,OAAO,MAAM,SAAS,SAAS,MAAM,OAAO;AAAA;AAO9C,IAAM,cAAc,CAAC,SAA0B;AAAA,EAC7C,MAAM,OAAoB,EAAE,KAAK,QAAQ,IAAI;AAAA,EAC7C,IAAI,SAAS,WAAW;AAAA,IACtB,KAAK,OAAO;AAAA,EACd;AAAA,EACA,OAAO,KAAK,UAAU,IAAI;AAAA;AAAA;AAIrB,MAAM,yBAAyB,MAAM;AAAA,EACjC;AAAA,EAET,WAAW,CAAC,MAAmB;AAAA,IAC7B,MAAM,2BAA2B,KAAK,8BAA8B;AAAA,IACpE,KAAK,OAAO;AAAA,IACZ,KAAK,OAAO;AAAA;AAEhB;AAEA,IAAM,WAAW,CAAC,WAA4B;AAAA,EAC5C,MAAM,OAAO,SAAS,MAAM;AAAA,EAC5B,IAAI,CAAC,WAAW,IAAI,GAAG;AAAA,IACrB,OAAO;AAAA,EACT;AAAA,EACA,IAAI;AAAA,IACF,OAAO,UAAU,aAAa,MAAM,OAAO,CAAC,GAAG,QAAQ,QAAQ;AAAA,IAC/D,MAAM;AAAA,IACN,OAAO;AAAA;AAAA;AAaX,IAAM,gBAAgB,CAAC,WAAyB;AAAA,EAC9C,MAAM,QAAQ,SAAS,MAAM;AAAA,EAC7B,IAAI,CAAC,gBAAgB,OAAO,YAAY,CAAC,GAAG;AAAA,IAC1C,MAAM,SAAS,aAAa,KAAK;AAAA,IACjC,MAAM,MAAM,SAAS,UAAU,OAAO,GAAG,GAAG,MAAM;AAAA,IAClD,IAAI,QAAQ,aAAa,QAAQ,QAAQ,OAAO,eAAe,GAAG,GAAG;AAAA,MACnE,MAAM,cAAc;AAAA,IACtB,EAAO,SAAI,QAAQ;AAAA,MACjB,OAAO,OAAO,EAAE,OAAO,KAAK,CAAC;AAAA,IAC/B;AAAA,IACA;AAAA,EACF;AAAA,EACA,IAAI;AAAA,IACF,IAAI,YAAY,YAAY,MAAM,CAAC,GAAG;AAAA,MACpC,OAAO,SAAS,MAAM,GAAG,EAAE,OAAO,KAAK,CAAC;AAAA,IAC1C;AAAA,YACA;AAAA,IACA,OAAO,OAAO,EAAE,OAAO,KAAK,CAAC;AAAA;AAAA;AAc1B,IAAM,iBAAiB,CAAC,QAAgB,SAAgC;AAAA,EAC7E,UAAU,QAAQ,EAAE,WAAW,KAAK,CAAC;AAAA,EACrC,MAAM,UAAU,YAAY,IAAI;AAAA,EAChC,OAAO,CAAC,gBAAgB,SAAS,MAAM,GAAG,OAAO,GAAG;AAAA,IAClD,MAAM,QAAQ,YAAY,MAAM;AAAA,IAChC,IAAI,YAAY,KAAK,GAAG;AAAA,MACtB,cAAc,MAAM;AAAA,IACtB,EAAO,SAAI,MAAM,SAAS,QAAQ;AAAA,MAChC,MAAM,IAAI,iBAAiB,MAAM,IAAI;AAAA,IACvC,EAAO,SAAI,MAAM,SAAS,QAAQ;AAAA,MAChC,MAAM,cAAc;AAAA,IACtB;AAAA,EAEF;AAAA,EACA,IAAI,WAAW;AAAA,EACf,OAAO,MAAM;AAAA,IACX,IAAI,UAAU;AAAA,MACZ;AAAA,IACF;AAAA,IACA,WAAW;AAAA,IACX,IAAI;AAAA,MACF,IAAI,SAAS,MAAM,GAAG;AAAA,QACpB,OAAO,SAAS,MAAM,GAAG,EAAE,OAAO,KAAK,CAAC;AAAA,MAC1C;AAAA,MACA,MAAM;AAAA;AAAA;AAWL,IAAM,oBAAoB,CAAC,QAAgB,SAAuB;AAAA,EACvE,IAAI,SAAS,MAAM,GAAG;AAAA,IAGpB,YAAY,SAAS,MAAM,GAAG,YAAY,IAAI,CAAC;AAAA,EACjD;AAAA;AAIK,IAAM,kBAAkB,CAAC,SAC9B,KAAK,SAAS,YAAY,KAAK,wBAAwB,KAAK;AAUvD,IAAM,qBAAqB,CAChC,MACA,QACA,UAA2D,CAAC,MACnD;AAAA,EACT,MAAM,OAAO,YAAY,kBAAkB,MAAM,QAAQ,UAAU,CAAC;AAAA,EACpE,IAAI,MAAM;AAAA,IACR,MAAM,WAAW,QAAQ,eACrB,2HACA;AAAA,IACJ,OAAO,MACL,oCAAoC,gBAAgB,IAAI,MAAM,4CAA4C,UAC5G;AAAA,IACA,QAAQ,KAAK,CAAC;AAAA,EAChB;AAAA;",
8
+ "debugId": "BA0F0BBCC7BD124F64756E2164756E21",
9
+ "names": []
10
+ }
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  commandsFor,
7
7
  detectProjectPackageManager
8
- } from "./chunk-qkqwkpte.js";
8
+ } from "./chunk-pv29h0wf.js";
9
9
 
10
10
  // src/astro/islands.ts
11
11
  import { readFile } from "node:fs/promises";
@@ -142,4 +142,4 @@ var missingDependencyDiagnostic = async (config, root, severity, frameworks = []
142
142
  export { readClientMode, discoverIslands, missingDependencyDiagnostic };
143
143
 
144
144
  //# debugId=137E521D7DE6F81064756E2164756E21
145
- //# sourceMappingURL=chunk-wm7js3j9.js.map
145
+ //# sourceMappingURL=chunk-b07cmahc.js.map
@@ -6,6 +6,7 @@ import {
6
6
  enrichDiagnostic
7
7
  } from "./index.js";
8
8
  import {
9
+ resolveFallbackLocale,
9
10
  OPENAPI_PATH,
10
11
  API_PAGES_PATH,
11
12
  API_PAGE_PATH,
@@ -26,11 +27,11 @@ import {
26
27
  routeIsTaken,
27
28
  hasGeneratedChangelog,
28
29
  customOgRoutes,
29
- resolveFallbackLocale,
30
30
  resolveAskBackend,
31
31
  GOOGLE_FONTS,
32
32
  isFontSlug,
33
33
  fontLocaleCodes,
34
+ localeFontSubsets,
34
35
  buildFontsCss,
35
36
  configuredFonts,
36
37
  repoUrl,
@@ -43,32 +44,28 @@ import {
43
44
  collectContentAssets,
44
45
  buildRssFeeds,
45
46
  renderRssFeed,
47
+ HTTP_METHODS,
48
+ withServerDefaults,
46
49
  isOpenApiSource,
47
50
  buildRawMarkdown,
48
51
  markdownRoutePaths
49
- } from "./chunk-qkqwkpte.js";
52
+ } from "./chunk-pv29h0wf.js";
50
53
  import {
51
54
  trimChar,
52
55
  normalizeBasePath,
53
56
  withBasePath,
57
+ mountBasePath,
54
58
  siteRoot,
55
59
  absoluteUrl2
56
- } from "./chunk-jts8mvcz.js";
60
+ } from "./chunk-3em5wd2y.js";
57
61
  import {
58
62
  validateSearchPopularIcons,
59
63
  validateNavTargets
60
- } from "./chunk-fs23ddbb.js";
64
+ } from "./chunk-j85vccga.js";
61
65
  import {
62
66
  buildSearchDocuments,
63
67
  buildMcpData
64
- } from "./chunk-6crbhc3x.js";
65
- import {
66
- emptyComponentOverrides,
67
- analyzeComponentOverrides
68
- } from "./chunk-vtk4a6dg.js";
69
- import {
70
- writeTextAtomic
71
- } from "./chunk-jq5n4avg.js";
68
+ } from "./chunk-yfyb25rh.js";
72
69
  import {
73
70
  planComponentSlots,
74
71
  publishRuntimeModules,
@@ -108,15 +105,22 @@ import {
108
105
  examplesPageTemplate,
109
106
  runtimePackageTemplate,
110
107
  runtimeTsconfigTemplate
111
- } from "./chunk-2hn4b8z7.js";
108
+ } from "./chunk-5m5nmvyq.js";
109
+ import {
110
+ emptyComponentOverrides,
111
+ analyzeComponentOverrides
112
+ } from "./chunk-8ktnccpt.js";
113
+ import {
114
+ writeTextAtomic
115
+ } from "./chunk-jq5n4avg.js";
112
116
  import {
113
117
  registry
114
- } from "./chunk-zxcczpyx.js";
118
+ } from "./chunk-r20tn01b.js";
115
119
  import {
116
120
  readClientMode,
117
121
  discoverIslands,
118
122
  missingDependencyDiagnostic
119
- } from "./chunk-wm7js3j9.js";
123
+ } from "./chunk-b07cmahc.js";
120
124
 
121
125
  // src/astro/integration.ts
122
126
  import { join as join3, relative, resolve as resolve2 } from "pathe";
@@ -153,18 +157,29 @@ var publishDevNegotiation = (negotiation) => {
153
157
  homeLinkHeader: negotiation.homeLinkHeader
154
158
  } : null;
155
159
  };
160
+ var overlayChannelOf = (server) => server?.ws ?? server?.hot;
161
+ var DATA_STORE_MODULE_ID = "\x00astro:data-layer-content";
162
+ var invalidateDataStore = (server) => {
163
+ for (const { moduleGraph } of Object.values(server.environments)) {
164
+ const mod = moduleGraph.getModuleById(DATA_STORE_MODULE_ID);
165
+ if (mod) {
166
+ moduleGraph.invalidateModule(mod);
167
+ }
168
+ }
169
+ overlayChannelOf(server)?.send({ type: "full-reload" });
170
+ };
156
171
  var refreshBlumeContent = async () => {
157
- const { refreshContent } = registry2();
172
+ const { overlay, refreshContent } = registry2();
158
173
  if (!refreshContent) {
159
174
  return false;
160
175
  }
161
176
  await refreshContent({});
177
+ if (overlay) {
178
+ invalidateDataStore(overlay);
179
+ }
162
180
  return true;
163
181
  };
164
- var overlayChannel = () => {
165
- const { overlay } = registry2();
166
- return overlay?.ws ?? overlay?.hot;
167
- };
182
+ var overlayChannel = () => overlayChannelOf(registry2().overlay);
168
183
  var showBlumeErrorOverlay = (diagnostics) => {
169
184
  const errors = [];
170
185
  for (const diagnostic of diagnostics) {
@@ -261,6 +276,7 @@ var PROBLEM_TYPE = "application/problem+json";
261
276
 
262
277
  // src/ai/api/spec.ts
263
278
  var JSON_TYPE = "application/json";
279
+ var EVENT_STREAM_TYPE = "text/event-stream";
264
280
  var MARKDOWN_TYPE = "text/markdown";
265
281
  var TEXT_TYPE = "text/plain";
266
282
  var ref = (name) => ({
@@ -717,14 +733,21 @@ var buildApiSpec = (input) => {
717
733
  input.mcpRoute,
718
734
  {
719
735
  post: {
720
- description: "The Model Context Protocol server (Streamable HTTP, stateless, JSON responses). Tools: `search_docs`, `get_page`, `list_pages`, `get_navigation` — the same operations this API exposes — plus every page as a `text/markdown` resource. Discovery document at `/.well-known/mcp.json`.",
736
+ description: "The Model Context Protocol server (Streamable HTTP, stateless, JSON responses). Send `Accept: application/json, text/event-stream`: the Streamable HTTP transport requires a client to accept both and answers `406` otherwise, though this server always replies with JSON. Tools: `search_docs`, `get_page`, `list_pages`, `get_navigation` — the same operations this API exposes — plus every page as a `text/markdown` resource. Discovery document at `/.well-known/mcp.json`.",
721
737
  operationId: "mcp",
722
738
  requestBody: {
723
739
  content: { [JSON_TYPE]: { schema: ref("JsonRpcRequest") } },
724
740
  required: true
725
741
  },
726
742
  responses: {
727
- "200": jsonResponse("The JSON-RPC response.", "JsonRpcResponse")
743
+ "200": {
744
+ content: {
745
+ [JSON_TYPE]: { schema: ref("JsonRpcResponse") },
746
+ [EVENT_STREAM_TYPE]: { schema: { type: "string" } }
747
+ },
748
+ description: "The JSON-RPC response."
749
+ },
750
+ "406": jsonResponse("The request's `Accept` header doesn't list both `application/json` and `text/event-stream`.", "JsonRpcResponse")
728
751
  },
729
752
  summary: "Call the MCP server",
730
753
  tags: ["MCP"]
@@ -763,7 +786,7 @@ var buildApiSpec = (input) => {
763
786
  if (input.site) {
764
787
  document.externalDocs = {
765
788
  description: `${input.name} documentation`,
766
- url: absoluteUrl2(input.site, withBasePath(input.base, "/"))
789
+ url: absoluteUrl2(input.site, mountBasePath(input.base, "/"))
767
790
  };
768
791
  }
769
792
  return document;
@@ -776,17 +799,28 @@ var buildAskData = async (project) => {
776
799
  content: "markdown",
777
800
  includeWhenDisabled: true
778
801
  });
779
- return {
802
+ const versioned = Boolean(project.config.versions);
803
+ const data = {
780
804
  defaultLocale: project.config.i18n?.defaultLocale,
781
- documents: documents.map((doc) => ({
782
- content: doc.content,
783
- description: doc.description,
784
- locale: doc.locale,
785
- route: doc.route,
786
- title: doc.title
787
- })),
805
+ documents: documents.map((doc) => {
806
+ const document = {
807
+ content: doc.content,
808
+ description: doc.description,
809
+ locale: doc.locale,
810
+ route: doc.route,
811
+ title: doc.title
812
+ };
813
+ if (versioned) {
814
+ document.version = doc.version;
815
+ }
816
+ return document;
817
+ }),
788
818
  site: project.config.deployment.options.site ?? null
789
819
  };
820
+ if (versioned) {
821
+ data.versioned = true;
822
+ }
823
+ return data;
790
824
  };
791
825
 
792
826
  // src/components/layout/nav-utils.ts
@@ -1201,12 +1235,87 @@ var deriveOgFonts = (fonts, root) => {
1201
1235
  }
1202
1236
  return result;
1203
1237
  };
1238
+ var BUILT_IN_FAMILY = "Geist";
1239
+ var SCRIPT_FAMILIES = {
1240
+ am: "Noto Sans Ethiopic",
1241
+ ar: "Noto Sans Arabic",
1242
+ as: "Noto Sans Bengali",
1243
+ bn: "Noto Sans Bengali",
1244
+ ckb: "Noto Sans Arabic",
1245
+ fa: "Noto Sans Arabic",
1246
+ gu: "Noto Sans Gujarati",
1247
+ he: "Noto Sans Hebrew",
1248
+ hi: "Noto Sans Devanagari",
1249
+ hy: "Noto Sans Armenian",
1250
+ ja: "Noto Sans JP",
1251
+ ka: "Noto Sans Georgian",
1252
+ km: "Noto Sans Khmer",
1253
+ kn: "Noto Sans Kannada",
1254
+ ko: "Noto Sans KR",
1255
+ lo: "Noto Sans Lao",
1256
+ ml: "Noto Sans Malayalam",
1257
+ mr: "Noto Sans Devanagari",
1258
+ my: "Noto Sans Myanmar",
1259
+ ne: "Noto Sans Devanagari",
1260
+ or: "Noto Sans Oriya",
1261
+ pa: "Noto Sans Gurmukhi",
1262
+ ps: "Noto Sans Arabic",
1263
+ sa: "Noto Sans Devanagari",
1264
+ si: "Noto Sans Sinhala",
1265
+ ta: "Noto Sans Tamil",
1266
+ te: "Noto Sans Telugu",
1267
+ th: "Noto Sans Thai",
1268
+ ti: "Noto Sans Ethiopic",
1269
+ ur: "Noto Sans Arabic",
1270
+ yi: "Noto Sans Hebrew",
1271
+ zh: "Noto Sans SC"
1272
+ };
1273
+ var isScriptLanguage = (language) => Object.hasOwn(SCRIPT_FAMILIES, language);
1274
+ var TRADITIONAL_CHINESE = new Set(["hant", "hk", "mo", "tw"]);
1275
+ var localeFamily = (locale) => {
1276
+ const [language = "", ...subtags] = locale.toLowerCase().split("-");
1277
+ if (language === "zh" && subtags.some((tag) => TRADITIONAL_CHINESE.has(tag))) {
1278
+ return "Noto Sans TC";
1279
+ }
1280
+ if (isScriptLanguage(language)) {
1281
+ return SCRIPT_FAMILIES[language];
1282
+ }
1283
+ return localeFontSubsets([locale]).length > 1 ? "Noto Sans" : null;
1284
+ };
1285
+ var DEFAULT_FALLBACKS = [
1286
+ "Noto Sans",
1287
+ ...new Set(Object.values(SCRIPT_FAMILIES)),
1288
+ "Noto Sans TC"
1289
+ ];
1290
+ var ogFallbackFonts = (locales) => {
1291
+ const names = new Set;
1292
+ for (const family of [...locales.map(localeFamily), ...DEFAULT_FALLBACKS]) {
1293
+ if (family) {
1294
+ names.add(family);
1295
+ }
1296
+ }
1297
+ return [...names].map((name) => ({ name, weight: CARD_WEIGHTS }));
1298
+ };
1299
+ var isGoogleFamilyName = (font) => typeof font === "string";
1300
+ var ogFontName = (font) => isGoogleFamilyName(font) ? font : font.name;
1301
+ var withFallbacks = (derived, locales) => {
1302
+ const loaded = new Set(derived.fonts.map(ogFontName));
1303
+ return {
1304
+ fallbacks: ogFallbackFonts(locales).filter((font) => !loaded.has(font.name)),
1305
+ families: derived.families ?? {
1306
+ body: BUILT_IN_FAMILY,
1307
+ title: BUILT_IN_FAMILY
1308
+ },
1309
+ fonts: derived.fonts
1310
+ };
1311
+ };
1204
1312
  var resolveOgFontSources = (fonts, root) => fonts.map((font) => isLocalOgFont(font) ? { ...font, src: absoluteSrc(root, font.src) } : font);
1205
1313
  var resolveOgFonts = (options, root) => {
1206
1314
  if (options.ogFonts) {
1207
1315
  return { fonts: resolveOgFontSources(options.ogFonts, root) };
1208
1316
  }
1209
- return options.themeFontsConfigured ? deriveOgFonts(options.themeFonts, root) : { fonts: [] };
1317
+ const derived = options.themeFontsConfigured ? deriveOgFonts(options.themeFonts, root) : { fonts: [] };
1318
+ return withFallbacks(derived, options.locales ?? []);
1210
1319
  };
1211
1320
  var missingFontFiles = (options, root) => {
1212
1321
  const sources = [];
@@ -1635,7 +1744,7 @@ ${THEME_MAPPING}
1635
1744
  @apply block rounded-[0.65rem] px-2.5 py-1.5 text-muted-foreground text-sm transition-colors hover:bg-muted hover:text-foreground aria-[current=page]:bg-muted aria-[current=page]:font-medium aria-[current=page]:text-foreground;
1636
1745
  }
1637
1746
  @utility blume-nav-drill {
1638
- @apply flex w-full items-center gap-2 rounded-[0.65rem] px-2.5 py-1.5 text-left font-medium text-foreground text-sm transition-colors hover:bg-muted;
1747
+ @apply flex w-full items-center gap-2 rounded-[0.65rem] px-2.5 py-1.5 text-start font-medium text-foreground text-sm transition-colors hover:bg-muted;
1639
1748
  }
1640
1749
  @utility blume-nav-summary {
1641
1750
  @apply flex cursor-pointer list-none items-center gap-1.5 rounded-[0.65rem] px-2.5 py-1.5 text-muted-foreground text-sm transition-colors hover:bg-muted hover:text-foreground [&::-webkit-details-marker]:hidden;
@@ -2251,11 +2360,18 @@ pre:has(.line.focused):hover .line:not(.focused) {
2251
2360
  }
2252
2361
 
2253
2362
  /* Print / "Save as PDF" (the page-actions Export → PDF runs window.print()).
2254
- Strip the surrounding chrome so the printout is just the article. */
2363
+ Strip the surrounding chrome so the printout is just the article. Scoped to
2364
+ the chrome itself, never bare \`header\`/\`aside\`: content renders those too
2365
+ (every Callout and Panel is an <aside>, every changelog Update has a
2366
+ <header>), and they belong in the printout. \`body > header\` keeps a
2367
+ \`layout.Header\` override out as well. */
2255
2368
  @media print {
2256
2369
  [data-blume-banner],
2257
- header,
2258
- aside,
2370
+ [data-blume-header],
2371
+ body > header,
2372
+ [data-blume-nav-drawer],
2373
+ [data-blume-toc],
2374
+ [data-blume-assistant-panel],
2259
2375
  [data-blume-page-actions],
2260
2376
  #blume-content > nav,
2261
2377
  #blume-content > details {
@@ -3205,10 +3321,12 @@ var writeApiFiles = async (project, plan, write, data, mcp) => {
3205
3321
  }
3206
3322
  await Promise.all(writes);
3207
3323
  };
3324
+ var PLAYGROUND_PROXY_ENTRY = join11("blume-openapi", "api-proxy.ts");
3325
+ var playgroundProxyPattern = (config) => withBasePath(config.basePath, "/_api-proxy");
3208
3326
  var planPlaygroundProxy = (config, srcDir) => ({
3209
3327
  enabled: needsPlaygroundProxy(config),
3210
- entrypoint: join11(srcDir, "blume-openapi", "api-proxy.ts"),
3211
- pattern: "/_api-proxy"
3328
+ entrypoint: join11(srcDir, PLAYGROUND_PROXY_ENTRY),
3329
+ pattern: playgroundProxyPattern(config)
3212
3330
  });
3213
3331
  var specOriginsOf = (spec) => {
3214
3332
  const origins = new Set;
@@ -3217,15 +3335,24 @@ var specOriginsOf = (spec) => {
3217
3335
  origins.add(new URL(spec.endpoint).origin);
3218
3336
  } catch {}
3219
3337
  }
3220
- const { servers } = spec.document;
3221
- for (const server of Array.isArray(servers) ? servers : []) {
3222
- const url = server.url ?? "";
3223
- if (url.includes("{")) {
3224
- continue;
3338
+ const document = spec.document;
3339
+ const lists = [document.servers];
3340
+ for (const item of Object.values(document.paths ?? {})) {
3341
+ lists.push(item?.servers);
3342
+ for (const method of HTTP_METHODS) {
3343
+ lists.push(item?.[method]?.servers);
3344
+ }
3345
+ }
3346
+ for (const servers of lists) {
3347
+ for (const server of Array.isArray(servers) ? servers : []) {
3348
+ const url = withServerDefaults(server.url ?? "", server.variables);
3349
+ if (url.includes("{")) {
3350
+ continue;
3351
+ }
3352
+ try {
3353
+ origins.add(new URL(url).origin);
3354
+ } catch {}
3225
3355
  }
3226
- try {
3227
- origins.add(new URL(url).origin);
3228
- } catch {}
3229
3356
  }
3230
3357
  return [...origins];
3231
3358
  };
@@ -3237,7 +3364,7 @@ var proxyAllowlistWarnings = (config, data) => {
3237
3364
  if (!proxied.has(spec.slug) || specOriginsOf(spec).length > 0) {
3238
3365
  continue;
3239
3366
  }
3240
- warnings.push(spec.kind === "graphql" ? `The "${spec.label}" GraphQL reference (${spec.route}) has playground.proxy: true, but no absolute endpoint is configured for it, so the built-in proxy has no origin to allow and will refuse every request its playground sends. Set \`endpoint\` on the graphql() adapter (or the source) to the live GraphQL URL, or point playground.proxy at an external proxy URL.` : `The "${spec.label}" reference (${spec.route}) has playground.proxy: true, but its spec declares no absolute servers[].url (relative and templated URLs carry no origin), so the built-in proxy has no origin to allow and will refuse every request its playground sends. Add an absolute server URL to the spec, or point playground.proxy at an external proxy URL.`);
3367
+ warnings.push(spec.kind === "graphql" ? `The "${spec.label}" GraphQL reference (${spec.route}) has playground.proxy: true, but no absolute endpoint is configured for it, so the built-in proxy has no origin to allow and will refuse every request its playground sends. Set \`endpoint\` on the graphql() adapter (or the source) to the live GraphQL URL, or point playground.proxy at an external proxy URL.` : `The "${spec.label}" reference (${spec.route}) has playground.proxy: true, but its spec declares no absolute servers[].url (relative URLs, and templated ones with a variable missing its default, carry no origin), so the built-in proxy has no origin to allow and will refuse every request its playground sends. Add an absolute server URL to the spec, or point playground.proxy at an external proxy URL.`);
3241
3368
  }
3242
3369
  return warnings;
3243
3370
  };
@@ -3280,6 +3407,7 @@ var dependencyPreflight = async (project, frameworks) => {
3280
3407
  };
3281
3408
  var analyzeComponentsFile = async (componentsFile) => componentsFile ? analyzeComponentOverrides(await readFile4(componentsFile, "utf-8"), componentsFile) : emptyComponentOverrides();
3282
3409
  var projectOgFonts = (project) => resolveOgFonts({
3410
+ locales: fontLocaleCodes(project.config.i18n),
3283
3411
  ogFonts: project.config.seo.og.fonts,
3284
3412
  themeFonts: project.config.theme.fonts,
3285
3413
  themeFontsConfigured: project.themeFontsConfigured
@@ -3327,7 +3455,7 @@ var generateRuntime = async (project) => {
3327
3455
  const modules = new Map;
3328
3456
  const depsLinkWarning = await ensureDepsLink(out);
3329
3457
  const contentRoutes = markdownRoutePaths(project);
3330
- const homeLinkHeader = buildHomeLinkHeader(config, contentRoutes) ?? undefined;
3458
+ const homeLinkHeader = buildHomeLinkHeader(config, contentRoutes, "dev") ?? undefined;
3331
3459
  const assistantEnabled = config.ai.assistant?.enabled ?? false;
3332
3460
  const exportPdf = config.export.pdf;
3333
3461
  const exportEpub = config.export.epub;
@@ -3558,7 +3686,7 @@ var generateRuntime = async (project) => {
3558
3686
  return { structuralChange: structural.some(Boolean), warnings };
3559
3687
  };
3560
3688
 
3561
- export { publishBuildProject, refreshBlumeContent, showBlumeErrorOverlay, ogCacheDir, pruneCardCache, cardCacheTally, buildAskData, buildThemeCss, buildReferenceFiles, tailwindEntryTemplate, examplesEntryTemplate, rebaseSourceDirectives, twoslashCss, EXAMPLE_SCAN_GLOB, exampleScanRoots, discoverExamples, exampleMarkdownLookup, packageDirFrom, detectNeedsReact, detectUsesMath, collectStaged, buildRuntimeData, analyzeComponentsFile, languageIconCssFor, clientFeaturesFor, generateRuntime };
3689
+ export { publishBuildProject, refreshBlumeContent, showBlumeErrorOverlay, ogCacheDir, pruneCardCache, cardCacheTally, buildApiSpec, buildAskData, resolveOgFonts, buildThemeCss, buildReferenceFiles, tailwindEntryTemplate, examplesEntryTemplate, rebaseSourceDirectives, twoslashCss, EXAMPLE_SCAN_GLOB, exampleScanRoots, discoverExamples, exampleMarkdownLookup, packageDirFrom, detectNeedsReact, detectUsesMath, collectStaged, buildRuntimeData, PLAYGROUND_PROXY_ENTRY, playgroundProxyPattern, specOrigins, proxyAllowlistWarnings, analyzeComponentsFile, languageIconCssFor, clientFeaturesFor, generateRuntime };
3562
3690
 
3563
- //# debugId=35E2A04C63CD05BF64756E2164756E21
3564
- //# sourceMappingURL=chunk-wgm7m9qk.js.map
3691
+ //# debugId=067C177A5C0052FA64756E2164756E21
3692
+ //# sourceMappingURL=chunk-c8chx29p.js.map