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
@@ -1,5 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ resolveFallbackLocale,
4
+ localizeRoute,
5
+ localizeInternalPath,
6
+ i18nDiagnostics,
3
7
  blumeReferences,
4
8
  frontmatter_default,
5
9
  resolveDocsCollection,
@@ -12,10 +16,7 @@ import {
12
16
  pollingWatch,
13
17
  snapshotCache,
14
18
  loadWithCache,
15
- resolveFallbackLocale,
16
- localizeRoute,
17
- localizeInternalPath,
18
- i18nDiagnostics,
19
+ MDX_BODY_FEATURES,
19
20
  normalizeRef,
20
21
  isPageRef,
21
22
  pagesByRef,
@@ -27,6 +28,7 @@ import {
27
28
  versionsDiagnostics,
28
29
  slugify,
29
30
  slugifyPath,
31
+ unloadablePathDiagnostic,
30
32
  extractHeadings,
31
33
  strippedLineOffset,
32
34
  isStringValue,
@@ -42,7 +44,7 @@ import {
42
44
  guardBlockStart,
43
45
  renderInline,
44
46
  destination,
45
- renderLink,
47
+ linkParts,
46
48
  headingPrefix,
47
49
  blockquote,
48
50
  listItem,
@@ -65,7 +67,7 @@ import {
65
67
  createModuleLoader,
66
68
  resolveProjectContext,
67
69
  loadConfig
68
- } from "./chunk-v6ya5kcb.js";
70
+ } from "./chunk-pv29h0wf.js";
69
71
  import {
70
72
  getBlumeVersion,
71
73
  BlumeError,
@@ -76,7 +78,7 @@ import {
76
78
  isInternalPath,
77
79
  withBasePath,
78
80
  mountBasePath
79
- } from "./chunk-gs7r695n.js";
81
+ } from "./chunk-3em5wd2y.js";
80
82
 
81
83
  // src/core/manifest.ts
82
84
  var versionAlternateKey = (versionKey, locale) => `${versionKey}\x00${locale}`;
@@ -203,6 +205,103 @@ var buildManifest = (options) => {
203
205
  // src/core/project-graph.ts
204
206
  import { isAbsolute as isAbsolute3, relative as relative5 } from "pathe";
205
207
 
208
+ // src/core/directive-diagnostics.ts
209
+ import { mdxToMdast } from "satteri";
210
+
211
+ // src/markdown/directives.ts
212
+ import { toString as mdastToString } from "mdast-util-to-string";
213
+ var CALLOUT_TYPES = new Set([
214
+ "danger",
215
+ "info",
216
+ "note",
217
+ "success",
218
+ "tip",
219
+ "warning"
220
+ ]);
221
+ var CALLOUT_ALIASES = {
222
+ caution: "warning",
223
+ error: "danger",
224
+ important: "note",
225
+ warn: "warning"
226
+ };
227
+ var calloutTypeFor = (name) => {
228
+ const lower = name.toLowerCase();
229
+ if (CALLOUT_TYPES.has(lower)) {
230
+ return lower;
231
+ }
232
+ return CALLOUT_ALIASES[lower] ?? null;
233
+ };
234
+ var LITERAL_MARKERS = new Map([
235
+ ["leafDirective", "::"],
236
+ ["textDirective", ":"]
237
+ ]);
238
+ var labelSource = (label) => label.length > 0 ? `[${mdastToString(label, { includeImageAlt: false })}]` : "";
239
+ var attributeSource = (node) => {
240
+ const attributes = Object.entries(node.attributes ?? {}).map(([key, value]) => value ? `${key}="${value}"` : key);
241
+ return attributes.length > 0 ? `{${attributes.join(" ")}}` : "";
242
+ };
243
+ var spannedSource = (node, source) => {
244
+ const start = node.position?.start?.offset;
245
+ const end = node.position?.end?.offset;
246
+ return start !== undefined && end !== undefined ? source.slice(start, end) : null;
247
+ };
248
+ var directiveSource = (node, marker, source) => {
249
+ const opening = `${marker}${node.name}`;
250
+ const slice = spannedSource(node, source);
251
+ if (slice?.startsWith(opening)) {
252
+ return slice;
253
+ }
254
+ return `${opening}${labelSource(node.children ?? [])}${attributeSource(node)}`;
255
+ };
256
+
257
+ // src/core/directive-diagnostics.ts
258
+ var CONTAINER_OPENING = /^[\t >]*:{3,}(?<name>[a-z][\w-]*)/gimu;
259
+ var codeList = (names) => [...names].map((name) => `\`${name}\``).join(", ");
260
+ var CALLOUT_NAMES = `${codeList(CALLOUT_TYPES)} (or the aliases ${codeList(Object.keys(CALLOUT_ALIASES))})`;
261
+ var unknownContainers = (text) => {
262
+ const named = [...text.matchAll(CONTAINER_OPENING)].some((match) => calloutTypeFor(match.groups?.name ?? "") === null);
263
+ if (!named) {
264
+ return [];
265
+ }
266
+ let tree;
267
+ try {
268
+ tree = mdxToMdast(text, { features: MDX_BODY_FEATURES });
269
+ } catch {
270
+ return [];
271
+ }
272
+ const found = [];
273
+ const walk = (node) => {
274
+ if (node.type === "containerDirective" && calloutTypeFor(node.name) === null) {
275
+ found.push({ line: node.position?.start.line ?? 1, name: node.name });
276
+ }
277
+ if ("children" in node) {
278
+ for (const child of node.children) {
279
+ walk(child);
280
+ }
281
+ }
282
+ };
283
+ walk(tree);
284
+ return found;
285
+ };
286
+ var unknownDirectiveDiagnostics = (entry, sourceName) => {
287
+ if (entry.body.format !== "mdx") {
288
+ return [];
289
+ }
290
+ const page = entry.sourcePath ?? `${sourceName}:${entry.ref}`;
291
+ const offset = entry.bodyLineOffset ?? strippedLineOffset(entry.raw, entry.body.text);
292
+ return unknownContainers(entry.expanded?.text ?? entry.body.text).map(({ line, name }) => {
293
+ const origin = entry.expanded?.origins[line - 1];
294
+ return {
295
+ code: "BLUME_UNKNOWN_DIRECTIVE",
296
+ file: origin?.file ?? page,
297
+ line: origin?.line ?? line + offset,
298
+ message: `\`:::${name}\` isn't a callout type, so the page shows its \`:::\` lines as written around its content.`,
299
+ severity: "warning",
300
+ suggestion: `Use a callout type — ${CALLOUT_NAMES} — or remove the \`:::\` lines to keep the content as plain prose.`
301
+ };
302
+ });
303
+ };
304
+
206
305
  // src/theme/icon-kind.ts
207
306
  var IMAGE_ICON = /^(?:https?:\/\/|data:image\/|\/|\.{1,2}\/)|\.(?:avif|gif|jpe?g|png|svg|webp)$/iu;
208
307
  var INLINE_SVG = /^\s*<svg[\s\S]*<\/svg>\s*$/u;
@@ -681,7 +780,8 @@ var buildContentGraph = (pages, options) => {
681
780
 
682
781
  // src/core/last-modified.ts
683
782
  import { execFileSync } from "node:child_process";
684
- import { relative } from "pathe";
783
+ import { realpathSync } from "node:fs";
784
+ import { normalize as normalize2, relative } from "pathe";
685
785
  var GIT_LOCATION_VARS = new Set([
686
786
  "GIT_COMMON_DIR",
687
787
  "GIT_DIR",
@@ -705,6 +805,13 @@ var parseGitLog = (output) => {
705
805
  }
706
806
  return times;
707
807
  };
808
+ var realPath = (path) => {
809
+ try {
810
+ return normalize2(realpathSync.native(path));
811
+ } catch {
812
+ return path;
813
+ }
814
+ };
708
815
  var gitRepositoryRoot = (root) => {
709
816
  try {
710
817
  return execFileSync("git", ["-C", root, "rev-parse", "--show-toplevel"], { encoding: "utf-8", env: gitEnv(), stdio: ["ignore", "pipe", "ignore"] }).trim();
@@ -720,6 +827,7 @@ var gitLastModifiedTimes = (root, contentRoots, sourcePaths, repositoryRoot) =>
720
827
  if (gitRoot === null) {
721
828
  return new Map;
722
829
  }
830
+ const top = realPath(gitRoot);
723
831
  try {
724
832
  const output = execFileSync("git", [
725
833
  "-C",
@@ -730,12 +838,12 @@ var gitLastModifiedTimes = (root, contentRoots, sourcePaths, repositoryRoot) =>
730
838
  "--format=%x00%cI",
731
839
  "--name-only",
732
840
  "--",
733
- ...contentRoots
841
+ ...contentRoots.map(realPath)
734
842
  ], { encoding: "utf-8", env: gitEnv(), maxBuffer: 256 * 1024 * 1024 });
735
843
  const byRepoPath = parseGitLog(output);
736
844
  const result = new Map;
737
845
  for (const sourcePath of sourcePaths) {
738
- const iso = byRepoPath.get(relative(gitRoot, sourcePath));
846
+ const iso = byRepoPath.get(relative(top, realPath(sourcePath)));
739
847
  if (iso) {
740
848
  result.set(sourcePath, iso);
741
849
  }
@@ -797,6 +905,20 @@ var globBase = (pattern) => {
797
905
  };
798
906
  var onPathOf = (dir, base) => dir === base || base === "" || dir === "" || dir.startsWith(`${base}/`) || base.startsWith(`${dir}/`);
799
907
  var withinInclude = (dir, include) => include === undefined || include.some((pattern) => !pattern.startsWith("!") && onPathOf(dir, globBase(pattern)));
908
+ var findFolderMetaFiles = async (source, patterns = META_FILES) => {
909
+ const found = await glob([...patterns], {
910
+ absolute: true,
911
+ cwd: source.root,
912
+ ignore: [
913
+ ...source.exclude ?? [],
914
+ "**/node_modules/**",
915
+ "**/.blume/**",
916
+ "**/dist/**"
917
+ ],
918
+ onlyFiles: true
919
+ });
920
+ return found.filter((file) => withinInclude(relative2(source.root, dirname(file)), source.include));
921
+ };
800
922
  var metaKeyFor = (prefix, dir) => {
801
923
  const clean = prefix ? trimChar(prefix, "/") : "";
802
924
  if (!clean) {
@@ -813,18 +935,7 @@ var discoverFolderMeta = async (sources, options = {}) => {
813
935
  const shared = new Map;
814
936
  const diagnostics = [];
815
937
  const perSource = await Promise.all(list.map(async (source) => {
816
- const found = await glob(META_FILES, {
817
- absolute: true,
818
- cwd: source.root,
819
- ignore: [
820
- ...source.exclude ?? [],
821
- "**/node_modules/**",
822
- "**/.blume/**",
823
- "**/dist/**"
824
- ],
825
- onlyFiles: true
826
- });
827
- const files = found.filter((file) => withinInclude(relative2(source.root, dirname(file)), source.include));
938
+ const files = await findFolderMetaFiles(source);
828
939
  const loaded = await Promise.all(files.map(async (file) => {
829
940
  try {
830
941
  return {
@@ -965,30 +1076,31 @@ var embeddedEntry = (node, options) => {
965
1076
  }
966
1077
  return unsupported(`Contentful embedded entry${contentType ? `: ${contentType}` : ""}`, writesMdx(options.serializers));
967
1078
  };
968
- var renderInlines = (nodes, options) => nodes.map((node) => renderInlineNode(node, options)).join("");
969
- var renderInlineNode = (node, options) => {
1079
+ var inlineParts = (nodes, options) => nodes.flatMap((node) => inlineNodeParts(node, options));
1080
+ var inlineNodeParts = (node, options) => {
970
1081
  switch (asString(node.nodeType)) {
971
1082
  case "text": {
972
- return renderInline(asString(node.value) ?? "", marksOf(node));
1083
+ return [{ marks: marksOf(node), text: asString(node.value) ?? "" }];
973
1084
  }
974
1085
  case "hyperlink": {
975
- return renderLink(renderInlines(children(node), options), asString(getPath(node, "data.uri")));
1086
+ return linkParts(inlineParts(children(node), options), asString(getPath(node, "data.uri")));
976
1087
  }
977
1088
  case "asset-hyperlink": {
978
- return renderLink(renderInlines(children(node), options), linkedAsset(node, options)?.url);
1089
+ return linkParts(inlineParts(children(node), options), linkedAsset(node, options)?.url);
979
1090
  }
980
1091
  case "embedded-entry-inline": {
981
- return embeddedEntry(node, options);
1092
+ return [{ markdown: embeddedEntry(node, options) }];
982
1093
  }
983
1094
  default: {
984
- return renderInlines(children(node), options);
1095
+ return inlineParts(children(node), options);
985
1096
  }
986
1097
  }
987
1098
  };
1099
+ var blockText = (node, options) => guardBlockStart(renderInline(inlineParts(children(node), options)));
988
1100
  var renderList = (items, marker, options) => items.map((item, index) => listItem(marker(index), children(item).map((child) => renderBlock(child, options)).filter((block) => block !== "").join(`
989
1101
  `))).join(`
990
1102
  `);
991
- var cellText = (cell, options) => children(cell).map((paragraph) => renderInlines(children(paragraph), options)).join(" ").replaceAll(CELL_BREAK, " ").replaceAll(CELL_PIPE, String.raw`\|`);
1103
+ var cellText = (cell, options) => children(cell).map((paragraph) => blockText(paragraph, options)).join(" ").replaceAll(CELL_BREAK, " ").replaceAll(CELL_PIPE, String.raw`\|`);
992
1104
  var tableRow = (cells) => `| ${cells.join(" | ")} |`;
993
1105
  var renderTable = (node, options) => {
994
1106
  const rows = children(node).map((row) => children(row).map((cell) => cellText(cell, options)));
@@ -1007,11 +1119,11 @@ var renderBlock = (node, options) => {
1007
1119
  const type = asString(node.nodeType) ?? "";
1008
1120
  const heading = HEADING.exec(type)?.groups?.level;
1009
1121
  if (heading) {
1010
- return `${headingPrefix(Number(heading))}${guardBlockStart(renderInlines(children(node), options))}`;
1122
+ return `${headingPrefix(Number(heading))}${blockText(node, options)}`;
1011
1123
  }
1012
1124
  switch (type) {
1013
1125
  case "paragraph": {
1014
- return guardBlockStart(renderInlines(children(node), options));
1126
+ return blockText(node, options);
1015
1127
  }
1016
1128
  case "blockquote": {
1017
1129
  return blockquote(joinBlocks(children(node).map((child) => renderBlock(child, options))));
@@ -1230,7 +1342,17 @@ var filesystemSource = (options) => {
1230
1342
  onlyFiles: true
1231
1343
  });
1232
1344
  files.sort();
1233
- const entries = await Promise.all(files.map(async (file) => {
1345
+ const diagnostics = [];
1346
+ const loadable = [];
1347
+ for (const file of files) {
1348
+ const unloadable = unloadablePathDiagnostic(relative3(contentRoot, file), file);
1349
+ if (unloadable) {
1350
+ diagnostics.push(unloadable);
1351
+ } else {
1352
+ loadable.push(file);
1353
+ }
1354
+ }
1355
+ const entries = await Promise.all(loadable.map(async (file) => {
1234
1356
  const source = await readFile(file, "utf-8");
1235
1357
  const ext = extname(file).toLowerCase();
1236
1358
  const format = ext === ".mdx" ? "mdx" : "md";
@@ -1243,7 +1365,7 @@ var filesystemSource = (options) => {
1243
1365
  sourcePath: file
1244
1366
  };
1245
1367
  }));
1246
- return { diagnostics: [], entries };
1368
+ return { diagnostics, entries };
1247
1369
  };
1248
1370
  const validate = () => {
1249
1371
  if (!existsSync(contentRoot)) {
@@ -1284,7 +1406,7 @@ var filesystemSource = (options) => {
1284
1406
  // src/core/sources/github-releases.ts
1285
1407
  import { fromMarkdown } from "mdast-util-from-markdown";
1286
1408
  import { gfmFromMarkdown } from "mdast-util-gfm";
1287
- import { toString as mdastToString } from "mdast-util-to-string";
1409
+ import { toString as mdastToString2 } from "mdast-util-to-string";
1288
1410
  import { gfm } from "micromark-extension-gfm";
1289
1411
  import stringWidth from "string-width";
1290
1412
  var DEFAULT_LIMIT = 100;
@@ -1303,7 +1425,7 @@ var releaseDescription = (body) => {
1303
1425
  extensions: [gfm()],
1304
1426
  mdastExtensions: [gfmFromMarkdown()]
1305
1427
  });
1306
- const text = tree.children.filter((node) => !NON_PROSE.has(node.type)).map((node) => mdastToString(node, { includeHtml: false, includeImageAlt: false })).join(" ").replaceAll(WHITESPACE, " ").trim();
1428
+ const text = tree.children.filter((node) => !NON_PROSE.has(node.type)).map((node) => mdastToString2(node, { includeHtml: false, includeImageAlt: false })).join(" ").replaceAll(WHITESPACE, " ").trim();
1307
1429
  if (!text) {
1308
1430
  return;
1309
1431
  }
@@ -1357,7 +1479,7 @@ var rewrittenLink = (markdown, node, path) => {
1357
1479
  }
1358
1480
  const start = node.position?.start.offset ?? 0;
1359
1481
  if (markdown[start] !== "[") {
1360
- return `[${escapeMarkdownText(mdastToString(node))}](${target})`;
1482
+ return `[${escapeMarkdownText(mdastToString2(node))}](${target})`;
1361
1483
  }
1362
1484
  const first = node.children.at(0)?.position?.start.offset ?? start + 1;
1363
1485
  const last = node.children.at(-1)?.position?.end.offset ?? first;
@@ -1449,11 +1571,21 @@ var githubReleasesSource = (options, ctx) => {
1449
1571
  const include = (release) => (options.drafts || !release.draft) && (options.prereleases || !release.prerelease);
1450
1572
  const fetchPage = async (page) => {
1451
1573
  const url = `${base}/repos/${options.owner}/${options.repo}/releases?per_page=${PER_PAGE}&page=${page}`;
1452
- const res = await doFetch(url, { headers: githubHeaders() });
1453
- if (!res.ok) {
1454
- throw new Error(`${url} -> ${res.status}`);
1574
+ try {
1575
+ const res = await doFetch(url, {
1576
+ headers: githubHeaders(),
1577
+ signal: AbortSignal.timeout(REMOTE_TIMEOUT_MS)
1578
+ });
1579
+ if (!res.ok) {
1580
+ throw new Error(`${url} -> ${res.status}`);
1581
+ }
1582
+ return await res.json();
1583
+ } catch (error) {
1584
+ if (error instanceof DOMException && error.name === "TimeoutError") {
1585
+ throw new Error(`${url} did not respond within ${REMOTE_TIMEOUT_MS / 1000}s`, { cause: error });
1586
+ }
1587
+ throw error;
1455
1588
  }
1456
- return await res.json();
1457
1589
  };
1458
1590
  const fetchReleases = async () => {
1459
1591
  const collected = [];
@@ -1527,15 +1659,29 @@ var githubHeaders2 = (url) => {
1527
1659
  }
1528
1660
  return GITHUB_HOSTS.has(host) ? { authorization: `Bearer ${token}` } : {};
1529
1661
  };
1662
+ var fetchText = async (url, doFetch) => {
1663
+ try {
1664
+ const res = await doFetch(url, {
1665
+ headers: githubHeaders2(url),
1666
+ signal: AbortSignal.timeout(REMOTE_TIMEOUT_MS)
1667
+ });
1668
+ if (!res.ok) {
1669
+ throw new Error(`${url} -> ${res.status}`);
1670
+ }
1671
+ return await res.text();
1672
+ } catch (error) {
1673
+ if (error instanceof DOMException && error.name === "TimeoutError") {
1674
+ throw new Error(`${url} did not respond within ${REMOTE_TIMEOUT_MS / 1000}s`, { cause: error });
1675
+ }
1676
+ throw error;
1677
+ }
1678
+ };
1530
1679
  var enumerateGithub = async (github, include, doFetch) => {
1531
1680
  const { owner, repo, ref } = github;
1532
1681
  const base = github.path.replaceAll(/^\/|\/$/gu, "");
1533
1682
  const treeUrl = `https://api.github.com/repos/${owner}/${repo}/git/trees/${ref}?recursive=1`;
1534
- const res = await doFetch(treeUrl, { headers: githubHeaders2(treeUrl) });
1535
- if (!res.ok) {
1536
- throw new Error(`${treeUrl} -> ${res.status}`);
1537
- }
1538
- const body = await res.json();
1683
+ const text = await fetchText(treeUrl, doFetch);
1684
+ const body = JSON.parse(text);
1539
1685
  const prefix = base ? `${base}/` : "";
1540
1686
  const included = picomatch(include);
1541
1687
  const refs = (body.tree ?? []).flatMap((node) => {
@@ -1580,13 +1726,7 @@ var mdxRemoteSource = (options, ctx) => {
1580
1726
  return { refs, truncated: false };
1581
1727
  };
1582
1728
  const fetchEntry = async (item) => {
1583
- const res = await doFetch(item.fetchUrl, {
1584
- headers: githubHeaders2(item.fetchUrl)
1585
- });
1586
- if (!res.ok) {
1587
- throw new Error(`${item.fetchUrl} -> ${res.status}`);
1588
- }
1589
- const text = await res.text();
1729
+ const text = await fetchText(item.fetchUrl, doFetch);
1590
1730
  const parsed = frontmatter_default(text);
1591
1731
  const format = item.ref.toLowerCase().endsWith(".mdx") ? "mdx" : "md";
1592
1732
  return {
@@ -1610,13 +1750,16 @@ var mdxRemoteSource = (options, ctx) => {
1610
1750
  severity: "warning"
1611
1751
  });
1612
1752
  }
1753
+ const reasons = [];
1613
1754
  const settled = await Promise.all(refs.map(async (ref) => {
1614
1755
  try {
1615
1756
  return await fetchEntry(ref);
1616
1757
  } catch (error) {
1758
+ const reason = error.message;
1759
+ reasons.push(reason);
1617
1760
  skipped.push({
1618
1761
  code: "BLUME_SOURCE_FETCH_FAILED",
1619
- message: `Source "${options.name}" skipped "${ref.ref}" (${error.message}); the rest were imported.`,
1762
+ message: `Source "${options.name}" skipped "${ref.ref}" (${reason}); the rest were imported.`,
1620
1763
  severity: "warning"
1621
1764
  });
1622
1765
  return null;
@@ -1625,7 +1768,7 @@ var mdxRemoteSource = (options, ctx) => {
1625
1768
  const entries = settled.filter((entry) => entry !== null);
1626
1769
  if (refs.length > 0 && entries.length === 0) {
1627
1770
  skipped.length = 0;
1628
- throw new Error(`all ${refs.length} remote file(s) failed to fetch`);
1771
+ throw new Error(`all ${refs.length} remote file(s) failed to fetch (${reasons[0]})`);
1629
1772
  }
1630
1773
  return entries;
1631
1774
  }, refresh);
@@ -1647,6 +1790,7 @@ var mdxRemoteSource = (options, ctx) => {
1647
1790
  return {
1648
1791
  load,
1649
1792
  name: options.name,
1793
+ orderedNames: true,
1650
1794
  prefix: options.prefix,
1651
1795
  read,
1652
1796
  staged: true,
@@ -1825,12 +1969,27 @@ var materializeAssets = async (markdown, ctx) => {
1825
1969
  };
1826
1970
 
1827
1971
  // src/core/sources/notion.ts
1828
- var richToMarkdown = (rich = []) => rich.map(({ annotations = {}, href, plain_text: text }) => renderLink(renderInline(text, {
1829
- bold: annotations.bold,
1830
- code: annotations.code,
1831
- italic: annotations.italic,
1832
- strike: annotations.strikethrough
1833
- }), href ?? undefined)).join("");
1972
+ var richToMarkdown = (rich = []) => {
1973
+ const linked = [];
1974
+ for (const { annotations = {}, href, plain_text: text } of rich) {
1975
+ const run = {
1976
+ marks: {
1977
+ bold: annotations.bold,
1978
+ code: annotations.code,
1979
+ italic: annotations.italic,
1980
+ strike: annotations.strikethrough
1981
+ },
1982
+ text
1983
+ };
1984
+ const last = linked.at(-1);
1985
+ if (last && last.href === (href ?? undefined)) {
1986
+ last.runs.push(run);
1987
+ } else {
1988
+ linked.push({ href: href ?? undefined, runs: [run] });
1989
+ }
1990
+ }
1991
+ return renderInline(linked.flatMap(({ href, runs }) => linkParts(runs, href)));
1992
+ };
1834
1993
  var isBlockPayload = (value) => typeof value === "object";
1835
1994
  var payloadOf = (block) => {
1836
1995
  const value = block[block.type];
@@ -1884,7 +2043,7 @@ var renderVideo = (data) => {
1884
2043
  }
1885
2044
  const caption = richToMarkdown(data.caption);
1886
2045
  const title = caption ? ` title=${jsxString(richToPlain(data.caption))}` : "";
1887
- const media = isYouTubeUrl(url) ? `<YouTube${title} url=${JSON.stringify(url)} />` : `<video controls src=${JSON.stringify(url)} />`;
2046
+ const media = isYouTubeUrl(url) ? `<YouTube${title} url=${jsxString(url)} />` : `<video controls src="${url.replaceAll('"', "%22")}" />`;
1888
2047
  return caption ? `<Frame caption=${jsxString(caption.replaceAll(FRAME_ESCAPED, ""))}>
1889
2048
  ${media}
1890
2049
  </Frame>` : media;
@@ -2074,7 +2233,7 @@ ${nested}`;
2074
2233
  data.sidebar = { order };
2075
2234
  }
2076
2235
  const slugProp = richToPlain(page.properties[props.slug ?? "Slug"]?.rich_text);
2077
- const slug = slugifyPath(slugProp || title) || page.id;
2236
+ const slug = (slugProp ? slugifyPath(slugProp) : slugify(title.replaceAll("/", "-"))) || page.id;
2078
2237
  return { data, slug };
2079
2238
  };
2080
2239
  const toEntry = async (client, page) => {
@@ -2567,14 +2726,26 @@ var obsidianSource = (options, ctx) => {
2567
2726
  const vaultDir = resolve2(ctx.projectRoot, options.vault);
2568
2727
  const exclude = new Set([...BLUME_IGNORE_DIRS, ...options.exclude ?? []]);
2569
2728
  const load = async () => {
2570
- const files = await walkVault(vaultDir, vaultDir, exclude);
2729
+ const skipped = [];
2730
+ const files = [];
2731
+ for (const rel of await walkVault(vaultDir, vaultDir, exclude)) {
2732
+ const unloadable = unloadablePathDiagnostic(rel, join5(vaultDir, rel));
2733
+ if (unloadable) {
2734
+ skipped.push(unloadable);
2735
+ } else {
2736
+ files.push(rel);
2737
+ }
2738
+ }
2571
2739
  const read = await Promise.all(files.map((rel) => readNote(vaultDir, rel, options)));
2572
2740
  const notes = read.filter((note) => note !== null);
2573
2741
  const { index, pairs } = buildLinkIndex(notes, options);
2574
2742
  const unresolved = noTargets();
2575
2743
  const entries = pairs.map((pair) => noteToEntry(pair, index, options, unresolved));
2576
2744
  return {
2577
- diagnostics: unresolvedDiagnostics(options.name, unresolved),
2745
+ diagnostics: [
2746
+ ...skipped,
2747
+ ...unresolvedDiagnostics(options.name, unresolved)
2748
+ ],
2578
2749
  entries
2579
2750
  };
2580
2751
  };
@@ -2652,32 +2823,33 @@ var customBlock = (node, options) => {
2652
2823
  }
2653
2824
  return unsupported(`Lexical block${blockType ? `: ${blockType}` : ""}`, writesMdx(options.serializers));
2654
2825
  };
2655
- var renderInlines2 = (nodes, options) => nodes.map((node) => renderInlineNode2(node, options)).join("");
2656
- var renderInlineNode2 = (node, options) => {
2826
+ var inlineParts2 = (nodes, options) => nodes.flatMap((node) => inlineNodeParts2(node, options));
2827
+ var inlineNodeParts2 = (node, options) => {
2657
2828
  switch (typeOf(node)) {
2658
2829
  case "text": {
2659
- return renderInline(asString(node.text) ?? "", marksOf2(node));
2830
+ return [{ marks: marksOf2(node), text: asString(node.text) ?? "" }];
2660
2831
  }
2661
2832
  case "linebreak": {
2662
- return `
2663
- `;
2833
+ return [{ markdown: `
2834
+ ` }];
2664
2835
  }
2665
2836
  case "tab": {
2666
- return "\t";
2837
+ return [{ markdown: "\t" }];
2667
2838
  }
2668
2839
  case "link":
2669
2840
  case "autolink": {
2670
- return renderLink(renderInlines2(children2(node), options), asString(getPath(node, "fields.url")) ?? asString(node.url));
2841
+ return linkParts(inlineParts2(children2(node), options), asString(getPath(node, "fields.url")) ?? asString(node.url));
2671
2842
  }
2672
2843
  case "inlineBlock": {
2673
- return customBlock(node, options);
2844
+ return [{ markdown: customBlock(node, options) }];
2674
2845
  }
2675
2846
  default: {
2676
- return renderInlines2(children2(node), options);
2847
+ return inlineParts2(children2(node), options);
2677
2848
  }
2678
2849
  }
2679
2850
  };
2680
- var blockText = (node, options) => guardBlockStart(renderInlines2(children2(node), options));
2851
+ var inlineText = (nodes, options) => guardBlockStart(renderInline(inlineParts2(nodes, options)));
2852
+ var blockText2 = (node, options) => inlineText(children2(node), options);
2681
2853
  var renderUpload = (node, options) => {
2682
2854
  const value = asObject(node.value);
2683
2855
  const url = value ? asString(value.url) : undefined;
@@ -2708,7 +2880,7 @@ var renderList2 = (node, options) => {
2708
2880
  if (listType === "check") {
2709
2881
  check = item.checked === true ? "[x] " : "[ ] ";
2710
2882
  }
2711
- const line = `${check}${guardBlockStart(renderInlines2(inline, options))}`;
2883
+ const line = `${check}${inlineText(inline, options)}`;
2712
2884
  items.push(listItem(lastMarker, sub ? `${line}
2713
2885
  ${sub}` : line));
2714
2886
  index += 1;
@@ -2719,14 +2891,14 @@ ${sub}` : line));
2719
2891
  var renderBlock2 = (node, options) => {
2720
2892
  switch (typeOf(node)) {
2721
2893
  case "paragraph": {
2722
- return blockText(node, options);
2894
+ return blockText2(node, options);
2723
2895
  }
2724
2896
  case "heading": {
2725
2897
  const level = Number((asString(node.tag) ?? "h1").slice(1));
2726
- return `${headingPrefix(level)}${blockText(node, options)}`;
2898
+ return `${headingPrefix(level)}${blockText2(node, options)}`;
2727
2899
  }
2728
2900
  case "quote": {
2729
- return blockquote(blockText(node, options));
2901
+ return blockquote(blockText2(node, options));
2730
2902
  }
2731
2903
  case "list": {
2732
2904
  return renderList2(node, options);
@@ -2825,19 +2997,31 @@ var HEADING_STYLES = new Map([
2825
2997
  ["h5", "##### "],
2826
2998
  ["h6", "###### "]
2827
2999
  ]);
2828
- var renderSpan = (span, defs) => {
3000
+ var spanRun = (span) => {
2829
3001
  const marks = span.marks ?? [];
2830
- const link = marks.map((mark) => defs.get(mark)).findLast((def) => def?._type === "link");
2831
- return renderLink(renderInline(span.text ?? "", {
2832
- bold: marks.includes("strong"),
2833
- code: marks.includes("code"),
2834
- italic: marks.includes("em"),
2835
- strike: marks.includes("strike-through")
2836
- }), link?.href);
3002
+ return {
3003
+ marks: {
3004
+ bold: marks.includes("strong"),
3005
+ code: marks.includes("code"),
3006
+ italic: marks.includes("em"),
3007
+ strike: marks.includes("strike-through")
3008
+ },
3009
+ text: span.text ?? ""
3010
+ };
2837
3011
  };
2838
3012
  var renderChildren = (block) => {
2839
3013
  const defs = new Map((block.markDefs ?? []).map((def) => [def._key, def]));
2840
- return guardBlockStart((block.children ?? []).map((span) => renderSpan(span, defs)).join(""));
3014
+ const linked = [];
3015
+ for (const span of block.children ?? []) {
3016
+ const link = (span.marks ?? []).map((mark) => defs.get(mark)).findLast((def) => def?._type === "link");
3017
+ const last = linked.at(-1);
3018
+ if (last && last.link === link) {
3019
+ last.runs.push(spanRun(span));
3020
+ } else {
3021
+ linked.push({ link, runs: [spanRun(span)] });
3022
+ }
3023
+ }
3024
+ return guardBlockStart(renderInline(linked.flatMap(({ link, runs }) => linkParts(runs, link?.href))));
2841
3025
  };
2842
3026
  var isAltText = (value) => typeof value === "string";
2843
3027
  var listMarker = (block) => block.listItem === "number" ? "1." : "-";
@@ -2996,31 +3180,36 @@ var sanitySource = (options, ctx) => {
2996
3180
  // src/core/sources/strapi-blocks.ts
2997
3181
  var children3 = (node) => objectsIn(node.children);
2998
3182
  var typeOf2 = (node) => asString(node.type) ?? "";
2999
- var renderInlines3 = (nodes) => nodes.map((node) => renderInlineNode3(node)).join("");
3000
- var renderInlineNode3 = (node) => {
3183
+ var inlineParts3 = (nodes) => nodes.flatMap((node) => inlineNodeParts3(node));
3184
+ var inlineNodeParts3 = (node) => {
3001
3185
  switch (typeOf2(node)) {
3002
3186
  case "text": {
3003
- return renderInline(asString(node.text) ?? "", {
3004
- bold: node.bold === true,
3005
- code: node.code === true,
3006
- italic: node.italic === true,
3007
- strike: node.strikethrough === true
3008
- });
3187
+ return [
3188
+ {
3189
+ marks: {
3190
+ bold: node.bold === true,
3191
+ code: node.code === true,
3192
+ italic: node.italic === true,
3193
+ strike: node.strikethrough === true
3194
+ },
3195
+ text: asString(node.text) ?? ""
3196
+ }
3197
+ ];
3009
3198
  }
3010
3199
  case "link": {
3011
- return renderLink(renderInlines3(children3(node)), asString(node.url));
3200
+ return linkParts(inlineParts3(children3(node)), asString(node.url));
3012
3201
  }
3013
3202
  default: {
3014
- return renderInlines3(children3(node));
3203
+ return inlineParts3(children3(node));
3015
3204
  }
3016
3205
  }
3017
3206
  };
3018
- var blockText2 = (nodes) => guardBlockStart(renderInlines3(nodes));
3207
+ var blockText3 = (nodes) => guardBlockStart(renderInline(inlineParts3(nodes)));
3019
3208
  var renderList3 = (node) => {
3020
3209
  const ordered = asString(node.format) === "ordered";
3021
3210
  return children3(node).map((item, index) => {
3022
3211
  const kids = children3(item);
3023
- const line = blockText2(kids.filter((kid) => typeOf2(kid) !== "list"));
3212
+ const line = blockText3(kids.filter((kid) => typeOf2(kid) !== "list"));
3024
3213
  const sub = kids.filter((kid) => typeOf2(kid) === "list").map((list) => renderList3(list)).join(`
3025
3214
  `);
3026
3215
  const body = sub ? `${line}
@@ -3040,13 +3229,13 @@ var renderImage = (node, options) => {
3040
3229
  var renderBlock4 = (node, options) => {
3041
3230
  switch (typeOf2(node)) {
3042
3231
  case "paragraph": {
3043
- return blockText2(children3(node));
3232
+ return blockText3(children3(node));
3044
3233
  }
3045
3234
  case "heading": {
3046
- return `${headingPrefix(asNumber(node.level) ?? 1)}${blockText2(children3(node))}`;
3235
+ return `${headingPrefix(asNumber(node.level) ?? 1)}${blockText3(children3(node))}`;
3047
3236
  }
3048
3237
  case "quote": {
3049
- return blockquote(blockText2(children3(node)));
3238
+ return blockquote(blockText3(children3(node)));
3050
3239
  }
3051
3240
  case "list": {
3052
3241
  return renderList3(node);
@@ -3317,10 +3506,20 @@ var normalizeLoadedEntries = (loaded, config) => {
3317
3506
  }
3318
3507
  pages.push(...normalized.pages);
3319
3508
  allDiagnostics.push(...normalized.diagnostics);
3509
+ if (normalized.pages.length > 0) {
3510
+ allDiagnostics.push(...unknownDirectiveDiagnostics(entry, source.name));
3511
+ }
3320
3512
  }
3321
3513
  }
3322
3514
  return { diagnostics: allDiagnostics, droppedPages, pages };
3323
3515
  };
3516
+ var gitContentRoots = (sources, gitRoot) => {
3517
+ if (gitRoot === null) {
3518
+ return [];
3519
+ }
3520
+ const top = realPath(gitRoot);
3521
+ return sources.flatMap((source) => source.contentRoot ? [source.contentRoot] : []).filter((dir) => isWithin(top, realPath(dir)));
3522
+ };
3324
3523
  var isLogoShorthand = (logo) => typeof logo === "string";
3325
3524
  var logoHref = (logo) => logo === undefined || isLogoShorthand(logo) ? "/" : logo.href ?? "/";
3326
3525
  var isBannerShorthand = (banner) => typeof banner === "string";
@@ -3392,7 +3591,7 @@ var scanProject = async (root, options = {}) => {
3392
3591
  if (lastModified.enabled && lastModified.source === "git") {
3393
3592
  const fsPaths = pages.map((page) => page.sourcePath).filter((path) => path !== undefined);
3394
3593
  const gitRoot = gitRepositoryRoot(context.root);
3395
- const contentRoots = sources.flatMap((source) => source.contentRoot ? [source.contentRoot] : []).filter((dir) => gitRoot !== null && isWithin(gitRoot, dir));
3594
+ const contentRoots = gitContentRoots(sources, gitRoot);
3396
3595
  const gitTimes = gitLastModifiedTimes(context.root, contentRoots, fsPaths, gitRoot);
3397
3596
  for (const page of pages) {
3398
3597
  if (!page.lastModified && page.sourcePath) {
@@ -3442,7 +3641,7 @@ var scanProject = async (root, options = {}) => {
3442
3641
  };
3443
3642
  };
3444
3643
 
3445
- export { validateSearchPopularIcons, validateNavTargets, contentIndexable, buildManifest, isWithin, scanProject };
3644
+ export { directiveSource, validateSearchPopularIcons, validateNavTargets, contentIndexable, buildManifest, findFolderMetaFiles, isWithin, scanProject };
3446
3645
 
3447
- //# debugId=B3E8BA7A9A3228DD64756E2164756E21
3448
- //# sourceMappingURL=chunk-5r8g91qn.js.map
3646
+ //# debugId=B7A86608D56AB00864756E2164756E21
3647
+ //# sourceMappingURL=chunk-j85vccga.js.map