blume 2.0.2 → 2.1.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 -0
- package/CHANGELOG.md +113 -0
- package/README.md +1 -1
- package/dist/cli/{chunk-6k4ftwze.js → chunk-0gz36akr.js} +18 -2
- package/dist/cli/{chunk-6k4ftwze.js.map → chunk-0gz36akr.js.map} +3 -3
- package/dist/cli/{chunk-zp79m0ts.js → chunk-1n228xqb.js} +2 -2
- package/dist/cli/{chunk-ddndchfr.js → chunk-2f3ndkpw.js} +57 -29
- package/dist/cli/chunk-2f3ndkpw.js.map +14 -0
- package/dist/cli/{chunk-fsmrqk8a.js → chunk-2f7n4qzt.js} +8 -2
- package/dist/cli/{chunk-fsmrqk8a.js.map → chunk-2f7n4qzt.js.map} +3 -3
- package/dist/cli/{chunk-ppzjqwx2.js → chunk-2n4ps1b3.js} +17 -18
- package/dist/cli/{chunk-ppzjqwx2.js.map → chunk-2n4ps1b3.js.map} +3 -3
- package/dist/cli/{chunk-5r8g91qn.js → chunk-43zcf4gz.js} +398 -159
- package/dist/cli/chunk-43zcf4gz.js.map +36 -0
- package/dist/cli/chunk-4ejxbzee.js +39 -0
- package/dist/cli/chunk-4ejxbzee.js.map +10 -0
- package/dist/cli/{chunk-hr8ne106.js → chunk-4h8z9vv5.js} +296 -77
- package/dist/cli/chunk-4h8z9vv5.js.map +16 -0
- package/dist/cli/{chunk-k7pj68a8.js → chunk-5cg2rzgf.js} +18 -16
- package/dist/cli/{chunk-k7pj68a8.js.map → chunk-5cg2rzgf.js.map} +2 -2
- package/dist/cli/{chunk-h2ez8dzb.js → chunk-5ffywsmb.js} +4 -4
- package/dist/cli/{chunk-g698a744.js → chunk-5wj2qwn2.js} +5 -5
- package/dist/cli/chunk-6bm0xpgd.js +18 -0
- package/dist/cli/chunk-6bm0xpgd.js.map +10 -0
- package/dist/cli/{chunk-3yce002v.js → chunk-713mngdq.js} +15 -8
- package/dist/cli/chunk-713mngdq.js.map +14 -0
- package/dist/cli/{chunk-91ws1n6j.js → chunk-9geymqns.js} +17 -15
- package/dist/cli/{chunk-91ws1n6j.js.map → chunk-9geymqns.js.map} +2 -2
- package/dist/cli/{chunk-6dtt0zfn.js → chunk-9xr4dgee.js} +27 -18
- package/dist/cli/chunk-9xr4dgee.js.map +10 -0
- package/dist/cli/{chunk-sqw4ekg1.js → chunk-amrb6hgh.js} +2 -2
- package/dist/cli/chunk-cm89scdv.js +443 -0
- package/dist/cli/chunk-cm89scdv.js.map +11 -0
- package/dist/cli/{chunk-wdrt2k2v.js → chunk-cmtcnh9f.js} +90 -26
- package/dist/cli/chunk-cmtcnh9f.js.map +10 -0
- package/dist/cli/chunk-cy5bm0j0.js +104 -0
- package/dist/cli/chunk-cy5bm0j0.js.map +11 -0
- package/dist/cli/{chunk-7mbqtmgb.js → chunk-e7vvk5ya.js} +21 -12
- package/dist/cli/chunk-e7vvk5ya.js.map +10 -0
- package/dist/cli/{chunk-qkb5a8sa.js → chunk-g2z9x01v.js} +6 -98
- package/dist/cli/chunk-g2z9x01v.js.map +10 -0
- package/dist/cli/{chunk-273ygyr4.js → chunk-ga0pf4aj.js} +7 -7
- package/dist/cli/{chunk-273ygyr4.js.map → chunk-ga0pf4aj.js.map} +3 -3
- package/dist/cli/{chunk-h7k3nq3v.js → chunk-gp84za0h.js} +2 -2
- package/dist/cli/{chunk-hqp2ajnh.js → chunk-h2a48yhd.js} +195 -73
- package/dist/cli/chunk-h2a48yhd.js.map +36 -0
- package/dist/cli/{chunk-pbg5a4s3.js → chunk-jnwj5kjj.js} +71 -47
- package/dist/cli/chunk-jnwj5kjj.js.map +19 -0
- package/dist/cli/chunk-kwrg63tm.js +31 -0
- package/dist/cli/chunk-kwrg63tm.js.map +10 -0
- package/dist/cli/{chunk-8g8ytmgx.js → chunk-nd1821sk.js} +21 -19
- package/dist/cli/{chunk-8g8ytmgx.js.map → chunk-nd1821sk.js.map} +2 -2
- package/dist/cli/{chunk-w4bxdvsa.js → chunk-ntv4qrt7.js} +17 -15
- package/dist/cli/{chunk-w4bxdvsa.js.map → chunk-ntv4qrt7.js.map} +2 -2
- package/dist/cli/{chunk-bfwp9vp6.js → chunk-p804f3pe.js} +7 -7
- package/dist/cli/{chunk-4e9b9ra6.js → chunk-py62fewh.js} +6 -6
- package/dist/cli/{chunk-4e9b9ra6.js.map → chunk-py62fewh.js.map} +1 -1
- package/dist/cli/chunk-q3wxxq39.js +126 -0
- package/dist/cli/chunk-q3wxxq39.js.map +11 -0
- package/dist/cli/{chunk-j85scx15.js → chunk-rekqz4qg.js} +142 -46
- package/dist/cli/chunk-rekqz4qg.js.map +10 -0
- package/dist/cli/{chunk-00gs3wqs.js → chunk-ta27feev.js} +1 -1
- package/dist/cli/{chunk-v6ya5kcb.js → chunk-xkz5xbtv.js} +4031 -1132
- package/dist/cli/chunk-xkz5xbtv.js.map +213 -0
- package/dist/cli/{chunk-bbnwccaz.js → chunk-y4ykbark.js} +2 -2
- package/dist/cli/{chunk-n1yg3tj3.js → chunk-y5h4r2y0.js} +6 -6
- package/dist/cli/{chunk-n1yg3tj3.js.map → chunk-y5h4r2y0.js.map} +3 -3
- package/dist/cli/{chunk-nfcyttvj.js → chunk-yj17vs39.js} +9 -9
- package/dist/cli/{chunk-nfcyttvj.js.map → chunk-yj17vs39.js.map} +1 -1
- package/dist/cli/{chunk-7vtckvaw.js → chunk-yxmk4pec.js} +16 -14
- package/dist/cli/{chunk-7vtckvaw.js.map → chunk-yxmk4pec.js.map} +2 -2
- package/dist/cli/{chunk-gs7r695n.js → chunk-zccbjcj0.js} +22 -8
- package/dist/cli/{chunk-gs7r695n.js.map → chunk-zccbjcj0.js.map} +3 -3
- package/dist/cli/{chunk-xh43dwgw.js → chunk-zf748avv.js} +415 -225
- package/dist/cli/chunk-zf748avv.js.map +37 -0
- package/dist/cli/{chunk-d1v5rhy0.js → chunk-zhvd6adm.js} +16 -14
- package/dist/cli/{chunk-d1v5rhy0.js.map → chunk-zhvd6adm.js.map} +2 -2
- package/dist/cli/index.js +28 -20
- package/dist/cli/index.js.map +5 -5
- package/dist/types/ai/agent-surface.d.ts +8 -7
- package/dist/types/ai/ai-catalog.d.ts +7 -0
- package/dist/types/ai/ask-context.d.ts +22 -0
- package/dist/types/ai/ask.d.ts +271 -58
- package/dist/types/ai/index.d.ts +2 -2
- package/dist/types/ai/link-headers.d.ts +8 -1
- package/dist/types/ai/openapi-components.d.ts +5 -2
- package/dist/types/ai/relative-links.d.ts +9 -7
- package/dist/types/ai/site-skill.d.ts +26 -0
- package/dist/types/ai/skills.d.ts +20 -1
- package/dist/types/ai/tar.d.ts +1 -3
- package/dist/types/analytics/index.d.ts +2 -0
- package/dist/types/analytics/one-dollar-stats.d.ts +48 -0
- package/dist/types/analytics/schema.d.ts +14 -0
- package/dist/types/astro/integration.d.ts +11 -2
- package/dist/types/captcha/hcaptcha.d.ts +27 -0
- package/dist/types/captcha/index.d.ts +28 -0
- package/dist/types/captcha/schema.d.ts +29 -0
- package/dist/types/captcha/turnstile.d.ts +28 -0
- package/dist/types/components/content/api-field.d.ts +59 -0
- package/dist/types/components/content/api-page.d.ts +95 -0
- package/dist/types/components/layout/nav-utils.d.ts +26 -0
- package/dist/types/components/openapi/helpers.d.ts +137 -0
- package/dist/types/components/openapi/security.d.ts +85 -0
- package/dist/types/consent/ethyca.d.ts +48 -0
- package/dist/types/consent/index.d.ts +37 -0
- package/dist/types/consent/native.d.ts +28 -0
- package/dist/types/consent/osano.d.ts +42 -0
- package/dist/types/consent/schema.d.ts +110 -0
- package/dist/types/core/base-path.d.ts +21 -7
- package/dist/types/core/config-input.d.ts +196 -27
- package/dist/types/core/data.d.ts +49 -4
- package/dist/types/core/directive-diagnostics.d.ts +12 -0
- package/dist/types/core/footer.d.ts +8 -0
- package/dist/types/core/heading-markers.d.ts +5 -7
- package/dist/types/core/i18n-ui.d.ts +86 -0
- package/dist/types/core/i18n.d.ts +2 -0
- package/dist/types/core/includes.d.ts +8 -2
- package/dist/types/core/last-modified.d.ts +10 -0
- package/dist/types/core/localizable.d.ts +7 -0
- package/dist/types/core/meta.d.ts +8 -0
- package/dist/types/core/page-modes.d.ts +29 -0
- package/dist/types/core/redirect-patterns.d.ts +144 -0
- package/dist/types/core/related.d.ts +40 -0
- package/dist/types/core/schema.d.ts +558 -56
- package/dist/types/core/sources/lower.d.ts +29 -16
- package/dist/types/core/sources/normalize.d.ts +13 -1
- package/dist/types/core/sources/read.d.ts +5 -0
- package/dist/types/core/sources/watch.d.ts +12 -5
- package/dist/types/core/standard-schema.d.ts +5 -0
- package/dist/types/core/types.d.ts +1 -1
- package/dist/types/core/variables.d.ts +42 -0
- package/dist/types/deploy/artifacts.d.ts +6 -4
- package/dist/types/deploy/headers.d.ts +5 -0
- package/dist/types/deploy/node-headers.d.ts +13 -2
- package/dist/types/deploy/platforms/cloudflare.d.ts +5 -0
- package/dist/types/deploy/platforms/netlify.d.ts +7 -0
- package/dist/types/deploy/platforms/types.d.ts +8 -0
- package/dist/types/deploy/platforms/vercel.d.ts +6 -0
- package/dist/types/deploy/redirects.d.ts +61 -22
- package/dist/types/deploy/vercel-negotiation.d.ts +9 -0
- package/dist/types/markdown/code-title.d.ts +17 -0
- package/dist/types/markdown/directives.d.ts +62 -0
- package/dist/types/markdown/features.d.ts +24 -2
- package/dist/types/markdown/mdast.d.ts +63 -0
- package/dist/types/narration/build.d.ts +70 -0
- package/dist/types/narration/provider.d.ts +26 -0
- package/dist/types/narration/script.d.ts +154 -0
- package/dist/types/openapi/asyncapi.d.ts +4 -2
- package/dist/types/openapi/model.d.ts +12 -6
- package/dist/types/openapi/overlay.d.ts +54 -0
- package/dist/types/openapi/parse.d.ts +13 -0
- package/dist/types/openapi/references.d.ts +14 -4
- package/dist/types/ratelimit/cloudflare.d.ts +39 -0
- package/dist/types/ratelimit/index.d.ts +27 -0
- package/dist/types/ratelimit/memory.d.ts +36 -0
- package/dist/types/ratelimit/schema.d.ts +111 -0
- package/dist/types/ratelimit/upstash.d.ts +21 -0
- package/dist/types/ratelimit/wrangler.d.ts +23 -0
- package/dist/types/reference/asyncapi.d.ts +10 -10
- package/dist/types/reference/graphql.d.ts +13 -10
- package/dist/types/reference/openapi.d.ts +33 -12
- package/dist/types/reference/options.d.ts +45 -5
- package/dist/types/reference/scalar.d.ts +13 -0
- package/dist/types/reference/schema.d.ts +60 -36
- package/dist/types/search/documents.d.ts +12 -1
- package/dist/types/search/orama-index.d.ts +4 -0
- package/dist/types/seo/metatags.d.ts +20 -0
- package/docs/02-deployment.mdx +44 -6
- package/docs/03-upgrading.mdx +4 -4
- package/docs/04-migrating.mdx +1 -1
- package/docs/08-faq.mdx +1 -1
- package/docs/advanced/changelog.mdx +2 -2
- package/docs/advanced/custom-pages.mdx +3 -3
- package/docs/advanced/skills.mdx +14 -0
- package/docs/cli/audit.mdx +38 -2
- package/docs/cli/evals.mdx +3 -3
- package/docs/cli/index.mdx +1 -0
- package/docs/cli/translate.mdx +3 -3
- package/docs/cli/version.mdx +1 -1
- package/docs/configuration/analytics.mdx +22 -1
- package/docs/configuration/assistant.mdx +188 -36
- package/docs/configuration/consent.mdx +100 -0
- package/docs/configuration/customization.mdx +6 -4
- package/docs/configuration/index.mdx +63 -5
- package/docs/configuration/meta.ts +3 -0
- package/docs/configuration/narration.mdx +119 -0
- package/docs/configuration/rate-limiting.mdx +69 -0
- package/docs/configuration/search.mdx +30 -2
- package/docs/configuration/theming.mdx +3 -1
- package/docs/content/components.mdx +107 -1
- package/docs/content/frontmatter.mdx +77 -1
- package/docs/content/i18n.mdx +40 -3
- package/docs/content/includes.mdx +16 -0
- package/docs/content/index.mdx +4 -2
- package/docs/content/islands.mdx +1 -1
- package/docs/content/meta.mdx +4 -1
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +28 -6
- package/docs/content/sources/contentful.mdx +32 -0
- package/docs/content/sources/custom.mdx +39 -0
- package/docs/content/sources/github-releases.mdx +31 -0
- package/docs/content/sources/index.mdx +91 -0
- package/docs/content/sources/meta.ts +16 -0
- package/docs/content/sources/notion.mdx +32 -0
- package/docs/content/sources/obsidian.mdx +37 -0
- package/docs/content/sources/payload.mdx +30 -0
- package/docs/content/sources/remote-mdx.mdx +40 -0
- package/docs/content/sources/sanity.mdx +29 -0
- package/docs/content/sources/strapi.mdx +31 -0
- package/docs/content/syntax.mdx +81 -2
- package/docs/content/variables.mdx +41 -0
- package/docs/content/versioning.mdx +1 -1
- package/docs/discoverability/agent-discovery.mdx +30 -3
- package/docs/discoverability/index.mdx +3 -2
- package/docs/discoverability/llms-txt.mdx +1 -1
- package/docs/discoverability/markdown.mdx +2 -2
- package/docs/discoverability/metadata.mdx +17 -0
- package/docs/discoverability/open-graph.mdx +5 -3
- package/docs/discoverability/rss.mdx +1 -1
- package/docs/references/api-pages.mdx +74 -0
- package/docs/references/asyncapi.mdx +2 -2
- package/docs/references/graphql.mdx +3 -3
- package/docs/references/meta.ts +1 -1
- package/docs/references/openapi.mdx +106 -5
- package/docs/references/scalar.mdx +3 -1
- package/package.json +36 -1
- package/skills/blume/SKILL.md +3 -0
- package/skills/blume-migrate/SKILL.md +5 -5
- package/skills/blume-migrate/references/docusaurus.md +3 -3
- package/skills/blume-migrate/references/fumadocs.md +1 -1
- package/skills/blume-migrate/references/mintlify.md +37 -19
- package/skills/blume-migrate/references/nextra.md +3 -3
- package/skills/blume-migrate/references/starlight.md +2 -1
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +67 -16
- package/skills/blume-write-skill/SKILL.md +82 -0
- package/src/ai/agent-readability.ts +4 -3
- package/src/ai/agent-surface.ts +9 -7
- package/src/ai/ai-catalog.ts +12 -5
- package/src/ai/api/handlers.ts +2 -2
- package/src/ai/api/spec.ts +2 -2
- package/src/ai/api-catalog.ts +6 -2
- package/src/ai/ask-context.ts +73 -20
- package/src/ai/ask-data.ts +6 -0
- package/src/ai/ask-tools.ts +142 -0
- package/src/ai/ask.ts +354 -76
- package/src/ai/changelog-markdown.ts +2 -2
- package/src/ai/component-markdown.ts +75 -0
- package/src/ai/cors.ts +2 -0
- package/src/ai/index.ts +12 -0
- package/src/ai/link-headers.ts +14 -5
- package/src/ai/llms.ts +24 -9
- package/src/ai/markdown.ts +2 -1
- package/src/ai/mcp/data.ts +6 -0
- package/src/ai/mcp/discovery.ts +2 -2
- package/src/ai/mcp/query.ts +2 -2
- package/src/ai/mcp/server.ts +2 -2
- package/src/ai/openapi-components.ts +31 -9
- package/src/ai/relative-links.ts +42 -26
- package/src/ai/serializers.ts +2 -1
- package/src/ai/site-skill.ts +274 -0
- package/src/ai/skills.ts +49 -3
- package/src/ai/tar.ts +139 -12
- package/src/ai/write-skill.ts +97 -0
- package/src/analytics/head.ts +4 -0
- package/src/analytics/index.ts +5 -0
- package/src/analytics/one-dollar-stats.ts +86 -0
- package/src/analytics/schema.ts +2 -0
- package/src/astro/generate.ts +133 -19
- package/src/astro/include-hmr.ts +31 -12
- package/src/astro/include-refresh.ts +19 -8
- package/src/astro/index.ts +1 -0
- package/src/astro/integration.ts +143 -14
- package/src/astro/module-types.ts +6 -0
- package/src/astro/runtime-modules.ts +28 -13
- package/src/astro/templates.ts +364 -67
- package/src/astro/variables.ts +31 -0
- package/src/audit/catalog.ts +19 -0
- package/src/audit/checks/contrast.ts +183 -0
- package/src/audit/checks/i18n.ts +2 -3
- package/src/audit/checks/indexability.ts +2 -3
- package/src/audit/checks/links.ts +13 -13
- package/src/audit/checks/sitemap.ts +2 -3
- package/src/audit/graph.ts +3 -1
- package/src/audit/redirects.ts +46 -15
- package/src/audit/run.ts +14 -9
- package/src/audit/snapshot.ts +5 -0
- package/src/audit/types.ts +2 -1
- package/src/blume-modules.d.ts +7 -0
- package/src/captcha/client.ts +152 -0
- package/src/captcha/hcaptcha.ts +36 -0
- package/src/captcha/index.ts +28 -0
- package/src/captcha/schema.ts +32 -0
- package/src/captcha/turnstile.ts +38 -0
- package/src/captcha/verify.ts +71 -0
- package/src/cli/args.ts +32 -0
- package/src/cli/command-meta.ts +5 -0
- package/src/cli/commands/audit.ts +4 -1
- package/src/cli/commands/doctor.ts +25 -17
- package/src/cli/commands/eval.ts +19 -11
- package/src/cli/commands/skill.ts +96 -0
- package/src/cli/commands/translate.ts +9 -12
- package/src/cli/commands/validate.ts +3 -1
- package/src/cli/dev-lock.ts +157 -37
- package/src/cli/index.ts +5 -0
- package/src/cli/report-format.ts +11 -6
- package/src/cli/required-secrets.ts +71 -29
- package/src/components/BlumePage.astro +2 -0
- package/src/components/colors.ts +19 -0
- package/src/components/content/ApiEndpoint.astro +18 -0
- package/src/components/content/ApiField.astro +79 -0
- package/src/components/content/ApiPlayground.astro +62 -0
- package/src/components/content/ApiRail.astro +19 -0
- package/src/components/content/Badge.astro +5 -3
- package/src/components/content/Color.astro +1 -0
- package/src/components/content/Component.astro +2 -2
- package/src/components/content/FileTree.astro +1 -0
- package/src/components/content/GithubInfo.astro +1 -0
- package/src/components/content/Panel.astro +1 -0
- package/src/components/content/ParamField.astro +25 -0
- package/src/components/content/RequestExample.astro +17 -0
- package/src/components/content/ResponseExample.astro +17 -0
- package/src/components/content/ResponseField.astro +32 -0
- package/src/components/content/Step.astro +1 -0
- package/src/components/content/Tab.astro +0 -1
- package/src/components/content/Tabs.astro +4 -0
- package/src/components/content/Tile.astro +1 -0
- package/src/components/content/Tooltip.astro +1 -0
- package/src/components/content/Tree.astro +1 -0
- package/src/components/content/TypeTable.astro +4 -1
- package/src/components/content/View.astro +21 -0
- package/src/components/content/ViewSwitcher.astro +168 -0
- package/src/components/content/api-field.ts +100 -0
- package/src/components/content/api-page.ts +224 -0
- package/src/components/content/badge-color.ts +5 -2
- package/src/components/content/base-href.ts +13 -36
- package/src/components/content/view-switcher.ts +71 -0
- package/src/components/index.ts +2 -0
- package/src/components/islands/Assistant.astro +10 -1
- package/src/components/islands/assistant.tsx +125 -18
- package/src/components/islands/base-path.ts +47 -10
- package/src/components/islands/code-question.ts +62 -0
- package/src/components/islands/hooks.ts +145 -40
- package/src/components/islands/support-link.ts +68 -0
- package/src/components/islands/webmcp.ts +4 -2
- package/src/components/layout/Analytics.astro +11 -2
- package/src/components/layout/Banner.astro +14 -10
- package/src/components/layout/Breadcrumbs.astro +11 -4
- package/src/components/layout/ConsentBanner.astro +62 -0
- package/src/components/layout/ConsentHead.astro +38 -0
- package/src/components/layout/Directory.astro +94 -0
- package/src/components/layout/DiscoveryLinks.astro +9 -5
- package/src/components/layout/DrawerSwitchers.astro +51 -0
- package/src/components/layout/Empty.astro +2 -2
- package/src/components/layout/Header.astro +124 -82
- package/src/components/layout/LanguageSwitcher.astro +50 -17
- package/src/components/layout/NarrationPlayer.astro +1085 -0
- package/src/components/layout/NavSelector.astro +35 -9
- package/src/components/layout/NavTabMenu.astro +3 -3
- package/src/components/layout/NavTree.astro +16 -6
- package/src/components/layout/PageActions.astro +4 -3
- package/src/components/layout/PageFeedback.astro +54 -49
- package/src/components/layout/PageLayout.astro +78 -9
- package/src/components/layout/Pagination.astro +3 -3
- package/src/components/layout/ReferenceLayout.astro +17 -6
- package/src/components/layout/RelatedPages.astro +42 -0
- package/src/components/layout/RootLayout.astro +313 -50
- package/src/components/layout/Search.astro +64 -30
- package/src/components/layout/SiteFooter.astro +124 -0
- package/src/components/layout/SiteMetatags.astro +16 -0
- package/src/components/layout/VersionBanner.astro +2 -2
- package/src/components/layout/analytics-client.ts +12 -0
- package/src/components/layout/consent/native.ts +79 -0
- package/src/components/layout/consent/types.ts +37 -0
- package/src/components/layout/footer-links.ts +53 -0
- package/src/components/layout/footer-socials.ts +87 -0
- package/src/components/layout/locale-redirect.ts +107 -0
- package/src/components/layout/nav-utils.ts +83 -0
- package/src/components/layout/page-feedback.ts +96 -0
- package/src/components/layout/search/analytics.ts +98 -0
- package/src/components/layout/search/flexsearch.ts +17 -5
- package/src/components/layout/search/orama-cloud.ts +26 -14
- package/src/components/layout/search/types.ts +20 -0
- package/src/components/layout/search/typesense.ts +5 -1
- package/src/components/layout/toc-active.ts +41 -0
- package/src/components/layout/toc-element.ts +8 -14
- package/src/components/openapi/ApiTagOperations.astro +2 -2
- package/src/components/openapi/AsyncApiOperation.astro +7 -4
- package/src/components/openapi/GraphqlChip.astro +2 -2
- package/src/components/openapi/Operation.astro +163 -13
- package/src/components/openapi/Playground.astro +4 -4
- package/src/components/openapi/RequestBody.astro +6 -4
- package/src/components/openapi/RequestPanel.astro +63 -8
- package/src/components/openapi/Responses.astro +6 -4
- package/src/components/openapi/SchemaTable.astro +7 -0
- package/src/components/openapi/async-snippets.ts +4 -4
- package/src/components/openapi/async.ts +38 -6
- package/src/components/openapi/code-samples.ts +97 -0
- package/src/components/openapi/helpers.ts +19 -9
- package/src/components/openapi/message-composer.ts +6 -1
- package/src/components/openapi/message.ts +17 -2
- package/src/components/openapi/operation-model.ts +81 -11
- package/src/components/openapi/panel.ts +4 -2
- package/src/components/openapi/param-style.ts +181 -0
- package/src/components/openapi/playground-client.ts +73 -16
- package/src/components/openapi/request.ts +190 -26
- package/src/components/openapi/schema-tree.ts +30 -24
- package/src/components/openapi/security.ts +6 -3
- package/src/components/openapi/snippets.ts +953 -13
- package/src/components/openapi/ws-client.ts +18 -2
- package/src/components/props.ts +6 -0
- package/src/consent/client.ts +95 -0
- package/src/consent/clients.ts +19 -0
- package/src/consent/ethyca.ts +71 -0
- package/src/consent/head.ts +24 -0
- package/src/consent/index.ts +37 -0
- package/src/consent/init.ts +29 -0
- package/src/consent/native.ts +36 -0
- package/src/consent/osano.ts +59 -0
- package/src/consent/schema.ts +30 -0
- package/src/core/base-path.ts +62 -16
- package/src/core/builtin-tags.ts +5 -0
- package/src/core/client-address.ts +19 -0
- package/src/core/config-input.ts +203 -27
- package/src/core/data.ts +44 -4
- package/src/core/diagnostics.ts +5 -2
- package/src/core/directive-diagnostics.ts +99 -0
- package/src/core/footer.ts +26 -0
- package/src/core/frontmatter.ts +21 -18
- package/src/core/graph.ts +39 -36
- package/src/core/heading-markers.ts +5 -18
- package/src/core/i18n-ui.ts +82 -2
- package/src/core/i18n.ts +31 -3
- package/src/core/includes.ts +20 -3
- package/src/core/last-modified.ts +25 -3
- package/src/core/links.ts +16 -2
- package/src/core/locale-links.ts +5 -1
- package/src/core/localizable.ts +26 -0
- package/src/core/meta.ts +33 -19
- package/src/core/navigation.ts +71 -20
- package/src/core/page-modes.ts +56 -0
- package/src/core/project-graph.ts +138 -10
- package/src/core/redirect-patterns.ts +491 -0
- package/src/core/related.ts +131 -0
- package/src/core/schema.ts +342 -68
- package/src/core/sources/contentful-rich-text.ts +27 -20
- package/src/core/sources/filesystem.ts +20 -2
- package/src/core/sources/github-releases.ts +25 -6
- package/src/core/sources/lexical.ts +23 -18
- package/src/core/sources/lower.ts +201 -34
- package/src/core/sources/mdx-remote.ts +51 -16
- package/src/core/sources/normalize.ts +327 -91
- package/src/core/sources/notion.ts +52 -25
- package/src/core/sources/obsidian.ts +23 -6
- package/src/core/sources/portable-text.ts +38 -21
- package/src/core/sources/read.ts +8 -3
- package/src/core/sources/strapi-blocks.ts +20 -16
- package/src/core/sources/watch.ts +20 -7
- package/src/core/standard-schema.ts +10 -6
- package/src/core/types.ts +1 -1
- package/src/core/ui-packs/ar.ts +43 -0
- package/src/core/ui-packs/bg.ts +45 -0
- package/src/core/ui-packs/bn.ts +43 -0
- package/src/core/ui-packs/ca.ts +46 -0
- package/src/core/ui-packs/cs.ts +44 -0
- package/src/core/ui-packs/da.ts +45 -0
- package/src/core/ui-packs/de.ts +46 -0
- package/src/core/ui-packs/el.ts +45 -0
- package/src/core/ui-packs/es.ts +46 -0
- package/src/core/ui-packs/fa.ts +45 -0
- package/src/core/ui-packs/fi.ts +45 -0
- package/src/core/ui-packs/fr.ts +46 -0
- package/src/core/ui-packs/he.ts +43 -0
- package/src/core/ui-packs/hi.ts +44 -0
- package/src/core/ui-packs/hr.ts +45 -0
- package/src/core/ui-packs/hu.ts +44 -0
- package/src/core/ui-packs/id.ts +45 -0
- package/src/core/ui-packs/it.ts +45 -0
- package/src/core/ui-packs/ja.ts +45 -0
- package/src/core/ui-packs/ko.ts +44 -0
- package/src/core/ui-packs/nl.ts +46 -0
- package/src/core/ui-packs/no.ts +44 -0
- package/src/core/ui-packs/pl.ts +45 -0
- package/src/core/ui-packs/pt-br.ts +46 -0
- package/src/core/ui-packs/pt.ts +45 -0
- package/src/core/ui-packs/ro.ts +45 -0
- package/src/core/ui-packs/ru.ts +45 -0
- package/src/core/ui-packs/sk.ts +44 -0
- package/src/core/ui-packs/sr.ts +45 -0
- package/src/core/ui-packs/sv.ts +44 -0
- package/src/core/ui-packs/th.ts +43 -0
- package/src/core/ui-packs/tr.ts +45 -0
- package/src/core/ui-packs/uk.ts +45 -0
- package/src/core/ui-packs/vi.ts +45 -0
- package/src/core/ui-packs/zh-tw.ts +43 -0
- package/src/core/ui-packs/zh.ts +43 -0
- package/src/core/variables.ts +103 -0
- package/src/core/version-cut.ts +52 -15
- package/src/deploy/artifacts.ts +104 -14
- package/src/deploy/cloudflare-negotiation.ts +39 -17
- package/src/deploy/headers.ts +10 -5
- package/src/deploy/node-headers.ts +64 -10
- package/src/deploy/platforms/cloudflare.ts +44 -3
- package/src/deploy/platforms/netlify.ts +34 -1
- package/src/deploy/platforms/node.ts +1 -0
- package/src/deploy/platforms/static.ts +1 -0
- package/src/deploy/platforms/types.ts +8 -0
- package/src/deploy/platforms/vercel.ts +38 -2
- package/src/deploy/redirects.ts +139 -36
- package/src/deploy/robots.ts +2 -2
- package/src/deploy/rss.ts +4 -3
- package/src/deploy/sitemap.ts +7 -5
- package/src/deploy/vercel-negotiation.ts +36 -0
- package/src/markdown/api-rail.ts +259 -0
- package/src/markdown/base-links.ts +34 -36
- package/src/markdown/code-title.ts +35 -9
- package/src/markdown/directives.ts +242 -36
- package/src/markdown/features.ts +20 -2
- package/src/markdown/fence-meta.ts +2 -0
- package/src/markdown/include.ts +11 -1
- package/src/markdown/index.ts +35 -11
- package/src/markdown/math.ts +4 -4
- package/src/markdown/mdast.ts +5 -2
- package/src/markdown/relative-links.ts +12 -4
- package/src/markdown/variables.ts +56 -0
- package/src/markdown/views.ts +82 -0
- package/src/narration/build.ts +412 -0
- package/src/narration/player.ts +249 -0
- package/src/narration/provider.ts +29 -0
- package/src/narration/script.ts +592 -0
- package/src/og/card.ts +136 -11
- package/src/og/derive.ts +41 -31
- package/src/og/index.ts +1 -0
- package/src/openapi/asyncapi.ts +4 -2
- package/src/openapi/model.ts +77 -36
- package/src/openapi/overlay.ts +256 -0
- package/src/openapi/parse.ts +55 -2
- package/src/openapi/proxy.ts +63 -10
- package/src/openapi/references.ts +21 -5
- package/src/openapi/render-mdx.ts +46 -3
- package/src/openapi/scalar.ts +40 -6
- package/src/openapi/source.ts +1 -1
- package/src/ratelimit/cloudflare.ts +54 -0
- package/src/ratelimit/index.ts +30 -0
- package/src/ratelimit/memory.ts +45 -0
- package/src/ratelimit/runtime.ts +229 -0
- package/src/ratelimit/schema.ts +28 -0
- package/src/ratelimit/upstash.ts +30 -0
- package/src/ratelimit/wrangler.ts +70 -0
- package/src/reference/asyncapi.ts +2 -2
- package/src/reference/graphql.ts +5 -2
- package/src/reference/openapi.ts +21 -7
- package/src/reference/options.ts +51 -7
- package/src/reference/scalar.ts +33 -8
- package/src/registry/eject.ts +201 -28
- package/src/registry/registry.ts +7 -0
- package/src/search/adapters/version-scope.ts +30 -0
- package/src/search/documents.ts +93 -28
- package/src/search/orama-index.ts +28 -3
- package/src/search/pagefind-ranking.ts +39 -0
- package/src/search/popular.ts +2 -1
- package/src/search/sync/algolia.ts +15 -4
- package/src/search/sync/orama-cloud.ts +3 -0
- package/src/search/sync/typesense.ts +5 -0
- package/src/seo/jsonld.ts +7 -3
- package/src/seo/metatags.ts +67 -0
- package/src/theme/chrome-icons.ts +1 -0
- package/src/theme/color.ts +500 -0
- package/src/theme/entry.ts +56 -3
- package/src/theme/palette.ts +121 -45
- package/src/translate/meta.ts +68 -24
- package/src/translate/prompts.ts +1 -0
- package/src/translate/run.ts +3 -3
- package/src/translate/validate.ts +12 -3
- package/src/translate/work-list.ts +56 -17
- package/src/upgrade/upgrade.ts +4 -171
- package/dist/cli/chunk-3yce002v.js.map +0 -14
- package/dist/cli/chunk-5r8g91qn.js.map +0 -34
- package/dist/cli/chunk-6dtt0zfn.js.map +0 -10
- package/dist/cli/chunk-7mbqtmgb.js.map +0 -10
- package/dist/cli/chunk-ddndchfr.js.map +0 -14
- package/dist/cli/chunk-esh98wmb.js +0 -23
- package/dist/cli/chunk-esh98wmb.js.map +0 -10
- package/dist/cli/chunk-hqp2ajnh.js.map +0 -35
- package/dist/cli/chunk-hr8ne106.js.map +0 -13
- package/dist/cli/chunk-j85scx15.js.map +0 -10
- package/dist/cli/chunk-mqc662a6.js +0 -75
- package/dist/cli/chunk-mqc662a6.js.map +0 -11
- package/dist/cli/chunk-pbg5a4s3.js.map +0 -19
- package/dist/cli/chunk-qkb5a8sa.js.map +0 -10
- package/dist/cli/chunk-v6ya5kcb.js.map +0 -189
- package/dist/cli/chunk-wdrt2k2v.js.map +0 -10
- package/dist/cli/chunk-xh43dwgw.js.map +0 -36
- package/docs/content/sources.mdx +0 -338
- /package/dist/cli/{chunk-zp79m0ts.js.map → chunk-1n228xqb.js.map} +0 -0
- /package/dist/cli/{chunk-h2ez8dzb.js.map → chunk-5ffywsmb.js.map} +0 -0
- /package/dist/cli/{chunk-g698a744.js.map → chunk-5wj2qwn2.js.map} +0 -0
- /package/dist/cli/{chunk-sqw4ekg1.js.map → chunk-amrb6hgh.js.map} +0 -0
- /package/dist/cli/{chunk-h7k3nq3v.js.map → chunk-gp84za0h.js.map} +0 -0
- /package/dist/cli/{chunk-bfwp9vp6.js.map → chunk-p804f3pe.js.map} +0 -0
- /package/dist/cli/{chunk-00gs3wqs.js.map → chunk-ta27feev.js.map} +0 -0
- /package/dist/cli/{chunk-bbnwccaz.js.map → chunk-y4ykbark.js.map} +0 -0
|
@@ -3,15 +3,30 @@ import { toString as mdastToString } from "mdast-util-to-string";
|
|
|
3
3
|
import { jsxAttribute, jsxFlowElement } from "./mdast.ts";
|
|
4
4
|
import type { MdastNode, MdastVisitorContext } from "./mdast.ts";
|
|
5
5
|
|
|
6
|
-
interface DirectiveNode extends MdastNode {
|
|
6
|
+
export interface DirectiveNode extends MdastNode {
|
|
7
7
|
attributes?: Record<string, string | null | undefined> | null;
|
|
8
8
|
// Satteri gives an empty container directive (`:::note\n:::`) `children: null`.
|
|
9
9
|
children?: MdastNode[] | null;
|
|
10
10
|
name: string;
|
|
11
|
+
position?: {
|
|
12
|
+
start?: { offset?: number };
|
|
13
|
+
end?: { offset?: number };
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The visitor-context slice the directive visitors use. `source` is the page
|
|
19
|
+
* the directive offsets index into; without it the literal fallback rebuilds
|
|
20
|
+
* a directive from its node instead. `parent` walks up to an enclosing
|
|
21
|
+
* container directive, which renders the directives inside it itself.
|
|
22
|
+
*/
|
|
23
|
+
interface DirectiveVisitorContext extends MdastVisitorContext {
|
|
24
|
+
parent?: (node: MdastNode) => MdastNode | undefined;
|
|
25
|
+
source?: string;
|
|
11
26
|
}
|
|
12
27
|
|
|
13
28
|
/** Directive names that map directly onto a Callout type. */
|
|
14
|
-
const CALLOUT_TYPES = new Set([
|
|
29
|
+
export const CALLOUT_TYPES: ReadonlySet<string> = new Set([
|
|
15
30
|
"danger",
|
|
16
31
|
"info",
|
|
17
32
|
"note",
|
|
@@ -25,7 +40,7 @@ interface CalloutAliases {
|
|
|
25
40
|
[alias: string]: string;
|
|
26
41
|
}
|
|
27
42
|
|
|
28
|
-
const
|
|
43
|
+
export const CALLOUT_ALIASES: Readonly<CalloutAliases> = {
|
|
29
44
|
caution: "warning",
|
|
30
45
|
error: "danger",
|
|
31
46
|
important: "note",
|
|
@@ -38,48 +53,239 @@ export const calloutTypeFor = (name: string): string | null => {
|
|
|
38
53
|
if (CALLOUT_TYPES.has(lower)) {
|
|
39
54
|
return lower;
|
|
40
55
|
}
|
|
41
|
-
return
|
|
56
|
+
return CALLOUT_ALIASES[lower] ?? null;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/** The markers that open a text (`:name`) and a leaf (`::name`) directive. */
|
|
60
|
+
const LITERAL_MARKERS = new Map([
|
|
61
|
+
["leafDirective", "::"],
|
|
62
|
+
["textDirective", ":"],
|
|
63
|
+
]);
|
|
64
|
+
|
|
65
|
+
/** A directive's `[label]` rebuilt from its label's text, or nothing. */
|
|
66
|
+
const labelSource = (label: MdastNode[]): string =>
|
|
67
|
+
label.length > 0
|
|
68
|
+
? `[${mdastToString(label, { includeImageAlt: false })}]`
|
|
69
|
+
: "";
|
|
70
|
+
|
|
71
|
+
/** A directive's `{attributes}` rebuilt from its node, or nothing. */
|
|
72
|
+
const attributeSource = (node: DirectiveNode): string => {
|
|
73
|
+
const attributes = Object.entries(node.attributes ?? {}).map(
|
|
74
|
+
([key, value]) => (value ? `${key}="${value}"` : key)
|
|
75
|
+
);
|
|
76
|
+
return attributes.length > 0 ? `{${attributes.join(" ")}}` : "";
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
/** The source a directive node spans, when its offsets point into `source`. */
|
|
80
|
+
const spannedSource = (node: DirectiveNode, source: string): string | null => {
|
|
81
|
+
const start = node.position?.start?.offset;
|
|
82
|
+
const end = node.position?.end?.offset;
|
|
83
|
+
return start !== undefined && end !== undefined
|
|
84
|
+
? source.slice(start, end)
|
|
85
|
+
: null;
|
|
42
86
|
};
|
|
43
87
|
|
|
44
88
|
/**
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
89
|
+
* A text or leaf directive exactly as the author wrote it. The slice by
|
|
90
|
+
* offsets is the exact text — `[label]` and `{attrs}` included — and is
|
|
91
|
+
* trusted only when it opens with the directive's own marker and name;
|
|
92
|
+
* content an `<include>` spliced in carries no offsets into this page, so it
|
|
93
|
+
* is rebuilt from the node instead.
|
|
49
94
|
*/
|
|
50
|
-
export const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
95
|
+
export const directiveSource = (
|
|
96
|
+
node: DirectiveNode,
|
|
97
|
+
marker: string,
|
|
98
|
+
source: string
|
|
99
|
+
): string => {
|
|
100
|
+
const opening = `${marker}${node.name}`;
|
|
101
|
+
const slice = spannedSource(node, source);
|
|
102
|
+
if (slice?.startsWith(opening)) {
|
|
103
|
+
return slice;
|
|
104
|
+
}
|
|
105
|
+
return `${opening}${labelSource(node.children ?? [])}${attributeSource(node)}`;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* The node a text or leaf directive renders as: its literal source, as text
|
|
110
|
+
* in place of a text directive and as a paragraph in place of a leaf one.
|
|
111
|
+
*/
|
|
112
|
+
const literalDirective = (
|
|
113
|
+
node: DirectiveNode,
|
|
114
|
+
marker: string,
|
|
115
|
+
source: string
|
|
116
|
+
): MdastNode => {
|
|
117
|
+
const text = { type: "text", value: directiveSource(node, marker, source) };
|
|
118
|
+
return marker === ":" ? text : { children: [text], type: "paragraph" };
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const FENCE = /^:{3,}/u;
|
|
122
|
+
|
|
123
|
+
// The line that closes a container: a colon fence, after whatever quote or
|
|
124
|
+
// list indentation the container sits in.
|
|
125
|
+
const CLOSING_FENCE = /\n[\t >]*(?<fence>:{3,})\s*$/u;
|
|
126
|
+
|
|
127
|
+
/** A paragraph holding one line of literal text. */
|
|
128
|
+
const literalLine = (value: string): MdastNode => ({
|
|
129
|
+
children: [{ type: "text", value }],
|
|
130
|
+
type: "paragraph",
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* The fence lines of a container directive as the author wrote them — the
|
|
135
|
+
* opening one with its `[label]` and `{attrs}` — or, without offsets into
|
|
136
|
+
* this page (an `<include>`), rebuilt from the node. A container left
|
|
137
|
+
* unclosed runs to the end of its parent and has no closing line.
|
|
138
|
+
*/
|
|
139
|
+
const containerFences = (
|
|
140
|
+
node: DirectiveNode,
|
|
141
|
+
label: MdastNode | undefined,
|
|
142
|
+
source: string
|
|
143
|
+
): string[] => {
|
|
144
|
+
const slice = spannedSource(node, source) ?? "";
|
|
145
|
+
const fence = FENCE.exec(slice)?.[0];
|
|
146
|
+
if (fence === undefined || !slice.startsWith(node.name, fence.length)) {
|
|
147
|
+
const labelText = labelSource(label ? [label] : []);
|
|
148
|
+
return [`:::${node.name}${labelText}${attributeSource(node)}`, ":::"];
|
|
149
|
+
}
|
|
150
|
+
const [opening = ""] = slice.split("\n", 1);
|
|
151
|
+
const closing = CLOSING_FENCE.exec(slice.slice(opening.length))?.groups
|
|
152
|
+
?.fence;
|
|
153
|
+
// A shorter fence can't close the container; it is the body's last line.
|
|
154
|
+
return closing !== undefined && closing.length >= fence.length
|
|
155
|
+
? [opening.trimEnd(), closing]
|
|
156
|
+
: [opening.trimEnd()];
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* What a container directive renders as. A callout name becomes a
|
|
161
|
+
* `<Callout>`: the title comes from a `[label]` or a `{title="…"}` attribute,
|
|
162
|
+
* and the body becomes the callout content. Blume has no other container, and
|
|
163
|
+
* dropping one would drop its body with it, so any other name — `:::details`,
|
|
164
|
+
* a `:::warnig` typo — renders its body between its fence lines, as written.
|
|
165
|
+
* The directives inside render here too, since Satteri reaches them only
|
|
166
|
+
* after this replacement has taken their original.
|
|
167
|
+
*/
|
|
168
|
+
const renderContainer = (
|
|
169
|
+
node: DirectiveNode,
|
|
170
|
+
source: string
|
|
171
|
+
): MdastNode | MdastNode[] => {
|
|
172
|
+
const children = (node.children ?? []).flatMap((child) =>
|
|
173
|
+
// oxlint-disable-next-line no-use-before-define -- mutual recursion: a container's body holds directives, containers included
|
|
174
|
+
literalize(child, source)
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
// A leading `:::name[Label]` parses to a paragraph flagged `directiveLabel`.
|
|
178
|
+
// SAFETY: Satteri stamps `directiveLabel` on that paragraph's `data`; any
|
|
179
|
+
// other node reads undefined and fails the check.
|
|
180
|
+
const labelIndex = children.findIndex(
|
|
181
|
+
(child) =>
|
|
182
|
+
child.type === "paragraph" &&
|
|
183
|
+
(child.data as { directiveLabel?: boolean } | undefined)?.directiveLabel
|
|
184
|
+
);
|
|
185
|
+
const [label] = labelIndex === -1 ? [] : children.splice(labelIndex, 1);
|
|
186
|
+
|
|
187
|
+
const type = calloutTypeFor(node.name);
|
|
188
|
+
if (type === null) {
|
|
189
|
+
const [opening = "", closing] = containerFences(node, label, source);
|
|
190
|
+
return [
|
|
191
|
+
literalLine(opening),
|
|
192
|
+
...children,
|
|
193
|
+
...(closing === undefined ? [] : [literalLine(closing)]),
|
|
194
|
+
];
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Flatten the label's phrasing children so `:::note[Read **this**]` yields
|
|
198
|
+
// `Read this`; image alt is excluded (an image is not label text), matching
|
|
199
|
+
// the historical child-values-only behavior.
|
|
200
|
+
const title =
|
|
201
|
+
node.attributes?.title ??
|
|
202
|
+
(label ? mdastToString(label, { includeImageAlt: false }) : undefined);
|
|
203
|
+
const attributes = [jsxAttribute("type", type)];
|
|
204
|
+
if (title) {
|
|
205
|
+
attributes.push(jsxAttribute("title", title));
|
|
206
|
+
}
|
|
207
|
+
return jsxFlowElement("Callout", attributes, children);
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* `node` with every directive in it rendered: text and leaf directives as
|
|
212
|
+
* their literal source, containers as {@link renderContainer}.
|
|
213
|
+
*/
|
|
214
|
+
const literalize = (node: MdastNode, source: string): MdastNode[] => {
|
|
215
|
+
if (node.type === "containerDirective") {
|
|
216
|
+
// SAFETY: a `containerDirective` carries a `name` plus optional
|
|
217
|
+
// attributes, children, and position — the `DirectiveNode` shape.
|
|
218
|
+
return [renderContainer(node as DirectiveNode, source)].flat();
|
|
219
|
+
}
|
|
220
|
+
const marker = LITERAL_MARKERS.get(node.type);
|
|
221
|
+
if (marker) {
|
|
222
|
+
// SAFETY: only Satteri's `textDirective`/`leafDirective` nodes have a
|
|
223
|
+
// marker, and they carry a `name` plus optional attributes, children,
|
|
224
|
+
// and position — the `DirectiveNode` shape.
|
|
225
|
+
return [literalDirective(node as DirectiveNode, marker, source)];
|
|
226
|
+
}
|
|
227
|
+
// SAFETY: a parent's `children` is always a node list; leaves carry none.
|
|
228
|
+
const children = node.children as MdastNode[] | null | undefined;
|
|
229
|
+
if (!children) {
|
|
230
|
+
return [node];
|
|
231
|
+
}
|
|
232
|
+
return [
|
|
233
|
+
{
|
|
234
|
+
...node,
|
|
235
|
+
children: children.flatMap((child) => literalize(child, source)),
|
|
236
|
+
},
|
|
237
|
+
];
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
/** Whether a container directive (already rendered, body and all) holds `node`. */
|
|
241
|
+
const insideContainer = (node: MdastNode, ctx: DirectiveVisitorContext) => {
|
|
242
|
+
for (
|
|
243
|
+
let parent = ctx.parent?.(node);
|
|
244
|
+
parent !== undefined;
|
|
245
|
+
parent = ctx.parent?.(parent)
|
|
246
|
+
) {
|
|
247
|
+
if (parent.type === "containerDirective") {
|
|
248
|
+
return true;
|
|
55
249
|
}
|
|
250
|
+
}
|
|
251
|
+
return false;
|
|
252
|
+
};
|
|
56
253
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
// A
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
child.type === "paragraph" &&
|
|
66
|
-
(child.data as { directiveLabel?: boolean } | undefined)?.directiveLabel
|
|
67
|
-
);
|
|
68
|
-
if (labelIndex !== -1) {
|
|
69
|
-
const [label] = children.splice(labelIndex, 1);
|
|
70
|
-
if (label) {
|
|
71
|
-
// Flatten the label's phrasing children so `:::note[Read **this**]`
|
|
72
|
-
// yields `Read this`; image alt is excluded (an image is not label
|
|
73
|
-
// text), matching the historical child-values-only behavior.
|
|
74
|
-
title ??= mdastToString(label, { includeImageAlt: false }) || undefined;
|
|
75
|
-
}
|
|
254
|
+
/** The text and leaf visitor: render the directive as its literal source. */
|
|
255
|
+
const renderLiteral =
|
|
256
|
+
(marker: string) => (node: DirectiveNode, ctx: DirectiveVisitorContext) => {
|
|
257
|
+
// A container's body was already rendered into its replacement; a
|
|
258
|
+
// transform queued on the replaced original would be dropped with a
|
|
259
|
+
// warning.
|
|
260
|
+
if (insideContainer(node, ctx)) {
|
|
261
|
+
return;
|
|
76
262
|
}
|
|
263
|
+
ctx.replaceNode(node, literalDirective(node, marker, ctx.source ?? ""));
|
|
264
|
+
};
|
|
77
265
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
266
|
+
/**
|
|
267
|
+
* Satteri MDAST plugin for directives. Container directives (`:::note`,
|
|
268
|
+
* `:::warning`, `:::tip`, …) map onto Blume's `<Callout>` component, and any
|
|
269
|
+
* other container renders its body between its literal fence lines (see
|
|
270
|
+
* {@link renderContainer}).
|
|
271
|
+
*
|
|
272
|
+
* Blume handles no text (`:name`) or leaf (`::name`) directives, and prose is
|
|
273
|
+
* full of text that parses as one — `16:9`, `10:30am`, `og:image`,
|
|
274
|
+
* `pets:read` — so both render as the literal source the author wrote instead
|
|
275
|
+
* of vanishing.
|
|
276
|
+
*/
|
|
277
|
+
export const directiveToCalloutPlugin = () => ({
|
|
278
|
+
containerDirective(node: DirectiveNode, ctx: DirectiveVisitorContext) {
|
|
279
|
+
// A container inside another was rendered with its enclosing one.
|
|
280
|
+
if (insideContainer(node, ctx)) {
|
|
281
|
+
return;
|
|
81
282
|
}
|
|
82
|
-
ctx.replaceNode(node,
|
|
283
|
+
ctx.replaceNode(node, renderContainer(node, ctx.source ?? ""));
|
|
83
284
|
},
|
|
285
|
+
leafDirective: renderLiteral("::"),
|
|
84
286
|
name: "blume-directive-callout",
|
|
287
|
+
// Positions are opt-in since satteri 0.10; the literal fallback slices
|
|
288
|
+
// directives out of the source by offset.
|
|
289
|
+
options: { position: true },
|
|
290
|
+
textDirective: renderLiteral(":"),
|
|
85
291
|
});
|
package/src/markdown/features.ts
CHANGED
|
@@ -11,11 +11,29 @@ export const MARKDOWN_FEATURES = {
|
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* The `.mdx` feature set: Markdown's plus `:::` directives (→ `<Callout>`) and
|
|
14
|
-
*
|
|
15
|
-
*
|
|
14
|
+
* math — `singleDollarTextMath: false` keeps a bare `$` (currency, shell,
|
|
15
|
+
* code) as literal text and only parses `$$…$$`, as a block on its own lines
|
|
16
|
+
* or inline within a sentence.
|
|
16
17
|
*/
|
|
17
18
|
export const MDX_FEATURES = {
|
|
18
19
|
...MARKDOWN_FEATURES,
|
|
19
20
|
directive: true,
|
|
20
21
|
math: { singleDollarTextMath: false },
|
|
21
22
|
} satisfies Features;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The feature sets for a page body, once its front matter is off. Astro reads
|
|
26
|
+
* a page's front matter itself and hands the renderer the body alone, and the
|
|
27
|
+
* search extractor strips it first too — so front matter parsing is off here:
|
|
28
|
+
* left on, a body that opens with a `---` rule read everything up to the next
|
|
29
|
+
* `---` line as front matter and dropped it from the page.
|
|
30
|
+
*/
|
|
31
|
+
export const MARKDOWN_BODY_FEATURES = {
|
|
32
|
+
...MARKDOWN_FEATURES,
|
|
33
|
+
frontmatter: false,
|
|
34
|
+
} satisfies Features;
|
|
35
|
+
|
|
36
|
+
export const MDX_BODY_FEATURES = {
|
|
37
|
+
...MDX_FEATURES,
|
|
38
|
+
frontmatter: false,
|
|
39
|
+
} satisfies Features;
|
|
@@ -41,9 +41,11 @@ export const metaTokens = (meta: string | null | undefined): string[] =>
|
|
|
41
41
|
* a block title.
|
|
42
42
|
*/
|
|
43
43
|
export const RESERVED_META_KEYWORDS: ReadonlySet<string> = new Set([
|
|
44
|
+
"expandable",
|
|
44
45
|
"lineNumbers",
|
|
45
46
|
"ts2js",
|
|
46
47
|
"twoslash",
|
|
48
|
+
"wrap",
|
|
47
49
|
]);
|
|
48
50
|
|
|
49
51
|
/** A Shiki `{1,3-5}` line-range token. */
|
package/src/markdown/include.ts
CHANGED
|
@@ -9,6 +9,8 @@ import {
|
|
|
9
9
|
hasIncludeStatements,
|
|
10
10
|
matchIncludeStatement,
|
|
11
11
|
} from "../core/includes.ts";
|
|
12
|
+
import { substituteVariables } from "../core/variables.ts";
|
|
13
|
+
import type { ContentVariables } from "../core/variables.ts";
|
|
12
14
|
import type { MdastNode, MdastValue } from "./mdast.ts";
|
|
13
15
|
|
|
14
16
|
/**
|
|
@@ -83,6 +85,8 @@ const errorBlock = (message: string): string =>
|
|
|
83
85
|
export interface IncludePluginOptions {
|
|
84
86
|
/** The docs content root; bounds include resolution when set. */
|
|
85
87
|
contentRoot?: string;
|
|
88
|
+
/** Content variables, substituted in each included file before it's parsed. */
|
|
89
|
+
variables?: ContentVariables;
|
|
86
90
|
}
|
|
87
91
|
|
|
88
92
|
/** A plain string attribute value; expression values don't carry a path. */
|
|
@@ -104,6 +108,10 @@ const statementFromJsx = (
|
|
|
104
108
|
if (attr.name === "meta" && attr.value) {
|
|
105
109
|
attributes.meta = attr.value;
|
|
106
110
|
}
|
|
111
|
+
// Every other string attribute is a prop, as in the string-level parser.
|
|
112
|
+
if (attr.name && attr.name !== "lang" && attr.name !== "meta") {
|
|
113
|
+
attributes.props = { ...attributes.props, [attr.name]: attr.value };
|
|
114
|
+
}
|
|
107
115
|
}
|
|
108
116
|
return { attributes, target: ctx.textContent(node).trim() };
|
|
109
117
|
};
|
|
@@ -147,7 +155,9 @@ export const includePlugin = (options: IncludePluginOptions = {}) => {
|
|
|
147
155
|
for (const nested of expanded.errors) {
|
|
148
156
|
ctx.report({ message: nested.message, node, severity: "warning" });
|
|
149
157
|
}
|
|
150
|
-
|
|
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);
|
|
151
161
|
};
|
|
152
162
|
|
|
153
163
|
/**
|
package/src/markdown/index.ts
CHANGED
|
@@ -9,11 +9,14 @@ import {
|
|
|
9
9
|
import { escape as escapeHtml } from "html-escaper";
|
|
10
10
|
import { codeToHtml } from "shiki";
|
|
11
11
|
|
|
12
|
+
import { hasVariables } from "../core/variables.ts";
|
|
13
|
+
import type { ContentVariables } from "../core/variables.ts";
|
|
14
|
+
import { apiRailPlugin } from "./api-rail.ts";
|
|
12
15
|
import { baseLinksPlugin } from "./base-links.ts";
|
|
13
16
|
import { codeTitleTransformer } from "./code-title.ts";
|
|
14
17
|
import { directiveToCalloutPlugin } from "./directives.ts";
|
|
15
18
|
import { externalLinksPlugin } from "./external-links.ts";
|
|
16
|
-
import {
|
|
19
|
+
import { MARKDOWN_BODY_FEATURES, MDX_BODY_FEATURES } from "./features.ts";
|
|
17
20
|
import { headingAnchorPlugin } from "./heading-anchors.ts";
|
|
18
21
|
import { includePlugin } from "./include.ts";
|
|
19
22
|
import { inlineCodeHighlightPlugin } from "./inline-code.ts";
|
|
@@ -26,6 +29,8 @@ import { tableWrapPlugin } from "./table-wrap.ts";
|
|
|
26
29
|
import { DEFAULT_CODE_THEMES } from "./themes.ts";
|
|
27
30
|
import type { CodeThemes } from "./themes.ts";
|
|
28
31
|
import { ts2jsPlugin } from "./ts2js.ts";
|
|
32
|
+
import { variablesPlugin } from "./variables.ts";
|
|
33
|
+
import { viewsPlugin } from "./views.ts";
|
|
29
34
|
|
|
30
35
|
export type { CodeTheme, CodeThemes } from "./themes.ts";
|
|
31
36
|
|
|
@@ -277,6 +282,12 @@ export interface BlumeMarkdownOptions {
|
|
|
277
282
|
* `basePath` link isn't double-prefixed (see `withComposedBasePath`).
|
|
278
283
|
*/
|
|
279
284
|
deployBase?: string;
|
|
285
|
+
/**
|
|
286
|
+
* `variables`: `{{name}}` references replaced in `.md` pages and in every
|
|
287
|
+
* included file (`.mdx` pages are substituted before parsing, by the
|
|
288
|
+
* `variablesVitePlugin`).
|
|
289
|
+
*/
|
|
290
|
+
variables?: ContentVariables;
|
|
280
291
|
/**
|
|
281
292
|
* The docs content root, bounding `<include>` target resolution (and
|
|
282
293
|
* anchoring `/`-leading include paths). When unset, relative includes still
|
|
@@ -295,9 +306,9 @@ export interface BlumeMarkdownOptions {
|
|
|
295
306
|
|
|
296
307
|
/**
|
|
297
308
|
* MDAST plugins that apply to both `.md` and `.mdx`: relative page links
|
|
298
|
-
* rewritten to the
|
|
299
|
-
* rewrite (added only when a `basePath` or
|
|
300
|
-
*
|
|
309
|
+
* rewritten to the served URL of the route they mean, then the base-path link
|
|
310
|
+
* rewrite for root-relative links (added only when a `basePath` or
|
|
311
|
+
* `deployBase` is configured).
|
|
301
312
|
*/
|
|
302
313
|
const blumeSharedMdastPlugins = (
|
|
303
314
|
options: BlumeMarkdownOptions
|
|
@@ -306,6 +317,7 @@ const blumeSharedMdastPlugins = (
|
|
|
306
317
|
relativeLinksPlugin({
|
|
307
318
|
contentRoot: options.contentRoot,
|
|
308
319
|
dataFile: options.dataFile,
|
|
320
|
+
deployBase: options.deployBase,
|
|
309
321
|
})
|
|
310
322
|
),
|
|
311
323
|
...(options.basePath || options.deployBase
|
|
@@ -325,15 +337,23 @@ const blumeSharedMdastPlugins = (
|
|
|
325
337
|
* (callouts, mermaid, math, base links) like inline content.
|
|
326
338
|
*/
|
|
327
339
|
const blumeIncludePlugin = (options: BlumeMarkdownOptions): MdastPlugin =>
|
|
328
|
-
asMdastPlugin(
|
|
340
|
+
asMdastPlugin(
|
|
341
|
+
includePlugin({
|
|
342
|
+
contentRoot: options.contentRoot,
|
|
343
|
+
variables: options.variables,
|
|
344
|
+
})
|
|
345
|
+
);
|
|
329
346
|
|
|
330
347
|
/** Sätteri processor for plain `.md`, with Blume's curated feature set. */
|
|
331
348
|
export const blumeMarkdownProcessor = (options: BlumeMarkdownOptions = {}) =>
|
|
332
349
|
satteri({
|
|
333
|
-
features: { ...
|
|
350
|
+
features: { ...MARKDOWN_BODY_FEATURES },
|
|
334
351
|
hastPlugins: blumeHastPlugins(options),
|
|
335
352
|
mdastPlugins: [
|
|
336
353
|
blumeIncludePlugin(options),
|
|
354
|
+
...(hasVariables(options.variables)
|
|
355
|
+
? [asMdastPlugin(variablesPlugin(options.variables))]
|
|
356
|
+
: []),
|
|
337
357
|
...blumeSharedMdastPlugins(options),
|
|
338
358
|
],
|
|
339
359
|
});
|
|
@@ -344,13 +364,15 @@ export type BlumeMdxOptions = BlumeMarkdownOptions;
|
|
|
344
364
|
* Sätteri MDX processor: Blume's feature set plus the MDAST plugins that target
|
|
345
365
|
* components — `package-install` → package-manager tabs, ` ```ts ts2js ` →
|
|
346
366
|
* TypeScript/JavaScript tabs, `:::note` → `<Callout>`, ` ```mermaid ` → a
|
|
347
|
-
* `<blume-mermaid>` element,
|
|
348
|
-
* (`$$…$$`) → the `<Math>` component
|
|
367
|
+
* `<blume-mermaid>` element, block math
|
|
368
|
+
* (`$$…$$`) → the `<Math>` component, and top-level `<RequestExample>` and
|
|
369
|
+
* `<ResponseExample>` → the page's `<ApiRail>`. Used as the `processor` for
|
|
349
370
|
* `@astrojs/mdx` so these apply to `.mdx` only (plain `.md` uses
|
|
350
371
|
* {@link blumeMarkdownProcessor}).
|
|
351
372
|
*
|
|
352
|
-
* Math is always on
|
|
353
|
-
* `$` (currency, shell, code) as
|
|
373
|
+
* Math is always on and written `$$…$$`, as a block or inline:
|
|
374
|
+
* `singleDollarTextMath: false` keeps a bare `$` (currency, shell, code) as
|
|
375
|
+
* literal text. The
|
|
354
376
|
* generated runtime imports the `<Math>` component (and KaTeX's stylesheet) only
|
|
355
377
|
* when content actually uses `$$`, so a math-free site ships no KaTeX CSS.
|
|
356
378
|
*
|
|
@@ -359,7 +381,7 @@ export type BlumeMdxOptions = BlumeMarkdownOptions;
|
|
|
359
381
|
*/
|
|
360
382
|
export const blumeMdxProcessor = (options: BlumeMdxOptions = {}) =>
|
|
361
383
|
satteri({
|
|
362
|
-
features: { ...
|
|
384
|
+
features: { ...MDX_BODY_FEATURES },
|
|
363
385
|
hastPlugins: blumeHastPlugins(options),
|
|
364
386
|
mdastPlugins: [
|
|
365
387
|
blumeIncludePlugin(options),
|
|
@@ -369,5 +391,7 @@ export const blumeMdxProcessor = (options: BlumeMdxOptions = {}) =>
|
|
|
369
391
|
asMdastPlugin(mermaidPlugin()),
|
|
370
392
|
asMdastPlugin(mathPlugin()),
|
|
371
393
|
...blumeSharedMdastPlugins(options),
|
|
394
|
+
asMdastPlugin(apiRailPlugin()),
|
|
395
|
+
asMdastPlugin(viewsPlugin()),
|
|
372
396
|
],
|
|
373
397
|
});
|
package/src/markdown/math.ts
CHANGED
|
@@ -7,10 +7,10 @@ interface MathNode extends MdastNode {
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Satteri MDAST plugin that turns math nodes into Blume's `<Math>` component,
|
|
10
|
-
* which renders them with KaTeX at build time.
|
|
11
|
-
* block element
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* which renders them with KaTeX at build time. `$$…$$` on its own lines is
|
|
11
|
+
* block math and becomes a display element; `$$…$$` inside a sentence is
|
|
12
|
+
* inline math and stays inline. The parser runs with `singleDollarTextMath:
|
|
13
|
+
* false`, so a single `$` (currency, a shell variable) never opens math.
|
|
14
14
|
*/
|
|
15
15
|
export const mathPlugin = () => ({
|
|
16
16
|
inlineMath(node: MathNode, ctx: MdastVisitorContext) {
|
package/src/markdown/mdast.ts
CHANGED
|
@@ -19,9 +19,12 @@ export type MdastValue =
|
|
|
19
19
|
| MdastValue[]
|
|
20
20
|
| { [key: string]: MdastValue };
|
|
21
21
|
|
|
22
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* The visitor context Blume's plugins use to mutate the tree. A list of
|
|
24
|
+
* nodes takes the replaced node's place in order.
|
|
25
|
+
*/
|
|
23
26
|
export interface MdastVisitorContext {
|
|
24
|
-
replaceNode: (node: MdastNode, replacement: MdastNode) => void;
|
|
27
|
+
replaceNode: (node: MdastNode, replacement: MdastNode | MdastNode[]) => void;
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
/** Any MDAST node, keyed loosely since we build a small subset by hand. */
|
|
@@ -2,6 +2,7 @@ import { fileURLToPath } from "node:url";
|
|
|
2
2
|
|
|
3
3
|
import { dirname, normalize, relative, resolve } from "pathe";
|
|
4
4
|
|
|
5
|
+
import { mountBasePath } from "../core/base-path.ts";
|
|
5
6
|
import { isIndexFileName, resolveRelativeHref } from "../core/links.ts";
|
|
6
7
|
import type { RelativeLinkBase } from "../core/links.ts";
|
|
7
8
|
import type { MdastNode, MdastValue } from "./mdast.ts";
|
|
@@ -130,6 +131,8 @@ export interface RelativeLinksPluginOptions {
|
|
|
130
131
|
* to publish the snapshot, the plugin reads the file eject writes instead.
|
|
131
132
|
*/
|
|
132
133
|
dataFile?: string;
|
|
134
|
+
/** Astro's `deployment.base` subdirectory (`""` or `/seg`). */
|
|
135
|
+
deployBase?: string;
|
|
133
136
|
}
|
|
134
137
|
|
|
135
138
|
/**
|
|
@@ -145,9 +148,11 @@ export interface RelativeLinksPluginOptions {
|
|
|
145
148
|
* entries (remote sources) by the longest trailing path that names one. A file
|
|
146
149
|
* the snapshot doesn't know keeps its links as written.
|
|
147
150
|
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
* `
|
|
151
|
+
* A rewritten route already carries `basePath`, and the `deployment.base`
|
|
152
|
+
* prefix goes on here, unconditionally: the route is one Blume serves, so
|
|
153
|
+
* `guides/setup.md` under base `/guides` is linked at `/guides/guides/setup`.
|
|
154
|
+
* The base-links plugin that runs next is idempotent per layer, so it leaves
|
|
155
|
+
* the based route alone.
|
|
151
156
|
*/
|
|
152
157
|
export const relativeLinksPlugin = (
|
|
153
158
|
options: RelativeLinksPluginOptions = {}
|
|
@@ -155,6 +160,7 @@ export const relativeLinksPlugin = (
|
|
|
155
160
|
const contentRoot = options.contentRoot
|
|
156
161
|
? resolve(options.contentRoot)
|
|
157
162
|
: undefined;
|
|
163
|
+
const deployBase = options.deployBase ?? "";
|
|
158
164
|
const readSnapshot = routeSnapshotReader(options.dataFile);
|
|
159
165
|
|
|
160
166
|
// Parsed once per published snapshot: the CLI republishes on regeneration,
|
|
@@ -245,7 +251,9 @@ export const relativeLinksPlugin = (
|
|
|
245
251
|
const next = resolveRelativeHref(url, page, page.routeOf, (route) =>
|
|
246
252
|
page.routes.has(route)
|
|
247
253
|
);
|
|
248
|
-
return next ===
|
|
254
|
+
return next === undefined || next === url
|
|
255
|
+
? undefined
|
|
256
|
+
: mountBasePath(deployBase, next);
|
|
249
257
|
};
|
|
250
258
|
|
|
251
259
|
const rewrite = (node: UrlNode, ctx: RelativeLinksContext): void => {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { substituteVariables } from "../core/variables.ts";
|
|
2
|
+
import type { ContentVariables } from "../core/variables.ts";
|
|
3
|
+
import type { MdastNode, MdastValue } from "./mdast.ts";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The Markdown half of content variables (see `core/variables.ts`): a Sätteri
|
|
7
|
+
* MDAST plugin that replaces `{{name}}` in a plain `.md` page's text, code,
|
|
8
|
+
* raw HTML, and link and image destinations. A `.md` page has no expressions,
|
|
9
|
+
* so every reference survives parsing as text and can be replaced here; MDX
|
|
10
|
+
* pages are substituted before they're parsed instead (`astro/variables.ts`).
|
|
11
|
+
* Nodes change through `setProperty`, not by mutating the node object.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
interface VariableContext {
|
|
15
|
+
setProperty: (node: MdastNode, key: string, value: string) => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const isText = (value: MdastValue): value is string =>
|
|
19
|
+
typeof value === "string";
|
|
20
|
+
|
|
21
|
+
/** The node properties that can hold a reference, per node type. */
|
|
22
|
+
const FIELDS = {
|
|
23
|
+
code: ["value"],
|
|
24
|
+
definition: ["url", "title"],
|
|
25
|
+
html: ["value"],
|
|
26
|
+
image: ["url", "title", "alt"],
|
|
27
|
+
inlineCode: ["value"],
|
|
28
|
+
link: ["url", "title"],
|
|
29
|
+
text: ["value"],
|
|
30
|
+
} as const;
|
|
31
|
+
|
|
32
|
+
export const variablesPlugin = (variables: ContentVariables) => {
|
|
33
|
+
const replaceIn =
|
|
34
|
+
(keys: readonly string[]) =>
|
|
35
|
+
(node: MdastNode, ctx: VariableContext): void => {
|
|
36
|
+
for (const key of keys) {
|
|
37
|
+
const value = node[key];
|
|
38
|
+
if (value !== undefined && isText(value)) {
|
|
39
|
+
const next = substituteVariables(value, variables);
|
|
40
|
+
if (next !== value) {
|
|
41
|
+
ctx.setProperty(node, key, next);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
return {
|
|
47
|
+
code: replaceIn(FIELDS.code),
|
|
48
|
+
definition: replaceIn(FIELDS.definition),
|
|
49
|
+
html: replaceIn(FIELDS.html),
|
|
50
|
+
image: replaceIn(FIELDS.image),
|
|
51
|
+
inlineCode: replaceIn(FIELDS.inlineCode),
|
|
52
|
+
link: replaceIn(FIELDS.link),
|
|
53
|
+
name: "blume-variables",
|
|
54
|
+
text: replaceIn(FIELDS.text),
|
|
55
|
+
};
|
|
56
|
+
};
|