blume 2.0.2 → 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 (293) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/dist/cli/{chunk-6k4ftwze.js → chunk-1d7ve1dm.js} +1 -1
  3. package/dist/cli/{chunk-zp79m0ts.js → chunk-2eytanqx.js} +2 -2
  4. package/dist/cli/{chunk-8g8ytmgx.js → chunk-2hsdwb9n.js} +19 -19
  5. package/dist/cli/{chunk-8g8ytmgx.js.map → chunk-2hsdwb9n.js.map} +1 -1
  6. package/dist/cli/{chunk-g698a744.js → chunk-2z928egk.js} +5 -5
  7. package/dist/cli/{chunk-ppzjqwx2.js → chunk-35d4wj9f.js} +17 -18
  8. package/dist/cli/{chunk-ppzjqwx2.js.map → chunk-35d4wj9f.js.map} +3 -3
  9. package/dist/cli/{chunk-mqc662a6.js → chunk-364znk6q.js} +2 -2
  10. package/dist/cli/{chunk-gs7r695n.js → chunk-3em5wd2y.js} +21 -8
  11. package/dist/cli/{chunk-gs7r695n.js.map → chunk-3em5wd2y.js.map} +3 -3
  12. package/dist/cli/{chunk-k7pj68a8.js → chunk-5f86nr5m.js} +15 -15
  13. package/dist/cli/{chunk-hr8ne106.js → chunk-5m5nmvyq.js} +68 -43
  14. package/dist/cli/chunk-5m5nmvyq.js.map +13 -0
  15. package/dist/cli/{chunk-91ws1n6j.js → chunk-5xvm6tfj.js} +14 -14
  16. package/dist/cli/{chunk-w4bxdvsa.js → chunk-6dsbexzp.js} +14 -14
  17. package/dist/cli/{chunk-00gs3wqs.js → chunk-8ktnccpt.js} +1 -1
  18. package/dist/cli/{chunk-j85scx15.js → chunk-9t7a85s3.js} +130 -44
  19. package/dist/cli/chunk-9t7a85s3.js.map +10 -0
  20. package/dist/cli/{chunk-bbnwccaz.js → chunk-a58773jm.js} +2 -2
  21. package/dist/cli/{chunk-nfcyttvj.js → chunk-acanzt5p.js} +9 -9
  22. package/dist/cli/{chunk-nfcyttvj.js.map → chunk-acanzt5p.js.map} +1 -1
  23. package/dist/cli/{chunk-wdrt2k2v.js → chunk-akbpwfxc.js} +90 -26
  24. package/dist/cli/chunk-akbpwfxc.js.map +10 -0
  25. package/dist/cli/{chunk-sqw4ekg1.js → chunk-b07cmahc.js} +2 -2
  26. package/dist/cli/{chunk-xh43dwgw.js → chunk-c8chx29p.js} +42 -29
  27. package/dist/cli/{chunk-xh43dwgw.js.map → chunk-c8chx29p.js.map} +9 -9
  28. package/dist/cli/{chunk-7mbqtmgb.js → chunk-crgn1q09.js} +21 -12
  29. package/dist/cli/chunk-crgn1q09.js.map +10 -0
  30. package/dist/cli/chunk-e04dxsz1.js +39 -0
  31. package/dist/cli/chunk-e04dxsz1.js.map +10 -0
  32. package/dist/cli/{chunk-4e9b9ra6.js → chunk-ey84smr6.js} +3 -3
  33. package/dist/cli/{chunk-d1v5rhy0.js → chunk-g4hq16wv.js} +13 -13
  34. package/dist/cli/{chunk-273ygyr4.js → chunk-ga0pf4aj.js} +7 -7
  35. package/dist/cli/{chunk-273ygyr4.js.map → chunk-ga0pf4aj.js.map} +3 -3
  36. package/dist/cli/{chunk-pbg5a4s3.js → chunk-hm3vjy5s.js} +64 -45
  37. package/dist/cli/chunk-hm3vjy5s.js.map +19 -0
  38. package/dist/cli/{chunk-5r8g91qn.js → chunk-j85vccga.js} +306 -107
  39. package/dist/cli/chunk-j85vccga.js.map +36 -0
  40. package/dist/cli/{chunk-n1yg3tj3.js → chunk-p3v96n38.js} +6 -6
  41. package/dist/cli/{chunk-n1yg3tj3.js.map → chunk-p3v96n38.js.map} +3 -3
  42. package/dist/cli/{chunk-7vtckvaw.js → chunk-p73c0m7w.js} +14 -14
  43. package/dist/cli/{chunk-7vtckvaw.js.map → chunk-p73c0m7w.js.map} +1 -1
  44. package/dist/cli/{chunk-qkb5a8sa.js → chunk-pehfxfta.js} +3 -3
  45. package/dist/cli/{chunk-v6ya5kcb.js → chunk-pv29h0wf.js} +1223 -978
  46. package/dist/cli/{chunk-v6ya5kcb.js.map → chunk-pv29h0wf.js.map} +47 -46
  47. package/dist/cli/{chunk-6dtt0zfn.js → chunk-q58y5e6a.js} +10 -10
  48. package/dist/cli/{chunk-6dtt0zfn.js.map → chunk-q58y5e6a.js.map} +3 -3
  49. package/dist/cli/{chunk-fsmrqk8a.js → chunk-r20tn01b.js} +1 -1
  50. package/dist/cli/{chunk-bfwp9vp6.js → chunk-r9rcc4w7.js} +7 -7
  51. package/dist/cli/{chunk-h7k3nq3v.js → chunk-tkacnehg.js} +2 -2
  52. package/dist/cli/{chunk-h2ez8dzb.js → chunk-tzmab476.js} +4 -4
  53. package/dist/cli/{chunk-3yce002v.js → chunk-vg9r4eb9.js} +6 -6
  54. package/dist/cli/{chunk-3yce002v.js.map → chunk-vg9r4eb9.js.map} +4 -4
  55. package/dist/cli/{chunk-hqp2ajnh.js → chunk-wrr3j9w9.js} +16 -17
  56. package/dist/cli/{chunk-hqp2ajnh.js.map → chunk-wrr3j9w9.js.map} +7 -7
  57. package/dist/cli/{chunk-ddndchfr.js → chunk-yfyb25rh.js} +38 -26
  58. package/dist/cli/chunk-yfyb25rh.js.map +14 -0
  59. package/dist/cli/index.js +20 -18
  60. package/dist/cli/index.js.map +3 -3
  61. package/dist/types/ai/link-headers.d.ts +8 -1
  62. package/dist/types/ai/openapi-components.d.ts +5 -2
  63. package/dist/types/ai/relative-links.d.ts +9 -7
  64. package/dist/types/ai/skills.d.ts +4 -1
  65. package/dist/types/ai/tar.d.ts +1 -3
  66. package/dist/types/analytics/index.d.ts +2 -0
  67. package/dist/types/analytics/one-dollar-stats.d.ts +48 -0
  68. package/dist/types/analytics/schema.d.ts +14 -0
  69. package/dist/types/astro/integration.d.ts +3 -2
  70. package/dist/types/core/base-path.d.ts +21 -7
  71. package/dist/types/core/config-input.d.ts +9 -7
  72. package/dist/types/core/directive-diagnostics.d.ts +12 -0
  73. package/dist/types/core/heading-markers.d.ts +5 -7
  74. package/dist/types/core/i18n.d.ts +2 -0
  75. package/dist/types/core/last-modified.d.ts +10 -0
  76. package/dist/types/core/meta.d.ts +8 -0
  77. package/dist/types/core/schema.d.ts +7 -0
  78. package/dist/types/core/sources/lower.d.ts +29 -16
  79. package/dist/types/core/sources/normalize.d.ts +13 -1
  80. package/dist/types/core/sources/watch.d.ts +12 -5
  81. package/dist/types/core/standard-schema.d.ts +5 -0
  82. package/dist/types/deploy/artifacts.d.ts +6 -4
  83. package/dist/types/deploy/headers.d.ts +5 -0
  84. package/dist/types/deploy/platforms/types.d.ts +8 -0
  85. package/dist/types/deploy/redirects.d.ts +24 -13
  86. package/dist/types/markdown/directives.d.ts +62 -0
  87. package/dist/types/markdown/features.d.ts +21 -0
  88. package/dist/types/markdown/mdast.d.ts +63 -0
  89. package/dist/types/openapi/asyncapi.d.ts +4 -2
  90. package/docs/02-deployment.mdx +4 -2
  91. package/docs/08-faq.mdx +1 -1
  92. package/docs/advanced/custom-pages.mdx +3 -3
  93. package/docs/cli/audit.mdx +17 -1
  94. package/docs/cli/evals.mdx +3 -3
  95. package/docs/cli/translate.mdx +3 -3
  96. package/docs/cli/version.mdx +1 -1
  97. package/docs/configuration/analytics.mdx +20 -1
  98. package/docs/configuration/customization.mdx +2 -0
  99. package/docs/configuration/search.mdx +1 -1
  100. package/docs/content/components.mdx +1 -1
  101. package/docs/content/frontmatter.mdx +1 -1
  102. package/docs/content/i18n.mdx +2 -0
  103. package/docs/content/index.mdx +4 -2
  104. package/docs/content/islands.mdx +1 -1
  105. package/docs/content/meta.mdx +3 -1
  106. package/docs/content/sources.mdx +1 -5
  107. package/docs/content/syntax.mdx +14 -0
  108. package/docs/content/versioning.mdx +1 -1
  109. package/docs/discoverability/agent-discovery.mdx +1 -1
  110. package/docs/discoverability/index.mdx +2 -1
  111. package/docs/discoverability/markdown.mdx +2 -2
  112. package/docs/discoverability/open-graph.mdx +5 -3
  113. package/docs/discoverability/rss.mdx +1 -1
  114. package/docs/references/asyncapi.mdx +1 -1
  115. package/docs/references/graphql.mdx +1 -1
  116. package/docs/references/openapi.mdx +5 -3
  117. package/package.json +1 -1
  118. package/skills/blume-migrate/references/fumadocs.md +1 -1
  119. package/skills/blume-migrate/references/nextra.md +1 -1
  120. package/skills/blume-migrate/scripts/mintlify-codemod.mjs +7 -2
  121. package/src/ai/agent-readability.ts +2 -2
  122. package/src/ai/ai-catalog.ts +6 -2
  123. package/src/ai/api/handlers.ts +2 -2
  124. package/src/ai/api/spec.ts +2 -2
  125. package/src/ai/api-catalog.ts +6 -2
  126. package/src/ai/changelog-markdown.ts +2 -2
  127. package/src/ai/link-headers.ts +14 -5
  128. package/src/ai/llms.ts +18 -7
  129. package/src/ai/mcp/discovery.ts +2 -2
  130. package/src/ai/mcp/query.ts +2 -2
  131. package/src/ai/mcp/server.ts +2 -2
  132. package/src/ai/openapi-components.ts +22 -6
  133. package/src/ai/relative-links.ts +42 -26
  134. package/src/ai/serializers.ts +2 -1
  135. package/src/ai/skills.ts +14 -1
  136. package/src/ai/tar.ts +139 -12
  137. package/src/analytics/head.ts +4 -0
  138. package/src/analytics/index.ts +5 -0
  139. package/src/analytics/one-dollar-stats.ts +86 -0
  140. package/src/analytics/schema.ts +2 -0
  141. package/src/astro/generate.ts +1 -1
  142. package/src/astro/include-hmr.ts +31 -12
  143. package/src/astro/include-refresh.ts +19 -8
  144. package/src/astro/integration.ts +108 -14
  145. package/src/astro/runtime-modules.ts +28 -13
  146. package/src/astro/templates.ts +81 -37
  147. package/src/audit/checks/links.ts +8 -1
  148. package/src/audit/graph.ts +3 -1
  149. package/src/audit/run.ts +12 -9
  150. package/src/audit/snapshot.ts +5 -0
  151. package/src/cli/args.ts +32 -0
  152. package/src/cli/commands/audit.ts +4 -1
  153. package/src/cli/commands/doctor.ts +3 -1
  154. package/src/cli/commands/eval.ts +19 -11
  155. package/src/cli/commands/translate.ts +9 -12
  156. package/src/cli/commands/validate.ts +3 -1
  157. package/src/cli/dev-lock.ts +157 -37
  158. package/src/cli/report-format.ts +11 -6
  159. package/src/components/colors.ts +19 -0
  160. package/src/components/content/Badge.astro +5 -3
  161. package/src/components/content/Component.astro +2 -2
  162. package/src/components/content/Tab.astro +0 -1
  163. package/src/components/content/Tabs.astro +4 -0
  164. package/src/components/content/badge-color.ts +5 -2
  165. package/src/components/content/base-href.ts +13 -36
  166. package/src/components/islands/assistant.tsx +21 -4
  167. package/src/components/islands/base-path.ts +47 -10
  168. package/src/components/islands/hooks.ts +35 -19
  169. package/src/components/islands/webmcp.ts +4 -2
  170. package/src/components/layout/Breadcrumbs.astro +5 -2
  171. package/src/components/layout/DiscoveryLinks.astro +9 -5
  172. package/src/components/layout/Header.astro +2 -2
  173. package/src/components/layout/LanguageSwitcher.astro +2 -2
  174. package/src/components/layout/NavSelector.astro +2 -2
  175. package/src/components/layout/NavTabMenu.astro +3 -3
  176. package/src/components/layout/NavTree.astro +16 -6
  177. package/src/components/layout/PageActions.astro +4 -3
  178. package/src/components/layout/PageLayout.astro +7 -6
  179. package/src/components/layout/Pagination.astro +3 -3
  180. package/src/components/layout/RootLayout.astro +5 -5
  181. package/src/components/layout/Search.astro +33 -13
  182. package/src/components/layout/VersionBanner.astro +2 -2
  183. package/src/components/layout/analytics-client.ts +12 -0
  184. package/src/components/layout/toc-active.ts +41 -0
  185. package/src/components/layout/toc-element.ts +8 -14
  186. package/src/components/openapi/ApiTagOperations.astro +2 -2
  187. package/src/components/openapi/AsyncApiOperation.astro +7 -4
  188. package/src/components/openapi/GraphqlChip.astro +2 -2
  189. package/src/components/openapi/Operation.astro +2 -0
  190. package/src/components/openapi/Playground.astro +4 -4
  191. package/src/components/openapi/RequestPanel.astro +5 -2
  192. package/src/components/openapi/SchemaTable.astro +7 -0
  193. package/src/components/openapi/async.ts +38 -6
  194. package/src/components/openapi/helpers.ts +19 -9
  195. package/src/components/openapi/message-composer.ts +6 -1
  196. package/src/components/openapi/message.ts +17 -2
  197. package/src/components/openapi/operation-model.ts +81 -11
  198. package/src/components/openapi/panel.ts +4 -2
  199. package/src/components/openapi/param-style.ts +181 -0
  200. package/src/components/openapi/playground-client.ts +73 -16
  201. package/src/components/openapi/request.ts +190 -26
  202. package/src/components/openapi/schema-tree.ts +30 -24
  203. package/src/components/openapi/snippets.ts +85 -6
  204. package/src/components/openapi/ws-client.ts +18 -2
  205. package/src/core/base-path.ts +62 -16
  206. package/src/core/config-input.ts +9 -7
  207. package/src/core/diagnostics.ts +2 -0
  208. package/src/core/directive-diagnostics.ts +99 -0
  209. package/src/core/frontmatter.ts +21 -18
  210. package/src/core/heading-markers.ts +5 -18
  211. package/src/core/i18n.ts +31 -3
  212. package/src/core/last-modified.ts +25 -3
  213. package/src/core/locale-links.ts +5 -1
  214. package/src/core/meta.ts +33 -19
  215. package/src/core/navigation.ts +28 -8
  216. package/src/core/project-graph.ts +27 -5
  217. package/src/core/schema.ts +24 -4
  218. package/src/core/sources/contentful-rich-text.ts +27 -20
  219. package/src/core/sources/filesystem.ts +20 -2
  220. package/src/core/sources/github-releases.ts +25 -6
  221. package/src/core/sources/lexical.ts +23 -18
  222. package/src/core/sources/lower.ts +201 -34
  223. package/src/core/sources/mdx-remote.ts +51 -16
  224. package/src/core/sources/normalize.ts +325 -90
  225. package/src/core/sources/notion.ts +52 -25
  226. package/src/core/sources/obsidian.ts +23 -6
  227. package/src/core/sources/portable-text.ts +38 -21
  228. package/src/core/sources/strapi-blocks.ts +20 -16
  229. package/src/core/sources/watch.ts +20 -7
  230. package/src/core/standard-schema.ts +10 -6
  231. package/src/core/version-cut.ts +52 -15
  232. package/src/deploy/artifacts.ts +27 -6
  233. package/src/deploy/cloudflare-negotiation.ts +4 -12
  234. package/src/deploy/headers.ts +8 -4
  235. package/src/deploy/node-headers.ts +1 -1
  236. package/src/deploy/platforms/cloudflare.ts +12 -3
  237. package/src/deploy/platforms/netlify.ts +1 -0
  238. package/src/deploy/platforms/node.ts +1 -0
  239. package/src/deploy/platforms/static.ts +1 -0
  240. package/src/deploy/platforms/types.ts +8 -0
  241. package/src/deploy/platforms/vercel.ts +1 -0
  242. package/src/deploy/redirects.ts +54 -18
  243. package/src/deploy/robots.ts +2 -2
  244. package/src/deploy/rss.ts +4 -3
  245. package/src/deploy/sitemap.ts +7 -5
  246. package/src/markdown/base-links.ts +34 -36
  247. package/src/markdown/directives.ts +242 -36
  248. package/src/markdown/features.ts +17 -0
  249. package/src/markdown/index.ts +7 -6
  250. package/src/markdown/mdast.ts +5 -2
  251. package/src/markdown/relative-links.ts +12 -4
  252. package/src/og/card.ts +129 -5
  253. package/src/og/derive.ts +41 -31
  254. package/src/og/index.ts +1 -0
  255. package/src/openapi/asyncapi.ts +4 -2
  256. package/src/openapi/model.ts +22 -14
  257. package/src/openapi/proxy.ts +63 -10
  258. package/src/openapi/render-mdx.ts +41 -2
  259. package/src/registry/eject.ts +181 -24
  260. package/src/search/adapters/version-scope.ts +30 -0
  261. package/src/search/documents.ts +67 -26
  262. package/src/search/popular.ts +2 -1
  263. package/src/seo/jsonld.ts +7 -3
  264. package/src/translate/meta.ts +68 -24
  265. package/src/translate/run.ts +3 -3
  266. package/src/translate/validate.ts +4 -1
  267. package/src/translate/work-list.ts +56 -17
  268. package/dist/cli/chunk-5r8g91qn.js.map +0 -34
  269. package/dist/cli/chunk-7mbqtmgb.js.map +0 -10
  270. package/dist/cli/chunk-ddndchfr.js.map +0 -14
  271. package/dist/cli/chunk-esh98wmb.js +0 -23
  272. package/dist/cli/chunk-esh98wmb.js.map +0 -10
  273. package/dist/cli/chunk-hr8ne106.js.map +0 -13
  274. package/dist/cli/chunk-j85scx15.js.map +0 -10
  275. package/dist/cli/chunk-pbg5a4s3.js.map +0 -19
  276. package/dist/cli/chunk-wdrt2k2v.js.map +0 -10
  277. /package/dist/cli/{chunk-6k4ftwze.js.map → chunk-1d7ve1dm.js.map} +0 -0
  278. /package/dist/cli/{chunk-zp79m0ts.js.map → chunk-2eytanqx.js.map} +0 -0
  279. /package/dist/cli/{chunk-g698a744.js.map → chunk-2z928egk.js.map} +0 -0
  280. /package/dist/cli/{chunk-mqc662a6.js.map → chunk-364znk6q.js.map} +0 -0
  281. /package/dist/cli/{chunk-k7pj68a8.js.map → chunk-5f86nr5m.js.map} +0 -0
  282. /package/dist/cli/{chunk-91ws1n6j.js.map → chunk-5xvm6tfj.js.map} +0 -0
  283. /package/dist/cli/{chunk-w4bxdvsa.js.map → chunk-6dsbexzp.js.map} +0 -0
  284. /package/dist/cli/{chunk-00gs3wqs.js.map → chunk-8ktnccpt.js.map} +0 -0
  285. /package/dist/cli/{chunk-bbnwccaz.js.map → chunk-a58773jm.js.map} +0 -0
  286. /package/dist/cli/{chunk-sqw4ekg1.js.map → chunk-b07cmahc.js.map} +0 -0
  287. /package/dist/cli/{chunk-4e9b9ra6.js.map → chunk-ey84smr6.js.map} +0 -0
  288. /package/dist/cli/{chunk-d1v5rhy0.js.map → chunk-g4hq16wv.js.map} +0 -0
  289. /package/dist/cli/{chunk-qkb5a8sa.js.map → chunk-pehfxfta.js.map} +0 -0
  290. /package/dist/cli/{chunk-fsmrqk8a.js.map → chunk-r20tn01b.js.map} +0 -0
  291. /package/dist/cli/{chunk-bfwp9vp6.js.map → chunk-r9rcc4w7.js.map} +0 -0
  292. /package/dist/cli/{chunk-h7k3nq3v.js.map → chunk-tkacnehg.js.map} +0 -0
  293. /package/dist/cli/{chunk-h2ez8dzb.js.map → chunk-tzmab476.js.map} +0 -0
@@ -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": "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",
8
+ "debugId": "BA0F0BBCC7BD124F64756E2164756E21",
9
+ "names": []
10
+ }
@@ -5,7 +5,7 @@ import {
5
5
  import {
6
6
  commandsFor,
7
7
  detectProjectPackageManager
8
- } from "./chunk-v6ya5kcb.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-sqw4ekg1.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,7 +27,6 @@ import {
26
27
  routeIsTaken,
27
28
  hasGeneratedChangelog,
28
29
  customOgRoutes,
29
- resolveFallbackLocale,
30
30
  resolveAskBackend,
31
31
  GOOGLE_FONTS,
32
32
  isFontSlug,
@@ -49,22 +49,23 @@ import {
49
49
  isOpenApiSource,
50
50
  buildRawMarkdown,
51
51
  markdownRoutePaths
52
- } from "./chunk-v6ya5kcb.js";
52
+ } from "./chunk-pv29h0wf.js";
53
53
  import {
54
54
  trimChar,
55
55
  normalizeBasePath,
56
56
  withBasePath,
57
+ mountBasePath,
57
58
  siteRoot,
58
59
  absoluteUrl2
59
- } from "./chunk-gs7r695n.js";
60
+ } from "./chunk-3em5wd2y.js";
60
61
  import {
61
62
  validateSearchPopularIcons,
62
63
  validateNavTargets
63
- } from "./chunk-5r8g91qn.js";
64
+ } from "./chunk-j85vccga.js";
64
65
  import {
65
66
  buildSearchDocuments,
66
67
  buildMcpData
67
- } from "./chunk-ddndchfr.js";
68
+ } from "./chunk-yfyb25rh.js";
68
69
  import {
69
70
  planComponentSlots,
70
71
  publishRuntimeModules,
@@ -104,22 +105,22 @@ import {
104
105
  examplesPageTemplate,
105
106
  runtimePackageTemplate,
106
107
  runtimeTsconfigTemplate
107
- } from "./chunk-hr8ne106.js";
108
+ } from "./chunk-5m5nmvyq.js";
108
109
  import {
109
110
  emptyComponentOverrides,
110
111
  analyzeComponentOverrides
111
- } from "./chunk-00gs3wqs.js";
112
+ } from "./chunk-8ktnccpt.js";
112
113
  import {
113
114
  writeTextAtomic
114
115
  } from "./chunk-jq5n4avg.js";
115
116
  import {
116
117
  registry
117
- } from "./chunk-fsmrqk8a.js";
118
+ } from "./chunk-r20tn01b.js";
118
119
  import {
119
120
  readClientMode,
120
121
  discoverIslands,
121
122
  missingDependencyDiagnostic
122
- } from "./chunk-sqw4ekg1.js";
123
+ } from "./chunk-b07cmahc.js";
123
124
 
124
125
  // src/astro/integration.ts
125
126
  import { join as join3, relative, resolve as resolve2 } from "pathe";
@@ -156,18 +157,29 @@ var publishDevNegotiation = (negotiation) => {
156
157
  homeLinkHeader: negotiation.homeLinkHeader
157
158
  } : null;
158
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
+ };
159
171
  var refreshBlumeContent = async () => {
160
- const { refreshContent } = registry2();
172
+ const { overlay, refreshContent } = registry2();
161
173
  if (!refreshContent) {
162
174
  return false;
163
175
  }
164
176
  await refreshContent({});
177
+ if (overlay) {
178
+ invalidateDataStore(overlay);
179
+ }
165
180
  return true;
166
181
  };
167
- var overlayChannel = () => {
168
- const { overlay } = registry2();
169
- return overlay?.ws ?? overlay?.hot;
170
- };
182
+ var overlayChannel = () => overlayChannelOf(registry2().overlay);
171
183
  var showBlumeErrorOverlay = (diagnostics) => {
172
184
  const errors = [];
173
185
  for (const diagnostic of diagnostics) {
@@ -774,7 +786,7 @@ var buildApiSpec = (input) => {
774
786
  if (input.site) {
775
787
  document.externalDocs = {
776
788
  description: `${input.name} documentation`,
777
- url: absoluteUrl2(input.site, withBasePath(input.base, "/"))
789
+ url: absoluteUrl2(input.site, mountBasePath(input.base, "/"))
778
790
  };
779
791
  }
780
792
  return document;
@@ -1270,10 +1282,14 @@ var localeFamily = (locale) => {
1270
1282
  }
1271
1283
  return localeFontSubsets([locale]).length > 1 ? "Noto Sans" : null;
1272
1284
  };
1273
- var localeOgFonts = (locales) => {
1285
+ var DEFAULT_FALLBACKS = [
1286
+ "Noto Sans",
1287
+ ...new Set(Object.values(SCRIPT_FAMILIES)),
1288
+ "Noto Sans TC"
1289
+ ];
1290
+ var ogFallbackFonts = (locales) => {
1274
1291
  const names = new Set;
1275
- for (const locale of locales) {
1276
- const family = localeFamily(locale);
1292
+ for (const family of [...locales.map(localeFamily), ...DEFAULT_FALLBACKS]) {
1277
1293
  if (family) {
1278
1294
  names.add(family);
1279
1295
  }
@@ -1282,18 +1298,15 @@ var localeOgFonts = (locales) => {
1282
1298
  };
1283
1299
  var isGoogleFamilyName = (font) => typeof font === "string";
1284
1300
  var ogFontName = (font) => isGoogleFamilyName(font) ? font : font.name;
1285
- var withLocaleFonts = (derived, locales) => {
1301
+ var withFallbacks = (derived, locales) => {
1286
1302
  const loaded = new Set(derived.fonts.map(ogFontName));
1287
- const fallbacks = localeOgFonts(locales).filter((font) => !loaded.has(ogFontName(font)));
1288
- if (fallbacks.length === 0) {
1289
- return derived;
1290
- }
1291
1303
  return {
1304
+ fallbacks: ogFallbackFonts(locales).filter((font) => !loaded.has(font.name)),
1292
1305
  families: derived.families ?? {
1293
1306
  body: BUILT_IN_FAMILY,
1294
1307
  title: BUILT_IN_FAMILY
1295
1308
  },
1296
- fonts: [...derived.fonts, ...fallbacks]
1309
+ fonts: derived.fonts
1297
1310
  };
1298
1311
  };
1299
1312
  var resolveOgFontSources = (fonts, root) => fonts.map((font) => isLocalOgFont(font) ? { ...font, src: absoluteSrc(root, font.src) } : font);
@@ -1302,7 +1315,7 @@ var resolveOgFonts = (options, root) => {
1302
1315
  return { fonts: resolveOgFontSources(options.ogFonts, root) };
1303
1316
  }
1304
1317
  const derived = options.themeFontsConfigured ? deriveOgFonts(options.themeFonts, root) : { fonts: [] };
1305
- return withLocaleFonts(derived, options.locales ?? []);
1318
+ return withFallbacks(derived, options.locales ?? []);
1306
1319
  };
1307
1320
  var missingFontFiles = (options, root) => {
1308
1321
  const sources = [];
@@ -3442,7 +3455,7 @@ var generateRuntime = async (project) => {
3442
3455
  const modules = new Map;
3443
3456
  const depsLinkWarning = await ensureDepsLink(out);
3444
3457
  const contentRoutes = markdownRoutePaths(project);
3445
- const homeLinkHeader = buildHomeLinkHeader(config, contentRoutes) ?? undefined;
3458
+ const homeLinkHeader = buildHomeLinkHeader(config, contentRoutes, "dev") ?? undefined;
3446
3459
  const assistantEnabled = config.ai.assistant?.enabled ?? false;
3447
3460
  const exportPdf = config.export.pdf;
3448
3461
  const exportEpub = config.export.epub;
@@ -3673,7 +3686,7 @@ var generateRuntime = async (project) => {
3673
3686
  return { structuralChange: structural.some(Boolean), warnings };
3674
3687
  };
3675
3688
 
3676
- 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, PLAYGROUND_PROXY_ENTRY, playgroundProxyPattern, specOrigins, proxyAllowlistWarnings, 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 };
3677
3690
 
3678
- //# debugId=0D8B04D4ECFE76CE64756E2164756E21
3679
- //# sourceMappingURL=chunk-xh43dwgw.js.map
3691
+ //# debugId=067C177A5C0052FA64756E2164756E21
3692
+ //# sourceMappingURL=chunk-c8chx29p.js.map