blume 1.7.3 → 2.0.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 +19 -0
- package/CHANGELOG.md +245 -0
- package/README.md +34 -21
- package/dist/cli/{chunk-vacwm2hv.js → chunk-27g6wdth.js} +2 -2
- package/dist/cli/{chunk-ps4m1xh4.js → chunk-2hn4b8z7.js} +513 -550
- package/dist/cli/chunk-2hn4b8z7.js.map +12 -0
- package/dist/cli/chunk-5shv93fd.js +39 -0
- package/dist/cli/chunk-5shv93fd.js.map +10 -0
- package/dist/cli/chunk-6crbhc3x.js +361 -0
- package/dist/cli/chunk-6crbhc3x.js.map +14 -0
- package/dist/cli/{chunk-8cjtbafj.js → chunk-6hsn950k.js} +109 -383
- package/dist/cli/chunk-6hsn950k.js.map +10 -0
- package/dist/cli/chunk-6vm74dry.js +148 -0
- package/dist/cli/chunk-6vm74dry.js.map +10 -0
- package/dist/cli/{chunk-yg63d42r.js → chunk-79jhk4py.js} +87 -58
- package/dist/cli/chunk-79jhk4py.js.map +35 -0
- package/dist/cli/chunk-82bbrxdn.js +51 -0
- package/dist/cli/chunk-82bbrxdn.js.map +10 -0
- package/dist/cli/chunk-abh8yjkn.js +31 -0
- package/dist/cli/chunk-abh8yjkn.js.map +10 -0
- package/dist/cli/chunk-ah61y8py.js +75 -0
- package/dist/cli/chunk-ah61y8py.js.map +11 -0
- package/dist/cli/{chunk-dwgcp5sm.js → chunk-ce574jw2.js} +1 -1
- package/dist/cli/chunk-ch6g3ar0.js +102 -0
- package/dist/cli/chunk-ch6g3ar0.js.map +10 -0
- package/dist/cli/chunk-dh8cwk36.js +279 -0
- package/dist/cli/chunk-dh8cwk36.js.map +10 -0
- package/dist/cli/{chunk-rqy0s5wh.js → chunk-epjnccmv.js} +17 -16
- package/dist/cli/{chunk-rqy0s5wh.js.map → chunk-epjnccmv.js.map} +3 -3
- package/dist/cli/chunk-f2z5v128.js +97 -0
- package/dist/cli/chunk-f2z5v128.js.map +10 -0
- package/dist/cli/{chunk-2z47ypj8.js → chunk-fa25z98p.js} +16 -3
- package/dist/cli/chunk-fa25z98p.js.map +11 -0
- package/dist/cli/{chunk-1jefwnfs.js → chunk-fs23ddbb.js} +1076 -2592
- package/dist/cli/chunk-fs23ddbb.js.map +35 -0
- package/dist/cli/{chunk-e7f42gdj.js → chunk-fxypxtvm.js} +2 -2
- package/dist/cli/{chunk-bvwwhd84.js → chunk-fz5wtpmh.js} +15 -15
- package/dist/cli/{chunk-bvwwhd84.js.map → chunk-fz5wtpmh.js.map} +1 -1
- package/dist/cli/chunk-hdpx1tax.js +91 -0
- package/dist/cli/chunk-hdpx1tax.js.map +10 -0
- package/dist/cli/{chunk-ct47dqpx.js → chunk-jts8mvcz.js} +67 -7
- package/dist/cli/{chunk-2mzebbbz.js.map → chunk-jts8mvcz.js.map} +6 -4
- package/dist/cli/{chunk-ahnw3kxw.js → chunk-jwyddg7y.js} +27 -22
- package/dist/cli/chunk-jwyddg7y.js.map +15 -0
- package/dist/cli/{chunk-cjtn640a.js → chunk-kdp5q7ke.js} +43 -20
- package/dist/cli/chunk-kdp5q7ke.js.map +10 -0
- package/dist/cli/{chunk-5g0w1e2c.js → chunk-kpf8rrjc.js} +28 -16
- package/dist/cli/{chunk-5g0w1e2c.js.map → chunk-kpf8rrjc.js.map} +4 -4
- package/dist/cli/chunk-m3vmjgmq.js +133 -0
- package/dist/cli/chunk-m3vmjgmq.js.map +10 -0
- package/dist/cli/{chunk-b27xqwn9.js → chunk-mb2919y2.js} +9 -5
- package/dist/cli/chunk-mb2919y2.js.map +10 -0
- package/dist/cli/{chunk-5qk08vmp.js → chunk-q5163e60.js} +133 -54
- package/dist/cli/chunk-q5163e60.js.map +11 -0
- package/dist/cli/chunk-qkqwkpte.js +12437 -0
- package/dist/cli/chunk-qkqwkpte.js.map +182 -0
- package/dist/cli/{chunk-4x36ddpw.js → chunk-qs4q5p4e.js} +81 -87
- package/dist/cli/chunk-qs4q5p4e.js.map +10 -0
- package/dist/cli/{chunk-0xjyb285.js → chunk-qwsrynx5.js} +15 -5
- package/dist/cli/{chunk-0xjyb285.js.map → chunk-qwsrynx5.js.map} +4 -4
- package/dist/cli/chunk-s1p84fyh.js +261 -0
- package/dist/cli/chunk-s1p84fyh.js.map +10 -0
- package/dist/cli/chunk-s6jhgk0q.js +176 -0
- package/dist/cli/chunk-s6jhgk0q.js.map +11 -0
- package/dist/cli/chunk-vtk4a6dg.js +374 -0
- package/dist/cli/chunk-vtk4a6dg.js.map +10 -0
- package/dist/cli/{chunk-k79xp7av.js → chunk-wgm7m9qk.js} +230 -700
- package/dist/cli/chunk-wgm7m9qk.js.map +36 -0
- package/dist/cli/chunk-wm7js3j9.js +145 -0
- package/dist/cli/chunk-wm7js3j9.js.map +11 -0
- package/dist/cli/chunk-yt5n7ppj.js +79 -0
- package/dist/cli/chunk-yt5n7ppj.js.map +10 -0
- package/dist/cli/{chunk-3r45185y.js → chunk-yw7dm696.js} +9 -11
- package/dist/cli/{chunk-3r45185y.js.map → chunk-yw7dm696.js.map} +3 -3
- package/dist/cli/{chunk-nn13znc2.js → chunk-zxcczpyx.js} +1 -1
- package/dist/cli/chunk-zxh4d9vy.js +122 -0
- package/dist/cli/chunk-zxh4d9vy.js.map +11 -0
- package/dist/cli/index.js +214 -57
- package/dist/cli/index.js.map +8 -7
- package/dist/types/ai/agent-readability.d.ts +52 -0
- package/dist/types/ai/ai-catalog.d.ts +42 -0
- package/dist/types/ai/api/paths.d.ts +17 -0
- package/dist/types/ai/api-catalog.d.ts +18 -0
- package/dist/types/ai/ask-context.d.ts +7 -7
- package/dist/types/ai/ask.d.ts +368 -0
- package/dist/types/ai/changelog-markdown.d.ts +2 -0
- package/dist/types/ai/component-markdown.d.ts +2 -2
- package/dist/types/ai/index.d.ts +24 -0
- package/dist/types/ai/link-headers.d.ts +24 -0
- package/dist/types/ai/llms.d.ts +25 -0
- package/dist/types/ai/markdown.d.ts +45 -0
- package/dist/types/ai/mcp/discovery.d.ts +68 -0
- package/dist/types/ai/mcp/tools.d.ts +16 -0
- package/dist/types/ai/openapi-components.d.ts +43 -0
- package/dist/types/ai/relative-links.d.ts +26 -0
- package/dist/types/ai/serializers.d.ts +15 -0
- package/dist/types/ai/skills.d.ts +42 -0
- package/dist/types/ai/tar.d.ts +25 -0
- package/dist/types/ai/visibility.d.ts +17 -0
- package/dist/types/ai/web-bot-auth.d.ts +16 -0
- package/dist/types/analytics/adobe.d.ts +35 -0
- package/dist/types/analytics/amplitude.d.ts +50 -0
- package/dist/types/analytics/clarity.d.ts +31 -0
- package/dist/types/analytics/clearbit.d.ts +29 -0
- package/dist/types/analytics/cloudflare.d.ts +41 -0
- package/dist/types/analytics/fathom.d.ts +41 -0
- package/dist/types/analytics/google-analytics.d.ts +44 -0
- package/dist/types/analytics/google-tag-manager.d.ts +40 -0
- package/dist/types/analytics/head.d.ts +30 -0
- package/dist/types/analytics/heap.d.ts +40 -0
- package/dist/types/analytics/hightouch.d.ts +44 -0
- package/dist/types/analytics/hotjar.d.ts +33 -0
- package/dist/types/analytics/index.d.ts +61 -0
- package/dist/types/analytics/inline.d.ts +17 -0
- package/dist/types/analytics/logrocket.d.ts +44 -0
- package/dist/types/analytics/mixpanel.d.ts +67 -0
- package/dist/types/analytics/pirsch.d.ts +42 -0
- package/dist/types/analytics/plausible.d.ts +56 -0
- package/dist/types/analytics/posthog.d.ts +45 -0
- package/dist/types/analytics/schema.d.ts +320 -0
- package/dist/types/analytics/script.d.ts +46 -0
- package/dist/types/analytics/segment.d.ts +50 -0
- package/dist/types/analytics/vercel.d.ts +48 -0
- package/dist/types/astro/integration.d.ts +76 -0
- package/dist/types/astro/markdown-negotiation.d.ts +23 -0
- package/dist/types/astro/module-types.d.ts +14 -0
- package/dist/types/astro/pages.d.ts +44 -0
- package/dist/types/cli/env.d.ts +12 -0
- package/dist/types/cli/init/scaffold.d.ts +154 -0
- package/dist/types/components/layout/nav-utils.d.ts +11 -0
- package/dist/types/core/adapter.d.ts +47 -0
- package/dist/types/core/api-name.d.ts +7 -0
- package/dist/types/core/changelog-index.d.ts +13 -0
- package/dist/types/core/config-input.d.ts +197 -526
- package/dist/types/core/config.d.ts +61 -35
- package/dist/types/core/content-assets.d.ts +76 -0
- package/dist/types/core/custom-pages.d.ts +33 -0
- package/dist/types/core/data.d.ts +30 -15
- package/dist/types/core/define-components.d.ts +12 -9
- package/dist/types/core/deployment-env.d.ts +6 -11
- package/dist/types/core/frontmatter.d.ts +10 -0
- package/dist/types/core/graph.d.ts +18 -0
- package/dist/types/core/heading-markers.d.ts +54 -0
- package/dist/types/core/i18n-ui.d.ts +12 -10
- package/dist/types/core/i18n.d.ts +87 -0
- package/dist/types/core/includes.d.ts +138 -0
- package/dist/types/core/last-modified.d.ts +47 -0
- package/dist/types/core/links.d.ts +95 -0
- package/dist/types/core/locale-links.d.ts +60 -0
- package/dist/types/core/manifest.d.ts +17 -0
- package/dist/types/core/meta.d.ts +38 -0
- package/dist/types/core/nav-diagnostics.d.ts +26 -0
- package/dist/types/core/navigation.d.ts +6 -0
- package/dist/types/core/node-require.d.ts +19 -0
- package/dist/types/core/package-json.d.ts +13 -0
- package/dist/types/core/probe.d.ts +42 -0
- package/dist/types/core/project-graph.d.ts +51 -0
- package/dist/types/core/project.d.ts +2 -0
- package/dist/types/core/safe-href.d.ts +2 -0
- package/dist/types/core/safe-links.d.ts +26 -0
- package/dist/types/core/schema.d.ts +2284 -454
- package/dist/types/core/site-url.d.ts +16 -0
- package/dist/types/core/sources/assets.d.ts +36 -0
- package/dist/types/core/sources/cache.d.ts +37 -0
- package/dist/types/core/sources/collection.d.ts +28 -0
- package/dist/types/core/sources/contentful-rich-text.d.ts +31 -0
- package/dist/types/core/sources/contentful.d.ts +40 -0
- package/dist/types/core/sources/filesystem.d.ts +24 -0
- package/dist/types/core/sources/github-releases.d.ts +31 -0
- package/dist/types/core/sources/json.d.ts +30 -0
- package/dist/types/core/sources/lexical.d.ts +19 -0
- package/dist/types/core/sources/lower.d.ts +75 -0
- package/dist/types/core/sources/mdx-remote.d.ts +28 -0
- package/dist/types/core/sources/normalize.d.ts +147 -0
- package/dist/types/core/sources/notion.d.ts +131 -0
- package/dist/types/core/sources/obsidian.d.ts +46 -0
- package/dist/types/core/sources/payload.d.ts +39 -0
- package/dist/types/core/sources/portable-text.d.ts +42 -0
- package/dist/types/core/sources/read.d.ts +23 -0
- package/dist/types/core/sources/remote.d.ts +74 -0
- package/dist/types/core/sources/resolve.d.ts +19 -0
- package/dist/types/core/sources/sanity.d.ts +43 -0
- package/dist/types/core/sources/strapi-blocks.d.ts +12 -0
- package/dist/types/core/sources/strapi.d.ts +33 -0
- package/dist/types/core/sources/types.d.ts +7 -0
- package/dist/types/core/sources/watch.d.ts +45 -0
- package/dist/types/core/text-width.d.ts +11 -0
- package/dist/types/core/types.d.ts +15 -1
- package/dist/types/core/unrecognized-keys.d.ts +7 -0
- package/dist/types/core/versions.d.ts +72 -0
- package/dist/types/core/yaml.d.ts +9 -0
- package/dist/types/deploy/adapter-output.d.ts +45 -0
- package/dist/types/deploy/adapters/cloudflare.d.ts +40 -0
- package/dist/types/deploy/adapters/index.d.ts +29 -0
- package/dist/types/deploy/adapters/netlify.d.ts +37 -0
- package/dist/types/deploy/adapters/node.d.ts +37 -0
- package/dist/types/deploy/adapters/registry.d.ts +133 -0
- package/dist/types/deploy/adapters/types.d.ts +71 -0
- package/dist/types/deploy/adapters/vercel.d.ts +38 -0
- package/dist/types/deploy/artifacts.d.ts +65 -0
- package/dist/types/deploy/cloudflare-negotiation.d.ts +196 -0
- package/dist/types/deploy/function-bundle.d.ts +80 -0
- package/dist/types/deploy/headers.d.ts +50 -0
- package/dist/types/deploy/node-headers.d.ts +42 -0
- package/dist/types/deploy/platforms/cloudflare.d.ts +40 -0
- package/dist/types/deploy/platforms/index.d.ts +18 -0
- package/dist/types/deploy/platforms/netlify.d.ts +13 -0
- package/dist/types/deploy/platforms/node.d.ts +11 -0
- package/dist/types/deploy/platforms/paths.d.ts +27 -0
- package/dist/types/deploy/platforms/static.d.ts +10 -0
- package/dist/types/deploy/platforms/types.d.ts +104 -0
- package/dist/types/deploy/platforms/vercel.d.ts +32 -0
- package/dist/types/deploy/redirects.d.ts +53 -0
- package/dist/types/deploy/robots.d.ts +8 -0
- package/dist/types/deploy/rss.d.ts +31 -0
- package/dist/types/deploy/sitemap.d.ts +21 -0
- package/dist/types/deploy/vercel-negotiation.d.ts +109 -0
- package/dist/types/markdown/code-title.d.ts +32 -0
- package/dist/types/markdown/fence-meta.d.ts +23 -0
- package/dist/types/markdown/themes.d.ts +3 -3
- package/dist/types/openapi/asyncapi.d.ts +129 -0
- package/dist/types/openapi/graphql-build.d.ts +8 -0
- package/dist/types/openapi/graphql.d.ts +122 -0
- package/dist/types/openapi/model.d.ts +158 -0
- package/dist/types/openapi/parse.d.ts +57 -0
- package/dist/types/openapi/references.d.ts +37 -25
- package/dist/types/openapi/render-mdx.d.ts +33 -0
- package/dist/types/openapi/sentence.d.ts +7 -0
- package/dist/types/openapi/signature.d.ts +10 -0
- package/dist/types/openapi/source.d.ts +22 -0
- package/dist/types/openapi/spec-dependency-error.d.ts +10 -0
- package/dist/types/reference/asyncapi.d.ts +166 -0
- package/dist/types/reference/graphql.d.ts +181 -0
- package/dist/types/reference/index.d.ts +32 -0
- package/dist/types/reference/openapi.d.ts +165 -0
- package/dist/types/reference/options.d.ts +157 -0
- package/dist/types/reference/scalar.d.ts +136 -0
- package/dist/types/reference/schema.d.ts +630 -0
- package/dist/types/search/adapters/algolia.d.ts +32 -0
- package/dist/types/search/adapters/flexsearch.d.ts +12 -0
- package/dist/types/search/adapters/index.d.ts +31 -0
- package/dist/types/search/adapters/mixedbread.d.ts +22 -0
- package/dist/types/search/adapters/orama-cloud.d.ts +33 -0
- package/dist/types/search/adapters/orama.d.ts +13 -0
- package/dist/types/search/adapters/pagefind.d.ts +12 -0
- package/dist/types/search/adapters/registry.d.ts +228 -0
- package/dist/types/search/adapters/types.d.ts +34 -0
- package/dist/types/search/adapters/typesense.d.ts +42 -0
- package/dist/types/search/build.d.ts +23 -0
- package/dist/types/search/documents.d.ts +90 -0
- package/dist/types/search/facets.d.ts +3 -0
- package/dist/types/search/orama-index.d.ts +1 -1
- package/dist/types/search/sync/algolia.d.ts +14 -0
- package/dist/types/search/sync/index.d.ts +14 -0
- package/dist/types/search/sync/orama-cloud.d.ts +10 -0
- package/dist/types/search/sync/typesense.d.ts +14 -0
- package/dist/types/sources/contentful.d.ts +68 -0
- package/dist/types/sources/custom.d.ts +20 -0
- package/dist/types/sources/filesystem.d.ts +42 -0
- package/dist/types/sources/github-releases.d.ts +46 -0
- package/dist/types/sources/index.d.ts +48 -0
- package/dist/types/sources/mdx-remote.d.ts +63 -0
- package/dist/types/sources/notion.d.ts +65 -0
- package/dist/types/sources/obsidian.d.ts +34 -0
- package/dist/types/sources/payload.d.ts +68 -0
- package/dist/types/sources/registry.d.ts +1414 -0
- package/dist/types/sources/sanity.d.ts +69 -0
- package/dist/types/sources/shared.d.ts +46 -0
- package/dist/types/sources/strapi.d.ts +66 -0
- package/dist/types/theme/icon-kind.d.ts +11 -0
- package/dist/types/theme/icons.d.ts +20 -0
- package/docs/01-quickstart.mdx +18 -18
- package/docs/02-deployment.mdx +52 -28
- package/docs/03-upgrading.mdx +364 -0
- package/docs/04-migrating.mdx +58 -0
- package/docs/08-faq.mdx +5 -5
- package/docs/advanced/blog.mdx +13 -6
- package/docs/advanced/changelog.mdx +23 -35
- package/docs/advanced/custom-pages.mdx +22 -10
- package/docs/advanced/meta.ts +1 -8
- package/docs/advanced/skills.mdx +8 -0
- package/docs/cli/audit.mdx +646 -0
- package/docs/cli/doctor.mdx +29 -0
- package/docs/{reference/eval.mdx → cli/evals.mdx} +12 -11
- package/docs/cli/index.mdx +105 -0
- package/docs/cli/meta.ts +7 -0
- package/docs/{reference → cli}/translate.mdx +9 -9
- package/docs/cli/validate.mdx +41 -0
- package/docs/cli/version.mdx +40 -0
- package/docs/configuration/analytics.mdx +350 -59
- package/docs/configuration/assistant.mdx +357 -0
- package/docs/configuration/customization.mdx +16 -10
- package/docs/configuration/index.mdx +50 -31
- package/docs/configuration/meta.ts +1 -1
- package/docs/configuration/search.mdx +76 -55
- package/docs/configuration/theming.mdx +24 -15
- package/docs/content/components.mdx +21 -5
- package/docs/{reference → content}/frontmatter.mdx +35 -1
- package/docs/content/i18n.mdx +9 -7
- package/docs/content/includes.mdx +2 -4
- package/docs/content/index.mdx +1 -1
- package/docs/content/islands.mdx +11 -6
- package/docs/content/meta.mdx +1 -1
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +9 -7
- package/docs/content/sources.mdx +145 -50
- package/docs/content/syntax.mdx +16 -12
- package/docs/content/versioning.mdx +3 -3
- package/docs/discoverability/agent-discovery.mdx +12 -12
- package/docs/discoverability/index.mdx +4 -4
- package/docs/discoverability/json-api.mdx +4 -4
- package/docs/discoverability/llms-txt.mdx +6 -6
- package/docs/discoverability/markdown.mdx +4 -4
- package/docs/discoverability/mcp.mdx +11 -11
- package/docs/discoverability/sitemap-and-robots.mdx +3 -3
- package/docs/index.mdx +4 -4
- package/docs/references/asyncapi.mdx +59 -0
- package/docs/{advanced → references}/graphql.mdx +45 -32
- package/docs/{reference → references}/meta.ts +2 -2
- package/docs/references/openapi.mdx +171 -0
- package/docs/references/scalar.mdx +64 -0
- package/package.json +42 -8
- package/skills/blume/SKILL.md +23 -10
- package/skills/blume-migrate/SKILL.md +22 -21
- package/skills/blume-migrate/assets/oxfmt@0.67.0.patch +49 -0
- package/skills/blume-migrate/references/docusaurus.md +5 -4
- package/skills/blume-migrate/references/fumadocs.md +4 -4
- package/skills/blume-migrate/references/mintlify.md +23 -8
- package/skills/blume-migrate/references/monorepo.md +6 -6
- package/skills/blume-migrate/references/starlight.md +4 -4
- package/src/ai/agent-readability.ts +25 -26
- package/src/ai/ai-catalog.ts +50 -32
- package/src/ai/api/handlers.ts +46 -11
- package/src/ai/api/paths.ts +1 -1
- package/src/ai/api-catalog.ts +8 -8
- package/src/ai/ask-context.ts +7 -7
- package/src/ai/ask-data.ts +3 -3
- package/src/ai/ask.ts +637 -100
- package/src/ai/changelog-markdown.ts +91 -0
- package/src/ai/component-markdown.ts +328 -12
- package/src/ai/cors.ts +3 -3
- package/src/ai/index.ts +45 -0
- package/src/ai/link-headers.ts +7 -6
- package/src/ai/llms.ts +20 -15
- package/src/ai/markdown.ts +35 -5
- package/src/ai/mcp/data.ts +9 -5
- package/src/ai/openapi-components.ts +5 -2
- package/src/ai/relative-links.ts +170 -0
- package/src/ai/serializers.ts +3 -3
- package/src/ai/skills.ts +1 -1
- package/src/ai/visibility.ts +1 -1
- package/src/ai/web-bot-auth.ts +2 -2
- package/src/analytics/adobe.ts +46 -0
- package/src/analytics/amplitude.ts +79 -0
- package/src/analytics/clarity.ts +46 -0
- package/src/analytics/clearbit.ts +47 -0
- package/src/analytics/cloudflare.ts +67 -0
- package/src/analytics/fathom.ts +64 -0
- package/src/analytics/google-analytics.ts +84 -0
- package/src/analytics/google-tag-manager.ts +61 -0
- package/src/analytics/head.ts +130 -0
- package/src/analytics/heap.ts +65 -0
- package/src/analytics/hightouch.ts +77 -0
- package/src/analytics/hotjar.ts +47 -0
- package/src/analytics/index.ts +71 -0
- package/src/analytics/inline.ts +21 -0
- package/src/analytics/logrocket.ts +71 -0
- package/src/analytics/mixpanel.ts +92 -0
- package/src/analytics/pirsch.ts +66 -0
- package/src/analytics/plausible.ts +83 -0
- package/src/analytics/posthog.ts +78 -0
- package/src/analytics/schema.ts +60 -0
- package/src/analytics/script.ts +60 -0
- package/src/analytics/segment.ts +85 -0
- package/src/analytics/vercel.ts +50 -0
- package/src/astro/adapter-root.ts +7 -9
- package/src/astro/component-slots.ts +131 -91
- package/src/astro/generate.ts +129 -361
- package/src/astro/integration.ts +2 -6
- package/src/astro/module-types.ts +1 -1
- package/src/astro/pages.ts +13 -101
- package/src/astro/render-deps.ts +379 -0
- package/src/astro/runtime-deps.ts +201 -0
- package/src/astro/templates.ts +575 -562
- package/src/audit/agent.ts +24 -0
- package/src/audit/catalog.ts +2 -2
- package/src/audit/checks/assets.ts +2 -2
- package/src/audit/checks/dns-aid.ts +1 -1
- package/src/audit/checks/duplicates.ts +3 -1
- package/src/audit/checks/i18n.ts +1 -1
- package/src/audit/checks/indexability.ts +7 -7
- package/src/audit/checks/links.ts +2 -2
- package/src/audit/checks/llms.ts +6 -6
- package/src/audit/checks/network.ts +3 -3
- package/src/audit/checks/og-image.ts +2 -2
- package/src/audit/checks/robots.ts +1 -1
- package/src/audit/checks/sitemap.ts +2 -2
- package/src/audit/checks/social.ts +1 -1
- package/src/audit/run.ts +4 -3
- package/src/audit/terms.ts +31 -0
- package/src/audit/url.ts +13 -13
- package/src/blume-modules.d.ts +2 -2
- package/src/cli/command-meta.ts +10 -0
- package/src/cli/commands/audit.ts +40 -21
- package/src/cli/commands/build.ts +71 -316
- package/src/cli/commands/check.ts +1 -0
- package/src/cli/commands/dev.ts +40 -1
- package/src/cli/commands/doctor.ts +92 -14
- package/src/cli/commands/eject.ts +44 -7
- package/src/cli/commands/eval.ts +5 -5
- package/src/cli/commands/init.ts +161 -41
- package/src/cli/commands/migrate.ts +121 -0
- package/src/cli/commands/preview.ts +7 -1
- package/src/cli/commands/translate.ts +5 -5
- package/src/cli/commands/upgrade.ts +141 -0
- package/src/cli/commands/version.ts +57 -44
- package/src/cli/eject-scripts.ts +121 -6
- package/src/cli/index.ts +11 -1
- package/src/cli/init/install.ts +70 -0
- package/src/cli/init/questions.ts +7 -0
- package/src/cli/init/scaffold.ts +459 -75
- package/src/cli/lazy-command.ts +37 -1
- package/src/cli/prepare.ts +40 -6
- package/src/cli/required-secrets.ts +39 -12
- package/src/cli/unknown-flags.ts +266 -0
- package/src/cli/yarn-pnp.ts +52 -0
- package/src/components/content/AccordionItem.astro +7 -1
- package/src/components/content/Card.astro +4 -3
- package/src/components/content/ColorItem.astro +22 -4
- package/src/components/content/GithubInfo.astro +2 -2
- package/src/components/content/Prompt.astro +25 -25
- package/src/components/content/Tabs.astro +3 -1
- package/src/components/content/Tile.astro +2 -3
- package/src/components/content/Tooltip.astro +57 -9
- package/src/components/content/content-strings.ts +34 -0
- package/src/components/content/diff.ts +1 -1
- package/src/components/content/mermaid-element.ts +13 -2
- package/src/components/content/prompt-markdown.ts +292 -0
- package/src/components/content/tooltip-id.ts +41 -0
- package/src/components/copy-feedback.ts +1 -1
- package/src/components/islands/{AskAI.astro → Assistant.astro} +10 -10
- package/src/components/islands/{ask-ai.tsx → assistant.tsx} +23 -23
- package/src/components/islands/hooks.ts +36 -11
- package/src/components/layout/Analytics.astro +21 -79
- package/src/components/layout/Banner.astro +3 -1
- package/src/components/layout/DiscoveryLinks.astro +69 -0
- package/src/components/layout/Header.astro +93 -30
- package/src/components/layout/LanguageSwitcher.astro +4 -1
- package/src/components/layout/Logo.astro +23 -2
- package/src/components/layout/NavSelector.astro +13 -2
- package/src/components/layout/NavTree.astro +12 -3
- package/src/components/layout/NavTreeScript.astro +17 -3
- package/src/components/layout/PageActions.astro +3 -3
- package/src/components/layout/PageFeedback.astro +11 -1
- package/src/components/layout/PageLayout.astro +58 -11
- package/src/components/layout/Pagination.astro +7 -7
- package/src/components/layout/ReferenceLayout.astro +22 -13
- package/src/components/layout/RootLayout.astro +75 -72
- package/src/components/layout/Search.astro +43 -19
- package/src/components/layout/WebMcp.astro +1 -1
- package/src/components/layout/analytics-client.ts +73 -16
- package/src/components/layout/drawer-inert.ts +113 -15
- package/src/components/layout/dropdown-clamp.ts +105 -0
- package/src/components/layout/head-scripts.ts +15 -6
- package/src/components/layout/nav-utils.ts +17 -0
- package/src/components/layout/search/algolia.ts +8 -8
- package/src/components/layout/search/orama-cloud.ts +9 -7
- package/src/components/layout/search/typesense.ts +11 -17
- package/src/components/openapi/MessageComposer.astro +2 -2
- package/src/components/openapi/Playground.astro +2 -2
- package/src/components/openapi/description.ts +2 -2
- package/src/components/openapi/playground-client.ts +79 -10
- package/src/core/changelog-index.ts +24 -0
- package/src/core/code-fences.ts +1 -1
- package/src/core/component-overrides.ts +399 -154
- package/src/core/config-input.ts +201 -566
- package/src/core/config.ts +131 -42
- package/src/core/custom-pages.ts +105 -0
- package/src/core/data.ts +34 -15
- package/src/core/define-components.ts +12 -9
- package/src/core/deployment-env.ts +18 -74
- package/src/core/diagnostics.ts +14 -7
- package/src/core/graph.ts +69 -25
- package/src/core/i18n-ui.ts +41 -11
- package/src/core/i18n.ts +17 -0
- package/src/core/includes.ts +156 -38
- package/src/core/last-modified.ts +6 -11
- package/src/core/links.ts +166 -2
- package/src/core/manifest.ts +10 -3
- package/src/core/navigation.ts +115 -16
- package/src/core/new-tab.ts +35 -0
- package/src/core/node-require.ts +21 -0
- package/src/core/project-graph.ts +42 -26
- package/src/core/project.ts +9 -4
- package/src/core/request-body.ts +61 -0
- package/src/core/safe-href.ts +28 -0
- package/src/core/safe-links.ts +68 -0
- package/src/core/schema.ts +528 -745
- package/src/core/server-features.ts +10 -11
- package/src/core/sources/assets.ts +47 -11
- package/src/core/sources/collection.ts +67 -0
- package/src/core/sources/contentful-rich-text.ts +285 -0
- package/src/core/sources/contentful.ts +173 -0
- package/src/core/sources/github-releases.ts +51 -1
- package/src/core/sources/json.ts +71 -0
- package/src/core/sources/lexical.ts +195 -0
- package/src/core/sources/lower.ts +226 -0
- package/src/core/sources/normalize.ts +52 -2
- package/src/core/sources/notion.ts +39 -28
- package/src/core/sources/payload.ts +135 -0
- package/src/core/sources/portable-text.ts +11 -16
- package/src/core/sources/remote.ts +226 -0
- package/src/core/sources/resolve.ts +104 -166
- package/src/core/sources/sanity.ts +16 -49
- package/src/core/sources/strapi-blocks.ts +124 -0
- package/src/core/sources/strapi.ts +191 -0
- package/src/core/sources/types.ts +12 -1
- package/src/core/types.ts +15 -1
- package/src/core/ui-packs/ar.ts +10 -7
- package/src/core/ui-packs/bg.ts +10 -7
- package/src/core/ui-packs/bn.ts +10 -7
- package/src/core/ui-packs/ca.ts +7 -6
- package/src/core/ui-packs/cs.ts +10 -7
- package/src/core/ui-packs/da.ts +10 -7
- package/src/core/ui-packs/de.ts +10 -7
- package/src/core/ui-packs/el.ts +7 -6
- package/src/core/ui-packs/es.ts +7 -6
- package/src/core/ui-packs/fa.ts +10 -7
- package/src/core/ui-packs/fi.ts +10 -7
- package/src/core/ui-packs/fr.ts +7 -6
- package/src/core/ui-packs/he.ts +10 -7
- package/src/core/ui-packs/hi.ts +10 -7
- package/src/core/ui-packs/hr.ts +10 -7
- package/src/core/ui-packs/hu.ts +10 -7
- package/src/core/ui-packs/id.ts +10 -7
- package/src/core/ui-packs/it.ts +7 -6
- package/src/core/ui-packs/ja.ts +7 -6
- package/src/core/ui-packs/ko.ts +7 -6
- package/src/core/ui-packs/nl.ts +10 -7
- package/src/core/ui-packs/no.ts +10 -7
- package/src/core/ui-packs/pl.ts +10 -7
- package/src/core/ui-packs/pt-br.ts +7 -6
- package/src/core/ui-packs/pt.ts +7 -6
- package/src/core/ui-packs/ro.ts +10 -7
- package/src/core/ui-packs/ru.ts +10 -7
- package/src/core/ui-packs/sk.ts +10 -7
- package/src/core/ui-packs/sr.ts +10 -7
- package/src/core/ui-packs/sv.ts +10 -7
- package/src/core/ui-packs/th.ts +7 -6
- package/src/core/ui-packs/tr.ts +10 -7
- package/src/core/ui-packs/uk.ts +10 -7
- package/src/core/ui-packs/vi.ts +7 -6
- package/src/core/ui-packs/zh-tw.ts +7 -6
- package/src/core/ui-packs/zh.ts +7 -6
- package/src/core/unrecognized-keys.ts +10 -0
- package/src/core/version-cut.ts +116 -8
- package/src/deploy/adapter-output.ts +57 -97
- package/src/deploy/adapters/cloudflare.ts +39 -0
- package/src/deploy/adapters/index.ts +41 -0
- package/src/deploy/adapters/netlify.ts +34 -0
- package/src/deploy/adapters/node.ts +34 -0
- package/src/deploy/adapters/registry.ts +127 -0
- package/src/deploy/adapters/types.ts +92 -0
- package/src/deploy/adapters/vercel.ts +35 -0
- package/src/deploy/artifacts.ts +55 -27
- package/src/deploy/cloudflare-negotiation.ts +179 -100
- package/src/deploy/function-bundle.ts +18 -3
- package/src/deploy/headers.ts +124 -23
- package/src/deploy/node-headers.ts +198 -0
- package/src/deploy/platforms/cloudflare.ts +312 -0
- package/src/deploy/platforms/index.ts +67 -0
- package/src/deploy/platforms/netlify.ts +52 -0
- package/src/deploy/platforms/node.ts +40 -0
- package/src/deploy/platforms/paths.ts +42 -0
- package/src/deploy/platforms/static.ts +29 -0
- package/src/deploy/platforms/types.ts +112 -0
- package/src/deploy/platforms/vercel.ts +193 -0
- package/src/deploy/redirects.ts +30 -18
- package/src/deploy/robots.ts +3 -3
- package/src/deploy/rss.ts +2 -2
- package/src/deploy/sitemap.ts +2 -2
- package/src/deploy/vercel-negotiation.ts +2 -2
- package/src/eval/agents.ts +32 -1
- package/src/eval/findings.ts +19 -11
- package/src/eval/report.ts +10 -2
- package/src/markdown/external-links.ts +65 -0
- package/src/markdown/include.ts +45 -27
- package/src/markdown/index.ts +34 -9
- package/src/markdown/inline-code.ts +12 -6
- package/src/markdown/relative-links.ts +324 -0
- package/src/markdown/themes.ts +3 -3
- package/src/migrate/migrate.ts +149 -0
- package/src/openapi/parse.ts +64 -16
- package/src/openapi/proxy.ts +62 -10
- package/src/openapi/references.ts +147 -147
- package/src/openapi/render-mdx.ts +32 -10
- package/src/openapi/scalar.ts +15 -13
- package/src/openapi/sentence.ts +14 -0
- package/src/openapi/source.ts +37 -21
- package/src/openapi/spec-dependency-error.ts +15 -0
- package/src/reference/asyncapi.ts +83 -0
- package/src/reference/graphql.ts +89 -0
- package/src/reference/index.ts +40 -0
- package/src/reference/openapi.ts +83 -0
- package/src/reference/options.ts +201 -0
- package/src/reference/scalar.ts +136 -0
- package/src/reference/schema.ts +88 -0
- package/src/registry/eject.ts +109 -53
- package/src/search/adapters/algolia.ts +46 -0
- package/src/search/adapters/flexsearch.ts +29 -0
- package/src/search/adapters/index.ts +39 -0
- package/src/search/adapters/mixedbread.ts +39 -0
- package/src/search/adapters/orama-cloud.ts +51 -0
- package/src/search/adapters/orama.ts +24 -0
- package/src/search/adapters/pagefind.ts +27 -0
- package/src/search/adapters/registry.ts +131 -0
- package/src/search/adapters/types.ts +46 -0
- package/src/search/adapters/typesense.ts +57 -0
- package/src/search/build.ts +8 -4
- package/src/search/documents.ts +8 -2
- package/src/search/orama-index.ts +1 -1
- package/src/search/sync/algolia.ts +12 -11
- package/src/search/sync/index.ts +35 -20
- package/src/search/sync/orama-cloud.ts +12 -9
- package/src/search/sync/typesense.ts +15 -13
- package/src/sources/contentful.ts +63 -0
- package/src/sources/custom.ts +38 -0
- package/src/sources/filesystem.ts +51 -0
- package/src/sources/github-releases.ts +52 -0
- package/src/sources/index.ts +60 -0
- package/src/sources/mdx-remote.ts +76 -0
- package/src/sources/notion.ts +63 -0
- package/src/sources/obsidian.ts +38 -0
- package/src/sources/payload.ts +60 -0
- package/src/sources/registry.ts +182 -0
- package/src/sources/sanity.ts +66 -0
- package/src/sources/shared.ts +52 -0
- package/src/sources/strapi.ts +58 -0
- package/src/theme/entry.ts +24 -2
- package/src/translate/report.ts +40 -7
- package/src/upgrade/upgrade.ts +499 -0
- package/dist/cli/chunk-0qymqwzz.js +0 -164
- package/dist/cli/chunk-0qymqwzz.js.map +0 -15
- package/dist/cli/chunk-1jefwnfs.js.map +0 -48
- package/dist/cli/chunk-2mzebbbz.js +0 -69
- package/dist/cli/chunk-2z47ypj8.js.map +0 -11
- package/dist/cli/chunk-4x36ddpw.js.map +0 -11
- package/dist/cli/chunk-5093q3n7.js +0 -68
- package/dist/cli/chunk-5093q3n7.js.map +0 -10
- package/dist/cli/chunk-5qk08vmp.js.map +0 -11
- package/dist/cli/chunk-7s8hm3b6.js +0 -5347
- package/dist/cli/chunk-7s8hm3b6.js.map +0 -58
- package/dist/cli/chunk-8cjtbafj.js.map +0 -13
- package/dist/cli/chunk-97r59kpr.js +0 -381
- package/dist/cli/chunk-97r59kpr.js.map +0 -12
- package/dist/cli/chunk-ahnw3kxw.js.map +0 -15
- package/dist/cli/chunk-b27xqwn9.js.map +0 -10
- package/dist/cli/chunk-bf6bt1xt.js +0 -185
- package/dist/cli/chunk-bf6bt1xt.js.map +0 -11
- package/dist/cli/chunk-cjtn640a.js.map +0 -10
- package/dist/cli/chunk-ct47dqpx.js.map +0 -11
- package/dist/cli/chunk-esphfr8p.js +0 -107
- package/dist/cli/chunk-esphfr8p.js.map +0 -11
- package/dist/cli/chunk-ex56aa81.js +0 -1016
- package/dist/cli/chunk-ex56aa81.js.map +0 -13
- package/dist/cli/chunk-garjf5z9.js +0 -30
- package/dist/cli/chunk-garjf5z9.js.map +0 -10
- package/dist/cli/chunk-js7saxwm.js +0 -1045
- package/dist/cli/chunk-js7saxwm.js.map +0 -22
- package/dist/cli/chunk-k79xp7av.js.map +0 -39
- package/dist/cli/chunk-ps4m1xh4.js.map +0 -15
- package/dist/cli/chunk-q4rae3bg.js +0 -60
- package/dist/cli/chunk-q4rae3bg.js.map +0 -10
- package/dist/cli/chunk-rz9jmfhz.js +0 -108
- package/dist/cli/chunk-rz9jmfhz.js.map +0 -10
- package/dist/cli/chunk-vh9w1sgp.js +0 -73
- package/dist/cli/chunk-vh9w1sgp.js.map +0 -10
- package/dist/cli/chunk-vrfp10qk.js +0 -81
- package/dist/cli/chunk-vrfp10qk.js.map +0 -10
- package/dist/cli/chunk-yg63d42r.js.map +0 -34
- package/docs/advanced/api-reference.mdx +0 -240
- package/docs/configuration/ask-ai.mdx +0 -256
- package/docs/reference/cli.mdx +0 -197
- package/skills/blume-migrate/assets/oxfmt@0.55.0.patch +0 -20
- package/src/components/content/changelog-element.ts +0 -69
- package/src/search/providers.ts +0 -91
- /package/dist/cli/{chunk-vacwm2hv.js.map → chunk-27g6wdth.js.map} +0 -0
- /package/dist/cli/{chunk-dwgcp5sm.js.map → chunk-ce574jw2.js.map} +0 -0
- /package/dist/cli/{chunk-e7f42gdj.js.map → chunk-fxypxtvm.js.map} +0 -0
- /package/dist/cli/{chunk-nn13znc2.js.map → chunk-zxcczpyx.js.map} +0 -0
package/src/core/schema.ts
CHANGED
|
@@ -1,19 +1,41 @@
|
|
|
1
1
|
import type { AstroIntegration } from "astro";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
|
|
4
|
+
import {
|
|
5
|
+
assistantAdapterSchema,
|
|
6
|
+
assistantMovedFieldsHint,
|
|
7
|
+
DEFAULT_ASSISTANT_PROVIDER,
|
|
8
|
+
} from "../ai/ask.ts";
|
|
4
9
|
import type { ComponentMarkdown } from "../ai/component-markdown.ts";
|
|
10
|
+
import { analyticsConfigSchema } from "../analytics/schema.ts";
|
|
11
|
+
import { resolvedDeploymentSchema } from "../deploy/adapters/registry.ts";
|
|
5
12
|
import type { CodeTheme } from "../markdown/themes.ts";
|
|
6
13
|
import { normalizeRoute } from "../openapi/references.ts";
|
|
14
|
+
import {
|
|
15
|
+
referenceConfigSchema,
|
|
16
|
+
removedReferenceKeysHint,
|
|
17
|
+
} from "../reference/schema.ts";
|
|
18
|
+
import { orama } from "../search/adapters/orama.ts";
|
|
19
|
+
import {
|
|
20
|
+
NONE_SEARCH_ADAPTER,
|
|
21
|
+
resolvedSearchAdapterSchema,
|
|
22
|
+
} from "../search/adapters/registry.ts";
|
|
23
|
+
import type { SearchAdapterInput } from "../search/adapters/registry.ts";
|
|
7
24
|
import { normalizeXHandle } from "../seo/x-handle.ts";
|
|
25
|
+
import { filesystem } from "../sources/filesystem.ts";
|
|
26
|
+
import {
|
|
27
|
+
contentSourcesSchema,
|
|
28
|
+
resolvedSourceAdapterSchema,
|
|
29
|
+
} from "../sources/registry.ts";
|
|
8
30
|
import { FONT_SLUGS, isFontSlug } from "../theme/fonts.ts";
|
|
9
31
|
import { normalizeBasePath } from "./base-path.ts";
|
|
10
32
|
import { PUBLIC_HOST_URL } from "./github.ts";
|
|
11
33
|
import { uiLocaleOverridesSchema } from "./i18n-ui.ts";
|
|
12
34
|
import { openInChatProviders } from "./open-in-chat.ts";
|
|
13
|
-
import type { ContentSource } from "./sources/types.ts";
|
|
14
35
|
import { isStandardSchema } from "./standard-schema.ts";
|
|
15
36
|
import type { StandardSchema } from "./standard-schema.ts";
|
|
16
37
|
import { trimEnd } from "./trim.ts";
|
|
38
|
+
import { unrecognizedKeysMessage } from "./unrecognized-keys.ts";
|
|
17
39
|
|
|
18
40
|
/**
|
|
19
41
|
* An absolute HTTP(S) URL, for any field that lands verbatim in an `href` —
|
|
@@ -42,12 +64,40 @@ const isString = <Value>(value: Value): value is Value & string =>
|
|
|
42
64
|
const isBoolean = <Value>(value: Value): value is Value & boolean =>
|
|
43
65
|
typeof value === "boolean";
|
|
44
66
|
|
|
67
|
+
const isObjectLike = <Value>(value: Value): value is Value & object =>
|
|
68
|
+
typeof value === "object" && value !== null;
|
|
69
|
+
|
|
45
70
|
/** Icon inputs in serializable contexts (frontmatter, meta files). */
|
|
46
71
|
const iconName = z.string().min(1);
|
|
47
72
|
|
|
48
|
-
/**
|
|
49
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Error params for a strict object whose keys were removed or moved in a
|
|
75
|
+
* major release. A config still carrying one of `hints`' keys fails with
|
|
76
|
+
* the message that names its replacement, instead of Zod's bare
|
|
77
|
+
* "Unrecognized key"; any other unknown key keeps the default message.
|
|
78
|
+
*/
|
|
79
|
+
const removedKeysHint = (hints: Record<string, string>) => ({
|
|
80
|
+
error: (issue: z.core.$ZodRawIssue): string | undefined => {
|
|
81
|
+
if (issue.code !== "unrecognized_keys") {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const messages = issue.keys.flatMap((key) =>
|
|
85
|
+
Object.hasOwn(hints, key) ? [hints[key]] : []
|
|
86
|
+
);
|
|
87
|
+
if (messages.length === 0) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
// A hinted key beside a plain unknown one: keep Zod's wording for the
|
|
91
|
+
// latter so it isn't silently dropped from the diagnostic.
|
|
92
|
+
const others = issue.keys.filter((key) => !Object.hasOwn(hints, key));
|
|
93
|
+
if (others.length > 0) {
|
|
94
|
+
messages.push(unrecognizedKeysMessage(others));
|
|
95
|
+
}
|
|
96
|
+
return messages.join(" ");
|
|
97
|
+
},
|
|
98
|
+
});
|
|
50
99
|
|
|
100
|
+
/** Default include glob for filesystem-backed content sources. */
|
|
51
101
|
const hydrationMode = z.enum(["load", "idle", "visible", "media", "only"]);
|
|
52
102
|
export type HydrationMode = z.infer<typeof hydrationMode>;
|
|
53
103
|
|
|
@@ -105,11 +155,16 @@ const seoMetaSchema = z.strictObject({
|
|
|
105
155
|
x: z.strictObject({ creator: xHandleSchema }).optional(),
|
|
106
156
|
});
|
|
107
157
|
|
|
108
|
-
const searchMetaSchema = z.strictObject(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
158
|
+
const searchMetaSchema = z.strictObject(
|
|
159
|
+
{
|
|
160
|
+
exclude: z.boolean().default(false),
|
|
161
|
+
tags: z.array(z.string()).optional(),
|
|
162
|
+
},
|
|
163
|
+
removedKeysHint({
|
|
164
|
+
boost:
|
|
165
|
+
"search.boost was removed: search never read it, so the page ranked the same without it. Delete the field.",
|
|
166
|
+
})
|
|
167
|
+
);
|
|
113
168
|
|
|
114
169
|
const aiMetaSchema = z.strictObject({
|
|
115
170
|
/** Exclude this page from llms.txt and llms-full.txt. */
|
|
@@ -291,161 +346,8 @@ const bannerConfigSchema = z.union([
|
|
|
291
346
|
}),
|
|
292
347
|
]);
|
|
293
348
|
|
|
294
|
-
/** A
|
|
295
|
-
|
|
296
|
-
exclude: z.array(z.string()).default(["**/_*", "**/.*"]),
|
|
297
|
-
include: z.array(z.string()).default([DEFAULT_CONTENT_GLOB]),
|
|
298
|
-
/** Namespaces the source's routes under `/<prefix>/`. */
|
|
299
|
-
prefix: z.string().optional(),
|
|
300
|
-
root: z.string().default("docs"),
|
|
301
|
-
type: z.literal("filesystem"),
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* Remote Markdown/MDX fetched over HTTP. Enumerate files either explicitly
|
|
306
|
-
* (`files` against a raw `url` base) or from a GitHub repo subtree (`github`).
|
|
307
|
-
* The token, when needed, comes from `GITHUB_TOKEN` — never inlined here.
|
|
308
|
-
*/
|
|
309
|
-
const mdxRemoteSourceSchema = z.strictObject({
|
|
310
|
-
/** Explicit list of source-relative file paths to fetch from `url`. */
|
|
311
|
-
files: z.array(z.string()).optional(),
|
|
312
|
-
/** Enumerate a GitHub repo subtree via the git-trees API. */
|
|
313
|
-
github: z
|
|
314
|
-
.strictObject({
|
|
315
|
-
owner: z.string(),
|
|
316
|
-
path: z.string().default(""),
|
|
317
|
-
ref: z.string().default("main"),
|
|
318
|
-
repo: z.string(),
|
|
319
|
-
})
|
|
320
|
-
.optional(),
|
|
321
|
-
/** Glob patterns applied to enumerated refs. */
|
|
322
|
-
include: z.array(z.string()).default([DEFAULT_CONTENT_GLOB]),
|
|
323
|
-
/** Opt-in dev polling interval (seconds); omit to freeze for the session. */
|
|
324
|
-
pollInterval: z.number().positive().optional(),
|
|
325
|
-
/** Namespaces the source's routes under `/<prefix>/`. */
|
|
326
|
-
prefix: z.string().optional(),
|
|
327
|
-
type: z.literal("mdx-remote"),
|
|
328
|
-
/** Raw base URL, e.g. `https://raw.githubusercontent.com/acme/sdk/main/docs`. */
|
|
329
|
-
url: z.string().optional(),
|
|
330
|
-
});
|
|
331
|
-
|
|
332
|
-
/** A Sanity dataset queried with GROQ; Portable Text bodies become Markdown. */
|
|
333
|
-
const sanitySourceSchema = z.object({
|
|
334
|
-
/** Sanity API version (a date); default `2024-01-01`. */
|
|
335
|
-
apiVersion: z.string().optional(),
|
|
336
|
-
dataset: z.string(),
|
|
337
|
-
/** Field paths mapping a document onto Blume meta + body. */
|
|
338
|
-
fields: z
|
|
339
|
-
.strictObject({
|
|
340
|
-
body: z.string().optional(),
|
|
341
|
-
description: z.string().optional(),
|
|
342
|
-
lastModified: z.string().optional(),
|
|
343
|
-
slug: z.string().optional(),
|
|
344
|
-
title: z.string().optional(),
|
|
345
|
-
})
|
|
346
|
-
.optional(),
|
|
347
|
-
/** Opt-in dev polling interval (seconds); omit to freeze for the session. */
|
|
348
|
-
pollInterval: z.number().positive().optional(),
|
|
349
|
-
prefix: z.string().optional(),
|
|
350
|
-
projectId: z.string(),
|
|
351
|
-
/** GROQ query selecting the documents to import. */
|
|
352
|
-
query: z.string(),
|
|
353
|
-
type: z.literal("sanity"),
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
/** A Notion database; pages become entries, blocks become MDX. */
|
|
357
|
-
const notionSourceSchema = z.object({
|
|
358
|
-
/** Max concurrent Notion API requests; default 3 (Notion's per-integration pace). */
|
|
359
|
-
concurrency: z.number().positive().optional(),
|
|
360
|
-
database: z.string(),
|
|
361
|
-
/** Opt-in dev polling interval (seconds); omit to freeze for the session. */
|
|
362
|
-
pollInterval: z.number().positive().optional(),
|
|
363
|
-
prefix: z.string().optional(),
|
|
364
|
-
/** Notion property names mapped onto Blume meta. */
|
|
365
|
-
properties: z
|
|
366
|
-
.strictObject({
|
|
367
|
-
description: z.string().optional(),
|
|
368
|
-
order: z.string().optional(),
|
|
369
|
-
slug: z.string().optional(),
|
|
370
|
-
status: z.string().optional(),
|
|
371
|
-
title: z.string().optional(),
|
|
372
|
-
})
|
|
373
|
-
.optional(),
|
|
374
|
-
/** Status value treated as published; others map to `draft`. Default `Published`. */
|
|
375
|
-
publishedValue: z.string().optional(),
|
|
376
|
-
type: z.literal("notion"),
|
|
377
|
-
});
|
|
378
|
-
|
|
379
|
-
/**
|
|
380
|
-
* An Obsidian vault, read in place. Wikilinks become route links and
|
|
381
|
-
* `%%comments%%` are stripped at load time, so the vault stays the source of
|
|
382
|
-
* truth — no export step and no generated notes in the repo.
|
|
383
|
-
*/
|
|
384
|
-
const obsidianSourceSchema = z.strictObject({
|
|
385
|
-
/** Vault folder names to skip at any depth, in addition to dot-folders. */
|
|
386
|
-
exclude: z.array(z.string()).optional(),
|
|
387
|
-
/** Namespaces the source's routes under `/<prefix>/`; e.g. `vault`. */
|
|
388
|
-
prefix: z.string().optional(),
|
|
389
|
-
type: z.literal("obsidian"),
|
|
390
|
-
/** Vault directory, absolute or relative to the project root. */
|
|
391
|
-
vault: z.string().min(1),
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
/**
|
|
395
|
-
* A repo's GitHub Releases, materialized as `type: changelog` entries — release
|
|
396
|
-
* notes become the changelog with no files to maintain. A private repo reads a
|
|
397
|
-
* token from `GITHUB_TOKEN`; it is never inlined here.
|
|
398
|
-
*/
|
|
399
|
-
const githubReleasesSourceSchema = z.strictObject({
|
|
400
|
-
/** Include draft releases (needs a token with repo write access). */
|
|
401
|
-
drafts: z.boolean().optional(),
|
|
402
|
-
/** Cap the number of releases materialized, newest-first. Default 100. */
|
|
403
|
-
limit: z.number().positive().optional(),
|
|
404
|
-
/** Repository owner (user or org). */
|
|
405
|
-
owner: z.string(),
|
|
406
|
-
/** Opt-in dev polling interval (seconds); omit to freeze for the session. */
|
|
407
|
-
pollInterval: z.number().positive().optional(),
|
|
408
|
-
/** Namespaces the source's routes under `/<prefix>/`; e.g. `changelog`. */
|
|
409
|
-
prefix: z.string().optional(),
|
|
410
|
-
/** Include prereleases. */
|
|
411
|
-
prereleases: z.boolean().optional(),
|
|
412
|
-
/** Repository name. */
|
|
413
|
-
repo: z.string(),
|
|
414
|
-
type: z.literal("github-releases"),
|
|
415
|
-
});
|
|
416
|
-
|
|
417
|
-
/**
|
|
418
|
-
* A user-provided `ContentSource` instance, passed straight through from
|
|
419
|
-
* `blume.config.ts`. This is the extension point that lets adapters with custom
|
|
420
|
-
* serializers (or any backend) ship without their SDKs touching core.
|
|
421
|
-
*/
|
|
422
|
-
const customSourceSchema = z.object({
|
|
423
|
-
source: z.custom<ContentSource>(
|
|
424
|
-
(val): val is ContentSource =>
|
|
425
|
-
typeof val === "object" &&
|
|
426
|
-
val !== null &&
|
|
427
|
-
"load" in val &&
|
|
428
|
-
typeof val.load === "function" &&
|
|
429
|
-
"name" in val &&
|
|
430
|
-
typeof val.name === "string",
|
|
431
|
-
{ message: "custom source must be a ContentSource (with name + load)" }
|
|
432
|
-
),
|
|
433
|
-
type: z.literal("custom"),
|
|
434
|
-
});
|
|
435
|
-
|
|
436
|
-
/** A single configured content source. */
|
|
437
|
-
const contentSourceSchema = z.discriminatedUnion("type", [
|
|
438
|
-
filesystemSourceSchema,
|
|
439
|
-
mdxRemoteSourceSchema,
|
|
440
|
-
githubReleasesSourceSchema,
|
|
441
|
-
sanitySourceSchema,
|
|
442
|
-
notionSourceSchema,
|
|
443
|
-
obsidianSourceSchema,
|
|
444
|
-
customSourceSchema,
|
|
445
|
-
]);
|
|
446
|
-
|
|
447
|
-
/** A resolved content-source config entry (post-defaults). */
|
|
448
|
-
export type ContentSourceConfig = z.infer<typeof contentSourceSchema>;
|
|
349
|
+
/** A validated `content.sources` entry: an adapter descriptor from `blume/sources`. */
|
|
350
|
+
export type { ContentSourceAdapter } from "../sources/registry.ts";
|
|
449
351
|
|
|
450
352
|
/**
|
|
451
353
|
* Per-type content definition. An object (rather than a bare frontmatter map)
|
|
@@ -471,24 +373,51 @@ const contentTypeConfigSchema = z.strictObject({
|
|
|
471
373
|
frontmatter: customKeySchemaRecord("content.types"),
|
|
472
374
|
});
|
|
473
375
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
376
|
+
/** The top-level fields that are shorthand for a single `filesystem()` source. */
|
|
377
|
+
const FILESYSTEM_SHORTHAND_KEYS = ["exclude", "include", "root"] as const;
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* `content`: where pages come from. `sources` lists adapters from
|
|
381
|
+
* `blume/sources`; the top-level `root`/`include`/`exclude` are zero-config
|
|
382
|
+
* shorthand that desugars to exactly one `filesystem()` entry when `sources`
|
|
383
|
+
* is absent, and are rejected beside it — so after parse, `sources` is the
|
|
384
|
+
* one source of truth and nothing downstream picks between the two.
|
|
385
|
+
*/
|
|
386
|
+
const contentConfigSchema = z
|
|
387
|
+
.strictObject({
|
|
388
|
+
defaultType: z.string().default("doc"),
|
|
389
|
+
exclude: z.array(z.string()).optional(),
|
|
390
|
+
include: z.array(z.string()).optional(),
|
|
391
|
+
pages: z.string().default("pages"),
|
|
392
|
+
root: z.string().optional(),
|
|
393
|
+
sources: contentSourcesSchema.optional(),
|
|
394
|
+
/**
|
|
395
|
+
* Per-type content definitions, keyed by the frontmatter `type` they apply
|
|
396
|
+
* to (including `defaultType`, for pages that set none).
|
|
397
|
+
*/
|
|
398
|
+
types: z.record(z.string(), contentTypeConfigSchema).default({}),
|
|
399
|
+
})
|
|
400
|
+
.superRefine((value, ctx) => {
|
|
401
|
+
if (!value.sources) {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
for (const key of FILESYSTEM_SHORTHAND_KEYS) {
|
|
405
|
+
if (value[key] !== undefined) {
|
|
406
|
+
ctx.addIssue({
|
|
407
|
+
code: z.ZodIssueCode.custom,
|
|
408
|
+
message: `content.${key} is shorthand for a single filesystem() source and can't be combined with content.sources — move it into a filesystem({ ${key} }) entry in content.sources.`,
|
|
409
|
+
path: [key],
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
})
|
|
414
|
+
.transform(({ exclude, include, root, sources, ...rest }) => ({
|
|
415
|
+
...rest,
|
|
416
|
+
sources: sources ?? [
|
|
417
|
+
// The shorthand's defaults are the adapter's own, applied by its schema.
|
|
418
|
+
resolvedSourceAdapterSchema.parse(filesystem({ exclude, include, root })),
|
|
419
|
+
],
|
|
420
|
+
}));
|
|
492
421
|
|
|
493
422
|
/**
|
|
494
423
|
* A header label that may localize: a plain string, or a map of locale code to
|
|
@@ -655,7 +584,7 @@ const perModeValueSchema = z
|
|
|
655
584
|
isString(value) ? { dark: value, light: value } : value
|
|
656
585
|
);
|
|
657
586
|
|
|
658
|
-
const
|
|
587
|
+
const themeConfigFields = {
|
|
659
588
|
accent: z
|
|
660
589
|
.union([
|
|
661
590
|
z.string(),
|
|
@@ -675,58 +604,17 @@ const themeConfigSchema = z.strictObject({
|
|
|
675
604
|
mono: fontValueSchema.default("ibm-plex-mono"),
|
|
676
605
|
})
|
|
677
606
|
.prefault({}),
|
|
678
|
-
layout: z.enum(["sidebar"]).default("sidebar"),
|
|
679
607
|
mode: z.enum(["system", "light", "dark"]).default("system"),
|
|
680
608
|
radius: z.enum(["none", "sm", "md", "lg"]).default("md"),
|
|
681
|
-
}
|
|
682
|
-
|
|
683
|
-
/** Public credentials for the Algolia search backend (sync key is an env var). */
|
|
684
|
-
const algoliaSearchSchema = z.strictObject({
|
|
685
|
-
appId: z.string(),
|
|
686
|
-
indexName: z.string(),
|
|
687
|
-
searchApiKey: z.string(),
|
|
688
|
-
});
|
|
689
|
-
|
|
690
|
-
/** Public credentials for the Orama Cloud search backend. */
|
|
691
|
-
const oramaCloudSearchSchema = z.strictObject({
|
|
692
|
-
apiKey: z.string(),
|
|
693
|
-
endpoint: z.string(),
|
|
694
|
-
/** Index id used by the build-time sync (with `ORAMA_PRIVATE_API_KEY`). */
|
|
695
|
-
indexId: z.string().optional(),
|
|
696
|
-
});
|
|
697
|
-
|
|
698
|
-
/** Public credentials for a (self-hosted or cloud) Typesense backend. */
|
|
699
|
-
const typesenseSearchSchema = z.strictObject({
|
|
700
|
-
collection: z.string(),
|
|
701
|
-
host: z.string(),
|
|
702
|
-
port: z.number().int().positive().optional(),
|
|
703
|
-
protocol: z.enum(["http", "https"]).optional(),
|
|
704
|
-
searchApiKey: z.string(),
|
|
705
|
-
});
|
|
706
|
-
|
|
707
|
-
/** Mixedbread semantic search: the store the server endpoint queries. */
|
|
708
|
-
const mixedbreadSearchSchema = z.strictObject({
|
|
709
|
-
storeId: z.string(),
|
|
710
|
-
});
|
|
711
|
-
|
|
712
|
-
export const searchProviders = [
|
|
713
|
-
"orama",
|
|
714
|
-
"pagefind",
|
|
715
|
-
"flexsearch",
|
|
716
|
-
"algolia",
|
|
717
|
-
"orama-cloud",
|
|
718
|
-
"typesense",
|
|
719
|
-
"mixedbread",
|
|
720
|
-
"none",
|
|
721
|
-
] as const;
|
|
609
|
+
};
|
|
722
610
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
611
|
+
const themeConfigSchema = z.strictObject(
|
|
612
|
+
themeConfigFields,
|
|
613
|
+
removedKeysHint({
|
|
614
|
+
layout:
|
|
615
|
+
"theme.layout was removed: the sidebar layout is the only one, so delete the field.",
|
|
616
|
+
})
|
|
617
|
+
);
|
|
730
618
|
|
|
731
619
|
/** Curated link for the search dialog empty state (internal route or external URL). */
|
|
732
620
|
const searchPopularLinkSchema = z.strictObject({
|
|
@@ -735,59 +623,82 @@ const searchPopularLinkSchema = z.strictObject({
|
|
|
735
623
|
label: z.string(),
|
|
736
624
|
});
|
|
737
625
|
|
|
738
|
-
|
|
626
|
+
/**
|
|
627
|
+
* The search backend: an adapter descriptor from `blume/search` (`algolia({…})`,
|
|
628
|
+
* `orama()`, …) or `false` to disable search. Resolves to a descriptor either
|
|
629
|
+
* way — `false` becomes the `none` adapter — so consumers read `kind`,
|
|
630
|
+
* `runtimeDeps`, and `requiredSecrets` without a special case.
|
|
631
|
+
*/
|
|
632
|
+
const searchProviderSchema = z
|
|
633
|
+
.custom<false | SearchAdapterInput>(
|
|
634
|
+
// A 1.x provider name (`"algolia"`, `"none"`) fails here with the adapter
|
|
635
|
+
// that replaces it, rather than the pipe's bare "expected object".
|
|
636
|
+
(value) => value === false || isObjectLike(value),
|
|
637
|
+
{
|
|
638
|
+
message:
|
|
639
|
+
'search.provider takes an adapter from "blume/search" — algolia({…}), pagefind(), … — not a provider name. The 1.x provider string was removed, and "none" is now `search: false`.',
|
|
640
|
+
}
|
|
641
|
+
)
|
|
642
|
+
.transform((value) => (value === false ? NONE_SEARCH_ADAPTER : value))
|
|
643
|
+
.pipe(resolvedSearchAdapterSchema);
|
|
644
|
+
|
|
645
|
+
/** Indexing behavior shared by every source-built index. */
|
|
646
|
+
const searchIndexingSchema = z
|
|
739
647
|
.strictObject({
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
648
|
+
includeCodeBlocks: z.boolean().default(false),
|
|
649
|
+
includeHiddenPages: z.boolean().default(false),
|
|
650
|
+
})
|
|
651
|
+
.prefault({});
|
|
652
|
+
|
|
653
|
+
/** The object form of `search`: the adapter plus its adapter-independent settings. */
|
|
654
|
+
const searchOptionsSchema = z.strictObject(
|
|
655
|
+
{
|
|
656
|
+
indexing: searchIndexingSchema,
|
|
749
657
|
/** Curated links for the Cmd+K empty state; defaults to the first sidebar pages. */
|
|
750
658
|
popular: z.array(searchPopularLinkSchema).default([]),
|
|
751
|
-
provider:
|
|
752
|
-
|
|
659
|
+
provider: searchProviderSchema.default(() => orama()),
|
|
660
|
+
},
|
|
661
|
+
// The 1.x credential blocks, each now its adapter's options.
|
|
662
|
+
removedKeysHint({
|
|
663
|
+
algolia:
|
|
664
|
+
'search.algolia moved into its adapter: `search: algolia({ appId, indexName, apiKey })` from "blume/search", where the 1.x `searchApiKey` is now `apiKey`.',
|
|
665
|
+
mixedbread:
|
|
666
|
+
'search.mixedbread moved into its adapter: `search: mixedbread({ storeId })` from "blume/search".',
|
|
667
|
+
oramaCloud:
|
|
668
|
+
'search.oramaCloud moved into its adapter: `search: oramaCloud({ endpoint, apiKey, indexId })` from "blume/search".',
|
|
669
|
+
typesense:
|
|
670
|
+
'search.typesense moved into its adapter: `search: typesense({ host, collection, apiKey })` from "blume/search", where the 1.x `searchApiKey` is now `apiKey`.',
|
|
753
671
|
})
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
PROVIDER_CONFIG_KEY[value.provider as keyof typeof PROVIDER_CONFIG_KEY];
|
|
761
|
-
if (field && !value[field]) {
|
|
762
|
-
ctx.addIssue({
|
|
763
|
-
code: z.ZodIssueCode.custom,
|
|
764
|
-
message: `search.${field} is required when provider is "${value.provider}".`,
|
|
765
|
-
path: [field],
|
|
766
|
-
});
|
|
767
|
-
}
|
|
768
|
-
});
|
|
672
|
+
);
|
|
673
|
+
|
|
674
|
+
type SearchOptionsInput = z.input<typeof searchOptionsSchema>;
|
|
675
|
+
|
|
676
|
+
/** What `search` accepts: an adapter (or `false`) directly, or the object form. */
|
|
677
|
+
type SearchConfigInput = false | SearchAdapterInput | SearchOptionsInput;
|
|
769
678
|
|
|
770
679
|
/**
|
|
771
|
-
*
|
|
772
|
-
*
|
|
680
|
+
* `search` takes an adapter directly (`search: algolia({…})`, or `false`) as
|
|
681
|
+
* shorthand for the object form (`search: { provider: algolia({…}), popular,
|
|
682
|
+
* indexing }`). The shorthand is lifted into `provider` before the object
|
|
683
|
+
* schema validates, rather than through a union: a union reports whichever
|
|
684
|
+
* branch fails "softest", which for a descriptor missing an option is the
|
|
685
|
+
* object form's "unrecognized keys" — pointing at the wrong problem. A
|
|
686
|
+
* descriptor is recognized by its `kind`; the object form never has one.
|
|
773
687
|
*/
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
"inkeep",
|
|
789
|
-
"openai-compatible",
|
|
790
|
-
] as const;
|
|
688
|
+
const searchConfigSchema = z
|
|
689
|
+
.custom<SearchConfigInput>(
|
|
690
|
+
// Anything else (a 1.x provider string, null, true) must become a
|
|
691
|
+
// diagnostic here: the `in` check below would throw a TypeError on it.
|
|
692
|
+
(value) => value === false || isObjectLike(value),
|
|
693
|
+
{
|
|
694
|
+
message:
|
|
695
|
+
'search must be an adapter from "blume/search" (orama(), algolia({…}), …), false, or { provider, popular, indexing }. The 1.x provider string was removed.',
|
|
696
|
+
}
|
|
697
|
+
)
|
|
698
|
+
.transform((value): SearchOptionsInput =>
|
|
699
|
+
value === false || "kind" in value ? { provider: value } : value
|
|
700
|
+
)
|
|
701
|
+
.pipe(searchOptionsSchema);
|
|
791
702
|
|
|
792
703
|
/**
|
|
793
704
|
* JWK parameters that carry private or secret key material (RFC 7518): the
|
|
@@ -833,7 +744,7 @@ const mcpConfigSchema = z.strictObject({
|
|
|
833
744
|
route: z.string().default("/mcp").transform(normalizeRoute),
|
|
834
745
|
});
|
|
835
746
|
|
|
836
|
-
const
|
|
747
|
+
const assistantEndpointSchema = z
|
|
837
748
|
.string()
|
|
838
749
|
.trim()
|
|
839
750
|
.min(1)
|
|
@@ -851,11 +762,11 @@ const askEndpointSchema = z
|
|
|
851
762
|
},
|
|
852
763
|
{
|
|
853
764
|
message:
|
|
854
|
-
"ai.
|
|
765
|
+
"ai.assistant.endpoint must be an HTTP(S) URL or a root-relative path.",
|
|
855
766
|
}
|
|
856
767
|
);
|
|
857
768
|
|
|
858
|
-
/** The object form of `
|
|
769
|
+
/** The object form of `agents.llmsTxt`; a bare boolean normalizes onto it. */
|
|
859
770
|
const llmsTxtObjectSchema = z.strictObject({
|
|
860
771
|
/**
|
|
861
772
|
* Markdown inserted after the title and summary, before the page sections:
|
|
@@ -869,7 +780,7 @@ const llmsTxtObjectSchema = z.strictObject({
|
|
|
869
780
|
|
|
870
781
|
type LlmsTxtResolved = z.output<typeof llmsTxtObjectSchema>;
|
|
871
782
|
|
|
872
|
-
/** The object form of `
|
|
783
|
+
/** The object form of `agents.catalog`; a bare boolean normalizes onto it. */
|
|
873
784
|
const aiCatalogObjectSchema = z.strictObject({
|
|
874
785
|
enabled: z.boolean().default(true),
|
|
875
786
|
/**
|
|
@@ -886,168 +797,104 @@ const aiCatalogObjectSchema = z.strictObject({
|
|
|
886
797
|
|
|
887
798
|
type AiCatalogResolved = z.output<typeof aiCatalogObjectSchema>;
|
|
888
799
|
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
z.strictObject({
|
|
960
|
-
icon: iconName.optional(),
|
|
961
|
-
label: z.string().min(1),
|
|
800
|
+
/**
|
|
801
|
+
* The keys that moved from `ai` to `agents`: `ai` now holds only what faces a
|
|
802
|
+
* model at read time (the assistant, Open in chat), and the machine-readable surface
|
|
803
|
+
* agents consume lives under `agents`.
|
|
804
|
+
*/
|
|
805
|
+
const MOVED_TO_AGENTS = [
|
|
806
|
+
"api",
|
|
807
|
+
"catalog",
|
|
808
|
+
"llmsTxt",
|
|
809
|
+
"markdownComponents",
|
|
810
|
+
"mcp",
|
|
811
|
+
"skills",
|
|
812
|
+
"webBotAuth",
|
|
813
|
+
"webmcp",
|
|
814
|
+
] as const;
|
|
815
|
+
|
|
816
|
+
const movedToAgentsHints = (from: string): Record<string, string> =>
|
|
817
|
+
Object.fromEntries(
|
|
818
|
+
MOVED_TO_AGENTS.map((key) => [
|
|
819
|
+
key,
|
|
820
|
+
`${from}.${key} moved to agents.${key}.`,
|
|
821
|
+
])
|
|
822
|
+
);
|
|
823
|
+
|
|
824
|
+
/** Model-facing config: the assistant and the "Open in chat" action. */
|
|
825
|
+
const aiConfigFields = {
|
|
826
|
+
assistant: z
|
|
827
|
+
.strictObject(
|
|
828
|
+
{
|
|
829
|
+
// Origins allowed to call the generated `/api/ask` from another site (a
|
|
830
|
+
// marketing page that embeds an ask box, say), or `"*"` for every
|
|
831
|
+
// origin. Each URL is reduced to its origin so a trailing slash or path
|
|
832
|
+
// can't defeat the exact match the route performs. Read by the
|
|
833
|
+
// generated route only; an external `endpoint` owns its own CORS.
|
|
834
|
+
cors: z
|
|
835
|
+
.array(
|
|
836
|
+
z.union([
|
|
837
|
+
z.literal("*"),
|
|
838
|
+
z
|
|
839
|
+
.url({ protocol: /^https?$/u })
|
|
840
|
+
.transform((value) => new URL(value).origin),
|
|
841
|
+
])
|
|
842
|
+
)
|
|
843
|
+
.optional(),
|
|
844
|
+
enabled: z.boolean().default(false),
|
|
845
|
+
// Optional external endpoint for projects that keep their docs static
|
|
846
|
+
// and host the assistant in an existing backend. Absolute URLs and root-relative
|
|
847
|
+
// paths are both valid; the built-in request/stream contract is unchanged.
|
|
848
|
+
endpoint: assistantEndpointSchema.optional(),
|
|
849
|
+
// Extra system-prompt text (identity, language, tone) appended to the
|
|
850
|
+
// built-in instructions, so the grounding contract — answer from the
|
|
851
|
+
// retrieved excerpts, cite pages as Markdown links — stays intact.
|
|
852
|
+
instructions: z.string().trim().min(1).optional(),
|
|
853
|
+
// The adapter descriptor a `gateway()`/`openrouter()`/... factory
|
|
854
|
+
// returns; each adapter validates its own options (model, key env var,
|
|
855
|
+
// reasoning mapping, `providerOptions` passthrough) in `ai/ask.ts`.
|
|
856
|
+
// Unset means the gateway with its default model, so the zero-config assistant
|
|
857
|
+
// is unchanged.
|
|
858
|
+
provider: assistantAdapterSchema.prefault(DEFAULT_ASSISTANT_PROVIDER),
|
|
859
|
+
// How much documentation each question carries. Injected characters are
|
|
860
|
+
// the dominant term in time-to-first-token on a self-hosted backend, so
|
|
861
|
+
// these trade recall for latency. No zod defaults here: only what the
|
|
862
|
+
// user set reaches the generated (and ejected) endpoint, so omitted
|
|
863
|
+
// fields keep tracking the installed package's built-in defaults in
|
|
864
|
+
// `ai/ask-context.ts` instead of pinning today's numbers as literals.
|
|
865
|
+
retrieval: z
|
|
866
|
+
.strictObject({
|
|
867
|
+
contextBudget: z.number().int().positive().optional(),
|
|
868
|
+
excerptChars: z.number().int().positive().optional(),
|
|
869
|
+
maxResults: z.number().int().positive().optional(),
|
|
962
870
|
})
|
|
963
|
-
|
|
964
|
-
.
|
|
965
|
-
|
|
871
|
+
.optional(),
|
|
872
|
+
// Empty-state prompts shown before the first question. Each renders as a
|
|
873
|
+
// clickable suggestion; `icon` is an optional Lucide name beside it.
|
|
874
|
+
suggestions: z
|
|
875
|
+
.array(
|
|
876
|
+
z.strictObject({
|
|
877
|
+
icon: iconName.optional(),
|
|
878
|
+
label: z.string().min(1),
|
|
879
|
+
})
|
|
880
|
+
)
|
|
881
|
+
.default([]),
|
|
882
|
+
},
|
|
883
|
+
assistantMovedFieldsHint
|
|
884
|
+
)
|
|
966
885
|
.superRefine((value, ctx) => {
|
|
967
|
-
// A generic OpenAI-compatible backend has no preset URL, so the user
|
|
968
|
-
// must supply one; the named providers fall back to their preset.
|
|
969
|
-
if (
|
|
970
|
-
value.provider === "openai-compatible" &&
|
|
971
|
-
!(value.baseUrl || value.endpoint)
|
|
972
|
-
) {
|
|
973
|
-
ctx.addIssue({
|
|
974
|
-
code: z.ZodIssueCode.custom,
|
|
975
|
-
message:
|
|
976
|
-
'ai.ask.baseUrl is required when provider is "openai-compatible".',
|
|
977
|
-
path: ["baseUrl"],
|
|
978
|
-
});
|
|
979
|
-
}
|
|
980
886
|
// `cors` configures the generated route, which an external `endpoint`
|
|
981
887
|
// replaces; accepting both would silently do nothing.
|
|
982
888
|
if (value.cors && value.endpoint) {
|
|
983
889
|
ctx.addIssue({
|
|
984
890
|
code: z.ZodIssueCode.custom,
|
|
985
891
|
message:
|
|
986
|
-
"ai.
|
|
892
|
+
"ai.assistant.cors only applies to the generated route; with ai.assistant.endpoint, CORS is that backend's job.",
|
|
987
893
|
path: ["cors"],
|
|
988
894
|
});
|
|
989
895
|
}
|
|
990
|
-
// Inkeep runs its own QA pipeline behind an OpenAI-compatible endpoint
|
|
991
|
-
// with no reasoning control; a level would only reach it as an
|
|
992
|
-
// unsupported `reasoning_effort`, so refuse it up front.
|
|
993
|
-
if (value.provider === "inkeep" && value.reasoning) {
|
|
994
|
-
ctx.addIssue({
|
|
995
|
-
code: z.ZodIssueCode.custom,
|
|
996
|
-
message:
|
|
997
|
-
'ai.ask.reasoning is not supported when provider is "inkeep".',
|
|
998
|
-
path: ["reasoning"],
|
|
999
|
-
});
|
|
1000
|
-
}
|
|
1001
896
|
})
|
|
1002
897
|
.optional(),
|
|
1003
|
-
/**
|
|
1004
|
-
* The AI Catalog / ARD manifest at `/.well-known/ai-catalog.json` (mirrored
|
|
1005
|
-
* at `/.well-known/ard.json`): one entry per agent-facing resource the site
|
|
1006
|
-
* publishes — the MCP server card, each agent skill, the JSON docs API's
|
|
1007
|
-
* OpenAPI document, each rendered API reference, and llms.txt — so agent
|
|
1008
|
-
* registries can index the site from its domain alone. Needs a
|
|
1009
|
-
* `deployment.site` (identifiers are domain-anchored URNs). On by default;
|
|
1010
|
-
* the object form overrides the generated representative queries.
|
|
1011
|
-
*/
|
|
1012
|
-
catalog: z
|
|
1013
|
-
.union([z.boolean(), aiCatalogObjectSchema])
|
|
1014
|
-
.default(true)
|
|
1015
|
-
.transform((value): AiCatalogResolved =>
|
|
1016
|
-
isBoolean(value) ? { enabled: value, queries: {} } : value
|
|
1017
|
-
),
|
|
1018
|
-
/**
|
|
1019
|
-
* `llms.txt`/`llms-full.txt` emission. A bare boolean toggles it; the object
|
|
1020
|
-
* form adds `openapi: false` to keep generated API reference pages out of
|
|
1021
|
-
* both files (e.g. when the configured spec is example content) and
|
|
1022
|
-
* `details`, free-form Markdown placed after the summary — the llms.txt
|
|
1023
|
-
* spec's details block, where a site tells agents when to reach for it.
|
|
1024
|
-
*/
|
|
1025
|
-
llmsTxt: z
|
|
1026
|
-
.union([z.boolean(), llmsTxtObjectSchema])
|
|
1027
|
-
.default(true)
|
|
1028
|
-
.transform((value): LlmsTxtResolved =>
|
|
1029
|
-
isBoolean(value) ? { enabled: value, openapi: true } : value
|
|
1030
|
-
),
|
|
1031
|
-
// Serializers for the agent-facing Markdown downlevel (the `.md` mirror,
|
|
1032
|
-
// llms-full.txt, MCP get_page), keyed by JSX name. Functions live here —
|
|
1033
|
-
// not in components.tsx — because the config file is executed at build
|
|
1034
|
-
// time while the components file is only statically analyzed. A same-name
|
|
1035
|
-
// entry replaces the built-in serializer.
|
|
1036
|
-
// Two-argument `z.record` — the single-argument form throws at
|
|
1037
|
-
// schema-construction time under Zod 4 (see uiStringsOverrideSchema).
|
|
1038
|
-
markdownComponents: z
|
|
1039
|
-
.record(
|
|
1040
|
-
z.string(),
|
|
1041
|
-
z.custom<ComponentMarkdown>(
|
|
1042
|
-
(value): value is ComponentMarkdown => typeof value === "function",
|
|
1043
|
-
{
|
|
1044
|
-
message: "Expected a serializer function.",
|
|
1045
|
-
}
|
|
1046
|
-
)
|
|
1047
|
-
)
|
|
1048
|
-
.default({}),
|
|
1049
|
-
/** Expose the docs as an MCP server for connecting agents. */
|
|
1050
|
-
mcp: mcpConfigSchema.prefault({}),
|
|
1051
898
|
/**
|
|
1052
899
|
* The "Open in chat" page action. `true` (the default) lists every
|
|
1053
900
|
* provider, `false` hides the action entirely, and an array of provider
|
|
@@ -1070,35 +917,15 @@ const aiConfigSchema = z.strictObject({
|
|
|
1070
917
|
}
|
|
1071
918
|
return value;
|
|
1072
919
|
}),
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
/**
|
|
1083
|
-
* Web Bot Auth (IETF `webbotauth`): publish the org's HTTP Message
|
|
1084
|
-
* Signature public keys at `/.well-known/http-message-signatures-directory`
|
|
1085
|
-
* so sites receiving requests from the org's agents can verify them.
|
|
1086
|
-
* Opt-in and public-keys-only — the private keys live wherever the signing
|
|
1087
|
-
* agents run, never in the site.
|
|
1088
|
-
*/
|
|
1089
|
-
webBotAuth: z
|
|
1090
|
-
.strictObject({
|
|
1091
|
-
keys: z.array(publicJwkSchema).default([]),
|
|
1092
|
-
})
|
|
1093
|
-
.prefault({}),
|
|
1094
|
-
/**
|
|
1095
|
-
* WebMCP: register in-page tools (search, page Markdown, the docs index)
|
|
1096
|
-
* on the browser's model context so agentic browsers can drive the docs
|
|
1097
|
-
* without a separate MCP connection. A tiny script that no-ops in browsers
|
|
1098
|
-
* without the API; on by default.
|
|
1099
|
-
*/
|
|
1100
|
-
webmcp: z.boolean().default(true),
|
|
1101
|
-
});
|
|
920
|
+
};
|
|
921
|
+
|
|
922
|
+
const aiConfigSchema = z.strictObject(
|
|
923
|
+
aiConfigFields,
|
|
924
|
+
removedKeysHint({
|
|
925
|
+
...movedToAgentsHints("ai"),
|
|
926
|
+
ask: "ai.ask was renamed to ai.assistant.",
|
|
927
|
+
})
|
|
928
|
+
);
|
|
1102
929
|
|
|
1103
930
|
/**
|
|
1104
931
|
* A pinned link rendered above the sidebar sections — a blog, changelog, or
|
|
@@ -1164,9 +991,11 @@ const navigationConfigSchema = z.strictObject({
|
|
|
1164
991
|
tabs: z.array(navTabSchema).default([]),
|
|
1165
992
|
});
|
|
1166
993
|
|
|
1167
|
-
export
|
|
1168
|
-
export type
|
|
1169
|
-
export type
|
|
994
|
+
export { assistantReasoningLevels } from "../ai/ask.ts";
|
|
995
|
+
export type { AssistantReasoning } from "../ai/ask.ts";
|
|
996
|
+
export type AssistantConfig = NonNullable<
|
|
997
|
+
z.infer<typeof aiConfigSchema>["assistant"]
|
|
998
|
+
>;
|
|
1170
999
|
export { openInChatProviders } from "./open-in-chat.ts";
|
|
1171
1000
|
export type { OpenInChatProvider } from "./open-in-chat.ts";
|
|
1172
1001
|
|
|
@@ -1316,57 +1145,28 @@ const versionsConfigSchema = z
|
|
|
1316
1145
|
}
|
|
1317
1146
|
});
|
|
1318
1147
|
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
// Load strategy for an external script.
|
|
1328
|
-
strategy: z.enum(["async", "defer"]).optional(),
|
|
1329
|
-
})
|
|
1330
|
-
.refine((value) => Boolean(value.src) !== Boolean(value.content), {
|
|
1331
|
-
message: "An analytics script must set exactly one of `src` or `content`.",
|
|
1332
|
-
});
|
|
1333
|
-
|
|
1334
|
-
const analyticsConfigSchema = z.strictObject({
|
|
1335
|
-
// Cloudflare Web Analytics in manual (JS snippet) mode; the token comes from
|
|
1336
|
-
// the site's snippet in the dashboard. A zone Cloudflare proxies with
|
|
1337
|
-
// automatic RUM injection on needs no config at all.
|
|
1338
|
-
cloudflare: z
|
|
1339
|
-
.strictObject({
|
|
1340
|
-
token: z.string().min(1),
|
|
1341
|
-
})
|
|
1342
|
-
.optional(),
|
|
1343
|
-
posthog: z
|
|
1344
|
-
.strictObject({
|
|
1345
|
-
host: z.string().optional(),
|
|
1346
|
-
key: z.string(),
|
|
1347
|
-
})
|
|
1348
|
-
.optional(),
|
|
1349
|
-
// Escape hatch for any other provider (Plausible, Fathom, GA, Umami, …).
|
|
1350
|
-
scripts: z.array(analyticsScriptSchema).optional(),
|
|
1351
|
-
vercel: z.boolean().optional(),
|
|
1352
|
-
});
|
|
1148
|
+
/**
|
|
1149
|
+
* A pattern segment in a redirect path: a named `:param` segment or a `*`
|
|
1150
|
+
* splat. `from` is matched as an exact path, and hosts disagree on patterns —
|
|
1151
|
+
* a static build would even write a literal `:slug` folder — so both ends are
|
|
1152
|
+
* checked. An absolute `to` URL's own scheme and host are skipped.
|
|
1153
|
+
*/
|
|
1154
|
+
const REDIRECT_PATTERN = /(?:^|\/):[A-Za-z_]|\*/u;
|
|
1155
|
+
const URL_ORIGIN = /^[a-z][\d+.a-z-]*:\/\/[^/]*/iu;
|
|
1353
1156
|
|
|
1354
|
-
const
|
|
1355
|
-
|
|
1356
|
-
.
|
|
1357
|
-
.
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
output: z.enum(["static", "server"]).default("static"),
|
|
1361
|
-
site: z.url().optional(),
|
|
1362
|
-
});
|
|
1157
|
+
const exactRedirectPath = (end: "from" | "to") =>
|
|
1158
|
+
z
|
|
1159
|
+
.string()
|
|
1160
|
+
.refine((path) => !REDIRECT_PATTERN.test(path.replace(URL_ORIGIN, "")), {
|
|
1161
|
+
message: `redirects take exact paths: \`${end}\` can't hold a \`:param\` segment or a \`*\` wildcard. Add one redirect per path, or put pattern rules in your host's redirect config (vercel.json, _redirects).`,
|
|
1162
|
+
});
|
|
1363
1163
|
|
|
1364
1164
|
const redirectSchema = z.strictObject({
|
|
1365
|
-
from:
|
|
1165
|
+
from: exactRedirectPath("from"),
|
|
1366
1166
|
status: z
|
|
1367
1167
|
.union([z.literal(301), z.literal(302), z.literal(307), z.literal(308)])
|
|
1368
1168
|
.default(301),
|
|
1369
|
-
to:
|
|
1169
|
+
to: exactRedirectPath("to"),
|
|
1370
1170
|
});
|
|
1371
1171
|
|
|
1372
1172
|
/**
|
|
@@ -1584,15 +1384,7 @@ const softwareConfigSchema = z.strictObject({
|
|
|
1584
1384
|
type SoftwareResolved = z.output<typeof softwareConfigSchema>;
|
|
1585
1385
|
|
|
1586
1386
|
/** Discoverability features: OG images, feeds, sitemap, structured data. */
|
|
1587
|
-
const
|
|
1588
|
-
/**
|
|
1589
|
-
* Emit `agent-readability.json` at the site root: a manifest that indexes
|
|
1590
|
-
* the agent-facing surface (llms.txt, Markdown mirrors, MCP server, feeds)
|
|
1591
|
-
* so agents can discover it without scraping HTML.
|
|
1592
|
-
*/
|
|
1593
|
-
agentReadability: z.boolean().default(true),
|
|
1594
|
-
/** robots.txt `Content-Signal` usage declaration (on by default). */
|
|
1595
|
-
contentSignals: contentSignalsSchema.prefault(true),
|
|
1387
|
+
const seoConfigFields = {
|
|
1596
1388
|
og: ogConfigSchema.default({}),
|
|
1597
1389
|
/** The organization behind the site, as an `Organization` JSON-LD node. */
|
|
1598
1390
|
organization: organizationConfigSchema.optional(),
|
|
@@ -1615,6 +1407,114 @@ const seoConfigSchema = z.strictObject({
|
|
|
1615
1407
|
structuredData: z.boolean().default(true),
|
|
1616
1408
|
/** X (Twitter) account attribution for share cards. */
|
|
1617
1409
|
x: xConfigSchema.default({}),
|
|
1410
|
+
};
|
|
1411
|
+
|
|
1412
|
+
const seoConfigSchema = z.strictObject(
|
|
1413
|
+
seoConfigFields,
|
|
1414
|
+
removedKeysHint({
|
|
1415
|
+
agentReadability: "seo.agentReadability moved to agents.agentReadability.",
|
|
1416
|
+
contentSignals: "seo.contentSignals moved to agents.contentSignals.",
|
|
1417
|
+
})
|
|
1418
|
+
);
|
|
1419
|
+
|
|
1420
|
+
/**
|
|
1421
|
+
* The machine-readable surface agents consume: the JSON API, `llms.txt`, the
|
|
1422
|
+
* MCP server, published skills, discovery manifests, and the robots.txt
|
|
1423
|
+
* usage policy. Everything reader-facing that talks to a model (the assistant, Open
|
|
1424
|
+
* in chat) stays under `ai`.
|
|
1425
|
+
*/
|
|
1426
|
+
const agentsConfigSchema = z.strictObject({
|
|
1427
|
+
/**
|
|
1428
|
+
* Emit `agent-readability.json` at the site root: a manifest that indexes
|
|
1429
|
+
* the agent-facing surface (llms.txt, Markdown mirrors, MCP server, feeds)
|
|
1430
|
+
* so agents can discover it without scraping HTML.
|
|
1431
|
+
*/
|
|
1432
|
+
agentReadability: z.boolean().default(true),
|
|
1433
|
+
/**
|
|
1434
|
+
* The JSON docs API: the page index, per-page JSON, and navigation under
|
|
1435
|
+
* `/api/docs/` (prerendered, so a static site serves them from files), the
|
|
1436
|
+
* live search endpoint on server output, and the OpenAPI description of
|
|
1437
|
+
* the whole machine-readable surface at `/openapi.json`. On by default.
|
|
1438
|
+
*/
|
|
1439
|
+
api: z.boolean().default(true),
|
|
1440
|
+
/**
|
|
1441
|
+
* The AI Catalog / ARD manifest at `/.well-known/ai-catalog.json` (mirrored
|
|
1442
|
+
* at `/.well-known/ard.json`): one entry per agent-facing resource the site
|
|
1443
|
+
* publishes — the MCP server card, each agent skill, the JSON docs API's
|
|
1444
|
+
* OpenAPI document, each rendered API reference, and llms.txt — so agent
|
|
1445
|
+
* registries can index the site from its domain alone. Needs a
|
|
1446
|
+
* `deployment.site` (identifiers are domain-anchored URNs). On by default;
|
|
1447
|
+
* the object form overrides the generated representative queries.
|
|
1448
|
+
*/
|
|
1449
|
+
catalog: z
|
|
1450
|
+
.union([z.boolean(), aiCatalogObjectSchema])
|
|
1451
|
+
.default(true)
|
|
1452
|
+
.transform((value): AiCatalogResolved =>
|
|
1453
|
+
isBoolean(value) ? { enabled: value, queries: {} } : value
|
|
1454
|
+
),
|
|
1455
|
+
/** robots.txt `Content-Signal` usage declaration (on by default). */
|
|
1456
|
+
contentSignals: contentSignalsSchema.prefault(true),
|
|
1457
|
+
/**
|
|
1458
|
+
* `llms.txt`/`llms-full.txt` emission. A bare boolean toggles it; the object
|
|
1459
|
+
* form adds `openapi: false` to keep generated API reference pages out of
|
|
1460
|
+
* both files (e.g. when the configured spec is example content) and
|
|
1461
|
+
* `details`, free-form Markdown placed after the summary — the llms.txt
|
|
1462
|
+
* spec's details block, where a site tells agents when to reach for it.
|
|
1463
|
+
*/
|
|
1464
|
+
llmsTxt: z
|
|
1465
|
+
.union([z.boolean(), llmsTxtObjectSchema])
|
|
1466
|
+
.default(true)
|
|
1467
|
+
.transform((value): LlmsTxtResolved =>
|
|
1468
|
+
isBoolean(value) ? { enabled: value, openapi: true } : value
|
|
1469
|
+
),
|
|
1470
|
+
// Serializers for the agent-facing Markdown downlevel (the `.md` mirror,
|
|
1471
|
+
// llms-full.txt, MCP get_page), keyed by JSX name. Functions live here —
|
|
1472
|
+
// not in components.tsx — because the config file is executed at build
|
|
1473
|
+
// time while the components file is only statically analyzed. A same-name
|
|
1474
|
+
// entry replaces the built-in serializer.
|
|
1475
|
+
// Two-argument `z.record` — the single-argument form throws at
|
|
1476
|
+
// schema-construction time under Zod 4 (see uiStringsOverrideSchema).
|
|
1477
|
+
markdownComponents: z
|
|
1478
|
+
.record(
|
|
1479
|
+
z.string(),
|
|
1480
|
+
z.custom<ComponentMarkdown>(
|
|
1481
|
+
(value): value is ComponentMarkdown => typeof value === "function",
|
|
1482
|
+
{
|
|
1483
|
+
message: "Expected a serializer function.",
|
|
1484
|
+
}
|
|
1485
|
+
)
|
|
1486
|
+
)
|
|
1487
|
+
.default({}),
|
|
1488
|
+
/** Expose the docs as an MCP server for connecting agents. */
|
|
1489
|
+
mcp: mcpConfigSchema.prefault({}),
|
|
1490
|
+
/**
|
|
1491
|
+
* Publish Agent Skills for discovery: a directory (resolved against the
|
|
1492
|
+
* project root) whose subdirectories each hold a `SKILL.md`. The build
|
|
1493
|
+
* copies each skill under `/.well-known/agent-skills/` — a lone `SKILL.md`
|
|
1494
|
+
* verbatim, a skill with supporting files as a `.tar.gz` — and emits the
|
|
1495
|
+
* discovery index (`index.json`) with SHA-256 digests per the Agent Skills
|
|
1496
|
+
* Discovery RFC.
|
|
1497
|
+
*/
|
|
1498
|
+
skills: z.string().min(1).optional(),
|
|
1499
|
+
/**
|
|
1500
|
+
* Web Bot Auth (IETF `webbotauth`): publish the org's HTTP Message
|
|
1501
|
+
* Signature public keys at `/.well-known/http-message-signatures-directory`
|
|
1502
|
+
* so sites receiving requests from the org's agents can verify them.
|
|
1503
|
+
* Opt-in and public-keys-only — the private keys live wherever the signing
|
|
1504
|
+
* agents run, never in the site.
|
|
1505
|
+
*/
|
|
1506
|
+
webBotAuth: z
|
|
1507
|
+
.strictObject({
|
|
1508
|
+
keys: z.array(publicJwkSchema).default([]),
|
|
1509
|
+
})
|
|
1510
|
+
.prefault({}),
|
|
1511
|
+
/**
|
|
1512
|
+
* WebMCP: register in-page tools (search, page Markdown, the docs index)
|
|
1513
|
+
* on the browser's model context so agentic browsers can drive the docs
|
|
1514
|
+
* without a separate MCP connection. A tiny script that no-ops in browsers
|
|
1515
|
+
* without the API; on by default.
|
|
1516
|
+
*/
|
|
1517
|
+
webmcp: z.boolean().default(true),
|
|
1618
1518
|
});
|
|
1619
1519
|
|
|
1620
1520
|
/**
|
|
@@ -1691,10 +1591,6 @@ const codeBlockThemeSchema = z.strictObject({
|
|
|
1691
1591
|
light: codeThemeSchema.default("github-light"),
|
|
1692
1592
|
});
|
|
1693
1593
|
|
|
1694
|
-
const codeBlocksConfigSchema = z.strictObject({
|
|
1695
|
-
theme: codeBlockThemeSchema.prefault({}),
|
|
1696
|
-
});
|
|
1697
|
-
|
|
1698
1594
|
/**
|
|
1699
1595
|
* `<Component />` example previews. A string is shorthand for `{ source }`:
|
|
1700
1596
|
* where examples live, relative to the project root (default `examples`).
|
|
@@ -1726,13 +1622,20 @@ const examplesConfigSchema = z
|
|
|
1726
1622
|
|
|
1727
1623
|
/**
|
|
1728
1624
|
* "Last updated" timestamps for content pages. `false` (default) disables the
|
|
1729
|
-
* feature; `
|
|
1730
|
-
*
|
|
1625
|
+
* feature; `"git"` derives each page's date from the repository history;
|
|
1626
|
+
* `"frontmatter"` never runs git and reads only the page's own field. A page's
|
|
1627
|
+
* `lastModified` frontmatter always wins. The 1.x `true` and `{ type }` forms
|
|
1628
|
+
* fail with the hint below.
|
|
1731
1629
|
*/
|
|
1732
|
-
const lastModifiedConfigSchema = z.union(
|
|
1733
|
-
z.
|
|
1734
|
-
|
|
1735
|
-
|
|
1630
|
+
const lastModifiedConfigSchema = z.union(
|
|
1631
|
+
[z.literal(false), z.enum(["git", "frontmatter"])],
|
|
1632
|
+
{
|
|
1633
|
+
error: (issue) =>
|
|
1634
|
+
issue.code === "invalid_union"
|
|
1635
|
+
? 'lastModified takes false, "git", or "frontmatter": `true` became "git" and `{ type: "…" }` became the bare string.'
|
|
1636
|
+
: undefined,
|
|
1637
|
+
}
|
|
1638
|
+
);
|
|
1736
1639
|
|
|
1737
1640
|
/**
|
|
1738
1641
|
* How the "last updated" stamp and the changelog timeline render their dates —
|
|
@@ -1777,13 +1680,18 @@ const dateFormatConfigSchema = z
|
|
|
1777
1680
|
}
|
|
1778
1681
|
);
|
|
1779
1682
|
|
|
1780
|
-
/** Code
|
|
1683
|
+
/** Code rendering options (`markdown.code`). */
|
|
1781
1684
|
const codeConfigSchema = z.strictObject({
|
|
1782
1685
|
/**
|
|
1783
1686
|
* Show a brand language icon in the code-block header (TypeScript, Python,
|
|
1784
1687
|
* …). On by default; recognized languages only.
|
|
1785
1688
|
*/
|
|
1786
1689
|
icons: z.boolean().default(true),
|
|
1690
|
+
/**
|
|
1691
|
+
* Light/dark Shiki themes for every code surface: fenced blocks, inline
|
|
1692
|
+
* `` `code`{:lang} ``, `<CodeBlock>`, and `<Diff>`.
|
|
1693
|
+
*/
|
|
1694
|
+
theme: codeBlockThemeSchema.prefault({}),
|
|
1787
1695
|
/**
|
|
1788
1696
|
* Wrap long lines instead of scrolling horizontally. Off by default, so
|
|
1789
1697
|
* code keeps its original line breaks and overflows into a scroll area.
|
|
@@ -1791,10 +1699,17 @@ const codeConfigSchema = z.strictObject({
|
|
|
1791
1699
|
wrap: z.boolean().default(false),
|
|
1792
1700
|
});
|
|
1793
1701
|
|
|
1794
|
-
const
|
|
1795
|
-
/** Code
|
|
1702
|
+
const markdownConfigFields = {
|
|
1703
|
+
/** Code rendering: language icons, syntax themes, and line wrapping. */
|
|
1796
1704
|
code: codeConfigSchema.prefault({}),
|
|
1797
|
-
|
|
1705
|
+
/**
|
|
1706
|
+
* Open external Markdown links (absolute `http(s)://` and `//host` URLs) in
|
|
1707
|
+
* a new tab, like Blume's own header and sidebar links: `target="_blank"`,
|
|
1708
|
+
* `rel="noreferrer"`, an arrow icon, and a screen-reader "Opens in a new
|
|
1709
|
+
* tab" hint. Off by default; site routes, fragments, and `mailto:`/`tel:`
|
|
1710
|
+
* links are never affected.
|
|
1711
|
+
*/
|
|
1712
|
+
externalLinks: z.boolean().default(false),
|
|
1798
1713
|
/**
|
|
1799
1714
|
* Wrap each `##`–`######` heading in a link to its own anchor so readers can
|
|
1800
1715
|
* click to copy, bookmark, or share a permalink to that section. On by
|
|
@@ -1806,176 +1721,27 @@ const markdownConfigSchema = z.strictObject({
|
|
|
1806
1721
|
* opt a single image out with `data-no-zoom`.
|
|
1807
1722
|
*/
|
|
1808
1723
|
imageZoom: z.boolean().default(true),
|
|
1809
|
-
}
|
|
1724
|
+
};
|
|
1725
|
+
|
|
1726
|
+
const markdownConfigSchema = z.strictObject(
|
|
1727
|
+
markdownConfigFields,
|
|
1728
|
+
removedKeysHint({
|
|
1729
|
+
codeBlocks:
|
|
1730
|
+
"markdown.codeBlocks was merged into markdown.code: move theme: { light, dark } under markdown.code.",
|
|
1731
|
+
})
|
|
1732
|
+
);
|
|
1810
1733
|
|
|
1811
1734
|
/** React island behavior (`react`). */
|
|
1812
1735
|
const reactConfigSchema = z.strictObject({
|
|
1813
1736
|
/**
|
|
1814
1737
|
* Auto-memoize React components/hooks with the React Compiler
|
|
1815
1738
|
* (`babel-plugin-react-compiler`). On by default whenever React is enabled
|
|
1816
|
-
* (a project `.tsx`/`.jsx`, a React island/example/override, or
|
|
1739
|
+
* (a project `.tsx`/`.jsx`, a React island/example/override, or the assistant); set
|
|
1817
1740
|
* to `false` to skip the compiler's babel pass.
|
|
1818
1741
|
*/
|
|
1819
1742
|
compiler: z.boolean().default(true),
|
|
1820
1743
|
});
|
|
1821
1744
|
|
|
1822
|
-
/**
|
|
1823
|
-
* A single spec rendered by the API reference. `spec` is a local path or an
|
|
1824
|
-
* `http(s)` URL (an OpenAPI document under `openapi`, an AsyncAPI document
|
|
1825
|
-
* under `asyncapi`).
|
|
1826
|
-
*/
|
|
1827
|
-
const openapiSourceSchema = z.strictObject({
|
|
1828
|
-
/** Include generated pages from this spec in llms.txt/llms-full.txt. */
|
|
1829
|
-
includeInLlms: z.boolean().default(true),
|
|
1830
|
-
/** Include generated pages from this spec in site search. */
|
|
1831
|
-
includeInSearch: z.boolean().default(true),
|
|
1832
|
-
/** Nav/section label for this source. */
|
|
1833
|
-
label: z.string().optional(),
|
|
1834
|
-
/** Emit noindex metadata and omit generated pages from the sitemap. */
|
|
1835
|
-
noindex: z.boolean().default(false),
|
|
1836
|
-
/** Per-source route; defaults to the block's `route` (or a derived path). */
|
|
1837
|
-
route: z.string().optional(),
|
|
1838
|
-
/**
|
|
1839
|
-
* Append the English "Reference for the … endpoint in the … API." sentence
|
|
1840
|
-
* to every generated operation page's meta description. On by default, so
|
|
1841
|
-
* terse specs still ship distinct, snippet-length descriptions; set to
|
|
1842
|
-
* `false` on a non-English site to describe pages with the spec's own prose
|
|
1843
|
-
* alone (falling back to the page title when an operation has none).
|
|
1844
|
-
*/
|
|
1845
|
-
seoDescriptionSuffix: z.boolean().default(true),
|
|
1846
|
-
/** Local path or `http(s)` URL to the spec. */
|
|
1847
|
-
spec: z.string(),
|
|
1848
|
-
});
|
|
1849
|
-
|
|
1850
|
-
export type OpenApiSource = z.input<typeof openapiSourceSchema>;
|
|
1851
|
-
|
|
1852
|
-
/**
|
|
1853
|
-
* Arbitrary Scalar API-reference options forwarded verbatim to the generated
|
|
1854
|
-
* `<ScalarComponent>` (Scalar renderer only). A passthrough map — Blume doesn't
|
|
1855
|
-
* mirror Scalar's full config surface — so keys like `localization`, `agent`,
|
|
1856
|
-
* `hideTestRequestButton`, or `orderSchemaPropertiesBy` all flow through. These
|
|
1857
|
-
* take precedence over Blume's own derived config (spec, theme), so this is a
|
|
1858
|
-
* full escape hatch; the dedicated `theme` field is the ergonomic shorthand.
|
|
1859
|
-
*/
|
|
1860
|
-
const scalarConfigSchema = z.record(z.string(), z.unknown()).optional();
|
|
1861
|
-
|
|
1862
|
-
/**
|
|
1863
|
-
* The interactive "Try it" panel on operation pages (Blume renderer). On by
|
|
1864
|
-
* default; `false` hides it. The object form keeps it on and sets `proxy`,
|
|
1865
|
-
* the CORS escape hatch the Send button routes requests through: a proxy URL,
|
|
1866
|
-
* or `true` for the built-in `/_api-proxy` endpoint (which requires
|
|
1867
|
-
* `deployment.output: "server"`). Booleans normalize to the object shape so
|
|
1868
|
-
* consumers read `{ enabled, proxy }` directly. `proxy` applies to the
|
|
1869
|
-
* HTTP-posting playgrounds (OpenAPI, GraphQL) — an event composer's WebSocket
|
|
1870
|
-
* connect is direct. One schema for every reference block, so the
|
|
1871
|
-
* normalization can never drift between them.
|
|
1872
|
-
*/
|
|
1873
|
-
const playgroundConfigSchema = z
|
|
1874
|
-
.union([
|
|
1875
|
-
z.boolean(),
|
|
1876
|
-
z.strictObject({
|
|
1877
|
-
enabled: z.boolean().default(true),
|
|
1878
|
-
proxy: z.union([z.boolean(), z.string()]).default(false),
|
|
1879
|
-
}),
|
|
1880
|
-
])
|
|
1881
|
-
.default(true)
|
|
1882
|
-
.transform((value) =>
|
|
1883
|
-
isBoolean(value) ? { enabled: value, proxy: false } : value
|
|
1884
|
-
);
|
|
1885
|
-
|
|
1886
|
-
/**
|
|
1887
|
-
* The shared shape of the API-reference blocks — only the mount route and
|
|
1888
|
-
* code-sample defaults differ per spec kind, so each block declares just
|
|
1889
|
-
* those (the GraphQL block derives from this via omit/extend below).
|
|
1890
|
-
*/
|
|
1891
|
-
const referenceConfigSchema = (defaults: {
|
|
1892
|
-
codeSamples: string[];
|
|
1893
|
-
route: string;
|
|
1894
|
-
}) =>
|
|
1895
|
-
z.strictObject({
|
|
1896
|
-
/** Code-sample languages/tools shown per operation (Blume renderer). */
|
|
1897
|
-
codeSamples: z.array(z.string()).default(defaults.codeSamples),
|
|
1898
|
-
enabled: z.boolean().default(false),
|
|
1899
|
-
/** Start nested schema rows expanded rather than collapsed (Blume renderer). */
|
|
1900
|
-
expandSchemas: z.boolean().default(false),
|
|
1901
|
-
/** The "Try it" panel; see {@link playgroundConfigSchema}. */
|
|
1902
|
-
playground: playgroundConfigSchema,
|
|
1903
|
-
/** Who renders the reference: Blume's own UI, or the embedded Scalar SPA. */
|
|
1904
|
-
renderer: z.enum(["blume", "scalar"]).default("blume"),
|
|
1905
|
-
/** Where the reference mounts. */
|
|
1906
|
-
route: z.string().default(defaults.route),
|
|
1907
|
-
/** Extra Scalar config forwarded to `<ScalarComponent>` (Scalar renderer only). */
|
|
1908
|
-
scalar: scalarConfigSchema,
|
|
1909
|
-
/** One or more specs; each renders on its own route by default. */
|
|
1910
|
-
sources: z.array(openapiSourceSchema).default([]),
|
|
1911
|
-
/** Shorthand for a single source: `sources: [{ spec }]`. */
|
|
1912
|
-
spec: z.string().optional(),
|
|
1913
|
-
/** Scalar theme name (Scalar renderer only). */
|
|
1914
|
-
theme: z.string().optional(),
|
|
1915
|
-
});
|
|
1916
|
-
|
|
1917
|
-
/**
|
|
1918
|
-
* OpenAPI reference. By default (`renderer: "blume"`) Blume parses the spec with
|
|
1919
|
-
* Scalar's parser and renders its own UI: one real page per operation, grouped
|
|
1920
|
-
* by tag in the sidebar and included in site search, llms.txt, and OG. Set
|
|
1921
|
-
* `renderer: "scalar"` to fall back to the embedded Scalar SPA (a single
|
|
1922
|
-
* self-contained route that doesn't weave into the sidebar or search).
|
|
1923
|
-
*/
|
|
1924
|
-
const openapiConfigSchema = referenceConfigSchema({
|
|
1925
|
-
codeSamples: ["curl", "js", "python"],
|
|
1926
|
-
route: "/reference",
|
|
1927
|
-
});
|
|
1928
|
-
|
|
1929
|
-
/**
|
|
1930
|
-
* AsyncAPI reference. Same shape as {@link openapiConfigSchema}: by default
|
|
1931
|
-
* (`renderer: "blume"`) Blume normalizes the spec to AsyncAPI 3.x and renders
|
|
1932
|
-
* its own UI — one real page per operation — with `renderer: "scalar"` as the
|
|
1933
|
-
* embedded-SPA opt-out. Only the defaults differ: the reference mounts at
|
|
1934
|
-
* `/events`, and empty `codeSamples` means every tool the operation's protocol
|
|
1935
|
-
* binding suggests.
|
|
1936
|
-
*/
|
|
1937
|
-
const asyncapiConfigSchema = referenceConfigSchema({
|
|
1938
|
-
codeSamples: [],
|
|
1939
|
-
route: "/events",
|
|
1940
|
-
});
|
|
1941
|
-
|
|
1942
|
-
/**
|
|
1943
|
-
* A single GraphQL schema rendered by the reference. `spec` is a local path or
|
|
1944
|
-
* an `http(s)` URL to SDL text or an introspection JSON result; `endpoint` is
|
|
1945
|
-
* the live GraphQL API URL the playground and code samples target (a schema,
|
|
1946
|
-
* unlike an OpenAPI document, names no server).
|
|
1947
|
-
*/
|
|
1948
|
-
const graphqlSourceSchema = openapiSourceSchema.extend({
|
|
1949
|
-
/** URL of the live GraphQL endpoint (playground + code samples). */
|
|
1950
|
-
endpoint: z.string().optional(),
|
|
1951
|
-
});
|
|
1952
|
-
|
|
1953
|
-
export type GraphqlSource = z.input<typeof graphqlSourceSchema>;
|
|
1954
|
-
|
|
1955
|
-
/**
|
|
1956
|
-
* GraphQL reference. Blume lowers the schema (SDL or introspection JSON) to
|
|
1957
|
-
* one real page per root field — grouped as Queries/Mutations/Subscriptions —
|
|
1958
|
-
* plus one page per named type (Objects, Input Objects, Enums, Interfaces,
|
|
1959
|
-
* Unions, Scalars), all included in the sidebar, search, llms.txt, and OG.
|
|
1960
|
-
* Always Blume-rendered: the Scalar SPA reads OpenAPI documents only, so the
|
|
1961
|
-
* block declares no `renderer`/`scalar`/`theme` escape hatches.
|
|
1962
|
-
*/
|
|
1963
|
-
const graphqlConfigSchema = referenceConfigSchema({
|
|
1964
|
-
codeSamples: ["curl", "js", "python"],
|
|
1965
|
-
route: "/graphql",
|
|
1966
|
-
})
|
|
1967
|
-
// No `renderer`/`scalar`/`theme` escape hatches (the Scalar SPA reads
|
|
1968
|
-
// OpenAPI documents only) and no `expandSchemas` (GraphQL field tables have
|
|
1969
|
-
// no nesting) — everything else, the playground normalization included, is
|
|
1970
|
-
// the shared reference shape.
|
|
1971
|
-
.omit({ expandSchemas: true, renderer: true, scalar: true, theme: true })
|
|
1972
|
-
.extend({
|
|
1973
|
-
/** Default live endpoint URL for every source (per-source `endpoint` wins). */
|
|
1974
|
-
endpoint: z.string().optional(),
|
|
1975
|
-
/** One or more schemas; each renders on its own route by default. */
|
|
1976
|
-
sources: z.array(graphqlSourceSchema).default([]),
|
|
1977
|
-
});
|
|
1978
|
-
|
|
1979
1745
|
/**
|
|
1980
1746
|
* Opt-in custom frontmatter keys. `extend` maps each extra key a project's
|
|
1981
1747
|
* pages may carry (e.g. `owner`, `reviewedAt`) to a validation schema; the
|
|
@@ -2025,60 +1791,77 @@ const tocConfigSchema = z
|
|
|
2025
1791
|
});
|
|
2026
1792
|
|
|
2027
1793
|
export const blumeConfigSchema = z
|
|
2028
|
-
.strictObject(
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
1794
|
+
.strictObject(
|
|
1795
|
+
{
|
|
1796
|
+
agents: agentsConfigSchema.prefault({}),
|
|
1797
|
+
ai: aiConfigSchema.prefault({}),
|
|
1798
|
+
// Adapters from `blume/analytics`, each a serializable descriptor.
|
|
1799
|
+
analytics: analyticsConfigSchema,
|
|
1800
|
+
banner: bannerConfigSchema.optional(),
|
|
1801
|
+
/**
|
|
1802
|
+
* Site-wide mount point prepended to every generated route (e.g. `/docs`),
|
|
1803
|
+
* while staying invisible to the sidebar/nav tree. Distinct from a per-source
|
|
1804
|
+
* `prefix` (which creates a group) and from `deployment.base` (Astro's
|
|
1805
|
+
* host-subdirectory base); the two compose. Normalized to `""` or `/seg`.
|
|
1806
|
+
*/
|
|
1807
|
+
basePath: z
|
|
1808
|
+
.string()
|
|
1809
|
+
.optional()
|
|
1810
|
+
.transform((value) => normalizeBasePath(value)),
|
|
1811
|
+
content: contentConfigSchema.prefault({}),
|
|
1812
|
+
/**
|
|
1813
|
+
* Date presentation for the "last updated" stamp and the changelog timeline.
|
|
1814
|
+
* Pass-through `Intl.DateTimeFormat` options; defaults to `{ dateStyle: "long" }`.
|
|
1815
|
+
*/
|
|
1816
|
+
dateFormat: dateFormatConfigSchema.default({ dateStyle: "long" }),
|
|
1817
|
+
/**
|
|
1818
|
+
* A host adapter from `blume/deploy` (`vercel()`, `netlify()`,
|
|
1819
|
+
* `cloudflare()`, `node()`) for a server build on that host, or the plain
|
|
1820
|
+
* `{ site, base }` form for a static build anywhere. Resolves to the
|
|
1821
|
+
* adapter's descriptor with `output` filled in; `static` when unset.
|
|
1822
|
+
*/
|
|
1823
|
+
deployment: resolvedDeploymentSchema.prefault({}),
|
|
1824
|
+
description: z.string().optional(),
|
|
1825
|
+
/**
|
|
1826
|
+
* Where `<Component path>` resolves live previews and their source from.
|
|
1827
|
+
* A string is shorthand for `{ source }` — the directory (or glob, for
|
|
1828
|
+
* colocated registry layouts) under the project root that holds example
|
|
1829
|
+
* files. The object form adds `css`: a stylesheet injected into every
|
|
1830
|
+
* preview frame (design tokens, shadcn variables, `@theme` mappings).
|
|
1831
|
+
*/
|
|
1832
|
+
examples: examplesConfigSchema.prefault("examples"),
|
|
1833
|
+
export: exportConfigSchema.prefault(false),
|
|
1834
|
+
feedback: z.boolean().default(true),
|
|
1835
|
+
/** Opt-in custom frontmatter keys, validated by user-supplied schemas. */
|
|
1836
|
+
frontmatter: frontmatterConfigSchema.prefault({}),
|
|
1837
|
+
github: githubConfigSchema.optional(),
|
|
1838
|
+
i18n: i18nConfigSchema.optional(),
|
|
1839
|
+
image: imageConfigSchema.prefault({}),
|
|
1840
|
+
integrations: z.array(z.custom<AstroIntegration>()).default([]),
|
|
1841
|
+
lastModified: lastModifiedConfigSchema.default(false),
|
|
1842
|
+
logo: logoConfigSchema.optional(),
|
|
1843
|
+
markdown: markdownConfigSchema.prefault({}),
|
|
1844
|
+
navigation: navigationConfigSchema.prefault({}),
|
|
1845
|
+
react: reactConfigSchema.prefault({}),
|
|
1846
|
+
redirects: z.array(redirectSchema).default([]),
|
|
1847
|
+
/** API references: adapters from `blume/reference`, each a serializable descriptor. */
|
|
1848
|
+
reference: referenceConfigSchema,
|
|
1849
|
+
search: searchConfigSchema.prefault({}),
|
|
1850
|
+
seo: seoConfigSchema.prefault({}),
|
|
1851
|
+
theme: themeConfigSchema.prefault({}),
|
|
1852
|
+
title: z.string().default("Documentation"),
|
|
1853
|
+
toc: tocConfigSchema,
|
|
1854
|
+
versions: versionsConfigSchema.optional(),
|
|
1855
|
+
},
|
|
1856
|
+
{
|
|
1857
|
+
// The 1.x `openapi`/`asyncapi`/`graphql` blocks name the `reference` list
|
|
1858
|
+
// that replaced them, alongside every other issue in the config.
|
|
1859
|
+
error: (issue) =>
|
|
1860
|
+
issue.code === "unrecognized_keys"
|
|
1861
|
+
? removedReferenceKeysHint(issue.keys)
|
|
1862
|
+
: undefined,
|
|
1863
|
+
}
|
|
1864
|
+
)
|
|
2082
1865
|
.superRefine((config, ctx) => {
|
|
2083
1866
|
// A version id that is also a configured locale code would make a leading
|
|
2084
1867
|
// `<id>/` directory ambiguous between the two axes — refuse it outright so
|
|
@@ -2150,8 +1933,8 @@ export type ArchivedVersionConfig = z.infer<typeof archivedVersionSchema>;
|
|
|
2150
1933
|
* guard keeps structurally identical to this.
|
|
2151
1934
|
*/
|
|
2152
1935
|
export type BlumeConfigInput = z.input<typeof blumeConfigSchema>;
|
|
2153
|
-
/**
|
|
2154
|
-
export type
|
|
1936
|
+
/** The resolved search backend: an adapter descriptor, or `none`. */
|
|
1937
|
+
export type { ResolvedSearchAdapter } from "../search/adapters/registry.ts";
|
|
2155
1938
|
/** Resolved robots.txt `Content-Signal` preferences (`null` when disabled). */
|
|
2156
1939
|
export type ContentSignals = z.infer<typeof contentSignalsSchema>;
|
|
2157
1940
|
/** The resolved per-signal policy object (present when signals are enabled). */
|