blume 2.0.3 → 2.1.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 -0
- package/CHANGELOG.md +142 -0
- package/README.md +1 -1
- package/dist/cli/{chunk-5f86nr5m.js → chunk-073rdvgb.js} +21 -48
- package/dist/cli/{chunk-5f86nr5m.js.map → chunk-073rdvgb.js.map} +4 -5
- package/dist/cli/{chunk-ga0pf4aj.js → chunk-0n9xkp3d.js} +12 -3
- package/dist/cli/{chunk-ga0pf4aj.js.map → chunk-0n9xkp3d.js.map} +3 -3
- package/dist/cli/chunk-150jk7km.js +52 -0
- package/dist/cli/chunk-150jk7km.js.map +10 -0
- package/dist/cli/{chunk-9t7a85s3.js → chunk-313vnn40.js} +30 -19
- package/dist/cli/chunk-313vnn40.js.map +10 -0
- package/dist/cli/{chunk-tkacnehg.js → chunk-3v3ffbrj.js} +2 -2
- package/dist/cli/{chunk-q58y5e6a.js → chunk-3x6x3pph.js} +46 -24
- package/dist/cli/chunk-3x6x3pph.js.map +10 -0
- package/dist/cli/{chunk-1d7ve1dm.js → chunk-42t4jxdx.js} +37 -5
- package/dist/cli/chunk-42t4jxdx.js.map +12 -0
- package/dist/cli/{chunk-8ktnccpt.js → chunk-54ztw1nj.js} +21 -2
- package/dist/cli/chunk-54ztw1nj.js.map +10 -0
- package/dist/cli/{chunk-hm3vjy5s.js → chunk-5vjtgs6e.js} +28 -10
- package/dist/cli/{chunk-hm3vjy5s.js.map → chunk-5vjtgs6e.js.map} +4 -4
- package/dist/cli/chunk-66w9j7p6.js +322 -0
- package/dist/cli/chunk-66w9j7p6.js.map +14 -0
- package/dist/cli/{chunk-2hsdwb9n.js → chunk-7ppf1rva.js} +34 -18
- package/dist/cli/chunk-7ppf1rva.js.map +10 -0
- package/dist/cli/{chunk-r9rcc4w7.js → chunk-8y2kmjv8.js} +7 -7
- package/dist/cli/{chunk-r20tn01b.js → chunk-c1y538kd.js} +8 -2
- package/dist/cli/{chunk-r20tn01b.js.map → chunk-c1y538kd.js.map} +3 -3
- package/dist/cli/{chunk-2eytanqx.js → chunk-c887fj0s.js} +2 -2
- package/dist/cli/{chunk-p3v96n38.js → chunk-cfyg47zg.js} +16 -6
- package/dist/cli/chunk-cfyg47zg.js.map +10 -0
- package/dist/cli/chunk-cm89scdv.js +443 -0
- package/dist/cli/chunk-cm89scdv.js.map +11 -0
- package/dist/cli/{chunk-akbpwfxc.js → chunk-dzwehpy7.js} +2 -2
- package/dist/cli/{chunk-wrr3j9w9.js → chunk-e6atmn4h.js} +299 -72
- package/dist/cli/chunk-e6atmn4h.js.map +36 -0
- package/dist/cli/{chunk-tzmab476.js → chunk-e8xw9qkh.js} +8 -6
- package/dist/cli/{chunk-tzmab476.js.map → chunk-e8xw9qkh.js.map} +3 -3
- package/dist/cli/{chunk-6dsbexzp.js → chunk-e9q7a2ak.js} +17 -15
- package/dist/cli/{chunk-6dsbexzp.js.map → chunk-e9q7a2ak.js.map} +2 -2
- package/dist/cli/{chunk-pv29h0wf.js → chunk-ehweg4fr.js} +5155 -1249
- package/dist/cli/chunk-ehweg4fr.js.map +218 -0
- package/dist/cli/{chunk-c8chx29p.js → chunk-ep6nd0rn.js} +390 -318
- package/dist/cli/chunk-ep6nd0rn.js.map +36 -0
- package/dist/cli/{chunk-p73c0m7w.js → chunk-fdrkhpjy.js} +18 -15
- package/dist/cli/{chunk-p73c0m7w.js.map → chunk-fdrkhpjy.js.map} +3 -3
- package/dist/cli/{chunk-2z928egk.js → chunk-ft9vfys6.js} +5 -5
- package/dist/cli/{chunk-5m5nmvyq.js → chunk-gb420vvz.js} +316 -79
- package/dist/cli/chunk-gb420vvz.js.map +17 -0
- package/dist/cli/{chunk-vg9r4eb9.js → chunk-hebn0tpx.js} +86 -13
- package/dist/cli/chunk-hebn0tpx.js.map +14 -0
- package/dist/cli/{chunk-35d4wj9f.js → chunk-htrwgabr.js} +41 -23
- package/dist/cli/chunk-htrwgabr.js.map +15 -0
- package/dist/cli/{chunk-g4hq16wv.js → chunk-hx3xqnk9.js} +16 -14
- package/dist/cli/{chunk-g4hq16wv.js.map → chunk-hx3xqnk9.js.map} +2 -2
- package/dist/cli/chunk-j134vrp2.js +65 -0
- package/dist/cli/chunk-j134vrp2.js.map +10 -0
- package/dist/cli/{chunk-a58773jm.js → chunk-kma9f6sf.js} +2 -2
- package/dist/cli/chunk-kwrg63tm.js +31 -0
- package/dist/cli/chunk-kwrg63tm.js.map +10 -0
- package/dist/cli/{chunk-ey84smr6.js → chunk-mrcccgnh.js} +6 -6
- package/dist/cli/{chunk-ey84smr6.js.map → chunk-mrcccgnh.js.map} +1 -1
- package/dist/cli/{chunk-yfyb25rh.js → chunk-n0v7m8ry.js} +24 -8
- package/dist/cli/chunk-n0v7m8ry.js.map +14 -0
- package/dist/cli/{chunk-j85vccga.js → chunk-ncj7w596.js} +576 -367
- package/dist/cli/chunk-ncj7w596.js.map +35 -0
- package/dist/cli/{chunk-5xvm6tfj.js → chunk-nq1d20w2.js} +17 -15
- package/dist/cli/{chunk-5xvm6tfj.js.map → chunk-nq1d20w2.js.map} +2 -2
- package/dist/cli/{chunk-pehfxfta.js → chunk-nrns10mj.js} +6 -98
- package/dist/cli/chunk-nrns10mj.js.map +10 -0
- package/dist/cli/{chunk-crgn1q09.js → chunk-sds923fa.js} +4 -4
- package/dist/cli/chunk-t2m5j4pr.js +104 -0
- package/dist/cli/chunk-t2m5j4pr.js.map +11 -0
- package/dist/cli/{chunk-acanzt5p.js → chunk-tdqhyxfz.js} +6 -6
- package/dist/cli/chunk-tphac74f.js +126 -0
- package/dist/cli/chunk-tphac74f.js.map +11 -0
- package/dist/cli/chunk-w1r4vase.js +18 -0
- package/dist/cli/chunk-w1r4vase.js.map +10 -0
- package/dist/cli/{chunk-3em5wd2y.js → chunk-zccbjcj0.js} +4 -3
- package/dist/cli/{chunk-3em5wd2y.js.map → chunk-zccbjcj0.js.map} +2 -2
- package/dist/cli/index.js +31 -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 +26 -0
- package/dist/types/ai/ask.d.ts +271 -58
- package/dist/types/ai/component-markdown.d.ts +2 -0
- package/dist/types/ai/index.d.ts +2 -2
- package/dist/types/ai/openapi-components.d.ts +4 -1
- package/dist/types/ai/site-skill.d.ts +26 -0
- package/dist/types/ai/skills.d.ts +16 -0
- package/dist/types/astro/integration.d.ts +9 -0
- package/dist/types/astro/markdown-negotiation.d.ts +3 -0
- package/dist/types/astro/pages.d.ts +10 -0
- 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/cli/init/scaffold.d.ts +1 -1
- package/dist/types/components/content/api-field.d.ts +62 -0
- package/dist/types/components/content/api-page.d.ts +100 -0
- package/dist/types/components/layout/nav-utils.d.ts +26 -0
- package/dist/types/components/openapi/code-samples.d.ts +29 -0
- package/dist/types/components/openapi/helpers.d.ts +158 -0
- package/dist/types/components/openapi/security.d.ts +95 -0
- package/dist/types/components/openapi/snippets.d.ts +60 -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/changelog-index.d.ts +8 -0
- package/dist/types/core/config-input.d.ts +217 -23
- package/dist/types/core/data.d.ts +53 -4
- package/dist/types/core/footer.d.ts +8 -0
- package/dist/types/core/i18n-ui.d.ts +88 -0
- package/dist/types/core/includes.d.ts +8 -2
- package/dist/types/core/links.d.ts +8 -0
- package/dist/types/core/localizable.d.ts +7 -0
- package/dist/types/core/page-modes.d.ts +29 -0
- package/dist/types/core/probe.d.ts +2 -0
- package/dist/types/core/project-graph.d.ts +6 -0
- package/dist/types/core/redirect-patterns.d.ts +152 -0
- package/dist/types/core/related.d.ts +40 -0
- package/dist/types/core/schema.d.ts +670 -56
- package/dist/types/core/sources/cache.d.ts +3 -0
- package/dist/types/core/sources/contentful-rich-text.d.ts +11 -2
- package/dist/types/core/sources/contentful.d.ts +17 -1
- package/dist/types/core/sources/lexical.d.ts +5 -0
- package/dist/types/core/sources/normalize.d.ts +20 -1
- package/dist/types/core/sources/read.d.ts +5 -0
- package/dist/types/core/sources/remote.d.ts +37 -10
- package/dist/types/core/sources/sanity.d.ts +1 -1
- package/dist/types/core/types.d.ts +18 -1
- package/dist/types/core/variables.d.ts +42 -0
- package/dist/types/deploy/adapter-output.d.ts +2 -1
- package/dist/types/deploy/adapters/cloudflare.d.ts +7 -5
- package/dist/types/deploy/adapters/node.d.ts +58 -23
- package/dist/types/deploy/adapters/registry.d.ts +10 -0
- package/dist/types/deploy/adapters/types.d.ts +3 -2
- package/dist/types/deploy/node-headers.d.ts +13 -2
- package/dist/types/deploy/platforms/cloudflare.d.ts +15 -7
- package/dist/types/deploy/platforms/netlify.d.ts +7 -0
- package/dist/types/deploy/platforms/node.d.ts +3 -1
- package/dist/types/deploy/platforms/types.d.ts +18 -7
- package/dist/types/deploy/platforms/vercel.d.ts +26 -1
- package/dist/types/deploy/redirects.d.ts +55 -11
- package/dist/types/deploy/sitemap.d.ts +2 -1
- package/dist/types/deploy/vercel-negotiation.d.ts +51 -21
- package/dist/types/markdown/code-title.d.ts +17 -0
- package/dist/types/markdown/features.d.ts +3 -2
- 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/checks.d.ts +27 -0
- package/dist/types/openapi/graphql.d.ts +6 -0
- package/dist/types/openapi/model.d.ts +27 -10
- package/dist/types/openapi/overlay.d.ts +54 -0
- package/dist/types/openapi/parse.d.ts +16 -0
- package/dist/types/openapi/references.d.ts +30 -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 +119 -0
- package/dist/types/ratelimit/upstash.d.ts +46 -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 +89 -11
- package/dist/types/reference/index.d.ts +1 -1
- package/dist/types/reference/openapi.d.ts +33 -12
- package/dist/types/reference/options.d.ts +82 -6
- package/dist/types/reference/scalar.d.ts +13 -0
- package/dist/types/reference/schema.d.ts +144 -36
- package/dist/types/search/adapters/registry.d.ts +3 -0
- package/dist/types/search/adapters/typesense.d.ts +14 -4
- package/dist/types/search/build.d.ts +3 -1
- package/dist/types/search/documents.d.ts +12 -1
- package/dist/types/search/orama-index.d.ts +13 -9
- package/dist/types/search/sync/algolia.d.ts +5 -2
- package/dist/types/search/sync/index.d.ts +3 -1
- package/dist/types/search/sync/typesense.d.ts +11 -7
- package/dist/types/seo/metatags.d.ts +20 -0
- package/dist/types/sources/contentful.d.ts +16 -0
- package/dist/types/sources/github-releases.d.ts +8 -1
- package/dist/types/sources/payload.d.ts +2 -0
- package/dist/types/sources/registry.d.ts +54 -0
- package/dist/types/sources/shared.d.ts +3 -0
- package/dist/types/sources/strapi.d.ts +2 -0
- package/docs/01-quickstart.mdx +4 -2
- package/docs/02-deployment.mdx +71 -17
- package/docs/03-upgrading.mdx +4 -4
- package/docs/04-migrating.mdx +1 -1
- package/docs/advanced/changelog.mdx +13 -2
- package/docs/advanced/skills.mdx +15 -1
- package/docs/cli/audit.mdx +51 -8
- package/docs/cli/doctor.mdx +5 -1
- package/docs/cli/evals.mdx +4 -4
- package/docs/cli/index.mdx +1 -0
- package/docs/cli/translate.mdx +1 -0
- package/docs/cli/validate.mdx +4 -3
- package/docs/configuration/analytics.mdx +3 -1
- package/docs/configuration/assistant.mdx +194 -38
- package/docs/configuration/consent.mdx +100 -0
- package/docs/configuration/customization.mdx +8 -6
- package/docs/configuration/export.mdx +5 -3
- package/docs/configuration/index.mdx +64 -5
- package/docs/configuration/meta.ts +3 -0
- package/docs/configuration/narration.mdx +119 -0
- package/docs/configuration/rate-limiting.mdx +90 -0
- package/docs/configuration/search.mdx +63 -12
- package/docs/configuration/theming.mdx +3 -1
- package/docs/content/components.mdx +108 -2
- package/docs/content/frontmatter.mdx +80 -2
- package/docs/content/i18n.mdx +39 -4
- package/docs/content/includes.mdx +16 -0
- package/docs/content/meta.mdx +1 -0
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +32 -10
- package/docs/content/sources/contentful.mdx +35 -0
- package/docs/content/sources/custom.mdx +43 -0
- package/docs/content/sources/github-releases.mdx +39 -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 +31 -0
- package/docs/content/sources/remote-mdx.mdx +44 -0
- package/docs/content/sources/sanity.mdx +29 -0
- package/docs/content/sources/strapi.mdx +32 -0
- package/docs/content/syntax.mdx +69 -4
- package/docs/content/variables.mdx +41 -0
- package/docs/discoverability/agent-discovery.mdx +29 -2
- package/docs/discoverability/index.mdx +2 -2
- package/docs/discoverability/json-api.mdx +2 -0
- package/docs/discoverability/llms-txt.mdx +2 -2
- package/docs/discoverability/markdown.mdx +3 -1
- package/docs/discoverability/mcp.mdx +4 -0
- package/docs/discoverability/metadata.mdx +17 -0
- package/docs/discoverability/sitemap-and-robots.mdx +1 -1
- package/docs/references/api-pages.mdx +74 -0
- package/docs/references/asyncapi.mdx +4 -2
- package/docs/references/graphql.mdx +14 -2
- package/docs/references/meta.ts +1 -1
- package/docs/references/openapi.mdx +148 -7
- package/docs/references/scalar.mdx +3 -1
- package/package.json +43 -8
- package/skills/blume/SKILL.md +3 -0
- package/skills/blume-migrate/SKILL.md +6 -6
- package/skills/blume-migrate/references/docusaurus.md +7 -7
- package/skills/blume-migrate/references/fumadocs.md +17 -13
- package/skills/blume-migrate/references/mintlify.md +37 -19
- package/skills/blume-migrate/references/nextra.md +10 -7
- package/skills/blume-migrate/references/starlight.md +11 -8
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +60 -14
- package/skills/blume-write-skill/SKILL.md +82 -0
- package/src/ai/agent-readability.ts +2 -1
- package/src/ai/agent-surface.ts +9 -7
- package/src/ai/ai-catalog.ts +6 -3
- package/src/ai/ask-context.ts +103 -20
- package/src/ai/ask-data.ts +6 -0
- package/src/ai/ask-limits.ts +13 -0
- package/src/ai/ask-tools.ts +142 -0
- package/src/ai/ask.ts +354 -76
- package/src/ai/changelog-markdown.ts +11 -6
- package/src/ai/component-markdown.ts +76 -1
- package/src/ai/cors.ts +14 -3
- package/src/ai/index.ts +12 -0
- package/src/ai/llms.ts +6 -2
- package/src/ai/markdown.ts +2 -1
- package/src/ai/mcp/data.ts +6 -0
- package/src/ai/mcp/query.ts +14 -6
- package/src/ai/openapi-components.ts +36 -6
- package/src/ai/relative-links.ts +4 -38
- package/src/ai/site-skill.ts +274 -0
- package/src/ai/skills.ts +35 -2
- package/src/ai/write-skill.ts +97 -0
- package/src/astro/generate.ts +210 -66
- package/src/astro/index.ts +1 -0
- package/src/astro/integration.ts +42 -4
- package/src/astro/markdown-negotiation.ts +3 -0
- package/src/astro/module-types.ts +9 -1
- package/src/astro/pages.ts +23 -0
- package/src/astro/templates.ts +406 -108
- package/src/astro/variables.ts +31 -0
- package/src/audit/catalog.ts +38 -3
- 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 +19 -13
- package/src/audit/checks/network.ts +110 -6
- package/src/audit/checks/redirects.ts +6 -4
- package/src/audit/checks/robots.ts +58 -2
- package/src/audit/checks/sitemap.ts +2 -3
- package/src/audit/redirects.ts +46 -15
- package/src/audit/run.ts +5 -0
- package/src/audit/types.ts +4 -1
- package/src/audit/url.ts +14 -5
- package/src/blume-modules.d.ts +12 -1
- 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 +51 -0
- package/src/cli/build-failure.ts +23 -0
- package/src/cli/command-meta.ts +5 -0
- package/src/cli/commands/audit.ts +10 -1
- package/src/cli/commands/dev.ts +18 -2
- package/src/cli/commands/doctor.ts +67 -28
- package/src/cli/commands/eval.ts +36 -4
- package/src/cli/commands/init.ts +6 -4
- package/src/cli/commands/skill.ts +96 -0
- package/src/cli/commands/validate.ts +10 -1
- package/src/cli/index.ts +5 -0
- package/src/cli/init/scaffold.ts +3 -3
- package/src/cli/prepare.ts +6 -3
- package/src/cli/required-secrets.ts +72 -30
- package/src/components/BlumePage.astro +2 -0
- package/src/components/content/ApiEndpoint.astro +18 -0
- package/src/components/content/ApiField.astro +79 -0
- package/src/components/content/ApiPlayground.astro +66 -0
- package/src/components/content/ApiRail.astro +19 -0
- package/src/components/content/Color.astro +1 -0
- 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/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 +103 -0
- package/src/components/content/api-page.ts +248 -0
- package/src/components/content/mermaid-element.ts +15 -1
- 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 +104 -14
- package/src/components/islands/code-question.ts +62 -0
- package/src/components/islands/hooks.ts +136 -21
- package/src/components/islands/support-link.ts +68 -0
- package/src/components/layout/Analytics.astro +11 -2
- package/src/components/layout/Banner.astro +14 -10
- package/src/components/layout/Breadcrumbs.astro +6 -2
- 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/DrawerSwitchers.astro +51 -0
- package/src/components/layout/Empty.astro +2 -2
- package/src/components/layout/Header.astro +122 -80
- package/src/components/layout/LanguageSwitcher.astro +48 -15
- package/src/components/layout/NarrationPlayer.astro +1085 -0
- package/src/components/layout/NavSelector.astro +33 -7
- package/src/components/layout/PageActions.astro +139 -24
- package/src/components/layout/PageFeedback.astro +54 -49
- package/src/components/layout/PageLayout.astro +71 -3
- package/src/components/layout/ReferenceLayout.astro +17 -6
- package/src/components/layout/RelatedPages.astro +42 -0
- package/src/components/layout/RootLayout.astro +318 -47
- package/src/components/layout/Search.astro +47 -19
- package/src/components/layout/SiteFooter.astro +124 -0
- package/src/components/layout/SiteMetatags.astro +16 -0
- package/src/components/layout/TableOfContents.astro +24 -17
- 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/head-scripts.ts +6 -1
- 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/algolia.ts +10 -1
- package/src/components/layout/search/analytics.ts +126 -0
- package/src/components/layout/search/endpoint.ts +48 -5
- package/src/components/layout/search/flexsearch.ts +17 -5
- package/src/components/layout/search/orama-cloud.ts +26 -14
- package/src/components/layout/search/pagefind.ts +114 -5
- package/src/components/layout/search/types.ts +32 -0
- package/src/components/layout/search/typesense.ts +19 -3
- package/src/components/openapi/AsyncApiOperation.astro +14 -7
- package/src/components/openapi/Authorization.astro +10 -0
- package/src/components/openapi/GraphqlOperation.astro +5 -0
- package/src/components/openapi/Operation.astro +184 -13
- package/src/components/openapi/ParametersTable.astro +8 -4
- package/src/components/openapi/Playground.astro +7 -1
- package/src/components/openapi/RequestBody.astro +24 -5
- package/src/components/openapi/RequestPanel.astro +59 -7
- package/src/components/openapi/Responses.astro +7 -4
- package/src/components/openapi/SchemaTable.astro +15 -3
- package/src/components/openapi/async-snippets.ts +65 -9
- package/src/components/openapi/async.ts +123 -29
- package/src/components/openapi/code-samples.ts +97 -0
- package/src/components/openapi/graphql-helpers.ts +35 -12
- package/src/components/openapi/helpers.ts +36 -2
- package/src/components/openapi/message-model.ts +54 -11
- package/src/components/openapi/message.ts +14 -4
- package/src/components/openapi/operation-model.ts +16 -7
- package/src/components/openapi/playground-client.ts +24 -5
- package/src/components/openapi/playground-schema.ts +1 -1
- package/src/components/openapi/schema-tree.ts +44 -14
- package/src/components/openapi/security.ts +16 -3
- package/src/components/openapi/snippets.ts +873 -10
- package/src/components/openapi/validate-json.ts +4 -3
- 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/builtin-tags.ts +5 -0
- package/src/core/changelog-index.ts +31 -1
- package/src/core/client-address.ts +19 -0
- package/src/core/component-diagnostics.ts +53 -0
- package/src/core/component-overrides.ts +32 -0
- package/src/core/config-input.ts +225 -23
- package/src/core/data.ts +46 -4
- package/src/core/diagnostics.ts +8 -2
- package/src/core/footer.ts +26 -0
- package/src/core/graph.ts +39 -36
- package/src/core/i18n-ui.ts +84 -2
- package/src/core/includes.ts +21 -4
- package/src/core/links.ts +63 -19
- package/src/core/localizable.ts +26 -0
- package/src/core/navigation.ts +43 -12
- package/src/core/page-modes.ts +56 -0
- package/src/core/probe.ts +26 -6
- package/src/core/project-graph.ts +163 -16
- package/src/core/redirect-patterns.ts +520 -0
- package/src/core/related.ts +131 -0
- package/src/core/schema.ts +339 -66
- package/src/core/sources/cache.ts +6 -0
- package/src/core/sources/contentful-rich-text.ts +29 -6
- package/src/core/sources/contentful.ts +135 -25
- package/src/core/sources/filesystem.ts +26 -4
- package/src/core/sources/github-releases.ts +12 -1
- package/src/core/sources/lexical.ts +15 -10
- package/src/core/sources/mdx-remote.ts +62 -10
- package/src/core/sources/normalize.ts +228 -41
- package/src/core/sources/notion.ts +7 -1
- package/src/core/sources/obsidian.ts +16 -3
- package/src/core/sources/payload.ts +38 -15
- package/src/core/sources/read.ts +8 -3
- package/src/core/sources/remote.ts +72 -15
- package/src/core/sources/resolve.ts +11 -1
- package/src/core/sources/sanity.ts +43 -25
- package/src/core/sources/strapi.ts +2 -2
- package/src/core/types.ts +19 -1
- package/src/core/ui-packs/ar.ts +44 -0
- package/src/core/ui-packs/bg.ts +46 -0
- package/src/core/ui-packs/bn.ts +44 -0
- package/src/core/ui-packs/ca.ts +47 -0
- package/src/core/ui-packs/cs.ts +45 -0
- package/src/core/ui-packs/da.ts +46 -0
- package/src/core/ui-packs/de.ts +47 -0
- package/src/core/ui-packs/el.ts +46 -0
- package/src/core/ui-packs/es.ts +47 -0
- package/src/core/ui-packs/fa.ts +46 -0
- package/src/core/ui-packs/fi.ts +46 -0
- package/src/core/ui-packs/fr.ts +47 -0
- package/src/core/ui-packs/he.ts +44 -0
- package/src/core/ui-packs/hi.ts +45 -0
- package/src/core/ui-packs/hr.ts +46 -0
- package/src/core/ui-packs/hu.ts +45 -0
- package/src/core/ui-packs/id.ts +46 -0
- package/src/core/ui-packs/it.ts +46 -0
- package/src/core/ui-packs/ja.ts +46 -0
- package/src/core/ui-packs/ko.ts +45 -0
- package/src/core/ui-packs/nl.ts +47 -0
- package/src/core/ui-packs/no.ts +45 -0
- package/src/core/ui-packs/pl.ts +46 -0
- package/src/core/ui-packs/pt-br.ts +47 -0
- package/src/core/ui-packs/pt.ts +46 -0
- package/src/core/ui-packs/ro.ts +46 -0
- package/src/core/ui-packs/ru.ts +46 -0
- package/src/core/ui-packs/sk.ts +45 -0
- package/src/core/ui-packs/sr.ts +46 -0
- package/src/core/ui-packs/sv.ts +45 -0
- package/src/core/ui-packs/th.ts +44 -0
- package/src/core/ui-packs/tr.ts +46 -0
- package/src/core/ui-packs/uk.ts +46 -0
- package/src/core/ui-packs/vi.ts +46 -0
- package/src/core/ui-packs/zh-tw.ts +44 -0
- package/src/core/ui-packs/zh.ts +44 -0
- package/src/core/variables.ts +103 -0
- package/src/deploy/adapter-output.ts +7 -2
- package/src/deploy/adapters/cloudflare.ts +7 -5
- package/src/deploy/adapters/node.ts +47 -9
- package/src/deploy/adapters/types.ts +7 -3
- package/src/deploy/artifacts.ts +79 -9
- package/src/deploy/cloudflare-negotiation.ts +35 -5
- package/src/deploy/headers.ts +2 -1
- package/src/deploy/node-headers.ts +63 -9
- package/src/deploy/platforms/cloudflare.ts +45 -9
- package/src/deploy/platforms/netlify.ts +35 -2
- package/src/deploy/platforms/node.ts +12 -2
- package/src/deploy/platforms/types.ts +21 -7
- package/src/deploy/platforms/vercel.ts +149 -17
- package/src/deploy/redirects.ts +151 -24
- package/src/deploy/rss.ts +3 -1
- package/src/deploy/sitemap.ts +39 -5
- package/src/deploy/vercel-negotiation.ts +326 -102
- package/src/eval/agents.ts +18 -1
- package/src/eval/prompts.ts +6 -3
- package/src/eval/report.ts +34 -13
- package/src/eval/run.ts +5 -0
- package/src/markdown/api-rail.ts +259 -0
- package/src/markdown/code-title.ts +35 -9
- package/src/markdown/features.ts +3 -2
- package/src/markdown/fence-meta.ts +2 -0
- package/src/markdown/include.ts +11 -1
- package/src/markdown/index.ts +28 -5
- package/src/markdown/math.ts +4 -4
- package/src/markdown/relative-links.ts +3 -2
- 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 +7 -6
- package/src/openapi/checks.ts +273 -0
- package/src/openapi/graphql-build.ts +21 -0
- package/src/openapi/graphql.ts +11 -0
- package/src/openapi/model.ts +72 -27
- package/src/openapi/overlay.ts +256 -0
- package/src/openapi/parse.ts +182 -4
- package/src/openapi/references.ts +64 -8
- package/src/openapi/render-mdx.ts +5 -1
- package/src/openapi/scalar.ts +40 -6
- package/src/openapi/source.ts +40 -15
- 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 +247 -0
- package/src/ratelimit/schema.ts +28 -0
- package/src/ratelimit/upstash.ts +60 -0
- package/src/ratelimit/wrangler.ts +70 -0
- package/src/reference/asyncapi.ts +2 -2
- package/src/reference/graphql.ts +20 -3
- package/src/reference/index.ts +1 -0
- package/src/reference/openapi.ts +21 -7
- package/src/reference/options.ts +80 -8
- package/src/reference/scalar.ts +33 -8
- package/src/registry/eject.ts +23 -5
- package/src/registry/registry.ts +7 -0
- package/src/search/adapters/locale-scope.ts +30 -0
- package/src/search/adapters/typesense.ts +14 -4
- package/src/search/build.ts +21 -3
- package/src/search/documents.ts +26 -2
- package/src/search/orama-index.ts +191 -34
- package/src/search/pagefind-ranking.ts +39 -0
- package/src/search/source-pages.ts +29 -0
- package/src/search/sync/algolia.ts +111 -10
- package/src/search/sync/index.ts +52 -13
- package/src/search/sync/orama-cloud.ts +3 -0
- package/src/search/sync/typesense.ts +76 -26
- package/src/seo/metatags.ts +67 -0
- package/src/sources/contentful.ts +12 -0
- package/src/sources/github-releases.ts +7 -1
- package/src/sources/shared.ts +3 -0
- package/src/theme/chrome-icons.ts +1 -0
- package/src/theme/color.ts +500 -0
- package/src/theme/entry.ts +85 -6
- package/src/theme/palette.ts +121 -45
- package/src/translate/prompts.ts +1 -0
- package/src/translate/validate.ts +31 -3
- package/src/upgrade/upgrade.ts +4 -171
- package/dist/cli/chunk-1d7ve1dm.js.map +0 -12
- package/dist/cli/chunk-2hsdwb9n.js.map +0 -10
- package/dist/cli/chunk-35d4wj9f.js.map +0 -15
- package/dist/cli/chunk-364znk6q.js +0 -75
- package/dist/cli/chunk-364znk6q.js.map +0 -11
- package/dist/cli/chunk-5m5nmvyq.js.map +0 -13
- package/dist/cli/chunk-8ktnccpt.js.map +0 -10
- package/dist/cli/chunk-9t7a85s3.js.map +0 -10
- package/dist/cli/chunk-b07cmahc.js +0 -145
- package/dist/cli/chunk-b07cmahc.js.map +0 -11
- package/dist/cli/chunk-c8chx29p.js.map +0 -36
- package/dist/cli/chunk-e04dxsz1.js +0 -39
- package/dist/cli/chunk-e04dxsz1.js.map +0 -10
- package/dist/cli/chunk-j85vccga.js.map +0 -36
- package/dist/cli/chunk-p3v96n38.js.map +0 -10
- package/dist/cli/chunk-pehfxfta.js.map +0 -10
- package/dist/cli/chunk-pv29h0wf.js.map +0 -190
- package/dist/cli/chunk-q58y5e6a.js.map +0 -10
- package/dist/cli/chunk-vg9r4eb9.js.map +0 -14
- package/dist/cli/chunk-wrr3j9w9.js.map +0 -35
- package/dist/cli/chunk-yfyb25rh.js.map +0 -14
- package/docs/content/sources.mdx +0 -334
- /package/dist/cli/{chunk-tkacnehg.js.map → chunk-3v3ffbrj.js.map} +0 -0
- /package/dist/cli/{chunk-r9rcc4w7.js.map → chunk-8y2kmjv8.js.map} +0 -0
- /package/dist/cli/{chunk-2eytanqx.js.map → chunk-c887fj0s.js.map} +0 -0
- /package/dist/cli/{chunk-akbpwfxc.js.map → chunk-dzwehpy7.js.map} +0 -0
- /package/dist/cli/{chunk-2z928egk.js.map → chunk-ft9vfys6.js.map} +0 -0
- /package/dist/cli/{chunk-a58773jm.js.map → chunk-kma9f6sf.js.map} +0 -0
- /package/dist/cli/{chunk-crgn1q09.js.map → chunk-sds923fa.js.map} +0 -0
- /package/dist/cli/{chunk-acanzt5p.js.map → chunk-tdqhyxfz.js.map} +0 -0
package/src/eval/report.ts
CHANGED
|
@@ -10,27 +10,40 @@ import { duration, money, seconds } from "../cli/report-format.ts";
|
|
|
10
10
|
import { countBySeverity } from "../core/diagnostics.ts";
|
|
11
11
|
import type { EvalResult, QuestionResult, QuestionStatus } from "./run.ts";
|
|
12
12
|
|
|
13
|
+
/** How a question reads in the report: its status, or `warn` for a warned miss. */
|
|
14
|
+
type ShownStatus = QuestionStatus | "warn";
|
|
15
|
+
|
|
13
16
|
const GLYPH = {
|
|
14
17
|
error: "!",
|
|
15
18
|
fail: "✖",
|
|
16
19
|
pass: "✔",
|
|
17
20
|
skip: "⊘",
|
|
18
|
-
|
|
21
|
+
warn: "⚠",
|
|
22
|
+
} satisfies Record<ShownStatus, string>;
|
|
19
23
|
|
|
20
24
|
const STATUS_COLOR = {
|
|
21
25
|
error: colors.yellow,
|
|
22
26
|
fail: colors.red,
|
|
23
27
|
pass: colors.green,
|
|
24
28
|
skip: colors.dim,
|
|
25
|
-
|
|
29
|
+
warn: colors.yellow,
|
|
30
|
+
} satisfies Record<ShownStatus, ColorFunction>;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* A failed `severity: warning` question: its miss never counts against the
|
|
34
|
+
* gate, so the report shows and counts it as a warning, not a failure.
|
|
35
|
+
*/
|
|
36
|
+
const warned = (result: QuestionResult): boolean =>
|
|
37
|
+
result.status === "fail" && result.severity === "warning";
|
|
26
38
|
|
|
27
39
|
/** Longest id gets the room; everything shorter aligns to it. */
|
|
28
40
|
const ID_PAD = 28;
|
|
29
41
|
|
|
30
42
|
/** One question's progress/report line: glyph, id, status, score, time, cost. */
|
|
31
43
|
export const questionLine = (result: QuestionResult): string => {
|
|
32
|
-
const
|
|
33
|
-
const
|
|
44
|
+
const shown: ShownStatus = warned(result) ? "warn" : result.status;
|
|
45
|
+
const color = STATUS_COLOR[shown];
|
|
46
|
+
const glyph = color(GLYPH[shown]);
|
|
34
47
|
const id = result.id.padEnd(ID_PAD);
|
|
35
48
|
if (result.status === "skip") {
|
|
36
49
|
return ` ${glyph} ${id} ${colors.dim("skipped")}`;
|
|
@@ -38,7 +51,7 @@ export const questionLine = (result: QuestionResult): string => {
|
|
|
38
51
|
const score = result.score === undefined ? "" : result.score.toFixed(2);
|
|
39
52
|
const cost = money(result.costUsd);
|
|
40
53
|
const cells = [
|
|
41
|
-
color(
|
|
54
|
+
color(shown),
|
|
42
55
|
score,
|
|
43
56
|
colors.dim(seconds(result.durationMs)),
|
|
44
57
|
cost === "" ? "" : colors.dim(cost),
|
|
@@ -75,9 +88,12 @@ export const questionDetails = (
|
|
|
75
88
|
/** The one-line totals: `9 passed · 2 failed · 1 skipped · 1m 42s · $0.71`. */
|
|
76
89
|
export const summaryLine = (result: EvalResult): string => {
|
|
77
90
|
const { counts } = result;
|
|
91
|
+
const warnings = result.results.filter(warned).length;
|
|
92
|
+
const failures = counts.fail - warnings;
|
|
78
93
|
const parts = [
|
|
79
94
|
`${counts.pass} passed`,
|
|
80
|
-
|
|
95
|
+
failures > 0 ? `${failures} failed` : "",
|
|
96
|
+
warnings > 0 ? `${warnings} warned` : "",
|
|
81
97
|
counts.error > 0 ? `${counts.error} errored` : "",
|
|
82
98
|
counts.skip > 0 ? `${counts.skip} skipped` : "",
|
|
83
99
|
duration(result.durationMs),
|
|
@@ -98,10 +114,11 @@ export const startLine = (id: string, index: number, total: number): string =>
|
|
|
98
114
|
* `fix:` pointers for failed questions, naming the file that resolves each. A
|
|
99
115
|
* question whose agent run errored gets a `run failed:` line pointing at the
|
|
100
116
|
* question instead: the run never graded the docs, so there's no page to fix.
|
|
117
|
+
* A `severity: warning` question's miss is a warning line instead.
|
|
101
118
|
*/
|
|
102
119
|
export const fixLines = (result: EvalResult, root: string): string[] =>
|
|
103
120
|
result.diagnostics
|
|
104
|
-
.filter((diagnostic) => diagnostic.
|
|
121
|
+
.filter((diagnostic) => diagnostic.severity !== "warning")
|
|
105
122
|
.map((finding) => {
|
|
106
123
|
const site = finding.file
|
|
107
124
|
? `${relative(root, finding.file)}${finding.line ? `:${finding.line}` : ""}`
|
|
@@ -113,10 +130,13 @@ export const fixLines = (result: EvalResult, root: string): string[] =>
|
|
|
113
130
|
return ` ${label} ${site} ${colors.dim(finding.message)}`;
|
|
114
131
|
});
|
|
115
132
|
|
|
116
|
-
/**
|
|
133
|
+
/**
|
|
134
|
+
* Dim warnings: route hints that no longer match a page, and the misses of
|
|
135
|
+
* `severity: warning` questions.
|
|
136
|
+
*/
|
|
117
137
|
export const warningLines = (result: EvalResult, root: string): string[] =>
|
|
118
138
|
result.diagnostics
|
|
119
|
-
.filter((diagnostic) => diagnostic.
|
|
139
|
+
.filter((diagnostic) => diagnostic.severity === "warning")
|
|
120
140
|
.map((finding) => {
|
|
121
141
|
const site = finding.file
|
|
122
142
|
? ` ${relative(root, finding.file)}${finding.line ? `:${finding.line}` : ""}`
|
|
@@ -140,10 +160,11 @@ export const formatEvalReport = (
|
|
|
140
160
|
}
|
|
141
161
|
lines.push("");
|
|
142
162
|
|
|
143
|
-
// The finding tells the author which file fixes which failure
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
163
|
+
// The finding tells the author which file fixes which failure, warnings
|
|
164
|
+
// first, as the command prints them.
|
|
165
|
+
const findings = [...warningLines(result, root), ...fixLines(result, root)];
|
|
166
|
+
lines.push(...findings);
|
|
167
|
+
if (findings.length > 0) {
|
|
147
168
|
lines.push("");
|
|
148
169
|
}
|
|
149
170
|
|
package/src/eval/run.ts
CHANGED
|
@@ -40,6 +40,8 @@ export interface QuestionResult {
|
|
|
40
40
|
question: string;
|
|
41
41
|
routes: string[];
|
|
42
42
|
score?: number;
|
|
43
|
+
/** The question's severity: a `warning` miss is reported as a warning. */
|
|
44
|
+
severity?: EvalQuestion["severity"];
|
|
43
45
|
status: QuestionStatus;
|
|
44
46
|
}
|
|
45
47
|
|
|
@@ -99,6 +101,7 @@ const errored = (
|
|
|
99
101
|
missing: [],
|
|
100
102
|
question: question.question,
|
|
101
103
|
routes: question.routes,
|
|
104
|
+
severity: question.severity,
|
|
102
105
|
status: "error",
|
|
103
106
|
});
|
|
104
107
|
|
|
@@ -177,6 +180,7 @@ const runQuestion = async (
|
|
|
177
180
|
question: question.question,
|
|
178
181
|
routes: question.routes,
|
|
179
182
|
score: verdict.score,
|
|
183
|
+
severity: question.severity,
|
|
180
184
|
status: verdict.pass ? "pass" : "fail",
|
|
181
185
|
};
|
|
182
186
|
};
|
|
@@ -250,6 +254,7 @@ export const runEval = async (options: EvalRunOptions): Promise<EvalResult> => {
|
|
|
250
254
|
missing: [],
|
|
251
255
|
question: question.question,
|
|
252
256
|
routes: question.routes,
|
|
257
|
+
severity: question.severity,
|
|
253
258
|
status: "skip",
|
|
254
259
|
});
|
|
255
260
|
continue;
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import type { EvaluatedValue } from "../ai/component-markdown.ts";
|
|
2
|
+
import { readStaticExpression } from "../ai/static-expression.ts";
|
|
3
|
+
import { PARAM_LOCATIONS } from "../components/content/api-field.ts";
|
|
4
|
+
import type { FieldValue } from "../components/content/api-field.ts";
|
|
5
|
+
import {
|
|
6
|
+
AUTH_METHODS,
|
|
7
|
+
PLAYGROUND_MODES,
|
|
8
|
+
parseApiEndpoint,
|
|
9
|
+
} from "../components/content/api-page.ts";
|
|
10
|
+
import type {
|
|
11
|
+
EndpointField,
|
|
12
|
+
EndpointSpec,
|
|
13
|
+
} from "../components/content/api-page.ts";
|
|
14
|
+
import { jsxAttribute, jsxFlowElement } from "./mdast.ts";
|
|
15
|
+
import type { MdastNode, MdastValue } from "./mdast.ts";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The right-hand column of a hand-written API page, as Mintlify renders one.
|
|
19
|
+
* Top-level `<RequestExample>` and `<ResponseExample>` move into an
|
|
20
|
+
* `<ApiRail>` at the end of the document, request examples first, and the
|
|
21
|
+
* render is flagged so the layout makes room for the column (see
|
|
22
|
+
* `ApiRail.astro`). Below `xl` the rail follows the page's content, and the
|
|
23
|
+
* examples are ordinary code groups there. An example nested in another
|
|
24
|
+
* component stays where it is written.
|
|
25
|
+
*
|
|
26
|
+
* A page with `api` frontmatter (`POST /v1/users`) also gets its endpoint: the
|
|
27
|
+
* method and path at the top of the page (`<ApiEndpoint>`), and at the head of
|
|
28
|
+
* the rail a Try it panel and request samples (`<ApiPlayground>`) built from
|
|
29
|
+
* the page's `<ParamField>`s, which the plugin collects here, nested body
|
|
30
|
+
* fields included (see `components/content/api-page.ts`).
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/** The render-frontmatter key that tells the layout a page has a rail. */
|
|
34
|
+
export const API_RAIL_KEY = "blumeApiRail";
|
|
35
|
+
|
|
36
|
+
/** The components that move to the rail, in the order they stack there. */
|
|
37
|
+
const RAIL_COMPONENTS = ["RequestExample", "ResponseExample"];
|
|
38
|
+
|
|
39
|
+
/** The root, as the plugin's `after` hook receives it. */
|
|
40
|
+
interface RailRoot {
|
|
41
|
+
children: MdastNode[];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** The slice of Satteri's visitor context the plugin uses. */
|
|
45
|
+
export interface ApiRailContext {
|
|
46
|
+
appendChild: (node: RailRoot, child: MdastNode) => void;
|
|
47
|
+
data?: { astro?: { frontmatter?: Record<string, EvaluatedValue> } };
|
|
48
|
+
insertChildAt: (node: RailRoot, index: number, child: MdastNode) => void;
|
|
49
|
+
removeNode: (node: MdastNode) => void;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* A detached copy of a node Satteri materialized lazily: its own fields,
|
|
54
|
+
* children included, without the arena handles that tie it to its old place.
|
|
55
|
+
* Appending the original instead would move an empty shell.
|
|
56
|
+
*/
|
|
57
|
+
const detach = (node: MdastNode): MdastNode =>
|
|
58
|
+
JSON.parse(
|
|
59
|
+
JSON.stringify(node, (key: string, value: MdastValue) =>
|
|
60
|
+
key === "_id" || key === "_resolver" ? undefined : value
|
|
61
|
+
)
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
const isName = <Value>(value: Value): value is Value & string =>
|
|
65
|
+
typeof value === "string";
|
|
66
|
+
|
|
67
|
+
const railIndex = (node: MdastNode): number =>
|
|
68
|
+
node.type === "mdxJsxFlowElement" && isName(node.name)
|
|
69
|
+
? RAIL_COMPONENTS.indexOf(node.name)
|
|
70
|
+
: -1;
|
|
71
|
+
|
|
72
|
+
/** An element's name, when it is a JSX element. */
|
|
73
|
+
const elementName = (node: MdastNode): string | undefined =>
|
|
74
|
+
node.type === "mdxJsxFlowElement" && isName(node.name)
|
|
75
|
+
? node.name
|
|
76
|
+
: undefined;
|
|
77
|
+
|
|
78
|
+
const isNode = (value: MdastValue): value is MdastNode =>
|
|
79
|
+
typeof value === "object" && value !== null && !Array.isArray(value);
|
|
80
|
+
|
|
81
|
+
/** A node's children, when it has any. */
|
|
82
|
+
const childrenOf = (node: MdastNode): MdastNode[] =>
|
|
83
|
+
Array.isArray(node.children) ? node.children.filter(isNode) : [];
|
|
84
|
+
|
|
85
|
+
/** One JSX attribute, as the parser leaves it. */
|
|
86
|
+
interface JsxAttribute {
|
|
87
|
+
name?: string;
|
|
88
|
+
type: string;
|
|
89
|
+
value?: string | { value: string } | null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const isAttribute = (value: MdastValue): value is JsxAttribute & MdastNode =>
|
|
93
|
+
isNode(value) && value.type === "mdxJsxAttribute";
|
|
94
|
+
|
|
95
|
+
/** An element's attributes, name to value. */
|
|
96
|
+
interface AttributeValues {
|
|
97
|
+
[name: string]: EvaluatedValue;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* An element's attributes as values: text, shorthand flags as `true`, and
|
|
102
|
+
* expressions read as literal data (see `ai/static-expression.ts`); one that
|
|
103
|
+
* isn't literal is left out.
|
|
104
|
+
*/
|
|
105
|
+
const attributeValues = (
|
|
106
|
+
node: MdastNode,
|
|
107
|
+
frontmatter: Record<string, EvaluatedValue> | undefined
|
|
108
|
+
): AttributeValues => {
|
|
109
|
+
const values: AttributeValues = {};
|
|
110
|
+
const attributes = Array.isArray(node.attributes) ? node.attributes : [];
|
|
111
|
+
for (const attribute of attributes.filter(isAttribute)) {
|
|
112
|
+
const { name, value } = attribute;
|
|
113
|
+
if (!name) {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (value === null || value === undefined) {
|
|
117
|
+
values[name] = true;
|
|
118
|
+
} else if (isName(value)) {
|
|
119
|
+
values[name] = value;
|
|
120
|
+
} else {
|
|
121
|
+
const read = readStaticExpression(value.value, frontmatter);
|
|
122
|
+
if (read.ok) {
|
|
123
|
+
values[name] = read.value;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return values;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const isFlag = (value: EvaluatedValue): boolean =>
|
|
131
|
+
value === true || value === "true";
|
|
132
|
+
|
|
133
|
+
/** A `<ParamField>`'s values as an endpoint field, or `null` with no location. */
|
|
134
|
+
const endpointField = (values: AttributeValues): EndpointField | null => {
|
|
135
|
+
const location = PARAM_LOCATIONS.find((key) => isName(values[key]));
|
|
136
|
+
const name = location ? values[location] : undefined;
|
|
137
|
+
if (!(location && isName(name))) {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
const field: EndpointField = { location, name };
|
|
141
|
+
if (isName(values.type)) {
|
|
142
|
+
field.type = values.type;
|
|
143
|
+
}
|
|
144
|
+
if (isName(values.placeholder)) {
|
|
145
|
+
field.placeholder = values.placeholder;
|
|
146
|
+
}
|
|
147
|
+
if (isFlag(values.required)) {
|
|
148
|
+
field.required = true;
|
|
149
|
+
}
|
|
150
|
+
if (isFlag(values.deprecated)) {
|
|
151
|
+
field.deprecated = true;
|
|
152
|
+
}
|
|
153
|
+
if (values.default !== undefined) {
|
|
154
|
+
// SAFETY: an attribute's literal data is JSON-shaped; a frontmatter
|
|
155
|
+
// date only arrives through `frontmatter.*`, which a default never reads.
|
|
156
|
+
field.default = values.default as FieldValue;
|
|
157
|
+
}
|
|
158
|
+
return field;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* The `<ParamField>`s under `nodes`, in document order. A field's own nested
|
|
163
|
+
* fields (in its `<Expandable>`) become its `fields`, the properties of the
|
|
164
|
+
* object it describes.
|
|
165
|
+
*/
|
|
166
|
+
const collectFields = (
|
|
167
|
+
nodes: MdastNode[],
|
|
168
|
+
frontmatter: Record<string, EvaluatedValue> | undefined
|
|
169
|
+
): EndpointField[] =>
|
|
170
|
+
nodes.flatMap((node) => {
|
|
171
|
+
const nested = collectFields(childrenOf(node), frontmatter);
|
|
172
|
+
if (elementName(node) !== "ParamField") {
|
|
173
|
+
return nested;
|
|
174
|
+
}
|
|
175
|
+
const field = endpointField(attributeValues(node, frontmatter));
|
|
176
|
+
if (!field) {
|
|
177
|
+
return nested;
|
|
178
|
+
}
|
|
179
|
+
return nested.length > 0 ? [{ ...field, fields: nested }] : [field];
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
/** The page's endpoint, when its `api` frontmatter names one. */
|
|
183
|
+
const endpointSpec = (
|
|
184
|
+
root: RailRoot,
|
|
185
|
+
frontmatter: Record<string, EvaluatedValue> | undefined,
|
|
186
|
+
requestExample: boolean
|
|
187
|
+
): EndpointSpec | null => {
|
|
188
|
+
const api = frontmatter?.api;
|
|
189
|
+
const endpoint = isName(api) ? parseApiEndpoint(api) : null;
|
|
190
|
+
if (!endpoint) {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
const spec: EndpointSpec = {
|
|
194
|
+
fields: collectFields(root.children, frontmatter),
|
|
195
|
+
method: endpoint.method,
|
|
196
|
+
requestExample,
|
|
197
|
+
target: endpoint.target,
|
|
198
|
+
};
|
|
199
|
+
const authMethod = AUTH_METHODS.find(
|
|
200
|
+
(method) => method === frontmatter?.authMethod
|
|
201
|
+
);
|
|
202
|
+
if (authMethod) {
|
|
203
|
+
spec.authMethod = authMethod;
|
|
204
|
+
}
|
|
205
|
+
const playground = PLAYGROUND_MODES.find(
|
|
206
|
+
(mode) => mode === frontmatter?.playground
|
|
207
|
+
);
|
|
208
|
+
if (playground) {
|
|
209
|
+
spec.playground = playground;
|
|
210
|
+
}
|
|
211
|
+
return spec;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
/** Where the endpoint header goes: after a front matter block, if any. */
|
|
215
|
+
const headerIndex = (root: RailRoot): number =>
|
|
216
|
+
root.children.findIndex(
|
|
217
|
+
(node) => node.type !== "yaml" && node.type !== "toml"
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
export const apiRailPlugin = () => ({
|
|
221
|
+
after(root: RailRoot, ctx: ApiRailContext) {
|
|
222
|
+
const frontmatter = ctx.data?.astro?.frontmatter;
|
|
223
|
+
const examples = root.children.filter((node) => railIndex(node) !== -1);
|
|
224
|
+
const spec = endpointSpec(
|
|
225
|
+
root,
|
|
226
|
+
frontmatter,
|
|
227
|
+
examples.some((node) => railIndex(node) === 0)
|
|
228
|
+
);
|
|
229
|
+
const specAttribute = spec
|
|
230
|
+
? [jsxAttribute("spec", JSON.stringify(spec))]
|
|
231
|
+
: [];
|
|
232
|
+
const playground =
|
|
233
|
+
spec && spec.playground !== "none"
|
|
234
|
+
? [jsxFlowElement("ApiPlayground", specAttribute, [])]
|
|
235
|
+
: [];
|
|
236
|
+
for (const example of examples) {
|
|
237
|
+
ctx.removeNode(example);
|
|
238
|
+
}
|
|
239
|
+
if (spec) {
|
|
240
|
+
ctx.insertChildAt(
|
|
241
|
+
root,
|
|
242
|
+
Math.max(headerIndex(root), 0),
|
|
243
|
+
jsxFlowElement("ApiEndpoint", specAttribute, [])
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
const rail = [
|
|
247
|
+
...playground,
|
|
248
|
+
...examples.toSorted((a, b) => railIndex(a) - railIndex(b)).map(detach),
|
|
249
|
+
];
|
|
250
|
+
if (rail.length === 0) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
ctx.appendChild(root, jsxFlowElement("ApiRail", [], rail));
|
|
254
|
+
if (frontmatter) {
|
|
255
|
+
frontmatter[API_RAIL_KEY] = true;
|
|
256
|
+
}
|
|
257
|
+
},
|
|
258
|
+
name: "blume-api-rail",
|
|
259
|
+
});
|
|
@@ -7,6 +7,12 @@
|
|
|
7
7
|
* 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
|
+
* - the `wrap` keyword becomes `data-wrap`: this block's long lines wrap
|
|
11
|
+
* instead of scrolling, as `markdown.code.wrap` does for every block.
|
|
12
|
+
* - the `expandable` keyword becomes `data-expandable` on a block of
|
|
13
|
+
* {@link EXPANDABLE_MIN_LINES} lines or more: the theme shows its first
|
|
14
|
+
* {@link EXPANDABLE_VISIBLE_LINES} lines, and the page script adds a toggle
|
|
15
|
+
* that shows the rest in full. A shorter block renders as it is.
|
|
10
16
|
*/
|
|
11
17
|
|
|
12
18
|
import {
|
|
@@ -16,9 +22,20 @@ import {
|
|
|
16
22
|
RESERVED_META_KEYWORDS,
|
|
17
23
|
} from "./fence-meta.ts";
|
|
18
24
|
|
|
25
|
+
/** The lines a collapsed `expandable` block shows. */
|
|
26
|
+
export const EXPANDABLE_VISIBLE_LINES = 10;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The lines a block needs before `expandable` collapses it: a few more than it
|
|
30
|
+
* shows, so the toggle never hides a line or two behind a click.
|
|
31
|
+
*/
|
|
32
|
+
export const EXPANDABLE_MIN_LINES = 16;
|
|
33
|
+
|
|
19
34
|
/** The slice of Shiki's transformer `this` context Blume reads. */
|
|
20
35
|
interface CodeMetaContext {
|
|
21
36
|
options: { meta?: { __raw?: string } };
|
|
37
|
+
/** The block's code, as highlighted. */
|
|
38
|
+
source?: string;
|
|
22
39
|
}
|
|
23
40
|
|
|
24
41
|
/** The `<pre>` hast node a Shiki `pre` hook receives. */
|
|
@@ -33,12 +50,6 @@ export interface CodeTitleTransformer {
|
|
|
33
50
|
}
|
|
34
51
|
|
|
35
52
|
const TITLE_ATTR = /(?:^|\s)title=(?:"(?<dq>[^"]*)"|'(?<sq>[^']*)')/u;
|
|
36
|
-
const LINE_NUMBERS = /(?:^|\s)lineNumbers(?=\s|$)/u;
|
|
37
|
-
|
|
38
|
-
// Quoted attrs are blanked before keyword/bare-token scans so a quoted value
|
|
39
|
-
// can't leak tokens (`title="enable lineNumbers later"`).
|
|
40
|
-
const withoutQuotedAttrs = (raw: string): string =>
|
|
41
|
-
raw.replace(QUOTED_ATTR, " ");
|
|
42
53
|
|
|
43
54
|
// The first bare token is the title (```ts blume.config.ts): a non-empty token
|
|
44
55
|
// that isn't a Shiki line range (`{1,3-5}`), a `key=value` attr, or a reserved
|
|
@@ -71,8 +82,14 @@ export const parseCodeTitle = (raw: string | undefined): string | undefined => {
|
|
|
71
82
|
return metaTokens(raw).find(isTitleToken);
|
|
72
83
|
};
|
|
73
84
|
|
|
74
|
-
|
|
75
|
-
|
|
85
|
+
// The shared tokenizer keeps a quoted attr whole, so a keyword inside a
|
|
86
|
+
// quoted value (`title="enable lineNumbers later"`) is never a token of its own.
|
|
87
|
+
const hasKeyword = (raw: string | undefined, keyword: string): boolean =>
|
|
88
|
+
metaTokens(raw).includes(keyword);
|
|
89
|
+
|
|
90
|
+
/** How many lines a block's code runs to, a trailing newline aside. */
|
|
91
|
+
export const lineCount = (source = ""): number =>
|
|
92
|
+
source === "" ? 0 : source.replace(/\r?\n$/u, "").split(/\r?\n/u).length;
|
|
76
93
|
|
|
77
94
|
/** Build the transformer. Runs after Shiki's built-in `data-language` hook. */
|
|
78
95
|
export const codeTitleTransformer = (): CodeTitleTransformer => ({
|
|
@@ -83,8 +100,17 @@ export const codeTitleTransformer = (): CodeTitleTransformer => ({
|
|
|
83
100
|
if (title) {
|
|
84
101
|
node.properties.dataTitle = title;
|
|
85
102
|
}
|
|
86
|
-
if (
|
|
103
|
+
if (hasKeyword(raw, "lineNumbers")) {
|
|
87
104
|
node.properties.dataLineNumbers = true;
|
|
88
105
|
}
|
|
106
|
+
if (hasKeyword(raw, "wrap")) {
|
|
107
|
+
node.properties.dataWrap = true;
|
|
108
|
+
}
|
|
109
|
+
if (
|
|
110
|
+
hasKeyword(raw, "expandable") &&
|
|
111
|
+
lineCount(this.source) >= EXPANDABLE_MIN_LINES
|
|
112
|
+
) {
|
|
113
|
+
node.properties.dataExpandable = true;
|
|
114
|
+
}
|
|
89
115
|
},
|
|
90
116
|
});
|
package/src/markdown/features.ts
CHANGED
|
@@ -11,8 +11,9 @@ 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,
|
|
@@ -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,6 +9,9 @@ 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";
|
|
@@ -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
|
|
@@ -326,7 +337,12 @@ const blumeSharedMdastPlugins = (
|
|
|
326
337
|
* (callouts, mermaid, math, base links) like inline content.
|
|
327
338
|
*/
|
|
328
339
|
const blumeIncludePlugin = (options: BlumeMarkdownOptions): MdastPlugin =>
|
|
329
|
-
asMdastPlugin(
|
|
340
|
+
asMdastPlugin(
|
|
341
|
+
includePlugin({
|
|
342
|
+
contentRoot: options.contentRoot,
|
|
343
|
+
variables: options.variables,
|
|
344
|
+
})
|
|
345
|
+
);
|
|
330
346
|
|
|
331
347
|
/** Sätteri processor for plain `.md`, with Blume's curated feature set. */
|
|
332
348
|
export const blumeMarkdownProcessor = (options: BlumeMarkdownOptions = {}) =>
|
|
@@ -335,6 +351,9 @@ export const blumeMarkdownProcessor = (options: BlumeMarkdownOptions = {}) =>
|
|
|
335
351
|
hastPlugins: blumeHastPlugins(options),
|
|
336
352
|
mdastPlugins: [
|
|
337
353
|
blumeIncludePlugin(options),
|
|
354
|
+
...(hasVariables(options.variables)
|
|
355
|
+
? [asMdastPlugin(variablesPlugin(options.variables))]
|
|
356
|
+
: []),
|
|
338
357
|
...blumeSharedMdastPlugins(options),
|
|
339
358
|
],
|
|
340
359
|
});
|
|
@@ -345,13 +364,15 @@ export type BlumeMdxOptions = BlumeMarkdownOptions;
|
|
|
345
364
|
* Sätteri MDX processor: Blume's feature set plus the MDAST plugins that target
|
|
346
365
|
* components — `package-install` → package-manager tabs, ` ```ts ts2js ` →
|
|
347
366
|
* TypeScript/JavaScript tabs, `:::note` → `<Callout>`, ` ```mermaid ` → a
|
|
348
|
-
* `<blume-mermaid>` element,
|
|
349
|
-
* (`$$…$$`) → 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
|
|
350
370
|
* `@astrojs/mdx` so these apply to `.mdx` only (plain `.md` uses
|
|
351
371
|
* {@link blumeMarkdownProcessor}).
|
|
352
372
|
*
|
|
353
|
-
* Math is always on
|
|
354
|
-
* `$` (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
|
|
355
376
|
* generated runtime imports the `<Math>` component (and KaTeX's stylesheet) only
|
|
356
377
|
* when content actually uses `$$`, so a math-free site ships no KaTeX CSS.
|
|
357
378
|
*
|
|
@@ -370,5 +391,7 @@ export const blumeMdxProcessor = (options: BlumeMdxOptions = {}) =>
|
|
|
370
391
|
asMdastPlugin(mermaidPlugin()),
|
|
371
392
|
asMdastPlugin(mathPlugin()),
|
|
372
393
|
...blumeSharedMdastPlugins(options),
|
|
394
|
+
asMdastPlugin(apiRailPlugin()),
|
|
395
|
+
asMdastPlugin(viewsPlugin()),
|
|
373
396
|
],
|
|
374
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) {
|
|
@@ -266,8 +266,9 @@ export const relativeLinksPlugin = (
|
|
|
266
266
|
|
|
267
267
|
// A component's string `href` (`<Card href="./install">`) is the same kind
|
|
268
268
|
// of link, and `blume validate` reads it as one. Lowercase elements are
|
|
269
|
-
// raw HTML in a `.md` page, which
|
|
270
|
-
//
|
|
269
|
+
// raw HTML in a `.md` page, which isn't rewritten, so only components are
|
|
270
|
+
// rewritten (validate reads a raw `<a href>` as the browser does); an
|
|
271
|
+
// expression-valued `href={…}` is left alone.
|
|
271
272
|
const rewriteHref = (node: JsxNode, ctx: RelativeLinksContext): void => {
|
|
272
273
|
if (!node.name || !COMPONENT_NAME.test(node.name)) {
|
|
273
274
|
return;
|