blume 2.1.3 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (397) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +134 -0
  3. package/README.md +4 -4
  4. package/dist/cli/{chunk-y4msrwm9.js → chunk-080mfch6.js} +15 -15
  5. package/dist/cli/{chunk-gfc5fqvf.js → chunk-1ch3ct3r.js} +18 -18
  6. package/dist/cli/{chunk-gfc5fqvf.js.map → chunk-1ch3ct3r.js.map} +1 -1
  7. package/dist/cli/{chunk-32khwcb6.js → chunk-2ssh60qh.js} +42 -69
  8. package/dist/cli/{chunk-32khwcb6.js.map → chunk-2ssh60qh.js.map} +9 -10
  9. package/dist/cli/{chunk-9qzgg6mj.js → chunk-34wap3ed.js} +3 -3
  10. package/dist/cli/{chunk-k3gr1nm9.js → chunk-40vk8kgf.js} +13 -16
  11. package/dist/cli/{chunk-k3gr1nm9.js.map → chunk-40vk8kgf.js.map} +3 -3
  12. package/dist/cli/chunk-487b95qy.js +329 -0
  13. package/dist/cli/chunk-487b95qy.js.map +13 -0
  14. package/dist/cli/chunk-4zxh25hc.js +157 -0
  15. package/dist/cli/chunk-4zxh25hc.js.map +10 -0
  16. package/dist/cli/chunk-69rjf786.js +146 -0
  17. package/dist/cli/chunk-69rjf786.js.map +11 -0
  18. package/dist/cli/{chunk-dqhg54mr.js → chunk-9h8mh2tk.js} +3 -3
  19. package/dist/cli/{chunk-dqhg54mr.js.map → chunk-9h8mh2tk.js.map} +2 -2
  20. package/dist/cli/{chunk-bqxaqn5p.js → chunk-9jqmq5hv.js} +8 -8
  21. package/dist/cli/{chunk-bqxaqn5p.js.map → chunk-9jqmq5hv.js.map} +1 -1
  22. package/dist/cli/{chunk-dv2z0rzf.js → chunk-aafhwx74.js} +38 -13
  23. package/dist/cli/{chunk-dv2z0rzf.js.map → chunk-aafhwx74.js.map} +5 -4
  24. package/dist/cli/{chunk-desvm72z.js → chunk-b680sv30.js} +22 -26
  25. package/dist/cli/chunk-b680sv30.js.map +13 -0
  26. package/dist/cli/{chunk-0w6hs479.js → chunk-beb0z983.js} +30 -18
  27. package/dist/cli/chunk-beb0z983.js.map +10 -0
  28. package/dist/cli/{chunk-1f882900.js → chunk-c5bjxq8v.js} +2 -2
  29. package/dist/cli/chunk-e1n41w9m.js +155 -0
  30. package/dist/cli/chunk-e1n41w9m.js.map +11 -0
  31. package/dist/cli/{chunk-sc93apfs.js → chunk-etckvbrh.js} +17 -17
  32. package/dist/cli/{chunk-sc93apfs.js.map → chunk-etckvbrh.js.map} +2 -2
  33. package/dist/cli/{chunk-bxwhtvw8.js → chunk-f260jdrn.js} +5 -5
  34. package/dist/cli/{chunk-74wfhv79.js → chunk-fnxgtjeq.js} +1 -1
  35. package/dist/cli/{chunk-ms9z66nz.js → chunk-gwy55cx3.js} +2 -2
  36. package/dist/cli/{chunk-ms9z66nz.js.map → chunk-gwy55cx3.js.map} +2 -2
  37. package/dist/cli/{chunk-dhwtqnnd.js → chunk-gxhcf2hs.js} +2 -2
  38. package/dist/cli/{chunk-tfycddbt.js → chunk-h0qwdbem.js} +2 -2
  39. package/dist/cli/{chunk-nbyvgnnm.js → chunk-hktq4j5r.js} +109 -49
  40. package/dist/cli/chunk-hktq4j5r.js.map +36 -0
  41. package/dist/cli/{chunk-twy7psdz.js → chunk-hn3g2b89.js} +14 -10
  42. package/dist/cli/chunk-hn3g2b89.js.map +10 -0
  43. package/dist/cli/{chunk-j1x92mx9.js → chunk-j4nfgn2j.js} +1 -1
  44. package/dist/cli/{chunk-dpy8qdjf.js → chunk-k45sq16q.js} +74 -183
  45. package/dist/cli/chunk-k45sq16q.js.map +18 -0
  46. package/dist/cli/{chunk-5cmts6dv.js → chunk-kmswjxj9.js} +7 -7
  47. package/dist/cli/{chunk-5cmts6dv.js.map → chunk-kmswjxj9.js.map} +1 -1
  48. package/dist/cli/{chunk-36bxs9c7.js → chunk-nqna8dzp.js} +27 -23
  49. package/dist/cli/chunk-nqna8dzp.js.map +10 -0
  50. package/dist/cli/{chunk-a57yh0h9.js → chunk-p834rkcn.js} +7 -7
  51. package/dist/cli/{chunk-a57yh0h9.js.map → chunk-p834rkcn.js.map} +1 -1
  52. package/dist/cli/{chunk-60hz265r.js → chunk-ppa6mg4d.js} +24 -11
  53. package/dist/cli/chunk-ppa6mg4d.js.map +10 -0
  54. package/dist/cli/{chunk-s0bdnc7v.js → chunk-q1wwrxzw.js} +5 -4
  55. package/dist/cli/chunk-q1wwrxzw.js.map +10 -0
  56. package/dist/cli/{chunk-ave1wcbr.js → chunk-qcyxkj44.js} +1 -1
  57. package/dist/cli/{chunk-124fvmzq.js → chunk-r5nm9w0c.js} +11183 -8806
  58. package/dist/cli/{chunk-124fvmzq.js.map → chunk-r5nm9w0c.js.map} +82 -66
  59. package/dist/cli/{chunk-ckrcm08h.js → chunk-rtvgmg2j.js} +48 -62
  60. package/dist/cli/{chunk-ckrcm08h.js.map → chunk-rtvgmg2j.js.map} +4 -5
  61. package/dist/cli/{chunk-297ajdcv.js → chunk-t2h8pwy1.js} +6 -6
  62. package/dist/cli/{chunk-297ajdcv.js.map → chunk-t2h8pwy1.js.map} +3 -3
  63. package/dist/cli/{chunk-gxtg6ed2.js → chunk-x60e15st.js} +21 -21
  64. package/dist/cli/{chunk-gxtg6ed2.js.map → chunk-x60e15st.js.map} +3 -3
  65. package/dist/cli/{chunk-58bt3hag.js → chunk-x7bh6d9j.js} +4 -4
  66. package/dist/cli/{chunk-hvcxng5f.js → chunk-ydqzkhjn.js} +6 -6
  67. package/dist/cli/{chunk-kdpzw38a.js → chunk-yg8ckc3g.js} +95 -7
  68. package/dist/cli/chunk-yg8ckc3g.js.map +11 -0
  69. package/dist/cli/{chunk-0pmb4tr4.js → chunk-zxd5jrgx.js} +1205 -222
  70. package/dist/cli/chunk-zxd5jrgx.js.map +44 -0
  71. package/dist/cli/index.js +78 -42
  72. package/dist/cli/index.js.map +7 -6
  73. package/dist/types/ai/changelog-components.d.ts +18 -0
  74. package/dist/types/ai/changelog-markdown.d.ts +12 -0
  75. package/dist/types/ai/openapi-components.d.ts +7 -7
  76. package/dist/types/ai/operation-details.d.ts +39 -0
  77. package/dist/types/ai/relative-links.d.ts +3 -1
  78. package/dist/types/ai/serializers.d.ts +6 -4
  79. package/dist/types/analytics/head.d.ts +4 -2
  80. package/dist/types/analytics/script.d.ts +8 -2
  81. package/dist/types/components/content/youtube.d.ts +20 -0
  82. package/dist/types/components/layout/nav-utils.d.ts +8 -0
  83. package/dist/types/components/openapi/example-panels.d.ts +33 -0
  84. package/dist/types/components/openapi/helpers.d.ts +53 -11
  85. package/dist/types/components/openapi/snippets.d.ts +7 -1
  86. package/dist/types/core/alert-diagnostics.d.ts +10 -0
  87. package/dist/types/core/builtin-tags.d.ts +16 -0
  88. package/dist/types/core/changelog-list.d.ts +48 -0
  89. package/dist/types/core/closest-match.d.ts +6 -0
  90. package/dist/types/core/code-fence-diagnostics.d.ts +18 -0
  91. package/dist/types/core/code-fences.d.ts +8 -1
  92. package/dist/types/core/config-input.d.ts +38 -6
  93. package/dist/types/core/content-assets.d.ts +16 -18
  94. package/dist/types/core/data.d.ts +6 -2
  95. package/dist/types/core/diagnostics.d.ts +14 -0
  96. package/dist/types/core/directive-diagnostics.d.ts +22 -8
  97. package/dist/types/core/former-routes.d.ts +14 -0
  98. package/dist/types/core/github.d.ts +5 -4
  99. package/dist/types/core/heading-markers.d.ts +65 -2
  100. package/dist/types/core/hidden-pages.d.ts +3 -0
  101. package/dist/types/core/includes.d.ts +23 -0
  102. package/dist/types/core/last-modified.d.ts +18 -6
  103. package/dist/types/core/links.d.ts +42 -2
  104. package/dist/types/core/load-module.d.ts +19 -4
  105. package/dist/types/core/manifest.d.ts +14 -1
  106. package/dist/types/core/markdown-mirrors.d.ts +22 -0
  107. package/dist/types/core/mcp-clients.d.ts +47 -0
  108. package/dist/types/core/mdx-elements.d.ts +32 -0
  109. package/dist/types/core/mdx-syntax.d.ts +100 -0
  110. package/dist/types/core/meta-diagnostics.d.ts +7 -0
  111. package/dist/types/core/meta.d.ts +32 -5
  112. package/dist/types/core/nav-diagnostics.d.ts +16 -2
  113. package/dist/types/core/navigation.d.ts +13 -0
  114. package/dist/types/core/ordering-prefix.d.ts +6 -0
  115. package/dist/types/core/pinned-ids.d.ts +23 -0
  116. package/dist/types/core/project-graph.d.ts +9 -1
  117. package/dist/types/core/redirect-patterns.d.ts +18 -0
  118. package/dist/types/core/relative-files.d.ts +31 -0
  119. package/dist/types/core/schema.d.ts +322 -11
  120. package/dist/types/core/sources/normalize.d.ts +101 -9
  121. package/dist/types/core/sources/types.d.ts +16 -0
  122. package/dist/types/core/static-files.d.ts +10 -0
  123. package/dist/types/core/static-host.d.ts +42 -0
  124. package/dist/types/core/svg-images.d.ts +26 -0
  125. package/dist/types/core/syntax-diagnostics.d.ts +14 -0
  126. package/dist/types/core/types.d.ts +42 -1
  127. package/dist/types/deploy/generated-files.d.ts +41 -0
  128. package/dist/types/deploy/redirects.d.ts +21 -7
  129. package/dist/types/markdown/code-title.d.ts +9 -5
  130. package/dist/types/markdown/directives.d.ts +8 -0
  131. package/dist/types/markdown/fence-language.d.ts +51 -0
  132. package/dist/types/markdown/fence-meta.d.ts +5 -0
  133. package/dist/types/markdown/github-alerts.d.ts +35 -0
  134. package/dist/types/openapi/asyncapi.d.ts +6 -5
  135. package/dist/types/openapi/checks.d.ts +10 -5
  136. package/dist/types/openapi/model.d.ts +55 -8
  137. package/dist/types/openapi/parse.d.ts +4 -1
  138. package/dist/types/ratelimit/index.d.ts +2 -0
  139. package/dist/types/ratelimit/memory.d.ts +1 -1
  140. package/dist/types/ratelimit/schema.d.ts +40 -0
  141. package/dist/types/ratelimit/unkey.d.ts +48 -0
  142. package/dist/types/sources/filesystem.d.ts +14 -4
  143. package/dist/types/sources/mdx-remote.d.ts +6 -3
  144. package/dist/types/sources/registry.d.ts +3 -3
  145. package/dist/types/theme/color.d.ts +33 -0
  146. package/dist/types/theme/palette.d.ts +122 -0
  147. package/docs/01-quickstart.mdx +1 -1
  148. package/docs/02-deployment.mdx +24 -8
  149. package/docs/04-migrating.mdx +16 -4
  150. package/docs/advanced/changelog.mdx +27 -1
  151. package/docs/advanced/skills.mdx +1 -1
  152. package/docs/cli/audit.mdx +1 -1
  153. package/docs/cli/doctor.mdx +2 -2
  154. package/docs/cli/evals.mdx +1 -1
  155. package/docs/cli/index.mdx +4 -2
  156. package/docs/cli/validate.mdx +10 -7
  157. package/docs/configuration/analytics.mdx +2 -0
  158. package/docs/configuration/customization.mdx +3 -1
  159. package/docs/configuration/index.mdx +7 -6
  160. package/docs/configuration/rate-limiting.mdx +20 -1
  161. package/docs/configuration/theming.mdx +5 -1
  162. package/docs/content/components.mdx +26 -6
  163. package/docs/content/frontmatter.mdx +1 -1
  164. package/docs/content/i18n.mdx +1 -1
  165. package/docs/content/includes.mdx +6 -2
  166. package/docs/content/index.mdx +11 -1
  167. package/docs/content/islands.mdx +2 -0
  168. package/docs/content/meta.mdx +9 -3
  169. package/docs/content/navigation.mdx +14 -6
  170. package/docs/content/sources/obsidian.mdx +1 -1
  171. package/docs/content/sources/remote-mdx.mdx +3 -1
  172. package/docs/content/syntax.mdx +76 -8
  173. package/docs/content/variables.mdx +3 -1
  174. package/docs/discoverability/agent-discovery.mdx +1 -1
  175. package/docs/discoverability/json-api.mdx +1 -1
  176. package/docs/discoverability/llms-txt.mdx +1 -1
  177. package/docs/discoverability/markdown.mdx +2 -2
  178. package/docs/discoverability/mcp.mdx +40 -8
  179. package/docs/discoverability/open-graph.mdx +1 -1
  180. package/docs/discoverability/sitemap-and-robots.mdx +1 -1
  181. package/docs/references/graphql.mdx +2 -0
  182. package/docs/references/openapi.mdx +45 -7
  183. package/package.json +4 -4
  184. package/skills/blume/SKILL.md +2 -2
  185. package/skills/blume-migrate/SKILL.md +51 -29
  186. package/skills/blume-migrate/references/docsify.md +262 -0
  187. package/skills/blume-migrate/references/docus.md +298 -0
  188. package/skills/blume-migrate/references/docusaurus.md +5 -5
  189. package/skills/blume-migrate/references/fern.md +327 -0
  190. package/skills/blume-migrate/references/fumadocs.md +1 -1
  191. package/skills/blume-migrate/references/gitbook.md +267 -0
  192. package/skills/blume-migrate/references/github-wiki.md +259 -0
  193. package/skills/blume-migrate/references/jekyll.md +253 -0
  194. package/skills/blume-migrate/references/mdbook.md +256 -0
  195. package/skills/blume-migrate/references/mintlify.md +5 -5
  196. package/skills/blume-migrate/references/mkdocs.md +236 -0
  197. package/skills/blume-migrate/references/monorepo.md +20 -8
  198. package/skills/blume-migrate/references/nextra.md +5 -5
  199. package/skills/blume-migrate/references/readme.md +257 -0
  200. package/skills/blume-migrate/references/redocly.md +198 -0
  201. package/skills/blume-migrate/references/starlight.md +3 -3
  202. package/skills/blume-migrate/references/vitepress.md +204 -0
  203. package/skills/blume-migrate/references/vuepress.md +271 -0
  204. package/skills/blume-migrate/scripts/docsify-codemod.mjs +2387 -0
  205. package/skills/blume-migrate/scripts/docus-codemod.mjs +2542 -0
  206. package/skills/blume-migrate/scripts/fern-codemod.mjs +2633 -0
  207. package/skills/blume-migrate/scripts/github-wiki-codemod.mjs +2808 -0
  208. package/skills/blume-migrate/scripts/include-excerpts.mjs +649 -0
  209. package/skills/blume-migrate/scripts/jekyll-codemod.mjs +3649 -0
  210. package/skills/blume-migrate/scripts/mintlify-codemod.mjs +17 -13
  211. package/skills/blume-migrate/scripts/mkdocs-codemod.mjs +2526 -0
  212. package/skills/blume-migrate/scripts/operation-routes.mjs +508 -0
  213. package/skills/blume-migrate/scripts/pin-heading-ids.mjs +1049 -0
  214. package/skills/blume-migrate/scripts/readme-codemod.mjs +4139 -0
  215. package/skills/blume-migrate/scripts/vitepress-codemod.mjs +1511 -0
  216. package/src/ai/changelog-components.ts +24 -0
  217. package/src/ai/changelog-markdown.ts +45 -41
  218. package/src/ai/component-markdown.ts +22 -9
  219. package/src/ai/llms.ts +36 -5
  220. package/src/ai/markdown.ts +2 -2
  221. package/src/ai/openapi-components.ts +25 -9
  222. package/src/ai/operation-details.ts +208 -0
  223. package/src/ai/relative-links.ts +48 -8
  224. package/src/ai/serializers.ts +7 -6
  225. package/src/ai/site-skill.ts +6 -2
  226. package/src/analytics/head.ts +11 -5
  227. package/src/analytics/script.ts +13 -3
  228. package/src/astro/generate.ts +47 -11
  229. package/src/astro/index.ts +1 -0
  230. package/src/astro/integration.ts +27 -1
  231. package/src/astro/mdx-source-errors.ts +46 -0
  232. package/src/astro/templates.ts +93 -189
  233. package/src/audit/checks/redirects.ts +5 -1
  234. package/src/audit/redirects.ts +36 -19
  235. package/src/audit/report.ts +22 -9
  236. package/src/audit/run.ts +12 -28
  237. package/src/audit/terms.ts +23 -0
  238. package/src/audit/url.ts +2 -2
  239. package/src/cli/build-failure.ts +256 -7
  240. package/src/cli/command-meta.ts +1 -1
  241. package/src/cli/commands/audit.ts +1 -1
  242. package/src/cli/commands/build.ts +12 -3
  243. package/src/cli/commands/check.ts +13 -2
  244. package/src/cli/commands/dev.ts +1 -1
  245. package/src/cli/commands/doctor.ts +4 -2
  246. package/src/cli/commands/init.ts +3 -3
  247. package/src/cli/commands/preview.ts +17 -1
  248. package/src/cli/commands/validate.ts +22 -10
  249. package/src/cli/prepare.ts +1 -1
  250. package/src/cli/preview-pages.ts +161 -0
  251. package/src/cli/required-secrets.ts +0 -1
  252. package/src/cli/unknown-flags.ts +1 -42
  253. package/src/components/code-copy.ts +51 -0
  254. package/src/components/code-language.ts +75 -0
  255. package/src/components/content/AccordionItem.astro +16 -1
  256. package/src/components/content/Callout.astro +11 -1
  257. package/src/components/content/Changelog.astro +189 -0
  258. package/src/components/content/CodeBlock.astro +8 -11
  259. package/src/components/content/Tabs.astro +16 -2
  260. package/src/components/content/YouTube.astro +6 -4
  261. package/src/components/content/code-block.ts +33 -0
  262. package/src/components/content/content-strings.ts +5 -1
  263. package/src/components/content/inline-markdown.ts +35 -8
  264. package/src/components/content/youtube.ts +49 -7
  265. package/src/components/layout/Analytics.astro +5 -1
  266. package/src/components/layout/NavTree.astro +8 -3
  267. package/src/components/layout/PageActions.astro +81 -23
  268. package/src/components/layout/RootLayout.astro +35 -32
  269. package/src/components/layout/SiteFooter.astro +31 -8
  270. package/src/components/layout/nav-utils.ts +14 -0
  271. package/src/components/layout/search/pagefind.ts +2 -1
  272. package/src/components/openapi/Operation.astro +4 -0
  273. package/src/components/openapi/PanelTabs.astro +9 -3
  274. package/src/components/openapi/RequestBody.astro +42 -8
  275. package/src/components/openapi/RequestPanel.astro +34 -53
  276. package/src/components/openapi/example-panels.ts +110 -0
  277. package/src/components/openapi/helpers.ts +195 -20
  278. package/src/components/openapi/operation-model.ts +63 -26
  279. package/src/components/openapi/request.ts +13 -0
  280. package/src/components/openapi/snippets.ts +14 -2
  281. package/src/core/alert-diagnostics.ts +89 -0
  282. package/src/core/builtin-tags.ts +76 -0
  283. package/src/core/changelog-list.ts +87 -0
  284. package/src/core/closest-match.ts +41 -0
  285. package/src/core/code-fence-diagnostics.ts +267 -0
  286. package/src/core/code-fences.ts +43 -7
  287. package/src/core/component-diagnostics.ts +65 -12
  288. package/src/core/config-input.ts +39 -5
  289. package/src/core/config.ts +46 -1
  290. package/src/core/content-assets.ts +64 -144
  291. package/src/core/data.ts +10 -3
  292. package/src/core/diagnostics.ts +36 -3
  293. package/src/core/directive-diagnostics.ts +265 -47
  294. package/src/core/former-routes.ts +46 -0
  295. package/src/core/git-ignored.ts +53 -0
  296. package/src/core/github.ts +5 -4
  297. package/src/core/heading-markers.ts +156 -2
  298. package/src/core/hidden-pages.ts +64 -0
  299. package/src/core/includes.ts +181 -41
  300. package/src/core/last-modified.ts +47 -10
  301. package/src/core/links.ts +438 -83
  302. package/src/core/load-module.ts +98 -9
  303. package/src/core/manifest.ts +12 -9
  304. package/src/core/markdown-mirrors.ts +52 -0
  305. package/src/core/mcp-clients.ts +87 -0
  306. package/src/core/mdx-elements.ts +153 -0
  307. package/src/core/mdx-syntax.ts +377 -0
  308. package/src/core/meta-diagnostics.ts +134 -0
  309. package/src/core/meta.ts +154 -55
  310. package/src/core/nav-diagnostics.ts +41 -4
  311. package/src/core/navigation.ts +70 -10
  312. package/src/core/ordering-prefix.ts +22 -2
  313. package/src/core/pinned-ids.ts +141 -0
  314. package/src/core/project-graph.ts +221 -29
  315. package/src/core/redirect-patterns.ts +41 -0
  316. package/src/core/relative-files.ts +145 -0
  317. package/src/core/schema.ts +110 -6
  318. package/src/core/sources/mdx-remote.ts +75 -14
  319. package/src/core/sources/normalize.ts +885 -179
  320. package/src/core/sources/notion.ts +5 -4
  321. package/src/core/sources/obsidian.ts +2 -5
  322. package/src/core/sources/types.ts +17 -0
  323. package/src/core/static-files.ts +40 -0
  324. package/src/core/static-host.ts +125 -0
  325. package/src/core/svg-images.ts +98 -0
  326. package/src/core/syntax-diagnostics.ts +491 -0
  327. package/src/core/types.ts +43 -1
  328. package/src/deploy/artifacts.ts +2 -28
  329. package/src/deploy/generated-files.ts +128 -0
  330. package/src/deploy/platforms/vercel.ts +25 -1
  331. package/src/deploy/redirects.ts +43 -16
  332. package/src/deploy/sitemap.ts +2 -1
  333. package/src/markdown/base-links.ts +87 -6
  334. package/src/markdown/code-title.ts +29 -13
  335. package/src/markdown/content-assets.ts +210 -0
  336. package/src/markdown/directives.ts +69 -5
  337. package/src/markdown/fence-language.ts +106 -0
  338. package/src/markdown/fence-meta.ts +42 -0
  339. package/src/markdown/github-alerts.ts +172 -0
  340. package/src/markdown/heading-anchors.ts +265 -56
  341. package/src/markdown/include.ts +30 -3
  342. package/src/markdown/index.ts +145 -40
  343. package/src/markdown/prompt-text.ts +95 -0
  344. package/src/markdown/relative-links.ts +37 -2
  345. package/src/markdown/route-snapshot.ts +22 -12
  346. package/src/markdown/svg-fallback.ts +51 -0
  347. package/src/markdown/title-heading.ts +134 -0
  348. package/src/migrate/migrate.ts +127 -2
  349. package/src/og/card.ts +14 -4
  350. package/src/openapi/asyncapi.ts +14 -6
  351. package/src/openapi/checks.ts +160 -15
  352. package/src/openapi/model.ts +172 -33
  353. package/src/openapi/parse.ts +13 -4
  354. package/src/openapi/render-mdx.ts +55 -9
  355. package/src/openapi/source.ts +87 -6
  356. package/src/ratelimit/index.ts +2 -0
  357. package/src/ratelimit/memory.ts +1 -1
  358. package/src/ratelimit/runtime.ts +81 -0
  359. package/src/ratelimit/schema.ts +2 -0
  360. package/src/ratelimit/unkey.ts +61 -0
  361. package/src/registry/eject.ts +0 -1
  362. package/src/registry/registry.ts +1 -1
  363. package/src/search/documents.ts +10 -2
  364. package/src/sources/filesystem.ts +28 -3
  365. package/src/sources/mdx-remote.ts +7 -15
  366. package/src/theme/color.ts +14 -0
  367. package/src/theme/entry.ts +22 -1
  368. package/src/theme/palette.ts +74 -1
  369. package/dist/cli/chunk-0pmb4tr4.js.map +0 -35
  370. package/dist/cli/chunk-0w6hs479.js.map +0 -10
  371. package/dist/cli/chunk-150jk7km.js +0 -52
  372. package/dist/cli/chunk-150jk7km.js.map +0 -10
  373. package/dist/cli/chunk-36bxs9c7.js.map +0 -10
  374. package/dist/cli/chunk-53jqw8z0.js +0 -89
  375. package/dist/cli/chunk-53jqw8z0.js.map +0 -10
  376. package/dist/cli/chunk-60hz265r.js.map +0 -10
  377. package/dist/cli/chunk-desvm72z.js.map +0 -14
  378. package/dist/cli/chunk-dpy8qdjf.js.map +0 -17
  379. package/dist/cli/chunk-es8h0v3j.js +0 -441
  380. package/dist/cli/chunk-es8h0v3j.js.map +0 -11
  381. package/dist/cli/chunk-kdpzw38a.js.map +0 -11
  382. package/dist/cli/chunk-nbyvgnnm.js.map +0 -36
  383. package/dist/cli/chunk-s0bdnc7v.js.map +0 -10
  384. package/dist/cli/chunk-twy7psdz.js.map +0 -10
  385. package/dist/cli/chunk-ydp3065p.js +0 -64
  386. package/dist/cli/chunk-ydp3065p.js.map +0 -10
  387. /package/dist/cli/{chunk-y4msrwm9.js.map → chunk-080mfch6.js.map} +0 -0
  388. /package/dist/cli/{chunk-9qzgg6mj.js.map → chunk-34wap3ed.js.map} +0 -0
  389. /package/dist/cli/{chunk-1f882900.js.map → chunk-c5bjxq8v.js.map} +0 -0
  390. /package/dist/cli/{chunk-bxwhtvw8.js.map → chunk-f260jdrn.js.map} +0 -0
  391. /package/dist/cli/{chunk-74wfhv79.js.map → chunk-fnxgtjeq.js.map} +0 -0
  392. /package/dist/cli/{chunk-dhwtqnnd.js.map → chunk-gxhcf2hs.js.map} +0 -0
  393. /package/dist/cli/{chunk-tfycddbt.js.map → chunk-h0qwdbem.js.map} +0 -0
  394. /package/dist/cli/{chunk-j1x92mx9.js.map → chunk-j4nfgn2j.js.map} +0 -0
  395. /package/dist/cli/{chunk-ave1wcbr.js.map → chunk-qcyxkj44.js.map} +0 -0
  396. /package/dist/cli/{chunk-58bt3hag.js.map → chunk-x7bh6d9j.js.map} +0 -0
  397. /package/dist/cli/{chunk-hvcxng5f.js.map → chunk-ydqzkhjn.js.map} +0 -0
@@ -5,8 +5,12 @@
5
5
  * - parses trailing markers (`[#custom-id]`, `{#custom-id}`, `[!toc]`, `[toc]`
6
6
  * — see `core/heading-markers.ts`) and strips them from the rendered text;
7
7
 
8
- * - assigns the anchor `id` (the `[#custom-id]` pin, else a `github-slugger`
9
- * slug of the marker-free text);
8
+ * - takes out an empty `<a>` the heading holds as its own anchor (GitBook's
9
+ * `<a href="#x" id="x"></a>`, a wiki's `<a name="x"></a>`), whose `id` or
10
+ * `name` then pins the heading's id — see {@link readContent};
11
+ * - assigns the anchor `id` (the `[#custom-id]` pin, else that anchor's id,
12
+ * else a `github-slugger` slug of the marker-free text, `<Badge>` text left
13
+ * out — see `headingSlug`);
10
14
  * - wraps `<h2>`–`<h6>` content in an `<a href="#slug">` so a reader can click
11
15
  * the heading to copy, bookmark, or share a link straight to that section
12
16
  * (`<h1>` — the page title — is slugged for parity but left unwrapped, and
@@ -28,23 +32,33 @@
28
32
  * surfaces as `remarkPluginFrontmatter` so the page template can filter them
29
33
  * out of the headings list. `[toc]` headings render with the
30
34
  * `blume-toc-only` class (visually hidden, still a live anchor target) so the
31
- * TOC entry has somewhere to scroll to.
35
+ * TOC entry has somewhere to scroll to. `heading-ids` reads a heading's TOC
36
+ * text from its whole text content, badge included, so a heading holding a
37
+ * `<Badge>` reports its badge-free text under `frontmatter[TOC_TEXT_KEY]`.
32
38
  */
33
39
 
34
40
  import { satteriCollectHastText } from "@astrojs/markdown-satteri";
35
41
  import GithubSlugger from "github-slugger";
36
42
 
37
43
  import {
44
+ headingSlug,
45
+ joinHeadingText,
46
+ jsxAnchorTarget,
38
47
  occupySlug,
39
48
  parseHeadingMarkers,
49
+ rawHeadingTag,
40
50
  TOC_HIDDEN_KEY,
51
+ TOC_TEXT_KEY,
41
52
  } from "../core/heading-markers.ts";
53
+ import type { JsxAttribute } from "../core/heading-markers.ts";
42
54
 
43
55
  /** A hast property value: an attribute primitive or a token list. */
44
56
  type HastPropertyValue = string | number | boolean | (string | number)[];
45
57
 
46
58
  /** A minimal hast node (avoids a hast type dependency). */
47
59
  interface HastNode {
60
+ /** An MDX JSX element's attributes. */
61
+ attributes?: JsxAttribute[];
48
62
  children?: HastNode[];
49
63
  name?: string;
50
64
  properties?: Record<string, HastPropertyValue>;
@@ -83,15 +97,18 @@ const WRAPPED = new Set(["h2", "h3", "h4", "h5", "h6"]);
83
97
  /** The class that renders a `[toc]`-only heading as an invisible anchor. */
84
98
  const TOC_ONLY_CLASS = "blume-toc-only";
85
99
 
86
- /** True if the subtree already contains an `<a>`, so wrapping would nest links. */
87
- const containsAnchor = (node: HastNode): boolean => {
88
- for (const child of node.children ?? []) {
89
- if ((child.tagName ?? child.name) === "a" || containsAnchor(child)) {
90
- return true;
91
- }
92
- }
93
- return false;
94
- };
100
+ /**
101
+ * True for an `<a>`: an element, a JSX element, or (in `.md`, where inline
102
+ * HTML stays raw) a raw opening `<a>` tag.
103
+ */
104
+ const isAnchor = (node: HastNode): boolean =>
105
+ (node.tagName ?? node.name) === "a" ||
106
+ (node.type === "raw" &&
107
+ rawHeadingTag(node.value ?? "").kind === "anchor-open");
108
+
109
+ /** True if the nodes already contain an `<a>`, so wrapping would nest links. */
110
+ const containsAnchor = (nodes: readonly HastNode[]): boolean =>
111
+ nodes.some((node) => isAnchor(node) || containsAnchor(node.children ?? []));
95
112
 
96
113
  // One state record per document render. The plugin instance is shared across
97
114
  // every page, but slug disambiguation (and the hidden-heading list) must reset
@@ -102,6 +119,11 @@ interface RenderState {
102
119
  /** Slugs of `[!toc]` headings, shared by reference with the frontmatter. */
103
120
  hidden: string[];
104
121
  slugger: GithubSlugger;
122
+ /**
123
+ * TOC text by slug for badge-holding headings, shared by reference with the
124
+ * frontmatter once the first one is recorded.
125
+ */
126
+ tocText?: Record<string, string>;
105
127
  }
106
128
 
107
129
  const FALLBACK_SCOPE = {};
@@ -122,10 +144,30 @@ const stateFor = (ctx: HastContext): RenderState => {
122
144
  const frontmatter = ctx.data?.astro?.frontmatter;
123
145
  if (frontmatter) {
124
146
  frontmatter[TOC_HIDDEN_KEY] = state.hidden;
147
+ // The TOC text map is added only by a page with a badge in a heading, so
148
+ // a stale one is dropped rather than replaced.
149
+ Reflect.deleteProperty(frontmatter, TOC_TEXT_KEY);
125
150
  }
126
151
  return state;
127
152
  };
128
153
 
154
+ /** Record a badge-holding heading's TOC text (see {@link TOC_TEXT_KEY}). */
155
+ const recordTocText = (
156
+ state: RenderState,
157
+ ctx: HastContext,
158
+ slug: string,
159
+ text: string
160
+ ): void => {
161
+ if (!state.tocText) {
162
+ state.tocText = {};
163
+ const frontmatter = ctx.data?.astro?.frontmatter;
164
+ if (frontmatter) {
165
+ frontmatter[TOC_TEXT_KEY] = state.tocText;
166
+ }
167
+ }
168
+ state.tocText[slug] = text;
169
+ };
170
+
129
171
  /** Whether a heading already carries a usable string `id`. */
130
172
  const isStringId = (value: HastPropertyValue | undefined): value is string =>
131
173
  typeof value === "string";
@@ -176,23 +218,147 @@ const stripMarkers = (node: HastNode): StrippedHeading => {
176
218
  };
177
219
  };
178
220
 
179
- /** The slug for a heading, mirroring Satteri's `heading-ids` exactly. */
180
- const slugFor = (
221
+ /** A heading's content read for its anchor, past its trailing markers. */
222
+ interface HeadingContent {
223
+ /** The children the heading renders: its own empty anchors taken out. */
224
+ children: HastNode[];
225
+ /** The `id` (else `name`) of an anchor taken out: the heading's id. */
226
+ target?: string;
227
+ /** The heading's text with its badges left out, when it holds one. */
228
+ text?: string;
229
+ }
230
+
231
+ /** An empty JSX `<a>` (an `.mdx` heading's own anchor). */
232
+ const isEmptyJsxAnchor = (node: HastNode): boolean =>
233
+ node.type === "mdxJsxTextElement" &&
234
+ node.name === "a" &&
235
+ (node.children ?? []).length === 0;
236
+
237
+ /** True for a raw `</a>`. */
238
+ const isRawAnchorClose = (node: HastNode | undefined): boolean =>
239
+ node?.type === "raw" &&
240
+ rawHeadingTag(node.value ?? "").kind === "anchor-close";
241
+
242
+ /** A heading child's text content; raw HTML has none. */
243
+ const textPiece = (node: HastNode, ctx: HastContext): string => {
244
+ if (node.type === "text") {
245
+ return node.value ?? "";
246
+ }
247
+ return node.type === "raw" ? "" : ctx.textContent(node);
248
+ };
249
+
250
+ /** An empty anchor in a heading: how many nodes it spans, and its target. */
251
+ interface OwnAnchor {
252
+ span: number;
253
+ target?: string;
254
+ }
255
+
256
+ /**
257
+ * The empty `<a>` that starts at `children[index]`, if one does: a JSX
258
+ * element with no children, a self-closing raw tag, or a raw tag closed by
259
+ * the next node.
260
+ */
261
+ const ownAnchorAt = (
262
+ children: readonly HastNode[],
263
+ index: number
264
+ ): OwnAnchor | undefined => {
265
+ const child = children[index];
266
+ if (child && isEmptyJsxAnchor(child)) {
267
+ return { span: 1, target: jsxAnchorTarget(child.attributes ?? []) };
268
+ }
269
+ const tag =
270
+ child?.type === "raw" ? rawHeadingTag(child.value ?? "") : undefined;
271
+ if (tag?.kind !== "anchor-open") {
272
+ return undefined;
273
+ }
274
+ if (tag.selfClosing) {
275
+ return { span: 1, target: tag.target };
276
+ }
277
+ return isRawAnchorClose(children[index + 1])
278
+ ? { span: 2, target: tag.target }
279
+ : undefined;
280
+ };
281
+
282
+ /**
283
+ * How a heading child moves through a badge: undefined for no badge, else
284
+ * the change it makes to the depth of raw `<Badge>` tags its text sits in
285
+ * (a JSX badge holds its text, so it changes nothing).
286
+ */
287
+ const badgeStep = (child: HastNode): number | undefined => {
288
+ if (child.type === "mdxJsxTextElement" && child.name === "Badge") {
289
+ return 0;
290
+ }
291
+ const tag =
292
+ child.type === "raw" ? rawHeadingTag(child.value ?? "") : undefined;
293
+ if (tag?.kind !== "badge") {
294
+ return undefined;
295
+ }
296
+ if (tag.selfClosing) {
297
+ return 0;
298
+ }
299
+ return tag.closing ? -1 : 1;
300
+ };
301
+
302
+ /**
303
+ * Read a heading's children for its anchor:
304
+ *
305
+ * - An empty `<a>` is the heading's own anchor — an export's
306
+ * `<a href="#x" id="x"></a>`, a wiki's `<a name="x"></a>` — kept beside
307
+ * the heading's text so links to `#x` land there. Left in, it would nest
308
+ * inside the self-link (invalid HTML), or stop the self-link from
309
+ * rendering. It comes out, and its `id` (else `name`) becomes the
310
+ * heading's id, so `#x` keeps working. A heading with no other content
311
+ * keeps it.
312
+ * - A `<Badge>` is a label beside the heading, not part of its name: its text
313
+ * stays out of the heading's id and TOC entry. In `.mdx` it is a JSX
314
+ * element; in `.md`, raw tags around its text.
315
+ */
316
+ const readContent = (
317
+ children: readonly HastNode[],
318
+ ctx: HastContext
319
+ ): HeadingContent => {
320
+ const kept: HastNode[] = [];
321
+ const pieces: (string | null)[] = [];
322
+ let target: string | undefined;
323
+ let badges = false;
324
+ let badgeDepth = 0;
325
+ // Nodes still to skip: the `</a>` of a raw anchor taken out.
326
+ let skip = 0;
327
+ for (const [index, child] of children.entries()) {
328
+ const anchor = skip > 0 ? undefined : ownAnchorAt(children, index);
329
+ if (skip > 0 || anchor) {
330
+ target ??= anchor?.target;
331
+ skip = anchor ? anchor.span - 1 : skip - 1;
332
+ continue;
333
+ }
334
+ kept.push(child);
335
+ const step = badgeStep(child);
336
+ if (step === undefined) {
337
+ if (badgeDepth === 0) {
338
+ pieces.push(textPiece(child, ctx));
339
+ }
340
+ } else {
341
+ badges = true;
342
+ pieces.push(null);
343
+ badgeDepth = Math.max(0, badgeDepth + step);
344
+ }
345
+ }
346
+ if (kept.length === 0) {
347
+ return { children: [...children] };
348
+ }
349
+ return {
350
+ children: kept,
351
+ target,
352
+ text: badges ? joinHeadingText(pieces) : undefined,
353
+ };
354
+ };
355
+
356
+ /** The heading's marker-free text content, as `heading-ids` reads it. */
357
+ const headingText = (
181
358
  node: HastNode,
182
359
  ctx: HastContext,
183
- slugger: GithubSlugger,
184
360
  stripped: StrippedHeading
185
361
  ): string => {
186
- if (stripped.id !== undefined) {
187
- // Pinning occupies the id, so a later heading whose auto-slug collides
188
- // disambiguates (`setup` → `setup-1`) instead of duplicating the anchor.
189
- occupySlug(slugger, stripped.id);
190
- return stripped.id;
191
- }
192
- const existingId = node.properties?.id;
193
- if (isStringId(existingId)) {
194
- return existingId;
195
- }
196
362
  // The marker suffix is a trailing slice of the text content, so the
197
363
  // marker-free text is the content minus exactly what the strip removed.
198
364
  const fullText = ctx.textContent(node);
@@ -203,7 +369,7 @@ const slugFor = (
203
369
  // resolved value; the helper is the same one `heading-ids` defers to.
204
370
  // SAFETY: HastNode is a structural subset of the hast element shape the
205
371
  // helper walks (children/type/value), so the node always fits.
206
- const text = rawText.includes("frontmatter")
372
+ return rawText.includes("frontmatter")
207
373
  ? satteriCollectHastText(
208
374
  {
209
375
  ...node,
@@ -212,7 +378,28 @@ const slugFor = (
212
378
  ctx.data?.astro?.frontmatter ?? {}
213
379
  )
214
380
  : rawText;
215
- return slugger.slug(text);
381
+ };
382
+
383
+ /** The slug for a heading, mirroring Satteri's `heading-ids` exactly. */
384
+ const slugFor = (
385
+ node: HastNode,
386
+ ctx: HastContext,
387
+ slugger: GithubSlugger,
388
+ stripped: StrippedHeading,
389
+ content: HeadingContent
390
+ ): string => {
391
+ const pinned = stripped.id ?? content.target;
392
+ if (pinned !== undefined) {
393
+ // Pinning occupies the id, so a later heading whose auto-slug collides
394
+ // disambiguates (`setup` → `setup-1`) instead of duplicating the anchor.
395
+ occupySlug(slugger, pinned);
396
+ return pinned;
397
+ }
398
+ const existingId = node.properties?.id;
399
+ if (isStringId(existingId)) {
400
+ return existingId;
401
+ }
402
+ return headingSlug(slugger, content.text ?? headingText(node, ctx, stripped));
216
403
  };
217
404
 
218
405
  /** The heading's class list with `blume-toc-only` appended. */
@@ -235,6 +422,47 @@ const hasTocOnlyClass = (node: HastNode): boolean => {
235
422
  : value === TOC_ONLY_CLASS;
236
423
  };
237
424
 
425
+ /**
426
+ * A heading left without its self-link. Marker-free headings mutate in place;
427
+ * a stripped one, one that lost its own anchor, or a `[toc]`-only one needs
428
+ * its children (and class) replaced, so it re-emits as a new element carrying
429
+ * the original children as refs.
430
+ */
431
+ const unwrappedHeading = (
432
+ node: HastNode,
433
+ ctx: HastContext,
434
+ slug: string,
435
+ stripped: StrippedHeading,
436
+ content: HeadingContent
437
+ ): HastNode | undefined => {
438
+ const tocOnly = stripped.toc === "only" || hasTocOnlyClass(node);
439
+ if (
440
+ stripped.strippedLength ||
441
+ content.children.length !== stripped.children.length ||
442
+ (tocOnly && !hasTocOnlyClass(node))
443
+ ) {
444
+ const properties = tocOnly
445
+ ? {
446
+ ...node.properties,
447
+ className: withTocOnlyClass(node.properties?.className),
448
+ id: slug,
449
+ }
450
+ : { ...node.properties, id: slug };
451
+ return {
452
+ children: content.children,
453
+ properties,
454
+ tagName: node.tagName,
455
+ type: "element",
456
+ };
457
+ }
458
+ // Unwrapped headings (h1, an empty slug, or one that already links) still
459
+ // need the id so `heading-ids` adopts it instead of re-slugging.
460
+ if (!isStringId(node.properties?.id)) {
461
+ ctx.setProperty(node, "id", slug);
462
+ }
463
+ return undefined;
464
+ };
465
+
238
466
  /**
239
467
  * Build the plugin. Always parses markers and assigns ids; `wrap: false` only
240
468
  * disables the self-linking anchor wrap on `<h2>`–`<h6>`.
@@ -247,50 +475,31 @@ export const headingAnchorPlugin = (
247
475
  visit(node, ctx) {
248
476
  const state = stateFor(ctx);
249
477
  const stripped = stripMarkers(node);
250
- const slug = slugFor(node, ctx, state.slugger, stripped);
478
+ const content = readContent(stripped.children, ctx);
479
+ const slug = slugFor(node, ctx, state.slugger, stripped, content);
251
480
  if (stripped.toc === "hide") {
252
481
  state.hidden.push(slug);
253
482
  }
254
- const tocOnly = stripped.toc === "only" || hasTocOnlyClass(node);
483
+ if (content.text !== undefined) {
484
+ recordTocText(state, ctx, slug, content.text.trim());
485
+ }
255
486
  const wrap =
256
487
  options.wrap !== false &&
257
488
  node.tagName !== undefined &&
258
489
  WRAPPED.has(node.tagName) &&
259
490
  slug !== "" &&
260
- !tocOnly &&
261
- !containsAnchor(node);
491
+ stripped.toc !== "only" &&
492
+ !hasTocOnlyClass(node) &&
493
+ !containsAnchor(content.children);
262
494
  if (!wrap) {
263
- // Marker-free headings mutate in place; a stripped or `[toc]`-only one
264
- // needs its children (and class) replaced, so it re-emits as a new
265
- // element carrying the original children as refs.
266
- if (stripped.strippedLength || (tocOnly && !hasTocOnlyClass(node))) {
267
- const properties = tocOnly
268
- ? {
269
- ...node.properties,
270
- className: withTocOnlyClass(node.properties?.className),
271
- id: slug,
272
- }
273
- : { ...node.properties, id: slug };
274
- return {
275
- children: stripped.children,
276
- properties,
277
- tagName: node.tagName,
278
- type: "element",
279
- };
280
- }
281
- // Unwrapped headings (h1, an empty slug, or one that already links)
282
- // still need the id so `heading-ids` adopts it instead of re-slugging.
283
- if (!isStringId(node.properties?.id)) {
284
- ctx.setProperty(node, "id", slug);
285
- }
286
- return;
495
+ return unwrappedHeading(node, ctx, slug, stripped, content);
287
496
  }
288
497
  // Replacing the heading re-emits its original children as refs inside the
289
498
  // new anchor (Satteri passes reused nodes through untouched).
290
499
  return {
291
500
  children: [
292
501
  {
293
- children: stripped.children,
502
+ children: content.children,
294
503
  properties: {
295
504
  className: ["blume-heading-anchor"],
296
505
  href: `#${slug}`,
@@ -1,6 +1,7 @@
1
1
  import { fileURLToPath } from "node:url";
2
2
 
3
3
  import { resolve } from "pathe";
4
+ import type { SourceFormat } from "satteri";
4
5
 
5
6
  import type { IncludeStatement } from "../core/includes.ts";
6
7
  import {
@@ -8,7 +9,11 @@ import {
8
9
  expandIncludeTarget,
9
10
  hasIncludeStatements,
10
11
  matchIncludeStatement,
12
+ withDefinitions,
11
13
  } from "../core/includes.ts";
14
+ import { escapePinnedIds } from "../core/pinned-ids.ts";
15
+ import { linkDefinitions } from "../core/sources/normalize.ts";
16
+ import type { LinkDefinition } from "../core/sources/normalize.ts";
12
17
  import { substituteVariables } from "../core/variables.ts";
13
18
  import type { ContentVariables } from "../core/variables.ts";
14
19
  import type { MdastNode, MdastValue } from "./mdast.ts";
@@ -68,6 +73,7 @@ interface PositionedNode extends MdastNode {
68
73
  interface IncludeVisitorContext {
69
74
  fileURL: URL | undefined;
70
75
  source: string;
76
+ sourceFormat: SourceFormat;
71
77
  replaceNode: (node: MdastNode, replacement: { raw: string }) => void;
72
78
  textContent: (node: MdastNode) => string;
73
79
  report: (report: {
@@ -125,6 +131,17 @@ export const includePlugin = (options: IncludePluginOptions = {}) => {
125
131
  ? resolve(options.contentRoot)
126
132
  : undefined;
127
133
 
134
+ // The page's link-reference definitions, read once per source: its own
135
+ // and, appended before the parse (see `withIncludedDefinitions`), every
136
+ // partial's.
137
+ let cached: { definitions: LinkDefinition[]; source: string } | undefined;
138
+ const pageDefinitions = (source: string): LinkDefinition[] => {
139
+ if (cached?.source !== source) {
140
+ cached = { definitions: linkDefinitions(source), source };
141
+ }
142
+ return cached.definitions;
143
+ };
144
+
128
145
  const splice = async (
129
146
  node: MdastNode,
130
147
  statement: IncludeStatement,
@@ -155,9 +172,19 @@ export const includePlugin = (options: IncludePluginOptions = {}) => {
155
172
  for (const nested of expanded.errors) {
156
173
  ctx.report({ message: nested.message, node, severity: "warning" });
157
174
  }
158
- // Substituted here, before the spliced text is parsed: in an MDX page it
159
- // parses as MDX, where `{{name}}` would be a JavaScript expression.
160
- return substituteVariables(expanded.text, options.variables);
175
+ // The splice parses on its own, so a reference in it to a definition
176
+ // elsewhere in the page (the page's, or another partial's) is resolved
177
+ // through a copy of that definition. Substituted here, before the
178
+ // spliced text is parsed: in an MDX page it parses as MDX, where
179
+ // `{{name}}` would be a JavaScript expression. Its pinned heading ids
180
+ // are escaped the way the page's own are (see `escapePinnedIds`).
181
+ return escapePinnedIds(
182
+ substituteVariables(
183
+ withDefinitions(expanded.text, pageDefinitions(ctx.source)),
184
+ options.variables
185
+ ),
186
+ ctx.sourceFormat
187
+ );
161
188
  };
162
189
 
163
190
  /**