blume 2.1.3 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +126 -0
- package/README.md +4 -4
- package/dist/cli/{chunk-74wfhv79.js → chunk-05f21r8h.js} +1 -1
- package/dist/cli/{chunk-9qzgg6mj.js → chunk-1cm0h819.js} +3 -3
- package/dist/cli/{chunk-nbyvgnnm.js → chunk-1rkxzg3n.js} +104 -47
- package/dist/cli/chunk-1rkxzg3n.js.map +36 -0
- package/dist/cli/{chunk-desvm72z.js → chunk-2nr29y95.js} +22 -26
- package/dist/cli/chunk-2nr29y95.js.map +13 -0
- package/dist/cli/{chunk-32khwcb6.js → chunk-49r370mb.js} +42 -69
- package/dist/cli/{chunk-32khwcb6.js.map → chunk-49r370mb.js.map} +9 -10
- package/dist/cli/{chunk-ms9z66nz.js → chunk-4rftmttv.js} +2 -2
- package/dist/cli/{chunk-s0bdnc7v.js → chunk-79bzzkx4.js} +5 -4
- package/dist/cli/chunk-79bzzkx4.js.map +10 -0
- package/dist/cli/{chunk-hvcxng5f.js → chunk-7tekknev.js} +6 -6
- package/dist/cli/{chunk-dv2z0rzf.js → chunk-8b489v1b.js} +38 -13
- package/dist/cli/{chunk-dv2z0rzf.js.map → chunk-8b489v1b.js.map} +5 -4
- package/dist/cli/{chunk-0pmb4tr4.js → chunk-8f8xw4x2.js} +1195 -222
- package/dist/cli/chunk-8f8xw4x2.js.map +44 -0
- package/dist/cli/chunk-96snx8yy.js +329 -0
- package/dist/cli/chunk-96snx8yy.js.map +13 -0
- package/dist/cli/{chunk-ckrcm08h.js → chunk-a3ydrqny.js} +48 -62
- package/dist/cli/{chunk-ckrcm08h.js.map → chunk-a3ydrqny.js.map} +4 -5
- package/dist/cli/{chunk-bxwhtvw8.js → chunk-ahc5gc9h.js} +5 -5
- package/dist/cli/{chunk-dpy8qdjf.js → chunk-as09pafp.js} +73 -182
- package/dist/cli/chunk-as09pafp.js.map +18 -0
- package/dist/cli/{chunk-tfycddbt.js → chunk-bjk964fp.js} +2 -2
- package/dist/cli/{chunk-gfc5fqvf.js → chunk-br0n8n3e.js} +18 -18
- package/dist/cli/{chunk-gfc5fqvf.js.map → chunk-br0n8n3e.js.map} +1 -1
- package/dist/cli/{chunk-297ajdcv.js → chunk-c69tw29j.js} +6 -6
- package/dist/cli/{chunk-297ajdcv.js.map → chunk-c69tw29j.js.map} +3 -3
- package/dist/cli/chunk-cn3dy3hz.js +146 -0
- package/dist/cli/chunk-cn3dy3hz.js.map +11 -0
- package/dist/cli/{chunk-124fvmzq.js → chunk-dm4mg9bj.js} +11064 -8742
- package/dist/cli/{chunk-124fvmzq.js.map → chunk-dm4mg9bj.js.map} +78 -64
- package/dist/cli/{chunk-dqhg54mr.js → chunk-dmx6cezx.js} +1 -1
- package/dist/cli/{chunk-60hz265r.js → chunk-dpcahcrb.js} +24 -11
- package/dist/cli/chunk-dpcahcrb.js.map +10 -0
- package/dist/cli/{chunk-a57yh0h9.js → chunk-dyk3r7jw.js} +7 -7
- package/dist/cli/{chunk-a57yh0h9.js.map → chunk-dyk3r7jw.js.map} +1 -1
- package/dist/cli/{chunk-twy7psdz.js → chunk-enk76qd5.js} +14 -10
- package/dist/cli/chunk-enk76qd5.js.map +10 -0
- package/dist/cli/{chunk-k3gr1nm9.js → chunk-fqy4n3q2.js} +13 -16
- package/dist/cli/{chunk-k3gr1nm9.js.map → chunk-fqy4n3q2.js.map} +3 -3
- package/dist/cli/{chunk-sc93apfs.js → chunk-frk2wdq1.js} +17 -17
- package/dist/cli/{chunk-sc93apfs.js.map → chunk-frk2wdq1.js.map} +2 -2
- package/dist/cli/{chunk-kdpzw38a.js → chunk-gprwej7h.js} +95 -7
- package/dist/cli/chunk-gprwej7h.js.map +11 -0
- package/dist/cli/chunk-kkrteb15.js +157 -0
- package/dist/cli/chunk-kkrteb15.js.map +10 -0
- package/dist/cli/{chunk-ave1wcbr.js → chunk-m9bp2hc1.js} +1 -1
- package/dist/cli/{chunk-58bt3hag.js → chunk-mrvh4c88.js} +4 -4
- package/dist/cli/{chunk-5cmts6dv.js → chunk-p8zg3a2h.js} +7 -7
- package/dist/cli/{chunk-5cmts6dv.js.map → chunk-p8zg3a2h.js.map} +1 -1
- package/dist/cli/{chunk-0w6hs479.js → chunk-rkqae7kh.js} +30 -18
- package/dist/cli/chunk-rkqae7kh.js.map +10 -0
- package/dist/cli/{chunk-bqxaqn5p.js → chunk-t5xx74rd.js} +8 -8
- package/dist/cli/{chunk-bqxaqn5p.js.map → chunk-t5xx74rd.js.map} +1 -1
- package/dist/cli/{chunk-1f882900.js → chunk-th0pgaj5.js} +2 -2
- package/dist/cli/{chunk-dhwtqnnd.js → chunk-vnbvhgmd.js} +2 -2
- package/dist/cli/{chunk-gxtg6ed2.js → chunk-vzy9rh6y.js} +21 -21
- package/dist/cli/{chunk-gxtg6ed2.js.map → chunk-vzy9rh6y.js.map} +3 -3
- package/dist/cli/{chunk-j1x92mx9.js → chunk-w6e455pz.js} +1 -1
- package/dist/cli/chunk-wehv26ry.js +155 -0
- package/dist/cli/chunk-wehv26ry.js.map +11 -0
- package/dist/cli/{chunk-y4msrwm9.js → chunk-xgq4eytj.js} +15 -15
- package/dist/cli/{chunk-36bxs9c7.js → chunk-xt0qvz1t.js} +27 -23
- package/dist/cli/chunk-xt0qvz1t.js.map +10 -0
- package/dist/cli/index.js +78 -42
- package/dist/cli/index.js.map +7 -6
- package/dist/types/ai/changelog-components.d.ts +18 -0
- package/dist/types/ai/changelog-markdown.d.ts +12 -0
- package/dist/types/ai/openapi-components.d.ts +7 -7
- package/dist/types/ai/operation-details.d.ts +39 -0
- package/dist/types/ai/relative-links.d.ts +3 -1
- package/dist/types/ai/serializers.d.ts +6 -4
- package/dist/types/analytics/head.d.ts +4 -2
- package/dist/types/analytics/script.d.ts +8 -2
- package/dist/types/components/content/youtube.d.ts +20 -0
- package/dist/types/components/layout/nav-utils.d.ts +8 -0
- package/dist/types/components/openapi/example-panels.d.ts +33 -0
- package/dist/types/components/openapi/helpers.d.ts +53 -11
- package/dist/types/components/openapi/snippets.d.ts +7 -1
- package/dist/types/core/alert-diagnostics.d.ts +10 -0
- package/dist/types/core/builtin-tags.d.ts +16 -0
- package/dist/types/core/changelog-list.d.ts +48 -0
- package/dist/types/core/closest-match.d.ts +6 -0
- package/dist/types/core/code-fence-diagnostics.d.ts +18 -0
- package/dist/types/core/code-fences.d.ts +8 -1
- package/dist/types/core/config-input.d.ts +1 -1
- package/dist/types/core/content-assets.d.ts +16 -18
- package/dist/types/core/diagnostics.d.ts +14 -0
- package/dist/types/core/directive-diagnostics.d.ts +22 -8
- package/dist/types/core/former-routes.d.ts +14 -0
- package/dist/types/core/github.d.ts +5 -4
- package/dist/types/core/heading-markers.d.ts +65 -2
- package/dist/types/core/hidden-pages.d.ts +3 -0
- package/dist/types/core/includes.d.ts +23 -0
- package/dist/types/core/last-modified.d.ts +18 -6
- package/dist/types/core/links.d.ts +42 -2
- package/dist/types/core/load-module.d.ts +19 -4
- package/dist/types/core/manifest.d.ts +14 -1
- package/dist/types/core/markdown-mirrors.d.ts +22 -0
- package/dist/types/core/mdx-elements.d.ts +32 -0
- package/dist/types/core/mdx-syntax.d.ts +100 -0
- package/dist/types/core/meta-diagnostics.d.ts +7 -0
- package/dist/types/core/meta.d.ts +32 -5
- package/dist/types/core/nav-diagnostics.d.ts +9 -2
- package/dist/types/core/navigation.d.ts +13 -0
- package/dist/types/core/ordering-prefix.d.ts +6 -0
- package/dist/types/core/pinned-ids.d.ts +23 -0
- package/dist/types/core/project-graph.d.ts +9 -1
- package/dist/types/core/redirect-patterns.d.ts +18 -0
- package/dist/types/core/relative-files.d.ts +31 -0
- package/dist/types/core/schema.d.ts +267 -7
- package/dist/types/core/sources/normalize.d.ts +101 -9
- package/dist/types/core/sources/types.d.ts +16 -0
- package/dist/types/core/static-files.d.ts +10 -0
- package/dist/types/core/static-host.d.ts +42 -0
- package/dist/types/core/svg-images.d.ts +26 -0
- package/dist/types/core/syntax-diagnostics.d.ts +14 -0
- package/dist/types/core/types.d.ts +42 -1
- package/dist/types/deploy/generated-files.d.ts +41 -0
- package/dist/types/deploy/redirects.d.ts +21 -7
- package/dist/types/markdown/code-title.d.ts +9 -5
- package/dist/types/markdown/directives.d.ts +8 -0
- package/dist/types/markdown/fence-language.d.ts +51 -0
- package/dist/types/markdown/fence-meta.d.ts +5 -0
- package/dist/types/markdown/github-alerts.d.ts +35 -0
- package/dist/types/openapi/asyncapi.d.ts +6 -5
- package/dist/types/openapi/checks.d.ts +10 -5
- package/dist/types/openapi/model.d.ts +55 -8
- package/dist/types/openapi/parse.d.ts +4 -1
- package/dist/types/sources/filesystem.d.ts +14 -4
- package/dist/types/sources/mdx-remote.d.ts +6 -3
- package/dist/types/sources/registry.d.ts +3 -3
- package/dist/types/theme/color.d.ts +33 -0
- package/dist/types/theme/palette.d.ts +122 -0
- package/docs/01-quickstart.mdx +1 -1
- package/docs/02-deployment.mdx +23 -8
- package/docs/04-migrating.mdx +16 -4
- package/docs/advanced/changelog.mdx +27 -1
- package/docs/advanced/skills.mdx +1 -1
- package/docs/cli/audit.mdx +1 -1
- package/docs/cli/doctor.mdx +2 -2
- package/docs/cli/evals.mdx +1 -1
- package/docs/cli/index.mdx +4 -2
- package/docs/cli/validate.mdx +10 -7
- package/docs/configuration/analytics.mdx +2 -0
- package/docs/configuration/customization.mdx +3 -1
- package/docs/configuration/index.mdx +2 -2
- package/docs/configuration/theming.mdx +5 -1
- package/docs/content/components.mdx +26 -6
- package/docs/content/frontmatter.mdx +1 -1
- package/docs/content/includes.mdx +6 -2
- package/docs/content/index.mdx +11 -1
- package/docs/content/islands.mdx +2 -0
- package/docs/content/meta.mdx +9 -3
- package/docs/content/navigation.mdx +14 -6
- package/docs/content/sources/obsidian.mdx +1 -1
- package/docs/content/sources/remote-mdx.mdx +3 -1
- package/docs/content/syntax.mdx +76 -8
- package/docs/content/variables.mdx +3 -1
- package/docs/discoverability/agent-discovery.mdx +1 -1
- package/docs/discoverability/json-api.mdx +1 -1
- package/docs/discoverability/llms-txt.mdx +1 -1
- package/docs/discoverability/markdown.mdx +2 -2
- package/docs/discoverability/open-graph.mdx +1 -1
- package/docs/discoverability/sitemap-and-robots.mdx +1 -1
- package/docs/references/graphql.mdx +2 -0
- package/docs/references/openapi.mdx +45 -7
- package/package.json +4 -4
- package/skills/blume/SKILL.md +2 -2
- package/skills/blume-migrate/SKILL.md +49 -27
- package/skills/blume-migrate/references/docsify.md +262 -0
- package/skills/blume-migrate/references/docus.md +298 -0
- package/skills/blume-migrate/references/docusaurus.md +3 -3
- package/skills/blume-migrate/references/fern.md +327 -0
- package/skills/blume-migrate/references/fumadocs.md +1 -1
- package/skills/blume-migrate/references/gitbook.md +267 -0
- package/skills/blume-migrate/references/github-wiki.md +259 -0
- package/skills/blume-migrate/references/jekyll.md +253 -0
- package/skills/blume-migrate/references/mdbook.md +256 -0
- package/skills/blume-migrate/references/mintlify.md +5 -5
- package/skills/blume-migrate/references/mkdocs.md +236 -0
- package/skills/blume-migrate/references/monorepo.md +20 -8
- package/skills/blume-migrate/references/nextra.md +2 -2
- package/skills/blume-migrate/references/readme.md +257 -0
- package/skills/blume-migrate/references/redocly.md +198 -0
- package/skills/blume-migrate/references/starlight.md +3 -3
- package/skills/blume-migrate/references/vitepress.md +204 -0
- package/skills/blume-migrate/references/vuepress.md +271 -0
- package/skills/blume-migrate/scripts/docsify-codemod.mjs +2387 -0
- package/skills/blume-migrate/scripts/docus-codemod.mjs +2542 -0
- package/skills/blume-migrate/scripts/fern-codemod.mjs +2633 -0
- package/skills/blume-migrate/scripts/github-wiki-codemod.mjs +2808 -0
- package/skills/blume-migrate/scripts/include-excerpts.mjs +649 -0
- package/skills/blume-migrate/scripts/jekyll-codemod.mjs +3649 -0
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +17 -13
- package/skills/blume-migrate/scripts/mkdocs-codemod.mjs +2526 -0
- package/skills/blume-migrate/scripts/operation-routes.mjs +508 -0
- package/skills/blume-migrate/scripts/pin-heading-ids.mjs +1049 -0
- package/skills/blume-migrate/scripts/readme-codemod.mjs +4139 -0
- package/skills/blume-migrate/scripts/vitepress-codemod.mjs +1511 -0
- package/src/ai/changelog-components.ts +24 -0
- package/src/ai/changelog-markdown.ts +45 -41
- package/src/ai/component-markdown.ts +22 -9
- package/src/ai/llms.ts +36 -5
- package/src/ai/markdown.ts +2 -2
- package/src/ai/openapi-components.ts +25 -9
- package/src/ai/operation-details.ts +208 -0
- package/src/ai/relative-links.ts +48 -8
- package/src/ai/serializers.ts +7 -6
- package/src/ai/site-skill.ts +6 -2
- package/src/analytics/head.ts +11 -5
- package/src/analytics/script.ts +13 -3
- package/src/astro/generate.ts +32 -6
- package/src/astro/index.ts +1 -0
- package/src/astro/integration.ts +27 -1
- package/src/astro/mdx-source-errors.ts +46 -0
- package/src/astro/templates.ts +89 -185
- package/src/audit/checks/redirects.ts +5 -1
- package/src/audit/redirects.ts +36 -19
- package/src/audit/report.ts +22 -9
- package/src/audit/run.ts +12 -28
- package/src/audit/terms.ts +23 -0
- package/src/audit/url.ts +2 -2
- package/src/cli/build-failure.ts +256 -7
- package/src/cli/command-meta.ts +1 -1
- package/src/cli/commands/audit.ts +1 -1
- package/src/cli/commands/build.ts +12 -3
- package/src/cli/commands/check.ts +13 -2
- package/src/cli/commands/dev.ts +1 -1
- package/src/cli/commands/doctor.ts +4 -2
- package/src/cli/commands/init.ts +3 -3
- package/src/cli/commands/preview.ts +17 -1
- package/src/cli/commands/validate.ts +22 -10
- package/src/cli/prepare.ts +1 -1
- package/src/cli/preview-pages.ts +161 -0
- package/src/cli/unknown-flags.ts +1 -42
- package/src/components/code-copy.ts +51 -0
- package/src/components/code-language.ts +75 -0
- package/src/components/content/AccordionItem.astro +16 -1
- package/src/components/content/Callout.astro +11 -1
- package/src/components/content/Changelog.astro +189 -0
- package/src/components/content/CodeBlock.astro +8 -11
- package/src/components/content/Tabs.astro +16 -2
- package/src/components/content/YouTube.astro +6 -4
- package/src/components/content/code-block.ts +33 -0
- package/src/components/content/content-strings.ts +5 -1
- package/src/components/content/inline-markdown.ts +35 -8
- package/src/components/content/youtube.ts +49 -7
- package/src/components/layout/Analytics.astro +5 -1
- package/src/components/layout/NavTree.astro +8 -3
- package/src/components/layout/RootLayout.astro +18 -31
- package/src/components/layout/nav-utils.ts +14 -0
- package/src/components/layout/search/pagefind.ts +2 -1
- package/src/components/openapi/Operation.astro +4 -0
- package/src/components/openapi/PanelTabs.astro +9 -3
- package/src/components/openapi/RequestBody.astro +42 -8
- package/src/components/openapi/RequestPanel.astro +34 -53
- package/src/components/openapi/example-panels.ts +110 -0
- package/src/components/openapi/helpers.ts +195 -20
- package/src/components/openapi/operation-model.ts +63 -26
- package/src/components/openapi/request.ts +13 -0
- package/src/components/openapi/snippets.ts +14 -2
- package/src/core/alert-diagnostics.ts +89 -0
- package/src/core/builtin-tags.ts +76 -0
- package/src/core/changelog-list.ts +87 -0
- package/src/core/closest-match.ts +41 -0
- package/src/core/code-fence-diagnostics.ts +267 -0
- package/src/core/code-fences.ts +43 -7
- package/src/core/component-diagnostics.ts +65 -12
- package/src/core/config-input.ts +1 -1
- package/src/core/config.ts +46 -1
- package/src/core/content-assets.ts +64 -144
- package/src/core/diagnostics.ts +36 -3
- package/src/core/directive-diagnostics.ts +265 -47
- package/src/core/former-routes.ts +46 -0
- package/src/core/git-ignored.ts +53 -0
- package/src/core/github.ts +5 -4
- package/src/core/heading-markers.ts +156 -2
- package/src/core/hidden-pages.ts +64 -0
- package/src/core/includes.ts +181 -41
- package/src/core/last-modified.ts +47 -10
- package/src/core/links.ts +438 -83
- package/src/core/load-module.ts +98 -9
- package/src/core/manifest.ts +12 -9
- package/src/core/markdown-mirrors.ts +52 -0
- package/src/core/mdx-elements.ts +153 -0
- package/src/core/mdx-syntax.ts +377 -0
- package/src/core/meta-diagnostics.ts +134 -0
- package/src/core/meta.ts +154 -55
- package/src/core/nav-diagnostics.ts +16 -4
- package/src/core/navigation.ts +70 -10
- package/src/core/ordering-prefix.ts +22 -2
- package/src/core/pinned-ids.ts +141 -0
- package/src/core/project-graph.ts +221 -29
- package/src/core/redirect-patterns.ts +41 -0
- package/src/core/relative-files.ts +145 -0
- package/src/core/schema.ts +17 -3
- package/src/core/sources/mdx-remote.ts +75 -14
- package/src/core/sources/normalize.ts +885 -179
- package/src/core/sources/notion.ts +5 -4
- package/src/core/sources/obsidian.ts +2 -5
- package/src/core/sources/types.ts +17 -0
- package/src/core/static-files.ts +40 -0
- package/src/core/static-host.ts +125 -0
- package/src/core/svg-images.ts +98 -0
- package/src/core/syntax-diagnostics.ts +491 -0
- package/src/core/types.ts +43 -1
- package/src/deploy/artifacts.ts +2 -28
- package/src/deploy/generated-files.ts +128 -0
- package/src/deploy/platforms/vercel.ts +25 -1
- package/src/deploy/redirects.ts +43 -16
- package/src/deploy/sitemap.ts +2 -1
- package/src/markdown/base-links.ts +87 -6
- package/src/markdown/code-title.ts +29 -13
- package/src/markdown/content-assets.ts +210 -0
- package/src/markdown/directives.ts +69 -5
- package/src/markdown/fence-language.ts +106 -0
- package/src/markdown/fence-meta.ts +42 -0
- package/src/markdown/github-alerts.ts +172 -0
- package/src/markdown/heading-anchors.ts +265 -56
- package/src/markdown/include.ts +30 -3
- package/src/markdown/index.ts +145 -40
- package/src/markdown/prompt-text.ts +95 -0
- package/src/markdown/relative-links.ts +37 -2
- package/src/markdown/route-snapshot.ts +22 -12
- package/src/markdown/svg-fallback.ts +51 -0
- package/src/markdown/title-heading.ts +134 -0
- package/src/migrate/migrate.ts +127 -2
- package/src/og/card.ts +14 -4
- package/src/openapi/asyncapi.ts +14 -6
- package/src/openapi/checks.ts +160 -15
- package/src/openapi/model.ts +172 -33
- package/src/openapi/parse.ts +13 -4
- package/src/openapi/render-mdx.ts +55 -9
- package/src/openapi/source.ts +87 -6
- package/src/registry/eject.ts +0 -1
- package/src/search/documents.ts +10 -2
- package/src/sources/filesystem.ts +28 -3
- package/src/sources/mdx-remote.ts +7 -15
- package/src/theme/color.ts +14 -0
- package/src/theme/entry.ts +22 -1
- package/src/theme/palette.ts +74 -1
- package/dist/cli/chunk-0pmb4tr4.js.map +0 -35
- package/dist/cli/chunk-0w6hs479.js.map +0 -10
- package/dist/cli/chunk-150jk7km.js +0 -52
- package/dist/cli/chunk-150jk7km.js.map +0 -10
- package/dist/cli/chunk-36bxs9c7.js.map +0 -10
- package/dist/cli/chunk-53jqw8z0.js +0 -89
- package/dist/cli/chunk-53jqw8z0.js.map +0 -10
- package/dist/cli/chunk-60hz265r.js.map +0 -10
- package/dist/cli/chunk-desvm72z.js.map +0 -14
- package/dist/cli/chunk-dpy8qdjf.js.map +0 -17
- package/dist/cli/chunk-es8h0v3j.js +0 -441
- package/dist/cli/chunk-es8h0v3j.js.map +0 -11
- package/dist/cli/chunk-kdpzw38a.js.map +0 -11
- package/dist/cli/chunk-nbyvgnnm.js.map +0 -36
- package/dist/cli/chunk-s0bdnc7v.js.map +0 -10
- package/dist/cli/chunk-twy7psdz.js.map +0 -10
- package/dist/cli/chunk-ydp3065p.js +0 -64
- package/dist/cli/chunk-ydp3065p.js.map +0 -10
- /package/dist/cli/{chunk-74wfhv79.js.map → chunk-05f21r8h.js.map} +0 -0
- /package/dist/cli/{chunk-9qzgg6mj.js.map → chunk-1cm0h819.js.map} +0 -0
- /package/dist/cli/{chunk-ms9z66nz.js.map → chunk-4rftmttv.js.map} +0 -0
- /package/dist/cli/{chunk-hvcxng5f.js.map → chunk-7tekknev.js.map} +0 -0
- /package/dist/cli/{chunk-bxwhtvw8.js.map → chunk-ahc5gc9h.js.map} +0 -0
- /package/dist/cli/{chunk-tfycddbt.js.map → chunk-bjk964fp.js.map} +0 -0
- /package/dist/cli/{chunk-dqhg54mr.js.map → chunk-dmx6cezx.js.map} +0 -0
- /package/dist/cli/{chunk-ave1wcbr.js.map → chunk-m9bp2hc1.js.map} +0 -0
- /package/dist/cli/{chunk-58bt3hag.js.map → chunk-mrvh4c88.js.map} +0 -0
- /package/dist/cli/{chunk-1f882900.js.map → chunk-th0pgaj5.js.map} +0 -0
- /package/dist/cli/{chunk-dhwtqnnd.js.map → chunk-vnbvhgmd.js.map} +0 -0
- /package/dist/cli/{chunk-j1x92mx9.js.map → chunk-w6e455pz.js.map} +0 -0
- /package/dist/cli/{chunk-y4msrwm9.js.map → chunk-xgq4eytj.js.map} +0 -0
package/src/markdown/index.ts
CHANGED
|
@@ -1,22 +1,31 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
|
|
1
3
|
import { satteri } from "@astrojs/markdown-satteri";
|
|
2
4
|
import {
|
|
3
5
|
transformerMetaHighlight,
|
|
4
6
|
transformerNotationDiff,
|
|
7
|
+
transformerNotationErrorLevel,
|
|
5
8
|
transformerNotationFocus,
|
|
6
9
|
transformerNotationHighlight,
|
|
7
10
|
transformerNotationWordHighlight,
|
|
8
11
|
} from "@shikijs/transformers";
|
|
9
12
|
import { escape as escapeHtml } from "html-escaper";
|
|
13
|
+
import { resolve } from "pathe";
|
|
10
14
|
import { codeToHtml } from "shiki";
|
|
11
15
|
|
|
12
|
-
import {
|
|
16
|
+
import { withIncludedDefinitions } from "../core/includes.ts";
|
|
17
|
+
import { escapePinnedIds } from "../core/pinned-ids.ts";
|
|
18
|
+
import { hasVariables, substituteVariables } from "../core/variables.ts";
|
|
13
19
|
import type { ContentVariables } from "../core/variables.ts";
|
|
14
20
|
import { apiRailPlugin } from "./api-rail.ts";
|
|
15
21
|
import { baseLinksPlugin } from "./base-links.ts";
|
|
16
22
|
import { codeTitleTransformer } from "./code-title.ts";
|
|
23
|
+
import { contentAssetsPlugin } from "./content-assets.ts";
|
|
17
24
|
import { directiveToCalloutPlugin } from "./directives.ts";
|
|
18
25
|
import { externalLinksPlugin } from "./external-links.ts";
|
|
19
26
|
import { MARKDOWN_BODY_FEATURES, MDX_BODY_FEATURES } from "./features.ts";
|
|
27
|
+
import { fenceLanguagePlugin } from "./fence-language.ts";
|
|
28
|
+
import { githubAlertsPlugin } from "./github-alerts.ts";
|
|
20
29
|
import { headingAnchorPlugin } from "./heading-anchors.ts";
|
|
21
30
|
import { includePlugin } from "./include.ts";
|
|
22
31
|
import { inlineCodeHighlightPlugin } from "./inline-code.ts";
|
|
@@ -24,10 +33,13 @@ import { languageIconTransformer } from "./language-icon.ts";
|
|
|
24
33
|
import { mathPlugin } from "./math.ts";
|
|
25
34
|
import { mermaidPlugin } from "./mermaid.ts";
|
|
26
35
|
import { packageInstallPlugin } from "./package-install.ts";
|
|
36
|
+
import { promptTextPlugin } from "./prompt-text.ts";
|
|
27
37
|
import { relativeLinksPlugin } from "./relative-links.ts";
|
|
38
|
+
import { svgFallbackPlugin } from "./svg-fallback.ts";
|
|
28
39
|
import { tableWrapPlugin } from "./table-wrap.ts";
|
|
29
40
|
import { DEFAULT_CODE_THEMES } from "./themes.ts";
|
|
30
41
|
import type { CodeThemes } from "./themes.ts";
|
|
42
|
+
import { titleHeadingPlugin } from "./title-heading.ts";
|
|
31
43
|
import { ts2jsPlugin } from "./ts2js.ts";
|
|
32
44
|
import { variablesPlugin } from "./variables.ts";
|
|
33
45
|
import { viewsPlugin } from "./views.ts";
|
|
@@ -94,29 +106,33 @@ const asShikiTransformer = (transformer: { name: string }): ShikiTransformer =>
|
|
|
94
106
|
* (`[#custom-id]`, `[!toc]`, `[toc]`), which must parse regardless of config —
|
|
95
107
|
* while `markdown.headingAnchors: false` only turns off the self-linking
|
|
96
108
|
* anchor wrap on `<h2>`–`<h6>`. Inline code runs first so the anchor wrap
|
|
97
|
-
* re-refs already-highlighted code. The
|
|
98
|
-
*
|
|
109
|
+
* re-refs already-highlighted code. The title-heading plugin runs after the
|
|
110
|
+
* heading plugin has slugged every heading, so dropping an untitled page's
|
|
111
|
+
* title `<h1>` moves no other heading's id. The external-link plugin is added
|
|
112
|
+
* only when `markdown.externalLinks` is on, so off stays today's exact output.
|
|
99
113
|
*/
|
|
100
114
|
const blumeHastPlugins = (options: BlumeMarkdownOptions): HastPlugin[] => [
|
|
101
115
|
asHastPlugin(inlineCodeHighlightPlugin(options.codeThemes)),
|
|
102
116
|
asHastPlugin(tableWrapPlugin()),
|
|
103
117
|
asHastPlugin(headingAnchorPlugin({ wrap: options.headingAnchors !== false })),
|
|
118
|
+
asHastPlugin(titleHeadingPlugin()),
|
|
104
119
|
...(options.externalLinks ? [asHastPlugin(externalLinksPlugin())] : []),
|
|
105
120
|
];
|
|
106
121
|
|
|
107
122
|
/**
|
|
108
|
-
* Shiki transformers enabled by default for every code block. The
|
|
123
|
+
* Shiki transformers enabled by default for every code block. The upstream
|
|
109
124
|
* notation transformers read GitHub-style comments and strip them from the
|
|
110
125
|
* output: `// [!code highlight]`, `// [!code ++]` / `// [!code --]`,
|
|
111
|
-
* `// [!code word:x]`,
|
|
126
|
+
* `// [!code word:x]`, `// [!code focus]`, and `// [!code error]` /
|
|
127
|
+
* `// [!code warning]`. The v3 match algorithm scopes a
|
|
112
128
|
* notation to the line it sits on (or the next, for a trailing comment).
|
|
113
129
|
* `transformerMetaHighlight` adds numeric range highlighting from the fence meta
|
|
114
130
|
* (` ```ts {1,3-5} `), reusing the same `highlighted` class. Blume's own
|
|
115
131
|
* {@link languageIconTransformer} prepends a brand icon, and
|
|
116
132
|
* {@link codeTitleTransformer} runs last to promote fence-meta (title / line
|
|
117
133
|
* numbers) to `<pre>` attributes. The theme styles the classes these emit
|
|
118
|
-
* (`highlighted`, `
|
|
119
|
-
* `blume-lang-icon`).
|
|
134
|
+
* (`highlighted`, `highlighted error/warning`, `diff add/remove`,
|
|
135
|
+
* `highlighted-word`, `focused`, `blume-lang-icon`).
|
|
120
136
|
*/
|
|
121
137
|
export interface BlumeShikiOptions {
|
|
122
138
|
/** Prepend a brand language icon to the header (`markdown.code.icons`). */
|
|
@@ -131,6 +147,15 @@ export const blumeShikiTransformers = (
|
|
|
131
147
|
transformerNotationDiff({ matchAlgorithm: "v3" }),
|
|
132
148
|
transformerNotationWordHighlight({ matchAlgorithm: "v3" }),
|
|
133
149
|
transformerNotationFocus({ matchAlgorithm: "v3" }),
|
|
150
|
+
// Only the two levels the theme styles: upstream also maps `[!code info]`,
|
|
151
|
+
// which would otherwise strip the comment and leave a plain highlight.
|
|
152
|
+
transformerNotationErrorLevel({
|
|
153
|
+
classMap: {
|
|
154
|
+
error: ["highlighted", "error"],
|
|
155
|
+
warning: ["highlighted", "warning"],
|
|
156
|
+
},
|
|
157
|
+
matchAlgorithm: "v3",
|
|
158
|
+
}),
|
|
134
159
|
transformerMetaHighlight(),
|
|
135
160
|
];
|
|
136
161
|
if (options.icons !== false) {
|
|
@@ -305,14 +330,17 @@ export interface BlumeMarkdownOptions {
|
|
|
305
330
|
}
|
|
306
331
|
|
|
307
332
|
/**
|
|
308
|
-
* MDAST plugins that apply to both `.md` and `.mdx`:
|
|
309
|
-
*
|
|
310
|
-
*
|
|
311
|
-
*
|
|
333
|
+
* MDAST plugins that apply to both `.md` and `.mdx`: an SVG Astro can't
|
|
334
|
+
* measure pointed at its served original, relative page links rewritten to
|
|
335
|
+
* the served URL of the route they mean, references to other files beside the
|
|
336
|
+
* page to their served copies, then the base-path link rewrite for
|
|
337
|
+
* root-relative links (added only when a `basePath` or `deployBase` is
|
|
338
|
+
* configured).
|
|
312
339
|
*/
|
|
313
340
|
const blumeSharedMdastPlugins = (
|
|
314
341
|
options: BlumeMarkdownOptions
|
|
315
342
|
): MdastPlugin[] => [
|
|
343
|
+
asMdastPlugin(svgFallbackPlugin()),
|
|
316
344
|
asMdastPlugin(
|
|
317
345
|
relativeLinksPlugin({
|
|
318
346
|
contentRoot: options.contentRoot,
|
|
@@ -320,6 +348,12 @@ const blumeSharedMdastPlugins = (
|
|
|
320
348
|
deployBase: options.deployBase,
|
|
321
349
|
})
|
|
322
350
|
),
|
|
351
|
+
asMdastPlugin(
|
|
352
|
+
contentAssetsPlugin({
|
|
353
|
+
dataFile: options.dataFile,
|
|
354
|
+
deployBase: options.deployBase,
|
|
355
|
+
})
|
|
356
|
+
),
|
|
323
357
|
...(options.basePath || options.deployBase
|
|
324
358
|
? [
|
|
325
359
|
asMdastPlugin(
|
|
@@ -344,29 +378,94 @@ const blumeIncludePlugin = (options: BlumeMarkdownOptions): MdastPlugin =>
|
|
|
344
378
|
})
|
|
345
379
|
);
|
|
346
380
|
|
|
381
|
+
/** A Sätteri processor, as `satteri()` builds one. */
|
|
382
|
+
type SatteriProcessor = ReturnType<typeof satteri>;
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* `processor`, rendering each page from the source its parse needs: with the
|
|
386
|
+
* link-reference definitions its includes write appended (see
|
|
387
|
+
* `withIncludedDefinitions`) — the include splice runs after the page is
|
|
388
|
+
* parsed, too late for the parse to resolve a reference in the page against
|
|
389
|
+
* a partial's definition — and with the punctuation in its pinned heading
|
|
390
|
+
* ids escaped (see `escapePinnedIds`), so smart punctuation leaves a
|
|
391
|
+
* `[#a--b]` pin as written. Pages with neither render their source as given.
|
|
392
|
+
*/
|
|
393
|
+
const withRenderSource = (
|
|
394
|
+
processor: SatteriProcessor,
|
|
395
|
+
options: BlumeMarkdownOptions
|
|
396
|
+
): SatteriProcessor => {
|
|
397
|
+
const contentRoot = options.contentRoot
|
|
398
|
+
? resolve(options.contentRoot)
|
|
399
|
+
: undefined;
|
|
400
|
+
const source = async (content: string, sourcePath: string) =>
|
|
401
|
+
substituteVariables(
|
|
402
|
+
await withIncludedDefinitions(content, { contentRoot, sourcePath }),
|
|
403
|
+
options.variables
|
|
404
|
+
);
|
|
405
|
+
const { createMdxRenderer, createRenderer } = processor;
|
|
406
|
+
const wrapped: SatteriProcessor = {
|
|
407
|
+
...processor,
|
|
408
|
+
createRenderer: async (shared) => {
|
|
409
|
+
const renderer = await createRenderer(shared);
|
|
410
|
+
return {
|
|
411
|
+
render: async (content, renderOptions) =>
|
|
412
|
+
renderer.render(
|
|
413
|
+
escapePinnedIds(
|
|
414
|
+
renderOptions?.fileURL
|
|
415
|
+
? await source(content, fileURLToPath(renderOptions.fileURL))
|
|
416
|
+
: content,
|
|
417
|
+
"markdown"
|
|
418
|
+
),
|
|
419
|
+
renderOptions
|
|
420
|
+
),
|
|
421
|
+
};
|
|
422
|
+
},
|
|
423
|
+
};
|
|
424
|
+
if (createMdxRenderer) {
|
|
425
|
+
wrapped.createMdxRenderer = async (shared, mdx) => {
|
|
426
|
+
const renderer = await createMdxRenderer(shared, mdx);
|
|
427
|
+
return {
|
|
428
|
+
process: async (content, filePath, frontmatter) =>
|
|
429
|
+
renderer.process(
|
|
430
|
+
escapePinnedIds(await source(content, filePath), "mdx"),
|
|
431
|
+
filePath,
|
|
432
|
+
frontmatter
|
|
433
|
+
),
|
|
434
|
+
};
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
return wrapped;
|
|
438
|
+
};
|
|
439
|
+
|
|
347
440
|
/** Sätteri processor for plain `.md`, with Blume's curated feature set. */
|
|
348
441
|
export const blumeMarkdownProcessor = (options: BlumeMarkdownOptions = {}) =>
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
442
|
+
withRenderSource(
|
|
443
|
+
satteri({
|
|
444
|
+
features: { ...MARKDOWN_BODY_FEATURES },
|
|
445
|
+
hastPlugins: blumeHastPlugins(options),
|
|
446
|
+
mdastPlugins: [
|
|
447
|
+
blumeIncludePlugin(options),
|
|
448
|
+
asMdastPlugin(fenceLanguagePlugin()),
|
|
449
|
+
...(hasVariables(options.variables)
|
|
450
|
+
? [asMdastPlugin(variablesPlugin(options.variables))]
|
|
451
|
+
: []),
|
|
452
|
+
...blumeSharedMdastPlugins(options),
|
|
453
|
+
],
|
|
454
|
+
}),
|
|
455
|
+
options
|
|
456
|
+
);
|
|
360
457
|
|
|
361
458
|
export type BlumeMdxOptions = BlumeMarkdownOptions;
|
|
362
459
|
|
|
363
460
|
/**
|
|
364
461
|
* Sätteri MDX processor: Blume's feature set plus the MDAST plugins that target
|
|
365
462
|
* components — `package-install` → package-manager tabs, ` ```ts ts2js ` →
|
|
366
|
-
* TypeScript/JavaScript tabs, `:::note`
|
|
463
|
+
* TypeScript/JavaScript tabs, `:::note` and GitHub's `> [!NOTE]` alerts →
|
|
464
|
+
* `<Callout>`, ` ```mermaid ` → a
|
|
367
465
|
* `<blume-mermaid>` element, block math
|
|
368
|
-
* (`$$…$$`) → the `<Math>` component,
|
|
369
|
-
* `<ResponseExample>` → the page's `<ApiRail
|
|
466
|
+
* (`$$…$$`) → the `<Math>` component, top-level `<RequestExample>` and
|
|
467
|
+
* `<ResponseExample>` → the page's `<ApiRail>`, and a `<Prompt>` body's text
|
|
468
|
+
* back to the punctuation its author typed. Used as the `processor` for
|
|
370
469
|
* `@astrojs/mdx` so these apply to `.mdx` only (plain `.md` uses
|
|
371
470
|
* {@link blumeMarkdownProcessor}).
|
|
372
471
|
*
|
|
@@ -380,18 +479,24 @@ export type BlumeMdxOptions = BlumeMarkdownOptions;
|
|
|
380
479
|
* Satteri's full `MdastPlugin` type at this single boundary.
|
|
381
480
|
*/
|
|
382
481
|
export const blumeMdxProcessor = (options: BlumeMdxOptions = {}) =>
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
482
|
+
withRenderSource(
|
|
483
|
+
satteri({
|
|
484
|
+
features: { ...MDX_BODY_FEATURES },
|
|
485
|
+
hastPlugins: blumeHastPlugins(options),
|
|
486
|
+
mdastPlugins: [
|
|
487
|
+
blumeIncludePlugin(options),
|
|
488
|
+
asMdastPlugin(fenceLanguagePlugin()),
|
|
489
|
+
asMdastPlugin(packageInstallPlugin()),
|
|
490
|
+
asMdastPlugin(ts2jsPlugin()),
|
|
491
|
+
asMdastPlugin(directiveToCalloutPlugin()),
|
|
492
|
+
asMdastPlugin(githubAlertsPlugin()),
|
|
493
|
+
asMdastPlugin(mermaidPlugin()),
|
|
494
|
+
asMdastPlugin(mathPlugin()),
|
|
495
|
+
...blumeSharedMdastPlugins(options),
|
|
496
|
+
asMdastPlugin(apiRailPlugin()),
|
|
497
|
+
asMdastPlugin(viewsPlugin()),
|
|
498
|
+
asMdastPlugin(promptTextPlugin()),
|
|
499
|
+
],
|
|
500
|
+
}),
|
|
501
|
+
options
|
|
502
|
+
);
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart punctuation (Astro's `smartypants`, on by default) curls quotes and
|
|
3
|
+
* turns `--`, `---`, and `...` into dashes and an ellipsis as a page parses.
|
|
4
|
+
* That suits prose, but a `<Prompt>`'s body is never shown: it's copied into
|
|
5
|
+
* an AI tool as Markdown, where `lang=“ts”` and `–force` are broken code. This
|
|
6
|
+
* plugin puts back the punctuation the author typed in the body's text.
|
|
7
|
+
*
|
|
8
|
+
* Each text node is compared with its own source: a typographic mark the
|
|
9
|
+
* source doesn't contain came from smart punctuation, so it goes back to the
|
|
10
|
+
* ASCII it was made from. A mark the author typed (or wrote as an entity)
|
|
11
|
+
* stays.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { MdastNode } from "./mdast.ts";
|
|
15
|
+
|
|
16
|
+
/** Each group of marks smart punctuation makes, and the ASCII it makes them from. */
|
|
17
|
+
const MARKS: readonly { ascii: string; marks: readonly string[] }[] = [
|
|
18
|
+
{ ascii: '"', marks: ["“", "”"] },
|
|
19
|
+
{ ascii: "'", marks: ["‘", "’"] },
|
|
20
|
+
{ ascii: "---", marks: ["—"] },
|
|
21
|
+
{ ascii: "--", marks: ["–"] },
|
|
22
|
+
{ ascii: "...", marks: ["…"] },
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const ANY_MARK = /[“”‘’—–…]/u;
|
|
26
|
+
|
|
27
|
+
/** A character reference (`’`, `’`), which can spell any mark. */
|
|
28
|
+
const ENTITY = /&[#\da-z]+;/iu;
|
|
29
|
+
|
|
30
|
+
/** The text as the author typed it, given the source it was parsed from. */
|
|
31
|
+
export const restorePunctuation = (value: string, source: string): string => {
|
|
32
|
+
if (!ANY_MARK.test(value) || ENTITY.test(source)) {
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
let restored = value;
|
|
36
|
+
for (const { ascii, marks } of MARKS) {
|
|
37
|
+
if (!marks.some((mark) => source.includes(mark))) {
|
|
38
|
+
for (const mark of marks) {
|
|
39
|
+
restored = restored.replaceAll(mark, ascii);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return restored;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/** The node slice the plugin reads. */
|
|
47
|
+
interface PromptNode extends MdastNode {
|
|
48
|
+
children?: PromptNode[];
|
|
49
|
+
name?: string | null;
|
|
50
|
+
position?: { end: { offset?: number }; start: { offset?: number } };
|
|
51
|
+
value?: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** The visitor context slice the plugin reads and writes through. */
|
|
55
|
+
interface PromptContext {
|
|
56
|
+
readonly source: string;
|
|
57
|
+
setProperty: (node: PromptNode, key: "value", value: string) => void;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Restore every text node under `node`. */
|
|
61
|
+
const restoreTexts = (node: PromptNode, ctx: PromptContext): void => {
|
|
62
|
+
for (const child of node.children ?? []) {
|
|
63
|
+
const start = child.position?.start.offset;
|
|
64
|
+
const end = child.position?.end.offset;
|
|
65
|
+
if (
|
|
66
|
+
child.type === "text" &&
|
|
67
|
+
child.value !== undefined &&
|
|
68
|
+
start !== undefined &&
|
|
69
|
+
end !== undefined
|
|
70
|
+
) {
|
|
71
|
+
const value = restorePunctuation(
|
|
72
|
+
child.value,
|
|
73
|
+
ctx.source.slice(start, end)
|
|
74
|
+
);
|
|
75
|
+
if (value !== child.value) {
|
|
76
|
+
ctx.setProperty(child, "value", value);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
restoreTexts(child, ctx);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const visit = (node: PromptNode, ctx: PromptContext): void => {
|
|
84
|
+
if (node.name === "Prompt") {
|
|
85
|
+
restoreTexts(node, ctx);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/** Satteri MDAST plugin that undoes smart punctuation in `<Prompt>` bodies. */
|
|
90
|
+
export const promptTextPlugin = () => ({
|
|
91
|
+
mdxJsxFlowElement: visit,
|
|
92
|
+
mdxJsxTextElement: visit,
|
|
93
|
+
name: "blume-prompt-text",
|
|
94
|
+
options: { position: true },
|
|
95
|
+
});
|
|
@@ -3,7 +3,11 @@ import { fileURLToPath } from "node:url";
|
|
|
3
3
|
import { dirname, normalize, relative, resolve } from "pathe";
|
|
4
4
|
|
|
5
5
|
import { mountBasePath } from "../core/base-path.ts";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
isIndexFileName,
|
|
8
|
+
resolveRelativeHref,
|
|
9
|
+
resolveRootFileHref,
|
|
10
|
+
} from "../core/links.ts";
|
|
7
11
|
import type { RelativeLinkBase } from "../core/links.ts";
|
|
8
12
|
import type { MdastNode, MdastValue } from "./mdast.ts";
|
|
9
13
|
import { routeSnapshotReader } from "./route-snapshot.ts";
|
|
@@ -71,6 +75,13 @@ interface LocatedPage extends RelativeLinkBase {
|
|
|
71
75
|
/** A JSX component name (`Card`, `Tree.File`), as opposed to an HTML tag. */
|
|
72
76
|
const COMPONENT_NAME = /^[A-Z]/u;
|
|
73
77
|
|
|
78
|
+
/**
|
|
79
|
+
* A root-relative link to a Markdown file (`/guide/new.md#x`), never
|
|
80
|
+
* `//host`: the one root-relative shape this plugin rewrites, when it names a
|
|
81
|
+
* content file.
|
|
82
|
+
*/
|
|
83
|
+
const ROOT_FILE_LINK = /^\/(?!\/)[^?#]*\.mdx?(?:[?#]|$)/iu;
|
|
84
|
+
|
|
74
85
|
/** A plain string attribute value; an expression value isn't a link target. */
|
|
75
86
|
const isStringValue = (value: MdastValue): value is string =>
|
|
76
87
|
typeof value === "string";
|
|
@@ -146,7 +157,10 @@ export interface RelativeLinksPluginOptions {
|
|
|
146
157
|
* snapshot the CLI publishes (or, ejected, the file eject writes), keyed by
|
|
147
158
|
* collection entry: `docs` entries by their path under `contentRoot`, staged
|
|
148
159
|
* entries (remote sources) by the longest trailing path that names one. A file
|
|
149
|
-
* the snapshot doesn't know keeps its links as written.
|
|
160
|
+
* the snapshot doesn't know keeps its links as written. A root-relative link
|
|
161
|
+
* to a content file (`/guide/new.md`, see `resolveRootFileHref`) lands on that
|
|
162
|
+
* file's page too, from any page; one naming no content file is left as
|
|
163
|
+
* written, since `/guide/new.md` is also a page's Markdown copy.
|
|
150
164
|
*
|
|
151
165
|
* A rewritten route already carries `basePath`, and the `deployment.base`
|
|
152
166
|
* prefix goes on here, unconditionally: the route is one Blume serves, so
|
|
@@ -225,11 +239,32 @@ export const relativeLinksPlugin = (
|
|
|
225
239
|
return undefined;
|
|
226
240
|
};
|
|
227
241
|
|
|
242
|
+
/**
|
|
243
|
+
* The route a root-relative link to a content file (`/guide/new.md`)
|
|
244
|
+
* means, when it names one (see `resolveRootFileHref`).
|
|
245
|
+
*/
|
|
246
|
+
const resolveRootFile = (url: string): string | undefined => {
|
|
247
|
+
const index = contentRoot ? routeIndex() : undefined;
|
|
248
|
+
if (!(contentRoot && index)) {
|
|
249
|
+
return undefined;
|
|
250
|
+
}
|
|
251
|
+
const route = resolveRootFileHref(url, {
|
|
252
|
+
contentRoot,
|
|
253
|
+
deployBase,
|
|
254
|
+
routeOfFile: (file) =>
|
|
255
|
+
index.routes.get(entryKey("docs", relative(contentRoot, file))),
|
|
256
|
+
});
|
|
257
|
+
return route === undefined ? undefined : mountBasePath(deployBase, route);
|
|
258
|
+
};
|
|
259
|
+
|
|
228
260
|
/** The route `url` means on the page at `fileURL`, when it's relative. */
|
|
229
261
|
const resolveUrl = (
|
|
230
262
|
url: string,
|
|
231
263
|
fileURL: URL | undefined
|
|
232
264
|
): string | undefined => {
|
|
265
|
+
if (ROOT_FILE_LINK.test(url)) {
|
|
266
|
+
return resolveRootFile(url);
|
|
267
|
+
}
|
|
233
268
|
// Cheap first: a target that can't be relative never needs the index. A
|
|
234
269
|
// dotted name (`./node.js`) passes, since only the index knows its route.
|
|
235
270
|
if (
|
|
@@ -3,35 +3,45 @@ import { readFileSync, statSync } from "node:fs";
|
|
|
3
3
|
import { resolve } from "pathe";
|
|
4
4
|
|
|
5
5
|
import { readRuntimeModule } from "../astro/runtime-modules.ts";
|
|
6
|
+
import type { RuntimeModuleId } from "../astro/runtime-modules.ts";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
|
-
* A reader for
|
|
9
|
-
* the
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* A reader for a runtime module snapshot a Markdown plugin consults: the text
|
|
10
|
+
* the CLI publishes under `id`, or — in an ejected app, with no CLI in the
|
|
11
|
+
* process — the file eject writes for it (`file`), re-read only when it
|
|
12
|
+
* changes. Resolves to `undefined` when neither is available.
|
|
12
13
|
*/
|
|
13
|
-
export const
|
|
14
|
-
|
|
14
|
+
export const snapshotReader = (
|
|
15
|
+
id: RuntimeModuleId,
|
|
16
|
+
file?: string
|
|
15
17
|
): (() => string | undefined) => {
|
|
16
|
-
const
|
|
18
|
+
const path = file ? resolve(file) : undefined;
|
|
17
19
|
let fileStamp: number | undefined;
|
|
18
20
|
let fileText: string | undefined;
|
|
19
21
|
|
|
20
22
|
/** The ejected snapshot file's text, re-read only when it changes. */
|
|
21
|
-
const
|
|
23
|
+
const readFile = (target: string): string | undefined => {
|
|
22
24
|
let stamp: number;
|
|
23
25
|
try {
|
|
24
|
-
stamp = statSync(
|
|
26
|
+
stamp = statSync(target).mtimeMs;
|
|
25
27
|
} catch {
|
|
26
28
|
return undefined;
|
|
27
29
|
}
|
|
28
30
|
if (stamp !== fileStamp) {
|
|
29
31
|
fileStamp = stamp;
|
|
30
|
-
fileText = readFileSync(
|
|
32
|
+
fileText = readFileSync(target, "utf-8");
|
|
31
33
|
}
|
|
32
34
|
return fileText;
|
|
33
35
|
};
|
|
34
36
|
|
|
35
|
-
return () =>
|
|
36
|
-
readRuntimeModule("blume:data") ?? (file ? readDataFile(file) : undefined);
|
|
37
|
+
return () => readRuntimeModule(id) ?? (path ? readFile(path) : undefined);
|
|
37
38
|
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* A reader for the `blume:data` snapshot the Markdown link plugins consult for
|
|
42
|
+
* the site's routes: the text the CLI publishes, or the snapshot file an
|
|
43
|
+
* ejected app aliases (`dataFile`).
|
|
44
|
+
*/
|
|
45
|
+
export const routeSnapshotReader = (
|
|
46
|
+
dataFile?: string
|
|
47
|
+
): (() => string | undefined) => snapshotReader("blume:data", dataFile);
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
|
|
3
|
+
import { dirname, resolve } from "pathe";
|
|
4
|
+
|
|
5
|
+
import { unmeasurableSvgUrl } from "../core/svg-images.ts";
|
|
6
|
+
import type { MdastNode } from "./mdast.ts";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Sätteri MDAST plugin that points an image embed of a colocated SVG Astro
|
|
10
|
+
* can't measure (a draw.io export, say: see `core/svg-images.ts`) at its
|
|
11
|
+
* served original, `/blume-assets/content/…`. A relative image is one Astro
|
|
12
|
+
* imports and optimizes, and an import it can't read the size of fails the
|
|
13
|
+
* whole build; a root-relative URL is one it leaves alone, so the page shows
|
|
14
|
+
* the file as it is. Runs before the base links plugin, which mounts
|
|
15
|
+
* `deployment.base` on the URL like any other root-relative image.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
interface ImageNode extends MdastNode {
|
|
19
|
+
url?: string | null;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** The slice of Sätteri's MDAST visitor context this plugin needs. */
|
|
23
|
+
interface ImageContext {
|
|
24
|
+
fileURL: URL | undefined;
|
|
25
|
+
setProperty: (node: MdastNode, key: "url", value: string) => void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const SVG = /\.svg$/iu;
|
|
29
|
+
|
|
30
|
+
export const svgFallbackPlugin = () => {
|
|
31
|
+
// Content image URLs are keyed by their path from the project root, where
|
|
32
|
+
// Blume runs Astro (see `contentAssetParam`).
|
|
33
|
+
const projectRoot = resolve(".");
|
|
34
|
+
return {
|
|
35
|
+
async image(node: ImageNode, ctx: ImageContext) {
|
|
36
|
+
const { url } = node;
|
|
37
|
+
if (!(ctx.fileURL && url && SVG.test(url))) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const served = await unmeasurableSvgUrl(
|
|
41
|
+
dirname(fileURLToPath(ctx.fileURL)),
|
|
42
|
+
url,
|
|
43
|
+
projectRoot
|
|
44
|
+
);
|
|
45
|
+
if (served) {
|
|
46
|
+
ctx.setProperty(node, "url", served);
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
name: "blume-svg-fallback",
|
|
50
|
+
};
|
|
51
|
+
};
|