blume 2.0.3 → 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 +48 -0
- package/README.md +1 -1
- package/dist/cli/{chunk-1d7ve1dm.js → chunk-0gz36akr.js} +18 -2
- package/dist/cli/{chunk-1d7ve1dm.js.map → chunk-0gz36akr.js.map} +3 -3
- package/dist/cli/{chunk-2eytanqx.js → chunk-1n228xqb.js} +2 -2
- package/dist/cli/{chunk-yfyb25rh.js → chunk-2f3ndkpw.js} +24 -8
- package/dist/cli/chunk-2f3ndkpw.js.map +14 -0
- package/dist/cli/{chunk-r20tn01b.js → chunk-2f7n4qzt.js} +8 -2
- package/dist/cli/{chunk-r20tn01b.js.map → chunk-2f7n4qzt.js.map} +3 -3
- package/dist/cli/{chunk-35d4wj9f.js → chunk-2n4ps1b3.js} +7 -7
- package/dist/cli/{chunk-j85vccga.js → chunk-43zcf4gz.js} +97 -57
- package/dist/cli/{chunk-j85vccga.js.map → chunk-43zcf4gz.js.map} +6 -6
- package/dist/cli/{chunk-e04dxsz1.js → chunk-4ejxbzee.js} +1 -1
- package/dist/cli/{chunk-5m5nmvyq.js → chunk-4h8z9vv5.js} +233 -39
- package/dist/cli/chunk-4h8z9vv5.js.map +16 -0
- package/dist/cli/{chunk-5f86nr5m.js → chunk-5cg2rzgf.js} +18 -16
- package/dist/cli/{chunk-5f86nr5m.js.map → chunk-5cg2rzgf.js.map} +2 -2
- package/dist/cli/{chunk-tzmab476.js → chunk-5ffywsmb.js} +4 -4
- package/dist/cli/{chunk-2z928egk.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-vg9r4eb9.js → chunk-713mngdq.js} +12 -5
- package/dist/cli/{chunk-vg9r4eb9.js.map → chunk-713mngdq.js.map} +3 -3
- package/dist/cli/{chunk-5xvm6tfj.js → chunk-9geymqns.js} +17 -15
- package/dist/cli/{chunk-5xvm6tfj.js.map → chunk-9geymqns.js.map} +2 -2
- package/dist/cli/{chunk-q58y5e6a.js → chunk-9xr4dgee.js} +26 -17
- package/dist/cli/chunk-9xr4dgee.js.map +10 -0
- package/dist/cli/{chunk-b07cmahc.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-akbpwfxc.js → chunk-cmtcnh9f.js} +2 -2
- package/dist/cli/chunk-cy5bm0j0.js +104 -0
- package/dist/cli/chunk-cy5bm0j0.js.map +11 -0
- package/dist/cli/{chunk-crgn1q09.js → chunk-e7vvk5ya.js} +4 -4
- package/dist/cli/{chunk-pehfxfta.js → chunk-g2z9x01v.js} +6 -98
- package/dist/cli/chunk-g2z9x01v.js.map +10 -0
- package/dist/cli/{chunk-tkacnehg.js → chunk-gp84za0h.js} +2 -2
- package/dist/cli/{chunk-wrr3j9w9.js → chunk-h2a48yhd.js} +186 -63
- package/dist/cli/chunk-h2a48yhd.js.map +36 -0
- package/dist/cli/{chunk-hm3vjy5s.js → chunk-jnwj5kjj.js} +14 -9
- package/dist/cli/{chunk-hm3vjy5s.js.map → chunk-jnwj5kjj.js.map} +4 -4
- package/dist/cli/chunk-kwrg63tm.js +31 -0
- package/dist/cli/chunk-kwrg63tm.js.map +10 -0
- package/dist/cli/{chunk-2hsdwb9n.js → chunk-nd1821sk.js} +18 -16
- package/dist/cli/{chunk-2hsdwb9n.js.map → chunk-nd1821sk.js.map} +2 -2
- package/dist/cli/{chunk-6dsbexzp.js → chunk-ntv4qrt7.js} +17 -15
- package/dist/cli/{chunk-6dsbexzp.js.map → chunk-ntv4qrt7.js.map} +2 -2
- package/dist/cli/{chunk-r9rcc4w7.js → chunk-p804f3pe.js} +7 -7
- package/dist/cli/{chunk-ey84smr6.js → chunk-py62fewh.js} +6 -6
- package/dist/cli/{chunk-ey84smr6.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-9t7a85s3.js → chunk-rekqz4qg.js} +23 -13
- package/dist/cli/chunk-rekqz4qg.js.map +10 -0
- package/dist/cli/{chunk-8ktnccpt.js → chunk-ta27feev.js} +1 -1
- package/dist/cli/{chunk-pv29h0wf.js → chunk-xkz5xbtv.js} +3476 -822
- package/dist/cli/chunk-xkz5xbtv.js.map +213 -0
- package/dist/cli/{chunk-a58773jm.js → chunk-y4ykbark.js} +2 -2
- package/dist/cli/{chunk-p3v96n38.js → chunk-y5h4r2y0.js} +4 -4
- package/dist/cli/{chunk-acanzt5p.js → chunk-yj17vs39.js} +6 -6
- package/dist/cli/{chunk-p73c0m7w.js → chunk-yxmk4pec.js} +16 -14
- package/dist/cli/{chunk-p73c0m7w.js.map → chunk-yxmk4pec.js.map} +2 -2
- 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/{chunk-c8chx29p.js → chunk-zf748avv.js} +384 -207
- package/dist/cli/chunk-zf748avv.js.map +37 -0
- package/dist/cli/{chunk-g4hq16wv.js → chunk-zhvd6adm.js} +16 -14
- package/dist/cli/{chunk-g4hq16wv.js.map → chunk-zhvd6adm.js.map} +2 -2
- package/dist/cli/index.js +26 -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/site-skill.d.ts +26 -0
- package/dist/types/ai/skills.d.ts +16 -0
- package/dist/types/astro/integration.d.ts +8 -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/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/config-input.d.ts +187 -20
- package/dist/types/core/data.d.ts +49 -4
- package/dist/types/core/footer.d.ts +8 -0
- package/dist/types/core/i18n-ui.d.ts +86 -0
- package/dist/types/core/includes.d.ts +8 -2
- package/dist/types/core/localizable.d.ts +7 -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 +551 -56
- package/dist/types/core/sources/read.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/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/vercel.d.ts +6 -0
- package/dist/types/deploy/redirects.d.ts +39 -11
- package/dist/types/deploy/vercel-negotiation.d.ts +9 -0
- 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/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 +41 -5
- package/docs/03-upgrading.mdx +4 -4
- package/docs/04-migrating.mdx +1 -1
- package/docs/advanced/changelog.mdx +2 -2
- package/docs/advanced/skills.mdx +14 -0
- package/docs/cli/audit.mdx +21 -1
- package/docs/cli/index.mdx +1 -0
- package/docs/configuration/analytics.mdx +3 -1
- package/docs/configuration/assistant.mdx +188 -36
- package/docs/configuration/consent.mdx +100 -0
- package/docs/configuration/customization.mdx +4 -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 +29 -1
- package/docs/configuration/theming.mdx +3 -1
- package/docs/content/components.mdx +106 -0
- package/docs/content/frontmatter.mdx +76 -0
- package/docs/content/i18n.mdx +38 -3
- 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 +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 +67 -2
- package/docs/content/variables.mdx +41 -0
- package/docs/discoverability/agent-discovery.mdx +29 -2
- package/docs/discoverability/index.mdx +1 -1
- package/docs/discoverability/llms-txt.mdx +1 -1
- package/docs/discoverability/metadata.mdx +17 -0
- package/docs/references/api-pages.mdx +74 -0
- package/docs/references/asyncapi.mdx +1 -1
- package/docs/references/graphql.mdx +2 -2
- package/docs/references/meta.ts +1 -1
- package/docs/references/openapi.mdx +102 -3
- 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/mintlify.md +37 -19
- package/skills/blume-migrate/references/nextra.md +2 -2
- package/skills/blume-migrate/references/starlight.md +2 -1
- 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 +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/component-markdown.ts +75 -0
- package/src/ai/cors.ts +2 -0
- 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/openapi-components.ts +9 -3
- 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 +132 -18
- package/src/astro/index.ts +1 -0
- package/src/astro/integration.ts +35 -0
- package/src/astro/module-types.ts +6 -0
- package/src/astro/templates.ts +283 -30
- 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 +5 -12
- package/src/audit/checks/sitemap.ts +2 -3
- package/src/audit/redirects.ts +46 -15
- package/src/audit/run.ts +2 -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/command-meta.ts +5 -0
- package/src/cli/commands/doctor.ts +22 -16
- package/src/cli/commands/skill.ts +96 -0
- package/src/cli/index.ts +5 -0
- package/src/cli/required-secrets.ts +71 -29
- 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 +62 -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 +100 -0
- package/src/components/content/api-page.ts +224 -0
- 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 +110 -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/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 +308 -45
- package/src/components/layout/Search.astro +31 -17
- package/src/components/layout/SiteFooter.astro +124 -0
- package/src/components/layout/SiteMetatags.astro +16 -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/openapi/Operation.astro +161 -13
- package/src/components/openapi/RequestBody.astro +6 -4
- package/src/components/openapi/RequestPanel.astro +59 -7
- package/src/components/openapi/Responses.astro +6 -4
- package/src/components/openapi/async-snippets.ts +4 -4
- package/src/components/openapi/code-samples.ts +97 -0
- package/src/components/openapi/security.ts +6 -3
- package/src/components/openapi/snippets.ts +869 -8
- 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/client-address.ts +19 -0
- package/src/core/config-input.ts +194 -20
- package/src/core/data.ts +44 -4
- package/src/core/diagnostics.ts +3 -2
- package/src/core/footer.ts +26 -0
- package/src/core/graph.ts +39 -36
- package/src/core/i18n-ui.ts +82 -2
- package/src/core/includes.ts +20 -3
- package/src/core/links.ts +16 -2
- 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/project-graph.ts +111 -5
- package/src/core/redirect-patterns.ts +491 -0
- package/src/core/related.ts +131 -0
- package/src/core/schema.ts +318 -64
- package/src/core/sources/normalize.ts +2 -1
- package/src/core/sources/read.ts +8 -3
- 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/deploy/artifacts.ts +77 -8
- 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 +32 -0
- package/src/deploy/platforms/netlify.ts +33 -1
- package/src/deploy/platforms/vercel.ts +37 -2
- package/src/deploy/redirects.ts +91 -24
- package/src/deploy/vercel-negotiation.ts +36 -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/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/model.ts +57 -24
- package/src/openapi/overlay.ts +256 -0
- package/src/openapi/parse.ts +55 -2
- package/src/openapi/references.ts +21 -5
- package/src/openapi/render-mdx.ts +5 -1
- 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 +20 -4
- package/src/registry/registry.ts +7 -0
- package/src/search/documents.ts +26 -2
- package/src/search/orama-index.ts +28 -3
- package/src/search/pagefind-ranking.ts +39 -0
- 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/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/prompts.ts +1 -0
- package/src/translate/validate.ts +8 -2
- package/src/upgrade/upgrade.ts +4 -171
- 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-9t7a85s3.js.map +0 -10
- package/dist/cli/chunk-c8chx29p.js.map +0 -36
- 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-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-2eytanqx.js.map → chunk-1n228xqb.js.map} +0 -0
- /package/dist/cli/{chunk-35d4wj9f.js.map → chunk-2n4ps1b3.js.map} +0 -0
- /package/dist/cli/{chunk-e04dxsz1.js.map → chunk-4ejxbzee.js.map} +0 -0
- /package/dist/cli/{chunk-tzmab476.js.map → chunk-5ffywsmb.js.map} +0 -0
- /package/dist/cli/{chunk-2z928egk.js.map → chunk-5wj2qwn2.js.map} +0 -0
- /package/dist/cli/{chunk-b07cmahc.js.map → chunk-amrb6hgh.js.map} +0 -0
- /package/dist/cli/{chunk-akbpwfxc.js.map → chunk-cmtcnh9f.js.map} +0 -0
- /package/dist/cli/{chunk-crgn1q09.js.map → chunk-e7vvk5ya.js.map} +0 -0
- /package/dist/cli/{chunk-tkacnehg.js.map → chunk-gp84za0h.js.map} +0 -0
- /package/dist/cli/{chunk-r9rcc4w7.js.map → chunk-p804f3pe.js.map} +0 -0
- /package/dist/cli/{chunk-8ktnccpt.js.map → chunk-ta27feev.js.map} +0 -0
- /package/dist/cli/{chunk-a58773jm.js.map → chunk-y4ykbark.js.map} +0 -0
- /package/dist/cli/{chunk-p3v96n38.js.map → chunk-y5h4r2y0.js.map} +0 -0
- /package/dist/cli/{chunk-acanzt5p.js.map → chunk-yj17vs39.js.map} +0 -0
package/src/core/config-input.ts
CHANGED
|
@@ -2,15 +2,20 @@ import type { AstroIntegration } from "astro";
|
|
|
2
2
|
import type { z } from "zod";
|
|
3
3
|
|
|
4
4
|
import type { AskRetrievalOptions } from "../ai/ask-context.ts";
|
|
5
|
-
import type { AssistantAdapter } from "../ai/ask.ts";
|
|
5
|
+
import type { AssistantAdapter, AssistantGatewayAdapter } from "../ai/ask.ts";
|
|
6
6
|
import type { ComponentMarkdown } from "../ai/component-markdown.ts";
|
|
7
7
|
import type { AnalyticsAdapter } from "../analytics/schema.ts";
|
|
8
|
+
import type { CaptchaAdapter } from "../captcha/schema.ts";
|
|
9
|
+
import type { ConsentAdapter } from "../consent/schema.ts";
|
|
8
10
|
import type { DeploymentInput } from "../deploy/adapters/registry.ts";
|
|
9
11
|
import type { CodeTheme } from "../markdown/themes.ts";
|
|
12
|
+
import type { RateLimitAdapter } from "../ratelimit/schema.ts";
|
|
13
|
+
import type { PlaygroundOptions } from "../reference/options.ts";
|
|
10
14
|
import type { ReferenceAdapter } from "../reference/schema.ts";
|
|
11
15
|
import type { AnySearchAdapter } from "../search/adapters/registry.ts";
|
|
12
16
|
import type { SourceAdapterInput } from "../sources/registry.ts";
|
|
13
17
|
import type { FontSlug } from "../theme/fonts.ts";
|
|
18
|
+
import type { FooterSocial } from "./footer.ts";
|
|
14
19
|
import type {
|
|
15
20
|
blumeConfigSchema,
|
|
16
21
|
OpenInChatProvider,
|
|
@@ -92,21 +97,64 @@ export type LogoConfig =
|
|
|
92
97
|
export type BannerConfig =
|
|
93
98
|
| string
|
|
94
99
|
| {
|
|
95
|
-
/** The banner message. */
|
|
96
|
-
content:
|
|
100
|
+
/** The banner message, or a map of locale code to message. */
|
|
101
|
+
content: LocalizableLabel;
|
|
97
102
|
/** Show a dismiss button; the choice is remembered per visitor. */
|
|
98
103
|
dismissible?: boolean;
|
|
99
|
-
/**
|
|
104
|
+
/**
|
|
105
|
+
* Stable key for remembering dismissal; defaults to the content (the
|
|
106
|
+
* default locale's, for a per-locale map).
|
|
107
|
+
*/
|
|
100
108
|
id?: string;
|
|
101
109
|
/** An optional call-to-action link. */
|
|
102
110
|
link?: {
|
|
103
111
|
/** Link target (internal route or external URL). */
|
|
104
112
|
href: string;
|
|
105
|
-
/** Link text. */
|
|
106
|
-
text:
|
|
113
|
+
/** Link text, or a map of locale code to text. */
|
|
114
|
+
text: LocalizableLabel;
|
|
107
115
|
};
|
|
108
116
|
};
|
|
109
117
|
|
|
118
|
+
/** Defaults for hand-written endpoint pages, the ones with `api` frontmatter. */
|
|
119
|
+
export interface ApiConfig {
|
|
120
|
+
/** How requests authenticate, unless a page sets `authMethod`. Defaults to none. */
|
|
121
|
+
auth?: {
|
|
122
|
+
method: "bearer" | "basic" | "key" | "none";
|
|
123
|
+
/** The header an API key goes in. Defaults to `x-api-key`. */
|
|
124
|
+
name?: string;
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* The Try it panel: `false` hides it, and `{ proxy }` sends requests through
|
|
128
|
+
* a CORS proxy, a URL or `true` for the built-in `/_api-proxy` route (server
|
|
129
|
+
* output only). Defaults to `true`, sending directly.
|
|
130
|
+
*/
|
|
131
|
+
playground?: PlaygroundOptions;
|
|
132
|
+
/** The base URL an `api` path joins, like `https://api.acme.com/v1`. */
|
|
133
|
+
server?: string;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** A link in the footer's row. */
|
|
137
|
+
export interface FooterLink {
|
|
138
|
+
/** Link target (internal route or external URL). An external href opens in a new tab. */
|
|
139
|
+
href: string;
|
|
140
|
+
/** Link text, or a map of locale code to text. */
|
|
141
|
+
label: LocalizableLabel;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* The site footer, below the content on every page: a row of links on one
|
|
146
|
+
* side, and social profile icons on the other.
|
|
147
|
+
*/
|
|
148
|
+
export interface FooterConfig {
|
|
149
|
+
/** Links in one row, left to right. */
|
|
150
|
+
links?: FooterLink[];
|
|
151
|
+
/**
|
|
152
|
+
* Social profiles, platform to URL, shown as icons in the order written:
|
|
153
|
+
* `{ github: "https://github.com/acme", x: "https://x.com/acme" }`.
|
|
154
|
+
*/
|
|
155
|
+
socials?: Partial<Record<FooterSocial, string>>;
|
|
156
|
+
}
|
|
157
|
+
|
|
110
158
|
/**
|
|
111
159
|
* Where content lives and how it's discovered. `root`/`include`/`exclude` are
|
|
112
160
|
* zero-config shorthand for a single `filesystem()` source; set `sources` to
|
|
@@ -203,7 +251,8 @@ export interface ContentTypeConfig {
|
|
|
203
251
|
// ---------------------------------------------------------------------------
|
|
204
252
|
|
|
205
253
|
/**
|
|
206
|
-
* A
|
|
254
|
+
* A label, optionally per locale (header tabs and links, the banner, the
|
|
255
|
+
* footer): a plain string, or a map of locale
|
|
207
256
|
* code to label (`{ en: "Docs", ja: "ドキュメント" }`). The active locale's
|
|
208
257
|
* entry wins, then the default locale's, then the map's first entry.
|
|
209
258
|
*/
|
|
@@ -286,8 +335,8 @@ export interface FeaturedLink {
|
|
|
286
335
|
href: string;
|
|
287
336
|
/** Lucide icon name shown beside the label. */
|
|
288
337
|
icon?: string;
|
|
289
|
-
/** Link label. */
|
|
290
|
-
label:
|
|
338
|
+
/** Link label, or a map of locale code to label. */
|
|
339
|
+
label: LocalizableLabel;
|
|
291
340
|
}
|
|
292
341
|
|
|
293
342
|
/**
|
|
@@ -312,8 +361,8 @@ export type SidebarConfig =
|
|
|
312
361
|
export interface HeaderAction {
|
|
313
362
|
/** Link target. An external href opens in a new tab. */
|
|
314
363
|
href: string;
|
|
315
|
-
/** Link label. */
|
|
316
|
-
label:
|
|
364
|
+
/** Link label, or a map of locale code to label. */
|
|
365
|
+
label: LocalizableLabel;
|
|
317
366
|
}
|
|
318
367
|
|
|
319
368
|
/** Header, sidebar, tabs, and switcher configuration. */
|
|
@@ -325,7 +374,7 @@ export interface NavigationConfig {
|
|
|
325
374
|
/** Pinned links shown above the generated sidebar sections. */
|
|
326
375
|
featured?: FeaturedLink[];
|
|
327
376
|
/**
|
|
328
|
-
* The GitHub link in the
|
|
377
|
+
* The GitHub link in the footer. `true` derives it from `github` (the
|
|
329
378
|
* default), `false` hides it, and an absolute URL points it anywhere on
|
|
330
379
|
* GitHub — an organization, say, when the docs repo itself is private.
|
|
331
380
|
*/
|
|
@@ -520,6 +569,13 @@ export interface AssistantRetrievalConfig {
|
|
|
520
569
|
|
|
521
570
|
/** The chat assistant. */
|
|
522
571
|
export interface AssistantConfig {
|
|
572
|
+
/**
|
|
573
|
+
* A bot check from `blume/captcha` — `turnstile({ siteKey })` or
|
|
574
|
+
* `hcaptcha({ siteKey })`. The panel sends a token with each question and
|
|
575
|
+
* the generated route verifies it (with `TURNSTILE_SECRET_KEY` or
|
|
576
|
+
* `HCAPTCHA_SECRET_KEY`) before the model runs.
|
|
577
|
+
*/
|
|
578
|
+
captcha?: CaptchaAdapter;
|
|
523
579
|
/**
|
|
524
580
|
* Origins allowed to call the generated endpoint from another site — a
|
|
525
581
|
* marketing page that embeds an ask box, for example — or `"*"` to allow
|
|
@@ -548,10 +604,10 @@ export interface AssistantConfig {
|
|
|
548
604
|
instructions?: string;
|
|
549
605
|
/**
|
|
550
606
|
* Which backend answers: the descriptor an adapter factory returns —
|
|
551
|
-
* `
|
|
552
|
-
* `
|
|
553
|
-
* `
|
|
554
|
-
* from `blume/ai`. Each adapter owns its model, key env var, reasoning
|
|
607
|
+
* `openai({ model, baseUrl })`, `anthropic({ model })`,
|
|
608
|
+
* `gemini({ model })`, `grok({ model })`, `gateway({ model })`,
|
|
609
|
+
* `openrouter({ model, reasoning })`, `llmgateway({ model })`, or
|
|
610
|
+
* `inkeep({ model })`, all exported from `blume/ai`. Each adapter owns its model, key env var, reasoning
|
|
555
611
|
* mapping, and `providerOptions` passthrough. Defaults to
|
|
556
612
|
* `gateway({ model: "openai/gpt-5.5" })`.
|
|
557
613
|
*/
|
|
@@ -562,8 +618,23 @@ export interface AssistantConfig {
|
|
|
562
618
|
* backend — at the cost of recall. Defaults keep the built-in behavior.
|
|
563
619
|
*/
|
|
564
620
|
retrieval?: AssistantRetrievalConfig;
|
|
621
|
+
/**
|
|
622
|
+
* A Contact support link in the panel once there's a conversation: a
|
|
623
|
+
* `mailto:` address starts an email with the conversation as its body; a
|
|
624
|
+
* URL or root-relative path gets the conversation's `thread` id, which the
|
|
625
|
+
* assistant's analytics events carry too.
|
|
626
|
+
*/
|
|
627
|
+
support?: string;
|
|
565
628
|
/** Starter prompts shown before the first question. */
|
|
566
629
|
suggestions?: AssistantSuggestion[];
|
|
630
|
+
/**
|
|
631
|
+
* Let the model search the docs and read whole pages itself, over several
|
|
632
|
+
* steps, instead of answering only from the excerpts retrieved up front.
|
|
633
|
+
* Defaults to `true`, except for `openai()` with a `baseUrl`, whose model
|
|
634
|
+
* may not support tool calling. `inkeep()` does its own retrieval and
|
|
635
|
+
* ignores it.
|
|
636
|
+
*/
|
|
637
|
+
tools?: boolean;
|
|
567
638
|
}
|
|
568
639
|
|
|
569
640
|
/** What the AI Catalog (ARD) manifest carries. */
|
|
@@ -693,6 +764,12 @@ export interface I18nConfig {
|
|
|
693
764
|
locales: LocaleConfigInput[];
|
|
694
765
|
/** `dir`: locale directories (`fr/page.mdx`). `dot`: filename suffix (`page.fr.mdx`). */
|
|
695
766
|
parser?: "dir" | "dot";
|
|
767
|
+
/**
|
|
768
|
+
* Send a visitor who lands on the default language's home page to the home
|
|
769
|
+
* page in their browser's preferred language, until they pick a language
|
|
770
|
+
* with the switcher. Defaults to `false`.
|
|
771
|
+
*/
|
|
772
|
+
routeByBrowserLanguage?: boolean;
|
|
696
773
|
/**
|
|
697
774
|
* Per-locale UI string overrides, e.g.
|
|
698
775
|
* `{ fr: { search: { button: "Rechercher" } } }`.
|
|
@@ -802,11 +879,19 @@ type RedirectStatus = RedirectStatusPermanent | RedirectStatusTemporary;
|
|
|
802
879
|
|
|
803
880
|
/** A URL redirect rule. */
|
|
804
881
|
export interface RedirectConfig {
|
|
805
|
-
/**
|
|
882
|
+
/**
|
|
883
|
+
* Path to redirect from: an exact path, or a pattern. `:name` matches one
|
|
884
|
+
* segment, `:name*` as the last segment the rest of the path
|
|
885
|
+
* (`/beta/:slug*`), and `*` ending a segment the rest from there
|
|
886
|
+
* (`/old/article-*`).
|
|
887
|
+
*/
|
|
806
888
|
from: string;
|
|
807
889
|
/** HTTP status. Defaults to `301`. */
|
|
808
890
|
status?: RedirectStatus;
|
|
809
|
-
/**
|
|
891
|
+
/**
|
|
892
|
+
* Path or URL to redirect to. Reads `from`'s captures as `/:name` (or `*`
|
|
893
|
+
* for what `*` matched): `/v2/:slug*`.
|
|
894
|
+
*/
|
|
810
895
|
to: string;
|
|
811
896
|
}
|
|
812
897
|
|
|
@@ -890,6 +975,13 @@ export interface AgentsConfig {
|
|
|
890
975
|
markdownComponents?: Record<string, ComponentMarkdown>;
|
|
891
976
|
/** Expose the docs as an MCP server for agents. */
|
|
892
977
|
mcp?: McpConfig;
|
|
978
|
+
/**
|
|
979
|
+
* Generate the site's own agent skill: a `SKILL.md` named after the site,
|
|
980
|
+
* built from its navigation and page descriptions, served at `/skill.md`
|
|
981
|
+
* and in the skills discovery index. Needs `deployment.site`. A skill in
|
|
982
|
+
* `agents.skills` with the same name replaces it. Defaults to `true`.
|
|
983
|
+
*/
|
|
984
|
+
skillMd?: boolean;
|
|
893
985
|
/**
|
|
894
986
|
* Publish Agent Skills for discovery: a directory (resolved against the
|
|
895
987
|
* project root) whose subdirectories each hold a `SKILL.md`. Skills are
|
|
@@ -1070,6 +1162,23 @@ export interface SoftwareConfig {
|
|
|
1070
1162
|
|
|
1071
1163
|
/** Discoverability: OG images, feeds, sitemap, robots, and structured data. */
|
|
1072
1164
|
export interface SeoConfig {
|
|
1165
|
+
/**
|
|
1166
|
+
* Meta tags written into every page's head, name to content: site
|
|
1167
|
+
* verification tokens, `theme-color`, an app banner, and anything else
|
|
1168
|
+
* Blume has no setting for. `og:*`, `fb:*`, and `article:*` tags render
|
|
1169
|
+
* with `property`, the rest with `name`. A tag Blume writes itself
|
|
1170
|
+
* (`description`, `robots`, `og:image`, `twitter:card`, …) is refused.
|
|
1171
|
+
*
|
|
1172
|
+
* ```ts
|
|
1173
|
+
* seo: {
|
|
1174
|
+
* metatags: {
|
|
1175
|
+
* "google-site-verification": "abc123",
|
|
1176
|
+
* "theme-color": "#0b5fff",
|
|
1177
|
+
* },
|
|
1178
|
+
* }
|
|
1179
|
+
* ```
|
|
1180
|
+
*/
|
|
1181
|
+
metatags?: Record<string, string>;
|
|
1073
1182
|
/** Per-page Open Graph image generation. */
|
|
1074
1183
|
og?: OgConfig;
|
|
1075
1184
|
/**
|
|
@@ -1241,6 +1350,37 @@ export type ExportConfig =
|
|
|
1241
1350
|
pdf?: boolean;
|
|
1242
1351
|
};
|
|
1243
1352
|
|
|
1353
|
+
/** Page feedback: the rating, and an optional written comment after it. */
|
|
1354
|
+
export interface FeedbackConfig {
|
|
1355
|
+
/**
|
|
1356
|
+
* After the rating, offer a box to say more. The comment is sent as a
|
|
1357
|
+
* `feedback_comment` event through every analytics adapter with an event
|
|
1358
|
+
* API. Defaults to `false`.
|
|
1359
|
+
*/
|
|
1360
|
+
comments?: boolean;
|
|
1361
|
+
/** Show the rating. Defaults to `true`. */
|
|
1362
|
+
enabled?: boolean;
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
/**
|
|
1366
|
+
* "Listen to this page". `true` reads pages aloud with the reader's browser
|
|
1367
|
+
* voices (no key, any host). The object form's `provider` generates neural
|
|
1368
|
+
* audio at build instead, one cached clip per sentence, and falls back to
|
|
1369
|
+
* browser voices where no clips exist. Defaults to `false`.
|
|
1370
|
+
*/
|
|
1371
|
+
export type NarrationConfig =
|
|
1372
|
+
| boolean
|
|
1373
|
+
| {
|
|
1374
|
+
/** Show the player. Defaults to `true` in the object form. */
|
|
1375
|
+
enabled?: boolean;
|
|
1376
|
+
/**
|
|
1377
|
+
* Generate audio at build with a speech model:
|
|
1378
|
+
* `gateway({ model: "openai/tts-1-hd", voice: "alloy" })` from
|
|
1379
|
+
* `blume/ai`. Without it, pages are read with browser voices.
|
|
1380
|
+
*/
|
|
1381
|
+
provider?: AssistantGatewayAdapter;
|
|
1382
|
+
};
|
|
1383
|
+
|
|
1244
1384
|
/**
|
|
1245
1385
|
* Opt-in custom frontmatter keys. Page frontmatter is strictly validated —
|
|
1246
1386
|
* an unknown key fails the build so typos are caught — and `extend` carves
|
|
@@ -1335,6 +1475,8 @@ export interface BlumeConfig {
|
|
|
1335
1475
|
agents?: AgentsConfig;
|
|
1336
1476
|
/** Model-facing features: the assistant and the "Open in chat" action. */
|
|
1337
1477
|
ai?: AiConfig;
|
|
1478
|
+
/** Defaults for hand-written endpoint pages (`api` frontmatter). */
|
|
1479
|
+
api?: ApiConfig;
|
|
1338
1480
|
/**
|
|
1339
1481
|
* Analytics adapters from `blume/analytics`, emitted into `<head>` of every
|
|
1340
1482
|
* production page in this order: `[posthog({ key }), vercel(),
|
|
@@ -1353,6 +1495,14 @@ export interface BlumeConfig {
|
|
|
1353
1495
|
* compose: with both set, a page lands at `{deployment.base}/{basePath}/page`.
|
|
1354
1496
|
*/
|
|
1355
1497
|
basePath?: string;
|
|
1498
|
+
/**
|
|
1499
|
+
* Ask readers before analytics runs, with an adapter from `blume/consent`:
|
|
1500
|
+
* `native()` for Blume's own banner, or a hosted consent manager
|
|
1501
|
+
* (`osano({ customerId, configId })`, `ethyca({ privacyCenter })`). Every
|
|
1502
|
+
* `analytics` adapter waits until the reader allows analytics. Unset runs
|
|
1503
|
+
* analytics as it loads.
|
|
1504
|
+
*/
|
|
1505
|
+
consent?: ConsentAdapter;
|
|
1356
1506
|
/** Where content lives and how it's discovered. */
|
|
1357
1507
|
content?: ContentConfig;
|
|
1358
1508
|
/**
|
|
@@ -1376,8 +1526,17 @@ export interface BlumeConfig {
|
|
|
1376
1526
|
examples?: string | ExamplesConfig;
|
|
1377
1527
|
/** Reader-facing PDF/EPUB export actions. Defaults to `false`. */
|
|
1378
1528
|
export?: ExportConfig;
|
|
1379
|
-
/**
|
|
1380
|
-
|
|
1529
|
+
/**
|
|
1530
|
+
* The "Was this page helpful?" rating at the foot of each page. On by
|
|
1531
|
+
* default; `false` hides it. `{ comments: true }` also asks for a written
|
|
1532
|
+
* comment after the rating, sent through your analytics adapters.
|
|
1533
|
+
*/
|
|
1534
|
+
feedback?: boolean | FeedbackConfig;
|
|
1535
|
+
/**
|
|
1536
|
+
* The site footer: social profile icons and up to four link columns. Unset,
|
|
1537
|
+
* the site has no footer.
|
|
1538
|
+
*/
|
|
1539
|
+
footer?: FooterConfig;
|
|
1381
1540
|
/** Opt-in custom frontmatter keys, validated by schemas you supply. */
|
|
1382
1541
|
frontmatter?: FrontmatterConfig;
|
|
1383
1542
|
/** Source repository (Edit-this-page links and the header repo link). */
|
|
@@ -1394,8 +1553,17 @@ export interface BlumeConfig {
|
|
|
1394
1553
|
logo?: LogoConfig;
|
|
1395
1554
|
/** Markdown / MDX rendering behavior. */
|
|
1396
1555
|
markdown?: MarkdownConfig;
|
|
1556
|
+
/** "Listen to this page" narration. Defaults to `false`. */
|
|
1557
|
+
narration?: NarrationConfig;
|
|
1397
1558
|
/** Header, sidebar, tabs, and switchers. */
|
|
1398
1559
|
navigation?: NavigationConfig;
|
|
1560
|
+
/**
|
|
1561
|
+
* Limit how often one reader (by IP address) can call the server routes —
|
|
1562
|
+
* the assistant, the API playground proxy, server-side search — with an
|
|
1563
|
+
* adapter from `blume/ratelimit`: `memory()` (the default, 30 requests per
|
|
1564
|
+
* 10 minutes), `upstash()`, or `cloudflare()`. `false` turns it off.
|
|
1565
|
+
*/
|
|
1566
|
+
rateLimit?: false | RateLimitAdapter;
|
|
1399
1567
|
/** React island behavior (compiler auto-memoization). */
|
|
1400
1568
|
react?: ReactConfig;
|
|
1401
1569
|
/** URL redirect rules. */
|
|
@@ -1416,6 +1584,12 @@ export interface BlumeConfig {
|
|
|
1416
1584
|
title?: string;
|
|
1417
1585
|
/** On-page table of contents. Defaults to on (H2–H3). */
|
|
1418
1586
|
toc?: TocConfig;
|
|
1587
|
+
/**
|
|
1588
|
+
* Content variables: `{{name}}` in a page reads the value, in prose, code,
|
|
1589
|
+
* and links alike. Names take letters, digits, `_`, and `-`; an undefined
|
|
1590
|
+
* name in prose fails the build. Defaults to none.
|
|
1591
|
+
*/
|
|
1592
|
+
variables?: Record<string, string>;
|
|
1419
1593
|
/** Docs versioning (opt-in frozen snapshots with a version switcher). */
|
|
1420
1594
|
versions?: VersionsConfig;
|
|
1421
1595
|
}
|
package/src/core/data.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import type { CaptchaSettings } from "../captcha/schema.ts";
|
|
2
|
+
import type { EndpointAuth } from "../components/content/api-page.ts";
|
|
1
3
|
import type { SearchAdapterKind } from "../search/adapters/registry.ts";
|
|
2
4
|
import type { StructuredDataIdentity } from "../seo/jsonld.ts";
|
|
3
5
|
import type { FontHead } from "../theme/fonts.ts";
|
|
4
6
|
import type { UIStrings } from "./i18n-ui.ts";
|
|
5
|
-
import type { ResolvedConfig } from "./schema.ts";
|
|
7
|
+
import type { LocalizableLabel, ResolvedConfig } from "./schema.ts";
|
|
6
8
|
import type { Navigation, RouteAlternate, VersionAlternate } from "./types.ts";
|
|
7
9
|
|
|
8
10
|
/**
|
|
@@ -42,10 +44,14 @@ export interface BlumeFavicon {
|
|
|
42
44
|
dark?: { href: string; type?: string };
|
|
43
45
|
}
|
|
44
46
|
|
|
45
|
-
/**
|
|
47
|
+
/**
|
|
48
|
+
* Announcement banner, normalized from its config (string shorthand or
|
|
49
|
+
* object). `content` and the link's `text` may be per-locale maps, resolved
|
|
50
|
+
* when the banner renders (see `core/localizable.ts`).
|
|
51
|
+
*/
|
|
46
52
|
export interface BlumeBanner {
|
|
47
|
-
content:
|
|
48
|
-
link?: { href: string; text:
|
|
53
|
+
content: LocalizableLabel;
|
|
54
|
+
link?: { href: string; text: LocalizableLabel };
|
|
49
55
|
dismissible: boolean;
|
|
50
56
|
/** Dismissal key: the configured id, else the content itself. */
|
|
51
57
|
key: string;
|
|
@@ -71,6 +77,8 @@ export interface BlumeDataI18n {
|
|
|
71
77
|
fallbackLocale: string | null;
|
|
72
78
|
hideDefaultLocalePrefix: boolean;
|
|
73
79
|
locales: BlumeDataLocale[];
|
|
80
|
+
/** Send visitors from the default home page to their browser's language. */
|
|
81
|
+
routeByBrowserLanguage: boolean;
|
|
74
82
|
}
|
|
75
83
|
|
|
76
84
|
/** A single content route, with the metadata custom pages can read. */
|
|
@@ -124,9 +132,23 @@ export interface BlumeDataConfig {
|
|
|
124
132
|
appleIcon: BlumeFavicon | null;
|
|
125
133
|
/** The assistant's empty-state suggestions, or `null` when the assistant is off. */
|
|
126
134
|
assistant: {
|
|
135
|
+
/** The bot check's public settings, or `null` without one. */
|
|
136
|
+
captcha: CaptchaSettings | null;
|
|
127
137
|
endpoint: string | null;
|
|
128
138
|
suggestions: NonNullable<ResolvedConfig["ai"]["assistant"]>["suggestions"];
|
|
139
|
+
/** The Contact support link (`ai.assistant.support`), or `null`. */
|
|
140
|
+
support: string | null;
|
|
129
141
|
} | null;
|
|
142
|
+
/**
|
|
143
|
+
* Defaults for hand-written endpoint pages (`api` frontmatter): the server a
|
|
144
|
+
* path joins, the default auth, and the playground, its `proxy` resolved to
|
|
145
|
+
* the URL sends go through (the built-in route under `basePath`) or `false`.
|
|
146
|
+
*/
|
|
147
|
+
api: {
|
|
148
|
+
auth?: EndpointAuth;
|
|
149
|
+
playground: { enabled: boolean; proxy: string | false };
|
|
150
|
+
server?: string;
|
|
151
|
+
};
|
|
130
152
|
banner: BlumeBanner | null;
|
|
131
153
|
/** Site-wide route mount point, normalized to `""` or `/seg` (see config). */
|
|
132
154
|
basePath: string;
|
|
@@ -134,6 +156,11 @@ export interface BlumeDataConfig {
|
|
|
134
156
|
codeThemes: ResolvedConfig["markdown"]["code"]["theme"];
|
|
135
157
|
/** `markdown.code.wrap`: wrap long code lines instead of scrolling. */
|
|
136
158
|
codeWrap: boolean;
|
|
159
|
+
/**
|
|
160
|
+
* The consent adapter's descriptor, or `null` without one. When set, the
|
|
161
|
+
* layouts hold analytics until the reader allows it.
|
|
162
|
+
*/
|
|
163
|
+
consent: ResolvedConfig["consent"];
|
|
137
164
|
/** `dateFormat`: `Intl.DateTimeFormat` options for the date stamps. */
|
|
138
165
|
dateFormat: ResolvedConfig["dateFormat"];
|
|
139
166
|
description: string | undefined;
|
|
@@ -156,7 +183,12 @@ export interface BlumeDataConfig {
|
|
|
156
183
|
sitemap: boolean;
|
|
157
184
|
};
|
|
158
185
|
favicon: BlumeFavicon;
|
|
186
|
+
/** Whether pages end with the "Was this page helpful?" rating. */
|
|
159
187
|
feedback: boolean;
|
|
188
|
+
/** Whether the rating asks for a written comment after it (`feedback.comments`). */
|
|
189
|
+
feedbackComments: boolean;
|
|
190
|
+
/** `footer`: social profile icons and link columns, or `null` when unset. */
|
|
191
|
+
footer: ResolvedConfig["footer"] | null;
|
|
160
192
|
/**
|
|
161
193
|
* Repo coordinates for content components that address the API or build
|
|
162
194
|
* their own repo links (`<GithubInfo>`, the OG card's footer slug), carrying
|
|
@@ -176,6 +208,14 @@ export interface BlumeDataConfig {
|
|
|
176
208
|
logo: BlumeLogo | null;
|
|
177
209
|
/** Hosted MCP server, or `null` when MCP is off. */
|
|
178
210
|
mcp: { name: string; route: string } | null;
|
|
211
|
+
/** `seo.metatags`: the site's own tags for every page's head, or `null`. */
|
|
212
|
+
metatags: Record<string, string> | null;
|
|
213
|
+
/**
|
|
214
|
+
* "Listen to this page": `generated` when a `narration.provider` makes
|
|
215
|
+
* `blume build` write audio clips the player should look for, else the
|
|
216
|
+
* player reads with browser voices. `null` when narration is off.
|
|
217
|
+
*/
|
|
218
|
+
narration: { generated: boolean } | null;
|
|
179
219
|
/**
|
|
180
220
|
* Open Graph image generation. Card fonts are baked into the generated OG
|
|
181
221
|
* endpoint (they can carry absolute build-machine paths) and deliberately
|
package/src/core/diagnostics.ts
CHANGED
|
@@ -24,6 +24,7 @@ const DOCS_BASE = "https://useblume.dev";
|
|
|
24
24
|
const DOCS_DEPLOYMENT = "/docs/deployment";
|
|
25
25
|
const DOCS_CLI_VALIDATE = "/docs/cli/validate";
|
|
26
26
|
const DOCS_CONTENT_SOURCES = "/docs/content/sources";
|
|
27
|
+
const DOCS_CONTENT_SOURCES_OBSIDIAN = "/docs/content/sources/obsidian";
|
|
27
28
|
const DOCS_CONTENT_NAVIGATION = "/docs/content/navigation";
|
|
28
29
|
const DOCS_CONTENT_INCLUDES = "/docs/content/includes";
|
|
29
30
|
|
|
@@ -73,8 +74,8 @@ const DOCS_PATHS = new Map(
|
|
|
73
74
|
BLUME_UNKNOWN_ICON: DOCS_CONTENT_NAVIGATION,
|
|
74
75
|
BLUME_UNKNOWN_OPTION: "/docs/cli",
|
|
75
76
|
BLUME_UNLOADABLE_FILE_NAME: "/docs/content",
|
|
76
|
-
BLUME_WIKILINK_AMBIGUOUS:
|
|
77
|
-
BLUME_WIKILINK_UNRESOLVED:
|
|
77
|
+
BLUME_WIKILINK_AMBIGUOUS: DOCS_CONTENT_SOURCES_OBSIDIAN,
|
|
78
|
+
BLUME_WIKILINK_UNRESOLVED: DOCS_CONTENT_SOURCES_OBSIDIAN,
|
|
78
79
|
BLUME_YARN_PNP: "/docs/quickstart",
|
|
79
80
|
})
|
|
80
81
|
);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The social platforms `footer.socials` links to, each shown by its brand
|
|
3
|
+
* icon: Mintlify's set, without its aliases (`twitter` and `x-twitter` are
|
|
4
|
+
* `x`, `earth-americas` is `website`).
|
|
5
|
+
*/
|
|
6
|
+
export const FOOTER_SOCIALS = [
|
|
7
|
+
"bluesky",
|
|
8
|
+
"discord",
|
|
9
|
+
"facebook",
|
|
10
|
+
"github",
|
|
11
|
+
"hacker-news",
|
|
12
|
+
"instagram",
|
|
13
|
+
"linkedin",
|
|
14
|
+
"medium",
|
|
15
|
+
"podcast",
|
|
16
|
+
"reddit",
|
|
17
|
+
"slack",
|
|
18
|
+
"telegram",
|
|
19
|
+
"threads",
|
|
20
|
+
"website",
|
|
21
|
+
"x",
|
|
22
|
+
"youtube",
|
|
23
|
+
] as const;
|
|
24
|
+
|
|
25
|
+
/** A platform `footer.socials` links to. */
|
|
26
|
+
export type FooterSocial = (typeof FOOTER_SOCIALS)[number];
|
package/src/core/graph.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
localizeRoute,
|
|
5
5
|
resolveFallbackLocale,
|
|
6
6
|
} from "./i18n.ts";
|
|
7
|
+
import { resolveLocalizable } from "./localizable.ts";
|
|
7
8
|
import {
|
|
8
9
|
validateNavIcons,
|
|
9
10
|
validateNavStructure,
|
|
@@ -97,31 +98,6 @@ const localePagesFor = (
|
|
|
97
98
|
return [...real, ...filled];
|
|
98
99
|
};
|
|
99
100
|
|
|
100
|
-
/**
|
|
101
|
-
* Resolve a possibly-per-locale header label to the string a locale renders:
|
|
102
|
-
* the active locale's entry, else the default locale's, else the map's first
|
|
103
|
-
* entry (which is also what a single-locale site gets).
|
|
104
|
-
*/
|
|
105
|
-
/** A label is either one string for every locale or a per-locale map. */
|
|
106
|
-
const isSingleLabel = (label: LocalizableLabel): label is string =>
|
|
107
|
-
typeof label === "string";
|
|
108
|
-
|
|
109
|
-
const resolveLabel = (
|
|
110
|
-
label: LocalizableLabel,
|
|
111
|
-
locale: string,
|
|
112
|
-
defaultLocale?: string
|
|
113
|
-
): string => {
|
|
114
|
-
if (isSingleLabel(label)) {
|
|
115
|
-
return label;
|
|
116
|
-
}
|
|
117
|
-
return (
|
|
118
|
-
label[locale] ??
|
|
119
|
-
(defaultLocale === undefined ? undefined : label[defaultLocale]) ??
|
|
120
|
-
Object.values(label)[0] ??
|
|
121
|
-
""
|
|
122
|
-
);
|
|
123
|
-
};
|
|
124
|
-
|
|
125
101
|
/**
|
|
126
102
|
* An explicit sidebar with every item's `href` passed through `localize` (page
|
|
127
103
|
* refs and `root`s resolve against each locale's own pages already).
|
|
@@ -154,11 +130,36 @@ const resolveTabLabels = (
|
|
|
154
130
|
...tab,
|
|
155
131
|
items: tab.items?.map((item) => ({
|
|
156
132
|
...item,
|
|
157
|
-
label:
|
|
133
|
+
label: resolveLocalizable(item.label, locale, defaultLocale),
|
|
158
134
|
})),
|
|
159
|
-
label:
|
|
135
|
+
label: resolveLocalizable(tab.label, locale, defaultLocale),
|
|
160
136
|
}));
|
|
161
137
|
|
|
138
|
+
/** A configured header or footer link with its label resolved for a locale. */
|
|
139
|
+
const withLabel = <T extends { label: LocalizableLabel }>(
|
|
140
|
+
link: T,
|
|
141
|
+
locale: string,
|
|
142
|
+
defaultLocale?: string
|
|
143
|
+
): Omit<T, "label"> & { label: string } => ({
|
|
144
|
+
...link,
|
|
145
|
+
label: resolveLocalizable(link.label, locale, defaultLocale),
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
/** The configured header links (plain, call to action, featured) in `locale`. */
|
|
149
|
+
const resolveHeaderLinks = (
|
|
150
|
+
navigation: BuildContentGraphOptions["navigation"],
|
|
151
|
+
locale: string,
|
|
152
|
+
defaultLocale?: string
|
|
153
|
+
) => ({
|
|
154
|
+
actions: navigation.actions.map((link) =>
|
|
155
|
+
withLabel(link, locale, defaultLocale)
|
|
156
|
+
),
|
|
157
|
+
cta: navigation.cta ? withLabel(navigation.cta, locale, defaultLocale) : null,
|
|
158
|
+
featured: navigation.featured.map((link) =>
|
|
159
|
+
withLabel(link, locale, defaultLocale)
|
|
160
|
+
),
|
|
161
|
+
});
|
|
162
|
+
|
|
162
163
|
/**
|
|
163
164
|
* Mount a configured link authored as if the site were served at root (the
|
|
164
165
|
* banner's): under `basePath`, except a route served outside the content tree
|
|
@@ -274,18 +275,22 @@ const buildLocaleNavigation = (
|
|
|
274
275
|
...item,
|
|
275
276
|
href: localizeServed(item.href, false),
|
|
276
277
|
});
|
|
277
|
-
const { actions, cta, featured } =
|
|
278
|
+
const { actions, cta, featured } = resolveHeaderLinks(
|
|
279
|
+
options.navigation,
|
|
280
|
+
code,
|
|
281
|
+
i18n.defaultLocale
|
|
282
|
+
);
|
|
278
283
|
const sidebarItems = options.navigation.sidebar.items;
|
|
279
284
|
|
|
280
285
|
const navigation = buildNavigation(localePages, {
|
|
281
|
-
actions: actions
|
|
286
|
+
actions: actions.map(localizeHref),
|
|
282
287
|
basePath,
|
|
283
288
|
cta: cta ? localizeHref(cta) : null,
|
|
284
289
|
diagnostics,
|
|
285
290
|
display: options.navigation.sidebar.display,
|
|
286
291
|
extraRoutes: options.extraRoutes,
|
|
287
292
|
fallbackMetaPrefix,
|
|
288
|
-
featured: featured
|
|
293
|
+
featured: featured.map(localizeHref),
|
|
289
294
|
folderMeta: options.folderMeta,
|
|
290
295
|
// The localized tree root ("/" for the hidden default, "/fr" otherwise;
|
|
291
296
|
// "/fr/v1.0" inside a snapshot): the tab pointing here spans the whole
|
|
@@ -415,13 +420,11 @@ const buildVersionNavigation = (
|
|
|
415
420
|
}
|
|
416
421
|
return {
|
|
417
422
|
"": buildNavigation(versionPages, {
|
|
418
|
-
|
|
423
|
+
...resolveHeaderLinks(options.navigation, ""),
|
|
419
424
|
basePath: options.basePath ?? "",
|
|
420
|
-
cta: options.navigation.cta,
|
|
421
425
|
diagnostics,
|
|
422
426
|
display: options.navigation.sidebar.display,
|
|
423
427
|
extraRoutes: options.extraRoutes,
|
|
424
|
-
featured: options.navigation.featured,
|
|
425
428
|
folderMeta: options.folderMeta,
|
|
426
429
|
localizedRoot: versionizeRoute("/", id),
|
|
427
430
|
metaPrefix: id,
|
|
@@ -465,13 +468,13 @@ export const buildContentGraph = (
|
|
|
465
468
|
));
|
|
466
469
|
} else {
|
|
467
470
|
navigation = buildNavigation(currentPages, {
|
|
468
|
-
|
|
471
|
+
// No locale to prefer: a per-locale label map resolves to its first
|
|
472
|
+
// entry on a single-locale site.
|
|
473
|
+
...resolveHeaderLinks(options.navigation, ""),
|
|
469
474
|
basePath: options.basePath ?? "",
|
|
470
|
-
cta: options.navigation.cta,
|
|
471
475
|
diagnostics,
|
|
472
476
|
display: options.navigation.sidebar.display,
|
|
473
477
|
extraRoutes: options.extraRoutes,
|
|
474
|
-
featured: options.navigation.featured,
|
|
475
478
|
folderMeta: options.folderMeta,
|
|
476
479
|
selectors: options.navigation.selectors,
|
|
477
480
|
sharedFolderMeta: options.sharedFolderMeta,
|