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.
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +134 -0
- package/README.md +4 -4
- package/dist/cli/{chunk-y4msrwm9.js → chunk-080mfch6.js} +15 -15
- package/dist/cli/{chunk-gfc5fqvf.js → chunk-1ch3ct3r.js} +18 -18
- package/dist/cli/{chunk-gfc5fqvf.js.map → chunk-1ch3ct3r.js.map} +1 -1
- package/dist/cli/{chunk-32khwcb6.js → chunk-2ssh60qh.js} +42 -69
- package/dist/cli/{chunk-32khwcb6.js.map → chunk-2ssh60qh.js.map} +9 -10
- package/dist/cli/{chunk-9qzgg6mj.js → chunk-34wap3ed.js} +3 -3
- package/dist/cli/{chunk-k3gr1nm9.js → chunk-40vk8kgf.js} +13 -16
- package/dist/cli/{chunk-k3gr1nm9.js.map → chunk-40vk8kgf.js.map} +3 -3
- package/dist/cli/chunk-487b95qy.js +329 -0
- package/dist/cli/chunk-487b95qy.js.map +13 -0
- package/dist/cli/chunk-4zxh25hc.js +157 -0
- package/dist/cli/chunk-4zxh25hc.js.map +10 -0
- package/dist/cli/chunk-69rjf786.js +146 -0
- package/dist/cli/chunk-69rjf786.js.map +11 -0
- package/dist/cli/{chunk-dqhg54mr.js → chunk-9h8mh2tk.js} +3 -3
- package/dist/cli/{chunk-dqhg54mr.js.map → chunk-9h8mh2tk.js.map} +2 -2
- package/dist/cli/{chunk-bqxaqn5p.js → chunk-9jqmq5hv.js} +8 -8
- package/dist/cli/{chunk-bqxaqn5p.js.map → chunk-9jqmq5hv.js.map} +1 -1
- package/dist/cli/{chunk-dv2z0rzf.js → chunk-aafhwx74.js} +38 -13
- package/dist/cli/{chunk-dv2z0rzf.js.map → chunk-aafhwx74.js.map} +5 -4
- package/dist/cli/{chunk-desvm72z.js → chunk-b680sv30.js} +22 -26
- package/dist/cli/chunk-b680sv30.js.map +13 -0
- package/dist/cli/{chunk-0w6hs479.js → chunk-beb0z983.js} +30 -18
- package/dist/cli/chunk-beb0z983.js.map +10 -0
- package/dist/cli/{chunk-1f882900.js → chunk-c5bjxq8v.js} +2 -2
- package/dist/cli/chunk-e1n41w9m.js +155 -0
- package/dist/cli/chunk-e1n41w9m.js.map +11 -0
- package/dist/cli/{chunk-sc93apfs.js → chunk-etckvbrh.js} +17 -17
- package/dist/cli/{chunk-sc93apfs.js.map → chunk-etckvbrh.js.map} +2 -2
- package/dist/cli/{chunk-bxwhtvw8.js → chunk-f260jdrn.js} +5 -5
- package/dist/cli/{chunk-74wfhv79.js → chunk-fnxgtjeq.js} +1 -1
- package/dist/cli/{chunk-ms9z66nz.js → chunk-gwy55cx3.js} +2 -2
- package/dist/cli/{chunk-ms9z66nz.js.map → chunk-gwy55cx3.js.map} +2 -2
- package/dist/cli/{chunk-dhwtqnnd.js → chunk-gxhcf2hs.js} +2 -2
- package/dist/cli/{chunk-tfycddbt.js → chunk-h0qwdbem.js} +2 -2
- package/dist/cli/{chunk-nbyvgnnm.js → chunk-hktq4j5r.js} +109 -49
- package/dist/cli/chunk-hktq4j5r.js.map +36 -0
- package/dist/cli/{chunk-twy7psdz.js → chunk-hn3g2b89.js} +14 -10
- package/dist/cli/chunk-hn3g2b89.js.map +10 -0
- package/dist/cli/{chunk-j1x92mx9.js → chunk-j4nfgn2j.js} +1 -1
- package/dist/cli/{chunk-dpy8qdjf.js → chunk-k45sq16q.js} +74 -183
- package/dist/cli/chunk-k45sq16q.js.map +18 -0
- package/dist/cli/{chunk-5cmts6dv.js → chunk-kmswjxj9.js} +7 -7
- package/dist/cli/{chunk-5cmts6dv.js.map → chunk-kmswjxj9.js.map} +1 -1
- package/dist/cli/{chunk-36bxs9c7.js → chunk-nqna8dzp.js} +27 -23
- package/dist/cli/chunk-nqna8dzp.js.map +10 -0
- package/dist/cli/{chunk-a57yh0h9.js → chunk-p834rkcn.js} +7 -7
- package/dist/cli/{chunk-a57yh0h9.js.map → chunk-p834rkcn.js.map} +1 -1
- package/dist/cli/{chunk-60hz265r.js → chunk-ppa6mg4d.js} +24 -11
- package/dist/cli/chunk-ppa6mg4d.js.map +10 -0
- package/dist/cli/{chunk-s0bdnc7v.js → chunk-q1wwrxzw.js} +5 -4
- package/dist/cli/chunk-q1wwrxzw.js.map +10 -0
- package/dist/cli/{chunk-ave1wcbr.js → chunk-qcyxkj44.js} +1 -1
- package/dist/cli/{chunk-124fvmzq.js → chunk-r5nm9w0c.js} +11183 -8806
- package/dist/cli/{chunk-124fvmzq.js.map → chunk-r5nm9w0c.js.map} +82 -66
- package/dist/cli/{chunk-ckrcm08h.js → chunk-rtvgmg2j.js} +48 -62
- package/dist/cli/{chunk-ckrcm08h.js.map → chunk-rtvgmg2j.js.map} +4 -5
- package/dist/cli/{chunk-297ajdcv.js → chunk-t2h8pwy1.js} +6 -6
- package/dist/cli/{chunk-297ajdcv.js.map → chunk-t2h8pwy1.js.map} +3 -3
- package/dist/cli/{chunk-gxtg6ed2.js → chunk-x60e15st.js} +21 -21
- package/dist/cli/{chunk-gxtg6ed2.js.map → chunk-x60e15st.js.map} +3 -3
- package/dist/cli/{chunk-58bt3hag.js → chunk-x7bh6d9j.js} +4 -4
- package/dist/cli/{chunk-hvcxng5f.js → chunk-ydqzkhjn.js} +6 -6
- package/dist/cli/{chunk-kdpzw38a.js → chunk-yg8ckc3g.js} +95 -7
- package/dist/cli/chunk-yg8ckc3g.js.map +11 -0
- package/dist/cli/{chunk-0pmb4tr4.js → chunk-zxd5jrgx.js} +1205 -222
- package/dist/cli/chunk-zxd5jrgx.js.map +44 -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 +38 -6
- package/dist/types/core/content-assets.d.ts +16 -18
- package/dist/types/core/data.d.ts +6 -2
- 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/mcp-clients.d.ts +47 -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 +16 -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 +322 -11
- 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/ratelimit/index.d.ts +2 -0
- package/dist/types/ratelimit/memory.d.ts +1 -1
- package/dist/types/ratelimit/schema.d.ts +40 -0
- package/dist/types/ratelimit/unkey.d.ts +48 -0
- 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 +24 -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 +7 -6
- package/docs/configuration/rate-limiting.mdx +20 -1
- package/docs/configuration/theming.mdx +5 -1
- package/docs/content/components.mdx +26 -6
- package/docs/content/frontmatter.mdx +1 -1
- package/docs/content/i18n.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/mcp.mdx +40 -8
- 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 +51 -29
- 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 +5 -5
- 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 +5 -5
- 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 +47 -11
- 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 +93 -189
- 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/required-secrets.ts +0 -1
- 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/PageActions.astro +81 -23
- package/src/components/layout/RootLayout.astro +35 -32
- package/src/components/layout/SiteFooter.astro +31 -8
- 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 +39 -5
- package/src/core/config.ts +46 -1
- package/src/core/content-assets.ts +64 -144
- package/src/core/data.ts +10 -3
- 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/mcp-clients.ts +87 -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 +41 -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 +110 -6
- 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/ratelimit/index.ts +2 -0
- package/src/ratelimit/memory.ts +1 -1
- package/src/ratelimit/runtime.ts +81 -0
- package/src/ratelimit/schema.ts +2 -0
- package/src/ratelimit/unkey.ts +61 -0
- package/src/registry/eject.ts +0 -1
- package/src/registry/registry.ts +1 -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-y4msrwm9.js.map → chunk-080mfch6.js.map} +0 -0
- /package/dist/cli/{chunk-9qzgg6mj.js.map → chunk-34wap3ed.js.map} +0 -0
- /package/dist/cli/{chunk-1f882900.js.map → chunk-c5bjxq8v.js.map} +0 -0
- /package/dist/cli/{chunk-bxwhtvw8.js.map → chunk-f260jdrn.js.map} +0 -0
- /package/dist/cli/{chunk-74wfhv79.js.map → chunk-fnxgtjeq.js.map} +0 -0
- /package/dist/cli/{chunk-dhwtqnnd.js.map → chunk-gxhcf2hs.js.map} +0 -0
- /package/dist/cli/{chunk-tfycddbt.js.map → chunk-h0qwdbem.js.map} +0 -0
- /package/dist/cli/{chunk-j1x92mx9.js.map → chunk-j4nfgn2j.js.map} +0 -0
- /package/dist/cli/{chunk-ave1wcbr.js.map → chunk-qcyxkj44.js.map} +0 -0
- /package/dist/cli/{chunk-58bt3hag.js.map → chunk-x7bh6d9j.js.map} +0 -0
- /package/dist/cli/{chunk-hvcxng5f.js.map → chunk-ydqzkhjn.js.map} +0 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { join } from "pathe";
|
|
2
|
+
|
|
3
|
+
import { buildAgentReadability } from "../ai/agent-readability.ts";
|
|
4
|
+
import {
|
|
5
|
+
AI_CATALOG_PATH,
|
|
6
|
+
ARD_MANIFEST_PATH,
|
|
7
|
+
buildAiCatalog,
|
|
8
|
+
} from "../ai/ai-catalog.ts";
|
|
9
|
+
import { API_CATALOG_PATH, buildApiCatalog } from "../ai/api-catalog.ts";
|
|
10
|
+
import {
|
|
11
|
+
API_NAVIGATION_PATH,
|
|
12
|
+
API_PAGES_PATH,
|
|
13
|
+
OPENAPI_PATH,
|
|
14
|
+
} from "../ai/api/paths.ts";
|
|
15
|
+
import { SKILL_MD_PATH } from "../ai/site-skill.ts";
|
|
16
|
+
import { AGENT_SKILLS_INDEX_PATH, servesSkillsIndex } from "../ai/skills.ts";
|
|
17
|
+
import type { SkillArtifact } from "../ai/skills.ts";
|
|
18
|
+
import {
|
|
19
|
+
buildSignaturesDirectory,
|
|
20
|
+
SIGNATURES_DIRECTORY_PATH,
|
|
21
|
+
} from "../ai/web-bot-auth.ts";
|
|
22
|
+
import type { BlumeProject } from "../core/project-graph.ts";
|
|
23
|
+
import type { ResolvedConfig } from "../core/schema.ts";
|
|
24
|
+
import { staticFileResolver } from "../core/static-files.ts";
|
|
25
|
+
import { buildRobots } from "./robots.ts";
|
|
26
|
+
import { buildRssFeeds } from "./rss.ts";
|
|
27
|
+
import { buildSitemapFiles } from "./sitemap.ts";
|
|
28
|
+
|
|
29
|
+
/** A generated `.well-known` discovery document: `null` content when it's off. */
|
|
30
|
+
export interface WellKnownFile {
|
|
31
|
+
content: string | null;
|
|
32
|
+
label: string;
|
|
33
|
+
path: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The generated `.well-known` discovery documents — the Web Bot Auth signature
|
|
38
|
+
* directory, the RFC 9727 API catalog, and the AI catalog under both the
|
|
39
|
+
* ai-catalog spec's well-known URI and the ARD v0.91 one (see
|
|
40
|
+
* `ai/ai-catalog.ts`) — each with `null` content when its feature is off.
|
|
41
|
+
*/
|
|
42
|
+
export const wellKnownFiles = (
|
|
43
|
+
config: ResolvedConfig,
|
|
44
|
+
skills: readonly SkillArtifact[]
|
|
45
|
+
): WellKnownFile[] => {
|
|
46
|
+
const aiCatalog = buildAiCatalog(config, skills);
|
|
47
|
+
return [
|
|
48
|
+
{
|
|
49
|
+
content: buildSignaturesDirectory(config),
|
|
50
|
+
label: "Web Bot Auth",
|
|
51
|
+
path: SIGNATURES_DIRECTORY_PATH,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
content: buildApiCatalog(config),
|
|
55
|
+
label: "RFC 9727",
|
|
56
|
+
path: API_CATALOG_PATH,
|
|
57
|
+
},
|
|
58
|
+
{ content: aiCatalog, label: "AI Catalog", path: AI_CATALOG_PATH },
|
|
59
|
+
{ content: aiCatalog, label: "ARD manifest", path: ARD_MANIFEST_PATH },
|
|
60
|
+
];
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The files a build serves beside its pages that don't come from `public/`,
|
|
65
|
+
* as base-less root-relative paths: what `publishBuildArtifacts` writes once
|
|
66
|
+
* Astro is done (llms.txt, the sitemap, robots.txt, `agent-readability.json`,
|
|
67
|
+
* the `.well-known` discovery documents, the Agent Skills index, `skill.md`)
|
|
68
|
+
* and the generated endpoints at fixed paths (the RSS feeds, the JSON docs
|
|
69
|
+
* API and its OpenAPI description, the MCP discovery documents). Each is
|
|
70
|
+
* listed under the gate its writer reads, so a feature the config switches
|
|
71
|
+
* off drops its file here too: `blume validate` accepts a link to
|
|
72
|
+
* `/llms.txt` exactly when the build writes one.
|
|
73
|
+
*
|
|
74
|
+
* Read from the config alone, before a build: the skill archives a build
|
|
75
|
+
* publishes beside the index, and the platform files (`_redirects`,
|
|
76
|
+
* `_headers`, `vercel.json`), aren't listed. A page's Markdown copy
|
|
77
|
+
* (`/guide.md`) is its route's, and resolves through the page.
|
|
78
|
+
*/
|
|
79
|
+
export const generatedFilePaths = (project: BlumeProject): string[] => {
|
|
80
|
+
const { config } = project;
|
|
81
|
+
const paths: string[] = [];
|
|
82
|
+
if (config.agents.llmsTxt.enabled) {
|
|
83
|
+
paths.push("/llms.txt", "/llms-full.txt");
|
|
84
|
+
}
|
|
85
|
+
paths.push(
|
|
86
|
+
...(buildSitemapFiles(project) ?? []).map((file) => `/${file.name}`)
|
|
87
|
+
);
|
|
88
|
+
if (buildRobots(project)) {
|
|
89
|
+
paths.push("/robots.txt");
|
|
90
|
+
}
|
|
91
|
+
if (buildAgentReadability(project)) {
|
|
92
|
+
paths.push("/agent-readability.json");
|
|
93
|
+
}
|
|
94
|
+
paths.push(
|
|
95
|
+
...wellKnownFiles(config, []).flatMap((file) =>
|
|
96
|
+
file.content ? [file.path] : []
|
|
97
|
+
)
|
|
98
|
+
);
|
|
99
|
+
if (servesSkillsIndex(config)) {
|
|
100
|
+
paths.push(AGENT_SKILLS_INDEX_PATH);
|
|
101
|
+
if (config.agents.skillMd) {
|
|
102
|
+
paths.push(SKILL_MD_PATH);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
paths.push(...buildRssFeeds(project).map((feed) => feed.path));
|
|
106
|
+
if (config.agents.api) {
|
|
107
|
+
paths.push(OPENAPI_PATH, API_PAGES_PATH, API_NAVIGATION_PATH);
|
|
108
|
+
}
|
|
109
|
+
if (config.agents.mcp.enabled) {
|
|
110
|
+
paths.push("/.well-known/mcp.json", "/.well-known/mcp/server-card.json");
|
|
111
|
+
}
|
|
112
|
+
return paths;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Whether a base-less path is a file the project's site serves beside its
|
|
117
|
+
* pages: one in `public/` (`/spec.pdf`, a folder's `index.html`) or one the
|
|
118
|
+
* build generates (`/llms.txt`). What `generateRuntime` and `blume doctor`
|
|
119
|
+
* check navigation entries against, beside the routes, as `blume validate`
|
|
120
|
+
* checks links.
|
|
121
|
+
*/
|
|
122
|
+
export const servedFiles = (
|
|
123
|
+
project: BlumeProject
|
|
124
|
+
): ((path: string) => boolean) =>
|
|
125
|
+
staticFileResolver(
|
|
126
|
+
join(project.context.root, "public"),
|
|
127
|
+
generatedFilePaths(project)
|
|
128
|
+
);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
-
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
2
|
+
import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
3
3
|
|
|
4
4
|
import { dirname, join } from "pathe";
|
|
5
5
|
|
|
@@ -99,6 +99,28 @@ export const checkVercelFunctionBundles = async (
|
|
|
99
99
|
return !fatal;
|
|
100
100
|
};
|
|
101
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Remove the routing config of a build that failed after the adapter wrote
|
|
104
|
+
* it. The adapter's config is complete as far as the adapter goes, but the
|
|
105
|
+
* redirects, negotiation, and base routes Blume adds were never spliced in,
|
|
106
|
+
* so `vercel deploy --prebuilt` would ship a site missing them. Without a
|
|
107
|
+
* `config.json`, the tree is no Build Output a deploy accepts; the function
|
|
108
|
+
* bundles stay for inspection.
|
|
109
|
+
*/
|
|
110
|
+
const withdrawBuildOutput = async (
|
|
111
|
+
context: ProjectContext,
|
|
112
|
+
log: BuildLog
|
|
113
|
+
): Promise<void> => {
|
|
114
|
+
const configPath = join(buildOutputDir(context), "config.json");
|
|
115
|
+
if (!existsSync(configPath)) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
await rm(configPath, { force: true });
|
|
119
|
+
log.info(
|
|
120
|
+
"Removed .vercel/output/config.json, so this failed build can't be deployed."
|
|
121
|
+
);
|
|
122
|
+
};
|
|
123
|
+
|
|
102
124
|
/**
|
|
103
125
|
* Splice `Accept: text/markdown` negotiation routes into the adapter's Build
|
|
104
126
|
* Output config, so a content-page request that prefers Markdown gets the
|
|
@@ -299,6 +321,7 @@ export const vercelPlatform: DeployPlatform = {
|
|
|
299
321
|
log
|
|
300
322
|
);
|
|
301
323
|
if (!ok) {
|
|
324
|
+
await withdrawBuildOutput(context, log);
|
|
302
325
|
return false;
|
|
303
326
|
}
|
|
304
327
|
// A verify build moves its static files too, where the budget gate reads
|
|
@@ -310,6 +333,7 @@ export const vercelPlatform: DeployPlatform = {
|
|
|
310
333
|
return true;
|
|
311
334
|
}
|
|
312
335
|
if (!(await rebaseVercelRoutes(project, log))) {
|
|
336
|
+
await withdrawBuildOutput(context, log);
|
|
313
337
|
return false;
|
|
314
338
|
}
|
|
315
339
|
await emitVercelNegotiation(project, log);
|
package/src/deploy/redirects.ts
CHANGED
|
@@ -8,6 +8,11 @@ import {
|
|
|
8
8
|
} from "../core/base-path.ts";
|
|
9
9
|
import { routeSetFor, servesRoute } from "../core/locale-links.ts";
|
|
10
10
|
import type { RouteSet } from "../core/locale-links.ts";
|
|
11
|
+
import {
|
|
12
|
+
MIRROR_EXTENSIONS,
|
|
13
|
+
mirrorName,
|
|
14
|
+
mirrorOwner,
|
|
15
|
+
} from "../core/markdown-mirrors.ts";
|
|
11
16
|
import type { BlumeProject } from "../core/project-graph.ts";
|
|
12
17
|
import {
|
|
13
18
|
compileRedirects,
|
|
@@ -113,29 +118,49 @@ export const applyBaseToPlatformRedirects = (
|
|
|
113
118
|
};
|
|
114
119
|
|
|
115
120
|
/**
|
|
116
|
-
*
|
|
117
|
-
*
|
|
121
|
+
* A path naming an `.html` file (`/guide.html`), the URL another generator
|
|
122
|
+
* served a page at. No Blume page was ever served there, so it had no
|
|
123
|
+
* Markdown copy (`/guide.html.md`) for a redirect to move.
|
|
118
124
|
*/
|
|
119
|
-
const
|
|
125
|
+
const HTML_FILE_PATH = /\.html$/u;
|
|
126
|
+
|
|
127
|
+
/** A path naming a folder's `index.html` (`/guide/index.html`, `/index.html`). */
|
|
128
|
+
const INDEX_FILE_PATH = /^(?<folder>.*)\/index\.html$/u;
|
|
120
129
|
|
|
121
130
|
/**
|
|
122
|
-
*
|
|
123
|
-
*
|
|
131
|
+
* Whether `from` names a page's own `index.html` (`/guide/index.html` for the
|
|
132
|
+
* page `/guide`, `/index.html` for the root), a URL a migrated site may have
|
|
133
|
+
* linked. A static build writes the page there, and Astro writes a redirect
|
|
134
|
+
* page to `<from>/index.html`, which would need that file to be a folder:
|
|
135
|
+
* the build fails with `EISDIR`. Hosts serve the page at that URL anyway,
|
|
136
|
+
* unless a redirect rule answers it first. `pages` are the served page
|
|
137
|
+
* routes, which carry `basePath`, as `from` does.
|
|
124
138
|
*/
|
|
125
|
-
const
|
|
126
|
-
const
|
|
127
|
-
return
|
|
139
|
+
export const isPageIndexFile = (from: string, pages: RouteSet): boolean => {
|
|
140
|
+
const folder = INDEX_FILE_PATH.exec(normalizePath(from))?.groups?.folder;
|
|
141
|
+
return folder !== undefined && servesRoute(pages, folder || "/");
|
|
128
142
|
};
|
|
129
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Where a page's Markdown copy is served, from the page's served path and the
|
|
146
|
+
* deployment base that path carries.
|
|
147
|
+
*/
|
|
148
|
+
const mirrorPath = (path: string, base: string, extension: string): string =>
|
|
149
|
+
`${base}${mirrorName(stripBasePath(base, path))}${extension}`;
|
|
150
|
+
|
|
130
151
|
/**
|
|
131
152
|
* Based `redirects`, each exact one that moves a page followed by the same
|
|
132
|
-
* redirect for the page's Markdown copies: from a path no page
|
|
133
|
-
* to one a page is, `/old.md` goes to `/new.md` (and `.mdx`
|
|
134
|
-
* would otherwise 404 for an agent still reading the old
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
153
|
+
* redirect for the page's Markdown copies: from a path whose copies no page
|
|
154
|
+
* serves to one a page is served at, `/old.md` goes to `/new.md` (and `.mdx`
|
|
155
|
+
* alike), where it would otherwise 404 for an agent still reading the old
|
|
156
|
+
* URL. A served copy never gives way: `/index` names the root's copies, so
|
|
157
|
+
* `/index` → `/` moving them would turn the home page's `/index.md` into a
|
|
158
|
+
* redirect to itself. A pattern gets none; one that carries its capture over
|
|
159
|
+
* (`/beta/:slug*` → `/v2/:slug*`) already moves `/beta/guide.md` along. Nor
|
|
160
|
+
* does a redirect from an `.html` file (`/guide.html`, from a migrated site),
|
|
161
|
+
* which had no copy to move. `pages` are the served page routes (carrying
|
|
162
|
+
* `basePath`, not `deployment.base`), and `bases` the deployment base each
|
|
163
|
+
* end carries: Astro's config leaves it off `from` (see
|
|
139
164
|
* {@link applyBaseToAstroRedirects}).
|
|
140
165
|
*/
|
|
141
166
|
export const withMirrorRedirects = (
|
|
@@ -148,8 +173,10 @@ export const withMirrorRedirects = (
|
|
|
148
173
|
const to = normalizePath(redirect.to);
|
|
149
174
|
const movesPage =
|
|
150
175
|
!isPatternPath(redirect.from) &&
|
|
176
|
+
!HTML_FILE_PATH.test(from) &&
|
|
151
177
|
servesRoute(pages, stripBasePath(bases.to, to)) &&
|
|
152
|
-
|
|
178
|
+
mirrorOwner(pages, mirrorName(stripBasePath(bases.from, from))) ===
|
|
179
|
+
undefined;
|
|
153
180
|
return movesPage
|
|
154
181
|
? [
|
|
155
182
|
redirect,
|
package/src/deploy/sitemap.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
normalizeBasePath,
|
|
12
12
|
normalizePath,
|
|
13
13
|
} from "../core/base-path.ts";
|
|
14
|
+
import { isHiddenPage } from "../core/hidden-pages.ts";
|
|
14
15
|
import type { BlumeProject } from "../core/project-graph.ts";
|
|
15
16
|
import { siteRoot } from "../core/site-url.ts";
|
|
16
17
|
|
|
@@ -163,7 +164,7 @@ export const buildSitemapFiles = (
|
|
|
163
164
|
const served = mountBasePath(deployBase, page.route);
|
|
164
165
|
if (
|
|
165
166
|
page.meta.draft ||
|
|
166
|
-
page.
|
|
167
|
+
isHiddenPage(page, project.graph) ||
|
|
167
168
|
page.meta.seo.noindex ||
|
|
168
169
|
ERROR_ROUTES.has(page.route) ||
|
|
169
170
|
archivedExcluded(page) ||
|
|
@@ -4,22 +4,51 @@ import {
|
|
|
4
4
|
withBasePath,
|
|
5
5
|
} from "../core/base-path.ts";
|
|
6
6
|
import { servesRoute } from "../core/locale-links.ts";
|
|
7
|
-
import
|
|
7
|
+
import { rewriteElementUrls } from "../core/sources/normalize.ts";
|
|
8
|
+
import type { MdastNode, MdastValue } from "./mdast.ts";
|
|
8
9
|
import { routeSnapshotReader } from "./route-snapshot.ts";
|
|
9
10
|
|
|
10
11
|
interface UrlNode extends MdastNode {
|
|
11
12
|
url?: string | null;
|
|
12
13
|
}
|
|
13
14
|
|
|
15
|
+
/** Raw HTML in a `.md` page. */
|
|
16
|
+
interface HtmlNode extends MdastNode {
|
|
17
|
+
value: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** An MDX JSX attribute, as the plugin reads it. */
|
|
21
|
+
interface JsxAttribute {
|
|
22
|
+
[key: string]: MdastValue;
|
|
23
|
+
name?: string;
|
|
24
|
+
type?: string;
|
|
25
|
+
value?: MdastValue;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** An MDX JSX element (`<a href="/guide">`), as the plugin reads it. */
|
|
29
|
+
interface JsxNode extends MdastNode {
|
|
30
|
+
attributes?: JsxAttribute[];
|
|
31
|
+
children?: MdastValue[];
|
|
32
|
+
name?: string | null;
|
|
33
|
+
}
|
|
34
|
+
|
|
14
35
|
/**
|
|
15
36
|
* The slice of Satteri's MDAST visitor context this plugin needs. Nodes are
|
|
16
37
|
* read-only (the tree compiles to an op-stream), so a URL edit is recorded via
|
|
17
38
|
* `setProperty`, not by mutating the node object.
|
|
18
39
|
*/
|
|
19
40
|
interface MdastUrlContext {
|
|
20
|
-
|
|
41
|
+
replaceNode: (node: MdastNode, replacement: MdastNode) => void;
|
|
42
|
+
setProperty: (node: MdastNode, key: "url" | "value", value: string) => void;
|
|
21
43
|
}
|
|
22
44
|
|
|
45
|
+
/** An HTML element's name, as opposed to a component's (`Card`). */
|
|
46
|
+
const HTML_ELEMENT = /^[a-z]/u;
|
|
47
|
+
|
|
48
|
+
/** A plain string attribute value; an expression value isn't a URL. */
|
|
49
|
+
const isStringValue = (value: MdastValue): value is string =>
|
|
50
|
+
typeof value === "string";
|
|
51
|
+
|
|
23
52
|
/** Only a string URL can be rebased; MDAST allows null or absent urls. */
|
|
24
53
|
const isUrl = (url: string | null | undefined): url is string =>
|
|
25
54
|
typeof url === "string";
|
|
@@ -53,10 +82,14 @@ export interface BaseLinksPluginOptions {
|
|
|
53
82
|
* gains `deployment.base` layered over the site-wide `basePath` (`[x](/guide)`
|
|
54
83
|
* -> `/base/docs/guide`); a public asset — an image, or a link to a file like
|
|
55
84
|
* `/spec.pdf` (see `withAuthoredBasePath`) — gains `deployment.base` alone,
|
|
56
|
-
* since Astro serves `public/` under it but never under `basePath`.
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
85
|
+
* since Astro serves `public/` under it but never under `basePath`. A raw
|
|
86
|
+
* HTML element's `href` or `src` (`<a href="/guide">`, `<img src="/x.png">`,
|
|
87
|
+
* in a `.md` page or as an `.mdx` element) gains `deployment.base` alone: the
|
|
88
|
+
* whole site moves under it, but a raw `href` keeps no `basePath`, as
|
|
89
|
+
* `blume validate` reads it. Idempotent per layer (a hand-written `/docs/x`
|
|
90
|
+
* isn't double-prefixed) and inert for external URLs, fragments, and
|
|
91
|
+
* relative paths. Only constructed when a base is set (see
|
|
92
|
+
* `markdown/index.ts`).
|
|
60
93
|
*/
|
|
61
94
|
export const baseLinksPlugin = (
|
|
62
95
|
deployBase: string,
|
|
@@ -95,12 +128,60 @@ export const baseLinksPlugin = (
|
|
|
95
128
|
// endpoint), served under the deployment base but not `basePath`.
|
|
96
129
|
const rebaseImage = (node: UrlNode, ctx: MdastUrlContext): void =>
|
|
97
130
|
rebase(node, ctx, (url) => withBasePath(deployBase, url));
|
|
131
|
+
|
|
132
|
+
/** A raw element's root-relative URL under the deployment base, if it moves. */
|
|
133
|
+
const based = (url: string): string | null => {
|
|
134
|
+
const next = withBasePath(deployBase, url);
|
|
135
|
+
return next === url ? null : next;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const rebaseHtml = (node: HtmlNode, ctx: MdastUrlContext): void => {
|
|
139
|
+
const next = rewriteElementUrls(node.value, ({ value }) => based(value));
|
|
140
|
+
if (next !== node.value) {
|
|
141
|
+
ctx.setProperty(node, "value", next);
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const rebaseElement = (node: JsxNode, ctx: MdastUrlContext): void => {
|
|
146
|
+
if (!(node.name && HTML_ELEMENT.test(node.name))) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
let changed = false;
|
|
150
|
+
const attributes = (node.attributes ?? []).map((attribute) => {
|
|
151
|
+
const { name, value } = attribute;
|
|
152
|
+
const next =
|
|
153
|
+
attribute.type === "mdxJsxAttribute" &&
|
|
154
|
+
(name === "href" || name === "src") &&
|
|
155
|
+
isStringValue(value)
|
|
156
|
+
? based(value)
|
|
157
|
+
: null;
|
|
158
|
+
if (next === null) {
|
|
159
|
+
return attribute;
|
|
160
|
+
}
|
|
161
|
+
changed = true;
|
|
162
|
+
return { name, type: attribute.type, value: next };
|
|
163
|
+
});
|
|
164
|
+
if (changed) {
|
|
165
|
+
// Sätteri can't set a JSX element's attributes in place, so the element
|
|
166
|
+
// is swapped for a copy; its children carry over and are still visited.
|
|
167
|
+
ctx.replaceNode(node, {
|
|
168
|
+
attributes,
|
|
169
|
+
children: node.children ?? [],
|
|
170
|
+
name: node.name,
|
|
171
|
+
type: node.type,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
|
|
98
176
|
// `link` covers inline links; `definition` covers reference-style
|
|
99
177
|
// definitions (`[x]: /guide`), which a link or an image may cite.
|
|
100
178
|
return {
|
|
101
179
|
definition: rebaseLink,
|
|
180
|
+
html: rebaseHtml,
|
|
102
181
|
image: rebaseImage,
|
|
103
182
|
link: rebaseLink,
|
|
183
|
+
mdxJsxFlowElement: rebaseElement,
|
|
184
|
+
mdxJsxTextElement: rebaseElement,
|
|
104
185
|
name: "blume-base-links",
|
|
105
186
|
};
|
|
106
187
|
};
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Code-fence meta. A Shiki transformer reads the tokens after the language and
|
|
3
3
|
* promotes them to attributes on the rendered `<pre>`:
|
|
4
4
|
*
|
|
5
|
-
* - a title — the
|
|
6
|
-
* becomes `data-title`; the theme's code header
|
|
7
|
-
* language label.
|
|
5
|
+
* - a title — the bare words (```ts blume.config.ts, ```js Install the
|
|
6
|
+
* client) or `title="..."` — becomes `data-title`; the theme's code header
|
|
7
|
+
* shows it, falling back to the language label.
|
|
8
8
|
* - the `lineNumbers` keyword (```ts file.ts lineNumbers) becomes
|
|
9
9
|
* `data-line-numbers`; the theme renders a counter-driven line-number gutter.
|
|
10
10
|
* - the `wrap` keyword becomes `data-wrap`: this block's long lines wrap
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
import {
|
|
19
|
+
isForeignKeyword,
|
|
19
20
|
isLineRange,
|
|
20
21
|
metaTokens,
|
|
21
22
|
QUOTED_ATTR,
|
|
@@ -33,7 +34,7 @@ export const EXPANDABLE_MIN_LINES = 16;
|
|
|
33
34
|
|
|
34
35
|
/** The slice of Shiki's transformer `this` context Blume reads. */
|
|
35
36
|
interface CodeMetaContext {
|
|
36
|
-
options: { meta?: { __raw?: string } };
|
|
37
|
+
options: { lang?: string; meta?: { __raw?: string } };
|
|
37
38
|
/** The block's code, as highlighted. */
|
|
38
39
|
source?: string;
|
|
39
40
|
}
|
|
@@ -51,17 +52,29 @@ export interface CodeTitleTransformer {
|
|
|
51
52
|
|
|
52
53
|
const TITLE_ATTR = /(?:^|\s)title=(?:"(?<dq>[^"]*)"|'(?<sq>[^']*)')/u;
|
|
53
54
|
|
|
54
|
-
// The
|
|
55
|
-
// that isn't a Shiki line range (`{1,3-5}`), a
|
|
56
|
-
// keyword
|
|
57
|
-
|
|
55
|
+
// The bare words are the title (```ts blume.config.ts, ```js Install the
|
|
56
|
+
// client): every token that isn't a Shiki line range (`{1,3-5}`), a
|
|
57
|
+
// `key=value` attr, a reserved keyword, or another tool's keyword for a
|
|
58
|
+
// fence in `lang` (```rust ignore).
|
|
59
|
+
const isTitleToken = (token: string, lang: string | undefined): boolean =>
|
|
58
60
|
token.length > 0 &&
|
|
59
61
|
!isLineRange(token) &&
|
|
60
62
|
!token.includes("=") &&
|
|
61
|
-
!RESERVED_META_KEYWORDS.has(token)
|
|
63
|
+
!RESERVED_META_KEYWORDS.has(token) &&
|
|
64
|
+
!isForeignKeyword(token, lang);
|
|
62
65
|
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
// A title wrapped in one pair of brackets (```ts [file.ts], the Docus and
|
|
67
|
+
// VitePress code-group spelling) shows without them.
|
|
68
|
+
const BRACKETED_TITLE = /^\[(?<inner>[^\]]+)\]$/u;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The title a fence's meta string promotes to `data-title`, if any. `lang` is
|
|
72
|
+
* the fence's language, which decides the other tools' keywords it drops.
|
|
73
|
+
*/
|
|
74
|
+
export const parseCodeTitle = (
|
|
75
|
+
raw: string | undefined,
|
|
76
|
+
lang?: string
|
|
77
|
+
): string | undefined => {
|
|
65
78
|
if (!raw) {
|
|
66
79
|
return undefined;
|
|
67
80
|
}
|
|
@@ -79,7 +92,10 @@ export const parseCodeTitle = (raw: string | undefined): string | undefined => {
|
|
|
79
92
|
// The shared tokenizer keeps a quoted attr (rejected below by its `=`) and
|
|
80
93
|
// a spaced line range (`{1, 3-5}`) whole, so neither can shed a fragment
|
|
81
94
|
// that reads as a bare title.
|
|
82
|
-
|
|
95
|
+
const title = metaTokens(raw)
|
|
96
|
+
.filter((token) => isTitleToken(token, lang))
|
|
97
|
+
.join(" ");
|
|
98
|
+
return BRACKETED_TITLE.exec(title)?.groups?.inner ?? (title || undefined);
|
|
83
99
|
};
|
|
84
100
|
|
|
85
101
|
// The shared tokenizer keeps a quoted attr whole, so a keyword inside a
|
|
@@ -96,7 +112,7 @@ export const codeTitleTransformer = (): CodeTitleTransformer => ({
|
|
|
96
112
|
name: "blume:code-meta",
|
|
97
113
|
pre(node) {
|
|
98
114
|
const raw = this.options.meta?.__raw;
|
|
99
|
-
const title = parseCodeTitle(raw);
|
|
115
|
+
const title = parseCodeTitle(raw, this.options.lang);
|
|
100
116
|
if (title) {
|
|
101
117
|
node.properties.dataTitle = title;
|
|
102
118
|
}
|